Merge inbound to m-c
authorWes Kocher <wkocher@mozilla.com>
Tue, 18 Feb 2014 21:02:55 -0800
changeset 169408 955ffa2c9620b68a57562e6e9d466474d0c42379
parent 169399 f4f3d86162a536c935b048eb85a49d4d60f4ae28 (current diff)
parent 169407 56fa355b196de79be1c3e6fba8c65aaa2518fe44 (diff)
child 169440 bf0e76f2a7d431337f51602bbc5a2f5d3a9d3f5f
push id1
push userroot
push dateMon, 20 Oct 2014 17:29:22 +0000
milestone30.0a1
Merge inbound to m-c
--- a/gfx/2d/DrawTargetCG.cpp
+++ b/gfx/2d/DrawTargetCG.cpp
@@ -8,16 +8,17 @@
 #include "Rect.h"
 #include "ScaledFontMac.h"
 #include "Tools.h"
 #include <vector>
 #include <algorithm>
 #include "MacIOSurface.h"
 #include "FilterNodeSoftware.h"
 #include "mozilla/Assertions.h"
+#include "mozilla/FloatingPoint.h"
 
 using namespace std;
 
 //CG_EXTERN void CGContextSetCompositeOperation (CGContextRef, PrivateCGCompositeMode);
 
 // A private API that Cairo has been using for a long time
 CG_EXTERN void CGContextSetCTM(CGContextRef, CGAffineTransform);
 
@@ -408,16 +409,18 @@ DrawTargetCG::CreateGradientStops(Gradie
 }
 
 static void
 UpdateLinearParametersToIncludePoint(double *min_t, double *max_t,
                                      CGPoint *start,
                                      double dx, double dy,
                                      double x, double y)
 {
+  MOZ_ASSERT(IsFinite(x) && IsFinite(y));
+
   /**
    * Compute a parameter t such that a line perpendicular to the (dx,dy)
    * vector, passing through (start->x + dx*t, start->y + dy*t), also
    * passes through (x,y).
    *
    * Let px = x - start->x, py = y - start->y.
    * t is given by
    *   (px - dx*t)*dx + (py - dy*t)*dy = 0
@@ -604,16 +607,20 @@ DrawRadialRepeatingGradient(CGContextRef
   CGContextDrawRadialGradient(cg, gradient, startCenter, startRadius, endCenter, endRadius,
                               kCGGradientDrawsBeforeStartLocation | kCGGradientDrawsAfterEndLocation);
   CGGradientRelease(gradient);
 }
 
 static void
 DrawGradient(CGContextRef cg, const Pattern &aPattern, const CGRect &aExtents)
 {
+  if (CGRectIsEmpty(aExtents)) {
+    return;
+  }
+
   if (aPattern.GetType() == PatternType::LINEAR_GRADIENT) {
     const LinearGradientPattern& pat = static_cast<const LinearGradientPattern&>(aPattern);
     GradientStopsCG *stops = static_cast<GradientStopsCG*>(pat.mStops.get());
     CGContextConcatCTM(cg, GfxMatrixToCGAffineTransform(pat.mMatrix));
     if (stops->mExtend == ExtendMode::CLAMP) {
 
       // XXX: we should take the m out of the properties of LinearGradientPatterns
       CGPoint startPoint = { pat.mBegin.x, pat.mBegin.y };
--- a/gfx/layers/Layers.cpp
+++ b/gfx/layers/Layers.cpp
@@ -808,19 +808,23 @@ ContainerLayer::RepositionChild(Layer* a
   Layer* prev = aChild->GetPrevSibling();
   Layer* next = aChild->GetNextSibling();
   if (prev == aAfter) {
     // aChild is already in the correct position, nothing to do.
     return;
   }
   if (prev) {
     prev->SetNextSibling(next);
+  } else {
+    mFirstChild = next;
   }
   if (next) {
     next->SetPrevSibling(prev);
+  } else {
+    mLastChild = prev;
   }
   if (!aAfter) {
     aChild->SetPrevSibling(nullptr);
     aChild->SetNextSibling(mFirstChild);
     if (mFirstChild) {
       mFirstChild->SetPrevSibling(aChild);
     }
     mFirstChild = aChild;
--- a/gfx/tests/gtest/TestLayers.cpp
+++ b/gfx/tests/gtest/TestLayers.cpp
@@ -46,43 +46,16 @@ public:
 
   virtual LayerType GetType() const {
     return TYPE_CONTAINER;
   }
 
   virtual void ComputeEffectiveTransforms(const Matrix4x4& aTransformToSurface) {
     DefaultComputeEffectiveTransforms(aTransformToSurface);
   }
-
-  virtual void RepositionChild(Layer* aChild, Layer* aAfter) {
-    MOZ_CRASH();
-  }
-
-  virtual void InsertAfter(Layer* aChild, Layer* aAfter) {
-    // Bad implementation but it should be fine for testing
-    if (this == aChild) {
-      MOZ_CRASH();
-    }
-    if (aAfter != nullptr && aAfter != mLastChild) {
-      // Fix the implementation to support this if you need it
-      MOZ_CRASH();
-    }
-    if (!mFirstChild) {
-      mFirstChild = aChild;
-    }
-    if (mLastChild) {
-      mLastChild->SetNextSibling(aChild);
-    }
-    aChild->SetPrevSibling(mLastChild);
-    mLastChild = aChild;
-  }
-
-  virtual void RemoveChild(Layer* aChild) {
-    MOZ_CRASH();
-  }
 };
 
 class TestThebesLayer: public ThebesLayer {
 public:
   TestThebesLayer(LayerManager* aManager)
     : ThebesLayer(aManager, nullptr)
   {}
 
@@ -212,30 +185,34 @@ already_AddRefed<Layer> CreateLayerTree(
         printf("Layer before '(' must be a container.\n");
         MOZ_CRASH();
       }
     } else if (aLayerTreeDescription[i] == ')') {
       parentContainerLayer = parentContainerLayer->GetParent();
       lastLayer = nullptr;
     } else {
       nsRefPtr<Layer> layer = CreateLayer(aLayerTreeDescription[i], manager.get());
-      layer->SetVisibleRegion(aVisibleRegions[layerNumber]);
-      Matrix4x4 transform;
-      ToMatrix4x4(aTransforms[layerNumber], transform);
-      layer->SetBaseTransform(transform);
+      if (aVisibleRegions) {
+        layer->SetVisibleRegion(aVisibleRegions[layerNumber]);
+      }
+      if (aTransforms) {
+        Matrix4x4 transform;
+        ToMatrix4x4(aTransforms[layerNumber], transform);
+        layer->SetBaseTransform(transform);
+      }
       aLayersOut.AppendElement(layer);
       layerNumber++;
       if (rootLayer && !parentContainerLayer) {
         MOZ_CRASH();
       }
       if (!rootLayer) {
         rootLayer = layer;
       }
       if (parentContainerLayer) {
-        parentContainerLayer->InsertAfter(layer, nullptr);
+        parentContainerLayer->InsertAfter(layer, parentContainerLayer->GetLastChild());
         layer->SetParent(parentContainerLayer);
       }
       lastLayer = layer;
     }
   }
   if (rootLayer) {
     rootLayer->ComputeEffectiveTransforms(Matrix4x4());
   }
@@ -265,8 +242,85 @@ TEST(Layers, LayerTree) {
   // an int.
   Layer* nullLayer = nullptr;
   ASSERT_NE(nullLayer, layers[0]->AsContainerLayer());
   ASSERT_NE(nullLayer, layers[1]->AsContainerLayer());
   ASSERT_NE(nullLayer, layers[2]->AsThebesLayer());
   ASSERT_NE(nullLayer, layers[3]->AsThebesLayer());
 }
 
+static void ValidateTreePointers(Layer* aLayer) {
+  if (aLayer->GetNextSibling()) {
+    ASSERT_EQ(aLayer, aLayer->GetNextSibling()->GetPrevSibling());
+  } else if (aLayer->GetParent()) {
+    ASSERT_EQ(aLayer, aLayer->GetParent()->GetLastChild());
+  }
+  if (aLayer->GetPrevSibling()) {
+    ASSERT_EQ(aLayer, aLayer->GetPrevSibling()->GetNextSibling());
+  } else if (aLayer->GetParent()) {
+    ASSERT_EQ(aLayer, aLayer->GetParent()->GetFirstChild());
+  }
+  if (aLayer->GetFirstChild()) {
+    ASSERT_EQ(aLayer, aLayer->GetFirstChild()->GetParent());
+  }
+  if (aLayer->GetLastChild()) {
+    ASSERT_EQ(aLayer, aLayer->GetLastChild()->GetParent());
+  }
+}
+
+static void ValidateTreePointers(nsTArray<nsRefPtr<Layer> >& aLayers) {
+  for (uint32_t i = 0; i < aLayers.Length(); i++) {
+    ValidateTreePointers(aLayers[i]);
+  }
+}
+
+TEST(Layers, RepositionChild) {
+  const char* layerTreeSyntax = "c(ttt)";
+
+  nsTArray<nsRefPtr<Layer> > layers;
+  nsRefPtr<LayerManager> lm;
+  nsRefPtr<Layer> root = CreateLayerTree(layerTreeSyntax, nullptr, nullptr, lm, layers);
+  ContainerLayer* parent = root->AsContainerLayer();
+  ValidateTreePointers(layers);
+
+  // tree is currently like this (using indexes into layers):
+  //   0
+  // 1 2 3
+  ASSERT_EQ(layers[2], layers[1]->GetNextSibling());
+  ASSERT_EQ(layers[3], layers[2]->GetNextSibling());
+  ASSERT_EQ(nullptr, layers[3]->GetNextSibling());
+
+  parent->RepositionChild(layers[1], layers[3]);
+  ValidateTreePointers(layers);
+
+  // now the tree is like this:
+  //   0
+  // 2 3 1
+  ASSERT_EQ(layers[3], layers[2]->GetNextSibling());
+  ASSERT_EQ(layers[1], layers[3]->GetNextSibling());
+  ASSERT_EQ(nullptr, layers[1]->GetNextSibling());
+
+  parent->RepositionChild(layers[3], layers[2]);
+  ValidateTreePointers(layers);
+
+  // no change
+  ASSERT_EQ(layers[3], layers[2]->GetNextSibling());
+  ASSERT_EQ(layers[1], layers[3]->GetNextSibling());
+  ASSERT_EQ(nullptr, layers[1]->GetNextSibling());
+
+  parent->RepositionChild(layers[3], layers[1]);
+  ValidateTreePointers(layers);
+
+  //   0
+  // 2 1 3
+  ASSERT_EQ(layers[1], layers[2]->GetNextSibling());
+  ASSERT_EQ(layers[3], layers[1]->GetNextSibling());
+  ASSERT_EQ(nullptr, layers[3]->GetNextSibling());
+
+  parent->RepositionChild(layers[3], nullptr);
+  ValidateTreePointers(layers);
+
+  //   0
+  // 3 2 1
+  ASSERT_EQ(layers[2], layers[3]->GetNextSibling());
+  ASSERT_EQ(layers[1], layers[2]->GetNextSibling());
+  ASSERT_EQ(nullptr, layers[1]->GetNextSibling());
+}
--- a/layout/style/forms.css
+++ b/layout/style/forms.css
@@ -886,26 +886,24 @@ input[type=range]::-moz-range-thumb {
 
 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 */
 }
 
-input[type=number] > div, /* work around bug 946184 */
 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%;
 }
 
-input[type=number] > div > input, /* work around bug 946184 */
 input[type=number]::-moz-number-text {
   -moz-appearance: none;
   /* work around autofocus bug 939248 on initial load */
   -moz-user-modify: read-write;
   /* This pseudo-element is also an 'input' element (nested inside and
    * distinct from the <input type=number> element) so we need to prevent the
    * explicit setting of 'text-align' by the general CSS rule for 'input'
    * above. We want to inherit its value from its <input type=number>
@@ -913,48 +911,45 @@ input[type=number]::-moz-number-text {
    */
   text-align: inherit;
   flex: 1;
   padding: 0;
   border: 0;
   margin: 0;
 }
 
-input[type=number] > div > div, /* work around bug 946184 */
 input[type=number]::-moz-number-spin-box {
   display: flex;
   flex-direction: column;
 %ifdef XP_WIN
   /* The Window's Theme's spin buttons have a very narrow minimum width, so
    * make it something reasonable:
    */
   width: 16px;
 %endif
   height: 0;
   align-self: center;
   justify-content: center;
 }
 
-input[type=number] > div > div > div:first-child, /* work around bug 946184 */
 input[type=number]::-moz-number-spin-up {
   -moz-appearance: spinner-upbutton;
   display: block; /* bug 926670 */
   flex: none;
   cursor: default;
   /* Style for when native theming is off: */
   background-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" width="6" height="5"><path d="M1,4 L3,0 5,4" fill="dimgrey"/></svg>');
   background-repeat: no-repeat;
   background-position: center bottom;
   border: 1px solid darkgray;
   border-bottom: none;
   border-top-left-radius: 4px;
   border-top-right-radius: 4px;
 }
 
-input[type=number] > div > div > div:not(:first-child), /* work around bug 946184 */
 input[type=number]::-moz-number-spin-down {
   -moz-appearance: spinner-downbutton;
   display: block; /* bug 926670 */
   flex: none;
   cursor: default;
   /* Style for when native theming is off: */
   background-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" width="6" height="5"><path d="M1,1 L3,5 5,1" fill="dimgrey"/></svg>');
   background-repeat: no-repeat;
--- a/testing/marionette/client/marionette/emulator.py
+++ b/testing/marionette/client/marionette/emulator.py
@@ -18,26 +18,32 @@ import tempfile
 import time
 import traceback
 
 from emulator_battery import EmulatorBattery
 from emulator_geo import EmulatorGeo
 from emulator_screen import EmulatorScreen
 
 
-class LogcatProc(ProcessHandlerMixin):
-    """Process handler for logcat which saves all output to a logfile.
+class LogOutputProc(ProcessHandlerMixin):
+    """
+    Process handler for processes which save all output to a logfile.
+    If no logfile is specified, output will still be consumed to prevent
+    the output pipe's from overflowing.
     """
 
-    def __init__(self, logfile, cmd, **kwargs):
+    def __init__(self, cmd, logfile=None,  **kwargs):
         self.logfile = logfile
         kwargs.setdefault('processOutputLine', []).append(self.log_output)
         ProcessHandlerMixin.__init__(self, cmd, **kwargs)
 
     def log_output(self, line):
+        if not self.logfile:
+            return
+
         f = open(self.logfile, 'a')
         f.write(line + "\n")
         f.flush()
 
 
 class Emulator(object):
 
     deviceRe = re.compile(r"^emulator-(\d+)(\s*)(.*)$")
@@ -312,19 +318,24 @@ waitFor(
         if self.copy_userdata:
             # Make a copy of the userdata.img for this instance of the emulator to use.
             self._tmp_userdata = tempfile.mktemp(prefix='marionette')
             shutil.copyfile(self.dataImg, self._tmp_userdata)
             qemu_args[qemu_args.index('-data') + 1] = self._tmp_userdata
 
         original_online, original_offline = self._get_adb_devices()
 
-        self.proc = subprocess.Popen(qemu_args,
-                                     stdout=subprocess.PIPE,
-                                     stderr=subprocess.PIPE)
+        filename = None
+        if self.logcat_dir:
+            filename = os.path.join(self.logcat_dir, 'qemu.log')
+            if os.path.isfile(filename):
+                self.rotate_log(filename)
+
+        self.proc = LogOutputProc(qemu_args, filename)
+        self.proc.run()
 
         online, offline = self._get_adb_devices()
         now = datetime.datetime.now()
         while online - original_online == set([]):
             time.sleep(1)
             if datetime.datetime.now() - now > datetime.timedelta(seconds=60):
                 raise Exception('timed out waiting for emulator to start')
             online, offline = self._get_adb_devices()
@@ -458,33 +469,39 @@ window.addEventListener('mozbrowserloade
         self.dm.pushFile(busybox, remote_file, retryLimit=10)
         self._run_adb(['shell', 'cd /system/bin; chmod 555 busybox; for x in `./busybox --list`; do ln -s ./busybox $x; done'])
         self.dm._verifyZip()
 
     def rotate_log(self, srclog, index=1):
         """ Rotate a logfile, by recursively rotating logs further in the sequence,
             deleting the last file if necessary.
         """
-        destlog = os.path.join(self.logcat_dir, 'emulator-%d.%d.log' % (self.port, index))
-        if os.access(destlog, os.F_OK):
+        basename = os.path.basename(srclog)
+        basename = basename[:-len('.log')]
+        if index > 1:
+            basename = basename[:-len('.1')]
+        basename = '%s.%d.log' % (basename, index)
+
+        destlog = os.path.join(self.logcat_dir, basename)
+        if os.path.isfile(destlog):
             if index == 3:
                 os.remove(destlog)
             else:
                 self.rotate_log(destlog, index+1)
         shutil.move(srclog, destlog)
 
     def save_logcat(self):
         """ Save the output of logcat to a file.
         """
         filename = os.path.join(self.logcat_dir, "emulator-%d.log" % self.port)
-        if os.access(filename, os.F_OK):
+        if os.path.isfile(filename):
             self.rotate_log(filename)
         cmd = [self.adb, '-s', 'emulator-%d' % self.port, 'logcat', '-v', 'threadtime']
 
-        self.logcat_proc = LogcatProc(filename, cmd)
+        self.logcat_proc = LogOutputProc(cmd, filename)
         self.logcat_proc.run()
 
     def setup_port_forwarding(self, remote_port):
         """ Set up TCP port forwarding to the specified port on the device,
             using any availble local port, and return the local port.
         """
         s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
         s.bind(("",0))
--- a/xpcom/reflect/xptcall/src/md/unix/Makefile.in
+++ b/xpcom/reflect/xptcall/src/md/unix/Makefile.in
@@ -10,19 +10,16 @@
 # Linux/ARM
 #
 ifeq ($(OS_ARCH),Linux)
 ifneq (,$(filter arm% sa110,$(OS_TEST)))
 CXXFLAGS += -O2
 endif
 endif
 
-ifeq ($(OS_TEST),aarch64)
-ASFILES := xptcinvoke_asm_aarch64.s xptcstubs_asm_aarch64.s
-endif
 ######################################################################
 # HPPA
 ######################################################################
 #
 # HP-UX/PA32
 #
 # for gas and gcc, check comment in xptcinvoke_asm_pa32.s
 ifeq ($(OS_ARCH),HP-UX)
--- a/xpcom/reflect/xptcall/src/md/unix/moz.build
+++ b/xpcom/reflect/xptcall/src/md/unix/moz.build
@@ -144,21 +144,16 @@ if CONFIG['OS_ARCH'] == 'NetBSD':
     if CONFIG['OS_TEST'] in ('amiga', 'atari', 'hp300', 'mac68k', 'mvme68k',
                              'next68k', 'sun3', 'sun3x', 'x68k'):
         SOURCES += [
             'xptcinvoke_netbsd_m68k.cpp',
             'xptcstubs_netbsd_m68k.cpp'
         ]
 
 if CONFIG['OS_ARCH'] == 'Linux':
-    if CONFIG['OS_TEST'] == 'aarch64':
-        SOURCES += [
-            'xptcinvoke_aarch64.cpp',
-            'xptcstubs_aarch64.cpp',
-        ]
     if CONFIG['OS_TEST'] == 'm68k':
         SOURCES += [
             'xptcinvoke_linux_m68k.cpp',
             'xptcstubs_linux_m68k.cpp',
         ]
     if CONFIG['OS_TEST'].find('mips') != -1:
         if CONFIG['OS_TEST'].find('mips64') != -1:
             SOURCES += [