Merge pull request #827 from jamesr/mojo_roll_d259eb58aa59e14a13d5e0dc3984b855b475ba09

Update to mojo d259eb58aa59e14a13d5e0dc3984b855b475ba09
diff --git a/sky/packages/sky/lib/rendering/sky_binding.dart b/sky/packages/sky/lib/rendering/sky_binding.dart
index d993d8d..5eca6e8 100644
--- a/sky/packages/sky/lib/rendering/sky_binding.dart
+++ b/sky/packages/sky/lib/rendering/sky_binding.dart
@@ -40,7 +40,7 @@
     sky.view.setMetricsChangedCallback(_handleMetricsChanged);
     scheduler.init();
     if (renderViewOverride == null) {
-      _renderView = new RenderView(child: root, devicePixelRatio: sky.view.devicePixelRatio);
+      _renderView = new RenderView(child: root);
       _renderView.attach();
       _renderView.rootConstraints = _createConstraints();
       _renderView.scheduleInitialFrame();
diff --git a/sky/packages/sky/lib/rendering/view.dart b/sky/packages/sky/lib/rendering/view.dart
index b1ede69..e835ce3 100644
--- a/sky/packages/sky/lib/rendering/view.dart
+++ b/sky/packages/sky/lib/rendering/view.dart
@@ -22,13 +22,11 @@
 class RenderView extends RenderObject with RenderObjectWithChildMixin<RenderBox> {
   RenderView({
     RenderBox child,
-    this.devicePixelRatio,
     this.timeForRotation: const Duration(microseconds: 83333)
   }) {
     this.child = child;
   }
 
-  final double devicePixelRatio;
   Duration timeForRotation;
 
   Size _size = Size.zero;
@@ -46,10 +44,14 @@
     markNeedsLayout();
   }
 
+  Matrix4 get _logicalToDeviceTransform {
+    double devicePixelRatio = sky.view.devicePixelRatio;
+    return new Matrix4.diagonal3Values(devicePixelRatio, devicePixelRatio, 1.0);
+  }
+
   void scheduleInitialFrame() {
-    Matrix4 logicalToDeviceZoom = new Matrix4.diagonal3Values(devicePixelRatio, devicePixelRatio, 1.0);
     scheduleInitialLayout();
-    scheduleInitialPaint(new TransformLayer(transform: logicalToDeviceZoom));
+    scheduleInitialPaint(new TransformLayer(transform: _logicalToDeviceTransform));
     scheduler.ensureVisualUpdate();
   }
 
@@ -98,6 +100,7 @@
   void compositeFrame() {
     sky.tracing.begin('RenderView.compositeFrame');
     try {
+      (layer as TransformLayer).transform = _logicalToDeviceTransform;
       Rect bounds = Point.origin & (size * sky.view.devicePixelRatio);
       sky.SceneBuilder builder = new sky.SceneBuilder(bounds);
       layer.addToScene(builder, Offset.zero);
diff --git a/sky/packages/sky/lib/widgets/framework.dart b/sky/packages/sky/lib/widgets/framework.dart
index 1e4ead3..9c4908d 100644
--- a/sky/packages/sky/lib/widgets/framework.dart
+++ b/sky/packages/sky/lib/widgets/framework.dart
@@ -97,10 +97,7 @@
     _syncedKeys.add(this);
   }
 
-  static bool _notifyingListeners = false;
-
   static void registerSyncListener(GlobalKey key, GlobalKeySyncListener listener) {
-    assert(!_notifyingListeners);
     assert(key != null);
     Set<GlobalKeySyncListener> listeners =
         _syncListeners.putIfAbsent(key, () => new Set<GlobalKeySyncListener>());
@@ -109,7 +106,6 @@
   }
 
   static void unregisterSyncListener(GlobalKey key, GlobalKeySyncListener listener) {
-    assert(!_notifyingListeners);
     assert(key != null);
     assert(_syncListeners.containsKey(key));
     bool removed = _syncListeners[key].remove(listener);
@@ -119,7 +115,6 @@
   }
 
   static void registerRemoveListener(GlobalKey key, GlobalKeyRemoveListener listener) {
-    assert(!_notifyingListeners);
     assert(key != null);
     Set<GlobalKeyRemoveListener> listeners =
         _removeListeners.putIfAbsent(key, () => new Set<GlobalKeyRemoveListener>());
@@ -128,7 +123,6 @@
   }
 
   static void unregisterRemoveListener(GlobalKey key, GlobalKeyRemoveListener listener) {
-    assert(!_notifyingListeners);
     assert(key != null);
     assert(_removeListeners.containsKey(key));
     bool removed = _removeListeners[key].remove(listener);
@@ -148,31 +142,27 @@
     assert(_debugDuplicates.isEmpty);
     if (_syncedKeys.isEmpty && _removedKeys.isEmpty)
       return;
-    _notifyingListeners = true;
     try {
-      Map<GlobalKey, Set<GlobalKeyRemoveListener>> localRemoveListeners =
-          new Map<GlobalKey, Set<GlobalKeyRemoveListener>>.from(_removeListeners);
-      Map<GlobalKey, Set<GlobalKeySyncListener>> localSyncListeners =
-          new Map<GlobalKey, Set<GlobalKeySyncListener>>.from(_syncListeners);
 
       for (GlobalKey key in _syncedKeys) {
         Widget widget = _registry[key];
-        if (widget != null && localSyncListeners.containsKey(key)) {
-          for (GlobalKeySyncListener listener in localSyncListeners[key])
+        if (widget != null && _syncListeners.containsKey(key)) {
+          Set<GlobalKeySyncListener> localListeners = new Set<GlobalKeySyncListener>.from(_syncListeners[key]);
+          for (GlobalKeySyncListener listener in localListeners)
             listener(key, widget);
         }
       }
 
       for (GlobalKey key in _removedKeys) {
-        if (!_registry.containsKey(key) && localRemoveListeners.containsKey(key)) {
-          for (GlobalKeyRemoveListener listener in localRemoveListeners[key])
+        if (!_registry.containsKey(key) && _removeListeners.containsKey(key)) {
+          Set<GlobalKeyRemoveListener> localListeners = new Set<GlobalKeyRemoveListener>.from(_removeListeners[key]);
+          for (GlobalKeyRemoveListener listener in localListeners)
             listener(key);
         }
       }
     } finally {
       _removedKeys.clear();
       _syncedKeys.clear();
-      _notifyingListeners = false;
     }
   }
 
diff --git a/sky/tools/webkitpy/layout_tests/run_webkit_tests.py b/sky/tools/webkitpy/layout_tests/run_webkit_tests.py
index ca0f257..52ad4f8 100644
--- a/sky/tools/webkitpy/layout_tests/run_webkit_tests.py
+++ b/sky/tools/webkitpy/layout_tests/run_webkit_tests.py
@@ -82,11 +82,7 @@
             gen_dash_board = GenerateDashBoard(port)
             gen_dash_board.generate()
 
-        if run_details.exit_code != 0:
-            return run_details.exit_code
-
-        analyzer_result = run_analyzer(port, options, args, stderr)
-        return analyzer_result
+        return run_details.exit_code
 
     # We need to still handle KeyboardInterrupt, atleast for webkitpy unittest cases.
     except KeyboardInterrupt:
@@ -391,23 +387,6 @@
     finally:
         printer.cleanup()
 
-def run_analyzer(port, options, args, logging_stream):
-    test_dir = os.path.dirname(os.path.abspath(__file__))
-    sky_tools_dir = os.path.dirname(os.path.dirname(test_dir))
-    analyzer_path = os.path.join(sky_tools_dir, 'skyanalyzer')
-    src_dir = os.path.dirname(os.path.dirname(sky_tools_dir))
-    analyzer_target_path = os.path.join(src_dir, 'examples/stocks/lib/main.dart')
-    analyzer_args = [
-        analyzer_path,
-        analyzer_target_path
-    ]
-    try:
-        output = subprocess.check_output(analyzer_args, stderr=subprocess.STDOUT)
-    except subprocess.CalledProcessError as e:
-        print >> logging_stream, "Analyzer found new issues:"
-        print >> logging_stream, e.output
-        return e.returncode
-    return 0
 
 if __name__ == '__main__':
     sys.exit(main(sys.argv[1:], sys.stdout, sys.stderr))
diff --git a/sky/unit/test/widget/global_key_test.dart b/sky/unit/test/widget/global_key_test.dart
index 18e1406..a410e05 100644
--- a/sky/unit/test/widget/global_key_test.dart
+++ b/sky/unit/test/widget/global_key_test.dart
@@ -106,4 +106,48 @@
     GlobalKey.unregisterSyncListener(globalKey, syncListener);
     GlobalKey.unregisterRemoveListener(globalKey, removeListener);
   });
+
+  test('Global key mutate during iteration', () {
+    GlobalKey globalKey = new GlobalKey();
+
+    bool syncListenerCalled = false;
+    bool removeListenerCalled = false;
+
+    void syncListener(GlobalKey key, Widget widget) {
+      GlobalKey.unregisterSyncListener(globalKey, syncListener);
+      syncListenerCalled = true;
+    }
+
+    void removeListener(GlobalKey key) {
+      GlobalKey.unregisterRemoveListener(globalKey, removeListener);
+      removeListenerCalled = true;
+    }
+
+    GlobalKey.registerSyncListener(globalKey, syncListener);
+    GlobalKey.registerRemoveListener(globalKey, removeListener);
+    WidgetTester tester = new WidgetTester();
+
+    tester.pumpFrame(() {
+      return new Container(key: globalKey);
+    });
+    expect(syncListenerCalled, isTrue);
+    expect(removeListenerCalled, isFalse);
+
+    syncListenerCalled = false;
+    removeListenerCalled = false;
+    tester.pumpFrame(() {
+      return new Container();
+    });
+    expect(syncListenerCalled, isFalse);
+    expect(removeListenerCalled, isTrue);
+
+    syncListenerCalled = false;
+    removeListenerCalled = false;
+    tester.pumpFrame(() {
+      return new Container(key: globalKey);
+    });
+    expect(syncListenerCalled, isFalse);
+    expect(removeListenerCalled, isFalse);
+
+  });
 }