Merge inbound to m-c.
authorRyan VanderMeulen <ryanvm@gmail.com>
Wed, 26 Feb 2014 16:16:11 -0500
changeset 171080 e840b5a70371d3776a6b2fa8c5e6bb6568e72780
parent 171079 fcd802ee7945e7f01bad4bc5f672525c2202952d (current diff)
parent 171046 0c8703fab0c991df30768f53ca2ca9c3c6d1e42f (diff)
child 171101 8b52fb24991d57ff8dd5205fd9334cf1e26b04d2
push id270
push userpvanderbeken@mozilla.com
push dateThu, 06 Mar 2014 09:24:21 +0000
milestone30.0a1
Merge inbound to m-c.
testing/marionette/client/marionette/tests/unit/test_getstatus.py
--- a/browser/app/Makefile.in
+++ b/browser/app/Makefile.in
@@ -56,21 +56,16 @@ include $(topsrcdir)/config/config.mk
 
 ifeq ($(OS_ARCH),WINNT)
 RCINCLUDE = splash.rc
 # Rebuild firefox.exe if the manifest changes - it's included by splash.rc.
 # (this dependency should really be just for firefox.exe, not other targets)
 # Note the manifest file exists in the tree, so we use the explicit filename
 # here.
 EXTRA_DEPS += firefox.exe.manifest
-ifndef GNU_CC
-RCFLAGS += -DMOZ_PHOENIX -I$(srcdir)
-else
-RCFLAGS += -DMOZ_PHOENIX --include-dir $(srcdir)
-endif
 endif
 
 PROGRAMS_DEST = $(DIST)/bin
 
 include $(topsrcdir)/config/rules.mk
 
 ifeq ($(OS_ARCH),WINNT) #{
 #
--- a/browser/app/moz.build
+++ b/browser/app/moz.build
@@ -32,8 +32,11 @@ LOCAL_INCLUDES += [
     '/xpcom/base',
     '/xpcom/build',
 ]
 
 if CONFIG['_MSC_VER']:
     # Always enter a Windows program through wmain, whether or not we're
     # a console application.
     WIN32_EXE_LDFLAGS += ['-ENTRY:wmainCRTStartup']
+
+if CONFIG['OS_ARCH'] == 'WINNT':
+    DEFINES['MOZ_PHOENIX'] = True
--- a/config/expandlibs_exec.py
+++ b/config/expandlibs_exec.py
@@ -343,17 +343,18 @@ def main():
         sys.stderr.write(stdout)
         sys.stderr.flush()
         if proc.returncode:
             exit(proc.returncode)
     if not options.depend:
         return
     ensureParentDir(options.depend)
     mk = Makefile()
-    deps = [dep for dep in deps if os.path.isfile(dep) and dep != options.target]
+    deps = [dep for dep in deps if os.path.isfile(dep) and dep != options.target
+            and os.path.abspath(dep) != os.path.abspath(options.depend)]
     no_dynamic_lib = [dep for dep in deps if not isDynamicLib(dep)]
     mk.create_rule([options.target]).add_dependencies(no_dynamic_lib)
     if len(deps) != len(no_dynamic_lib):
         mk.create_rule(['%s_order_only' % options.target]).add_dependencies(dep for dep in deps if isDynamicLib(dep))
 
     with open(options.depend, 'w') as depfile:
         mk.dump(depfile, removal_guard=True)
 
--- a/content/media/encoder/OmxTrackEncoder.cpp
+++ b/content/media/encoder/OmxTrackEncoder.cpp
@@ -21,21 +21,24 @@
 using namespace android;
 
 namespace mozilla {
 
 #define ENCODER_CONFIG_FRAME_RATE 30 // fps
 #define GET_ENCODED_VIDEO_FRAME_TIMEOUT 100000 // microseconds
 
 nsresult
-OmxVideoTrackEncoder::Init(int aWidth, int aHeight, TrackRate aTrackRate)
+OmxVideoTrackEncoder::Init(int aWidth, int aHeight, int aDisplayWidth,
+                           int aDisplayHeight, TrackRate aTrackRate)
 {
   mFrameWidth = aWidth;
   mFrameHeight = aHeight;
   mTrackRate = aTrackRate;
+  mDisplayWidth = aDisplayWidth;
+  mDisplayHeight = aDisplayHeight;
 
   mEncoder = OMXCodecWrapper::CreateAVCEncoder();
   NS_ENSURE_TRUE(mEncoder, NS_ERROR_FAILURE);
 
   nsresult rv = mEncoder->Configure(mFrameWidth, mFrameHeight,
                                     ENCODER_CONFIG_FRAME_RATE);
 
   ReentrantMonitorAutoEnter mon(mReentrantMonitor);
--- a/content/media/encoder/OmxTrackEncoder.h
+++ b/content/media/encoder/OmxTrackEncoder.h
@@ -30,17 +30,19 @@ public:
     : VideoTrackEncoder()
   {}
 
   already_AddRefed<TrackMetadataBase> GetMetadata() MOZ_OVERRIDE;
 
   nsresult GetEncodedTrack(EncodedFrameContainer& aData) MOZ_OVERRIDE;
 
 protected:
-  nsresult Init(int aWidth, int aHeight, TrackRate aTrackRate) MOZ_OVERRIDE;
+  nsresult Init(int aWidth, int aHeight,
+                int aDisplayWidth, int aDisplayHeight,
+                TrackRate aTrackRate) MOZ_OVERRIDE;
 
 private:
   nsAutoPtr<android::OMXVideoEncoder> mEncoder;
 };
 
 class OmxAudioTrackEncoder MOZ_FINAL : public AudioTrackEncoder
 {
 public:
--- a/content/media/encoder/TrackEncoder.cpp
+++ b/content/media/encoder/TrackEncoder.cpp
@@ -158,17 +158,20 @@ VideoTrackEncoder::NotifyQueuedTrackChan
 
    // Check and initialize parameters for codec encoder.
   if (!mInitialized) {
     VideoSegment::ChunkIterator iter(const_cast<VideoSegment&>(video));
     while (!iter.IsEnded()) {
       VideoChunk chunk = *iter;
       if (!chunk.IsNull()) {
         gfx::IntSize imgsize = chunk.mFrame.GetImage()->GetSize();
-        nsresult rv = Init(imgsize.width, imgsize.height, aTrackRate);
+        gfxIntSize intrinsicSize = chunk.mFrame.GetIntrinsicSize();
+        nsresult rv = Init(imgsize.width, imgsize.height,
+                           intrinsicSize.width, intrinsicSize.height,
+                           aTrackRate);
         if (NS_FAILED(rv)) {
           LOG("[VideoTrackEncoder]: Fail to initialize the encoder!");
           NotifyCancel();
         }
         break;
       }
 
       iter.Next();
@@ -209,17 +212,18 @@ VideoTrackEncoder::AppendVideoSegment(co
 }
 
 void
 VideoTrackEncoder::NotifyEndOfStream()
 {
   // If source video track is muted till the end of encoding, initialize the
   // encoder with default frame width, frame height, and track rate.
   if (!mCanceled && !mInitialized) {
-    Init(DEFAULT_FRAME_WIDTH, DEFAULT_FRAME_HEIGHT, DEFAULT_TRACK_RATE);
+    Init(DEFAULT_FRAME_WIDTH, DEFAULT_FRAME_HEIGHT,
+         DEFAULT_FRAME_WIDTH, DEFAULT_FRAME_HEIGHT, DEFAULT_TRACK_RATE);
   }
 
   ReentrantMonitorAutoEnter mon(mReentrantMonitor);
   mEndOfStream = true;
   mReentrantMonitor.NotifyAll();
 }
 
 void
--- a/content/media/encoder/TrackEncoder.h
+++ b/content/media/encoder/TrackEncoder.h
@@ -217,16 +217,18 @@ protected:
 
 class VideoTrackEncoder : public TrackEncoder
 {
 public:
   VideoTrackEncoder()
     : TrackEncoder()
     , mFrameWidth(0)
     , mFrameHeight(0)
+    , mDisplayWidth(0)
+    , mDisplayHeight(0)
     , mTrackRate(0)
     , mTotalFrameDuration(0)
   {}
 
   /**
    * Notified by the same callbcak of MediaEncoder when it has received a track
    * change from MediaStreamGraph. Called on the MediaStreamGraph thread.
    */
@@ -239,17 +241,18 @@ public:
 protected:
   /**
    * Initialized the video encoder. In order to collect the value of width and
    * height of source frames, this initialization is delayed until we have
    * received the first valid video frame from MediaStreamGraph;
    * mReentrantMonitor will be notified after it has successfully initialized,
    * and this method is called on the MediaStramGraph thread.
    */
-  virtual nsresult Init(int aWidth, int aHeight, TrackRate aTrackRate) = 0;
+  virtual nsresult Init(int aWidth, int aHeight, int aDisplayWidth,
+                        int aDisplayHeight, TrackRate aTrackRate) = 0;
 
   /**
    * Appends source video frames to mRawSegment. We only append the source chunk
    * if it is unique to mLastChunk. Called on the MediaStreamGraph thread.
    */
   nsresult AppendVideoSegment(const VideoSegment& aSegment);
 
   /**
@@ -271,16 +274,26 @@ protected:
   int mFrameWidth;
 
   /**
    * The height of source video frame, ceiled if the source height is odd.
    */
   int mFrameHeight;
 
   /**
+   * The display width of source video frame.
+   */
+  int mDisplayWidth;
+
+  /**
+   * The display height of source video frame.
+   */
+  int mDisplayHeight;
+
+  /**
    * The track rate of source video.
    */
   TrackRate mTrackRate;
 
   /**
    * The total duration of frames in encoded video in TrackTicks, kept track of
    * in subclasses.
    */
--- a/content/media/encoder/VP8TrackEncoder.cpp
+++ b/content/media/encoder/VP8TrackEncoder.cpp
@@ -48,29 +48,33 @@ VP8TrackEncoder::~VP8TrackEncoder()
 
   if (mVPXImageWrapper) {
     vpx_img_free(mVPXImageWrapper);
   }
   MOZ_COUNT_DTOR(VP8TrackEncoder);
 }
 
 nsresult
-VP8TrackEncoder::Init(int32_t aWidth, int32_t aHeight, TrackRate aTrackRate)
+VP8TrackEncoder::Init(int32_t aWidth, int32_t aHeight, int32_t aDisplayWidth,
+                      int32_t aDisplayHeight,TrackRate aTrackRate)
 {
-  if (aWidth < 1 || aHeight < 1 || aTrackRate <= 0) {
+  if (aWidth < 1 || aHeight < 1 || aDisplayWidth < 1 || aDisplayHeight < 1
+      || aTrackRate <= 0) {
     return NS_ERROR_FAILURE;
   }
 
   ReentrantMonitorAutoEnter mon(mReentrantMonitor);
 
   mTrackRate = aTrackRate;
   mEncodedFrameRate = DEFAULT_ENCODE_FRAMERATE;
   mEncodedFrameDuration = mTrackRate / mEncodedFrameRate;
   mFrameWidth = aWidth;
   mFrameHeight = aHeight;
+  mDisplayWidth = aDisplayWidth;
+  mDisplayHeight = aDisplayHeight;
 
   // Encoder configuration structure.
   vpx_codec_enc_cfg_t config;
   memset(&config, 0, sizeof(vpx_codec_enc_cfg_t));
   if (vpx_codec_enc_config_default(vpx_codec_vp8_cx(), &config, 0)) {
     return NS_ERROR_FAILURE;
   }
 
@@ -148,16 +152,18 @@ VP8TrackEncoder::GetMetadata()
 
   if (mCanceled || mEncodingComplete) {
     return nullptr;
   }
 
   nsRefPtr<VP8Metadata> meta = new VP8Metadata();
   meta->mWidth = mFrameWidth;
   meta->mHeight = mFrameHeight;
+  meta->mDisplayWidth = mDisplayWidth;
+  meta->mDisplayHeight = mDisplayHeight;
   meta->mEncodedFrameRate = mEncodedFrameRate;
 
   return meta.forget();
 }
 
 nsresult
 VP8TrackEncoder::GetEncodedPartitions(EncodedFrameContainer& aData)
 {
--- a/content/media/encoder/VP8TrackEncoder.h
+++ b/content/media/encoder/VP8TrackEncoder.h
@@ -33,16 +33,17 @@ public:
   virtual ~VP8TrackEncoder();
 
   already_AddRefed<TrackMetadataBase> GetMetadata() MOZ_FINAL MOZ_OVERRIDE;
 
   nsresult GetEncodedTrack(EncodedFrameContainer& aData) MOZ_FINAL MOZ_OVERRIDE;
 
 protected:
   nsresult Init(int32_t aWidth, int32_t aHeight,
+                int32_t aDisplayWidth, int32_t aDisplayHeight,
                 TrackRate aTrackRate) MOZ_FINAL MOZ_OVERRIDE;
 
 private:
   // Calculate the target frame's encoded duration.
   TrackTicks CalculateEncodedDuration(TrackTicks aDurationCopied);
 
   // Calculate the mRemainingTicks for next target frame.
   TrackTicks CalculateRemainingTicks(TrackTicks aDurationCopied,
--- a/content/media/webm/EbmlComposer.cpp
+++ b/content/media/webm/EbmlComposer.cpp
@@ -36,17 +36,18 @@ void EbmlComposer::GenerateHeader()
       writeSegmentInformation(&ebml, &ebmlLoc, TIME_CODE_SCALE, 0);
       {
         EbmlLoc trackLoc;
         Ebml_StartSubElement(&ebml, &trackLoc, Tracks);
         {
           // Video
           if (mWidth > 0 && mHeight > 0) {
             writeVideoTrack(&ebml, 0x1, 0, "V_VP8",
-                            mWidth, mHeight, mFrameRate);
+                            mWidth, mHeight,
+                            mDisplayWidth, mDisplayHeight, mFrameRate);
           }
           // Audio
           if (mCodecPrivateData.Length() > 0) {
             writeAudioTrack(&ebml, 0x2, 0x0, "A_VORBIS", mSampleFreq,
                             mChannels, mCodecPrivateData.Elements(),
                             mCodecPrivateData.Length());
           }
         }
@@ -118,23 +119,28 @@ EbmlComposer::WriteSimpleBlock(EncodedFr
   }
   MOZ_ASSERT_IF(ebml.offset > DEFAULT_HEADER_SIZE + aFrame->GetFrameData().Length(),
                 "write more data > EBML_BUFFER_SIZE");
   mClusterBuffs.LastElement().SetLength(ebml.offset);
 }
 
 void
 EbmlComposer::SetVideoConfig(uint32_t aWidth, uint32_t aHeight,
+                             uint32_t aDisplayWidth, uint32_t aDisplayHeight,
                              float aFrameRate)
 {
   MOZ_ASSERT(aWidth > 0, "Width should > 0");
   MOZ_ASSERT(aHeight > 0, "Height should > 0");
+  MOZ_ASSERT(aDisplayWidth > 0, "DisplayWidth should > 0");
+  MOZ_ASSERT(aDisplayHeight > 0, "DisplayHeight should > 0");
   MOZ_ASSERT(aFrameRate > 0, "FrameRate should > 0");
   mWidth = aWidth;
   mHeight = aHeight;
+  mDisplayWidth = aDisplayWidth;
+  mDisplayHeight = aDisplayHeight;
   mFrameRate = aFrameRate;
 }
 
 void
 EbmlComposer::SetAudioConfig(uint32_t aSampleFreq, uint32_t aChannels,
                              uint32_t aBitDepth)
 {
   MOZ_ASSERT(aSampleFreq > 0, "SampleFreq should > 0");
--- a/content/media/webm/EbmlComposer.h
+++ b/content/media/webm/EbmlComposer.h
@@ -14,17 +14,18 @@ namespace mozilla {
  * A WebM muxer helper for package the valid WebM format.
  */
 class EbmlComposer {
 public:
   EbmlComposer();
   /*
    * Assign the parameter which header required.
    */
-  void SetVideoConfig(uint32_t aWidth, uint32_t aHeight, float aFrameRate);
+  void SetVideoConfig(uint32_t aWidth, uint32_t aHeight, uint32_t aDisplayWidth,
+                      uint32_t aDisplayHeight, float aFrameRate);
 
   void SetAudioConfig(uint32_t aSampleFreq, uint32_t aChannels,
                       uint32_t bitDepth);
   /*
    * Set the CodecPrivateData for writing in header.
    */
   void SetAudioCodecPrivateData(nsTArray<uint8_t>& aBufs)
   {
@@ -59,16 +60,18 @@ private:
   nsTArray<uint8_t> mCodecPrivateData;
 
   // The timecode of the cluster.
   uint64_t mClusterTimecode;
 
   // Video configuration
   int mWidth;
   int mHeight;
+  int mDisplayWidth;
+  int mDisplayHeight;
   float mFrameRate;
   // Audio configuration
   float mSampleFreq;
   int mBitDepth;
   int mChannels;
 };
 
 }
--- a/content/media/webm/WebMWriter.cpp
+++ b/content/media/webm/WebMWriter.cpp
@@ -38,16 +38,17 @@ WebMWriter::GetContainerData(nsTArray<ns
 nsresult
 WebMWriter::SetMetadata(TrackMetadataBase* aMetadata)
 {
   MOZ_ASSERT(aMetadata);
   if (aMetadata->GetKind() == TrackMetadataBase::METADATA_VP8) {
     VP8Metadata* meta = static_cast<VP8Metadata*>(aMetadata);
     MOZ_ASSERT(meta, "Cannot find vp8 encoder metadata");
     mEbmlComposer->SetVideoConfig(meta->mWidth, meta->mHeight,
+                                  meta->mDisplayWidth, meta->mDisplayHeight,
                                   meta->mEncodedFrameRate);
     mMetadataRequiredFlag = mMetadataRequiredFlag & ~ContainerWriter::CREATE_VIDEO_TRACK;
   }
 
   if (aMetadata->GetKind() == TrackMetadataBase::METADATA_VORBIS) {
     VorbisMetadata* meta = static_cast<VorbisMetadata*>(aMetadata);
     MOZ_ASSERT(meta, "Cannot find vorbis encoder metadata");
     mEbmlComposer->SetAudioConfig(meta->mSamplingFrequency, meta->mChannels, meta->mBitDepth);
--- a/content/media/webm/WebMWriter.h
+++ b/content/media/webm/WebMWriter.h
@@ -24,16 +24,18 @@ public:
 };
 
 // VP8 meta data structure
 class VP8Metadata : public TrackMetadataBase
 {
 public:
   int32_t mWidth;
   int32_t mHeight;
+  int32_t mDisplayWidth;
+  int32_t mDisplayHeight;
   int32_t mEncodedFrameRate;
   MetadataKind GetKind() const MOZ_OVERRIDE { return METADATA_VP8; }
 };
 
 /**
  * WebM writer helper
  * This class accepts encoder to set audio or video meta data or
  * encoded data to ebml Composer, and get muxing data through GetContainerData.
--- a/dom/datastore/DataStore.jsm
+++ b/dom/datastore/DataStore.jsm
@@ -305,26 +305,33 @@ this.DataStore.prototype = {
   receiveMessage: function(aMessage) {
     debug("receiveMessage");
 
     if (aMessage.name != "DataStore:Changed:Return:OK") {
       debug("Wrong message: " + aMessage.name);
       return;
     }
 
+    // If this message is not for this DataStore, let's ignore it.
+    if (aMessage.data.owner != this._owner ||
+        aMessage.data.store != this._name) {
+      return;
+    }
+
     let self = this;
 
     this.retrieveRevisionId(
       function() {
         // If we have an active cursor we don't emit events.
         if (self._cursor) {
           return;
         }
 
-        let event = new self._window.DataStoreChangeEvent('change', aMessage.data);
+        let event = new self._window.DataStoreChangeEvent('change',
+                                                          aMessage.data.message);
         self.__DOM_IMPL__.dispatchEvent(event);
       }
     );
   },
 
   get exposedObject() {
     debug("get exposedObject");
     return this._exposedObject;
--- a/dom/datastore/DataStoreChangeNotifier.jsm
+++ b/dom/datastore/DataStoreChangeNotifier.jsm
@@ -51,42 +51,35 @@ this.DataStoreChangeNotifier = {
         break;
 
       default:
         debug("Wrong observer topic: " + aTopic);
         break;
     }
   },
 
-  broadcastMessage: function broadcastMessage(aMsgName, aData) {
-    debug("Broadast");
-    this.children.forEach(function(obj) {
-      if (obj.store == aData.store && obj.owner == aData.owner) {
-        obj.mm.sendAsyncMessage(aMsgName, aData.message);
-      }
-    });
-  },
-
   receiveMessage: function(aMessage) {
     debug("receiveMessage");
 
     // No check has to be done when the message is 'child-process-shutdown'
     // because at this point the target is already disconnected from
     // nsFrameMessageManager, so that assertAppHasStatus will always fail.
     let prefName = 'dom.testing.datastore_enabled_for_hosted_apps';
     if (aMessage.name != 'child-process-shutdown' &&
         (Services.prefs.getPrefType(prefName) == Services.prefs.PREF_INVALID ||
          !Services.prefs.getBoolPref(prefName)) &&
         !aMessage.target.assertAppHasStatus(Ci.nsIPrincipal.APP_STATUS_CERTIFIED)) {
       return;
     }
 
     switch (aMessage.name) {
       case "DataStore:Changed":
-        this.broadcastMessage("DataStore:Changed:Return:OK", aMessage.data);
+        debug("Broadasting message.");
+        let childMM = aMessage.target.QueryInterface(Ci.nsIMessageSender);
+        childMM.sendAsyncMessage("DataStore:Changed:Return:OK", aMessage.data);
         break;
 
       case "DataStore:RegisterForMessages":
         debug("Register!");
 
         for (let i = 0; i < this.children.length; ++i) {
           if (this.children[i].mm == aMessage.target &&
               this.children[i].store == aMessage.data.store &&
--- a/dom/datastore/tests/file_basic.html
+++ b/dom/datastore/tests/file_basic.html
@@ -118,18 +118,17 @@
     function() { testStoreGet(gId, "hello world 2"); },
 
     // getLength
     function() { testStoreGetLength(3).then(function() { runTest(); }, cbError); },
 
     // Remove
     function() { testStoreRemove(gId).then(function(what) {
                    runTest(); }, cbError); },
-    function() { testStoreGet(gId).catch(function() {
-                   runTest(); }); },
+    function() { testStoreGet(gId, undefined); },
 
     // Remove - wrong ID
     function() { testStoreRemove(gId).then(function(what) {
                    runTest(); }, cbError); },
 
     // Clear
     function() { testStoreClear().then(function(what) {
                    runTest(); }, cbError); },
new file mode 100644
--- /dev/null
+++ b/dom/datastore/tests/file_bug976311.html
@@ -0,0 +1,88 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <meta charset="utf-8">
+  <title>Test for DataStore - bug 976311 app1</title>
+</head>
+<body>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+  <script type="application/javascript;version=1.7">
+
+  var gStores = [];
+  var expectedWhere;
+
+  function is(a, b, msg) {
+    ok(a === b, msg);
+  }
+
+  function ok(a, msg) {
+    alert((a ? 'OK' : 'KO')+ ' ' + msg)
+  }
+
+  function cbError() {
+    alert('KO error');
+  }
+
+  function finish() {
+    alert('DONE');
+  }
+
+  function checkEvent(id) {
+    is(expectedWhere, id, "Message on the correct DS: " + id + " " + expectedWhere);
+    runTest();
+  }
+
+  function testGetDataStores() {
+    navigator.getDataStores('foo').then(function(stores) {
+      is(stores.length, 2, "getDataStores('foo') returns 1 element");
+
+      is(stores[0].name, 'foo', 'The dataStore.name is foo');
+      is(stores[0].readOnly, false, 'The dataStore foo is not in readonly');
+      stores[0].onchange = function(evt) { checkEvent(0); }
+      gStores.push(stores[0]);
+
+      is(stores[1].name, 'foo', 'The dataStore.name is foo');
+      is(stores[1].readOnly, false, 'The dataStore foo is not in readonly');
+      stores[1].onchange = function(evt) { checkEvent(1); }
+      gStores.push(stores[1]);
+
+      runTest();
+    }, cbError);
+  }
+
+  function testStoreAdd(where, value) {
+    expectedWhere = where;
+    dump("ADD TO: " + gStores[where].owner + "\n");
+    gStores[where].add({ a: value });
+  }
+
+  var tests = [
+    // Test for GetDataStore
+    testGetDataStores,
+
+    function() { testStoreAdd(0, 1); },
+    function() { testStoreAdd(1, 2); },
+    function() { testStoreAdd(0, 3); },
+    function() { testStoreAdd(1, 4); }
+  ];
+
+  function runTest() {
+    if (!tests.length) {
+      finish();
+      return;
+    }
+
+    var test = tests.shift();
+    test();
+  }
+
+  runTest();
+  </script>
+</pre>
+</body>
+</html>
+
new file mode 100644
--- /dev/null
+++ b/dom/datastore/tests/file_bug976311.template.webapp
@@ -0,0 +1,12 @@
+{
+  "name": "Really Rapid Release (hosted)",
+  "description": "Updated even faster than <a href='http://mozilla.org'>Firefox</a>, just to annoy slashdotters.",
+  "launch_path": "/tests/dom/datastore/tests/TESTTOKEN",
+  "icons": { "128": "default_icon" },
+  "datastores-owned" : {
+    "foo" : { "access": "readwrite", "description" : "This store is called foo" }
+  },
+  "datastores-access" : {
+    "foo" : { "readonly": false, "description" : "This store is called foo" }
+  }
+}
--- a/dom/datastore/tests/mochitest.ini
+++ b/dom/datastore/tests/mochitest.ini
@@ -9,20 +9,23 @@ support-files =
   file_app.template.webapp
   file_app2.template.webapp
   file_arrays.html
   file_sync.html
   file_bug924104.html
   file_certifiedApp.html
   file_keys.html
   file_duplicate.html
+  file_bug976311.html
+  file_bug976311.template.webapp
 
 [test_app_install.html]
 [test_readonly.html]
 [test_basic.html]
 [test_changes.html]
 [test_arrays.html]
 [test_oop.html]
 [test_sync.html]
 [test_bug924104.html]
 [test_certifiedApp.html]
 [test_keys.html]
 [test_duplicate.html]
+[test_bug976311.html]
new file mode 100644
--- /dev/null
+++ b/dom/datastore/tests/test_bug976311.html
@@ -0,0 +1,135 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <meta charset="utf-8">
+  <title>Test for DataStore - bug 976311</title>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<div id="container"></div>
+  <script type="application/javascript;version=1.7">
+
+  var gHostedManifestURL = 'http://test/tests/dom/datastore/tests/file_app.sjs?testToken=file_bug976311.html&template=file_bug976311.template.webapp';
+  var gHostedManifestURL2 = 'http://example.com/tests/dom/datastore/tests/file_app.sjs?testToken=file_bug976311.html&template=file_bug976311.template.webapp';
+  var gApps = [];
+
+  function cbError() {
+    ok(false, "Error callback invoked");
+    finish();
+  }
+
+  function installApp(aApp) {
+    var request = navigator.mozApps.install(aApp);
+    request.onerror = cbError;
+    request.onsuccess = function() {
+      gApps.push(request.result);
+      runTest();
+    }
+  }
+
+  function uninstallApps() {
+    if (!gApps.length) {
+      ok(true, "All done!");
+      runTest();
+      return;
+    }
+
+    var app = gApps.pop();
+    var request = navigator.mozApps.mgmt.uninstall(app);
+    request.onerror = cbError;
+    request.onsuccess = uninstallApps;
+  }
+
+
+  function testApp() {
+   var ifr = document.createElement('iframe');
+   ifr.setAttribute('mozbrowser', 'true');
+   ifr.setAttribute('mozapp', gApps[0].manifestURL);
+   ifr.setAttribute('src', gApps[0].manifest.launch_path);
+   var domParent = document.getElementById('container');
+
+   // Set us up to listen for messages from the app.
+   var listener = function(e) {
+     var message = e.detail.message;
+     if (/^OK/.exec(message)) {
+       ok(true, "Message from app: " + message);
+     } else if (/KO/.exec(message)) {
+       ok(false, "Message from app: " + message);
+     } else if (/DONE/.exec(message)) {
+       ok(true, "Messaging from app complete");
+       ifr.removeEventListener('mozbrowsershowmodalprompt', listener);
+       domParent.removeChild(ifr);
+       runTest();
+     }
+   }
+
+   // This event is triggered when the app calls "alert".
+   ifr.addEventListener('mozbrowsershowmodalprompt', listener, false);
+   domParent.appendChild(ifr);
+
+  }
+
+  var tests = [
+    // Permissions
+    function() {
+      SpecialPowers.pushPermissions(
+        [{ "type": "browser", "allow": 1, "context": document },
+         { "type": "embed-apps", "allow": 1, "context": document },
+         { "type": "webapps-manage", "allow": 1, "context": document }], runTest);
+    },
+
+    // Preferences
+    function() {
+      SpecialPowers.pushPrefEnv({"set": [["dom.datastore.enabled", true],
+                                         ["dom.testing.ignore_ipc_principal", true],
+                                         ["dom.testing.datastore_enabled_for_hosted_apps", true]]}, runTest);
+    },
+
+    function() {
+      SpecialPowers.setAllAppsLaunchable(true);
+      SpecialPowers.setBoolPref("dom.mozBrowserFramesEnabled", true);
+      runTest();
+    },
+
+    // No confirmation needed when an app is installed
+    function() {
+      SpecialPowers.autoConfirmAppInstall(runTest);
+    },
+
+    // Installing the app1
+    function() { installApp(gHostedManifestURL); },
+
+    // Installing the app2
+    function() { installApp(gHostedManifestURL2); },
+
+    // Run tests in app
+    testApp,
+
+    // Uninstall the apps
+    uninstallApps
+  ];
+
+  function runTest() {
+    if (!tests.length) {
+      finish();
+      return;
+    }
+
+    var test = tests.shift();
+    test();
+  }
+
+  function finish() {
+    SimpleTest.finish();
+  }
+
+  if (SpecialPowers.isMainProcess()) {
+    SpecialPowers.Cu.import("resource://gre/modules/DataStoreChangeNotifier.jsm");
+  }
+
+  SimpleTest.waitForExplicitFinish();
+  runTest();
+  </script>
+</body>
+</html>
--- a/gfx/2d/FilterNodeSoftware.cpp
+++ b/gfx/2d/FilterNodeSoftware.cpp
@@ -529,32 +529,32 @@ FilterNodeSoftware::Create(FilterType aT
       break;
     case FilterType::PREMULTIPLY:
       filter = new FilterNodePremultiplySoftware();
       break;
     case FilterType::UNPREMULTIPLY:
       filter = new FilterNodeUnpremultiplySoftware();
       break;
     case FilterType::POINT_DIFFUSE:
-      filter = new FilterNodeLightingSoftware<PointLightSoftware, DiffuseLightingSoftware>();
+      filter = new FilterNodeLightingSoftware<PointLightSoftware, DiffuseLightingSoftware>("FilterNodeLightingSoftware<PointLight, DiffuseLighting>");
       break;
     case FilterType::POINT_SPECULAR:
-      filter = new FilterNodeLightingSoftware<PointLightSoftware, SpecularLightingSoftware>();
+      filter = new FilterNodeLightingSoftware<PointLightSoftware, SpecularLightingSoftware>("FilterNodeLightingSoftware<PointLight, SpecularLighting>");
       break;
     case FilterType::SPOT_DIFFUSE:
-      filter = new FilterNodeLightingSoftware<SpotLightSoftware, DiffuseLightingSoftware>();
+      filter = new FilterNodeLightingSoftware<SpotLightSoftware, DiffuseLightingSoftware>("FilterNodeLightingSoftware<SpotLight, DiffuseLighting>");
       break;
     case FilterType::SPOT_SPECULAR:
-      filter = new FilterNodeLightingSoftware<SpotLightSoftware, SpecularLightingSoftware>();
+      filter = new FilterNodeLightingSoftware<SpotLightSoftware, SpecularLightingSoftware>("FilterNodeLightingSoftware<SpotLight, SpecularLighting>");
       break;
     case FilterType::DISTANT_DIFFUSE:
-      filter = new FilterNodeLightingSoftware<DistantLightSoftware, DiffuseLightingSoftware>();
+      filter = new FilterNodeLightingSoftware<DistantLightSoftware, DiffuseLightingSoftware>("FilterNodeLightingSoftware<DistantLight, DiffuseLighting>");
       break;
     case FilterType::DISTANT_SPECULAR:
-      filter = new FilterNodeLightingSoftware<DistantLightSoftware, SpecularLightingSoftware>();
+      filter = new FilterNodeLightingSoftware<DistantLightSoftware, SpecularLightingSoftware>("FilterNodeLightingSoftware<DistantLight, SpecularLighting>");
       break;
   }
   return filter;
 }
 
 void
 FilterNodeSoftware::Draw(DrawTarget* aDrawTarget,
                          const Rect &aSourceRect,
@@ -3054,18 +3054,21 @@ DistantLightSoftware::SetAttribute(uint3
 
 static inline Point3D Normalized(const Point3D &vec) {
   Point3D copy(vec);
   copy.Normalize();
   return copy;
 }
 
 template<typename LightType, typename LightingType>
-FilterNodeLightingSoftware<LightType, LightingType>::FilterNodeLightingSoftware()
+FilterNodeLightingSoftware<LightType, LightingType>::FilterNodeLightingSoftware(const char* aTypeName)
  : mSurfaceScale(0)
+#if defined(MOZILLA_INTERNAL_API) && (defined(DEBUG) || defined(FORCE_BUILD_REFCNT_LOGGING))
+ , mTypeName(aTypeName)
+#endif
 {}
 
 template<typename LightType, typename LightingType>
 int32_t
 FilterNodeLightingSoftware<LightType, LightingType>::InputIndex(uint32_t aInputEnumIndex)
 {
   switch (aInputEnumIndex) {
     case IN_LIGHTING_IN: return 0;
--- a/gfx/2d/FilterNodeSoftware.h
+++ b/gfx/2d/FilterNodeSoftware.h
@@ -678,18 +678,22 @@ protected:
   virtual int32_t InputIndex(uint32_t aInputEnumIndex) MOZ_OVERRIDE;
   virtual void RequestFromInputsForRect(const IntRect &aRect) MOZ_OVERRIDE;
 };
 
 template<typename LightType, typename LightingType>
 class FilterNodeLightingSoftware : public FilterNodeSoftware
 {
 public:
-  MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(FilterNodeLightingSoftware)
-  FilterNodeLightingSoftware();
+#if defined(MOZILLA_INTERNAL_API) && (defined(DEBUG) || defined(FORCE_BUILD_REFCNT_LOGGING))
+  // Helpers for refcounted
+  virtual const char* typeName() const MOZ_OVERRIDE { return mTypeName; }
+  virtual size_t typeSize() const MOZ_OVERRIDE { return sizeof(*this); }
+#endif
+  explicit FilterNodeLightingSoftware(const char* aTypeName);
   virtual const char* GetName() MOZ_OVERRIDE { return "Lighting"; }
   using FilterNodeSoftware::SetAttribute;
   virtual void SetAttribute(uint32_t aIndex, Float) MOZ_OVERRIDE;
   virtual void SetAttribute(uint32_t aIndex, const Size &) MOZ_OVERRIDE;
   virtual void SetAttribute(uint32_t aIndex, const Point3D &) MOZ_OVERRIDE;
   virtual void SetAttribute(uint32_t aIndex, const Color &) MOZ_OVERRIDE;
 
 protected:
@@ -704,14 +708,17 @@ private:
                                            CoordType aKernelUnitLengthX,
                                            CoordType aKernelUnitLengthY);
 
   LightType mLight;
   LightingType mLighting;
   Float mSurfaceScale;
   Size mKernelUnitLength;
   Color mColor;
+#if defined(MOZILLA_INTERNAL_API) && (defined(DEBUG) || defined(FORCE_BUILD_REFCNT_LOGGING))
+  const char* mTypeName;
+#endif
 };
 
 }
 }
 
 #endif // _MOZILLA_GFX_FILTERNODESOFTWARE_H_
--- a/gfx/layers/opengl/OGLShaderProgram.cpp
+++ b/gfx/layers/opengl/OGLShaderProgram.cpp
@@ -178,16 +178,22 @@ ProgramProfileOGL::GetProfileFor(ShaderC
 
   if (!(aConfig.mFeatures & ENABLE_RENDER_COLOR)) {
     vs << "  vTexCoord = (uTextureTransform * vec4(aTexCoord.x, aTexCoord.y, 0.0, 1.0)).xy;" << endl;
   }
 
   vs << "  gl_Position = finalPosition;" << endl;
   vs << "}" << endl;
 
+  if (aConfig.mFeatures & ENABLE_TEXTURE_RECT) {
+    fs << "#extension GL_ARB_texture_rectangle : require" << endl;
+  }
+  if (aConfig.mFeatures & ENABLE_TEXTURE_EXTERNAL) {
+    fs << "#extension GL_OES_EGL_image_external : require" << endl;
+  }
   fs << "#ifdef GL_ES" << endl;
   fs << "precision mediump float;" << endl;
   fs << "#define COLOR_PRECISION lowp" << endl;
   fs << "#else" << endl;
   fs << "#define COLOR_PRECISION" << endl;
   fs << "#endif" << endl;
   if (aConfig.mFeatures & ENABLE_RENDER_COLOR) {
     fs << "uniform COLOR_PRECISION vec4 uRenderColor;" << endl;
@@ -208,24 +214,22 @@ ProgramProfileOGL::GetProfileFor(ShaderC
       fs << "uniform COLOR_PRECISION float uLayerOpacity;" << endl;
     }
   }
 
   const char *sampler2D = "sampler2D";
   const char *texture2D = "texture2D";
 
   if (aConfig.mFeatures & ENABLE_TEXTURE_RECT) {
-    fs << "#extension GL_ARB_texture_rectangle : require" << endl;
     fs << "uniform vec2 uTexCoordMultiplier;" << endl;
     sampler2D = "sampler2DRect";
     texture2D = "texture2DRect";
   }
 
   if (aConfig.mFeatures & ENABLE_TEXTURE_EXTERNAL) {
-    fs << "#extension GL_OES_EGL_image_external : require" << endl;
     sampler2D = "samplerExternalOES";
   }
 
   if (aConfig.mFeatures & ENABLE_TEXTURE_YCBCR) {
     fs << "uniform sampler2D uYTexture;" << endl;
     fs << "uniform sampler2D uCbTexture;" << endl;
     fs << "uniform sampler2D uCrTexture;" << endl;
   } else if (aConfig.mFeatures & ENABLE_TEXTURE_COMPONENT_ALPHA) {
--- a/js/src/builtin/Object.cpp
+++ b/js/src/builtin/Object.cpp
@@ -651,31 +651,31 @@ obj_hasOwnProperty(JSContext *cx, unsign
         return false;
 
     /* Step 2. */
     RootedObject obj(cx, ToObject(cx, args.thisv()));
     if (!obj)
         return false;
 
     /* Non-standard code for proxies. */
-    RootedObject obj2(cx);
-    RootedShape prop(cx);
     if (obj->is<ProxyObject>()) {
         bool has;
         if (!Proxy::hasOwn(cx, obj, idRoot, &has))
             return false;
         args.rval().setBoolean(has);
         return true;
     }
 
     /* Step 3. */
-    if (!HasOwnProperty<CanGC>(cx, obj->getOps()->lookupGeneric, obj, idRoot, &obj2, &prop))
+    bool found;
+    if (!HasOwnProperty(cx, obj, idRoot, &found))
         return false;
+
     /* Step 4,5. */
-    args.rval().setBoolean(!!prop);
+    args.rval().setBoolean(found);
     return true;
 }
 
 /* ES5 15.2.4.6. */
 static bool
 obj_isPrototypeOf(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
--- a/js/src/frontend/Parser.cpp
+++ b/js/src/frontend/Parser.cpp
@@ -6424,18 +6424,20 @@ Parser<ParseHandler>::assignExprWithoutY
     }
     return res;
 }
 
 template <typename ParseHandler>
 bool
 Parser<ParseHandler>::argumentList(Node listNode, bool *isSpread)
 {
-    if (tokenStream.matchToken(TOK_RP, TokenStream::Operand))
+    if (tokenStream.matchToken(TOK_RP, TokenStream::Operand)) {
+        handler.setEndPosition(listNode, pos().end);
         return true;
+    }
 
     uint32_t startYieldOffset = pc->lastYieldOffset;
     bool arg0 = true;
 
     do {
         bool spread = false;
         uint32_t begin = 0;
         if (tokenStream.matchToken(TOK_TRIPLEDOT, TokenStream::Operand)) {
@@ -6478,16 +6480,17 @@ Parser<ParseHandler>::argumentList(Node 
 
         handler.addList(listNode, argNode);
     } while (tokenStream.matchToken(TOK_COMMA));
 
     if (tokenStream.getToken() != TOK_RP) {
         report(ParseError, false, null(), JSMSG_PAREN_AFTER_ARGS);
         return false;
     }
+    handler.setEndPosition(listNode, pos().end);
     return true;
 }
 
 template <typename ParseHandler>
 typename ParseHandler::Node
 Parser<ParseHandler>::memberExpr(TokenKind tt, bool allowCallSyntax)
 {
     JS_ASSERT(tokenStream.isCurrentTokenType(tt));
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/debug/bug973566.js
@@ -0,0 +1,7 @@
+Object.prototype[1] = 'peek';
+var g = newGlobal();
+var dbg = Debugger(g);
+dbg.onEnterFrame = function (frame) {
+    var lines = frame.script.getAllOffsets();
+};
+g.eval("1;");
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/ion/bug901086.js
@@ -0,0 +1,15 @@
+enableSPSProfilingAssertions(false);
+function foo(obj,x,y,z) {
+    if (!y)
+	assertEq(0, 1);
+    obj.x = x;
+    return y + z;
+}
+function bar() {
+    var objz = {x:2}
+    for(var i = 0; i < 1100; i++) {
+	foo(objz,1,2,3);
+	foo(objz, false, "bar", "foo");
+    }
+}
+bar();
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/ion/inlining/TypedObject-storage-opaque.js
@@ -0,0 +1,33 @@
+/* -*- Mode: C++; tab-width: 8; 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/. */
+
+/* Used to verify that the JIT resolves the transparent/opaque type
+ * tests internal to storage().
+ *
+ * In this case the argument type is always an opaque object, so
+ * ObjectIsOpaqueTypedObject resolves to true and
+ * ObjectIsTransparentTypedObject resolves to false.
+ *
+ * Load this into the js shell with IONFLAGS=logs, then exit and run
+ * iongraph.  func01 will likely be the one we want (look for calls to
+ * ObjectIsOpaqueTypedObject and ObjectIsTransparentTypedObject in the
+ * graph for pass00).
+ */
+
+var T = TypedObject;
+
+function check(v) {
+    return T.storage(v);
+}
+
+function test() {
+    var AT = new T.ArrayType(T.Any,10);
+    var v = new AT(10);
+    for ( var i=0 ; i < 1000 ; i++ )
+        check(v);
+    return check(v);
+}
+
+test();
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/ion/inlining/TypedObject-storage-transparent.js
@@ -0,0 +1,33 @@
+/* -*- Mode: C++; tab-width: 8; 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/. */
+
+/* Used to verify that the JIT resolves the transparent/opaque type
+ * tests internal to storage().
+ *
+ * In this case the argument type is always a transparent object, so
+ * ObjectIsOpaqueTypedObject resolves to false and
+ * ObjectIsTransparentTypedObject resolves to true.
+ *
+ * Load this into the js shell with IONFLAGS=logs, then exit and run
+ * iongraph.  func01 will likely be the one we want (look for calls to
+ * ObjectIsOpaqueTypedObject and ObjectIsTransparentTypedObject in the
+ * graph for pass00).
+ */
+
+var T = TypedObject;
+
+function check(v) {
+    return T.storage(v);
+}
+
+function test() {
+    var AT = new T.ArrayType(T.int32,10);
+    var v = new AT(10);
+    for ( var i=0 ; i < 1000 ; i++ )
+        check(v);
+    return check(v);
+}
+
+test();
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/ion/inlining/TypedObject-storage-unknown.js
@@ -0,0 +1,36 @@
+/* -*- Mode: C++; tab-width: 8; 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/. */
+
+/* Used to verify that the JIT resolves the transparent/opaque type
+ * tests internal to storage().
+ *
+ * In this case the argument type is variable and thus unknown to the
+ * JIT, so both ObjectIsOpaqueTypedObject and
+ * ObjectIsTransparentTypedObject are resolved as uses of the
+ * "HasClass" primitive.
+ *
+ * Load this into the js shell with IONFLAGS=logs, then exit and run
+ * iongraph.  func01 will likely be the one we want (look for calls to
+ * ObjectIsOpaqueTypedObject and ObjectIsTransparentTypedObject in the
+ * graph for pass00).
+ */
+
+var T = TypedObject;
+
+function check(v) {
+    return T.storage(v);
+}
+
+function test() {
+    var AT = new T.ArrayType(T.int32,10);
+    var v = new Object;         // Not actually a typed object
+    var w = new AT(10);         // Actually a typed object
+    var a = [v,w];
+    for ( var i=0 ; i < 1000 ; i++ )
+        try { check(a[i%2]); } catch (e) {}
+    try { return check(a[1]); } catch (e) {}
+}
+
+test();
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/ion/inlining/TypedObject-storage-wrong.js
@@ -0,0 +1,32 @@
+/* -*- Mode: C++; tab-width: 8; 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/. */
+
+/* Used to verify that the JIT resolves the transparent/opaque type
+ * tests internal to storage().
+ *
+ * In this case the argument type is always a non-TypedObject, so both
+ * ObjectIsOpaqueTypedObject and ObjectIsTransparentTypedObject
+ * resolve to false.
+ *
+ * Load this into the js shell with IONFLAGS=logs, then exit and run
+ * iongraph.  func01 will likely be the one we want (look for calls to
+ * ObjectIsOpaqueTypedObject and ObjectIsTransparentTypedObject in the
+ * graph for pass00).
+ */
+
+var T = TypedObject;
+
+function check(v) {
+    return T.storage(v);
+}
+
+function test() {
+    var v = new Object;         // Not actually a typed object
+    for ( var i=0 ; i < 1000 ; i++ )
+        try { check(v); } catch (e) {}
+    try { return check(v); } catch (e) {}
+}
+
+test();
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/parser/bug-975484.js
@@ -0,0 +1,7 @@
+var loc = Reflect.parse("f()").body[0].expression.loc;
+assertEq(loc.start.column, 0);
+assertEq(loc.end.column, 3);
+
+loc = Reflect.parse("f(x)").body[0].expression.loc;
+assertEq(loc.start.column, 0);
+assertEq(loc.end.column, 4);
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/xdr/scope.js
@@ -0,0 +1,19 @@
+load(libdir + 'bytecode-cache.js');
+var test = "";
+
+// code a function which has both used and unused inner functions.
+test  = (function () {
+  function f() {
+    var x = 3;
+    (function() {
+      with(obj) {
+        (function() {
+          assertEq(x, 2);
+        })();
+      }
+    })();
+  };
+
+  return "var obj = { x : 2 };" + f.toSource() + "; f()";
+})();
+evalWithCache(test, { assertEqBytecode: true, assertEqResult : true });
--- a/js/src/jit/CodeGenerator.cpp
+++ b/js/src/jit/CodeGenerator.cpp
@@ -8006,16 +8006,29 @@ CodeGenerator::visitHaveSameClass(LHaveS
     masm.loadObjClass(rhs, output);
     masm.cmpPtr(temp, output);
     masm.emitSet(Assembler::Equal, output);
 
     return true;
 }
 
 bool
+CodeGenerator::visitHasClass(LHasClass *ins)
+{
+    Register lhs = ToRegister(ins->lhs());
+    Register output = ToRegister(ins->output());
+
+    masm.loadObjClass(lhs, output);
+    masm.cmpPtr(output, ImmPtr(ins->mir()->getClass()));
+    masm.emitSet(Assembler::Equal, output);
+
+    return true;
+}
+
+bool
 CodeGenerator::visitAsmJSCall(LAsmJSCall *ins)
 {
     MAsmJSCall *mir = ins->mir();
 
 #if defined(JS_CODEGEN_ARM)
     if (!useHardFpABI() && mir->callee().which() == MAsmJSCall::Callee::Builtin) {
         for (unsigned i = 0, e = ins->numOperands(); i < e; i++) {
             LAllocation *a = ins->getOperand(i);
--- a/js/src/jit/CodeGenerator.h
+++ b/js/src/jit/CodeGenerator.h
@@ -275,16 +275,17 @@ class CodeGenerator : public CodeGenerat
     bool visitFunctionBoundary(LFunctionBoundary *lir);
     bool visitGetDOMProperty(LGetDOMProperty *lir);
     bool visitGetDOMMember(LGetDOMMember *lir);
     bool visitSetDOMProperty(LSetDOMProperty *lir);
     bool visitCallDOMNative(LCallDOMNative *lir);
     bool visitCallGetIntrinsicValue(LCallGetIntrinsicValue *lir);
     bool visitIsCallable(LIsCallable *lir);
     bool visitHaveSameClass(LHaveSameClass *lir);
+    bool visitHasClass(LHasClass *lir);
     bool visitAsmJSCall(LAsmJSCall *lir);
     bool visitAsmJSParameter(LAsmJSParameter *lir);
     bool visitAsmJSReturn(LAsmJSReturn *ret);
     bool visitAsmJSVoidReturn(LAsmJSVoidReturn *ret);
 
     bool visitCheckOverRecursed(LCheckOverRecursed *lir);
     bool visitCheckOverRecursedFailure(CheckOverRecursedFailure *ool);
     bool visitAsmJSCheckOverRecursed(LAsmJSCheckOverRecursed *lir);
--- a/js/src/jit/IonBuilder.h
+++ b/js/src/jit/IonBuilder.h
@@ -674,16 +674,17 @@ class IonBuilder : public MIRGenerator
     InliningStatus inlineUnsafeSetReservedSlot(CallInfo &callInfo);
     InliningStatus inlineUnsafeGetReservedSlot(CallInfo &callInfo);
 
     // Utility intrinsics.
     InliningStatus inlineIsCallable(CallInfo &callInfo);
     InliningStatus inlineHaveSameClass(CallInfo &callInfo);
     InliningStatus inlineToObject(CallInfo &callInfo);
     InliningStatus inlineDump(CallInfo &callInfo);
+    InliningStatus inlineHasClass(CallInfo &callInfo, const Class *clasp);
 
     // Testing functions.
     InliningStatus inlineForceSequentialOrInParallelSection(CallInfo &callInfo);
     InliningStatus inlineBailout(CallInfo &callInfo);
     InliningStatus inlineAssertFloat32(CallInfo &callInfo);
 
     // Main inlining functions
     InliningStatus inlineNativeCall(CallInfo &callInfo, JSNative native);
--- a/js/src/jit/LIR-Common.h
+++ b/js/src/jit/LIR-Common.h
@@ -5638,16 +5638,32 @@ class LHaveSameClass : public LInstructi
     const LAllocation *rhs() {
         return getOperand(1);
     }
     MHaveSameClass *mir() const {
         return mir_->toHaveSameClass();
     }
 };
 
+class LHasClass : public LInstructionHelper<1, 1, 0>
+{
+  public:
+    LIR_HEADER(HasClass);
+    LHasClass(const LAllocation &lhs) {
+        setOperand(0, lhs);
+    }
+
+    const LAllocation *lhs() {
+        return getOperand(0);
+    }
+    MHasClass *mir() const {
+        return mir_->toHasClass();
+    }
+};
+
 class LAsmJSLoadHeap : public LInstructionHelper<1, 1, 0>
 {
   public:
     LIR_HEADER(AsmJSLoadHeap);
     LAsmJSLoadHeap(const LAllocation &ptr) {
         setOperand(0, ptr);
     }
     MAsmJSLoadHeap *mir() const {
--- a/js/src/jit/LOpcodes.h
+++ b/js/src/jit/LOpcodes.h
@@ -270,16 +270,17 @@
     _(InterruptCheckImplicit)       \
     _(FunctionBoundary)             \
     _(GetDOMProperty)               \
     _(GetDOMMember)                 \
     _(SetDOMProperty)               \
     _(CallDOMNative)                \
     _(IsCallable)                   \
     _(HaveSameClass)                \
+    _(HasClass)                      \
     _(AsmJSLoadHeap)                \
     _(AsmJSStoreHeap)               \
     _(AsmJSLoadGlobalVar)           \
     _(AsmJSStoreGlobalVar)          \
     _(AsmJSLoadFFIFunc)             \
     _(AsmJSParameter)               \
     _(AsmJSReturn)                  \
     _(AsmJSVoidReturn)              \
--- a/js/src/jit/LinearScan.cpp
+++ b/js/src/jit/LinearScan.cpp
@@ -1074,17 +1074,17 @@ LinearScanAllocator::findBestBlockedRegi
     for (RegisterSet regs(allRegisters_); !regs.empty(needFloat); ) {
         AnyRegister reg = regs.takeAny(needFloat);
         nextUsePos[reg.code()] = CodePosition::MAX;
     }
     for (IntervalIterator i(active.begin()); i != active.end(); i++) {
         LAllocation *alloc = i->getAllocation();
         if (alloc->isRegister(needFloat)) {
             AnyRegister reg = alloc->toRegister();
-            if (i->start().ins() == current->start().ins()) {
+            if (i->start() == current->start()) {
                 nextUsePos[reg.code()] = CodePosition::MIN;
                 IonSpew(IonSpew_RegAlloc, "   Disqualifying %s due to recency", reg.name());
             } else if (nextUsePos[reg.code()] != CodePosition::MIN) {
                 nextUsePos[reg.code()] = i->nextUsePosAfter(current->start());
                 IonSpew(IonSpew_RegAlloc, "   Register %s next used %u", reg.name(),
                         nextUsePos[reg.code()].pos());
             }
         }
--- a/js/src/jit/Lowering.cpp
+++ b/js/src/jit/Lowering.cpp
@@ -3326,16 +3326,24 @@ LIRGenerator::visitHaveSameClass(MHaveSa
 
     JS_ASSERT(lhs->type() == MIRType_Object);
     JS_ASSERT(rhs->type() == MIRType_Object);
 
     return define(new(alloc()) LHaveSameClass(useRegister(lhs), useRegister(rhs), temp()), ins);
 }
 
 bool
+LIRGenerator::visitHasClass(MHasClass *ins)
+{
+    JS_ASSERT(ins->object()->type() == MIRType_Object);
+    JS_ASSERT(ins->type() == MIRType_Boolean);
+    return define(new(alloc()) LHasClass(useRegister(ins->object())), ins);
+}
+
+bool
 LIRGenerator::visitAsmJSLoadGlobalVar(MAsmJSLoadGlobalVar *ins)
 {
     return define(new(alloc()) LAsmJSLoadGlobalVar, ins);
 }
 
 bool
 LIRGenerator::visitAsmJSStoreGlobalVar(MAsmJSStoreGlobalVar *ins)
 {
--- a/js/src/jit/Lowering.h
+++ b/js/src/jit/Lowering.h
@@ -232,16 +232,17 @@ class LIRGenerator : public LIRGenerator
     bool visitThrow(MThrow *ins);
     bool visitIn(MIn *ins);
     bool visitInArray(MInArray *ins);
     bool visitInstanceOf(MInstanceOf *ins);
     bool visitCallInstanceOf(MCallInstanceOf *ins);
     bool visitFunctionBoundary(MFunctionBoundary *ins);
     bool visitIsCallable(MIsCallable *ins);
     bool visitHaveSameClass(MHaveSameClass *ins);
+    bool visitHasClass(MHasClass *ins);
     bool visitAsmJSLoadGlobalVar(MAsmJSLoadGlobalVar *ins);
     bool visitAsmJSStoreGlobalVar(MAsmJSStoreGlobalVar *ins);
     bool visitAsmJSLoadFFIFunc(MAsmJSLoadFFIFunc *ins);
     bool visitAsmJSParameter(MAsmJSParameter *ins);
     bool visitAsmJSReturn(MAsmJSReturn *ins);
     bool visitAsmJSVoidReturn(MAsmJSVoidReturn *ins);
     bool visitAsmJSPassStackArg(MAsmJSPassStackArg *ins);
     bool visitAsmJSCall(MAsmJSCall *ins);
--- a/js/src/jit/MCallOptimize.cpp
+++ b/js/src/jit/MCallOptimize.cpp
@@ -150,16 +150,22 @@ IonBuilder::inlineNativeCall(CallInfo &c
     // Utility intrinsics.
     if (native == intrinsic_IsCallable)
         return inlineIsCallable(callInfo);
     if (native == intrinsic_HaveSameClass)
         return inlineHaveSameClass(callInfo);
     if (native == intrinsic_ToObject)
         return inlineToObject(callInfo);
 
+    // TypedObject intrinsics.
+    if (native == intrinsic_ObjectIsTransparentTypedObject)
+        return inlineHasClass(callInfo, &TransparentTypedObject::class_);
+    if (native == intrinsic_ObjectIsOpaqueTypedObject)
+        return inlineHasClass(callInfo, &OpaqueTypedObject::class_);
+
     // Testing Functions
     if (native == testingFunc_inParallelSection)
         return inlineForceSequentialOrInParallelSection(callInfo);
     if (native == testingFunc_bailout)
         return inlineBailout(callInfo);
     if (native == testingFunc_assertFloat32)
         return inlineAssertFloat32(callInfo);
 
@@ -1437,16 +1443,41 @@ IonBuilder::inlineNewDenseArrayForParall
                                                           templateObject);
     current->add(newObject);
     current->push(newObject);
 
     return InliningStatus_Inlined;
 }
 
 IonBuilder::InliningStatus
+IonBuilder::inlineHasClass(CallInfo &callInfo, const Class *clasp)
+{
+    if (callInfo.constructing() || callInfo.argc() != 1)
+        return InliningStatus_NotInlined;
+
+    if (callInfo.getArg(0)->type() != MIRType_Object)
+        return InliningStatus_NotInlined;
+    if (getInlineReturnType() != MIRType_Boolean)
+        return InliningStatus_NotInlined;
+
+    types::TemporaryTypeSet *types = callInfo.getArg(0)->resultTypeSet();
+    const Class *knownClass = types ? types->getKnownClass() : nullptr;
+    if (knownClass) {
+        pushConstant(BooleanValue(knownClass == clasp));
+    } else {
+        MHasClass *hasClass = MHasClass::New(alloc(), callInfo.getArg(0), clasp);
+        current->add(hasClass);
+        current->push(hasClass);
+    }
+
+    callInfo.setImplicitlyUsedUnchecked();
+    return InliningStatus_Inlined;
+}
+
+IonBuilder::InliningStatus
 IonBuilder::inlineUnsafeSetReservedSlot(CallInfo &callInfo)
 {
     if (callInfo.argc() != 3 || callInfo.constructing())
         return InliningStatus_NotInlined;
     if (getInlineReturnType() != MIRType_Undefined)
         return InliningStatus_NotInlined;
     if (callInfo.getArg(0)->type() != MIRType_Object)
         return InliningStatus_NotInlined;
--- a/js/src/jit/MIR.h
+++ b/js/src/jit/MIR.h
@@ -9352,16 +9352,49 @@ class MHaveSameClass
     TypePolicy *typePolicy() {
         return this;
     }
     AliasSet getAliasSet() const {
         return AliasSet::None();
     }
 };
 
+class MHasClass
+    : public MUnaryInstruction,
+      public SingleObjectPolicy
+{
+    const Class *class_;
+
+    MHasClass(MDefinition *object, const Class *clasp)
+      : MUnaryInstruction(object)
+      , class_(clasp)
+    {
+        JS_ASSERT(object->type() == MIRType_Object);
+        setResultType(MIRType_Boolean);
+        setMovable();
+    }
+
+  public:
+    INSTRUCTION_HEADER(HasClass);
+
+    static MHasClass *New(TempAllocator &alloc, MDefinition *obj, const Class *clasp) {
+        return new(alloc) MHasClass(obj, clasp);
+    }
+
+    MDefinition *object() const {
+        return getOperand(0);
+    }
+    const Class *getClass() const {
+        return class_;
+    }
+    AliasSet getAliasSet() const {
+        return AliasSet::None();
+    }
+};
+
 // Increase the usecount of the provided script upon execution and test if
 // the usecount surpasses the threshold. Upon hit it will recompile the
 // outermost script (i.e. not the inlined script).
 class MRecompileCheck : public MNullaryInstruction
 {
     JSScript *script_;
     uint32_t recompileThreshold_;
 
--- a/js/src/jit/MOpcodes.h
+++ b/js/src/jit/MOpcodes.h
@@ -184,16 +184,17 @@ namespace jit {
     _(CallInstanceOf)                                                       \
     _(InterruptCheck)                                                       \
     _(FunctionBoundary)                                                     \
     _(GetDOMProperty)                                                       \
     _(GetDOMMember)                                                         \
     _(SetDOMProperty)                                                       \
     _(IsCallable)                                                           \
     _(HaveSameClass)                                                        \
+    _(HasClass)                                                              \
     _(AsmJSNeg)                                                             \
     _(AsmJSUnsignedToDouble)                                                \
     _(AsmJSUnsignedToFloat32)                                               \
     _(AsmJSLoadHeap)                                                        \
     _(AsmJSStoreHeap)                                                       \
     _(AsmJSLoadGlobalVar)                                                   \
     _(AsmJSStoreGlobalVar)                                                  \
     _(AsmJSLoadFuncPtr)                                                     \
--- a/js/src/jit/ParallelSafetyAnalysis.cpp
+++ b/js/src/jit/ParallelSafetyAnalysis.cpp
@@ -293,16 +293,17 @@ class ParallelSafetyVisitor : public MIn
     UNSAFE_OP(InArray)
     SAFE_OP(GuardThreadExclusive)
     SAFE_OP(InterruptCheckPar)
     SAFE_OP(CheckOverRecursedPar)
     SAFE_OP(FunctionDispatch)
     SAFE_OP(TypeObjectDispatch)
     SAFE_OP(IsCallable)
     SAFE_OP(HaveSameClass)
+    SAFE_OP(HasClass)
     UNSAFE_OP(EffectiveAddress)
     UNSAFE_OP(AsmJSUnsignedToDouble)
     UNSAFE_OP(AsmJSUnsignedToFloat32)
     UNSAFE_OP(AsmJSNeg)
     UNSAFE_OP(AsmJSLoadHeap)
     UNSAFE_OP(AsmJSStoreHeap)
     UNSAFE_OP(AsmJSLoadGlobalVar)
     UNSAFE_OP(AsmJSStoreGlobalVar)
--- a/js/src/js.msg
+++ b/js/src/js.msg
@@ -430,8 +430,9 @@ MSG_DEF(JSMSG_MODULES_NOT_IMPLEMENTED,  
 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, 1, JSEXN_TYPEERR, "[[SetPrototypeOf]] failed on {0}")
 MSG_DEF(JSMSG_INVALID_ARG_TYPE,         383, 3, JSEXN_TYPEERR, "Invalid type: {0} can't be a{1} {2}")
+MSG_DEF(JSMSG_TERMINATED,               384, 1, JSEXN_ERR, "Script terminated by timeout at:\n{0}")
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -4572,52 +4572,48 @@ JS_CompileUCScript(JSContext *cx, JS::Ha
                    size_t length, const JS::CompileOptions &options)
 {
     return Compile(cx, obj, options, chars, length);
 }
 
 JS_PUBLIC_API(bool)
 JS_BufferIsCompilableUnit(JSContext *cx, HandleObject obj, const char *utf8, size_t length)
 {
-    bool result;
-    JSExceptionState *exnState;
-    JSErrorReporter older;
-
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj);
+
+    cx->clearPendingException();
+
     jschar *chars = JS::UTF8CharsToNewTwoByteCharsZ(cx, JS::UTF8Chars(utf8, length), &length).get();
     if (!chars)
         return true;
 
-    /*
-     * Return true on any out-of-memory error, so our caller doesn't try to
-     * collect more buffered source.
-     */
-    result = true;
-    exnState = JS_SaveExceptionState(cx);
-    {
-        CompileOptions options(cx);
-        options.setCompileAndGo(false);
-        Parser<frontend::FullParseHandler> parser(cx, &cx->tempLifoAlloc(),
-                                                  options, chars, length,
-                                                  /* foldConstants = */ true, nullptr, nullptr);
-        older = JS_SetErrorReporter(cx, nullptr);
-        if (!parser.parse(obj) && parser.isUnexpectedEOF()) {
-            /*
-             * We ran into an error. If it was because we ran out of
-             * source, we return false so our caller knows to try to
-             * collect more buffered source.
-             */
+    // Return true on any out-of-memory error or non-EOF-related syntax error, so our
+    // caller doesn't try to collect more buffered source.
+    bool result = true;
+
+    CompileOptions options(cx);
+    options.setCompileAndGo(false);
+    Parser<frontend::FullParseHandler> parser(cx, &cx->tempLifoAlloc(),
+                                              options, chars, length,
+                                              /* foldConstants = */ true, nullptr, nullptr);
+    JSErrorReporter older = JS_SetErrorReporter(cx, nullptr);
+    if (!parser.parse(obj)) {
+        // We ran into an error. If it was because we ran out of source, we
+        // return false so our caller knows to try to collect more buffered
+        // source.
+        if (parser.isUnexpectedEOF())
             result = false;
-        }
-        JS_SetErrorReporter(cx, older);
+
+        cx->clearPendingException();
     }
+    JS_SetErrorReporter(cx, older);
+
     js_free(chars);
-    JS_RestoreExceptionState(cx, exnState);
     return result;
 }
 
 JS_PUBLIC_API(JSObject *)
 JS_GetGlobalFromScript(JSScript *script)
 {
     JS_ASSERT(!script->isCachedEval());
     return &script->global();
@@ -5871,16 +5867,43 @@ JS_ReportPendingException(JSContext *cx)
     CHECK_REQUEST(cx);
 
     // This can only fail due to oom.
     bool ok = js_ReportUncaughtException(cx);
     JS_ASSERT(!cx->isExceptionPending());
     return ok;
 }
 
+JS::AutoSaveExceptionState::AutoSaveExceptionState(JSContext *cx)
+    : context(cx), wasThrowing(cx->throwing), exceptionValue(cx)
+{
+    AssertHeapIsIdle(cx);
+    CHECK_REQUEST(cx);
+    if (wasThrowing) {
+        exceptionValue = cx->unwrappedException_;
+        cx->clearPendingException();
+    }
+}
+
+void
+JS::AutoSaveExceptionState::restore()
+{
+    context->throwing = wasThrowing;
+    context->unwrappedException_ = exceptionValue;
+    drop();
+}
+
+JS::AutoSaveExceptionState::~AutoSaveExceptionState()
+{
+    if (wasThrowing && !context->isExceptionPending()) {
+        context->throwing = true;
+        context->unwrappedException_ = exceptionValue;
+    }
+}
+
 struct JSExceptionState {
     bool throwing;
     jsval exception;
 };
 
 JS_PUBLIC_API(JSExceptionState *)
 JS_SaveExceptionState(JSContext *cx)
 {
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -4575,27 +4575,70 @@ extern JS_PUBLIC_API(void)
 JS_SetPendingException(JSContext *cx, JS::HandleValue v);
 
 extern JS_PUBLIC_API(void)
 JS_ClearPendingException(JSContext *cx);
 
 extern JS_PUBLIC_API(bool)
 JS_ReportPendingException(JSContext *cx);
 
+namespace JS {
+
 /*
- * Save the current exception state.  This takes a snapshot of cx's current
- * exception state without making any change to that state.
+ * Save and later restore the current exception state of a given JSContext.
+ * This is useful for implementing behavior in C++ that's like try/catch
+ * or try/finally in JS.
+ *
+ * Typical usage:
  *
- * The returned state pointer MUST be passed later to JS_RestoreExceptionState
- * (to restore that saved state, overriding any more recent state) or else to
- * JS_DropExceptionState (to free the state struct in case it is not correct
- * or desirable to restore it).  Both Restore and Drop free the state struct,
- * so callers must stop using the pointer returned from Save after calling the
- * Release or Drop API.
+ *     bool ok = JS_EvaluateScript(cx, ...);
+ *     AutoSaveExceptionState savedExc(cx);
+ *     ... cleanup that might re-enter JS ...
+ *     return ok;
  */
+class JS_PUBLIC_API(AutoSaveExceptionState)
+{
+  private:
+    JSContext *context;
+    bool wasThrowing;
+    RootedValue exceptionValue;
+
+  public:
+    /*
+     * Take a snapshot of cx's current exception state. Then clear any current
+     * pending exception in cx.
+     */
+    explicit AutoSaveExceptionState(JSContext *cx);
+
+    /*
+     * If neither drop() nor restore() was called, restore the exception
+     * state only if no exception is currently pending on cx.
+     */
+    ~AutoSaveExceptionState();
+
+    /*
+     * Discard any stored exception state.
+     * If this is called, the destructor is a no-op.
+     */
+    void drop() {
+        wasThrowing = false;
+        exceptionValue.setUndefined();
+    }
+
+    /*
+     * Replace cx's exception state with the stored exception state. Then
+     * discard the stored exception state. If this is called, the
+     * destructor is a no-op.
+     */
+    void restore();
+};
+
+} /* namespace JS */
+
+/* Deprecated API. Use AutoSaveExceptionState instead. */
 extern JS_PUBLIC_API(JSExceptionState *)
 JS_SaveExceptionState(JSContext *cx);
 
 extern JS_PUBLIC_API(void)
 JS_RestoreExceptionState(JSContext *cx, JSExceptionState *state);
 
 extern JS_PUBLIC_API(void)
 JS_DropExceptionState(JSContext *cx, JSExceptionState *state);
--- a/js/src/jscntxt.cpp
+++ b/js/src/jscntxt.cpp
@@ -1003,50 +1003,54 @@ js_GetErrorMessage(void *userRef, const 
 bool
 js_InvokeOperationCallback(JSContext *cx)
 {
     JS_ASSERT_REQUEST_DEPTH(cx);
 
     JSRuntime *rt = cx->runtime();
     JS_ASSERT(rt->interrupt);
 
-    /*
-     * Reset the callback counter first, then run GC and yield. If another
-     * thread is racing us here we will accumulate another callback request
-     * which will be serviced at the next opportunity.
-     */
+    // Reset the callback counter first, then run GC and yield. If another
+    // thread is racing us here we will accumulate another callback request
+    // which will be serviced at the next opportunity.
     rt->interrupt = false;
 
-    /*
-     * IonMonkey sets its stack limit to UINTPTR_MAX to trigger operation
-     * callbacks.
-     */
+    // IonMonkey sets its stack limit to UINTPTR_MAX to trigger operation
+    // callbacks.
     rt->resetIonStackLimit();
 
     js::gc::GCIfNeeded(cx);
 
 #ifdef JS_ION
 #ifdef JS_THREADSAFE
     rt->interruptPar = false;
 #endif
 
-    /*
-     * A worker thread may have set the callback after finishing an Ion
-     * compilation.
-     */
+    // A worker thread may have set the callback after finishing an Ion
+    // compilation.
     jit::AttachFinishedCompilations(cx);
 #endif
 
-    /*
-     * Important: Additional callbacks can occur inside the callback handler
-     * if it re-enters the JS engine. The embedding must ensure that the
-     * callback is disconnected before attempting such re-entry.
-     */
+    // Important: Additional callbacks can occur inside the callback handler
+    // if it re-enters the JS engine. The embedding must ensure that the
+    // callback is disconnected before attempting such re-entry.
     JSOperationCallback cb = cx->runtime()->operationCallback;
-    return !cb || cb(cx);
+    if (!cb || cb(cx))
+        return true;
+
+    // No need to set aside any pending exception here: ComputeStackString
+    // already does that.
+    Rooted<JSString*> stack(cx, ComputeStackString(cx));
+    const jschar *chars = stack ? stack->getCharsZ(cx) : nullptr;
+    if (!chars)
+        chars = MOZ_UTF16("(stack not available)");
+    JS_ReportErrorFlagsAndNumberUC(cx, JSREPORT_WARNING, js_GetErrorMessage, nullptr,
+                                   JSMSG_TERMINATED, chars);
+
+    return false;
 }
 
 bool
 js_HandleExecutionInterrupt(JSContext *cx)
 {
     if (cx->runtime()->interrupt)
         return js_InvokeOperationCallback(cx);
     return true;
--- a/js/src/jscntxt.h
+++ b/js/src/jscntxt.h
@@ -407,16 +407,17 @@ struct JSContext : public js::ExclusiveC
 {
     explicit JSContext(JSRuntime *rt);
     ~JSContext();
 
     JSRuntime *runtime() const { return runtime_; }
     js::PerThreadData &mainThread() const { return runtime()->mainThread; }
 
     friend class js::ExclusiveContext;
+    friend class JS::AutoSaveExceptionState;
 
   private:
     /* Exception state -- the exception member is a GC root by definition. */
     bool                throwing;            /* is there a pending exception? */
     js::Value           unwrappedException_; /* most-recently-thrown exception */
 
     /* Per-context options. */
     JS::ContextOptions  options_;
@@ -1028,16 +1029,19 @@ bool intrinsic_UnsafeGetReservedSlot(JSC
 bool intrinsic_HaveSameClass(JSContext *cx, unsigned argc, Value *vp);
 bool intrinsic_IsPackedArray(JSContext *cx, unsigned argc, Value *vp);
 
 bool intrinsic_ShouldForceSequential(JSContext *cx, unsigned argc, Value *vp);
 bool intrinsic_NewParallelArray(JSContext *cx, unsigned argc, Value *vp);
 bool intrinsic_ForkJoinGetSlice(JSContext *cx, unsigned argc, Value *vp);
 bool intrinsic_InParallelSection(JSContext *cx, unsigned argc, Value *vp);
 
+bool intrinsic_ObjectIsTransparentTypedObject(JSContext *cx, unsigned argc, Value *vp);
+bool intrinsic_ObjectIsOpaqueTypedObject(JSContext *cx, unsigned argc, Value *vp);
+
 class AutoLockForExclusiveAccess
 {
 #ifdef JS_THREADSAFE
     JSRuntime *runtime;
 
     void init(JSRuntime *rt) {
         runtime = rt;
         if (runtime->numExclusiveThreads) {
--- a/js/src/jsexn.cpp
+++ b/js/src/jsexn.cpp
@@ -183,33 +183,32 @@ js::CopyErrorReport(JSContext *cx, JSErr
 #undef JS_CHARS_SIZE
     return copy;
 }
 
 struct SuppressErrorsGuard
 {
     JSContext *cx;
     JSErrorReporter prevReporter;
-    JSExceptionState *prevState;
+    JS::AutoSaveExceptionState prevState;
 
     SuppressErrorsGuard(JSContext *cx)
       : cx(cx),
         prevReporter(JS_SetErrorReporter(cx, nullptr)),
-        prevState(JS_SaveExceptionState(cx))
+        prevState(cx)
     {}
 
     ~SuppressErrorsGuard()
     {
-        JS_RestoreExceptionState(cx, prevState);
         JS_SetErrorReporter(cx, prevReporter);
     }
 };
 
-static JSString *
-ComputeStackString(JSContext *cx)
+JSString *
+js::ComputeStackString(JSContext *cx)
 {
     StringBuffer sb(cx);
 
     {
         RootedAtom atom(cx);
         SuppressErrorsGuard seg(cx);
         // We should get rid of the CURRENT_CONTEXT and STOP_AT_SAVED here.
         // See bug 960820.
--- a/js/src/jsexn.h
+++ b/js/src/jsexn.h
@@ -12,18 +12,21 @@
 #define jsexn_h
 
 #include "jsapi.h"
 #include "NamespaceImports.h"
 
 namespace js {
 class ErrorObject;
 
-extern JSErrorReport *
+JSErrorReport *
 CopyErrorReport(JSContext *cx, JSErrorReport *report);
+
+JSString *
+ComputeStackString(JSContext *cx);
 }
 
 /*
  * Given a JSErrorReport, check to see if there is an exception associated with
  * the error number.  If there is, then create an appropriate exception object,
  * set it as the pending exception, and set the JSREPORT_EXCEPTION flag on the
  * error report.  Exception-aware host error reporters should probably ignore
  * error reports so flagged.
--- a/js/src/jsobj.cpp
+++ b/js/src/jsobj.cpp
@@ -4270,16 +4270,28 @@ js::HasOwnProperty<CanGC>(JSContext *cx,
                           HandleObject obj, HandleId id,
                           MutableHandleObject objp, MutableHandleShape propp);
 
 template bool
 js::HasOwnProperty<NoGC>(JSContext *cx, LookupGenericOp lookup,
                          JSObject *obj, jsid id,
                          FakeMutableHandle<JSObject*> objp, FakeMutableHandle<Shape*> propp);
 
+bool
+js::HasOwnProperty(JSContext *cx, HandleObject obj, HandleId id, bool *resultp)
+{
+    RootedObject pobj(cx);
+    RootedShape shape(cx);
+    if (!HasOwnProperty<CanGC>(cx, obj->getOps()->lookupGeneric, obj, id, &pobj, &shape))
+        return false;
+    *resultp = (shape != nullptr);
+    return true;
+}
+
+
 template <AllowGC allowGC>
 static MOZ_ALWAYS_INLINE bool
 NativeGetInline(JSContext *cx,
                 typename MaybeRooted<JSObject*, allowGC>::HandleType obj,
                 typename MaybeRooted<JSObject*, allowGC>::HandleType receiver,
                 typename MaybeRooted<JSObject*, allowGC>::HandleType pobj,
                 typename MaybeRooted<Shape*, allowGC>::HandleType shape,
                 typename MaybeRooted<Value, allowGC>::MutableHandleType vp)
--- a/js/src/jsobj.h
+++ b/js/src/jsobj.h
@@ -1281,16 +1281,20 @@ DenseRangeRef::mark(JSTracer *trc)
     js::gc::IsObjectMarked(&owner);
     uint32_t initLen = owner->getDenseInitializedLength();
     uint32_t clampedStart = Min(start, initLen);
     gc::MarkArraySlots(trc, Min(end, initLen) - clampedStart,
                        owner->getDenseElements() + clampedStart, "element");
 }
 #endif
 
+/* Set *resultp to tell whether obj has an own property with the given id. */
+bool
+HasOwnProperty(JSContext *cx, HandleObject obj, HandleId id, bool *resultp);
+
 template <AllowGC allowGC>
 extern bool
 HasOwnProperty(JSContext *cx, LookupGenericOp lookup,
                typename MaybeRooted<JSObject*, allowGC>::HandleType obj,
                typename MaybeRooted<jsid, allowGC>::HandleType id,
                typename MaybeRooted<JSObject*, allowGC>::MutableHandleType objp,
                typename MaybeRooted<Shape*, allowGC>::MutableHandleType propp);
 
--- a/js/src/jsscript.cpp
+++ b/js/src/jsscript.cpp
@@ -918,18 +918,21 @@ js::XDRScript(XDRState<mode> *xdr, Handl
                     funEnclosingScope = function->lazyScript()->enclosingScope();
                 else
                     funEnclosingScope = function->nonLazyScript()->enclosingStaticScope();
 
                 StaticScopeIter<NoGC> ssi(funEnclosingScope);
                 if (ssi.done() || ssi.type() == StaticScopeIter<NoGC>::FUNCTION) {
                     JS_ASSERT(ssi.done() == !fun);
                     funEnclosingScopeIndex = UINT32_MAX;
+                } else if (ssi.type() == StaticScopeIter<NoGC>::BLOCK) {
+                    funEnclosingScopeIndex = FindScopeObjectIndex(script, ssi.block());
+                    JS_ASSERT(funEnclosingScopeIndex < i);
                 } else {
-                    funEnclosingScopeIndex = FindScopeObjectIndex(script, ssi.block());
+                    funEnclosingScopeIndex = FindScopeObjectIndex(script, ssi.staticWith());
                     JS_ASSERT(funEnclosingScopeIndex < i);
                 }
             }
 
             if (!xdr->codeUint32(&funEnclosingScopeIndex))
                 return false;
 
             if (mode == XDR_DECODE) {
@@ -2794,20 +2797,22 @@ js::CloneScript(JSContext *cx, HandleObj
                     if (innerFun->isInterpretedLazy()) {
                         AutoCompartment ac(cx, innerFun);
                         if (!innerFun->getOrCreateScript(cx))
                             return nullptr;
                     }
                     RootedObject staticScope(cx, innerFun->nonLazyScript()->enclosingStaticScope());
                     StaticScopeIter<CanGC> ssi(cx, staticScope);
                     RootedObject enclosingScope(cx);
-                    if (!ssi.done() && ssi.type() == StaticScopeIter<CanGC>::BLOCK)
+                    if (ssi.done() || ssi.type() == StaticScopeIter<CanGC>::FUNCTION)
+                        enclosingScope = fun;
+                    else if (ssi.type() == StaticScopeIter<CanGC>::BLOCK)
                         enclosingScope = objects[FindScopeObjectIndex(src, ssi.block())];
                     else
-                        enclosingScope = fun;
+                        enclosingScope = objects[FindScopeObjectIndex(src, ssi.staticWith())];
 
                     clone = CloneFunctionAndScript(cx, enclosingScope, innerFun);
                 }
             } else {
                 /*
                  * Clone object literals emitted for the JSOP_NEWOBJECT opcode. We only emit that
                  * instead of the less-optimized JSOP_NEWINIT for self-hosted code or code compiled
                  * with JSOPTION_COMPILE_N_GO set. As we don't clone the latter type of code, this
--- a/js/src/shell/js.cpp
+++ b/js/src/shell/js.cpp
@@ -315,20 +315,19 @@ GetContextData(JSContext *cx)
 }
 
 static bool
 ShellOperationCallback(JSContext *cx)
 {
     if (!gTimedOut)
         return true;
 
-    JS_ClearPendingException(cx);
-
     bool result;
     if (!gTimeoutFunc.isNull()) {
+        JS::AutoSaveExceptionState savedExc(cx);
         JSAutoCompartment ac(cx, &gTimeoutFunc.toObject());
         RootedValue rval(cx);
         HandleValue timeoutFunc = HandleValue::fromMarkedLocation(&gTimeoutFunc);
         if (!JS_CallFunctionValue(cx, JS::NullPtr(), timeoutFunc, JS::EmptyValueArray, &rval))
             return false;
         if (rval.isBoolean())
             result = rval.toBoolean();
         else
--- a/js/src/vm/Debugger.cpp
+++ b/js/src/vm/Debugger.cpp
@@ -3365,17 +3365,17 @@ DebuggerScript_getAllOffsets(JSContext *
         if (!flowData[offset].hasNoEdges() && flowData[offset].lineno() != lineno) {
             /* Get the offsets array for this line. */
             RootedObject offsets(cx);
             RootedValue offsetsv(cx);
 
             RootedId id(cx, INT_TO_JSID(lineno));
 
             bool found;
-            if (!JSObject::hasProperty(cx, result, id, &found))
+            if (!js::HasOwnProperty(cx, result, id, &found))
                 return false;
             if (found && !JSObject::getGeneric(cx, result, result, id, &offsetsv))
                 return false;
 
             if (offsetsv.isObject()) {
                 offsets = &offsetsv.toObject();
             } else {
                 JS_ASSERT(offsetsv.isUndefined());
--- a/js/src/vm/SelfHosting.cpp
+++ b/js/src/vm/SelfHosting.cpp
@@ -614,16 +614,32 @@ intrinsic_InParallelSectionPar(ForkJoinC
     CallArgs args = CallArgsFromVp(argc, vp);
     args.rval().setBoolean(true);
     return true;
 }
 
 JS_JITINFO_NATIVE_PARALLEL(intrinsic_InParallelSection_jitInfo,
                            intrinsic_InParallelSectionPar);
 
+/* These wrappers are needed in order to recognize the function
+ * pointers within the JIT, and the raw js:: functions can't be used
+ * directly because they take a ThreadSafeContext* argument.
+ */
+bool
+js::intrinsic_ObjectIsTransparentTypedObject(JSContext *cx, unsigned argc, Value *vp)
+{
+    return js::ObjectIsTransparentTypedObject(cx, argc, vp);
+}
+
+bool
+js::intrinsic_ObjectIsOpaqueTypedObject(JSContext *cx, unsigned argc, Value *vp)
+{
+    return js::ObjectIsOpaqueTypedObject(cx, argc, vp);
+}
+
 /**
  * Returns the default locale as a well-formed, but not necessarily canonicalized,
  * BCP-47 language tag.
  */
 static bool
 intrinsic_RuntimeDefaultLocale(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
@@ -694,23 +710,23 @@ static const JSFunctionSpec intrinsic_fu
               &js::AttachTypedObjectJitInfo, 5, 0),
     JS_FNINFO("SetTypedObjectOffset",
               JSNativeThreadSafeWrapper<js::SetTypedObjectOffset>,
               &js::SetTypedObjectOffsetJitInfo, 2, 0),
     JS_FNINFO("ObjectIsTypeDescr",
               JSNativeThreadSafeWrapper<js::ObjectIsTypeDescr>,
               &js::ObjectIsTypeDescrJitInfo, 5, 0),
     JS_FNINFO("ObjectIsTransparentTypedObject",
-              JSNativeThreadSafeWrapper<js::ObjectIsTransparentTypedObject>,
+              intrinsic_ObjectIsTransparentTypedObject,
               &js::ObjectIsTransparentTypedObjectJitInfo, 5, 0),
     JS_FNINFO("TypedObjectIsAttached",
               JSNativeThreadSafeWrapper<js::TypedObjectIsAttached>,
               &js::TypedObjectIsAttachedJitInfo, 1, 0),
     JS_FNINFO("ObjectIsOpaqueTypedObject",
-              JSNativeThreadSafeWrapper<js::ObjectIsOpaqueTypedObject>,
+              intrinsic_ObjectIsOpaqueTypedObject,
               &js::ObjectIsOpaqueTypedObjectJitInfo, 5, 0),
     JS_FNINFO("ClampToUint8",
               JSNativeThreadSafeWrapper<js::ClampToUint8>,
               &js::ClampToUint8JitInfo, 1, 0),
     JS_FNINFO("Memcpy",
               JSNativeThreadSafeWrapper<js::Memcpy>,
               &js::MemcpyJitInfo, 5, 0),
     JS_FN("GetTypedObjectModule", js::GetTypedObjectModule, 0, 0),
--- a/js/src/vm/StructuredClone.cpp
+++ b/js/src/vm/StructuredClone.cpp
@@ -1028,24 +1028,21 @@ JSStructuredCloneWriter::write(const Val
             ids.popBack();
             checkStack();
             if (JSID_IS_STRING(id) || JSID_IS_INT(id)) {
                 /*
                  * If obj still has an own property named id, write it out.
                  * The cost of re-checking could be avoided by using
                  * NativeIterators.
                  */
-                RootedObject obj2(context());
-                RootedShape prop(context());
-                if (!HasOwnProperty<CanGC>(context(), obj->getOps()->lookupGeneric, obj, id,
-                                           &obj2, &prop)) {
+                bool found;
+                if (!HasOwnProperty(context(), obj, id, &found))
                     return false;
-                }
 
-                if (prop) {
+                if (found) {
                     RootedValue val(context());
                     if (!writeId(id) ||
                         !JSObject::getGeneric(context(), obj, obj, id, &val) ||
                         !startWrite(val))
                         return false;
                 }
             }
         } else {
--- a/js/xpconnect/src/XPCDebug.cpp
+++ b/js/xpconnect/src/XPCDebug.cpp
@@ -41,28 +41,23 @@ xpc_DumpJSStack(JSContext* cx, bool show
     }
     return true;
 }
 
 char*
 xpc_PrintJSStack(JSContext* cx, bool showArgs, bool showLocals,
                  bool showThisProps)
 {
-    char* buf;
-    JSExceptionState *state = JS_SaveExceptionState(cx);
-    if (!state)
-        DebugDump("%s", "Call to a debug function modifying state!\n");
+    JS::AutoSaveExceptionState state(cx);
 
-    JS_ClearPendingException(cx);
-
-    buf = JS::FormatStackDump(cx, nullptr, showArgs, showLocals, showThisProps);
+    char *buf = JS::FormatStackDump(cx, nullptr, showArgs, showLocals, showThisProps);
     if (!buf)
         DebugDump("%s", "Failed to format JavaScript stack for dump\n");
 
-    JS_RestoreExceptionState(cx, state);
+    state.restore();
     return buf;
 }
 
 /***************************************************************************/
 
 static void
 xpcDumpEvalErrorReporter(JSContext *cx, const char *message,
                          JSErrorReport *report)
@@ -94,30 +89,32 @@ xpc_DumpEvalInJSStackFrame(JSContext* cx
         num++;
     }
 
     if (!frame) {
         DebugDump("%s", "invalid frame number!\n");
         return false;
     }
 
-    JSExceptionState* exceptionState = JS_SaveExceptionState(cx);
+    JS::AutoSaveExceptionState exceptionState(cx);
     JSErrorReporter older = JS_SetErrorReporter(cx, xpcDumpEvalErrorReporter);
 
     JS::RootedValue rval(cx);
     JSString* str;
     JSAutoByteString bytes;
     if (frame.evaluateInStackFrame(cx, text, strlen(text), "eval", 1, &rval) &&
         nullptr != (str = ToString(cx, rval)) &&
         bytes.encodeLatin1(cx, str)) {
         DebugDump("%s\n", bytes.ptr());
-    } else
+    } else {
         DebugDump("%s", "eval failed!\n");
+    }
+
     JS_SetErrorReporter(cx, older);
-    JS_RestoreExceptionState(cx, exceptionState);
+    exceptionState.restore();
     return true;
 }
 
 /***************************************************************************/
 
 JSTrapStatus
 xpc_DebuggerKeywordHandler(JSContext *cx, JSScript *script, jsbytecode *pc,
                            jsval *rval, void *closure)
--- a/js/xpconnect/src/XPCJSRuntime.cpp
+++ b/js/xpconnect/src/XPCJSRuntime.cpp
@@ -3065,21 +3065,21 @@ XPCJSRuntime::XPCJSRuntime(nsXPConnect* 
     // MacOS has a gargantuan default stack size of 8MB. Go wild with 7MB,
     // and give trusted script 140k extra. The stack is huge on mac anyway.
     const size_t kStackQuota = 7 * 1024 * 1024;
     const size_t kTrustedScriptBuffer = 140 * 1024;
 #elif defined(MOZ_ASAN)
     // ASan requires more stack space due to red-zones, so give it double the
     // default (2MB on 32-bit, 4MB on 64-bit). ASAN stack frame measurements
     // were not taken at the time of this writing, so we hazard a guess that
-    // ASAN builds have roughly twice the stack overhead as normal builds.
+    // ASAN builds have roughly thrice the stack overhead as normal builds.
     // On normal builds, the largest stack frame size we might encounter is
-    // 8.2k, so let's use a buffer of 8.2 * 2 * 10 = 164k.
+    // 8.2k, so let's use a buffer of 8.2 * 3 * 10 = 246k.
     const size_t kStackQuota =  2 * kDefaultStackQuota;
-    const size_t kTrustedScriptBuffer = 164 * 1024;
+    const size_t kTrustedScriptBuffer = 246 * 1024;
 #elif defined(XP_WIN)
     // 1MB is the default stack size on Windows, so the default 1MB stack quota
     // we'd get on win32 is slightly too large. Use 900k instead. And since
     // windows stack frames are 3.4k each, let's use a buffer of 40k.
     const size_t kStackQuota = 900 * 1024;
     const size_t kTrustedScriptBuffer = 40 * 1024;
     // The following two configurations are linux-only. Given the numbers above,
     // we use 50k and 100k trusted buffers on 32-bit and 64-bit respectively.
--- a/js/xpconnect/src/XPCWrappedJSClass.cpp
+++ b/js/xpconnect/src/XPCWrappedJSClass.cpp
@@ -48,36 +48,26 @@ bool AutoScriptEvaluate::StartEvaluating
     mAutoCompartment.construct(mJSContext, scope);
 
     // Saving the exception state keeps us from interfering with another script
     // that may also be running on this context.  This occurred first with the
     // js debugger, as described in
     // http://bugzilla.mozilla.org/show_bug.cgi?id=88130 but presumably could
     // show up in any situation where a script calls into a wrapped js component
     // on the same context, while the context has a nonzero exception state.
-    // Because JS_SaveExceptionState/JS_RestoreExceptionState use malloc
-    // and addroot, we avoid them if possible by returning null (as opposed to
-    // a JSExceptionState with no information) when there is no pending
-    // exception.
-    if (JS_IsExceptionPending(mJSContext)) {
-        mState = JS_SaveExceptionState(mJSContext);
-        JS_ClearPendingException(mJSContext);
-    }
+    mState.construct(mJSContext);
 
     return true;
 }
 
 AutoScriptEvaluate::~AutoScriptEvaluate()
 {
     if (!mJSContext || !mEvaluated)
         return;
-    if (mState)
-        JS_RestoreExceptionState(mJSContext, mState);
-    else
-        JS_ClearPendingException(mJSContext);
+    mState.ref().restore();
 
     JS_EndRequest(mJSContext);
 
     if (mErrorReporterSet)
         JS_SetErrorReporter(mJSContext, nullptr);
 }
 
 // It turns out that some errors may be not worth reporting. So, this
--- a/js/xpconnect/src/xpcprivate.h
+++ b/js/xpconnect/src/xpcprivate.h
@@ -2933,18 +2933,17 @@ private:
 class MOZ_STACK_CLASS AutoScriptEvaluate
 {
 public:
     /**
      * Saves the JSContext as well as initializing our state
      * @param cx The JSContext, this can be null, we don't do anything then
      */
     AutoScriptEvaluate(JSContext * cx MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
-         : mJSContext(cx), mState(0), mErrorReporterSet(false),
-           mEvaluated(false) {
+         : mJSContext(cx), mErrorReporterSet(false), mEvaluated(false) {
         MOZ_GUARD_OBJECT_NOTIFIER_INIT;
     }
 
     /**
      * Does the pre script evaluation and sets the error reporter if given
      * This function should only be called once, and will assert if called
      * more than once
      * @param errorReporter the error reporter callback function to set
@@ -2953,17 +2952,17 @@ public:
     bool StartEvaluating(JS::HandleObject scope, JSErrorReporter errorReporter = nullptr);
 
     /**
      * Does the post script evaluation and resets the error reporter
      */
     ~AutoScriptEvaluate();
 private:
     JSContext* mJSContext;
-    JSExceptionState* mState;
+    mozilla::Maybe<JS::AutoSaveExceptionState> mState;
     bool mErrorReporterSet;
     bool mEvaluated;
     mozilla::Maybe<JSAutoCompartment> mAutoCompartment;
     MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
 
     // No copying or assignment allowed
     AutoScriptEvaluate(const AutoScriptEvaluate &) MOZ_DELETE;
     AutoScriptEvaluate & operator =(const AutoScriptEvaluate &) MOZ_DELETE;
--- a/layout/base/PositionedEventTargeting.cpp
+++ b/layout/base/PositionedEventTargeting.cpp
@@ -196,18 +196,20 @@ IsElementClickable(nsIFrame* aFrame, nsI
           tag == nsGkAtoms::menubutton ||
           tag == nsGkAtoms::menuitem ||
           tag == nsGkAtoms::menulist ||
           tag == nsGkAtoms::scrollbarbutton ||
           tag == nsGkAtoms::resizer) {
         return true;
       }
     }
-    if (content->AttrValueIs(kNameSpaceID_None, nsGkAtoms::role,
-                             nsGkAtoms::button, eIgnoreCase)) {
+    static nsIContent::AttrValuesArray clickableRoles[] =
+      { &nsGkAtoms::button, &nsGkAtoms::key, nullptr };
+    if (content->FindAttrValueIn(kNameSpaceID_None, nsGkAtoms::role,
+                                 clickableRoles, eIgnoreCase) >= 0) {
       return true;
     }
     if (content->IsEditable()) {
       return true;
     }
     nsCOMPtr<nsIURI> linkURI;
     if (content->IsLink(getter_AddRefs(linkURI))) {
       return true;
--- a/layout/base/nsDocumentViewer.cpp
+++ b/layout/base/nsDocumentViewer.cpp
@@ -2220,16 +2220,21 @@ nsDocumentViewer::CreateStyleSet(nsIDocu
 
   if (!shouldOverride) {
     sheet = nsLayoutStylesheetCache::ScrollbarsSheet();
     if (sheet) {
       styleSet->PrependStyleSheet(nsStyleSet::eAgentSheet, sheet);
     }
   }
 
+  sheet = nsLayoutStylesheetCache::NumberControlSheet();
+  if (sheet) {
+    styleSet->PrependStyleSheet(nsStyleSet::eAgentSheet, sheet);
+  }
+
   sheet = nsLayoutStylesheetCache::FormsSheet();
   if (sheet) {
     styleSet->PrependStyleSheet(nsStyleSet::eAgentSheet, sheet);
   }
 
   sheet = nsLayoutStylesheetCache::FullScreenOverrideSheet();
   if (sheet) {
     styleSet->PrependStyleSheet(nsStyleSet::eOverrideSheet, sheet);
--- a/layout/base/tests/test_event_target_radius.html
+++ b/layout/base/tests/test_event_target_radius.html
@@ -23,17 +23,18 @@ https://bugzilla.mozilla.org/show_bug.cg
 
   <input class="target" id="t3_1" hidden></input>
   <a href="#" class="target" id="t3_2" hidden></a>
   <label class="target" id="t3_3" hidden></label>
   <button class="target" id="t3_4" hidden></button>
   <select class="target" id="t3_5" hidden></select>
   <textarea class="target" id="t3_6" hidden></textarea>
   <div role="button" class="target" id="t3_7" hidden></div>
-  <img class="target" id="t3_8" hidden></img>
+  <div role="key" class="target" id="t3_8" hidden></div>
+  <img class="target" id="t3_9" hidden></img>
 
   <div class="target" style="transform:translate(-80px,0);" id="t4" onmousedown="x=1" hidden></div>
 
   <div class="target" style="left:0; z-index:1" id="t5_left" onmousedown="x=1" hidden></div>
   <div class="target" style="left:106px;" id="t5_right" onmousedown="x=1" hidden></div>
   <div class="target" style="left:0; top:210px;" id="t5_below" onmousedown="x=1" hidden></div>
 
   <div class="target" id="t6" onmousedown="x=1" hidden>
@@ -146,19 +147,19 @@ function test3() {
   t2.onclick = null;
   // Keypresses don't make click radius targets
   t2.onkeypress = function() {};
   testMouseClick("t2", 100 + 11*mm, 10, "body", "DIV with onkeypress");
   t2.onkeypress = null;
   setShowing("t2", false);
 
   // Now check that certain elements are click radius targets and others are not
-  for (var i = 1; i <= 8; ++i) {
+  for (var i = 1; i <= 9; ++i) {
     var id = "t3_" + i;
-    var shouldHit = i <= 7;
+    var shouldHit = i <= 8;
     setShowing(id, true);
     testMouseClick(id, 100 + 11*mm, 10, shouldHit ? id : "body",
                    "<" + document.getElementById(id).tagName + "> element");
     setShowing(id, false);
   }
 
   // Check that our targeting computations take into account the effects of
   // CSS transforms
--- a/layout/style/forms.css
+++ b/layout/style/forms.css
@@ -896,23 +896,19 @@ input[type=range]::-moz-range-thumb {
   height: 1em;
   border: 0.1em solid grey;
   border-radius: 0.5em;
   background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg'><linearGradient id='g' x2='0' y2='100%'><stop stop-color='%23ddd'/><stop offset='100%' stop-color='white'/></linearGradient><rect fill='url(%23g)' width='100%' height='100%'/></svg>");
   /* Prevent nsFrame::HandlePress setting mouse capture to this element. */
   -moz-user-select: none ! important;
 }
 
-input[type="number"] {
-  -moz-appearance: number-input;
-  /* Has to revert some properties applied by the generic input rule. */
-  -moz-binding: none;
-  width: 149px; /* to match type=text */
-  overflow-clip-box: content-box;
-}
+/* As a temporary workaround until bug 677302 the rule for input[type=number]
+ * has moved to number-control.css
+ */
 
 input[type=number]::-moz-number-wrapper {
   /* Prevent styling that would change the type of frame we construct. */
   display: flex;
   float: none !important;
   position: static !important;
   height: 100%;
 }
--- a/layout/style/jar.mn
+++ b/layout/style/jar.mn
@@ -5,12 +5,13 @@
 toolkit.jar:
 *  res/ua.css    (ua.css)
    res/html.css    (html.css)
    res/quirk.css    (quirk.css)
    res/full-screen-override.css    (full-screen-override.css)
    res/plaintext.css     (plaintext.css)
    res/viewsource.css    (viewsource.css)
 *  res/forms.css    (forms.css)
+   res/number-control.css    (number-control.css)
    res/arrow.gif    (arrow.gif)
    res/arrowd.gif   (arrowd.gif)
 
 % resource gre-resources %res/
--- a/layout/style/nsLayoutStylesheetCache.cpp
+++ b/layout/style/nsLayoutStylesheetCache.cpp
@@ -3,24 +3,31 @@
 /* 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 "nsLayoutStylesheetCache.h"
 
 #include "nsAppDirectoryServiceDefs.h"
 #include "mozilla/MemoryReporting.h"
+#include "mozilla/Preferences.h"
 #include "mozilla/css/Loader.h"
 #include "nsIFile.h"
 #include "nsNetUtil.h"
 #include "nsIObserverService.h"
 #include "nsServiceManagerUtils.h"
 #include "nsIXULRuntime.h"
 #include "nsCSSStyleSheet.h"
 
+using namespace mozilla;
+
+static bool sNumberControlEnabled;
+
+#define NUMBER_CONTROL_PREF "dom.forms.number"
+
 NS_IMPL_ISUPPORTS2(
   nsLayoutStylesheetCache, nsIObserver, nsIMemoryReporter)
 
 nsresult
 nsLayoutStylesheetCache::Observe(nsISupports* aSubject,
                             const char* aTopic,
                             const char16_t* aData)
 {
@@ -30,16 +37,17 @@ nsLayoutStylesheetCache::Observe(nsISupp
   }
   else if (!strcmp(aTopic, "profile-do-change")) {
     InitFromProfile();
   }
   else if (strcmp(aTopic, "chrome-flush-skin-caches") == 0 ||
            strcmp(aTopic, "chrome-flush-caches") == 0) {
     mScrollbarsSheet = nullptr;
     mFormsSheet = nullptr;
+    mNumberControlSheet = nullptr;
   }
   else {
     NS_NOTREACHED("Unexpected observer topic.");
   }
   return NS_OK;
 }
 
 nsCSSStyleSheet*
@@ -81,16 +89,41 @@ nsLayoutStylesheetCache::FormsSheet()
 
     NS_ASSERTION(gStyleCache->mFormsSheet, "Could not load forms.css.");
   }
 
   return gStyleCache->mFormsSheet;
 }
 
 nsCSSStyleSheet*
+nsLayoutStylesheetCache::NumberControlSheet()
+{
+  EnsureGlobal();
+  if (!gStyleCache)
+    return nullptr;
+
+  if (!sNumberControlEnabled) {
+    return nullptr;
+  }
+
+  if (!gStyleCache->mNumberControlSheet) {
+    nsCOMPtr<nsIURI> sheetURI;
+    NS_NewURI(getter_AddRefs(sheetURI),
+              NS_LITERAL_CSTRING("resource://gre-resources/number-control.css"));
+
+    if (sheetURI)
+      LoadSheet(sheetURI, gStyleCache->mNumberControlSheet, false);
+
+    NS_ASSERTION(gStyleCache->mNumberControlSheet, "Could not load number-control.css");
+  }
+
+  return gStyleCache->mNumberControlSheet;
+}
+
+nsCSSStyleSheet*
 nsLayoutStylesheetCache::UserContentSheet()
 {
   EnsureGlobal();
   if (!gStyleCache)
     return nullptr;
 
   return gStyleCache->mUserContentSheet;
 }
@@ -159,16 +192,17 @@ size_t
 nsLayoutStylesheetCache::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
 {
   size_t n = aMallocSizeOf(this);
 
   #define MEASURE(s) n += s ? s->SizeOfIncludingThis(aMallocSizeOf) : 0;
 
   MEASURE(mScrollbarsSheet);
   MEASURE(mFormsSheet);
+  MEASURE(mNumberControlSheet);
   MEASURE(mUserContentSheet);
   MEASURE(mUserChromeSheet);
   MEASURE(mUASheet);
   MEASURE(mQuirkSheet);
   MEASURE(mFullScreenOverrideSheet);
 
   // Measurement of the following members may be added later if DMD finds it is
   // worthwhile:
@@ -232,16 +266,19 @@ nsLayoutStylesheetCache::EnsureGlobal()
   if (gStyleCache) return;
 
   gStyleCache = new nsLayoutStylesheetCache();
   if (!gStyleCache) return;
 
   NS_ADDREF(gStyleCache);
 
   gStyleCache->InitMemoryReporter();
+
+  Preferences::AddBoolVarCache(&sNumberControlEnabled, NUMBER_CONTROL_PREF,
+                               true);
 }
 
 void
 nsLayoutStylesheetCache::InitFromProfile()
 {
   nsCOMPtr<nsIXULRuntime> appInfo = do_GetService("@mozilla.org/xre/app-info;1");
   if (appInfo) {
     bool inSafeMode = false;
--- a/layout/style/nsLayoutStylesheetCache.h
+++ b/layout/style/nsLayoutStylesheetCache.h
@@ -28,16 +28,19 @@ class nsLayoutStylesheetCache MOZ_FINAL
  , public nsIMemoryReporter
 {
   NS_DECL_ISUPPORTS
   NS_DECL_NSIOBSERVER
   NS_DECL_NSIMEMORYREPORTER
 
   static nsCSSStyleSheet* ScrollbarsSheet();
   static nsCSSStyleSheet* FormsSheet();
+  // This function is expected to return nullptr when the dom.forms.number
+  // pref is disabled.
+  static nsCSSStyleSheet* NumberControlSheet();
   static nsCSSStyleSheet* UserContentSheet();
   static nsCSSStyleSheet* UserChromeSheet();
   static nsCSSStyleSheet* UASheet();
   static nsCSSStyleSheet* QuirkSheet();
   static nsCSSStyleSheet* FullScreenOverrideSheet();
 
   static void Shutdown();
 
@@ -53,16 +56,17 @@ private:
   static void LoadSheetFile(nsIFile* aFile, nsRefPtr<nsCSSStyleSheet> &aSheet);
   static void LoadSheet(nsIURI* aURI, nsRefPtr<nsCSSStyleSheet> &aSheet,
                         bool aEnableUnsafeRules);
 
   static nsLayoutStylesheetCache* gStyleCache;
   static mozilla::css::Loader* gCSSLoader;
   nsRefPtr<nsCSSStyleSheet> mScrollbarsSheet;
   nsRefPtr<nsCSSStyleSheet> mFormsSheet;
+  nsRefPtr<nsCSSStyleSheet> mNumberControlSheet;
   nsRefPtr<nsCSSStyleSheet> mUserContentSheet;
   nsRefPtr<nsCSSStyleSheet> mUserChromeSheet;
   nsRefPtr<nsCSSStyleSheet> mUASheet;
   nsRefPtr<nsCSSStyleSheet> mQuirkSheet;
   nsRefPtr<nsCSSStyleSheet> mFullScreenOverrideSheet;
 };
 
 #endif
new file mode 100644
--- /dev/null
+++ b/layout/style/number-control.css
@@ -0,0 +1,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/. */
+
+/* This file exists purely because we need the styling for input[type=number]
+ * to apply only if the pref dom.forms.number is true. Once bug 677302 is
+ * fixed this rule can move back to forms.css.
+ */
+
+input[type="number"] {
+  -moz-appearance: number-input;
+  /* Has to revert some properties applied by the generic input rule. */
+  -moz-binding: none;
+  width: 149px; /* to match type=text */
+  overflow-clip-box: content-box;
+}
+
--- a/media/libmkv/WebMElement.c
+++ b/media/libmkv/WebMElement.c
@@ -52,32 +52,39 @@ static UInt64 generateTrackID(unsigned i
   r = r << 32;
   r +=  rand();
 //  UInt64 rval = t ^ r;
   return t ^ r;
 }
 
 void writeVideoTrack(EbmlGlobal *glob, unsigned int trackNumber, int flagLacing,
                      const char *codecId, unsigned int pixelWidth, unsigned int pixelHeight,
+                     unsigned int displayWidth, unsigned int displayHeight,
                      double frameRate) {
   EbmlLoc start;
   UInt64 trackID;
   Ebml_StartSubElement(glob, &start, TrackEntry);
   Ebml_SerializeUnsigned(glob, TrackNumber, trackNumber);
   trackID = generateTrackID(trackNumber);
   Ebml_SerializeUnsigned(glob, TrackUID, trackID);
   Ebml_SerializeString(glob, CodecName, "VP8");  // TODO shouldn't be fixed
 
   Ebml_SerializeUnsigned(glob, TrackType, 1); // video is always 1
   Ebml_SerializeString(glob, CodecID, codecId);
   {
     EbmlLoc videoStart;
     Ebml_StartSubElement(glob, &videoStart, Video);
     Ebml_SerializeUnsigned(glob, PixelWidth, pixelWidth);
     Ebml_SerializeUnsigned(glob, PixelHeight, pixelHeight);
+    if (pixelWidth != displayWidth) {
+      Ebml_SerializeUnsigned(glob, DisplayWidth, displayWidth);
+    }
+    if (pixelHeight != displayHeight) {
+      Ebml_SerializeUnsigned(glob, DisplayHeight, displayHeight);
+    }
     Ebml_SerializeFloat(glob, FrameRate, frameRate);
     Ebml_EndSubElement(glob, &videoStart); // Video
   }
   Ebml_EndSubElement(glob, &start); // Track Entry
 }
 void writeAudioTrack(EbmlGlobal *glob, unsigned int trackNumber, int flagLacing,
                      const char *codecId, double samplingFrequency, unsigned int channels,
                      unsigned char *private, unsigned long privateSize) {
--- a/media/libmkv/WebMElement.h
+++ b/media/libmkv/WebMElement.h
@@ -16,16 +16,17 @@ extern "C" {
 #include "EbmlWriter.h"
 
 // these are helper functions
 void writeHeader(EbmlGlobal *ebml);
 void writeSegmentInformation(EbmlGlobal *ebml, EbmlLoc *startInfo, unsigned long timeCodeScale, double duration);
 // this function is a helper only, it assumes a lot of defaults
 void writeVideoTrack(EbmlGlobal *ebml, unsigned int trackNumber, int flagLacing,
                      const char *codecId, unsigned int pixelWidth, unsigned int pixelHeight,
+                     unsigned int displayWidth, unsigned int displayHeight,
                      double frameRate);
 void writeAudioTrack(EbmlGlobal *glob, unsigned int trackNumber, int flagLacing,
                      const char *codecId, double samplingFrequency, unsigned int channels,
                      unsigned char *private_, unsigned long privateSize);
 
 void writeSimpleBlock(EbmlGlobal *ebml, unsigned char trackNumber, short timeCode,
                       int isKeyframe, unsigned char lacingFlag, int discardable,
                       unsigned char *data, unsigned long dataLength);
new file mode 100644
--- /dev/null
+++ b/media/libmkv/bug970774.patch
@@ -0,0 +1,64 @@
+diff --git a/media/libmkv/WebMElement.c b/media/libmkv/WebMElement.c
+--- a/media/libmkv/WebMElement.c
++++ b/media/libmkv/WebMElement.c
+@@ -52,32 +52,39 @@ static UInt64 generateTrackID(unsigned i
+   r = r << 32;
+   r +=  rand();
+ //  UInt64 rval = t ^ r;
+   return t ^ r;
+ }
+ 
+ void writeVideoTrack(EbmlGlobal *glob, unsigned int trackNumber, int flagLacing,
+                      const char *codecId, unsigned int pixelWidth, unsigned int pixelHeight,
++                     unsigned int displayWidth, unsigned int displayHeight,
+                      double frameRate) {
+   EbmlLoc start;
+   UInt64 trackID;
+   Ebml_StartSubElement(glob, &start, TrackEntry);
+   Ebml_SerializeUnsigned(glob, TrackNumber, trackNumber);
+   trackID = generateTrackID(trackNumber);
+   Ebml_SerializeUnsigned(glob, TrackUID, trackID);
+   Ebml_SerializeString(glob, CodecName, "VP8");  // TODO shouldn't be fixed
+ 
+   Ebml_SerializeUnsigned(glob, TrackType, 1); // video is always 1
+   Ebml_SerializeString(glob, CodecID, codecId);
+   {
+     EbmlLoc videoStart;
+     Ebml_StartSubElement(glob, &videoStart, Video);
+     Ebml_SerializeUnsigned(glob, PixelWidth, pixelWidth);
+     Ebml_SerializeUnsigned(glob, PixelHeight, pixelHeight);
++    if (pixelWidth != displayWidth) {
++      Ebml_SerializeUnsigned(glob, DisplayWidth, displayWidth);
++    }
++    if (pixelHeight != displayHeight) {
++      Ebml_SerializeUnsigned(glob, DisplayHeight, displayHeight);
++    }
+     Ebml_SerializeFloat(glob, FrameRate, frameRate);
+     Ebml_EndSubElement(glob, &videoStart); // Video
+   }
+   Ebml_EndSubElement(glob, &start); // Track Entry
+ }
+ void writeAudioTrack(EbmlGlobal *glob, unsigned int trackNumber, int flagLacing,
+                      const char *codecId, double samplingFrequency, unsigned int channels,
+                      unsigned char *private, unsigned long privateSize) {
+diff --git a/media/libmkv/WebMElement.h b/media/libmkv/WebMElement.h
+--- a/media/libmkv/WebMElement.h
++++ b/media/libmkv/WebMElement.h
+@@ -16,16 +16,17 @@ extern "C" {
+ #include "EbmlWriter.h"
+ 
+ // these are helper functions
+ void writeHeader(EbmlGlobal *ebml);
+ void writeSegmentInformation(EbmlGlobal *ebml, EbmlLoc *startInfo, unsigned long timeCodeScale, double duration);
+ // this function is a helper only, it assumes a lot of defaults
+ void writeVideoTrack(EbmlGlobal *ebml, unsigned int trackNumber, int flagLacing,
+                      const char *codecId, unsigned int pixelWidth, unsigned int pixelHeight,
++                     unsigned int displayWidth, unsigned int displayHeight,
+                      double frameRate);
+ void writeAudioTrack(EbmlGlobal *glob, unsigned int trackNumber, int flagLacing,
+                      const char *codecId, double samplingFrequency, unsigned int channels,
+                      unsigned char *private_, unsigned long privateSize);
+ 
+ void writeSimpleBlock(EbmlGlobal *ebml, unsigned char trackNumber, short timeCode,
+                       int isKeyframe, unsigned char lacingFlag, int discardable,
+                       unsigned char *data, unsigned long dataLength);
--- a/media/libmkv/update.sh
+++ b/media/libmkv/update.sh
@@ -30,8 +30,9 @@ else
   echo "Remember to update README_MOZILLA with the version details."
 fi
 
 # Apply any patches against upstream here.
 patch -p1 < source_fix.patch
 patch -p1 < gecko_fix.patch
 patch -p1 < const_fix.patch
 patch -p3 < bock_fix.patch
+patch -p3 < bug970774.patch
--- a/mfbt/RefPtr.h
+++ b/mfbt/RefPtr.h
@@ -96,21 +96,28 @@ class RefCounted
       MOZ_ASSERT(refCnt > 0);
       return refCnt == 1;
     }
 
   private:
     mutable typename Conditional<Atomicity == AtomicRefCount, Atomic<MozRefCountType>, MozRefCountType>::Type refCnt;
 };
 
+#if defined(MOZILLA_INTERNAL_API) && (defined(DEBUG) || defined(FORCE_BUILD_REFCNT_LOGGING))
 #define MOZ_DECLARE_REFCOUNTED_TYPENAME(T) \
-  const char* typeName() const { return #T; }
+  const char* typeName() const { return #T; } \
+  size_t typeSize() const { return sizeof(*this); }
 
 #define MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(T) \
-  virtual const char* typeName() const { return #T; }
+  virtual const char* typeName() const { return #T; } \
+  virtual size_t typeSize() const { return sizeof(*this); }
+#else
+#define MOZ_DECLARE_REFCOUNTED_TYPENAME(T)
+#define MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(T)
+#endif
 
 }
 
 template<typename T>
 class RefCounted : public detail::RefCounted<T, detail::NonAtomicRefCount>
 {
   public:
     ~RefCounted() {
--- a/netwerk/protocol/http/HttpBaseChannel.cpp
+++ b/netwerk/protocol/http/HttpBaseChannel.cpp
@@ -1805,16 +1805,27 @@ HttpBaseChannel::SetupReplacementChannel
   // convey the referrer if one was used for this channel to the next one
   if (mReferrer)
     httpChannel->SetReferrer(mReferrer);
   // convey the mAllowPipelining flag
   httpChannel->SetAllowPipelining(mAllowPipelining);
   // convey the new redirection limit
   httpChannel->SetRedirectionLimit(mRedirectionLimit - 1);
 
+  // convey the Accept header value
+  {
+    nsAutoCString oldAcceptValue;
+    nsresult hasHeader = mRequestHead.GetHeader(nsHttp::Accept, oldAcceptValue);
+    if (NS_SUCCEEDED(hasHeader)) {
+      httpChannel->SetRequestHeader(NS_LITERAL_CSTRING("Accept"),
+                                    oldAcceptValue,
+                                    false);
+    }
+  }
+
   nsCOMPtr<nsIHttpChannelInternal> httpInternal = do_QueryInterface(newChannel);
   if (httpInternal) {
     // convey the mForceAllowThirdPartyCookie flag
     httpInternal->SetForceAllowThirdPartyCookie(mForceAllowThirdPartyCookie);
     // convey the spdy flag
     httpInternal->SetAllowSpdy(mAllowSpdy);
 
     // update the DocumentURI indicator since we are being redirected.
new file mode 100644
--- /dev/null
+++ b/netwerk/test/unit/test_bug401564.js
@@ -0,0 +1,49 @@
+/* -*- Mode: JavaScript; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+"use strict";
+Cu.import("resource://testing-common/httpd.js");
+
+var httpserver = null;
+const noRedirectURI = "/content";
+const pageValue = "Final page";
+const acceptType = "application/json";
+
+function redirectHandler(metadata, response)
+{
+  response.setStatusLine(metadata.httpVersion, 302, "Moved Temporarily");
+  response.setHeader("Location", noRedirectURI, false);
+}
+
+function contentHandler(metadata, response)
+{
+  do_check_eq(metadata.getHeader("Accept"), acceptType);
+  httpserver.stop(do_test_finished);
+}
+
+function dummyHandler(request, buffer)
+{
+}
+
+function run_test()
+{
+  httpserver = new HttpServer();
+  httpserver.registerPathHandler("/redirect", redirectHandler);
+  httpserver.registerPathHandler("/content", contentHandler);
+  httpserver.start(-1);
+
+  var prefs = Cc["@mozilla.org/preferences-service;1"]
+                .getService(Components.interfaces.nsIPrefBranch);
+  prefs.setBoolPref("network.http.prompt-temp-redirect", false);
+
+  var ios = Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService);
+  var chan = ios.newChannel("http://localhost:" +
+                            httpserver.identity.primaryPort + "/redirect",
+                            "",
+                            null);
+
+  chan.QueryInterface(Ci.nsIHttpChannel);
+  chan.setRequestHeader("Accept", acceptType, false);
+
+  chan.asyncOpen(new ChannelListener(dummyHandler, null), null);
+
+  do_test_pending();
+}
--- a/netwerk/test/unit/xpcshell.ini
+++ b/netwerk/test/unit/xpcshell.ini
@@ -91,16 +91,17 @@ skip-if = "FTP channel implementation ne
 [test_bug371473.js]
 [test_bug376660.js]
 [test_bug376844.js]
 [test_bug376865.js]
 [test_bug379034.js]
 [test_bug380994.js]
 [test_bug388281.js]
 [test_bug396389.js]
+[test_bug401564.js]
 [test_bug411952.js]
 [test_bug412945.js]
 [test_bug414122.js]
 [test_bug427957.js]
 [test_bug429347.js]
 [test_bug455311.js]
 [test_bug455598.js]
 [test_bug468426.js]
--- a/testing/marionette/client/marionette/marionette.py
+++ b/testing/marionette/client/marionette/marionette.py
@@ -580,17 +580,17 @@ class Marionette(object):
                     time.sleep(5)
                     return True
             except socket.error:
                 pass
             time.sleep(1)
         return False
 
     def _send_message(self, command, response_key="ok", **kwargs):
-        if not self.session and command not in ("newSession", "getStatus"):
+        if not self.session and command != "newSession":
             raise MarionetteException("Please start a session")
 
         message = {"name": command}
         if self.session:
             message["sessionId"] = self.session
         if kwargs:
             message["parameters"] = kwargs
 
@@ -697,19 +697,16 @@ class Marionette(object):
     def absolute_url(self, relative_url):
         '''
         Returns an absolute url for files served from Marionette's www directory.
 
         :param relative_url: The url of a static file, relative to Marionette's www directory.
         '''
         return "%s%s" % (self.baseurl, relative_url)
 
-    def status(self):
-        return self._send_message('getStatus', 'value')
-
     def start_session(self, desired_capabilities=None):
         """Create a new Marionette session.
 
         This method must be called before performing any other action.
 
         :params desired_capabilities: An optional dict of desired
             capabilities.  This is currently ignored.
 
deleted file mode 100644
--- a/testing/marionette/client/marionette/tests/unit/test_getstatus.py
+++ /dev/null
@@ -1,19 +0,0 @@
-# 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/.
-
-from marionette_test import MarionetteTestCase
-
-class TestGetStatus(MarionetteTestCase):
-    def test_getStatus(self):
-        status = self.marionette.status()
-        self.assertTrue("os" in status)
-        status_os = status['os']
-        self.assertTrue("version" in status_os)
-        self.assertTrue("name" in status_os)
-        self.assertTrue("arch" in status_os)
-        self.assertTrue("build" in status)
-        status_build = status['build']
-        self.assertTrue("revision" in status_build)
-        self.assertTrue("time" in status_build)
-        self.assertTrue("version" in status_build)
--- a/testing/marionette/client/marionette/tests/unit/unit-tests.ini
+++ b/testing/marionette/client/marionette/tests/unit/unit-tests.ini
@@ -10,17 +10,16 @@ b2g = true
 
 ; true if the test should be skipped
 skip = false
 
 [test_session.py]
 
 [test_expectedfail.py]
 expected = fail
-[test_getstatus.py]
 [test_import_script.py]
 [test_import_script_reuse_window.py]
 b2g = false
 [test_click.py]
 [test_click_chrome.py]
 b2g = false
 [test_selected.py]
 [test_selected_chrome.py]
--- a/testing/marionette/marionette-server.js
+++ b/testing/marionette/marionette-server.js
@@ -583,43 +583,16 @@ MarionetteServerConnection.prototype = {
     // compatibility.  They only check for the presence of this
     // property and should so not be in caps if not on a B2G device.
     if (isB2G)
       caps.b2g = true;
 
     this.sendResponse(caps, this.command_id);
   },
 
-  getStatus: function MDA_getStatus(){
-    this.command_id = this.getCommandId();
-
-    let arch;
-    try {
-      arch = (Services.appinfo.XPCOMABI || 'unknown').split('-')[0]
-    }
-    catch (ignored) {
-      arch = 'unknown'
-    };
-
-    let value = {
-          'os': {
-            'arch': arch,
-            'name': Services.appinfo.OS,
-            'version': 'unknown'
-          },
-          'build': {
-            'revision': 'unknown',
-            'time': Services.appinfo.platformBuildID,
-            'version': Services.appinfo.version
-          }
-    };
-
-    this.sendResponse(value, this.command_id);
-  },
-
   /**
    * Log message. Accepts user defined log-level.
    *
    * @param object aRequest
    *        'value' member holds log message
    *        'level' member hold log level
    */
   log: function MDA_log(aRequest) {
@@ -2428,17 +2401,16 @@ MarionetteServerConnection.prototype = {
   }
 };
 
 MarionetteServerConnection.prototype.requestTypes = {
   "getMarionetteID": MarionetteServerConnection.prototype.getMarionetteID,
   "sayHello": MarionetteServerConnection.prototype.sayHello,
   "newSession": MarionetteServerConnection.prototype.newSession,
   "getSessionCapabilities": MarionetteServerConnection.prototype.getSessionCapabilities,
-  "getStatus": MarionetteServerConnection.prototype.getStatus,
   "log": MarionetteServerConnection.prototype.log,
   "getLogs": MarionetteServerConnection.prototype.getLogs,
   "setContext": MarionetteServerConnection.prototype.setContext,
   "executeScript": MarionetteServerConnection.prototype.execute,
   "setScriptTimeout": MarionetteServerConnection.prototype.setScriptTimeout,
   "timeouts": MarionetteServerConnection.prototype.timeouts,
   "singleTap": MarionetteServerConnection.prototype.singleTap,
   "actionChain": MarionetteServerConnection.prototype.actionChain,
--- a/testing/mochitest/tests/SimpleTest/SimpleTest.js
+++ b/testing/mochitest/tests/SimpleTest/SimpleTest.js
@@ -308,16 +308,31 @@ SimpleTest.getTestFileURL = function(pat
 };
 
 SimpleTest._getCurrentTestURL = function() {
     return parentRunner && parentRunner.currentTestURL ||
            typeof gTestPath == "string" && gTestPath ||
            "unknown test url";
 };
 
+SimpleTest._forceLogMessageOutput = false;
+
+/**
+ * Force all test messages to be displayed.  Only applies for the current test.
+ */
+SimpleTest.requestCompleteLog = function() {
+    if (SimpleTest._forceLogMessageOutput)
+        return;
+
+    SimpleTest._forceLogMessageOutput = true;
+    SimpleTest.registerCleanupFunction(function() {
+        SimpleTest._forceLogMessageOutput = false;
+    });
+};
+
 SimpleTest._logResult = (function () {
     var numCoalescedMessages = 1;
     var coalesceThreshold = 100;
 
     function logResult(test, passString, failString) {
         var isError = !test.result == !test.todo;
         var outputCoalescedMessage = numCoalescedMessages == coalesceThreshold;
 
@@ -329,17 +344,18 @@ SimpleTest._logResult = (function () {
         // TEST-PASS/TEST-KNOWN-FAIL messages.  But we always want to log
         // errors and informative messages.  We also want to output messages
         // every so often to let the user know the test is still running.
         // If they user is only running a single test, it is likely that they
         // want to see all the test messages.
         var shouldLog = (isError ||
                          passString == "TEST-INFO" ||
                          outputCoalescedMessage ||
-                         runningSingleTest);
+                         runningSingleTest ||
+                         SimpleTest._forceLogMessageOutput);
 
         if (!shouldLog) {
             ++numCoalescedMessages;
             return;
         }
 
         var resultString = test.result ? passString : failString;
         var url = SimpleTest._getCurrentTestURL();
--- a/toolkit/components/maintenanceservice/Makefile.in
+++ b/toolkit/components/maintenanceservice/Makefile.in
@@ -14,21 +14,16 @@ ifeq ($(OS_ARCH),WINNT)
 LIBS += $(call EXPAND_LIBNAME_PATH,updatecommon-standalone,../../mozapps/update/common-standalone)
 else
 LIBS += $(call EXPAND_LIBNAME_PATH,updatecommon,../../mozapps/update/common)
 endif
 
 RCINCLUDE = maintenanceservice.rc
 
 OS_LIBS += $(call EXPAND_LIBNAME,comctl32 ws2_32 shell32)
-ifndef GNU_CC
-RCFLAGS += -I$(srcdir)
-else
-RCFLAGS += --include-dir $(srcdir)
-endif
 
 ifndef MOZ_WINCONSOLE
 ifdef MOZ_DEBUG
 MOZ_WINCONSOLE = 1
 else
 MOZ_WINCONSOLE = 0
 endif
 endif
--- a/toolkit/mozapps/update/updater/Makefile.in
+++ b/toolkit/mozapps/update/updater/Makefile.in
@@ -17,22 +17,16 @@ LIBS += \
   $(call EXPAND_LIBNAME_PATH,mar,$(DEPTH)/modules/libmar/src) \
   $(MOZ_BZ2_LIBS) \
   $(NULL)
 
 ifeq ($(OS_ARCH),WINNT)
 LIBS += $(call EXPAND_LIBNAME_PATH,verifymar,$(DEPTH)/modules/libmar/verify)
 RCINCLUDE = updater.rc
 OS_LIBS += $(call EXPAND_LIBNAME,comctl32 ws2_32 shell32 shlwapi)
-ifndef GNU_CC
-RCFLAGS += -I$(srcdir)
-else
-RCFLAGS += --include-dir $(srcdir)
-endif
-
 endif
 
 ifdef MOZ_WIDGET_GTK
 OS_CXXFLAGS += $(TK_CFLAGS)
 OS_LIBS += $(TK_LIBS)
 endif
 
 ifeq (cocoa,$(MOZ_WIDGET_TOOLKIT))
@@ -74,16 +68,8 @@ libs::
 endif
 
 ifeq ($(OS_ARCH),WINNT)
 EXTRA_LIBS += $(call EXPAND_LIBNAME,crypt32)
 EXTRA_LIBS += $(call EXPAND_LIBNAME,advapi32)
 endif
 
 CXXFLAGS += $(MOZ_BZ2_CFLAGS)
-
-ifneq (,$(filter beta release esr,$(MOZ_UPDATE_CHANNEL)))
-RCFLAGS += -DMAR_SIGNING_RELEASE_BETA=1
-else
-ifneq (,$(filter nightly aurora nightly-elm nightly-profiling nightly-oak,$(MOZ_UPDATE_CHANNEL)))
-RCFLAGS += -DMAR_SIGNING_AURORA_NIGHTLY=1
-endif
-endif
--- a/toolkit/mozapps/update/updater/moz.build
+++ b/toolkit/mozapps/update/updater/moz.build
@@ -67,8 +67,13 @@ LOCAL_INCLUDES += [
 DELAYLOAD_DLLS += [
     'crypt32.dll',
     'userenv.dll',
     'wsock32.dll',
 ]
 
 if CONFIG['_MSC_VER']:
     WIN32_EXE_LDFLAGS += ['-ENTRY:wmainCRTStartup']
+
+if CONFIG['MOZ_UPDATE_CHANNEL'] in ('beta', 'release', 'esr'):
+    DEFINES['MAR_SIGNING_RELEASE_BETA'] = '1'
+elif CONFIG['MOZ_UPDATE_CHANNEL'] in ('nightly', 'aurora', 'nightly-elm', 'nightly-profiling', 'nightly-oak'):
+    DEFINES['MAR_SIGNING_AURORA_NIGHTLY'] = '1'
--- a/tools/mercurial/hgsetup/wizard.py
+++ b/tools/mercurial/hgsetup/wizard.py
@@ -60,17 +60,17 @@ https://hg.mozilla.org/hgcustom/version-
 MQEXT_INFO = '''
 The mqext extension (https://bitbucket.org/sfink/mqext) provides a number of
 useful abilities to Mercurial, including automatically committing changes to
 your mq patch queue.
 '''.strip()
 
 QIMPORTBZ_INFO = '''
 The qimportbz extension
-(https://hg.mozilla.org/users/robarnold_cmu.edu/qimportbz) makes it possible to
+(https://hg.mozilla.org/hgcustom/version-control-tools/file/default/hgext/qimportbz/README) makes it possible to
 import patches from Bugzilla using a friendly bz:// URL handler. e.g.
 |hg qimport bz://123456|.
 '''.strip()
 
 QNEWCURRENTUSER_INFO = '''
 The mercurial queues command |hg qnew|, which creates new patches in your patch
 queue does not set patch author information by default. Author information
 should be included when uploading for review.
@@ -201,33 +201,28 @@ class MercurialSetupWizard(object):
             if update_mqext:
                 self.update_mercurial_repo(
                 hg,
                 'https://bitbucket.org/sfink/mqext',
                 os.path.join(self.ext_dir, 'mqext'),
                 'default',
                 'Ensuring mqext extension is up to date...')
 
-            update_qimportbz = 'qimportbz' in active
+            activate_qimportbz = True
             if 'qimportbz' not in active:
                 print(QIMPORTBZ_INFO)
-                if self._prompt_yn('Would you like to activate qimportbz'):
-                    update_qimportbz = True
-                    c.activate_extension('qimportbz',
-                        os.path.join(self.ext_dir, 'qimportbz'))
-                    print('Activated qimportbz extension.')
-                    print('')
+                if not self._prompt_yn('Would you like to activate qimportbz'):
+                    activate_qimportbz = False
 
-            if update_qimportbz:
-                self.update_mercurial_repo(
-                    hg,
-                    'https://hg.mozilla.org/users/robarnold_cmu.edu/qimportbz',
-                    os.path.join(self.ext_dir, 'qimportbz'),
-                    'default',
-                    'Ensuring qimportbz extension is up to date...')
+            if activate_qimportbz:
+                update_vcs_tools = True
+                c.activate_extension('qimportbz',
+                    os.path.join(self.vcs_tools_dir, 'hgext', 'qimportbz'))
+                print('Activated qimportbz extension.')
+                print('')
 
             if not c.have_qnew_currentuser_default():
                 print(QNEWCURRENTUSER_INFO)
                 if self._prompt_yn('Would you like qnew to set patch author by '
                                    'default'):
                     c.ensure_qnew_currentuser_default()
                     print('Configured qnew to set patch author by default.')
                     print('')
@@ -236,17 +231,17 @@ class MercurialSetupWizard(object):
             self.update_mercurial_repo(
                 hg,
                 'https://hg.mozilla.org/hgcustom/version-control-tools',
                 self.vcs_tools_dir,
                 'default',
                 'Ensuring version-control-tools is up to date...')
 
         # Look for and clean up old extensions.
-        for ext in {'bzexport',}:
+        for ext in {'bzexport', 'qimportbz'}:
             path = os.path.join(self.ext_dir, ext)
             if os.path.exists(path):
                 if self._prompt_yn('Would you like to remove the old and no '
                     'longer referenced repository at %s' % path):
                     print('Cleaning up old repository: %s' % path)
                     shutil.rmtree(path)
 
         c.add_mozilla_host_fingerprints()
--- a/webapprt/win/Makefile.in
+++ b/webapprt/win/Makefile.in
@@ -26,24 +26,16 @@ include $(topsrcdir)/toolkit/mozapps/ins
 CONFIG_DIR = instgen
 SFX_MODULE = $(topsrcdir)/other-licenses/7zstub/firefox/7zSD.sfx
 APP_VERSION := $(shell cat $(topsrcdir)/browser/config/version.txt)
 DEFINES += -DAPP_VERSION=$(APP_VERSION)
 
 OS_LIBS += $(call EXPAND_LIBNAME,shell32)
 
 RCINCLUDE = webapprt.rc
-ifndef GNU_CC
-RCFLAGS += -I$(srcdir)
-else
-RCFLAGS += --include-dir $(srcdir)
-endif
-ifdef DEBUG
-RCFLAGS += -DDEBUG
-endif
 
 # Uninstaller
 ifdef LOCALE_MERGEDIR
 PPL_LOCALE_ARGS = \
   --l10n-dir=$(LOCALE_MERGEDIR)/webapprt/webapp-uninstaller \
   --l10n-dir=$(call EXPAND_LOCALE_SRCDIR,webapprt/locales)/webapp-uninstaller \
   --l10n-dir=$(topsrcdir)/webapprt/locales/en-US/webapp-uninstaller \
   $(NULL)
--- a/webapprt/win/moz.build
+++ b/webapprt/win/moz.build
@@ -6,16 +6,18 @@
 
 PROGRAM = 'webapprt-stub'
 
 SOURCES += [
     'webapprt.cpp',
 ]
 
 DEFINES['XPCOM_GLUE'] = True
+if CONFIG['DEBUG']:
+    DEFINES['DEBUG'] = True
 
 # Statically link against the CRT
 USE_STATIC_LIBS = True
 
 GENERATED_INCLUDES += ['/build']
 LOCAL_INCLUDES += [
     '/toolkit/xre',
     '/xpcom/base',
--- a/xulrunner/app/Makefile.in
+++ b/xulrunner/app/Makefile.in
@@ -30,24 +30,16 @@ endif
 # shouldn't get 755 perms need $(IFLAGS1) for either way of calling nsinstall.
 NSDISTMODE = copy
 
 include $(topsrcdir)/config/config.mk
 
 ifeq ($(OS_ARCH),WINNT)
 OS_LIBS += $(call EXPAND_LIBNAME,comctl32 comdlg32 uuid shell32 ole32 oleaut32 version winspool)
 RCINCLUDE = splash.rc
-ifndef GNU_CC
-RCFLAGS += -DMOZ_XULRUNNER -I$(srcdir)
-else
-RCFLAGS += -DMOZ_XULRUNNER --include-dir $(srcdir)
-endif
-ifdef DEBUG
-RCFLAGS += -DDEBUG
-endif
 endif
 
 include $(topsrcdir)/config/rules.mk
 
 DEFINES += -DXULRUNNER_ICO='"$(DIST)/branding/xulrunner.ico"' -DDOCUMENT_ICO='"$(DIST)/branding/document.ico"'
 
 ifeq ($(OS_ARCH),WINNT)
 #
--- a/xulrunner/app/moz.build
+++ b/xulrunner/app/moz.build
@@ -9,16 +9,18 @@ DIRS += ['profile']
 PROGRAM = 'xulrunner'
 
 SOURCES += [
     'nsXULRunnerApp.cpp',
 ]
 
 DEFINES['XULRUNNER_PROGNAME'] = '"xulrunner"'
 DEFINES['XPCOM_GLUE'] = True
+if CONFIG['DEBUG']:
+    DEFINES['DEBUG'] = True
 
 if CONFIG['TARGET_XPCOM_ABI']:
     DEFINES['TARGET_XPCOM_ABI'] = '"%s"' % CONFIG['TARGET_XPCOM_ABI']
 
 LOCAL_INCLUDES += [
     '/toolkit/profile',
     '/toolkit/xre',
     '/xpcom/base',
--- a/xulrunner/stub/Makefile.in
+++ b/xulrunner/stub/Makefile.in
@@ -15,21 +15,16 @@ LIBS = \
 ifeq (cocoa,$(MOZ_WIDGET_TOOLKIT))
 LIBS            += \
 		$(TK_LIBS) \
 		$(NULL)
 endif
 
 ifeq ($(OS_ARCH),WINNT)
 RCINCLUDE = xulrunner-stub.rc
-ifndef GNU_CC
-RCFLAGS += -DMOZ_XULRUNNER -I$(srcdir)
-else
-RCFLAGS += -DMOZ_XULRUNNER --include-dir $(srcdir)
-endif
 endif
 
 ifndef MOZ_WINCONSOLE
 ifdef MOZ_DEBUG
 MOZ_WINCONSOLE = 1
 else
 MOZ_WINCONSOLE = 0
 endif
--- a/xulrunner/stub/moz.build
+++ b/xulrunner/stub/moz.build
@@ -28,8 +28,11 @@ LOCAL_INCLUDES += [
 # Statically link against the RTL on windows
 USE_STATIC_LIBS = True
 
 if CONFIG['OS_ARCH'] == 'WINNT':
     LOCAL_INCLUDES += ['/toolkit/xre']
 
 if CONFIG['_MSC_VER']:
     WIN32_EXE_LDFLAGS += ['-ENTRY:wmainCRTStartup']
+
+if CONFIG['OS_ARCH'] == 'WINNT':
+    DEFINES['MOZ_XULRUNNER'] = True