Version 1.19.0-dev.3.0

Merge 59489091200e9739e8fcddcc0e5dfe63fef89a21 into dev
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 26425b5..3c62bf5 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,59 @@
+## 1.19.0
+
+### Tool Changes
+
+* `dartfmt` - upgraded to v0.2.9
+  * Support trailing commas in argument and parameter lists.
+  * Gracefully handle read-only files.
+  * About a dozen other bug fixes.
+
+* Pub
+  * Added the ability for packages to declare a constraint on the [Flutter][]
+    SDK:
+
+        environment:
+          flutter: ^0.1.2
+          sdk: >=1.19.0 <2.0.0
+
+    A Flutter constraint will only be satisfiable when pub is running in the
+    context of the `flutter` executable, and when the Flutter SDK version
+    matches the constraint.
+
+  * Added `sdk` as a new package source that fetches packages from a hard-coded
+    SDK. Currently only the `flutter` SDK is supported:
+
+        dependencies:
+          flutter_driver:
+            sdk: flutter
+            version: ^0.0.1
+
+    A Flutter `sdk` dependency will only be satisfiable when pub is running in
+    the context of the `flutter` executable, and when the Flutter SDK contains a
+    package with the given name whose version matches the constraint.
+
+  * Fixed a bug where packages from a hosted HTTP URL were considered the same
+    as packages from an otherwise-identical HTTPS URL.
+
+  * Fixed timer formatting for timers that lasted longer than a minute.
+
+  * Eliminate some false negatives when determining whether global executables
+    are on the user's executable path.
+
+[Flutter]: https://flutter.io/
+
+## 1.18.1 - 2016-08-02
+
+Patch release, resolves two issues and improves performance:
+
+* Debugger: Fixes a bug that crashes the VM
+(SDK issue [26941](https://github.com/dart-lang/sdk/issues/26941))
+
+* VM: Fixes an optimizer bug involving closures, try, and await
+(SDK issue [26948](https://github.com/dart-lang/sdk/issues/26948))
+
+* Dart2js: Speeds up generated code on Firefox
+(https://codereview.chromium.org/2180533002)
+
 ## 1.18.0 - 2016-07-27
 
 ### Core library changes
diff --git a/DEPS b/DEPS
index f7b6c5e..10ac7b8 100644
--- a/DEPS
+++ b/DEPS
@@ -35,8 +35,8 @@
   "buildtools_revision": "@565d04e8741429fb1b4f26d102f2c6c3b849edeb",
 
   # Revisions of /third_party/* dependencies.
-  "args_tag": "@0.13.4",
-  "async_tag": "@1.10.0",
+  "args_tag": "@0.13.5",
+  "async_tag": "@1.11.0",
   "barback-0.13.0_rev": "@34853",
   "barback-0.14.0_rev": "@36398",
   "barback-0.14.1_rev": "@38525",
@@ -54,7 +54,7 @@
   "csslib_tag" : "@0.12.0",
   "dart2js_info_rev" : "@0a221eaf16aec3879c45719de656680ccb80d8a1",
   "dart_services_rev" : "@7aea2574e6f3924bf409a80afb8ad52aa2be4f97",
-  "dart_style_tag": "@0.2.4",
+  "dart_style_tag": "@0.2.9",
   "dartdoc_tag" : "@v0.9.6+2",
   "dev_compiler_rev": "@9cc982b90f57c6132f648b0041c0b03bd23fcbfc",
   "fixnum_tag": "@0.10.5",
@@ -79,7 +79,7 @@
   "mime_rev": "@75890811d4af5af080351ba8a2853ad4c8df98dd",
   "mustache4dart_rev" : "@5724cfd85151e5b6b53ddcd3380daf188fe47f92",
   "oauth2_tag": "@1.0.0",
-  "observatory_pub_packages_rev": "@e5e1e543bea10d4bed95b22ad3e7aa2b20a23584",
+  "observatory_pub_packages_rev": "@a01235b5b71df27b602dae4676d0bf771cbe7fa2",
   "observe_rev": "@eee2b8ec34236fa46982575fbccff84f61202ac6",
   "package_config_rev": "@1.0.0",
   "path_tag": "@1.3.6",
@@ -88,8 +88,8 @@
   "pool_tag": "@1.2.1",
   "protobuf_tag": "@0.5.1+1",
   "pub_cache_tag": "@v0.1.0",
-  "pub_rev": "@488ab539770512a234f0a01b74882dcbb3f1a4da",
-  "pub_semver_tag": "@1.2.1",
+  "pub_rev": "@391b445dc6b28958794658b18caedb69d8cf8719",
+  "pub_semver_tag": "@1.3.0",
   "quiver_tag": "@0.21.4",
   "resource_rev":"@a49101ba2deb29c728acba6fb86000a8f730f4b1",
   "root_certificates_rev": "@aed07942ce98507d2be28cbd29e879525410c7fc",
@@ -103,7 +103,7 @@
   "source_maps_tag": "@0.10.1",
   "source_span_tag": "@1.2.0",
   "stack_trace_tag": "@1.4.2",
-  "stream_channel_tag": "@1.3.1",
+  "stream_channel_tag": "@1.5.0",
   "string_scanner_tag": "@0.1.4",
   "sunflower_rev": "@879b704933413414679396b129f5dfa96f7a0b1e",
   "test_reflective_loader_tag": "@0.0.3",
diff --git a/pkg/analysis_server/.analysis_options b/pkg/analysis_server/.analysis_options
index 7b230dd..49fda46 100644
--- a/pkg/analysis_server/.analysis_options
+++ b/pkg/analysis_server/.analysis_options
@@ -1,3 +1,5 @@
+analyzer:
+  strong-mode: true
 linter:
   rules:
     - unnecessary_brace_in_string_interp
diff --git a/pkg/analysis_server/lib/src/channel/byte_stream_channel.dart b/pkg/analysis_server/lib/src/channel/byte_stream_channel.dart
index ce6235d..c17b77b 100644
--- a/pkg/analysis_server/lib/src/channel/byte_stream_channel.dart
+++ b/pkg/analysis_server/lib/src/channel/byte_stream_channel.dart
@@ -51,10 +51,11 @@
   }
 
   @override
-  Future<Response> sendRequest(Request request) {
+  Future<Response> sendRequest(Request request) async {
     String id = request.id;
     output.write(JSON.encode(request.toJson()) + '\n');
-    return responseStream.firstWhere((Response response) => response.id == id);
+    return await responseStream
+        .firstWhere((Response response) => response.id == id);
   }
 }
 
diff --git a/pkg/analysis_server/lib/src/channel/web_socket_channel.dart b/pkg/analysis_server/lib/src/channel/web_socket_channel.dart
index 0368eb6..282b1f9 100644
--- a/pkg/analysis_server/lib/src/channel/web_socket_channel.dart
+++ b/pkg/analysis_server/lib/src/channel/web_socket_channel.dart
@@ -55,10 +55,11 @@
   }
 
   @override
-  Future<Response> sendRequest(Request request) {
+  Future<Response> sendRequest(Request request) async {
     String id = request.id;
     socket.add(JSON.encode(request.toJson()));
-    return responseStream.firstWhere((Response response) => response.id == id);
+    return await responseStream
+        .firstWhere((Response response) => response.id == id);
   }
 }
 
diff --git a/pkg/analysis_server/lib/src/services/index/index.dart b/pkg/analysis_server/lib/src/services/index/index.dart
index 7270ac2..aa06637 100644
--- a/pkg/analysis_server/lib/src/services/index/index.dart
+++ b/pkg/analysis_server/lib/src/services/index/index.dart
@@ -341,24 +341,39 @@
    * [element] is not referenced in the [index].
    */
   int findElementId(Element element) {
+    IndexElementInfo info = new IndexElementInfo(element);
+    element = info.element;
     // Find the id of the element's unit.
     int unitId = getUnitId(element);
     if (unitId == -1) {
       return -1;
     }
     // Prepare information about the element.
-    ElementInfo info = PackageIndexAssembler.newElementInfo(unitId, element);
-    // Find the first occurrence of an element with the same offset.
-    int elementId = _findFirstOccurrence(index.elementOffsets, info.offset);
+    int unitMemberId = getElementUnitMemberId(element);
+    if (unitMemberId == -1) {
+      return -1;
+    }
+    int classMemberId = getElementClassMemberId(element);
+    if (classMemberId == -1) {
+      return -1;
+    }
+    int parameterId = getElementParameterId(element);
+    if (parameterId == -1) {
+      return -1;
+    }
+    // Try to find the element id using classMemberId, parameterId, and kind.
+    int elementId =
+        _findFirstOccurrence(index.elementNameUnitMemberIds, unitMemberId);
     if (elementId == -1) {
       return -1;
     }
-    // Try to find the element id using offset, unit and kind.
     for (;
-        elementId < index.elementOffsets.length &&
-            index.elementOffsets[elementId] == info.offset;
+        elementId < index.elementNameUnitMemberIds.length &&
+            index.elementNameUnitMemberIds[elementId] == unitMemberId;
         elementId++) {
       if (index.elementUnits[elementId] == unitId &&
+          index.elementNameClassMemberIds[elementId] == classMemberId &&
+          index.elementNameParameterIds[elementId] == parameterId &&
           index.elementKinds[elementId] == info.kind) {
         return elementId;
       }
@@ -383,6 +398,45 @@
   }
 
   /**
+   * Return the [element]'s class member name identifier, `null` is not a class
+   * member, or `-1` if the [element] is not referenced in the [index].
+   */
+  int getElementClassMemberId(Element element) {
+    for (; element != null; element = element.enclosingElement) {
+      if (element.enclosingElement is ClassElement) {
+        return getStringId(element.name);
+      }
+    }
+    return getStringId(PackageIndexAssembler.NULL_STRING);
+  }
+
+  /**
+   * Return the [element]'s class member name identifier, `null` is not a class
+   * member, or `-1` if the [element] is not referenced in the [index].
+   */
+  int getElementParameterId(Element element) {
+    for (; element != null; element = element.enclosingElement) {
+      if (element is ParameterElement) {
+        return getStringId(element.name);
+      }
+    }
+    return getStringId(PackageIndexAssembler.NULL_STRING);
+  }
+
+  /**
+   * Return the [element]'s top-level name identifier, `0` is the unit, or
+   * `-1` if the [element] is not referenced in the [index].
+   */
+  int getElementUnitMemberId(Element element) {
+    for (; element != null; element = element.enclosingElement) {
+      if (element.enclosingElement is CompilationUnitElement) {
+        return getStringId(element.name);
+      }
+    }
+    return getStringId(PackageIndexAssembler.NULL_STRING);
+  }
+
+  /**
    * Complete with a list of locations where the given [element] has relation
    * of the given [kind].
    */
diff --git a/pkg/analysis_server/lib/src/services/search/search_engine_internal.dart b/pkg/analysis_server/lib/src/services/search/search_engine_internal.dart
index 47eb392..5b2b6e3 100644
--- a/pkg/analysis_server/lib/src/services/search/search_engine_internal.dart
+++ b/pkg/analysis_server/lib/src/services/search/search_engine_internal.dart
@@ -261,12 +261,10 @@
       ParameterElement parameter) async {
     List<SearchMatch> matches = <SearchMatch>[];
     matches.addAll(await _searchReferences(parameter));
-    matches.addAll(await _searchReferences_Local(
-        parameter,
-        (n) =>
-            n is ConstructorDeclaration ||
-            n is MethodDeclaration ||
-            n is FunctionExpression));
+    matches.addAll(await _searchReferences_Local(parameter, (AstNode node) {
+      AstNode parent = node.parent;
+      return parent is ClassDeclaration || parent is CompilationUnit;
+    }));
     return matches;
   }
 
@@ -408,7 +406,7 @@
   }
 
   void _addMatch(AstNode node, MatchKind kind) {
-    bool isQualified = node is SimpleIdentifier && node.isQualified;
+    bool isQualified = node.parent is Label;
     matches.add(new SearchMatch(context, libraryUri, unitUri, kind,
         rangeNode(node), true, isQualified));
   }
diff --git a/pkg/analysis_server/lib/src/source/caching_pub_package_map_provider.dart b/pkg/analysis_server/lib/src/source/caching_pub_package_map_provider.dart
index 3d99622..1997bff 100644
--- a/pkg/analysis_server/lib/src/source/caching_pub_package_map_provider.dart
+++ b/pkg/analysis_server/lib/src/source/caching_pub_package_map_provider.dart
@@ -106,7 +106,8 @@
     // Check for cached entry
     Map entry = _cache[folder.path];
     if (entry != null) {
-      Map<String, int> modificationStamps = entry[modificationStampsKey];
+      Map<String, int> modificationStamps =
+          entry[modificationStampsKey] as Map<String, int>;
       if (modificationStamps != null) {
         //
         // Check to see if any dependencies have changed
@@ -217,7 +218,7 @@
         TimestampedData<String> data = source.contents;
         Map map = JSON.decode(data.data);
         if (map[cacheVersionKey] == cacheVersion) {
-          _cache = map[cacheKey];
+          _cache = map[cacheKey] as Map<String, Map>;
           _cacheModificationTime = data.modificationTime;
         }
       } catch (exception, stackTrace) {
diff --git a/pkg/analysis_server/lib/src/status/get_handler.dart b/pkg/analysis_server/lib/src/status/get_handler.dart
index 13a149a..d9486dd 100644
--- a/pkg/analysis_server/lib/src/status/get_handler.dart
+++ b/pkg/analysis_server/lib/src/status/get_handler.dart
@@ -827,17 +827,17 @@
                 '<table style="border-collapse: separate; border-spacing: 10px 5px;">');
             _writeRow(buffer, ['Name', 'Count'], header: true);
             _writeRow(buffer, [
-              'Modified',
+              'Changed',
               PerformanceStatistics
-                  .cacheConsistencyValidationStatistics.numOfModified
+                  .cacheConsistencyValidationStatistics.numOfChanged
             ], classes: [
               null,
               "right"
             ]);
             _writeRow(buffer, [
-              'Deleted',
+              'Removed',
               PerformanceStatistics
-                  .cacheConsistencyValidationStatistics.numOfDeleted
+                  .cacheConsistencyValidationStatistics.numOfRemoved
             ], classes: [
               null,
               "right"
@@ -1415,8 +1415,6 @@
       _writeOption(
           buffer, 'Enable strict call checks', options.enableStrictCallChecks);
       _writeOption(buffer, 'Enable super mixins', options.enableSuperMixins);
-      _writeOption(
-          buffer, 'Enable trailing commas', options.enableTrailingCommas);
       _writeOption(buffer, 'Generate dart2js hints', options.dart2jsHint);
       _writeOption(buffer, 'Generate errors in implicit files',
           options.generateImplicitErrors);
diff --git a/pkg/analysis_server/test/services/refactoring/rename_class_member_test.dart b/pkg/analysis_server/test/services/refactoring/rename_class_member_test.dart
index cc09692..d35c631 100644
--- a/pkg/analysis_server/test/services/refactoring/rename_class_member_test.dart
+++ b/pkg/analysis_server/test/services/refactoring/rename_class_member_test.dart
@@ -6,6 +6,7 @@
 
 import 'package:analysis_server/plugin/protocol/protocol.dart';
 import 'package:analysis_server/src/services/correction/status.dart';
+import 'package:analyzer/src/generated/source.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 import 'package:unittest/unittest.dart';
 
@@ -265,15 +266,15 @@
         expectedContextSearch: 'test(); // marker');
   }
 
-  test_checkFinalConditions_shadowed_inSubClass() async {
+  test_checkFinalConditions_shadowedBySub_MethodElement() async {
     indexTestUnit('''
 class A {
-  newName() {} // marker
+  test() {}
 }
 class B extends A {
-  test() {}
+  newName() {} // marker
   main() {
-    newName();
+    test();
   }
 }
 ''');
@@ -282,11 +283,12 @@
     refactoring.newName = 'newName';
     RefactoringStatus status = await refactoring.checkFinalConditions();
     assertRefactoringStatus(status, RefactoringProblemSeverity.ERROR,
-        expectedMessage: "Renamed method will shadow method 'A.newName'.",
+        expectedMessage:
+            "Renamed method will be shadowed by method 'B.newName'.",
         expectedContextSearch: 'newName() {} // marker');
   }
 
-  test_checkFinalConditions_shadowsSuper_inSubClass_FieldElement() async {
+  test_checkFinalConditions_shadowsSuper_FieldElement() async {
     indexTestUnit('''
 class A {
   int newName; // marker
@@ -312,13 +314,10 @@
   test_checkFinalConditions_shadowsSuper_MethodElement() async {
     indexTestUnit('''
 class A {
-  test() {}
+  newName() {} // marker
 }
 class B extends A {
-  newName() {} // marker
-  main() {
-    test();
-  }
+  test() {}
 }
 ''');
     createRenameRefactoringAtString('test() {}');
@@ -326,11 +325,33 @@
     refactoring.newName = 'newName';
     RefactoringStatus status = await refactoring.checkFinalConditions();
     assertRefactoringStatus(status, RefactoringProblemSeverity.ERROR,
-        expectedMessage:
-            "Renamed method will be shadowed by method 'B.newName'.",
+        expectedMessage: "Renamed method will shadow method 'A.newName'.",
         expectedContextSearch: 'newName() {} // marker');
   }
 
+  test_checkFinalConditions_shadowsSuper_MethodElement_otherLib() async {
+    var libCode = r'''
+class A {
+  newName() {} // marker
+}
+''';
+    indexUnit('/lib.dart', libCode);
+    indexTestUnit('''
+import 'lib.dart';
+class B extends A {
+  test() {}
+}
+''');
+    createRenameRefactoringAtString('test() {}');
+    // check status
+    refactoring.newName = 'newName';
+    RefactoringStatus status = await refactoring.checkFinalConditions();
+    assertRefactoringStatus(status, RefactoringProblemSeverity.ERROR,
+        expectedMessage: "Renamed method will shadow method 'A.newName'.",
+        expectedContextRange: new SourceRange(
+            libCode.indexOf('newName() {} // marker'), 'newName'.length));
+  }
+
   test_checkInitialConditions_inSDK() async {
     indexTestUnit('''
 main() {
diff --git a/pkg/analyzer/.analysis_options b/pkg/analyzer/.analysis_options
index 2b11248..c952041 100644
--- a/pkg/analyzer/.analysis_options
+++ b/pkg/analyzer/.analysis_options
@@ -1,3 +1,5 @@
+analyzer:
+  strong-mode: true
 linter:
   rules:
     # TODO(pq): re-enable once we have a bulk edit tool
diff --git a/pkg/analyzer/lib/dart/ast/token.dart b/pkg/analyzer/lib/dart/ast/token.dart
index 14ba3f9..687111a 100644
--- a/pkg/analyzer/lib/dart/ast/token.dart
+++ b/pkg/analyzer/lib/dart/ast/token.dart
@@ -409,6 +409,9 @@
   static const TokenType AMPERSAND_AMPERSAND = const TokenType._(
       'AMPERSAND_AMPERSAND', TokenClass.LOGICAL_AND_OPERATOR, '&&');
 
+  static const TokenType AMPERSAND_AMPERSAND_EQ = const TokenType._(
+      'AMPERSAND_AMPERSAND_EQ', TokenClass.ASSIGNMENT_OPERATOR, '&&=');
+
   static const TokenType AMPERSAND_EQ =
       const TokenType._('AMPERSAND_EQ', TokenClass.ASSIGNMENT_OPERATOR, '&=');
 
@@ -426,6 +429,9 @@
   static const TokenType BAR_BAR =
       const TokenType._('BAR_BAR', TokenClass.LOGICAL_OR_OPERATOR, '||');
 
+  static const TokenType BAR_BAR_EQ =
+      const TokenType._('BAR_BAR_EQ', TokenClass.ASSIGNMENT_OPERATOR, '||=');
+
   static const TokenType BAR_EQ =
       const TokenType._('BAR_EQ', TokenClass.ASSIGNMENT_OPERATOR, '|=');
 
diff --git a/pkg/analyzer/lib/src/context/builder.dart b/pkg/analyzer/lib/src/context/builder.dart
index 3755353..377e9b1 100644
--- a/pkg/analyzer/lib/src/context/builder.dart
+++ b/pkg/analyzer/lib/src/context/builder.dart
@@ -147,6 +147,9 @@
     Map<String, List<Folder>> folderMap = new HashMap<String, List<Folder>>();
     packages.asMap().forEach((String packagePath, Uri uri) {
       String path = resourceProvider.pathContext.fromUri(uri);
+      if (path.endsWith(resourceProvider.pathContext.separator)) {
+        path = path.substring(0, path.length - 1);
+      }
       folderMap[packagePath] = [resourceProvider.getFolder(path)];
     });
     return folderMap;
@@ -284,7 +287,7 @@
           return embedderSdk;
         });
         return dartSdk;
-      } else if (extFilePaths != null) {
+      } else if (extFilePaths != null && extFilePaths.isNotEmpty) {
         //
         // We have an extension file, but no embedder file.
         //
diff --git a/pkg/analyzer/lib/src/context/cache.dart b/pkg/analyzer/lib/src/context/cache.dart
index efa8227..7b956a9 100644
--- a/pkg/analyzer/lib/src/context/cache.dart
+++ b/pkg/analyzer/lib/src/context/cache.dart
@@ -673,7 +673,7 @@
         deltaResult == DeltaResult.INVALIDATE_NO_DELTA) {
       _resultMap.remove(descriptor);
       // Stop depending on other results.
-      if (deltaResult != DeltaResult.KEEP_CONTINUE) {
+      {
         TargetedResult thisResult = new TargetedResult(target, descriptor);
         List<AnalysisCache> caches = _partition.containingCaches;
         int cacheLength = caches.length;
@@ -697,10 +697,6 @@
 //      if (deltaResult == null) {
 //        String indent = '  ' * level;
 //        print('[$id]$indent invalidate $descriptor for $target');
-//        if ('$descriptor for $target' ==
-//            'READY_LIBRARY_ELEMENT2 for /Users/scheglov/tmp/limited-invalidation/async/lib/async.dart') {
-//          print('interesting');
-//        }
 //      }
     }
     // Invalidate results that depend on this result.
@@ -714,8 +710,10 @@
       _partition._removeIfSource(target);
     }
     // Notify controller.
-    _partition.onResultInvalidated
-        .add(new InvalidatedResult(this, descriptor, thisData.value));
+    if (deltaResult != DeltaResult.KEEP_CONTINUE) {
+      _partition.onResultInvalidated
+          .add(new InvalidatedResult(this, descriptor, thisData.value));
+    }
   }
 
   /**
diff --git a/pkg/analyzer/lib/src/context/context.dart b/pkg/analyzer/lib/src/context/context.dart
index ca3eebc..fe33e3a 100644
--- a/pkg/analyzer/lib/src/context/context.dart
+++ b/pkg/analyzer/lib/src/context/context.dart
@@ -292,6 +292,9 @@
             ? this._options.implicitCasts != options.implicitCasts
             : false) ||
         ((options is AnalysisOptionsImpl)
+            ? this._options.nonnullableTypes != options.nonnullableTypes
+            : false) ||
+        ((options is AnalysisOptionsImpl)
             ? this._options.implicitDynamic != options.implicitDynamic
             : false) ||
         this._options.enableStrictCallChecks !=
@@ -326,6 +329,7 @@
     if (options is AnalysisOptionsImpl) {
       this._options.strongModeHints = options.strongModeHints;
       this._options.implicitCasts = options.implicitCasts;
+      this._options.nonnullableTypes = options.nonnullableTypes;
       this._options.implicitDynamic = options.implicitDynamic;
     }
     if (needsRecompute) {
@@ -2068,9 +2072,9 @@
 
   @override
   bool sourceModificationTimesComputed(List<Source> sources, List<int> times) {
-    int consistencyCheckStart = JavaSystem.nanoTime();
+    Stopwatch timer = new Stopwatch()..start();
     HashSet<Source> changedSources = new HashSet<Source>();
-    HashSet<Source> missingSources = new HashSet<Source>();
+    HashSet<Source> removedSources = new HashSet<Source>();
     for (int i = 0; i < sources.length; i++) {
       Source source = sources[i];
       // When a source is in the content cache,
@@ -2087,16 +2091,15 @@
       // Compare with the modification time in the cache entry.
       CacheEntry entry = context._privatePartition.get(source);
       if (entry != null) {
-        if (sourceTime != entry.modificationTime) {
-          changedSources.add(source);
-          PerformanceStatistics
-              .cacheConsistencyValidationStatistics.numOfModified++;
-        }
-        if (entry.exception != null) {
+        if (entry.modificationTime != sourceTime) {
           if (sourceTime == -1) {
-            missingSources.add(source);
+            removedSources.add(source);
             PerformanceStatistics
-                .cacheConsistencyValidationStatistics.numOfModified++;
+                .cacheConsistencyValidationStatistics.numOfRemoved++;
+          } else {
+            changedSources.add(source);
+            PerformanceStatistics
+                .cacheConsistencyValidationStatistics.numOfChanged++;
           }
         }
       }
@@ -2104,35 +2107,23 @@
     for (Source source in changedSources) {
       context._sourceChanged(source);
     }
-    int removalCount = 0;
-    for (Source source in missingSources) {
-      if (context.getLibrariesContaining(source).isEmpty &&
-          context.getLibrariesDependingOn(source).isEmpty) {
-        context._removeFromCache(source);
-        removalCount++;
-      }
+    for (Source source in removedSources) {
+      context._sourceRemoved(source);
     }
-    int consistencyCheckEnd = JavaSystem.nanoTime();
-    if (changedSources.length > 0 || missingSources.length > 0) {
+    if (changedSources.length > 0 || removedSources.length > 0) {
       StringBuffer buffer = new StringBuffer();
       buffer.write("Consistency check took ");
-      buffer.write((consistencyCheckEnd - consistencyCheckStart) / 1000000.0);
+      buffer.write(timer.elapsedMilliseconds);
       buffer.writeln(" ms and found");
       buffer.write("  ");
       buffer.write(changedSources.length);
-      buffer.writeln(" inconsistent entries");
+      buffer.writeln(" changed sources");
       buffer.write("  ");
-      buffer.write(missingSources.length);
-      buffer.write(" missing sources (");
-      buffer.write(removalCount);
-      buffer.writeln(" removed");
-      for (Source source in missingSources) {
-        buffer.write("    ");
-        buffer.writeln(source.fullName);
-      }
+      buffer.write(removedSources.length);
+      buffer.write(" removed sources.");
       context._logInformation(buffer.toString());
     }
-    return changedSources.length > 0;
+    return changedSources.isNotEmpty || removedSources.isNotEmpty;
   }
 }
 
diff --git a/pkg/analyzer/lib/src/dart/element/builder.dart b/pkg/analyzer/lib/src/dart/element/builder.dart
index 3b09bef..6eaaedb 100644
--- a/pkg/analyzer/lib/src/dart/element/builder.dart
+++ b/pkg/analyzer/lib/src/dart/element/builder.dart
@@ -976,7 +976,7 @@
         SimpleIdentifier propertyNameNode = node.name;
         String propertyName = propertyNameNode.name;
         FieldElementImpl field =
-            _currentHolder.getField(propertyName) as FieldElementImpl;
+            _currentHolder.getField(propertyName, synthetic: true) as FieldElementImpl;
         if (field == null) {
           field = new FieldElementImpl(node.name.name, -1);
           field.final2 = true;
diff --git a/pkg/analyzer/lib/src/dart/element/element.dart b/pkg/analyzer/lib/src/dart/element/element.dart
index 7743244..ddb414e 100644
--- a/pkg/analyzer/lib/src/dart/element/element.dart
+++ b/pkg/analyzer/lib/src/dart/element/element.dart
@@ -7336,7 +7336,7 @@
   DartType get type => setter.variable.type;
 
   @override
-  void set type(FunctionType type) {
+  void set type(DartType type) {
     assert(false); // Should never be called.
   }
 }
@@ -7656,7 +7656,7 @@
   }
 
   @override
-  DartType get type {
+  FunctionType get type {
     return _type ??= new FunctionTypeImpl(this);
   }
 
@@ -7699,7 +7699,7 @@
   }
 
   @override
-  DartType get type {
+  FunctionType get type {
     return _type ??= new FunctionTypeImpl(this);
   }
 
@@ -8260,20 +8260,20 @@
 abstract class UriReferencedElementImpl extends ElementImpl
     implements UriReferencedElement {
   /**
-   * The offset of the URI in the file, may be `-1` if synthetic.
+   * The offset of the URI in the file, or `-1` if this node is synthetic.
    */
-  int uriOffset = -1;
+  int _uriOffset = -1;
 
   /**
    * The offset of the character immediately following the last character of
-   * this node's URI, may be `-1` if synthetic.
+   * this node's URI, or `-1` if this node is synthetic.
    */
-  int uriEnd = -1;
+  int _uriEnd = -1;
 
   /**
    * The URI that is specified by this directive.
    */
-  String uri;
+  String _uri;
 
   /**
    * Initialize a newly created import element to have the given [name] and
@@ -8286,6 +8286,44 @@
    */
   UriReferencedElementImpl.forSerialized(ElementImpl enclosingElement)
       : super.forSerialized(enclosingElement);
+
+  /**
+   * Return the URI that is specified by this directive.
+   */
+  String get uri => _uri;
+
+  /**
+   * Set the URI that is specified by this directive to be the given [uri].
+   */
+  void set uri(String uri) {
+    _uri = uri;
+  }
+
+  /**
+   * Return the offset of the character immediately following the last character
+   * of this node's URI, or `-1` if this node is synthetic.
+   */
+  int get uriEnd => _uriEnd;
+
+  /**
+   * Set the offset of the character immediately following the last character of
+   * this node's URI to the given [offset].
+   */
+  void set uriEnd(int offset) {
+    _uriEnd = offset;
+  }
+
+  /**
+   * Return the offset of the URI in the file, or `-1` if this node is synthetic.
+   */
+  int get uriOffset => _uriOffset;
+
+  /**
+   * Set the offset of the URI in the file to the given [offset].
+   */
+  void set uriOffset(int offset) {
+    _uriOffset = offset;
+  }
 }
 
 /**
diff --git a/pkg/analyzer/lib/src/dart/scanner/scanner.dart b/pkg/analyzer/lib/src/dart/scanner/scanner.dart
index 7814eb7..0e60a90 100644
--- a/pkg/analyzer/lib/src/dart/scanner/scanner.dart
+++ b/pkg/analyzer/lib/src/dart/scanner/scanner.dart
@@ -10,6 +10,7 @@
 import 'package:analyzer/src/generated/error.dart';
 import 'package:analyzer/src/generated/java_engine.dart';
 import 'package:analyzer/src/generated/source.dart';
+import 'package:charcode/ascii.dart';
 
 /**
  * A state in a state machine used to scan keywords.
@@ -57,7 +58,7 @@
    * [character], or `null` if there is no valid state reachable from this state
    * with such a transition.
    */
-  KeywordState next(int character) => _table[character - 0x61];
+  KeywordState next(int character) => _table[character - $a];
 
   /**
    * Create the next state in the state machine where we have already recognized
@@ -69,7 +70,7 @@
       int start, List<String> strings, int offset, int length) {
     List<KeywordState> result = new List<KeywordState>(26);
     assert(length != 0);
-    int chunk = 0x0;
+    int chunk = $nul;
     int chunkStart = -1;
     bool isLeaf = false;
     for (int i = offset; i < offset + length; i++) {
@@ -80,7 +81,7 @@
         int c = strings[i].codeUnitAt(start);
         if (chunk != c) {
           if (chunkStart != -1) {
-            result[chunk - 0x61] = _computeKeywordStateTable(
+            result[chunk - $a] = _computeKeywordStateTable(
                 start + 1, strings, chunkStart, i - chunkStart);
           }
           chunkStart = i;
@@ -89,8 +90,8 @@
       }
     }
     if (chunkStart != -1) {
-      assert(result[chunk - 0x61] == null);
-      result[chunk - 0x61] = _computeKeywordStateTable(
+      assert(result[chunk - $a] == null);
+      result[chunk - $a] = _computeKeywordStateTable(
           start + 1, strings, chunkStart, offset + length - chunkStart);
     } else {
       assert(length == 1);
@@ -207,6 +208,12 @@
   bool scanGenericMethodComments = false;
 
   /**
+   * A flag indicating whether the lazy compound assignment operators '&&=' and
+   * '||=' are enabled.
+   */
+  bool scanLazyAssignmentOperators = false;
+
+  /**
    * Initialize a newly created scanner to scan characters from the given
    * [source]. The given character [_reader] will be used to read the characters
    * in the source. The given [_errorListener] will be informed of any errors
@@ -260,175 +267,175 @@
 
   int bigSwitch(int next) {
     _beginToken();
-    if (next == 0xD) {
+    if (next == $cr) {
       // '\r'
       next = _reader.advance();
-      if (next == 0xA) {
+      if (next == $lf) {
         // '\n'
         next = _reader.advance();
       }
       recordStartOfLine();
       return next;
-    } else if (next == 0xA) {
+    } else if (next == $lf) {
       // '\n'
       next = _reader.advance();
       recordStartOfLine();
       return next;
-    } else if (next == 0x9 || next == 0x20) {
+    } else if (next == $tab || next == $space) {
       // '\t' || ' '
       return _reader.advance();
     }
-    if (next == 0x72) {
+    if (next == $r) {
       // 'r'
       int peek = _reader.peek();
-      if (peek == 0x22 || peek == 0x27) {
+      if (peek == $double_quote || peek == $single_quote) {
         // '"' || "'"
         int start = _reader.offset;
         return _tokenizeString(_reader.advance(), start, true);
       }
     }
-    if (0x61 <= next && next <= 0x7A) {
+    if ($a <= next && next <= $z) {
       // 'a'-'z'
       return _tokenizeKeywordOrIdentifier(next, true);
     }
-    if ((0x41 <= next && next <= 0x5A) || next == 0x5F || next == 0x24) {
+    if (($A <= next && next <= $Z) || next == $_ || next == $$) {
       // 'A'-'Z' || '_' || '$'
       return _tokenizeIdentifier(next, _reader.offset, true);
     }
-    if (next == 0x3C) {
+    if (next == $lt) {
       // '<'
       return _tokenizeLessThan(next);
     }
-    if (next == 0x3E) {
+    if (next == $gt) {
       // '>'
       return _tokenizeGreaterThan(next);
     }
-    if (next == 0x3D) {
+    if (next == $equal) {
       // '='
       return _tokenizeEquals(next);
     }
-    if (next == 0x21) {
+    if (next == $exclamation) {
       // '!'
       return _tokenizeExclamation(next);
     }
-    if (next == 0x2B) {
+    if (next == $plus) {
       // '+'
       return _tokenizePlus(next);
     }
-    if (next == 0x2D) {
+    if (next == $minus) {
       // '-'
       return _tokenizeMinus(next);
     }
-    if (next == 0x2A) {
+    if (next == $asterisk) {
       // '*'
       return _tokenizeMultiply(next);
     }
-    if (next == 0x25) {
+    if (next == $percent) {
       // '%'
       return _tokenizePercent(next);
     }
-    if (next == 0x26) {
+    if (next == $ampersand) {
       // '&'
       return _tokenizeAmpersand(next);
     }
-    if (next == 0x7C) {
+    if (next == $bar) {
       // '|'
       return _tokenizeBar(next);
     }
-    if (next == 0x5E) {
+    if (next == $caret) {
       // '^'
       return _tokenizeCaret(next);
     }
-    if (next == 0x5B) {
+    if (next == $open_bracket) {
       // '['
       return _tokenizeOpenSquareBracket(next);
     }
-    if (next == 0x7E) {
+    if (next == $tilde) {
       // '~'
       return _tokenizeTilde(next);
     }
-    if (next == 0x5C) {
+    if (next == $backslash) {
       // '\\'
       _appendTokenOfType(TokenType.BACKSLASH);
       return _reader.advance();
     }
-    if (next == 0x23) {
+    if (next == $hash) {
       // '#'
       return _tokenizeTag(next);
     }
-    if (next == 0x28) {
+    if (next == $open_paren) {
       // '('
       _appendBeginToken(TokenType.OPEN_PAREN);
       return _reader.advance();
     }
-    if (next == 0x29) {
+    if (next == $close_paren) {
       // ')'
       _appendEndToken(TokenType.CLOSE_PAREN, TokenType.OPEN_PAREN);
       return _reader.advance();
     }
-    if (next == 0x2C) {
+    if (next == $comma) {
       // ','
       _appendTokenOfType(TokenType.COMMA);
       return _reader.advance();
     }
-    if (next == 0x3A) {
+    if (next == $colon) {
       // ':'
       _appendTokenOfType(TokenType.COLON);
       return _reader.advance();
     }
-    if (next == 0x3B) {
+    if (next == $semicolon) {
       // ';'
       _appendTokenOfType(TokenType.SEMICOLON);
       return _reader.advance();
     }
-    if (next == 0x3F) {
+    if (next == $question) {
       // '?'
       return _tokenizeQuestion();
     }
-    if (next == 0x5D) {
+    if (next == $close_bracket) {
       // ']'
       _appendEndToken(
           TokenType.CLOSE_SQUARE_BRACKET, TokenType.OPEN_SQUARE_BRACKET);
       return _reader.advance();
     }
-    if (next == 0x60) {
+    if (next == $backquote) {
       // '`'
       _appendTokenOfType(TokenType.BACKPING);
       return _reader.advance();
     }
-    if (next == 0x7B) {
+    if (next == $lbrace) {
       // '{'
       _appendBeginToken(TokenType.OPEN_CURLY_BRACKET);
       return _reader.advance();
     }
-    if (next == 0x7D) {
+    if (next == $rbrace) {
       // '}'
       _appendEndToken(
           TokenType.CLOSE_CURLY_BRACKET, TokenType.OPEN_CURLY_BRACKET);
       return _reader.advance();
     }
-    if (next == 0x2F) {
+    if (next == $slash) {
       // '/'
       return _tokenizeSlashOrComment(next);
     }
-    if (next == 0x40) {
+    if (next == $at) {
       // '@'
       _appendTokenOfType(TokenType.AT);
       return _reader.advance();
     }
-    if (next == 0x22 || next == 0x27) {
+    if (next == $double_quote || next == $single_quote) {
       // '"' || "'"
       return _tokenizeString(next, _reader.offset, false);
     }
-    if (next == 0x2E) {
+    if (next == $dot) {
       // '.'
       return _tokenizeDotOrNumber(next);
     }
-    if (next == 0x30) {
+    if (next == $0) {
       // '0'
       return _tokenizeHexOrNumber(next);
     }
-    if (0x31 <= next && next <= 0x39) {
+    if ($1 <= next && next <= $9) {
       // '1'-'9'
       return _tokenizeNumber(next);
     }
@@ -648,12 +655,12 @@
   TokenType _matchGenericMethodCommentType(String value) {
     if (scanGenericMethodComments) {
       // Match /*< and >*/
-      if (StringUtilities.startsWith3(value, 0, 0x2F, 0x2A, 0x3C) &&
-          StringUtilities.endsWith3(value, 0x3E, 0x2A, 0x2F)) {
+      if (StringUtilities.startsWith3(value, 0, $slash, $asterisk, $lt) &&
+          StringUtilities.endsWith3(value, $gt, $asterisk, $slash)) {
         return TokenType.GENERIC_METHOD_TYPE_LIST;
       }
       // Match /*=
-      if (StringUtilities.startsWith3(value, 0, 0x2F, 0x2A, 0x3D)) {
+      if (StringUtilities.startsWith3(value, 0, $slash, $asterisk, $equal)) {
         return TokenType.GENERIC_METHOD_TYPE_ASSIGN;
       }
     }
@@ -694,12 +701,17 @@
   }
 
   int _tokenizeAmpersand(int next) {
-    // && &= &
+    // &&= && &= &
     next = _reader.advance();
-    if (next == 0x26) {
+    if (next == $ampersand) {
+      next = _reader.advance();
+      if (scanLazyAssignmentOperators && next == $equal) {
+        _appendTokenOfType(TokenType.AMPERSAND_AMPERSAND_EQ);
+        return _reader.advance();
+      }
       _appendTokenOfType(TokenType.AMPERSAND_AMPERSAND);
-      return _reader.advance();
-    } else if (next == 0x3D) {
+      return next;
+    } else if (next == $equal) {
       _appendTokenOfType(TokenType.AMPERSAND_EQ);
       return _reader.advance();
     } else {
@@ -709,12 +721,17 @@
   }
 
   int _tokenizeBar(int next) {
-    // | || |=
+    // ||= || |= |
     next = _reader.advance();
-    if (next == 0x7C) {
+    if (next == $bar) {
+      next = _reader.advance();
+      if (scanLazyAssignmentOperators && next == $equal) {
+        _appendTokenOfType(TokenType.BAR_BAR_EQ);
+        return _reader.advance();
+      }
       _appendTokenOfType(TokenType.BAR_BAR);
-      return _reader.advance();
-    } else if (next == 0x3D) {
+      return next;
+    } else if (next == $equal) {
       _appendTokenOfType(TokenType.BAR_EQ);
       return _reader.advance();
     } else {
@@ -724,16 +741,16 @@
   }
 
   int _tokenizeCaret(int next) =>
-      _select(0x3D, TokenType.CARET_EQ, TokenType.CARET);
+      _select($equal, TokenType.CARET_EQ, TokenType.CARET);
 
   int _tokenizeDotOrNumber(int next) {
     int start = _reader.offset;
     next = _reader.advance();
-    if (0x30 <= next && next <= 0x39) {
+    if ($0 <= next && next <= $9) {
       return _tokenizeFractionPart(next, start);
-    } else if (0x2E == next) {
+    } else if ($dot == next) {
       return _select(
-          0x2E, TokenType.PERIOD_PERIOD_PERIOD, TokenType.PERIOD_PERIOD);
+          $dot, TokenType.PERIOD_PERIOD_PERIOD, TokenType.PERIOD_PERIOD);
     } else {
       _appendTokenOfType(TokenType.PERIOD);
       return next;
@@ -743,10 +760,10 @@
   int _tokenizeEquals(int next) {
     // = == =>
     next = _reader.advance();
-    if (next == 0x3D) {
+    if (next == $equal) {
       _appendTokenOfType(TokenType.EQ_EQ);
       return _reader.advance();
-    } else if (next == 0x3E) {
+    } else if (next == $gt) {
       _appendTokenOfType(TokenType.FUNCTION);
       return _reader.advance();
     }
@@ -757,7 +774,7 @@
   int _tokenizeExclamation(int next) {
     // ! !=
     next = _reader.advance();
-    if (next == 0x3D) {
+    if (next == $equal) {
       _appendTokenOfType(TokenType.BANG_EQ);
       return _reader.advance();
     }
@@ -766,12 +783,12 @@
   }
 
   int _tokenizeExponent(int next) {
-    if (next == 0x2B || next == 0x2D) {
+    if (next == $plus || next == $minus) {
       next = _reader.advance();
     }
     bool hasDigits = false;
     while (true) {
-      if (0x30 <= next && next <= 0x39) {
+      if ($0 <= next && next <= $9) {
         hasDigits = true;
       } else {
         if (!hasDigits) {
@@ -787,9 +804,9 @@
     bool done = false;
     bool hasDigit = false;
     LOOP: while (!done) {
-      if (0x30 <= next && next <= 0x39) {
+      if ($0 <= next && next <= $9) {
         hasDigit = true;
-      } else if (0x65 == next || 0x45 == next) {
+      } else if ($e == next || $E == next) {
         hasDigit = true;
         next = _tokenizeExponent(_reader.advance());
         done = true;
@@ -802,8 +819,8 @@
     }
     if (!hasDigit) {
       _appendStringToken(TokenType.INT, _reader.getString(start, -2));
-      if (0x2E == next) {
-        return _selectWithOffset(0x2E, TokenType.PERIOD_PERIOD_PERIOD,
+      if ($dot == next) {
+        return _selectWithOffset($dot, TokenType.PERIOD_PERIOD_PERIOD,
             TokenType.PERIOD_PERIOD, _reader.offset - 1);
       }
       _appendTokenOfTypeWithOffset(TokenType.PERIOD, _reader.offset - 1);
@@ -817,12 +834,12 @@
   int _tokenizeGreaterThan(int next) {
     // > >= >> >>=
     next = _reader.advance();
-    if (0x3D == next) {
+    if ($equal == next) {
       _appendTokenOfType(TokenType.GT_EQ);
       return _reader.advance();
-    } else if (0x3E == next) {
+    } else if ($gt == next) {
       next = _reader.advance();
-      if (0x3D == next) {
+      if ($equal == next) {
         _appendTokenOfType(TokenType.GT_GT_EQ);
         return _reader.advance();
       } else {
@@ -840,9 +857,9 @@
     bool hasDigits = false;
     while (true) {
       next = _reader.advance();
-      if ((0x30 <= next && next <= 0x39) ||
-          (0x41 <= next && next <= 0x46) ||
-          (0x61 <= next && next <= 0x66)) {
+      if (($0 <= next && next <= $9) ||
+          ($A <= next && next <= $F) ||
+          ($a <= next && next <= $f)) {
         hasDigits = true;
       } else {
         if (!hasDigits) {
@@ -857,7 +874,7 @@
 
   int _tokenizeHexOrNumber(int next) {
     int x = _reader.peek();
-    if (x == 0x78 || x == 0x58) {
+    if (x == $x || x == $X) {
       _reader.advance();
       return _tokenizeHex(x);
     }
@@ -865,11 +882,11 @@
   }
 
   int _tokenizeIdentifier(int next, int start, bool allowDollar) {
-    while ((0x61 <= next && next <= 0x7A) ||
-        (0x41 <= next && next <= 0x5A) ||
-        (0x30 <= next && next <= 0x39) ||
-        next == 0x5F ||
-        (next == 0x24 && allowDollar)) {
+    while (($a <= next && next <= $z) ||
+        ($A <= next && next <= $Z) ||
+        ($0 <= next && next <= $9) ||
+        next == $_ ||
+        (next == $$ && allowDollar)) {
       next = _reader.advance();
     }
     _appendStringToken(
@@ -881,7 +898,7 @@
     _appendBeginToken(TokenType.STRING_INTERPOLATION_EXPRESSION);
     next = _reader.advance();
     while (next != -1) {
-      if (next == 0x7D) {
+      if (next == $rbrace) {
         BeginToken begin =
             _findTokenMatchingClosingBraceInInterpolationExpression();
         if (begin == null) {
@@ -914,9 +931,9 @@
   int _tokenizeInterpolatedIdentifier(int next, int start) {
     _appendStringTokenWithOffset(
         TokenType.STRING_INTERPOLATION_IDENTIFIER, "\$", 0);
-    if ((0x41 <= next && next <= 0x5A) ||
-        (0x61 <= next && next <= 0x7A) ||
-        next == 0x5F) {
+    if (($A <= next && next <= $Z) ||
+        ($a <= next && next <= $z) ||
+        next == $_) {
       _beginToken();
       next = _tokenizeKeywordOrIdentifier(next, false);
     }
@@ -927,17 +944,17 @@
   int _tokenizeKeywordOrIdentifier(int next, bool allowDollar) {
     KeywordState state = KeywordState.KEYWORD_STATE;
     int start = _reader.offset;
-    while (state != null && 0x61 <= next && next <= 0x7A) {
+    while (state != null && $a <= next && next <= $z) {
       state = state.next(next);
       next = _reader.advance();
     }
     if (state == null || state.keyword() == null) {
       return _tokenizeIdentifier(next, start, allowDollar);
     }
-    if ((0x41 <= next && next <= 0x5A) ||
-        (0x30 <= next && next <= 0x39) ||
-        next == 0x5F ||
-        next == 0x24) {
+    if (($A <= next && next <= $Z) ||
+        ($0 <= next && next <= $9) ||
+        next == $_ ||
+        next == $$) {
       return _tokenizeIdentifier(next, start, allowDollar);
     } else if (next < 128) {
       _appendKeywordToken(state.keyword());
@@ -950,11 +967,11 @@
   int _tokenizeLessThan(int next) {
     // < <= << <<=
     next = _reader.advance();
-    if (0x3D == next) {
+    if ($equal == next) {
       _appendTokenOfType(TokenType.LT_EQ);
       return _reader.advance();
-    } else if (0x3C == next) {
-      return _select(0x3D, TokenType.LT_LT_EQ, TokenType.LT_LT);
+    } else if ($lt == next) {
+      return _select($equal, TokenType.LT_LT_EQ, TokenType.LT_LT);
     } else {
       _appendTokenOfType(TokenType.LT);
       return next;
@@ -964,10 +981,10 @@
   int _tokenizeMinus(int next) {
     // - -- -=
     next = _reader.advance();
-    if (next == 0x2D) {
+    if (next == $minus) {
       _appendTokenOfType(TokenType.MINUS_MINUS);
       return _reader.advance();
-    } else if (next == 0x3D) {
+    } else if (next == $equal) {
       _appendTokenOfType(TokenType.MINUS_EQ);
       return _reader.advance();
     } else {
@@ -985,9 +1002,9 @@
         _appendCommentToken(
             TokenType.MULTI_LINE_COMMENT, _reader.getString(_tokenStart, 0));
         return next;
-      } else if (0x2A == next) {
+      } else if ($asterisk == next) {
         next = _reader.advance();
-        if (0x2F == next) {
+        if ($slash == next) {
           --nesting;
           if (0 == nesting) {
             _appendCommentToken(TokenType.MULTI_LINE_COMMENT,
@@ -997,19 +1014,19 @@
             next = _reader.advance();
           }
         }
-      } else if (0x2F == next) {
+      } else if ($slash == next) {
         next = _reader.advance();
-        if (0x2A == next) {
+        if ($asterisk == next) {
           next = _reader.advance();
           ++nesting;
         }
-      } else if (next == 0xD) {
+      } else if (next == $cr) {
         next = _reader.advance();
-        if (next == 0xA) {
+        if (next == $lf) {
           next = _reader.advance();
         }
         recordStartOfLine();
-      } else if (next == 0xA) {
+      } else if (next == $lf) {
         next = _reader.advance();
         recordStartOfLine();
       } else {
@@ -1024,13 +1041,13 @@
       while (next != quoteChar) {
         if (next == -1) {
           break outer;
-        } else if (next == 0xD) {
+        } else if (next == $cr) {
           next = _reader.advance();
-          if (next == 0xA) {
+          if (next == $lf) {
             next = _reader.advance();
           }
           recordStartOfLine();
-        } else if (next == 0xA) {
+        } else if (next == $lf) {
           next = _reader.advance();
           recordStartOfLine();
         } else {
@@ -1057,7 +1074,7 @@
     }
     int next = _reader.advance();
     while (next != -1) {
-      if (next == 0x24) {
+      if (next == $$) {
         _appendStringToken(TokenType.STRING, _reader.getString(start, -1));
         next = _tokenizeStringInterpolation(start);
         _beginToken();
@@ -1075,30 +1092,30 @@
         }
         continue;
       }
-      if (next == 0x5C) {
+      if (next == $backslash) {
         next = _reader.advance();
         if (next == -1) {
           break;
         }
-        if (next == 0xD) {
+        if (next == $cr) {
           next = _reader.advance();
-          if (next == 0xA) {
+          if (next == $lf) {
             next = _reader.advance();
           }
           recordStartOfLine();
-        } else if (next == 0xA) {
+        } else if (next == $lf) {
           recordStartOfLine();
           next = _reader.advance();
         } else {
           next = _reader.advance();
         }
-      } else if (next == 0xD) {
+      } else if (next == $cr) {
         next = _reader.advance();
-        if (next == 0xA) {
+        if (next == $lf) {
           next = _reader.advance();
         }
         recordStartOfLine();
-      } else if (next == 0xA) {
+      } else if (next == $lf) {
         recordStartOfLine();
         next = _reader.advance();
       } else {
@@ -1115,17 +1132,17 @@
   }
 
   int _tokenizeMultiply(int next) =>
-      _select(0x3D, TokenType.STAR_EQ, TokenType.STAR);
+      _select($equal, TokenType.STAR_EQ, TokenType.STAR);
 
   int _tokenizeNumber(int next) {
     int start = _reader.offset;
     while (true) {
       next = _reader.advance();
-      if (0x30 <= next && next <= 0x39) {
+      if ($0 <= next && next <= $9) {
         continue;
-      } else if (next == 0x2E) {
+      } else if (next == $dot) {
         return _tokenizeFractionPart(_reader.advance(), start);
-      } else if (next == 0x65 || next == 0x45) {
+      } else if (next == $e || next == $E) {
         return _tokenizeFractionPart(next, start);
       } else {
         _appendStringToken(
@@ -1138,8 +1155,8 @@
   int _tokenizeOpenSquareBracket(int next) {
     // [ []  []=
     next = _reader.advance();
-    if (next == 0x5D) {
-      return _select(0x3D, TokenType.INDEX_EQ, TokenType.INDEX);
+    if (next == $close_bracket) {
+      return _select($equal, TokenType.INDEX_EQ, TokenType.INDEX);
     } else {
       _appendBeginToken(TokenType.OPEN_SQUARE_BRACKET);
       return next;
@@ -1147,15 +1164,15 @@
   }
 
   int _tokenizePercent(int next) =>
-      _select(0x3D, TokenType.PERCENT_EQ, TokenType.PERCENT);
+      _select($equal, TokenType.PERCENT_EQ, TokenType.PERCENT);
 
   int _tokenizePlus(int next) {
     // + ++ +=
     next = _reader.advance();
-    if (0x2B == next) {
+    if ($plus == next) {
       _appendTokenOfType(TokenType.PLUS_PLUS);
       return _reader.advance();
-    } else if (0x3D == next) {
+    } else if ($equal == next) {
       _appendTokenOfType(TokenType.PLUS_EQ);
       return _reader.advance();
     } else {
@@ -1167,14 +1184,14 @@
   int _tokenizeQuestion() {
     // ? ?. ?? ??=
     int next = _reader.advance();
-    if (next == 0x2E) {
+    if (next == $dot) {
       // '.'
       _appendTokenOfType(TokenType.QUESTION_PERIOD);
       return _reader.advance();
-    } else if (next == 0x3F) {
+    } else if (next == $question) {
       // '?'
       next = _reader.advance();
-      if (next == 0x3D) {
+      if (next == $equal) {
         // '='
         _appendTokenOfType(TokenType.QUESTION_QUESTION_EQ);
         return _reader.advance();
@@ -1195,7 +1212,7 @@
         _appendCommentToken(
             TokenType.SINGLE_LINE_COMMENT, _reader.getString(_tokenStart, 0));
         return next;
-      } else if (0xA == next || 0xD == next) {
+      } else if ($lf == next || $cr == next) {
         _appendCommentToken(
             TokenType.SINGLE_LINE_COMMENT, _reader.getString(_tokenStart, -1));
         return next;
@@ -1209,7 +1226,7 @@
       if (next == quoteChar) {
         _appendStringToken(TokenType.STRING, _reader.getString(start, 0));
         return _reader.advance();
-      } else if (next == 0xD || next == 0xA) {
+      } else if (next == $cr || next == $lf) {
         _reportError(ScannerErrorCode.UNTERMINATED_STRING_LITERAL);
         _appendStringToken(TokenType.STRING, _reader.getString(start, -1));
         return _reader.advance();
@@ -1223,16 +1240,16 @@
 
   int _tokenizeSingleLineString(int next, int quoteChar, int start) {
     while (next != quoteChar) {
-      if (next == 0x5C) {
+      if (next == $backslash) {
         next = _reader.advance();
-      } else if (next == 0x24) {
+      } else if (next == $$) {
         _appendStringToken(TokenType.STRING, _reader.getString(start, -1));
         next = _tokenizeStringInterpolation(start);
         _beginToken();
         start = _reader.offset;
         continue;
       }
-      if (next <= 0xD && (next == 0xA || next == 0xD || next == -1)) {
+      if (next <= $cr && (next == $lf || next == $cr || next == -1)) {
         _reportError(ScannerErrorCode.UNTERMINATED_STRING_LITERAL);
         if (start == _reader.offset) {
           _appendStringTokenWithOffset(TokenType.STRING, "", 1);
@@ -1251,11 +1268,11 @@
 
   int _tokenizeSlashOrComment(int next) {
     next = _reader.advance();
-    if (0x2A == next) {
+    if ($asterisk == next) {
       return _tokenizeMultiLineComment(next);
-    } else if (0x2F == next) {
+    } else if ($slash == next) {
       return _tokenizeSingleLineComment(next);
-    } else if (0x3D == next) {
+    } else if ($equal == next) {
       _appendTokenOfType(TokenType.SLASH_EQ);
       return _reader.advance();
     } else {
@@ -1288,7 +1305,7 @@
   int _tokenizeStringInterpolation(int start) {
     _beginToken();
     int next = _reader.advance();
-    if (next == 0x7B) {
+    if (next == $lbrace) {
       return _tokenizeInterpolatedExpression(next, start);
     } else {
       return _tokenizeInterpolatedIdentifier(next, start);
@@ -1298,10 +1315,10 @@
   int _tokenizeTag(int next) {
     // # or #!.*[\n\r]
     if (_reader.offset == 0) {
-      if (_reader.peek() == 0x21) {
+      if (_reader.peek() == $exclamation) {
         do {
           next = _reader.advance();
-        } while (next != 0xA && next != 0xD && next > 0);
+        } while (next != $lf && next != $cr && next > 0);
         _appendStringToken(
             TokenType.SCRIPT_TAG, _reader.getString(_tokenStart, 0));
         return next;
@@ -1314,8 +1331,8 @@
   int _tokenizeTilde(int next) {
     // ~ ~/ ~/=
     next = _reader.advance();
-    if (next == 0x2F) {
-      return _select(0x3D, TokenType.TILDE_SLASH_EQ, TokenType.TILDE_SLASH);
+    if (next == $slash) {
+      return _select($equal, TokenType.TILDE_SLASH_EQ, TokenType.TILDE_SLASH);
     } else {
       _appendTokenOfType(TokenType.TILDE);
       return next;
@@ -1326,8 +1343,8 @@
    * Checks if [value] is a single-line or multi-line comment.
    */
   static bool _isDocumentationComment(String value) {
-    return StringUtilities.startsWith3(value, 0, 0x2F, 0x2F, 0x2F) ||
-        StringUtilities.startsWith3(value, 0, 0x2F, 0x2A, 0x2A);
+    return StringUtilities.startsWith3(value, 0, $slash, $slash, $slash) ||
+        StringUtilities.startsWith3(value, 0, $slash, $asterisk, $asterisk);
   }
 }
 
diff --git a/pkg/analyzer/lib/src/dart/sdk/sdk.dart b/pkg/analyzer/lib/src/dart/sdk/sdk.dart
new file mode 100644
index 0000000..338a560
--- /dev/null
+++ b/pkg/analyzer/lib/src/dart/sdk/sdk.dart
@@ -0,0 +1,708 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library analyzer.src.generated.sdk2;
+
+import 'dart:collection';
+import 'dart:io' as io;
+
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/file_system/file_system.dart';
+import 'package:analyzer/src/context/context.dart';
+import 'package:analyzer/src/dart/scanner/reader.dart';
+import 'package:analyzer/src/dart/scanner/scanner.dart';
+import 'package:analyzer/src/generated/engine.dart';
+import 'package:analyzer/src/generated/error.dart';
+import 'package:analyzer/src/generated/java_core.dart';
+import 'package:analyzer/src/generated/java_engine.dart';
+import 'package:analyzer/src/generated/java_engine_io.dart';
+import 'package:analyzer/src/generated/parser.dart';
+import 'package:analyzer/src/generated/sdk.dart';
+import 'package:analyzer/src/generated/source_io.dart';
+import 'package:analyzer/src/summary/idl.dart' show PackageBundle;
+import 'package:analyzer/src/summary/summary_sdk.dart';
+import 'package:path/path.dart' as pathos;
+import 'package:yaml/yaml.dart';
+
+/**
+ * An abstract implementation of a Dart SDK in which the available libraries are
+ * stored in a library map. Subclasses are responsible for populating the
+ * library map.
+ */
+abstract class AbstractDartSdk implements DartSdk {
+  /**
+   * The resource provider used to access the file system.
+   */
+  ResourceProvider resourceProvider;
+
+  /**
+   * A mapping from Dart library URI's to the library represented by that URI.
+   */
+  LibraryMap libraryMap = new LibraryMap();
+
+  /**
+   * The [AnalysisOptions] to use to create the [context].
+   */
+  AnalysisOptions _analysisOptions;
+
+  /**
+   * The flag that specifies whether an SDK summary should be used. This is a
+   * temporary flag until summaries are enabled by default.
+   */
+  bool _useSummary = false;
+
+  /**
+   * The [AnalysisContext] which is used for all of the sources in this SDK.
+   */
+  InternalAnalysisContext _analysisContext;
+
+  /**
+   * The mapping from Dart URI's to the corresponding sources.
+   */
+  Map<String, Source> _uriToSourceMap = new HashMap<String, Source>();
+
+  /**
+   * Set the [options] for this SDK analysis context.  Throw [StateError] if the
+   * context has been already created.
+   */
+  void set analysisOptions(AnalysisOptions options) {
+    if (_analysisContext != null) {
+      throw new StateError(
+          'Analysis options cannot be changed after context creation.');
+    }
+    _analysisOptions = options;
+  }
+
+  @override
+  AnalysisContext get context {
+    if (_analysisContext == null) {
+      _analysisContext = new SdkAnalysisContext(_analysisOptions);
+      SourceFactory factory = new SourceFactory([new DartUriResolver(this)]);
+      _analysisContext.sourceFactory = factory;
+      if (_useSummary) {
+        bool strongMode = _analysisOptions?.strongMode ?? false;
+        PackageBundle sdkBundle = getSummarySdkBundle(strongMode);
+        if (sdkBundle != null) {
+          _analysisContext.resultProvider = new SdkSummaryResultProvider(
+              _analysisContext, sdkBundle, strongMode);
+        }
+      }
+    }
+    return _analysisContext;
+  }
+
+  @override
+  List<SdkLibrary> get sdkLibraries => libraryMap.sdkLibraries;
+
+  /**
+   * Return the path separator used by the resource provider.
+   */
+  String get separator => resourceProvider.pathContext.separator;
+
+  @override
+  List<String> get uris => libraryMap.uris;
+
+  /**
+   * Return `true` if the SDK summary will be used when available.
+   */
+  bool get useSummary => _useSummary;
+
+  /**
+   * Specify whether SDK summary should be used.
+   */
+  void set useSummary(bool use) {
+    if (_analysisContext != null) {
+      throw new StateError(
+          'The "useSummary" flag cannot be changed after context creation.');
+    }
+    _useSummary = use;
+  }
+
+  @override
+  Source fromFileUri(Uri uri) {
+    File file =
+        resourceProvider.getFile(resourceProvider.pathContext.fromUri(uri));
+    String path = _getPath(file);
+    if (path == null) {
+      return null;
+    }
+    try {
+      return file.createSource(parseUriWithException(path));
+    } on URISyntaxException catch (exception, stackTrace) {
+      AnalysisEngine.instance.logger.logInformation(
+          "Failed to create URI: $path",
+          new CaughtException(exception, stackTrace));
+    }
+    return null;
+  }
+
+  String getRelativePathFromFile(File file);
+
+  @override
+  SdkLibrary getSdkLibrary(String dartUri) => libraryMap.getLibrary(dartUri);
+
+  /**
+   * Return the [PackageBundle] for this SDK, if it exists, or `null` otherwise.
+   * This method should not be used outside of `analyzer` and `analyzer_cli`
+   * packages.
+   */
+  PackageBundle getSummarySdkBundle(bool strongMode);
+
+  Source internalMapDartUri(String dartUri) {
+    // TODO(brianwilkerson) Figure out how to unify the implementations in the
+    // two subclasses.
+    String libraryName;
+    String relativePath;
+    int index = dartUri.indexOf('/');
+    if (index >= 0) {
+      libraryName = dartUri.substring(0, index);
+      relativePath = dartUri.substring(index + 1);
+    } else {
+      libraryName = dartUri;
+      relativePath = "";
+    }
+    SdkLibrary library = getSdkLibrary(libraryName);
+    if (library == null) {
+      return null;
+    }
+    String srcPath;
+    if (relativePath.isEmpty) {
+      srcPath = library.path;
+    } else {
+      String libraryPath = library.path;
+      int index = libraryPath.lastIndexOf(separator);
+      if (index == -1) {
+        index = libraryPath.lastIndexOf('/');
+        if (index == -1) {
+          return null;
+        }
+      }
+      String prefix = libraryPath.substring(0, index + 1);
+      srcPath = '$prefix$relativePath';
+    }
+    String filePath = srcPath.replaceAll('/', separator);
+    try {
+      File file = resourceProvider.getFile(filePath);
+      return file.createSource(parseUriWithException(dartUri));
+    } on URISyntaxException {
+      return null;
+    }
+  }
+
+  @override
+  Source mapDartUri(String dartUri) {
+    Source source = _uriToSourceMap[dartUri];
+    if (source == null) {
+      source = internalMapDartUri(dartUri);
+      _uriToSourceMap[dartUri] = source;
+    }
+    return source;
+  }
+
+  String _getPath(File file) {
+    List<SdkLibrary> libraries = libraryMap.sdkLibraries;
+    int length = libraries.length;
+    List<String> paths = new List(length);
+    String filePath = getRelativePathFromFile(file);
+    if (filePath == null) {
+      return null;
+    }
+    for (int i = 0; i < length; i++) {
+      SdkLibrary library = libraries[i];
+      String libraryPath = library.path.replaceAll('/', separator);
+      if (filePath == libraryPath) {
+        return library.shortName;
+      }
+      paths[i] = libraryPath;
+    }
+    for (int i = 0; i < length; i++) {
+      SdkLibrary library = libraries[i];
+      String libraryPath = paths[i];
+      int index = libraryPath.lastIndexOf(separator);
+      if (index >= 0) {
+        String prefix = libraryPath.substring(0, index + 1);
+        if (filePath.startsWith(prefix)) {
+          String relPath =
+              filePath.substring(prefix.length).replaceAll(separator, '/');
+          return '${library.shortName}/$relPath';
+        }
+      }
+    }
+    return null;
+  }
+}
+
+/**
+ * An SDK backed by URI mappings derived from an `_embedder.yaml` file.
+ */
+class EmbedderSdk extends AbstractDartSdk {
+  static const String _DART_COLON_PREFIX = 'dart:';
+
+  static const String _EMBEDDED_LIB_MAP_KEY = 'embedded_libs';
+  final Map<String, String> _urlMappings = new HashMap<String, String>();
+
+  EmbedderSdk(
+      ResourceProvider resourceProvider, Map<Folder, YamlMap> embedderYamls) {
+    this.resourceProvider = resourceProvider;
+    embedderYamls?.forEach(_processEmbedderYaml);
+  }
+
+  @override
+  // TODO(danrubel) Determine SDK version
+  String get sdkVersion => '0';
+
+  /**
+   * The url mappings for this SDK.
+   */
+  Map<String, String> get urlMappings => _urlMappings;
+
+  @override
+  String getRelativePathFromFile(File file) => file.path;
+
+  @override
+  PackageBundle getSummarySdkBundle(bool strongMode) => null;
+
+  @override
+  Source internalMapDartUri(String dartUri) {
+    String libraryName;
+    String relativePath;
+    int index = dartUri.indexOf('/');
+    if (index >= 0) {
+      libraryName = dartUri.substring(0, index);
+      relativePath = dartUri.substring(index + 1);
+    } else {
+      libraryName = dartUri;
+      relativePath = "";
+    }
+    SdkLibrary library = getSdkLibrary(libraryName);
+    if (library == null) {
+      return null;
+    }
+    String srcPath;
+    if (relativePath.isEmpty) {
+      srcPath = library.path;
+    } else {
+      String libraryPath = library.path;
+      int index =
+          libraryPath.lastIndexOf(resourceProvider.pathContext.separator);
+      if (index == -1) {
+        index = libraryPath.lastIndexOf('/');
+        if (index == -1) {
+          return null;
+        }
+      }
+      String prefix = libraryPath.substring(0, index + 1);
+      srcPath = '$prefix$relativePath';
+    }
+    String filePath =
+        srcPath.replaceAll('/', resourceProvider.pathContext.separator);
+    try {
+      File file = resourceProvider.getFile(filePath);
+      return file.createSource(parseUriWithException(dartUri));
+    } on URISyntaxException {
+      return null;
+    }
+  }
+
+  /**
+   * Install the mapping from [name] to [libDir]/[file].
+   */
+  void _processEmbeddedLibs(String name, String file, Folder libDir) {
+    if (!name.startsWith(_DART_COLON_PREFIX)) {
+      // SDK libraries must begin with 'dart:'.
+      return;
+    }
+    String libPath = libDir.canonicalizePath(file);
+    _urlMappings[name] = libPath;
+    SdkLibraryImpl library = new SdkLibraryImpl(name);
+    library.path = libPath;
+    libraryMap.setLibrary(name, library);
+  }
+
+  /**
+   * Given the 'embedderYamls' from [EmbedderYamlLocator] check each one for the
+   * top level key 'embedded_libs'. Under the 'embedded_libs' key are key value
+   * pairs. Each key is a 'dart:' library uri and each value is a path
+   * (relative to the directory containing `_embedder.yaml`) to a dart script
+   * for the given library. For example:
+   *
+   * embedded_libs:
+   *   'dart:io': '../../sdk/io/io.dart'
+   *
+   * If a key doesn't begin with `dart:` it is ignored.
+   */
+  void _processEmbedderYaml(Folder libDir, YamlMap map) {
+    YamlNode embedded_libs = map[_EMBEDDED_LIB_MAP_KEY];
+    if (embedded_libs is YamlMap) {
+      embedded_libs.forEach((k, v) => _processEmbeddedLibs(k, v, libDir));
+    }
+  }
+}
+
+/**
+ * A Dart SDK installed in a specified directory. Typical Dart SDK layout is
+ * something like...
+ *
+ *     dart-sdk/
+ *        bin/
+ *           dart[.exe]  <-- VM
+ *        lib/
+ *           core/
+ *              core.dart
+ *              ... other core library files ...
+ *           ... other libraries ...
+ *        util/
+ *           ... Dart utilities ...
+ *     Chromium/   <-- Dartium typically exists in a sibling directory
+ */
+class FolderBasedDartSdk extends AbstractDartSdk {
+  /**
+   * The name of the directory within the SDK directory that contains
+   * executables.
+   */
+  static String _BIN_DIRECTORY_NAME = "bin";
+
+  /**
+   * The name of the directory within the SDK directory that contains
+   * documentation for the libraries.
+   */
+  static String _DOCS_DIRECTORY_NAME = "docs";
+
+  /**
+   * The name of the directory within the SDK directory that contains the
+   * sdk_library_metadata directory.
+   */
+  static String _INTERNAL_DIR = "_internal";
+
+  /**
+   * The name of the sdk_library_metadata directory that contains the package
+   * holding the libraries.dart file.
+   */
+  static String _SDK_LIBRARY_METADATA_DIR = "sdk_library_metadata";
+
+  /**
+   * The name of the directory within the sdk_library_metadata that contains
+   * libraries.dart.
+   */
+  static String _SDK_LIBRARY_METADATA_LIB_DIR = "lib";
+
+  /**
+   * The name of the directory within the SDK directory that contains the
+   * libraries.
+   */
+  static String _LIB_DIRECTORY_NAME = "lib";
+
+  /**
+   * The name of the libraries file.
+   */
+  static String _LIBRARIES_FILE = "libraries.dart";
+
+  /**
+   * The name of the pub executable on windows.
+   */
+  static String _PUB_EXECUTABLE_NAME_WIN = "pub.bat";
+
+  /**
+   * The name of the pub executable on non-windows operating systems.
+   */
+  static String _PUB_EXECUTABLE_NAME = "pub";
+
+  /**
+   * The name of the file within the SDK directory that contains the version
+   * number of the SDK.
+   */
+  static String _VERSION_FILE_NAME = "version";
+
+  /**
+   * The directory containing the SDK.
+   */
+  Folder _sdkDirectory;
+
+  /**
+   * The directory within the SDK directory that contains the libraries.
+   */
+  Folder _libraryDirectory;
+
+  /**
+   * The revision number of this SDK, or `"0"` if the revision number cannot be
+   * discovered.
+   */
+  String _sdkVersion;
+
+  /**
+   * The file containing the pub executable.
+   */
+  File _pubExecutable;
+
+  /**
+   * Initialize a newly created SDK to represent the Dart SDK installed in the
+   * [sdkDirectory]. The flag [useDart2jsPaths] is `true` if the dart2js path
+   * should be used when it is available
+   */
+  FolderBasedDartSdk(ResourceProvider resourceProvider, this._sdkDirectory,
+      [bool useDart2jsPaths = false]) {
+    this.resourceProvider = resourceProvider;
+    libraryMap = initialLibraryMap(useDart2jsPaths);
+  }
+
+  /**
+   * Return the directory containing the SDK.
+   */
+  Folder get directory => _sdkDirectory;
+
+  /**
+   * Return the directory containing documentation for the SDK.
+   */
+  Folder get docDirectory =>
+      _sdkDirectory.getChildAssumingFolder(_DOCS_DIRECTORY_NAME);
+
+  /**
+   * Return the directory within the SDK directory that contains the libraries.
+   */
+  Folder get libraryDirectory {
+    if (_libraryDirectory == null) {
+      _libraryDirectory =
+          _sdkDirectory.getChildAssumingFolder(_LIB_DIRECTORY_NAME);
+    }
+    return _libraryDirectory;
+  }
+
+  /**
+   * Return the file containing the Pub executable, or `null` if it does not exist.
+   */
+  File get pubExecutable {
+    if (_pubExecutable == null) {
+      _pubExecutable = _sdkDirectory
+          .getChildAssumingFolder(_BIN_DIRECTORY_NAME)
+          .getChildAssumingFile(OSUtilities.isWindows()
+              ? _PUB_EXECUTABLE_NAME_WIN
+              : _PUB_EXECUTABLE_NAME);
+    }
+    return _pubExecutable;
+  }
+
+  /**
+   * Return the revision number of this SDK, or `"0"` if the revision number
+   * cannot be discovered.
+   */
+  @override
+  String get sdkVersion {
+    if (_sdkVersion == null) {
+      _sdkVersion = DartSdk.DEFAULT_VERSION;
+      File revisionFile =
+          _sdkDirectory.getChildAssumingFile(_VERSION_FILE_NAME);
+      try {
+        String revision = revisionFile.readAsStringSync();
+        if (revision != null) {
+          _sdkVersion = revision.trim();
+        }
+      } on FileSystemException {
+        // Fall through to return the default.
+      }
+    }
+    return _sdkVersion;
+  }
+
+  /**
+   * Determine the search order for trying to locate the [_LIBRARIES_FILE].
+   */
+  Iterable<File> get _libraryMapLocations sync* {
+    yield libraryDirectory
+        .getChildAssumingFolder(_INTERNAL_DIR)
+        .getChildAssumingFolder(_SDK_LIBRARY_METADATA_DIR)
+        .getChildAssumingFolder(_SDK_LIBRARY_METADATA_LIB_DIR)
+        .getChildAssumingFile(_LIBRARIES_FILE);
+    yield libraryDirectory
+        .getChildAssumingFolder(_INTERNAL_DIR)
+        .getChildAssumingFile(_LIBRARIES_FILE);
+  }
+
+  @override
+  String getRelativePathFromFile(File file) {
+    String filePath = file.path;
+    String libPath = libraryDirectory.path;
+    if (!filePath
+        .startsWith("$libPath${resourceProvider.pathContext.separator}")) {
+      return null;
+    }
+    return filePath.substring(libPath.length + 1);
+  }
+
+  /**
+   * Return the [PackageBundle] for this SDK, if it exists, or `null` otherwise.
+   * This method should not be used outside of `analyzer` and `analyzer_cli`
+   * packages.
+   */
+  PackageBundle getSummarySdkBundle(bool strongMode) {
+    String rootPath = directory.path;
+    String name = strongMode ? 'strong.sum' : 'spec.sum';
+    String path =
+        resourceProvider.pathContext.join(rootPath, 'lib', '_internal', name);
+    try {
+      File file = resourceProvider.getFile(path);
+      if (file.exists) {
+        List<int> bytes = file.readAsBytesSync();
+        return new PackageBundle.fromBuffer(bytes);
+      }
+    } catch (exception, stackTrace) {
+      AnalysisEngine.instance.logger.logError(
+          'Failed to load SDK analysis summary from $path',
+          new CaughtException(exception, stackTrace));
+    }
+    return null;
+  }
+
+  /**
+   * Read all of the configuration files to initialize the library maps. The
+   * flag [useDart2jsPaths] is `true` if the dart2js path should be used when it
+   * is available. Return the initialized library map.
+   */
+  LibraryMap initialLibraryMap(bool useDart2jsPaths) {
+    List<String> searchedPaths = <String>[];
+    var lastStackTrace = null;
+    var lastException = null;
+    for (File librariesFile in _libraryMapLocations) {
+      try {
+        String contents = librariesFile.readAsStringSync();
+        return new SdkLibrariesReader(useDart2jsPaths)
+            .readFromFile(librariesFile, contents);
+      } catch (exception, stackTrace) {
+        searchedPaths.add(librariesFile.path);
+        lastException = exception;
+        lastStackTrace = stackTrace;
+      }
+    }
+    AnalysisEngine.instance.logger.logError(
+        "Could not initialize the library map from $searchedPaths",
+        new CaughtException(lastException, lastStackTrace));
+    return new LibraryMap();
+  }
+
+  @override
+  Source internalMapDartUri(String dartUri) {
+    String libraryName;
+    String relativePath;
+    int index = dartUri.indexOf('/');
+    if (index >= 0) {
+      libraryName = dartUri.substring(0, index);
+      relativePath = dartUri.substring(index + 1);
+    } else {
+      libraryName = dartUri;
+      relativePath = "";
+    }
+    SdkLibrary library = getSdkLibrary(libraryName);
+    if (library == null) {
+      return null;
+    }
+    try {
+      File file = libraryDirectory.getChildAssumingFile(library.path);
+      if (!relativePath.isEmpty) {
+        file = file.parent.getChildAssumingFile(relativePath);
+      }
+      return file.createSource(parseUriWithException(dartUri));
+    } on URISyntaxException {
+      return null;
+    }
+  }
+
+  /**
+   * Return the default directory for the Dart SDK, or `null` if the directory
+   * cannot be determined (or does not exist). The default directory is provided
+   * by a system property named `com.google.dart.sdk`.
+   */
+  static Folder defaultSdkDirectory(ResourceProvider resourceProvider) {
+    // TODO(brianwilkerson) This is currently only being used in the analysis
+    // server's Driver class to find the default SDK. The command-line analyzer
+    // uses cli_utils to find the SDK. Not sure why they're different.
+    String sdkProperty = getSdkProperty(resourceProvider);
+    if (sdkProperty == null) {
+      return null;
+    }
+    Folder sdkDirectory = resourceProvider.getFolder(sdkProperty);
+    if (!sdkDirectory.exists) {
+      return null;
+    }
+    return sdkDirectory;
+  }
+
+  static String getSdkProperty(ResourceProvider resourceProvider) {
+    String exec = io.Platform.executable;
+    if (exec.length == 0) {
+      return null;
+    }
+    pathos.Context pathContext = resourceProvider.pathContext;
+    // Might be "xcodebuild/ReleaseIA32/dart" with "sdk" sibling
+    String outDir = pathContext.dirname(pathContext.dirname(exec));
+    String sdkPath = pathContext.join(pathContext.dirname(outDir), "sdk");
+    if (resourceProvider.getFolder(sdkPath).exists) {
+      return sdkPath;
+    }
+    // probably be "dart-sdk/bin/dart"
+    return pathContext.dirname(pathContext.dirname(exec));
+  }
+}
+
+/**
+ * An object used to read and parse the libraries file
+ * (dart-sdk/lib/_internal/sdk_library_metadata/lib/libraries.dart) for information
+ * about the libraries in an SDK. The library information is represented as a
+ * Dart file containing a single top-level variable whose value is a const map.
+ * The keys of the map are the names of libraries defined in the SDK and the
+ * values in the map are info objects defining the library. For example, a
+ * subset of a typical SDK might have a libraries file that looks like the
+ * following:
+ *
+ *     final Map<String, LibraryInfo> LIBRARIES = const <LibraryInfo> {
+ *       // Used by VM applications
+ *       "builtin" : const LibraryInfo(
+ *         "builtin/builtin_runtime.dart",
+ *         category: "Server",
+ *         platforms: VM_PLATFORM),
+ *
+ *       "compiler" : const LibraryInfo(
+ *         "compiler/compiler.dart",
+ *         category: "Tools",
+ *         platforms: 0),
+ *     };
+ */
+class SdkLibrariesReader {
+  /**
+   * A flag indicating whether the dart2js path should be used when it is
+   * available.
+   */
+  final bool _useDart2jsPaths;
+
+  /**
+   * Initialize a newly created library reader to use the dart2js path if
+   * [_useDart2jsPaths] is `true`.
+   */
+  SdkLibrariesReader(this._useDart2jsPaths);
+
+  /**
+   * Return the library map read from the given [file], given that the content
+   * of the file is already known to be [libraryFileContents].
+   */
+  LibraryMap readFromFile(File file, String libraryFileContents) =>
+      readFromSource(file.createSource(), libraryFileContents);
+
+  /**
+   * Return the library map read from the given [source], given that the content
+   * of the file is already known to be [libraryFileContents].
+   */
+  LibraryMap readFromSource(Source source, String libraryFileContents) {
+    BooleanErrorListener errorListener = new BooleanErrorListener();
+    Scanner scanner = new Scanner(
+        source, new CharSequenceReader(libraryFileContents), errorListener);
+    Parser parser = new Parser(source, errorListener);
+    CompilationUnit unit = parser.parseCompilationUnit(scanner.tokenize());
+    SdkLibrariesReader_LibraryBuilder libraryBuilder =
+        new SdkLibrariesReader_LibraryBuilder(_useDart2jsPaths);
+    // If any syntactic errors were found then don't try to visit the AST
+    // structure.
+    if (!errorListener.errorReported) {
+      unit.accept(libraryBuilder);
+    }
+    return libraryBuilder.librariesMap;
+  }
+}
diff --git a/pkg/analyzer/lib/src/generated/element_resolver.dart b/pkg/analyzer/lib/src/generated/element_resolver.dart
index b2c10e2..029b5c6 100644
--- a/pkg/analyzer/lib/src/generated/element_resolver.dart
+++ b/pkg/analyzer/lib/src/generated/element_resolver.dart
@@ -156,7 +156,9 @@
   Object visitAssignmentExpression(AssignmentExpression node) {
     Token operator = node.operator;
     TokenType operatorType = operator.type;
-    if (operatorType != TokenType.EQ &&
+    if (operatorType != TokenType.AMPERSAND_AMPERSAND_EQ &&
+        operatorType != TokenType.BAR_BAR_EQ &&
+        operatorType != TokenType.EQ &&
         operatorType != TokenType.QUESTION_QUESTION_EQ) {
       operatorType = _operatorFromCompoundAssignment(operatorType);
       Expression leftHandSide = node.leftHandSide;
diff --git a/pkg/analyzer/lib/src/generated/engine.dart b/pkg/analyzer/lib/src/generated/engine.dart
index bd08147..967095a 100644
--- a/pkg/analyzer/lib/src/generated/engine.dart
+++ b/pkg/analyzer/lib/src/generated/engine.dart
@@ -1070,6 +1070,12 @@
   bool get enableGenericMethods => null;
 
   /**
+   * Return `true` to enable the lazy compound assignment operators '&&=' and
+   * '||='.
+   */
+  bool get enableLazyAssignmentOperators;
+
+  /**
    * Return `true` to strictly follow the specification when generating
    * warnings on "call" methods (fixes dartbug.com/21938).
    */
@@ -1185,6 +1191,11 @@
   static const int ENABLE_SUPER_MIXINS_FLAG = 0x40;
 
   /**
+   * The default list of non-nullable type names.
+   */
+  static const List<String> NONNULLABLE_TYPES = const <String>[];
+
+  /**
    * A predicate indicating whether analysis is to parse and analyze function
    * bodies.
    */
@@ -1219,6 +1230,9 @@
    */
   bool enableGenericMethods = false;
 
+  @override
+  bool enableLazyAssignmentOperators = false;
+
   /**
    * A flag indicating whether analysis is to strictly follow the specification
    * when generating warnings on "call" methods (fixes dartbug.com/21938).
@@ -1234,9 +1248,6 @@
   @override
   bool enableTiming = false;
 
-  @override
-  bool enableTrailingCommas = true;
-
   /**
    * A flag indicating whether errors, warnings and hints should be generated
    * for sources that are implicitly being analyzed.
@@ -1306,6 +1317,12 @@
    */
   bool implicitCasts = true;
 
+  /**
+   * A list of non-nullable type names, prefixed by the library URI they belong
+   * to, e.g., 'dart:core,int', 'dart:core,bool', 'file:///foo.dart,bar', etc.
+   */
+  List<String> nonnullableTypes = NONNULLABLE_TYPES;
+
   @override
   bool finerGrainedInvalidation = false;
 
@@ -1353,6 +1370,7 @@
     if (options is AnalysisOptionsImpl) {
       strongModeHints = options.strongModeHints;
       implicitCasts = options.implicitCasts;
+      nonnullableTypes = options.nonnullableTypes;
       implicitDynamic = options.implicitDynamic;
     }
     trackCacheDependencies = options.trackCacheDependencies;
@@ -1542,18 +1560,26 @@
  */
 class CacheConsistencyValidationStatistics {
   /**
-   * Number of sources which were modified, but the context was not notified
+   * Number of sources which were changed, but the context was not notified
    * about it, so this fact was detected only during cache consistency
    * validation.
    */
-  int numOfModified = 0;
+  int numOfChanged = 0;
 
   /**
-   * Number of sources which were deleted, but the context was not notified
+   * Number of sources which stopped existing, but the context was not notified
    * about it, so this fact was detected only during cache consistency
    * validation.
    */
-  int numOfDeleted = 0;
+  int numOfRemoved = 0;
+
+  /**
+   * Reset all counters.
+   */
+  void reset() {
+    numOfChanged = 0;
+    numOfRemoved = 0;
+  }
 }
 
 /**
diff --git a/pkg/analyzer/lib/src/generated/error_verifier.dart b/pkg/analyzer/lib/src/generated/error_verifier.dart
index 4a7cef1..e3cf73c7 100644
--- a/pkg/analyzer/lib/src/generated/error_verifier.dart
+++ b/pkg/analyzer/lib/src/generated/error_verifier.dart
@@ -13,7 +13,6 @@
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/dart/element/visitor.dart';
-import 'package:analyzer/src/dart/ast/utilities.dart';
 import 'package:analyzer/src/dart/element/element.dart';
 import 'package:analyzer/src/dart/element/member.dart';
 import 'package:analyzer/src/dart/element/type.dart';
diff --git a/pkg/analyzer/lib/src/generated/resolver.dart b/pkg/analyzer/lib/src/generated/resolver.dart
index b111583..afa7cce 100644
--- a/pkg/analyzer/lib/src/generated/resolver.dart
+++ b/pkg/analyzer/lib/src/generated/resolver.dart
@@ -3143,14 +3143,14 @@
     _typeParameters.add(element);
   }
 
-  FieldElement getField(String fieldName) {
+  FieldElement getField(String fieldName, {bool synthetic: false}) {
     if (_fields == null) {
       return null;
     }
     int length = _fields.length;
     for (int i = 0; i < length; i++) {
       FieldElement field = _fields[i];
-      if (field.name == fieldName) {
+      if (field.name == fieldName && field.isSynthetic == synthetic) {
         return field;
       }
     }
@@ -3434,7 +3434,10 @@
     if (_nodeExits(leftHandSide)) {
       return true;
     }
-    if (node.operator.type == TokenType.QUESTION_QUESTION_EQ) {
+    TokenType operatorType = node.operator.type;
+    if (operatorType == TokenType.AMPERSAND_AMPERSAND_EQ ||
+        operatorType == TokenType.BAR_BAR_EQ ||
+        operatorType == TokenType.QUESTION_QUESTION_EQ) {
       return false;
     }
     if (leftHandSide is PropertyAccess &&
diff --git a/pkg/analyzer/lib/src/generated/static_type_analyzer.dart b/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
index 19019da..f681471 100644
--- a/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
+++ b/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
@@ -255,6 +255,9 @@
       // bound of the static types of the LHS and RHS.
       _analyzeLeastUpperBound(node, node.leftHandSide, node.rightHandSide);
       return null;
+    } else if (operator == TokenType.AMPERSAND_AMPERSAND_EQ ||
+        operator == TokenType.BAR_BAR_EQ) {
+      _recordStaticType(node, _typeProvider.boolType);
     } else {
       ExecutableElement staticMethodElement = node.staticElement;
       DartType staticType = _computeStaticReturnType(staticMethodElement);
@@ -2008,7 +2011,11 @@
       arguments.correspondingStaticParameters = ResolverVisitor
           .resolveArgumentsToParameters(arguments, inferred.parameters, null);
       inferConstructorName(constructor, inferred.returnType);
-      // TODO(jmesserly): should we fix up the staticElement as well?
+      // Update the static element as well. This is used in some cases, such as
+      // computing constant values. It is stored in two places.
+      constructor.staticElement =
+          ConstructorMember.from(rawElement, inferred.returnType);
+      node.staticElement = constructor.staticElement;
     }
   }
 
diff --git a/pkg/analyzer/lib/src/generated/type_system.dart b/pkg/analyzer/lib/src/generated/type_system.dart
index f7efd79..9154132 100644
--- a/pkg/analyzer/lib/src/generated/type_system.dart
+++ b/pkg/analyzer/lib/src/generated/type_system.dart
@@ -31,7 +31,14 @@
    */
   final bool implicitCasts;
 
-  StrongTypeSystemImpl({this.implicitCasts: true});
+  /**
+   * A list of non-nullable type names (e.g., 'int', 'bool', etc.).
+   */
+  final List<String> nonnullableTypes;
+
+  StrongTypeSystemImpl(
+      {this.implicitCasts: true,
+      this.nonnullableTypes: AnalysisOptionsImpl.NONNULLABLE_TYPES});
 
   bool anyParameterType(FunctionType ft, bool predicate(DartType t)) {
     return ft.parameters.any((p) => predicate(p.type));
@@ -156,7 +163,7 @@
     // subtypes (or supertypes) as necessary, and track the constraints that
     // are implied by this.
     var inferringTypeSystem =
-        new _StrongInferenceTypeSystem(typeProvider, fnType.typeFormals);
+        new _StrongInferenceTypeSystem(typeProvider, this, fnType.typeFormals);
 
     // Since we're trying to infer the instantiation, we want to ignore type
     // formals as we check the parameters and return type.
@@ -209,7 +216,7 @@
     // subtypes (or supertypes) as necessary, and track the constraints that
     // are implied by this.
     var inferringTypeSystem =
-        new _StrongInferenceTypeSystem(typeProvider, fnType.typeFormals);
+        new _StrongInferenceTypeSystem(typeProvider, this, fnType.typeFormals);
 
     // Special case inference for Future.then.
     //
@@ -622,8 +629,9 @@
   bool _isInterfaceSubtypeOf(
       InterfaceType i1, InterfaceType i2, Set<Element> visited) {
     // Guard recursive calls
-    _GuardedSubtypeChecker<InterfaceType> guardedInterfaceSubtype =
-        _guard(_isInterfaceSubtypeOf);
+    _GuardedSubtypeChecker<InterfaceType> guardedInterfaceSubtype = _guard(
+        (DartType i1, DartType i2, Set<Element> visited) =>
+            _isInterfaceSubtypeOf(i1, i2, visited));
 
     if (i1 == i2) {
       return true;
@@ -755,6 +763,16 @@
     return (t.isDynamic && !dynamicIsBottom) || t.isObject;
   }
 
+  bool isNonNullableType(DartType type) {
+    return nonnullableTypes.contains(_getTypeFullyQualifiedName(type));
+  }
+
+  /// Given a type return its name prepended with the URI to its containing
+  /// library and separated by a comma.
+  String _getTypeFullyQualifiedName(DartType type) {
+    return "${type?.element?.library?.source?.uri},$type";
+  }
+
   /**
    * This currently just implements a simple least upper bound to
    * handle some common cases.  It also avoids some termination issues
@@ -1185,7 +1203,9 @@
   static TypeSystem create(AnalysisContext context) {
     var options = context.analysisOptions as AnalysisOptionsImpl;
     return options.strongMode
-        ? new StrongTypeSystemImpl(implicitCasts: options.implicitCasts)
+        ? new StrongTypeSystemImpl(
+            implicitCasts: options.implicitCasts,
+            nonnullableTypes: options.nonnullableTypes)
         : new TypeSystemImpl();
   }
 }
@@ -1261,16 +1281,16 @@
 /// Tracks upper and lower type bounds for a set of type parameters.
 class _StrongInferenceTypeSystem extends StrongTypeSystemImpl {
   final TypeProvider _typeProvider;
+
+  /// The outer strong mode type system, used for GLB and LUB, so we don't
+  /// recurse into our constraint solving code.
+  final StrongTypeSystemImpl _typeSystem;
   final Map<TypeParameterType, _TypeParameterBound> _bounds;
 
-  _StrongInferenceTypeSystem(
-      this._typeProvider, Iterable<TypeParameterElement> typeFormals)
-      : _bounds =
-            new Map.fromIterable(typeFormals, key: (t) => t.type, value: (t) {
-          _TypeParameterBound bound = new _TypeParameterBound();
-          if (t.bound != null) bound.upper = t.bound;
-          return bound;
-        });
+  _StrongInferenceTypeSystem(this._typeProvider, this._typeSystem,
+      Iterable<TypeParameterElement> typeFormals)
+      : _bounds = new Map.fromIterable(typeFormals,
+            key: (t) => t.type, value: (t) => new _TypeParameterBound());
 
   /// Given the constraints that were given by calling [isSubtypeOf], find the
   /// instantiation of the generic function that satisfies these constraints.
@@ -1278,26 +1298,19 @@
     List<TypeParameterType> fnTypeParams =
         TypeParameterTypeImpl.getTypes(fnType.typeFormals);
 
-    var inferredTypes = new List<DartType>.from(fnTypeParams, growable: false);
+    // Initialize the inferred type array.
+    //
+    // They all start as `dynamic` to offer reasonable degradation for f-bounded
+    // type parameters.
+    var inferredTypes = new List<DartType>.filled(
+        fnTypeParams.length, DynamicTypeImpl.instance,
+        growable: false);
+
     for (int i = 0; i < fnTypeParams.length; i++) {
       TypeParameterType typeParam = fnTypeParams[i];
-      _TypeParameterBound bound = _bounds[typeParam];
 
-      // Now we've computed lower and upper bounds for each type parameter.
+      // Apply the `extends` clause for the type parameter, if any.
       //
-      // To decide on which type to assign, we look at the return type and see
-      // if the type parameter occurs in covariant or contravariant positions.
-      //
-      // If the type is "passed in" at all, or if our lower bound was bottom,
-      // we choose the upper bound as being the most useful.
-      //
-      // Otherwise we choose the more precise lower bound.
-      _TypeParameterVariance variance =
-          new _TypeParameterVariance.from(typeParam, fnType.returnType);
-
-      inferredTypes[i] =
-          variance.passedIn || bound.lower.isBottom ? bound.upper : bound.lower;
-
       // Assumption: if the current type parameter has an "extends" clause
       // that refers to another type variable we are inferring, it will appear
       // before us or in this list position. For example:
@@ -1313,8 +1326,28 @@
       // Or if the type parameter's bound depends on itself such as:
       //
       //     <T extends Clonable<T>>
+      DartType declaredUpperBound = typeParam.element.bound;
+      if (declaredUpperBound != null) {
+        // Assert that the type parameter is a subtype of its bound.
+        _inferTypeParameterSubtypeOf(typeParam,
+            declaredUpperBound.substitute2(inferredTypes, fnTypeParams), null);
+      }
+
+      // Now we've computed lower and upper bounds for each type parameter.
+      //
+      // To decide on which type to assign, we look at the return type and see
+      // if the type parameter occurs in covariant or contravariant positions.
+      //
+      // If the type is "passed in" at all, or if our lower bound was bottom,
+      // we choose the upper bound as being the most useful.
+      //
+      // Otherwise we choose the more precise lower bound.
+      _TypeParameterVariance variance =
+          new _TypeParameterVariance.from(typeParam, fnType.returnType);
+
+      _TypeParameterBound bound = _bounds[typeParam];
       inferredTypes[i] =
-          inferredTypes[i].substitute2(inferredTypes, fnTypeParams);
+          variance.passedIn || bound.lower.isBottom ? bound.upper : bound.lower;
 
       // See if the constraints on the type variable are satisfied.
       //
@@ -1348,7 +1381,8 @@
         // We already know T1 <: U, for some U.
         // So update U to reflect the new constraint T1 <: GLB(U, T2)
         //
-        bound.upper = getGreatestLowerBound(_typeProvider, bound.upper, t2);
+        bound.upper =
+            _typeSystem.getGreatestLowerBound(_typeProvider, bound.upper, t2);
         // Optimistically assume we will be able to satisfy the constraint.
         return true;
       }
@@ -1362,7 +1396,8 @@
         // We already know L <: T2, for some L.
         // So update L to reflect the new constraint LUB(L, T1) <: T2
         //
-        bound.lower = getLeastUpperBound(_typeProvider, bound.lower, t1);
+        bound.lower =
+            _typeSystem.getLeastUpperBound(_typeProvider, bound.lower, t1);
         // Optimistically assume we will be able to satisfy the constraint.
         return true;
       }
diff --git a/pkg/analyzer/lib/src/summary/format.dart b/pkg/analyzer/lib/src/summary/format.dart
index 1034bc5..bbed56e 100644
--- a/pkg/analyzer/lib/src/summary/format.dart
+++ b/pkg/analyzer/lib/src/summary/format.dart
@@ -2136,7 +2136,9 @@
 
 class PackageIndexBuilder extends Object with _PackageIndexMixin implements idl.PackageIndex {
   List<idl.IndexSyntheticElementKind> _elementKinds;
-  List<int> _elementOffsets;
+  List<int> _elementNameClassMemberIds;
+  List<int> _elementNameParameterIds;
+  List<int> _elementNameUnitMemberIds;
   List<int> _elementUnits;
   List<String> _strings;
   List<int> _unitLibraryUris;
@@ -2155,17 +2157,47 @@
   }
 
   @override
-  List<int> get elementOffsets => _elementOffsets ??= <int>[];
+  List<int> get elementNameClassMemberIds => _elementNameClassMemberIds ??= <int>[];
 
   /**
    * Each item of this list corresponds to a unique referenced element.  It is
-   * the offset of the element name relative to the beginning of the file.  The
-   * list is sorted in ascending order, so that the client can quickly check
-   * whether an element is referenced in this [PackageIndex].
+   * the identifier of the class member element name, or `null` if the element is
+   * a top-level element.  The list is sorted in ascending order, so that the
+   * client can quickly check whether an element is referenced in this
+   * [PackageIndex].
    */
-  void set elementOffsets(List<int> _value) {
+  void set elementNameClassMemberIds(List<int> _value) {
     assert(_value == null || _value.every((e) => e >= 0));
-    _elementOffsets = _value;
+    _elementNameClassMemberIds = _value;
+  }
+
+  @override
+  List<int> get elementNameParameterIds => _elementNameParameterIds ??= <int>[];
+
+  /**
+   * Each item of this list corresponds to a unique referenced element.  It is
+   * the identifier of the named parameter name, or `null` if the element is not
+   * a named parameter.  The list is sorted in ascending order, so that the
+   * client can quickly check whether an element is referenced in this
+   * [PackageIndex].
+   */
+  void set elementNameParameterIds(List<int> _value) {
+    assert(_value == null || _value.every((e) => e >= 0));
+    _elementNameParameterIds = _value;
+  }
+
+  @override
+  List<int> get elementNameUnitMemberIds => _elementNameUnitMemberIds ??= <int>[];
+
+  /**
+   * Each item of this list corresponds to a unique referenced element.  It is
+   * the identifier of the top-level element name, or `null` if the element is
+   * the unit.  The list is sorted in ascending order, so that the client can
+   * quickly check whether an element is referenced in this [PackageIndex].
+   */
+  void set elementNameUnitMemberIds(List<int> _value) {
+    assert(_value == null || _value.every((e) => e >= 0));
+    _elementNameUnitMemberIds = _value;
   }
 
   @override
@@ -2229,9 +2261,11 @@
     _unitUnitUris = _value;
   }
 
-  PackageIndexBuilder({List<idl.IndexSyntheticElementKind> elementKinds, List<int> elementOffsets, List<int> elementUnits, List<String> strings, List<int> unitLibraryUris, List<UnitIndexBuilder> units, List<int> unitUnitUris})
+  PackageIndexBuilder({List<idl.IndexSyntheticElementKind> elementKinds, List<int> elementNameClassMemberIds, List<int> elementNameParameterIds, List<int> elementNameUnitMemberIds, List<int> elementUnits, List<String> strings, List<int> unitLibraryUris, List<UnitIndexBuilder> units, List<int> unitUnitUris})
     : _elementKinds = elementKinds,
-      _elementOffsets = elementOffsets,
+      _elementNameClassMemberIds = elementNameClassMemberIds,
+      _elementNameParameterIds = elementNameParameterIds,
+      _elementNameUnitMemberIds = elementNameUnitMemberIds,
       _elementUnits = elementUnits,
       _strings = strings,
       _unitLibraryUris = unitLibraryUris,
@@ -2252,7 +2286,9 @@
 
   fb.Offset finish(fb.Builder fbBuilder) {
     fb.Offset offset_elementKinds;
-    fb.Offset offset_elementOffsets;
+    fb.Offset offset_elementNameClassMemberIds;
+    fb.Offset offset_elementNameParameterIds;
+    fb.Offset offset_elementNameUnitMemberIds;
     fb.Offset offset_elementUnits;
     fb.Offset offset_strings;
     fb.Offset offset_unitLibraryUris;
@@ -2261,8 +2297,14 @@
     if (!(_elementKinds == null || _elementKinds.isEmpty)) {
       offset_elementKinds = fbBuilder.writeListUint8(_elementKinds.map((b) => b.index).toList());
     }
-    if (!(_elementOffsets == null || _elementOffsets.isEmpty)) {
-      offset_elementOffsets = fbBuilder.writeListUint32(_elementOffsets);
+    if (!(_elementNameClassMemberIds == null || _elementNameClassMemberIds.isEmpty)) {
+      offset_elementNameClassMemberIds = fbBuilder.writeListUint32(_elementNameClassMemberIds);
+    }
+    if (!(_elementNameParameterIds == null || _elementNameParameterIds.isEmpty)) {
+      offset_elementNameParameterIds = fbBuilder.writeListUint32(_elementNameParameterIds);
+    }
+    if (!(_elementNameUnitMemberIds == null || _elementNameUnitMemberIds.isEmpty)) {
+      offset_elementNameUnitMemberIds = fbBuilder.writeListUint32(_elementNameUnitMemberIds);
     }
     if (!(_elementUnits == null || _elementUnits.isEmpty)) {
       offset_elementUnits = fbBuilder.writeListUint32(_elementUnits);
@@ -2283,8 +2325,14 @@
     if (offset_elementKinds != null) {
       fbBuilder.addOffset(5, offset_elementKinds);
     }
-    if (offset_elementOffsets != null) {
-      fbBuilder.addOffset(1, offset_elementOffsets);
+    if (offset_elementNameClassMemberIds != null) {
+      fbBuilder.addOffset(7, offset_elementNameClassMemberIds);
+    }
+    if (offset_elementNameParameterIds != null) {
+      fbBuilder.addOffset(8, offset_elementNameParameterIds);
+    }
+    if (offset_elementNameUnitMemberIds != null) {
+      fbBuilder.addOffset(1, offset_elementNameUnitMemberIds);
     }
     if (offset_elementUnits != null) {
       fbBuilder.addOffset(0, offset_elementUnits);
@@ -2324,7 +2372,9 @@
   _PackageIndexImpl(this._bc, this._bcOffset);
 
   List<idl.IndexSyntheticElementKind> _elementKinds;
-  List<int> _elementOffsets;
+  List<int> _elementNameClassMemberIds;
+  List<int> _elementNameParameterIds;
+  List<int> _elementNameUnitMemberIds;
   List<int> _elementUnits;
   List<String> _strings;
   List<int> _unitLibraryUris;
@@ -2338,9 +2388,21 @@
   }
 
   @override
-  List<int> get elementOffsets {
-    _elementOffsets ??= const fb.Uint32ListReader().vTableGet(_bc, _bcOffset, 1, const <int>[]);
-    return _elementOffsets;
+  List<int> get elementNameClassMemberIds {
+    _elementNameClassMemberIds ??= const fb.Uint32ListReader().vTableGet(_bc, _bcOffset, 7, const <int>[]);
+    return _elementNameClassMemberIds;
+  }
+
+  @override
+  List<int> get elementNameParameterIds {
+    _elementNameParameterIds ??= const fb.Uint32ListReader().vTableGet(_bc, _bcOffset, 8, const <int>[]);
+    return _elementNameParameterIds;
+  }
+
+  @override
+  List<int> get elementNameUnitMemberIds {
+    _elementNameUnitMemberIds ??= const fb.Uint32ListReader().vTableGet(_bc, _bcOffset, 1, const <int>[]);
+    return _elementNameUnitMemberIds;
   }
 
   @override
@@ -2379,7 +2441,9 @@
   Map<String, Object> toJson() {
     Map<String, Object> _result = <String, Object>{};
     if (elementKinds.isNotEmpty) _result["elementKinds"] = elementKinds.map((_value) => _value.toString().split('.')[1]).toList();
-    if (elementOffsets.isNotEmpty) _result["elementOffsets"] = elementOffsets;
+    if (elementNameClassMemberIds.isNotEmpty) _result["elementNameClassMemberIds"] = elementNameClassMemberIds;
+    if (elementNameParameterIds.isNotEmpty) _result["elementNameParameterIds"] = elementNameParameterIds;
+    if (elementNameUnitMemberIds.isNotEmpty) _result["elementNameUnitMemberIds"] = elementNameUnitMemberIds;
     if (elementUnits.isNotEmpty) _result["elementUnits"] = elementUnits;
     if (strings.isNotEmpty) _result["strings"] = strings;
     if (unitLibraryUris.isNotEmpty) _result["unitLibraryUris"] = unitLibraryUris;
@@ -2391,7 +2455,9 @@
   @override
   Map<String, Object> toMap() => {
     "elementKinds": elementKinds,
-    "elementOffsets": elementOffsets,
+    "elementNameClassMemberIds": elementNameClassMemberIds,
+    "elementNameParameterIds": elementNameParameterIds,
+    "elementNameUnitMemberIds": elementNameUnitMemberIds,
     "elementUnits": elementUnits,
     "strings": strings,
     "unitLibraryUris": unitLibraryUris,
diff --git a/pkg/analyzer/lib/src/summary/format.fbs b/pkg/analyzer/lib/src/summary/format.fbs
index d08851c..329fe6b 100644
--- a/pkg/analyzer/lib/src/summary/format.fbs
+++ b/pkg/analyzer/lib/src/summary/format.fbs
@@ -1232,11 +1232,29 @@
 
   /**
    * Each item of this list corresponds to a unique referenced element.  It is
-   * the offset of the element name relative to the beginning of the file.  The
-   * list is sorted in ascending order, so that the client can quickly check
-   * whether an element is referenced in this [PackageIndex].
+   * the identifier of the class member element name, or `null` if the element is
+   * a top-level element.  The list is sorted in ascending order, so that the
+   * client can quickly check whether an element is referenced in this
+   * [PackageIndex].
    */
-  elementOffsets:[uint] (id: 1);
+  elementNameClassMemberIds:[uint] (id: 7);
+
+  /**
+   * Each item of this list corresponds to a unique referenced element.  It is
+   * the identifier of the named parameter name, or `null` if the element is not
+   * a named parameter.  The list is sorted in ascending order, so that the
+   * client can quickly check whether an element is referenced in this
+   * [PackageIndex].
+   */
+  elementNameParameterIds:[uint] (id: 8);
+
+  /**
+   * Each item of this list corresponds to a unique referenced element.  It is
+   * the identifier of the top-level element name, or `null` if the element is
+   * the unit.  The list is sorted in ascending order, so that the client can
+   * quickly check whether an element is referenced in this [PackageIndex].
+   */
+  elementNameUnitMemberIds:[uint] (id: 1);
 
   /**
    * Each item of this list corresponds to a unique referenced element.  It is
diff --git a/pkg/analyzer/lib/src/summary/idl.dart b/pkg/analyzer/lib/src/summary/idl.dart
index 505ade8..60a0552 100644
--- a/pkg/analyzer/lib/src/summary/idl.dart
+++ b/pkg/analyzer/lib/src/summary/idl.dart
@@ -714,12 +714,32 @@
 
   /**
    * Each item of this list corresponds to a unique referenced element.  It is
-   * the offset of the element name relative to the beginning of the file.  The
-   * list is sorted in ascending order, so that the client can quickly check
-   * whether an element is referenced in this [PackageIndex].
+   * the identifier of the class member element name, or `null` if the element is
+   * a top-level element.  The list is sorted in ascending order, so that the
+   * client can quickly check whether an element is referenced in this
+   * [PackageIndex].
+   */
+  @Id(7)
+  List<int> get elementNameClassMemberIds;
+
+  /**
+   * Each item of this list corresponds to a unique referenced element.  It is
+   * the identifier of the named parameter name, or `null` if the element is not
+   * a named parameter.  The list is sorted in ascending order, so that the
+   * client can quickly check whether an element is referenced in this
+   * [PackageIndex].
+   */
+  @Id(8)
+  List<int> get elementNameParameterIds;
+
+  /**
+   * Each item of this list corresponds to a unique referenced element.  It is
+   * the identifier of the top-level element name, or `null` if the element is
+   * the unit.  The list is sorted in ascending order, so that the client can
+   * quickly check whether an element is referenced in this [PackageIndex].
    */
   @Id(1)
-  List<int> get elementOffsets;
+  List<int> get elementNameUnitMemberIds;
 
   /**
    * Each item of this list corresponds to a unique referenced element.  It is
diff --git a/pkg/analyzer/lib/src/summary/index_unit.dart b/pkg/analyzer/lib/src/summary/index_unit.dart
index bc09ee3..c1bbae5 100644
--- a/pkg/analyzer/lib/src/summary/index_unit.dart
+++ b/pkg/analyzer/lib/src/summary/index_unit.dart
@@ -13,198 +13,15 @@
 import 'package:analyzer/src/summary/idl.dart';
 
 /**
- * Information about an element referenced in index.
+ * Information about an element that is actually put into index for some other
+ * related element. For example for a synthetic getter this is the corresponding
+ * non-synthetic field and [IndexSyntheticElementKind.getter] as the [kind].
  */
-class ElementInfo {
-  /**
-   * The identifier of the [CompilationUnitElement] containing this element.
-   */
-  final int unitId;
-
-  /**
-   * The name offset of the element.
-   */
-  final int offset;
-
-  /**
-   * The kind of the element.
-   */
+class IndexElementInfo {
+  final Element element;
   final IndexSyntheticElementKind kind;
 
-  /**
-   * The unique id of the element.  It is set after indexing of the whole
-   * package is done and we are assembling the full package index.
-   */
-  int id;
-
-  ElementInfo(this.unitId, this.offset, this.kind) {
-    assert(offset >= 0);
-  }
-}
-
-/**
- * Object that gathers information about the whole package index and then uses
- * it to assemble a new [PackageIndexBuilder].  Call [index] on each compilation
- * unit to be indexed, then call [assemble] to retrieve the complete index for
- * the package.
- */
-class PackageIndexAssembler {
-  /**
-   * Map associating referenced elements with their [ElementInfo]s.
-   */
-  final Map<Element, ElementInfo> _elementMap = <Element, ElementInfo>{};
-
-  /**
-   * Map associating [CompilationUnitElement]s with their identifiers, which
-   * are indices into [_unitLibraryUris] and [_unitUnitUris].
-   */
-  final Map<CompilationUnitElement, int> _unitMap =
-      <CompilationUnitElement, int>{};
-
-  /**
-   * Each item of this list corresponds to the library URI of a unique
-   * [CompilationUnitElement].
-   */
-  final List<_StringInfo> _unitLibraryUris = <_StringInfo>[];
-
-  /**
-   * Each item of this list corresponds to the unit URI of a unique
-   * [CompilationUnitElement].
-   */
-  final List<_StringInfo> _unitUnitUris = <_StringInfo>[];
-
-  /**
-   * Map associating strings with their [_StringInfo]s.
-   */
-  final Map<String, _StringInfo> _stringMap = <String, _StringInfo>{};
-
-  /**
-   * List of information about each unit indexed in this index.
-   */
-  final List<_UnitIndexAssembler> _units = <_UnitIndexAssembler>[];
-
-  /**
-   * Assemble a new [PackageIndexBuilder] using the information gathered by
-   * [indexDeclarations] or [indexUnit].
-   */
-  PackageIndexBuilder assemble() {
-    // sort strings end set IDs
-    List<_StringInfo> stringInfoList = _stringMap.values.toList();
-    stringInfoList.sort((a, b) {
-      return a.value.compareTo(b.value);
-    });
-    for (int i = 0; i < stringInfoList.length; i++) {
-      stringInfoList[i].id = i;
-    }
-    // sort elements and set IDs
-    List<ElementInfo> elementInfoList = _elementMap.values.toList();
-    elementInfoList.sort((a, b) {
-      return a.offset - b.offset;
-    });
-    for (int i = 0; i < elementInfoList.length; i++) {
-      elementInfoList[i].id = i;
-    }
-    return new PackageIndexBuilder(
-        unitLibraryUris: _unitLibraryUris.map((s) => s.id).toList(),
-        unitUnitUris: _unitUnitUris.map((s) => s.id).toList(),
-        elementUnits: elementInfoList.map((e) => e.unitId).toList(),
-        elementOffsets: elementInfoList.map((e) => e.offset).toList(),
-        elementKinds: elementInfoList.map((e) => e.kind).toList(),
-        strings: stringInfoList.map((s) => s.value).toList(),
-        units: _units.map((unit) => unit.assemble()).toList());
-  }
-
-  /**
-   * Index declarations in the given partially resolved [unit].
-   */
-  void indexDeclarations(CompilationUnit unit) {
-    int unitId = _getUnitId(unit.element);
-    _UnitIndexAssembler assembler = new _UnitIndexAssembler(this, unitId);
-    _units.add(assembler);
-    unit.accept(new _IndexDeclarationContributor(assembler));
-  }
-
-  /**
-   * Index the given fully resolved [unit].
-   */
-  void indexUnit(CompilationUnit unit) {
-    int unitId = _getUnitId(unit.element);
-    _UnitIndexAssembler assembler = new _UnitIndexAssembler(this, unitId);
-    _units.add(assembler);
-    unit.accept(new _IndexContributor(assembler));
-  }
-
-  /**
-   * Return the unique [ElementInfo] corresponding the [element].  The field
-   * [ElementInfo.id] is filled by [assemble] during final sorting.
-   */
-  ElementInfo _getElementInfo(Element element) {
-    if (element is Member) {
-      element = (element as Member).baseElement;
-    }
-    return _elementMap.putIfAbsent(element, () {
-      CompilationUnitElement unitElement = getUnitElement(element);
-      int unitId = _getUnitId(unitElement);
-      return newElementInfo(unitId, element);
-    });
-  }
-
-  /**
-   * Return the unique [_StringInfo] corresponding the [str].  The field
-   * [_StringInfo.id] is filled by [assemble] during final sorting.
-   */
-  _StringInfo _getStringInfo(String str) {
-    return _stringMap.putIfAbsent(str, () {
-      return new _StringInfo(str);
-    });
-  }
-
-  /**
-   * Add information about [unitElement] to [_unitUnitUris] and
-   * [_unitLibraryUris] if necessary, and return the location in those
-   * arrays representing [unitElement].
-   */
-  int _getUnitId(CompilationUnitElement unitElement) {
-    return _unitMap.putIfAbsent(unitElement, () {
-      assert(_unitLibraryUris.length == _unitUnitUris.length);
-      int id = _unitUnitUris.length;
-      _unitLibraryUris.add(_getUriInfo(unitElement.library.source.uri));
-      _unitUnitUris.add(_getUriInfo(unitElement.source.uri));
-      return id;
-    });
-  }
-
-  /**
-   * Return the unique [_StringInfo] corresponding [uri].  The field
-   * [_StringInfo.id] is filled by [assemble] during final sorting.
-   */
-  _StringInfo _getUriInfo(Uri uri) {
-    String str = uri.toString();
-    return _getStringInfo(str);
-  }
-
-  /**
-   * Return the [CompilationUnitElement] that should be used for [element].
-   * Throw [StateError] if the [element] is not linked into a unit.
-   */
-  static CompilationUnitElement getUnitElement(Element element) {
-    for (Element e = element; e != null; e = e.enclosingElement) {
-      if (e is CompilationUnitElement) {
-        return e;
-      }
-      if (e is LibraryElement) {
-        return e.definingCompilationUnit;
-      }
-    }
-    throw new StateError(element.toString());
-  }
-
-  /**
-   * Return a new [ElementInfo] for the given [element] in the given [unitId].
-   * This method is static, so it cannot add any information to the index.
-   */
-  static ElementInfo newElementInfo(int unitId, Element element) {
-    int offset = null;
+  factory IndexElementInfo(Element element) {
     IndexSyntheticElementKind kind = IndexSyntheticElementKind.notSynthetic;
     if (element.isSynthetic) {
       if (element is ConstructorElement) {
@@ -245,10 +62,222 @@
       }
     } else if (element is LibraryElement || element is CompilationUnitElement) {
       kind = IndexSyntheticElementKind.unit;
-      offset = 0;
     }
-    offset ??= element.nameOffset;
-    return new ElementInfo(unitId, offset, kind);
+    return new IndexElementInfo._(element, kind);
+  }
+
+  IndexElementInfo._(this.element, this.kind);
+}
+
+/**
+ * Object that gathers information about the whole package index and then uses
+ * it to assemble a new [PackageIndexBuilder].  Call [indexUnit] on each
+ * compilation unit to be indexed, then call [assemble] to retrieve the
+ * complete index for the package.
+ */
+class PackageIndexAssembler {
+  /**
+   * The string to use place of the `null` string.
+   */
+  static const NULL_STRING = '--nullString--';
+
+  /**
+   * Map associating referenced elements with their [_ElementInfo]s.
+   */
+  final Map<Element, _ElementInfo> _elementMap = <Element, _ElementInfo>{};
+
+  /**
+   * Map associating [CompilationUnitElement]s with their identifiers, which
+   * are indices into [_unitLibraryUris] and [_unitUnitUris].
+   */
+  final Map<CompilationUnitElement, int> _unitMap =
+      <CompilationUnitElement, int>{};
+
+  /**
+   * Each item of this list corresponds to the library URI of a unique
+   * [CompilationUnitElement].
+   */
+  final List<_StringInfo> _unitLibraryUris = <_StringInfo>[];
+
+  /**
+   * Each item of this list corresponds to the unit URI of a unique
+   * [CompilationUnitElement].
+   */
+  final List<_StringInfo> _unitUnitUris = <_StringInfo>[];
+
+  /**
+   * Map associating strings with their [_StringInfo]s.
+   */
+  final Map<String, _StringInfo> _stringMap = <String, _StringInfo>{};
+
+  /**
+   * List of information about each unit indexed in this index.
+   */
+  final List<_UnitIndexAssembler> _units = <_UnitIndexAssembler>[];
+
+  /**
+   * The [_StringInfo] to use for `null` strings.
+   */
+  _StringInfo _nullString;
+
+  PackageIndexAssembler() {
+    _nullString = _getStringInfo(NULL_STRING);
+  }
+
+  /**
+   * Assemble a new [PackageIndexBuilder] using the information gathered by
+   * [indexDeclarations] or [indexUnit].
+   */
+  PackageIndexBuilder assemble() {
+    // sort strings end set IDs
+    List<_StringInfo> stringInfoList = _stringMap.values.toList();
+    stringInfoList.sort((a, b) {
+      return a.value.compareTo(b.value);
+    });
+    for (int i = 0; i < stringInfoList.length; i++) {
+      stringInfoList[i].id = i;
+    }
+    // sort elements and set IDs
+    List<_ElementInfo> elementInfoList = _elementMap.values.toList();
+    elementInfoList.sort((a, b) {
+      int delta;
+      delta = a.nameIdUnitMember.id - b.nameIdUnitMember.id;
+      if (delta != null) {
+        return delta;
+      }
+      delta = a.nameIdClassMember.id - b.nameIdClassMember.id;
+      if (delta != null) {
+        return delta;
+      }
+      return a.nameIdParameter.id - b.nameIdParameter.id;
+    });
+    for (int i = 0; i < elementInfoList.length; i++) {
+      elementInfoList[i].id = i;
+    }
+    return new PackageIndexBuilder(
+        unitLibraryUris: _unitLibraryUris.map((s) => s.id).toList(),
+        unitUnitUris: _unitUnitUris.map((s) => s.id).toList(),
+        elementUnits: elementInfoList.map((e) => e.unitId).toList(),
+        elementNameUnitMemberIds:
+            elementInfoList.map((e) => e.nameIdUnitMember.id).toList(),
+        elementNameClassMemberIds:
+            elementInfoList.map((e) => e.nameIdClassMember.id).toList(),
+        elementNameParameterIds:
+            elementInfoList.map((e) => e.nameIdParameter.id).toList(),
+        elementKinds: elementInfoList.map((e) => e.kind).toList(),
+        strings: stringInfoList.map((s) => s.value).toList(),
+        units: _units.map((unit) => unit.assemble()).toList());
+  }
+
+  /**
+   * Index declarations in the given partially resolved [unit].
+   */
+  void indexDeclarations(CompilationUnit unit) {
+    int unitId = _getUnitId(unit.element);
+    _UnitIndexAssembler assembler = new _UnitIndexAssembler(this, unitId);
+    _units.add(assembler);
+    unit.accept(new _IndexDeclarationContributor(assembler));
+  }
+
+  /**
+   * Index the given fully resolved [unit].
+   */
+  void indexUnit(CompilationUnit unit) {
+    int unitId = _getUnitId(unit.element);
+    _UnitIndexAssembler assembler = new _UnitIndexAssembler(this, unitId);
+    _units.add(assembler);
+    unit.accept(new _IndexContributor(assembler));
+  }
+
+  /**
+   * Return the unique [_ElementInfo] corresponding the [element].  The field
+   * [_ElementInfo.id] is filled by [assemble] during final sorting.
+   */
+  _ElementInfo _getElementInfo(Element element) {
+    if (element is Member) {
+      element = (element as Member).baseElement;
+    }
+    return _elementMap.putIfAbsent(element, () {
+      CompilationUnitElement unitElement = getUnitElement(element);
+      int unitId = _getUnitId(unitElement);
+      return _newElementInfo(unitId, element);
+    });
+  }
+
+  /**
+   * Return the unique [_StringInfo] corresponding the [str].  The field
+   * [_StringInfo.id] is filled by [assemble] during final sorting.
+   */
+  _StringInfo _getStringInfo(String str) {
+    return _stringMap.putIfAbsent(str, () {
+      return new _StringInfo(str);
+    });
+  }
+
+  /**
+   * Add information about [unitElement] to [_unitUnitUris] and
+   * [_unitLibraryUris] if necessary, and return the location in those
+   * arrays representing [unitElement].
+   */
+  int _getUnitId(CompilationUnitElement unitElement) {
+    return _unitMap.putIfAbsent(unitElement, () {
+      assert(_unitLibraryUris.length == _unitUnitUris.length);
+      int id = _unitUnitUris.length;
+      _unitLibraryUris.add(_getUriInfo(unitElement.library.source.uri));
+      _unitUnitUris.add(_getUriInfo(unitElement.source.uri));
+      return id;
+    });
+  }
+
+  /**
+   * Return the unique [_StringInfo] corresponding [uri].  The field
+   * [_StringInfo.id] is filled by [assemble] during final sorting.
+   */
+  _StringInfo _getUriInfo(Uri uri) {
+    String str = uri.toString();
+    return _getStringInfo(str);
+  }
+
+  /**
+   * Return a new [_ElementInfo] for the given [element] in the given [unitId].
+   * This method is static, so it cannot add any information to the index.
+   */
+  _ElementInfo _newElementInfo(int unitId, Element element) {
+    IndexElementInfo info = new IndexElementInfo(element);
+    element = info.element;
+    // Prepare name identifiers.
+    _StringInfo nameIdParameter = _nullString;
+    _StringInfo nameIdClassMember = _nullString;
+    _StringInfo nameIdUnitMember = _nullString;
+    if (element is ParameterElement) {
+      nameIdParameter = _getStringInfo(element.name);
+      element = element.enclosingElement;
+    }
+    if (element?.enclosingElement is ClassElement) {
+      nameIdClassMember = _getStringInfo(element.name);
+      element = element.enclosingElement;
+    }
+    if (element?.enclosingElement is CompilationUnitElement) {
+      nameIdUnitMember = _getStringInfo(element.name);
+    }
+    return new _ElementInfo(unitId, nameIdUnitMember, nameIdClassMember,
+        nameIdParameter, info.kind);
+  }
+
+  /**
+   * Return the [CompilationUnitElement] that should be used for [element].
+   * Throw [StateError] if the [element] is not linked into a unit.
+   */
+  static CompilationUnitElement getUnitElement(Element element) {
+    for (Element e = element; e != null; e = e.enclosingElement) {
+      if (e is CompilationUnitElement) {
+        return e;
+      }
+      if (e is LibraryElement) {
+        return e.definingCompilationUnit;
+      }
+    }
+    throw new StateError(element.toString());
   }
 }
 
@@ -278,13 +307,55 @@
 }
 
 /**
+ * Information about an element referenced in index.
+ */
+class _ElementInfo {
+  /**
+   * The identifier of the [CompilationUnitElement] containing this element.
+   */
+  final int unitId;
+
+  /**
+   * The identifier of the top-level name, or `null` if the element is a
+   * reference to the unit.
+   */
+  final _StringInfo nameIdUnitMember;
+
+  /**
+   * The identifier of the class member name, or `null` if the element is not a
+   * class member or a named parameter of a class member.
+   */
+  final _StringInfo nameIdClassMember;
+
+  /**
+   * The identifier of the named parameter name, or `null` if the element is not
+   * a named parameter.
+   */
+  final _StringInfo nameIdParameter;
+
+  /**
+   * The kind of the element.
+   */
+  final IndexSyntheticElementKind kind;
+
+  /**
+   * The unique id of the element.  It is set after indexing of the whole
+   * package is done and we are assembling the full package index.
+   */
+  int id;
+
+  _ElementInfo(this.unitId, this.nameIdUnitMember, this.nameIdClassMember,
+      this.nameIdParameter, this.kind);
+}
+
+/**
  * Information about a single relation.  Any [_ElementRelationInfo] is always
  * part of a [_UnitIndexAssembler], so [offset] and [length] should be
  * understood within the context of the compilation unit pointed to by the
  * [_UnitIndexAssembler].
  */
 class _ElementRelationInfo {
-  final ElementInfo elementInfo;
+  final _ElementInfo elementInfo;
   final IndexRelationKind kind;
   final int offset;
   final int length;
@@ -770,7 +841,7 @@
  *    compilation unit.
  *  - Call [addNameRelation] for each name relation found in the
  *    compilation unit.
- *  - Assign ids to all the [ElementInfo] objects reachable from
+ *  - Assign ids to all the [_ElementInfo] objects reachable from
  *    [elementRelations].
  *  - Call [assemble] to produce the final unit index.
  */
@@ -786,7 +857,7 @@
   void addElementRelation(Element element, IndexRelationKind kind, int offset,
       int length, bool isQualified) {
     try {
-      ElementInfo elementInfo = pkg._getElementInfo(element);
+      _ElementInfo elementInfo = pkg._getElementInfo(element);
       elementRelations.add(new _ElementRelationInfo(
           elementInfo, kind, offset, length, isQualified));
     } on StateError {}
diff --git a/pkg/analyzer/lib/src/summary/link.dart b/pkg/analyzer/lib/src/summary/link.dart
index 08cbde1..f76bdc2 100644
--- a/pkg/analyzer/lib/src/summary/link.dart
+++ b/pkg/analyzer/lib/src/summary/link.dart
@@ -347,7 +347,7 @@
   @override
   final CompilationUnitElementForLink enclosingElement;
 
-  @override
+  /// TODO(brianwilkerson) This appears to be unused and might be removable.
   bool hasBeenInferred;
 
   ClassElementForLink(CompilationUnitElementForLink enclosingElement)
@@ -368,7 +368,7 @@
   List<ConstructorElementForLink> get constructors;
 
   @override
-  CompilationUnitElementForLink get enclosingUnit => enclosingElement;
+  CompilationUnitElementImpl get enclosingUnit => enclosingElement;
 
   @override
   List<FieldElementForLink> get fields;
@@ -571,7 +571,7 @@
   }
 
   @override
-  DartType get type =>
+  InterfaceType get type =>
       _type ??= buildType((int i) => typeParameterTypes[i], null);
 
   @override
@@ -740,7 +740,7 @@
   InterfaceType get supertype => library._linker.typeProvider.objectType;
 
   @override
-  DartType get type => _type ??= new InterfaceTypeImpl(this);
+  InterfaceType get type => _type ??= new InterfaceTypeImpl(this);
 
   @override
   List<TypeParameterElement> get typeParameters => const [];
@@ -1198,7 +1198,7 @@
               enclosingClass != null ? addReference(enclosingClass) : null,
           dependency: enclosingClass != null
               ? null
-              : library.addDependency(element.library),
+              : library.addDependency(element.library as LibraryElementForLink),
           kind: kind);
     } else if (element is FunctionElementForLink_Initializer) {
       return addRawReference('',
@@ -1629,6 +1629,9 @@
   ConstructorElementForLink get asConstructor => this;
 
   @override
+  ClassElementImpl get enclosingElement => super.enclosingClass;
+
+  @override
   bool get isCycleFree {
     if (!_constNode.isEvaluated) {
       new ConstDependencyWalker().walk(_constNode);
@@ -1852,7 +1855,6 @@
   String _name;
   String _displayName;
 
-  @override
   final CompilationUnitElementForLink compilationUnit;
 
   ExecutableElementForLink(this.compilationUnit, this._unlinkedExecutable);
@@ -1929,7 +1931,7 @@
   bool get isSynthetic => false;
 
   @override
-  LibraryElementForLink get library => enclosingElement.library;
+  LibraryElement get library => enclosingElement.library;
 
   @override
   String get name {
@@ -1975,7 +1977,7 @@
    */
   DartType _computeDefaultReturnType() {
     if (_unlinkedExecutable.kind == UnlinkedExecutableKind.setter &&
-        library._linker.strongMode) {
+        (library as LibraryElementForLink)._linker.strongMode) {
       // In strong mode, setters without an explicit return type are
       // considered to return `void`.
       return VoidTypeImpl.instance;
@@ -3728,6 +3730,9 @@
   DartType get asStaticType => type;
 
   @override
+  ClassElementImpl get enclosingElement => super.enclosingClass;
+
+  @override
   String get identifier => name;
 
   @override
@@ -3998,7 +4003,7 @@
  * Mixin used by elements that can have parameters.
  */
 abstract class ParameterParentElementForLink implements Element {
-  List<ParameterElementForLink> _parameters;
+  List<ParameterElement> _parameters;
 
   /**
    * Get the appropriate integer list to store in
@@ -4012,11 +4017,11 @@
   /**
    * Get all the parameters of this element.
    */
-  List<ParameterElementForLink> get parameters {
+  List<ParameterElement> get parameters {
     if (_parameters == null) {
       List<UnlinkedParam> unlinkedParameters = this.unlinkedParameters;
       int numParameters = unlinkedParameters.length;
-      _parameters = new List<ParameterElementForLink>(numParameters);
+      _parameters = new List<ParameterElement>(numParameters);
       for (int i = 0; i < numParameters; i++) {
         UnlinkedParam unlinkedParam = unlinkedParameters[i];
         _parameters[i] = new ParameterElementForLink(
@@ -4142,7 +4147,7 @@
     with ReferenceableElementForLink
     implements PropertyAccessorElementForLink {
   @override
-  SyntheticVariableElementForLink variable;
+  PropertyInducingElement variable;
 
   PropertyAccessorElementForLink_Executable(
       CompilationUnitElementForLink enclosingUnit,
@@ -4175,7 +4180,8 @@
 
   @override
   ReferenceableElementForLink getContainedName(String name) {
-    return new NonstaticMemberElementForLink(library, this, name);
+    return new NonstaticMemberElementForLink(
+        library as LibraryElementForLink, this, name);
   }
 
   @override
diff --git a/pkg/analyzer/lib/src/summary/summarize_ast.dart b/pkg/analyzer/lib/src/summary/summarize_ast.dart
index c2a625b..eeaef9d 100644
--- a/pkg/analyzer/lib/src/summary/summarize_ast.dart
+++ b/pkg/analyzer/lib/src/summary/summarize_ast.dart
@@ -641,7 +641,7 @@
     bool isSemanticallyStatic = isTopLevel || isDeclaredStatic;
     if (formalParameters != null) {
       b.parameters = formalParameters.parameters
-          .map((FormalParameter p) => p.accept(this))
+          .map((FormalParameter p) => p.accept(this) as UnlinkedParamBuilder)
           .toList();
       if (!isSemanticallyStatic) {
         for (int i = 0; i < formalParameters.parameters.length; i++) {
@@ -751,7 +751,7 @@
       b.type = serializedReturnType;
     }
     b.parameters = parameters.parameters
-        .map((FormalParameter p) => p.accept(this))
+        .map((FormalParameter p) => p.accept(this) as UnlinkedParamBuilder)
         .toList();
   }
 
@@ -1042,7 +1042,7 @@
       b.nameOffset = node.returnType.offset;
     }
     b.parameters = node.parameters.parameters
-        .map((FormalParameter p) => p.accept(this))
+        .map((FormalParameter p) => p.accept(this) as UnlinkedParamBuilder)
         .toList();
     b.kind = UnlinkedExecutableKind.constructor;
     if (node.factoryKeyword != null) {
@@ -1235,7 +1235,7 @@
       b.returnType = serializedReturnType;
     }
     b.parameters = node.parameters.parameters
-        .map((FormalParameter p) => p.accept(this))
+        .map((FormalParameter p) => p.accept(this) as UnlinkedParamBuilder)
         .toList();
     b.documentationComment = serializeDocumentation(node.documentationComment);
     b.annotations = serializeAnnotations(node.metadata);
diff --git a/pkg/analyzer/lib/src/task/dart.dart b/pkg/analyzer/lib/src/task/dart.dart
index 0d3981f..4ff2448 100644
--- a/pkg/analyzer/lib/src/task/dart.dart
+++ b/pkg/analyzer/lib/src/task/dart.dart
@@ -1344,6 +1344,7 @@
       }
       return null;
     }
+
     EnumDeclaration firstEnum = findFirstEnum();
     if (firstEnum != null && firstEnum.element.accessors.isEmpty) {
       EnumMemberBuilder builder = new EnumMemberBuilder(typeProvider);
@@ -2228,6 +2229,7 @@
           deps.addAll(l.units);
         }
       }
+
       int length = component.length;
       for (int i = 0; i < length; i++) {
         LibraryElement library = component[i];
@@ -2633,6 +2635,14 @@
         return true;
       }
     }
+    for (String name in references.names) {
+      ClassElementDelta classDelta = changedClasses[name];
+      if (classDelta != null && classDelta.hasAnnotationChanges) {
+        _log(() => '$refLibrary hints/verify errors are  affected because '
+            '$name has a class delta with annotation changes');
+        return true;
+      }
+    }
     return false;
   }
 
@@ -4884,16 +4894,6 @@
     }
   }
 
-  static String _getSimpleName(Identifier identifier) {
-    if (identifier is SimpleIdentifier) {
-      return identifier.name;
-    }
-    if (identifier is PrefixedIdentifier) {
-      return identifier.identifier.name;
-    }
-    return null;
-  }
-
   @override
   visitClassTypeAlias(ClassTypeAlias node) {
     ReferencedNamesScope outerScope = scope;
@@ -4923,14 +4923,6 @@
   }
 
   @override
-  visitSuperConstructorInvocation(SuperConstructorInvocation node) {
-    if (node.constructorName == null && enclosingSuperClassName != null) {
-      names.extendedUsedUnnamedConstructorNames.add(enclosingSuperClassName);
-    }
-    super.visitSuperConstructorInvocation(node);
-  }
-
-  @override
   visitConstructorName(ConstructorName node) {
     if (node.parent is! ConstructorDeclaration) {
       super.visitConstructorName(node);
@@ -5050,6 +5042,14 @@
   }
 
   @override
+  visitSuperConstructorInvocation(SuperConstructorInvocation node) {
+    if (node.constructorName == null && enclosingSuperClassName != null) {
+      names.extendedUsedUnnamedConstructorNames.add(enclosingSuperClassName);
+    }
+    super.visitSuperConstructorInvocation(node);
+  }
+
+  @override
   visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) {
     VariableDeclarationList variableList = node.variables;
     // Prepare type dependencies.
@@ -5081,6 +5081,16 @@
   void _addSuperNames(String className, List<TypeName> types) {
     types?.forEach((type) => _addSuperName(className, type));
   }
+
+  static String _getSimpleName(Identifier identifier) {
+    if (identifier is SimpleIdentifier) {
+      return identifier.name;
+    }
+    if (identifier is PrefixedIdentifier) {
+      return identifier.identifier.name;
+    }
+    return null;
+  }
 }
 
 class ReferencedNamesScope {
@@ -6134,6 +6144,8 @@
       scanner.setSourceStart(fragment.line, fragment.column);
       scanner.preserveComments = context.analysisOptions.preserveComments;
       scanner.scanGenericMethodComments = context.analysisOptions.strongMode;
+      scanner.scanLazyAssignmentOperators =
+          context.analysisOptions.enableLazyAssignmentOperators;
 
       LineInfo lineInfo = new LineInfo(scanner.lineStarts);
 
@@ -6149,6 +6161,8 @@
           new Scanner(source, new CharSequenceReader(content), errorListener);
       scanner.preserveComments = context.analysisOptions.preserveComments;
       scanner.scanGenericMethodComments = context.analysisOptions.strongMode;
+      scanner.scanLazyAssignmentOperators =
+          context.analysisOptions.enableLazyAssignmentOperators;
 
       LineInfo lineInfo = new LineInfo(scanner.lineStarts);
 
@@ -6255,7 +6269,9 @@
     if (options.strongMode) {
       CodeChecker checker = new CodeChecker(
           typeProvider,
-          new StrongTypeSystemImpl(implicitCasts: options.implicitCasts),
+          new StrongTypeSystemImpl(
+              implicitCasts: options.implicitCasts,
+              nonnullableTypes: options.nonnullableTypes),
           errorListener,
           options);
       checker.visitCompilationUnit(unit);
diff --git a/pkg/analyzer/lib/src/task/incremental_element_builder.dart b/pkg/analyzer/lib/src/task/incremental_element_builder.dart
index 5d8496d..bd317cf 100644
--- a/pkg/analyzer/lib/src/task/incremental_element_builder.dart
+++ b/pkg/analyzer/lib/src/task/incremental_element_builder.dart
@@ -29,6 +29,8 @@
 
   final Set<ClassElementDelta> superDeltas = new Set<ClassElementDelta>();
 
+  bool hasAnnotationChanges = false;
+
   final List<PropertyAccessorElement> addedAccessors =
       <PropertyAccessorElement>[];
   final List<PropertyAccessorElement> removedAccessors =
@@ -213,10 +215,19 @@
     ElementHolder classElementHolder = new ElementHolder();
     ClassElementDelta classDelta =
         new ClassElementDelta(classElement, librarySource, classElement.name);
+    // Check for annotation changes.
+    {
+      String oldAnnotationsCode =
+          TokenUtils.getFullCodeOfList(oldClass.metadata);
+      String newAnnotationsCode =
+          TokenUtils.getFullCodeOfList(newClass.metadata);
+      classDelta.hasAnnotationChanges =
+          oldAnnotationsCode != newAnnotationsCode;
+    }
     // Prepare all old member elements.
-    var removedAccessors = new Set<PropertyAccessorElement>();
-    var removedConstructors = new Set<ConstructorElement>();
-    var removedMethods = new Set<MethodElement>();
+    var removedAccessors = new Set<PropertyAccessorElement>.identity();
+    var removedConstructors = new Set<ConstructorElement>.identity();
+    var removedMethods = new Set<MethodElement>.identity();
     removedAccessors.addAll(classElement.accessors);
     removedConstructors.addAll(classElement.constructors);
     removedMethods.addAll(classElement.methods);
@@ -357,6 +368,7 @@
       }
     }
     // Update ClassElement.
+    classElement.metadata = newElement.metadata;
     classElement.accessors = newAccessors;
     classElement.constructors = classElementHolder.constructors;
     classElement.fields = newFields.values.toList();
@@ -637,7 +649,7 @@
   }
 
   /**
-   * Return the token string of all the [node] tokens.
+   * Return the token string of all the [node].
    */
   static String getFullCode(AstNode node) {
     if (node == null) {
@@ -648,6 +660,16 @@
   }
 
   /**
+   * Return the token string of all the [nodes].
+   */
+  static String getFullCodeOfList(List<AstNode> nodes) {
+    if (nodes == null) {
+      return '';
+    }
+    return nodes.map(getFullCode).join(_SEPARATOR);
+  }
+
+  /**
    * Returns all tokens (including comments) of the given [node].
    */
   static List<Token> getTokens(AstNode node) {
diff --git a/pkg/analyzer/lib/src/task/inputs.dart b/pkg/analyzer/lib/src/task/inputs.dart
index 7bc5fa1..14d127c 100644
--- a/pkg/analyzer/lib/src/task/inputs.dart
+++ b/pkg/analyzer/lib/src/task/inputs.dart
@@ -92,7 +92,9 @@
   ListTaskInput/*<V>*/ toFlattenListOf/*<V>*/(
       ListResultDescriptor/*<V>*/ subListResult) {
     return new ListToFlattenListTaskInput<E, dynamic/*=V*/ >(
-        this, subListResult.of as dynamic);
+        this,
+        (E element) =>
+            subListResult.of(element as AnalysisTarget) as TaskInput/*<V>*/);
   }
 
   ListTaskInput/*<V>*/ toList/*<V>*/(UnaryFunction<E, dynamic/*=V*/ > mapper) {
@@ -370,7 +372,7 @@
       if (currentBuilder.moveNext()) {
         return true;
       }
-      baseMap = currentBuilder.inputValue;
+      baseMap = currentBuilder.inputValue as dynamic/*=Map<K, List<V>>*/;
       if (baseMap == null) {
         // No base map could be computed due to a circular dependency.  Use an
         // empty map so that no further results will be computed.
@@ -386,7 +388,7 @@
         return true;
       }
       // Add the result value for the current Map key/value.
-      E resultValue = currentBuilder.inputValue;
+      E resultValue = currentBuilder.inputValue as dynamic/*=E*/;
       if (resultValue != null) {
         inputValue.add(resultValue);
       }
@@ -444,20 +446,22 @@
   ListTaskInput/*<V>*/ toFlattenListOf/*<V>*/(
       ListResultDescriptor/*<V>*/ subListResult) {
     return new ListToFlattenListTaskInput<E, dynamic/*=V*/ >(
-        this, subListResult.of as dynamic);
+        this,
+        (E element) =>
+            subListResult.of(element as AnalysisTarget) as TaskInput/*<V>*/);
   }
 
   @override
   ListTaskInput/*<V>*/ toListOf/*<V>*/(ResultDescriptor/*<V>*/ valueResult) {
     return new ListToListTaskInput<E, dynamic/*=V*/ >(
-        this, valueResult.of as dynamic);
+        this, (E element) => valueResult.of(element as AnalysisTarget));
   }
 
   @override
   MapTaskInput<AnalysisTarget, dynamic/*=V*/ > toMapOf/*<V>*/(
       ResultDescriptor/*<V>*/ valueResult) {
     return new ListToMapTaskInput<AnalysisTarget, dynamic/*=V*/ >(
-        this as dynamic, valueResult.of);
+        this as dynamic/*=TaskInput<List<AnalysisTarget>>*/, valueResult.of);
   }
 }
 
@@ -696,7 +700,8 @@
 abstract class TaskInputImpl<V> implements TaskInput<V> {
   @override
   ListTaskInput/*<E>*/ mappedToList/*<E>*/(List/*<E>*/ mapper(V value)) {
-    return new ObjectToListTaskInput(this, mapper);
+    return new ObjectToListTaskInput(
+        this, (Object element) => mapper(element as V));
   }
 }
 
@@ -967,7 +972,7 @@
     if (_resultValue == null) {
       // We have finished computing the list of values from which the results
       // will be derived.
-      _baseList = currentBuilder.inputValue;
+      _baseList = currentBuilder.inputValue as dynamic/*=List<B>*/;
       if (_baseList == null) {
         // No base list could be computed due to a circular dependency.  Use an
         // empty list so that no further results will be computed.
@@ -978,7 +983,8 @@
     } else {
       // We have finished computing one of the elements in the result list.
       if (currentBuilder.inputValue != null) {
-        _addResultElement(_baseListElement, currentBuilder.inputValue);
+        _addResultElement(
+            _baseListElement, currentBuilder.inputValue as dynamic/*=E*/);
       }
       _baseListIndex++;
     }
diff --git a/pkg/analyzer/lib/src/task/strong/checker.dart b/pkg/analyzer/lib/src/task/strong/checker.dart
index 98c4aa6..c074b79 100644
--- a/pkg/analyzer/lib/src/task/strong/checker.dart
+++ b/pkg/analyzer/lib/src/task/strong/checker.dart
@@ -9,6 +9,7 @@
 import 'package:analyzer/analyzer.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/ast/token.dart' show TokenType;
+import 'package:analyzer/dart/ast/token.dart';
 import 'package:analyzer/dart/ast/visitor.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/type.dart';
@@ -20,6 +21,21 @@
 
 import 'ast_properties.dart';
 
+bool isKnownFunction(Expression expression) {
+  Element element = null;
+  if (expression is FunctionExpression) {
+    return true;
+  } else if (expression is PropertyAccess) {
+    element = expression.propertyName.staticElement;
+  } else if (expression is Identifier) {
+    element = expression.staticElement;
+  }
+// First class functions and static methods, where we know the original
+// declaration, will have an exact type, so we know a downcast will fail.
+  return element is FunctionElement ||
+      element is MethodElement && element.isStatic;
+}
+
 DartType _elementType(Element e) {
   if (e == null) {
     // Malformed code - just return dynamic.
@@ -28,6 +44,8 @@
   return (e as dynamic).type;
 }
 
+// Return the field on type corresponding to member, or null if none
+// exists or the "field" is actually a getter/setter.
 PropertyInducingElement _getMemberField(
     InterfaceType type, PropertyAccessorElement member) {
   String memberName = member.name;
@@ -53,8 +71,6 @@
   return field;
 }
 
-// Return the field on type corresponding to member, or null if none
-// exists or the "field" is actually a getter/setter.
 /// Looks up the declaration that matches [member] in [type] and returns it's
 /// declared type.
 FunctionType _getMemberType(InterfaceType type, ExecutableElement member) =>
@@ -147,6 +163,7 @@
       checkAssignment(expr.expression, type);
     } else {
       _checkDowncast(expr, type);
+      _checkNonNullAssignment(expr, type);
     }
   }
 
@@ -176,13 +193,6 @@
   }
 
   @override
-  void visitCompilationUnit(CompilationUnit node) {
-    _hasImplicitCasts = false;
-    node.visitChildren(this);
-    setHasImplicitCasts(node, _hasImplicitCasts);
-  }
-
-  @override
   void visitAsExpression(AsExpression node) {
     // We could do the same check as the IsExpression below, but that is
     // potentially too conservative.  Instead, at runtime, we must fail hard
@@ -192,11 +202,16 @@
 
   @override
   void visitAssignmentExpression(AssignmentExpression node) {
-    var token = node.operator;
-    if (token.type == TokenType.EQ ||
-        token.type == TokenType.QUESTION_QUESTION_EQ) {
+    Token operator = node.operator;
+    TokenType operatorType = operator.type;
+    if (operatorType == TokenType.EQ ||
+        operatorType == TokenType.QUESTION_QUESTION_EQ) {
       DartType staticType = _getStaticType(node.leftHandSide);
       checkAssignment(node.rightHandSide, staticType);
+    } else if (operatorType == TokenType.AMPERSAND_AMPERSAND_EQ ||
+        operatorType == TokenType.BAR_BAR_EQ) {
+      checkAssignment(node.leftHandSide, typeProvider.boolType);
+      checkAssignment(node.rightHandSide, typeProvider.boolType);
     } else {
       _checkCompoundAssignment(node);
     }
@@ -259,6 +274,13 @@
   }
 
   @override
+  void visitCompilationUnit(CompilationUnit node) {
+    _hasImplicitCasts = false;
+    node.visitChildren(this);
+    setHasImplicitCasts(node, _hasImplicitCasts);
+  }
+
+  @override
   void visitConditionalExpression(ConditionalExpression node) {
     checkBoolean(node.condition);
     node.visitChildren(this);
@@ -592,11 +614,10 @@
       // typing rules may have inferred a more precise type for the variable
       // based on the initializer.
     } else {
-      var dartType = getType(type);
       for (VariableDeclaration variable in node.variables) {
         var initializer = variable.initializer;
         if (initializer != null) {
-          checkAssignment(initializer, dartType);
+          checkAssignment(initializer, type.type);
         }
       }
     }
@@ -818,6 +839,14 @@
         [declElement.name]);
   }
 
+  void _checkNonNullAssignment(Expression expression, DartType type) {
+    var exprType = expression.staticType;
+    if (rules.isNonNullableType(type) && !rules.isNonNullableType(exprType)) {
+      _recordMessage(expression, StaticTypeWarningCode.INVALID_ASSIGNMENT,
+          [exprType, type]);
+    }
+  }
+
   void _checkReturnOrYield(Expression expression, AstNode node,
       {bool yieldStar: false}) {
     FunctionBody body = node.getAncestor((n) => n is FunctionBody);
@@ -853,90 +882,6 @@
     }
   }
 
-  /// Records an implicit cast for the [expression] from [fromType] to [toType].
-  ///
-  /// This will emit the appropriate error/warning/hint message as well as mark
-  /// the AST node.
-  void _recordImplicitCast(
-      Expression expression, DartType fromType, DartType toType) {
-    // toT <:_R fromT => to <: fromT
-    // NB: classes with call methods are subtypes of function
-    // types, but the function type is not assignable to the class
-    assert(toType.isSubtypeOf(fromType) || fromType.isAssignableTo(toType));
-
-    // Inference "casts":
-    if (expression is Literal || expression is FunctionExpression) {
-      // fromT should be an exact type - this will almost certainly fail at
-      // runtime.
-      _recordMessage(expression, StrongModeCode.STATIC_TYPE_ERROR,
-          [expression, fromType, toType]);
-      return;
-    }
-
-    if (expression is InstanceCreationExpression) {
-      ConstructorElement e = expression.staticElement;
-      if (e == null || !e.isFactory) {
-        // fromT should be an exact type - this will almost certainly fail at
-        // runtime.
-
-        _recordMessage(expression, StrongModeCode.STATIC_TYPE_ERROR,
-            [expression, fromType, toType]);
-        return;
-      }
-    }
-
-    if (isKnownFunction(expression)) {
-      _recordMessage(expression, StrongModeCode.STATIC_TYPE_ERROR,
-          [expression, fromType, toType]);
-      return;
-    }
-
-    // TODO(vsm): Change this to an assert when we have generic methods and
-    // fix TypeRules._coerceTo to disallow implicit sideways casts.
-    bool downCastComposite = false;
-    if (!rules.isSubtypeOf(toType, fromType)) {
-      assert(toType.isSubtypeOf(fromType) || fromType.isAssignableTo(toType));
-      downCastComposite = true;
-    }
-
-    // Composite cast: these are more likely to fail.
-    if (!rules.isGroundType(toType)) {
-      // This cast is (probably) due to our different treatment of dynamic.
-      // It may be more likely to fail at runtime.
-      if (fromType is InterfaceType) {
-        // For class types, we'd like to allow non-generic down casts, e.g.,
-        // Iterable<T> to List<T>.  The intuition here is that raw (generic)
-        // casts are problematic, and we should complain about those.
-        var typeArgs = fromType.typeArguments;
-        downCastComposite =
-            typeArgs.isEmpty || typeArgs.any((t) => t.isDynamic);
-      } else {
-        downCastComposite = true;
-      }
-    }
-
-    var parent = expression.parent;
-    ErrorCode errorCode;
-    if (downCastComposite) {
-      errorCode = StrongModeCode.DOWN_CAST_COMPOSITE;
-    } else if (fromType.isDynamic) {
-      errorCode = StrongModeCode.DYNAMIC_CAST;
-    } else if (parent is VariableDeclaration &&
-        parent.initializer == expression) {
-      errorCode = StrongModeCode.ASSIGNMENT_CAST;
-    } else {
-      errorCode = StrongModeCode.DOWN_CAST_IMPLICIT;
-    }
-
-    _recordMessage(expression, errorCode, [fromType, toType]);
-    setImplicitCast(expression, toType);
-    _hasImplicitCasts = true;
-  }
-
-  // Produce a coercion which coerces something of type fromT
-  // to something of type toT.
-  // Returns the error coercion if the types cannot be coerced
-  // according to our current criteria.
   /// Gets the expected return type of the given function [body], either from
   /// a normal return/yield, or from a yield*.
   DartType _getExpectedReturnType(FunctionBody body, {bool yieldStar: false}) {
@@ -991,6 +936,10 @@
     }
   }
 
+  // Produce a coercion which coerces something of type fromT
+  // to something of type toT.
+  // Returns the error coercion if the types cannot be coerced
+  // according to our current criteria.
   DartType _getStaticType(Expression expr) {
     DartType t = expr.staticType ?? DynamicTypeImpl.instance;
 
@@ -1085,6 +1034,86 @@
     setIsDynamicInvoke(target, true);
   }
 
+  /// Records an implicit cast for the [expression] from [fromType] to [toType].
+  ///
+  /// This will emit the appropriate error/warning/hint message as well as mark
+  /// the AST node.
+  void _recordImplicitCast(
+      Expression expression, DartType fromType, DartType toType) {
+    // toT <:_R fromT => to <: fromT
+    // NB: classes with call methods are subtypes of function
+    // types, but the function type is not assignable to the class
+    assert(toType.isSubtypeOf(fromType) || fromType.isAssignableTo(toType));
+
+    // Inference "casts":
+    if (expression is Literal || expression is FunctionExpression) {
+      // fromT should be an exact type - this will almost certainly fail at
+      // runtime.
+      _recordMessage(expression, StrongModeCode.STATIC_TYPE_ERROR,
+          [expression, fromType, toType]);
+      return;
+    }
+
+    if (expression is InstanceCreationExpression) {
+      ConstructorElement e = expression.staticElement;
+      if (e == null || !e.isFactory) {
+        // fromT should be an exact type - this will almost certainly fail at
+        // runtime.
+
+        _recordMessage(expression, StrongModeCode.STATIC_TYPE_ERROR,
+            [expression, fromType, toType]);
+        return;
+      }
+    }
+
+    if (isKnownFunction(expression)) {
+      _recordMessage(expression, StrongModeCode.STATIC_TYPE_ERROR,
+          [expression, fromType, toType]);
+      return;
+    }
+
+    // TODO(vsm): Change this to an assert when we have generic methods and
+    // fix TypeRules._coerceTo to disallow implicit sideways casts.
+    bool downCastComposite = false;
+    if (!rules.isSubtypeOf(toType, fromType)) {
+      assert(toType.isSubtypeOf(fromType) || fromType.isAssignableTo(toType));
+      downCastComposite = true;
+    }
+
+    // Composite cast: these are more likely to fail.
+    if (!rules.isGroundType(toType)) {
+      // This cast is (probably) due to our different treatment of dynamic.
+      // It may be more likely to fail at runtime.
+      if (fromType is InterfaceType) {
+        // For class types, we'd like to allow non-generic down casts, e.g.,
+        // Iterable<T> to List<T>.  The intuition here is that raw (generic)
+        // casts are problematic, and we should complain about those.
+        var typeArgs = fromType.typeArguments;
+        downCastComposite =
+            typeArgs.isEmpty || typeArgs.any((t) => t.isDynamic);
+      } else {
+        downCastComposite = true;
+      }
+    }
+
+    var parent = expression.parent;
+    ErrorCode errorCode;
+    if (downCastComposite) {
+      errorCode = StrongModeCode.DOWN_CAST_COMPOSITE;
+    } else if (fromType.isDynamic) {
+      errorCode = StrongModeCode.DYNAMIC_CAST;
+    } else if (parent is VariableDeclaration &&
+        parent.initializer == expression) {
+      errorCode = StrongModeCode.ASSIGNMENT_CAST;
+    } else {
+      errorCode = StrongModeCode.DOWN_CAST_IMPLICIT;
+    }
+
+    _recordMessage(expression, errorCode, [fromType, toType]);
+    setImplicitCast(expression, toType);
+    _hasImplicitCasts = true;
+  }
+
   void _recordMessage(AstNode node, ErrorCode errorCode, List arguments) {
     var severity = errorCode.errorSeverity;
     if (severity == ErrorSeverity.ERROR) _failure = true;
@@ -1101,21 +1130,6 @@
   }
 }
 
-bool isKnownFunction(Expression expression) {
-  Element element = null;
-  if (expression is FunctionExpression) {
-    return true;
-  } else if (expression is PropertyAccess) {
-    element = expression.propertyName.staticElement;
-  } else if (expression is Identifier) {
-    element = expression.staticElement;
-  }
-// First class functions and static methods, where we know the original
-// declaration, will have an exact type, so we know a downcast will fail.
-  return element is FunctionElement ||
-      element is MethodElement && element.isStatic;
-}
-
 /// Checks for overriding declarations of fields and methods. This is used to
 /// check overrides between classes and superclasses, interfaces, and mixin
 /// applications.
diff --git a/pkg/analyzer/lib/src/task/strong_mode.dart b/pkg/analyzer/lib/src/task/strong_mode.dart
index 420fd61..ea4e0b3 100644
--- a/pkg/analyzer/lib/src/task/strong_mode.dart
+++ b/pkg/analyzer/lib/src/task/strong_mode.dart
@@ -279,6 +279,12 @@
     List<FunctionType> overriddenTypes = new List<FunctionType>();
     for (ExecutableElement overriddenMethod in overriddenMethods) {
       FunctionType overriddenType = overriddenMethod.type;
+      if (overriddenType == null) {
+        // TODO(brianwilkerson) I think the overridden method should always have
+        // a type, but there appears to be a bug that causes it to sometimes be
+        // null, we guard against that case by not performing inference.
+        return;
+      }
       if (overriddenType.typeFormals.isNotEmpty) {
         if (overriddenType.typeFormals.length != typeFormals.length) {
           return;
@@ -466,6 +472,7 @@
         }
         return element;
       }
+
       Element element = nonAccessor(node.staticElement);
       if (element is VariableElement && (filter == null || filter(element))) {
         results.add(element);
diff --git a/pkg/analyzer/pubspec.yaml b/pkg/analyzer/pubspec.yaml
index 42691d9..4779ab9 100644
--- a/pkg/analyzer/pubspec.yaml
+++ b/pkg/analyzer/pubspec.yaml
@@ -1,5 +1,5 @@
 name: analyzer
-version: 0.27.4-alpha.19
+version: 0.27.4
 author: Dart Team <misc@dartlang.org>
 description: Static analyzer for Dart.
 homepage: https://github.com/dart-lang/sdk/tree/master/pkg/analyzer
@@ -7,10 +7,11 @@
   sdk: '>=1.12.0 <2.0.0'
 dependencies:
   args: '>=0.12.1 <0.14.0'
+  charcode: ^1.1.0
   crypto: '>=1.1.1 <3.0.0'
   glob: ^1.0.3
   isolate: ^0.2.2
-  html: ^0.12.0
+  html: '>=0.12.0 <1.14.0'
   package_config: '>=0.1.5 <2.0.0'
   path: '>=0.9.0 <2.0.0'
   plugin: ^0.2.0
diff --git a/pkg/analyzer/test/generated/all_the_rest_test.dart b/pkg/analyzer/test/generated/all_the_rest_test.dart
index 70e1c73..63fdd85 100644
--- a/pkg/analyzer/test/generated/all_the_rest_test.dart
+++ b/pkg/analyzer/test/generated/all_the_rest_test.dart
@@ -1591,6 +1591,43 @@
     expect(method.isSynthetic, isFalse);
   }
 
+  void test_visitMethodDeclaration_duplicateField_synthetic() {
+    buildElementsForText(r'''
+class A {
+  int f;
+  int get f => 42;
+}
+''');
+    ClassDeclaration classNode = compilationUnit.declarations.single;
+    // ClassElement
+    ClassElement classElement = classNode.element;
+    expect(classElement.fields, hasLength(2));
+    expect(classElement.accessors, hasLength(3));
+    FieldElement notSyntheticFieldElement = classElement.fields
+        .singleWhere((f) => f.displayName == 'f' && !f.isSynthetic);
+    FieldElement syntheticFieldElement = classElement.fields
+        .singleWhere((f) => f.displayName == 'f' && f.isSynthetic);
+    PropertyAccessorElement syntheticGetterElement = classElement.accessors
+        .singleWhere(
+            (a) => a.displayName == 'f' && a.isGetter && a.isSynthetic);
+    PropertyAccessorElement syntheticSetterElement = classElement.accessors
+        .singleWhere(
+            (a) => a.displayName == 'f' && a.isSetter && a.isSynthetic);
+    PropertyAccessorElement notSyntheticGetterElement = classElement.accessors
+        .singleWhere(
+            (a) => a.displayName == 'f' && a.isGetter && !a.isSynthetic);
+    expect(notSyntheticFieldElement.getter, same(syntheticGetterElement));
+    expect(notSyntheticFieldElement.setter, same(syntheticSetterElement));
+    expect(syntheticFieldElement.getter, same(notSyntheticGetterElement));
+    expect(syntheticFieldElement.setter, isNull);
+    // class members nodes and their elements
+    FieldDeclaration fieldDeclNode = classNode.members[0];
+    VariableDeclaration fieldNode = fieldDeclNode.fields.variables.single;
+    MethodDeclaration getterNode = classNode.members[1];
+    expect(fieldNode.element, notSyntheticFieldElement);
+    expect(getterNode.element, notSyntheticGetterElement);
+  }
+
   void test_visitMethodDeclaration_external() {
     // external m();
     ElementHolder holder = new ElementHolder();
@@ -2565,20 +2602,6 @@
 
 @reflectiveTest
 class ElementLocatorTest extends ResolverTestCase {
-  void test_locate_ExportDirective() {
-    AstNode id = _findNodeIn("export", "export 'dart:core';");
-    Element element = ElementLocator.locate(id);
-    EngineTestCase.assertInstanceOf(
-        (obj) => obj is ExportElement, ExportElement, element);
-  }
-
-  void test_locate_Identifier_libraryDirective() {
-    AstNode id = _findNodeIn("foo", "library foo.bar;");
-    Element element = ElementLocator.locate(id);
-    EngineTestCase.assertInstanceOf(
-        (obj) => obj is LibraryElement, LibraryElement, element);
-  }
-
   void fail_locate_Identifier_partOfDirective() {
     // Can't resolve the library element without the library declaration.
     //    AstNode id = findNodeIn("foo", "part of foo.bar;");
@@ -2643,6 +2666,13 @@
         (obj) => obj is ConstructorElement, ConstructorElement, element);
   }
 
+  void test_locate_ExportDirective() {
+    AstNode id = _findNodeIn("export", "export 'dart:core';");
+    Element element = ElementLocator.locate(id);
+    EngineTestCase.assertInstanceOf(
+        (obj) => obj is ExportElement, ExportElement, element);
+  }
+
   void test_locate_FunctionDeclaration() {
     AstNode id = _findNodeIn("f", "int f() => 3;");
     FunctionDeclaration declaration =
@@ -2724,6 +2754,13 @@
         (obj) => obj is FieldElement, FieldElement, element);
   }
 
+  void test_locate_Identifier_libraryDirective() {
+    AstNode id = _findNodeIn("foo", "library foo.bar;");
+    Element element = ElementLocator.locate(id);
+    EngineTestCase.assertInstanceOf(
+        (obj) => obj is LibraryElement, LibraryElement, element);
+  }
+
   void test_locate_Identifier_propertyAccess() {
     AstNode id = _findNodeIn(
         "length",
@@ -3287,6 +3324,11 @@
     _assertFalse("v = 1;");
   }
 
+  void test_assignmentExpression_compound_lazy() {
+    enableLazyAssignmentOperators = true;
+    _assertFalse("v ||= false;");
+  }
+
   void test_assignmentExpression_lhs_throw() {
     _assertTrue("a[throw ''] = 0;");
   }
@@ -3467,14 +3509,6 @@
     expect(new ExitDetector(), isNotNull);
   }
 
-  void test_doStatement_return() {
-    _assertTrue("{ do { return null; } while (1 == 2); }");
-  }
-
-  void test_doStatement_throwCondition() {
-    _assertTrue("{ do {} while (throw ''); }");
-  }
-
   void test_doStatement_break_and_throw() {
     _assertFalse("{ do { if (1==1) break; throw 'T'; } while (0==1); }");
   }
@@ -3483,19 +3517,6 @@
     _assertFalse("{ do { if (1==1) continue; throw 'T'; } while (0==1); }");
   }
 
-  void test_doStatement_continueInSwitch_and_throw() {
-    _assertFalse('''
-{
-  do {
-    switch (1) {
-      L: case 0: continue;
-      M: case 1: break;
-    }
-    throw 'T';
-  } while (0 == 1);
-}''');
-  }
-
   void test_doStatement_continueDoInSwitch_and_throw() {
     _assertFalse('''
 {
@@ -3509,6 +3530,27 @@
 }''');
   }
 
+  void test_doStatement_continueInSwitch_and_throw() {
+    _assertFalse('''
+{
+  do {
+    switch (1) {
+      L: case 0: continue;
+      M: case 1: break;
+    }
+    throw 'T';
+  } while (0 == 1);
+}''');
+  }
+
+  void test_doStatement_return() {
+    _assertTrue("{ do { return null; } while (1 == 2); }");
+  }
+
+  void test_doStatement_throwCondition() {
+    _assertTrue("{ do {} while (throw ''); }");
+  }
+
   void test_doStatement_true_break() {
     _assertFalse("{ do { break; } while (true); }");
   }
@@ -3521,7 +3563,6 @@
     _assertTrue("{ x: do { continue x; } while (true); }");
   }
 
-
   void test_doStatement_true_if_return() {
     _assertTrue("{ do { if (true) {return null;} } while (true); }");
   }
@@ -3924,6 +3965,10 @@
     _assertFalse("{ while (true) { break; } }");
   }
 
+  void test_whileStatement_true_break_and_throw() {
+    _assertFalse("{ while (true) { if (1==1) break; throw 'T'; } }");
+  }
+
   void test_whileStatement_true_continue() {
     _assertTrue("{ while (true) { continue; } }");
   }
@@ -3952,16 +3997,13 @@
     _assertTrue("{ while (true) { throw ''; } }");
   }
 
-  void test_whileStatement_true_break_and_throw() {
-    _assertFalse("{ while (true) { if (1==1) break; throw 'T'; } }");
-  }
-
   void _assertFalse(String source) {
     _assertHasReturn(false, source);
   }
 
   void _assertHasReturn(bool expectedResult, String source) {
-    Statement statement = ParserTestCase.parseStatement(source);
+    Statement statement = ParserTestCase.parseStatement(
+        source, [], enableLazyAssignmentOperators);
     expect(ExitDetector.exits(statement), expectedResult);
   }
 
@@ -4085,20 +4127,6 @@
     _assertNthStatementDoesNotExit(source, 0);
   }
 
-  void test_whileStatement_switchWithBreakWithLabel() {
-    Source source = addSource(r'''
-void f() {
-  x: while (true) {
-    switch (true) {
-      case false: break;
-      case true: break x;
-    }
-  }
-}
-''');
-    _assertNthStatementDoesNotExit(source, 0);
-  }
-
   void test_whileStatement_breakWithLabel_afterExting() {
     Source source = addSource(r'''
 void f() {
@@ -4113,6 +4141,20 @@
     _assertNthStatementExits(source, 0);
   }
 
+  void test_whileStatement_switchWithBreakWithLabel() {
+    Source source = addSource(r'''
+void f() {
+  x: while (true) {
+    switch (true) {
+      case false: break;
+      case true: break x;
+    }
+  }
+}
+''');
+    _assertNthStatementDoesNotExit(source, 0);
+  }
+
   void test_yieldStatement_plain() {
     Source source = addSource(r'''
 void f() sync* {
diff --git a/pkg/analyzer/test/generated/parser_test.dart b/pkg/analyzer/test/generated/parser_test.dart
index ee61b20..1d3577e 100644
--- a/pkg/analyzer/test/generated/parser_test.dart
+++ b/pkg/analyzer/test/generated/parser_test.dart
@@ -2786,6 +2786,12 @@
   bool enableGenericMethodComments = false;
 
   /**
+   * A flag indicating whether lazy assignment operators should be enabled for
+   * the test.
+   */
+  bool enableLazyAssignmentOperators = false;
+
+  /**
    * Return a CommentAndMetadata object with the given values that can be used for testing.
    *
    * @param comment the comment to be wrapped in the object
@@ -2829,6 +2835,7 @@
     Scanner scanner =
         new Scanner(null, new CharSequenceReader(source), listener);
     scanner.scanGenericMethodComments = enableGenericMethodComments;
+    scanner.scanLazyAssignmentOperators = enableLazyAssignmentOperators;
     Token tokenStream = scanner.tokenize();
     listener.setLineInfo(new TestSource(), scanner.lineStarts);
     //
@@ -3040,19 +3047,18 @@
   }
 
   /**
-   * Parse the given source as a statement.
-   *
-   * @param source the source to be parsed
-   * @param errorCodes the error codes of the errors that are expected to be found
-   * @return the statement that was parsed
-   * @throws Exception if the source could not be parsed, if the compilation errors in the source do
-   *           not match those that are expected, or if the result would have been `null`
+   * Parse the given [source] as a statement. The [errorCodes] are the error
+   * codes of the errors that are expected to be found. If
+   * [enableLazyAssignmentOperators] is `true`, then lazy assignment operators
+   * should be enabled.
    */
   static Statement parseStatement(String source,
-      [List<ErrorCode> errorCodes = ErrorCode.EMPTY_LIST]) {
+      [List<ErrorCode> errorCodes = ErrorCode.EMPTY_LIST,
+      bool enableLazyAssignmentOperators]) {
     GatheringErrorListener listener = new GatheringErrorListener();
     Scanner scanner =
         new Scanner(null, new CharSequenceReader(source), listener);
+    scanner.scanLazyAssignmentOperators = enableLazyAssignmentOperators;
     listener.setLineInfo(new TestSource(), scanner.lineStarts);
     Token token = scanner.tokenize();
     Parser parser = createParser(listener);
@@ -7452,6 +7458,15 @@
     expect(expression.rightHandSide, isNotNull);
   }
 
+  void test_parseExpression_assign_compound() {
+    enableLazyAssignmentOperators = true;
+    AssignmentExpression expression = parse4("parseExpression", "x ||= y");
+    expect(expression.leftHandSide, isNotNull);
+    expect(expression.operator, isNotNull);
+    expect(expression.operator.type, TokenType.BAR_BAR_EQ);
+    expect(expression.rightHandSide, isNotNull);
+  }
+
   void test_parseExpression_comparison() {
     BinaryExpression expression = parse4("parseExpression", "--a.b == c");
     expect(expression.leftOperand, isNotNull);
diff --git a/pkg/analyzer/test/generated/scanner_test.dart b/pkg/analyzer/test/generated/scanner_test.dart
index 071231e..cb75945 100644
--- a/pkg/analyzer/test/generated/scanner_test.dart
+++ b/pkg/analyzer/test/generated/scanner_test.dart
@@ -192,6 +192,11 @@
     _assertToken(TokenType.AMPERSAND_AMPERSAND, "&&");
   }
 
+  void test_ampersand_ampersand_eq() {
+    _assertToken(TokenType.AMPERSAND_AMPERSAND_EQ, "&&=",
+        lazyAssignmentOperators: true);
+  }
+
   void test_ampersand_eq() {
     _assertToken(TokenType.AMPERSAND_EQ, "&=");
   }
@@ -224,6 +229,10 @@
     _assertToken(TokenType.BAR_BAR, "||");
   }
 
+  void test_bar_bar_eq() {
+    _assertToken(TokenType.BAR_BAR_EQ, "||=", lazyAssignmentOperators: true);
+  }
+
   void test_bar_eq() {
     _assertToken(TokenType.BAR_EQ, "|=");
   }
@@ -1177,8 +1186,10 @@
    * Assert that the token scanned from the given [source] has the
    * [expectedType].
    */
-  Token _assertToken(TokenType expectedType, String source) {
-    Token originalToken = _scan(source);
+  Token _assertToken(TokenType expectedType, String source,
+      {bool lazyAssignmentOperators: false}) {
+    Token originalToken =
+        _scan(source, lazyAssignmentOperators: lazyAssignmentOperators);
     expect(originalToken, isNotNull);
     expect(originalToken.type, expectedType);
     expect(originalToken.offset, 0);
@@ -1190,7 +1201,8 @@
       return originalToken;
     } else if (expectedType == TokenType.SINGLE_LINE_COMMENT) {
       // Adding space to an end-of-line comment changes the comment.
-      Token tokenWithSpaces = _scan(" $source");
+      Token tokenWithSpaces =
+          _scan(" $source", lazyAssignmentOperators: lazyAssignmentOperators);
       expect(tokenWithSpaces, isNotNull);
       expect(tokenWithSpaces.type, expectedType);
       expect(tokenWithSpaces.offset, 1);
@@ -1199,20 +1211,23 @@
       return originalToken;
     } else if (expectedType == TokenType.INT ||
         expectedType == TokenType.DOUBLE) {
-      Token tokenWithLowerD = _scan("${source}d");
+      Token tokenWithLowerD =
+          _scan("${source}d", lazyAssignmentOperators: lazyAssignmentOperators);
       expect(tokenWithLowerD, isNotNull);
       expect(tokenWithLowerD.type, expectedType);
       expect(tokenWithLowerD.offset, 0);
       expect(tokenWithLowerD.length, source.length);
       expect(tokenWithLowerD.lexeme, source);
-      Token tokenWithUpperD = _scan("${source}D");
+      Token tokenWithUpperD =
+          _scan("${source}D", lazyAssignmentOperators: lazyAssignmentOperators);
       expect(tokenWithUpperD, isNotNull);
       expect(tokenWithUpperD.type, expectedType);
       expect(tokenWithUpperD.offset, 0);
       expect(tokenWithUpperD.length, source.length);
       expect(tokenWithUpperD.lexeme, source);
     }
-    Token tokenWithSpaces = _scan(" $source ");
+    Token tokenWithSpaces =
+        _scan(" $source ", lazyAssignmentOperators: lazyAssignmentOperators);
     expect(tokenWithSpaces, isNotNull);
     expect(tokenWithSpaces.type, expectedType);
     expect(tokenWithSpaces.offset, 1);
@@ -1249,21 +1264,24 @@
     expect(token.type, TokenType.EOF);
   }
 
-  Token _scan(String source, {bool genericMethodComments: false}) {
+  Token _scan(String source,
+      {bool genericMethodComments: false,
+      bool lazyAssignmentOperators: false}) {
     GatheringErrorListener listener = new GatheringErrorListener();
     Token token = _scanWithListener(source, listener,
-        genericMethodComments: genericMethodComments);
+        genericMethodComments: genericMethodComments,
+        lazyAssignmentOperators: lazyAssignmentOperators);
     listener.assertNoErrors();
     return token;
   }
 
   Token _scanWithListener(String source, GatheringErrorListener listener,
-      {bool genericMethodComments: false}) {
+      {bool genericMethodComments: false,
+      bool lazyAssignmentOperators: false}) {
     Scanner scanner =
         new Scanner(null, new CharSequenceReader(source), listener);
-    if (genericMethodComments) {
-      scanner.scanGenericMethodComments = true;
-    }
+    scanner.scanGenericMethodComments = genericMethodComments;
+    scanner.scanLazyAssignmentOperators = lazyAssignmentOperators;
     Token result = scanner.tokenize();
     listener.setLineInfo(new TestSource(), scanner.lineStarts);
     return result;
diff --git a/pkg/analyzer/test/generated/sdk_test.dart b/pkg/analyzer/test/generated/sdk_test.dart
index 7038f4d..ab634cb 100644
--- a/pkg/analyzer/test/generated/sdk_test.dart
+++ b/pkg/analyzer/test/generated/sdk_test.dart
@@ -66,7 +66,7 @@
     return null;
   }
 
-  DartSdk _failIfCreated(_) {
+  DartSdk _failIfCreated(AnalysisOptions _) {
     fail('Use of sdkCreator');
     return null;
   }
diff --git a/pkg/analyzer/test/generated/static_type_analyzer_test.dart b/pkg/analyzer/test/generated/static_type_analyzer_test.dart
index 23fac6b..2795236 100644
--- a/pkg/analyzer/test/generated/static_type_analyzer_test.dart
+++ b/pkg/analyzer/test/generated/static_type_analyzer_test.dart
@@ -394,6 +394,19 @@
     validate(TokenType.TILDE_SLASH_EQ);
   }
 
+  void test_visitAssignmentExpression_compound_lazy() {
+    validate(TokenType operator) {
+      InterfaceType boolType = _typeProvider.boolType;
+      SimpleIdentifier identifier = _resolvedVariable(boolType, "b");
+      AssignmentExpression node = AstFactory.assignmentExpression(
+          identifier, operator, _resolvedBool(true));
+      expect(_analyze(node), same(boolType));
+      _listener.assertNoErrors();
+    }
+    validate(TokenType.AMPERSAND_AMPERSAND_EQ);
+    validate(TokenType.BAR_BAR_EQ);
+  }
+
   void test_visitAssignmentExpression_compound_plusID() {
     validate(TokenType operator) {
       InterfaceType numType = _typeProvider.numType;
@@ -1565,6 +1578,16 @@
   }
 
   /**
+   * Return a boolean literal with the given [value] that has been resolved to
+   * the correct type.
+   */
+  BooleanLiteral _resolvedBool(bool value) {
+    BooleanLiteral literal = AstFactory.booleanLiteral(value);
+    literal.staticType = _typeProvider.intType;
+    return literal;
+  }
+
+  /**
    * Return an integer literal that has been resolved to the correct type.
    *
    * @param value the value of the literal
diff --git a/pkg/analyzer/test/generated/strong_mode_test.dart b/pkg/analyzer/test/generated/strong_mode_test.dart
index be5ee6b..75f4ea9 100644
--- a/pkg/analyzer/test/generated/strong_mode_test.dart
+++ b/pkg/analyzer/test/generated/strong_mode_test.dart
@@ -222,7 +222,7 @@
     check("g1", _isStreamOf([_isDynamic]));
 
     check("g2", _isListOf(_isInt));
-    check("g3", _isStreamOf([_isListOf(_isInt)]));
+    check("g3", _isStreamOf([(DartType type) => _isListOf(_isInt)(type)]));
   }
 
   void test_async_star_propagation() {
@@ -249,7 +249,7 @@
     check("g1", _isStreamOf([_isDynamic]));
 
     check("g2", _isListOf(_isInt));
-    check("g3", _isStreamOf([_isListOf(_isInt)]));
+    check("g3", _isStreamOf([(DartType type) => _isListOf(_isInt)(type)]));
   }
 
   void test_cascadeExpression() {
@@ -698,7 +698,7 @@
 
     Asserter<InterfaceType> assertListOfInt = _isListOf(_isInt);
     Asserter<InterfaceType> assertMapOfIntToListOfInt =
-        _isMapOf(_isInt, assertListOfInt);
+        _isMapOf(_isInt, (DartType type) => assertListOfInt(type));
 
     VariableDeclaration mapB = AstFinder.getFieldInClass(unit, "B", "map");
     MethodDeclaration mapC = AstFinder.getMethodInClass(unit, "C", "map");
@@ -955,7 +955,8 @@
     }
 
     Asserter<InterfaceType> assertListOfInt = _isListOf(_isInt);
-    Asserter<InterfaceType> assertListOfListOfInt = _isListOf(assertListOfInt);
+    Asserter<InterfaceType> assertListOfListOfInt =
+        _isListOf((DartType type) => assertListOfInt(type));
 
     assertListOfListOfInt(literal(0).staticType);
     assertListOfListOfInt(literal(1).staticType);
@@ -1095,7 +1096,7 @@
 
     Asserter<InterfaceType> assertListOfString = _isListOf(_isString);
     Asserter<InterfaceType> assertMapOfIntToListOfString =
-        _isMapOf(_isInt, assertListOfString);
+        _isMapOf(_isInt, (DartType type) => assertListOfString(type));
 
     assertMapOfIntToListOfString(literal(0).staticType);
     assertMapOfIntToListOfString(literal(1).staticType);
@@ -1249,7 +1250,7 @@
     check("f1", _isListOf(_isDynamic));
 
     check("f2", _isListOf(_isInt));
-    check("f3", _isListOf(_isListOf(_isInt)));
+    check("f3", _isListOf((DartType type) => _isListOf(_isInt)(type)));
   }
 
   void test_sync_star_propagation() {
@@ -1276,7 +1277,7 @@
     check("f1", _isListOf(_isDynamic));
 
     check("f2", _isListOf(_isInt));
-    check("f3", _isListOf(_isListOf(_isInt)));
+    check("f3", _isListOf((DartType type) => _isListOf(_isInt)(type)));
   }
 }
 
diff --git a/pkg/analyzer/test/src/context/builder_test.dart b/pkg/analyzer/test/src/context/builder_test.dart
index 50489e4..1f94afa 100644
--- a/pkg/analyzer/test/src/context/builder_test.dart
+++ b/pkg/analyzer/test/src/context/builder_test.dart
@@ -679,7 +679,6 @@
     expect(actual.enableGenericMethods, expected.enableGenericMethods);
     expect(actual.enableSuperMixins, expected.enableSuperMixins);
     expect(actual.enableTiming, expected.enableTiming);
-    expect(actual.enableTrailingCommas, expected.enableTrailingCommas);
     expect(actual.generateImplicitErrors, expected.generateImplicitErrors);
     expect(actual.generateSdkErrors, expected.generateSdkErrors);
     expect(actual.hint, expected.hint);
diff --git a/pkg/analyzer/test/src/context/cache_test.dart b/pkg/analyzer/test/src/context/cache_test.dart
index ab35ffb..dc09c80 100644
--- a/pkg/analyzer/test/src/context/cache_test.dart
+++ b/pkg/analyzer/test/src/context/cache_test.dart
@@ -701,6 +701,12 @@
         unorderedEquals([new TargetedResult(target, result2)]));
     expect(entry.getResultData(result2).dependedOnResults,
         unorderedEquals([new TargetedResult(target, result1)]));
+    // record invalidated results
+    Set<TargetedResult> reportedInvalidatedResults = new Set<TargetedResult>();
+    cache.onResultInvalidated.listen((InvalidatedResult invalidatedResult) {
+      reportedInvalidatedResults.add(new TargetedResult(
+          invalidatedResult.entry.target, invalidatedResult.descriptor));
+    });
     // invalidate result2 with Delta: keep result2, invalidate result3
     entry.setState(result2, CacheState.INVALID,
         delta: new _KeepContinueDelta(target, result2));
@@ -712,6 +718,10 @@
         unorderedEquals([new TargetedResult(target, result2)]));
     expect(entry.getResultData(result2).dependedOnResults,
         unorderedEquals([new TargetedResult(target, result1)]));
+    // (target, result3) was reported as invalidated
+    // (target, result2) was NOT reported
+    expect(reportedInvalidatedResults,
+        unorderedEquals([new TargetedResult(target, result3)]));
   }
 
   test_setState_valid() {
diff --git a/pkg/analyzer/test/src/context/context_test.dart b/pkg/analyzer/test/src/context/context_test.dart
index 8c13cf5..f5b695f 100644
--- a/pkg/analyzer/test/src/context/context_test.dart
+++ b/pkg/analyzer/test/src/context/context_test.dart
@@ -338,7 +338,7 @@
     // initially: A
     {
       LibraryElement libraryElement =
-          context.getResult(exporterSource, LIBRARY_ELEMENT1) as LibraryElement;
+          context.getResult(exporterSource, LIBRARY_ELEMENT1);
       expect(libraryElement.exportNamespace.definedNames.keys,
           unorderedEquals(['A']));
     }
@@ -350,7 +350,7 @@
     _performPendingAnalysisTasks();
     {
       LibraryElement libraryElement =
-          context.getResult(exporterSource, LIBRARY_ELEMENT1) as LibraryElement;
+          context.getResult(exporterSource, LIBRARY_ELEMENT1);
       expect(libraryElement.exportNamespace.definedNames.keys,
           unorderedEquals(['B']));
     }
@@ -455,8 +455,42 @@
     });
   }
 
-  void test_cacheConsistencyValidator_computed() {
+  void test_applyChanges_removeUsedLibrary_addAgain() {
+    String codeA = r'''
+import 'b.dart';
+B b = null;
+''';
+    String codeB = r'''
+class B {}
+''';
+    Source a = addSource('/a.dart', codeA);
+    Source b = addSource('/b.dart', codeB);
+    CacheState getErrorsState(Source source) =>
+        context.analysisCache.getState(source, LIBRARY_ERRORS_READY);
+    _performPendingAnalysisTasks();
+    expect(context.getErrors(a).errors, hasLength(0));
+    // Remove b.dart - errors in a.dart are invalidated and recomputed.
+    // Now a.dart has an error.
+    _removeSource(b);
+    expect(getErrorsState(a), CacheState.INVALID);
+    _performPendingAnalysisTasks();
+    expect(getErrorsState(a), CacheState.VALID);
+    expect(context.getErrors(a).errors, hasLength(isPositive));
+    // Add b.dart - errors in a.dart are invalidated and recomputed.
+    // The reason is that a.dart adds dependencies on (not existing) b.dart
+    // results in cache.
+    // Now a.dart does not have errors.
+    addSource('/b.dart', codeB);
+    expect(getErrorsState(a), CacheState.INVALID);
+    _performPendingAnalysisTasks();
+    expect(getErrorsState(a), CacheState.VALID);
+    expect(context.getErrors(a).errors, hasLength(0));
+  }
+
+  void test_cacheConsistencyValidator_computed_deleted() {
     CacheConsistencyValidator validator = context.cacheConsistencyValidator;
+    var stat = PerformanceStatistics.cacheConsistencyValidationStatistics;
+    stat.reset();
     // Add sources.
     MemoryResourceProvider resourceProvider = new MemoryResourceProvider();
     String path1 = '/test1.dart';
@@ -470,6 +504,45 @@
         validator.sourceModificationTimesComputed([source1, source2],
             [source1.modificationStamp, source2.modificationStamp]),
         isFalse);
+    expect(stat.numOfChanged, 0);
+    expect(stat.numOfRemoved, 0);
+    // Add overlay
+    context.setContents(source1, '// 1-2');
+    expect(
+        validator.sourceModificationTimesComputed(
+            [source1, source2], [-1, source2.modificationStamp]),
+        isFalse);
+    context.setContents(source1, null);
+    expect(stat.numOfChanged, 0);
+    expect(stat.numOfRemoved, 0);
+    // Different modification times.
+    expect(
+        validator.sourceModificationTimesComputed(
+            [source1, source2], [-1, source2.modificationStamp]),
+        isTrue);
+    expect(stat.numOfChanged, 0);
+    expect(stat.numOfRemoved, 1);
+  }
+
+  void test_cacheConsistencyValidator_computed_modified() {
+    CacheConsistencyValidator validator = context.cacheConsistencyValidator;
+    var stat = PerformanceStatistics.cacheConsistencyValidationStatistics;
+    stat.reset();
+    // Add sources.
+    MemoryResourceProvider resourceProvider = new MemoryResourceProvider();
+    String path1 = '/test1.dart';
+    String path2 = '/test2.dart';
+    Source source1 = resourceProvider.newFile(path1, '// 1-1').createSource();
+    Source source2 = resourceProvider.newFile(path2, '// 2-1').createSource();
+    context.applyChanges(
+        new ChangeSet()..addedSource(source1)..addedSource(source2));
+    // Same modification times.
+    expect(
+        validator.sourceModificationTimesComputed([source1, source2],
+            [source1.modificationStamp, source2.modificationStamp]),
+        isFalse);
+    expect(stat.numOfChanged, 0);
+    expect(stat.numOfRemoved, 0);
     // Add overlay
     context.setContents(source1, '// 1-2');
     expect(
@@ -477,11 +550,15 @@
             [source1.modificationStamp + 1, source2.modificationStamp]),
         isFalse);
     context.setContents(source1, null);
+    expect(stat.numOfChanged, 0);
+    expect(stat.numOfRemoved, 0);
     // Different modification times.
     expect(
         validator.sourceModificationTimesComputed([source1, source2],
             [source1.modificationStamp + 1, source2.modificationStamp]),
         isTrue);
+    expect(stat.numOfChanged, 1);
+    expect(stat.numOfRemoved, 0);
   }
 
   void test_cacheConsistencyValidator_getSources() {
@@ -2806,6 +2883,80 @@
     _assertValid(b, LIBRARY_ERRORS_READY);
   }
 
+  void test_class_annotation_add_deprecated() {
+    Source a = addSource(
+        '/a.dart',
+        r'''
+class A {}
+''');
+    Source b = addSource(
+        '/b.dart',
+        r'''
+import 'a.dart';
+List<A> foo() => [];
+''');
+    _performPendingAnalysisTasks();
+    expect(context.getErrors(b).errors, hasLength(0));
+    // Add @deprecated annotation.
+    // b.dart has valid resolution, because A is still A, so only errors are
+    // invalidated.
+    context.setContents(
+        a,
+        r'''
+@deprecated
+class A {}
+''');
+    _assertValidForChangedLibrary(a);
+    _assertInvalid(a, LIBRARY_ERRORS_READY);
+    _assertValidForDependentLibrary(b);
+    _assertInvalid(b, LIBRARY_ERRORS_READY);
+    _assertValidAllResolution(b);
+    // Analysis is done successfully.
+    _performPendingAnalysisTasks();
+    _assertValid(a, LIBRARY_ERRORS_READY);
+    _assertValid(a, READY_RESOLVED_UNIT);
+    _assertValid(b, LIBRARY_ERRORS_READY);
+    _assertValid(b, READY_RESOLVED_UNIT);
+    expect(context.getErrors(b).errors, hasLength(1));
+  }
+
+  void test_class_annotation_remove_deprecated() {
+    Source a = addSource(
+        '/a.dart',
+        r'''
+@deprecated
+class A {}
+''');
+    Source b = addSource(
+        '/b.dart',
+        r'''
+import 'a.dart';
+List<A> foo() => [];
+''');
+    _performPendingAnalysisTasks();
+    expect(context.getErrors(b).errors, hasLength(1));
+    // Add @deprecated annotation.
+    // b.dart has valid resolution, because A is still A, so only errors are
+    // invalidated.
+    context.setContents(
+        a,
+        r'''
+class A {}
+''');
+    _assertValidForChangedLibrary(a);
+    _assertInvalid(a, LIBRARY_ERRORS_READY);
+    _assertValidForDependentLibrary(b);
+    _assertInvalid(b, LIBRARY_ERRORS_READY);
+    _assertValidAllResolution(b);
+    // Analysis is done successfully.
+    _performPendingAnalysisTasks();
+    _assertValid(a, LIBRARY_ERRORS_READY);
+    _assertValid(a, READY_RESOLVED_UNIT);
+    _assertValid(b, LIBRARY_ERRORS_READY);
+    _assertValid(b, READY_RESOLVED_UNIT);
+    expect(context.getErrors(b).errors, hasLength(0));
+  }
+
   void test_class_constructor_named_changeName() {
     // Update a.dart: change A.named() to A.named2().
     //   b.dart is invalid, because it references A.named().
@@ -3407,30 +3558,6 @@
     _assertInvalid(b, LIBRARY_ERRORS_READY);
   }
 
-  void test_sequence_add_annotation() {
-    Source a = addSource(
-        '/a.dart',
-        r'''
-const myAnnotation = const Object();
-class A {}
-''');
-    _performPendingAnalysisTasks();
-    // Add a new annotation.
-    context.setContents(
-        a,
-        r'''
-const myAnnotation = const Object();
-@myAnnotation
-class A {}
-''');
-    _assertValidForChangedLibrary(a);
-    _assertInvalid(a, LIBRARY_ERRORS_READY);
-    // Analysis is done successfully.
-    _performPendingAnalysisTasks();
-    _assertValid(a, LIBRARY_ERRORS_READY);
-    _assertValid(a, READY_RESOLVED_UNIT);
-  }
-
   void test_sequence_applyChanges_changedSource() {
     Source a = addSource(
         '/a.dart',
@@ -3927,6 +4054,40 @@
     _assertInvalid(d, LIBRARY_ERRORS_READY);
   }
 
+  void test_sequence_duplicateField_syntheticAndNot_renameNotSynthetic() {
+    context.analysisOptions =
+        new AnalysisOptionsImpl.from(context.analysisOptions)
+          ..strongMode = true;
+    Source a = addSource(
+        '/a.dart',
+        r'''
+class A {
+  int foo;
+  int get foo => 1;
+}
+class B extends A {
+  int get foo => 2;
+}
+''');
+    _performPendingAnalysisTasks();
+    expect(context.getErrors(a).errors, hasLength(2));
+    // Update a.dart: rename "int foo" to "int bar".
+    // The strong mode "getter cannot override field" error is gone.
+    context.setContents(
+        a,
+        r'''
+class A {
+  int bar;
+  int get foo => 1;
+}
+class B extends A {
+  int get foo => 2;
+}
+''');
+    _performPendingAnalysisTasks();
+    expect(context.getErrors(a).errors, isEmpty);
+  }
+
   void test_sequence_inBodyChange_addRef_deltaChange() {
     Source a = addSource(
         '/a.dart',
diff --git a/pkg/analyzer/test/src/dart/sdk/sdk_test.dart b/pkg/analyzer/test/src/dart/sdk/sdk_test.dart
new file mode 100644
index 0000000..e613f96
--- /dev/null
+++ b/pkg/analyzer/test/src/dart/sdk/sdk_test.dart
@@ -0,0 +1,367 @@
+// Copyright (c) 2014, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library analyzer.test.generated.sdk_test;
+
+import 'package:analyzer/file_system/file_system.dart';
+import 'package:analyzer/file_system/memory_file_system.dart';
+import 'package:analyzer/source/embedder.dart' show EmbedderYamlLocator;
+import 'package:analyzer/src/dart/sdk/sdk.dart';
+import 'package:analyzer/src/generated/engine.dart';
+import 'package:analyzer/src/generated/java_engine_io.dart';
+import 'package:analyzer/src/generated/sdk.dart';
+import 'package:analyzer/src/generated/source.dart';
+import 'package:unittest/unittest.dart';
+
+import '../../../generated/test_support.dart';
+import '../../../reflective_tests.dart';
+import '../../../resource_utils.dart';
+import '../../../source/embedder_test.dart';
+import '../../../utils.dart';
+
+main() {
+  initializeTestEnvironment();
+  runReflectiveTests(EmbedderSdkTest);
+  runReflectiveTests(FolderBasedDartSdkTest);
+  runReflectiveTests(SDKLibrariesReaderTest);
+}
+
+@reflectiveTest
+class EmbedderSdkTest extends EmbedderRelatedTest {
+  void test_creation() {
+    EmbedderYamlLocator locator = new EmbedderYamlLocator({
+      'fox': [pathTranslator.getResource('/tmp')]
+    });
+    EmbedderSdk sdk = new EmbedderSdk(resourceProvider, locator.embedderYamls);
+
+    expect(sdk.urlMappings, hasLength(5));
+  }
+
+  void test_fromFileUri() {
+    EmbedderYamlLocator locator = new EmbedderYamlLocator({
+      'fox': [pathTranslator.getResource('/tmp')]
+    });
+    EmbedderSdk sdk = new EmbedderSdk(resourceProvider, locator.embedderYamls);
+
+    expectSource(String posixPath, String dartUri) {
+      Uri uri = Uri.parse(posixToOSFileUri(posixPath));
+      Source source = sdk.fromFileUri(uri);
+      expect(source, isNotNull, reason: posixPath);
+      expect(source.uri.toString(), dartUri);
+      expect(source.fullName, posixToOSPath(posixPath));
+    }
+
+    expectSource('/tmp/slippy.dart', 'dart:fox');
+    expectSource('/tmp/deep/directory/file.dart', 'dart:deep');
+    expectSource('/tmp/deep/directory/part.dart', 'dart:deep/part.dart');
+  }
+
+  void test_getSdkLibrary() {
+    EmbedderYamlLocator locator = new EmbedderYamlLocator({
+      'fox': [pathTranslator.getResource('/tmp')]
+    });
+    EmbedderSdk sdk = new EmbedderSdk(resourceProvider, locator.embedderYamls);
+
+    SdkLibrary lib = sdk.getSdkLibrary('dart:fox');
+    expect(lib, isNotNull);
+    expect(lib.path, posixToOSPath('/tmp/slippy.dart'));
+    expect(lib.shortName, 'dart:fox');
+  }
+
+  void test_mapDartUri() {
+    EmbedderYamlLocator locator = new EmbedderYamlLocator({
+      'fox': [pathTranslator.getResource('/tmp')]
+    });
+    EmbedderSdk sdk = new EmbedderSdk(resourceProvider, locator.embedderYamls);
+
+    void expectSource(String dartUri, String posixPath) {
+      Source source = sdk.mapDartUri(dartUri);
+      expect(source, isNotNull, reason: posixPath);
+      expect(source.uri.toString(), dartUri);
+      expect(source.fullName, posixToOSPath(posixPath));
+    }
+
+    expectSource('dart:core', '/tmp/core.dart');
+    expectSource('dart:fox', '/tmp/slippy.dart');
+    expectSource('dart:deep', '/tmp/deep/directory/file.dart');
+    expectSource('dart:deep/part.dart', '/tmp/deep/directory/part.dart');
+  }
+}
+
+@reflectiveTest
+class FolderBasedDartSdkTest {
+  /**
+   * The resource provider used by these tests.
+   */
+  MemoryResourceProvider resourceProvider;
+
+  void test_analysisOptions_afterContextCreation() {
+    FolderBasedDartSdk sdk = _createDartSdk();
+    sdk.context;
+    expect(() {
+      sdk.analysisOptions = new AnalysisOptionsImpl();
+    }, throwsStateError);
+  }
+
+  void test_analysisOptions_beforeContextCreation() {
+    FolderBasedDartSdk sdk = _createDartSdk();
+    sdk.analysisOptions = new AnalysisOptionsImpl();
+    sdk.context;
+    // cannot change "analysisOptions" in the context
+    expect(() {
+      sdk.context.analysisOptions = new AnalysisOptionsImpl();
+    }, throwsStateError);
+  }
+
+  void test_creation() {
+    FolderBasedDartSdk sdk = _createDartSdk();
+    expect(sdk, isNotNull);
+  }
+
+  void test_fromFile_invalid() {
+    FolderBasedDartSdk sdk = _createDartSdk();
+    expect(
+        sdk.fromFileUri(
+            resourceProvider.getFile("/not/in/the/sdk.dart").toUri()),
+        isNull);
+  }
+
+  void test_fromFile_library() {
+    FolderBasedDartSdk sdk = _createDartSdk();
+    Source source = sdk.fromFileUri(sdk.libraryDirectory
+        .getChildAssumingFolder("core")
+        .getChildAssumingFile("core.dart")
+        .toUri());
+    expect(source, isNotNull);
+    expect(source.isInSystemLibrary, isTrue);
+    expect(source.uri.toString(), "dart:core");
+  }
+
+  void test_fromFile_library_firstExact() {
+    FolderBasedDartSdk sdk = _createDartSdk();
+    Folder dirHtml = sdk.libraryDirectory.getChildAssumingFolder("html");
+    Folder dirDartium = dirHtml.getChildAssumingFolder("dartium");
+    File file = dirDartium.getChildAssumingFile("html_dartium.dart");
+    Source source = sdk.fromFileUri(file.toUri());
+    expect(source, isNotNull);
+    expect(source.isInSystemLibrary, isTrue);
+    expect(source.uri.toString(), "dart:html");
+  }
+
+  void test_fromFile_library_html_common_dart2js() {
+    FolderBasedDartSdk sdk = _createDartSdk();
+    Folder dirHtml = sdk.libraryDirectory.getChildAssumingFolder("html");
+    Folder dirCommon = dirHtml.getChildAssumingFolder("html_common");
+    File file = dirCommon.getChildAssumingFile("html_common_dart2js.dart");
+    Source source = sdk.fromFileUri(file.toUri());
+    expect(source, isNotNull);
+    expect(source.isInSystemLibrary, isTrue);
+    expect(source.uri.toString(), "dart:html_common/html_common_dart2js.dart");
+  }
+
+  void test_fromFile_part() {
+    FolderBasedDartSdk sdk = _createDartSdk();
+    Source source = sdk.fromFileUri(sdk.libraryDirectory
+        .getChildAssumingFolder("core")
+        .getChildAssumingFile("num.dart")
+        .toUri());
+    expect(source, isNotNull);
+    expect(source.isInSystemLibrary, isTrue);
+    expect(source.uri.toString(), "dart:core/num.dart");
+  }
+
+  void test_getDirectory() {
+    FolderBasedDartSdk sdk = _createDartSdk();
+    Folder directory = sdk.directory;
+    expect(directory, isNotNull);
+    expect(directory.exists, isTrue);
+  }
+
+  void test_getDocDirectory() {
+    FolderBasedDartSdk sdk = _createDartSdk();
+    Folder directory = sdk.docDirectory;
+    expect(directory, isNotNull);
+  }
+
+  void test_getLibraryDirectory() {
+    FolderBasedDartSdk sdk = _createDartSdk();
+    Folder directory = sdk.libraryDirectory;
+    expect(directory, isNotNull);
+    expect(directory.exists, isTrue);
+  }
+
+  void test_getPubExecutable() {
+    FolderBasedDartSdk sdk = _createDartSdk();
+    File executable = sdk.pubExecutable;
+    expect(executable, isNotNull);
+    expect(executable.exists, isTrue);
+  }
+
+  void test_getSdkVersion() {
+    FolderBasedDartSdk sdk = _createDartSdk();
+    String version = sdk.sdkVersion;
+    expect(version, isNotNull);
+    expect(version.length > 0, isTrue);
+  }
+
+  void test_useSummary_afterContextCreation() {
+    FolderBasedDartSdk sdk = _createDartSdk();
+    sdk.context;
+    expect(() {
+      sdk.useSummary = true;
+    }, throwsStateError);
+  }
+
+  void test_useSummary_beforeContextCreation() {
+    FolderBasedDartSdk sdk = _createDartSdk();
+    sdk.useSummary = true;
+    sdk.context;
+  }
+
+  FolderBasedDartSdk _createDartSdk() {
+    resourceProvider = new MemoryResourceProvider();
+    Folder sdkDirectory = resourceProvider.getFolder('/sdk');
+    _createFile(sdkDirectory,
+        ['lib', '_internal', 'sdk_library_metadata', 'lib', 'libraries.dart'],
+        content: _librariesFileContent());
+    _createFile(sdkDirectory, ['bin', 'dart']);
+    _createFile(sdkDirectory, ['bin', 'dart2js']);
+    _createFile(sdkDirectory, ['bin', 'pub']);
+    _createFile(sdkDirectory, ['lib', 'async', 'async.dart']);
+    _createFile(sdkDirectory, ['lib', 'core', 'core.dart']);
+    _createFile(sdkDirectory, ['lib', 'core', 'num.dart']);
+    _createFile(sdkDirectory,
+        ['lib', 'html', 'html_common', 'html_common_dart2js.dart']);
+    _createFile(sdkDirectory, ['lib', 'html', 'dartium', 'html_dartium.dart']);
+    _createFile(
+        sdkDirectory, ['bin', (OSUtilities.isWindows() ? 'pub.bat' : 'pub')]);
+    return new FolderBasedDartSdk(resourceProvider, sdkDirectory);
+  }
+
+  void _createFile(Folder directory, List<String> segments,
+      {String content: ''}) {
+    Folder parent = directory;
+    int last = segments.length - 1;
+    for (int i = 0; i < last; i++) {
+      parent = parent.getChildAssumingFolder(segments[i]);
+    }
+    File file = parent.getChildAssumingFile(segments[last]);
+    resourceProvider.newFile(file.path, content);
+  }
+
+  String _librariesFileContent() => '''
+final Map<String, LibraryInfo> LIBRARIES = const <String, LibraryInfo> {
+  "async": const LibraryInfo(
+      "async/async.dart",
+      categories: "Client,Server",
+      maturity: Maturity.STABLE,
+      dart2jsPatchPath: "_internal/js_runtime/lib/async_patch.dart"),
+
+  "core": const LibraryInfo(
+      "core/core.dart",
+      categories: "Client,Server,Embedded",
+      maturity: Maturity.STABLE,
+      dart2jsPatchPath: "_internal/js_runtime/lib/core_patch.dart"),
+
+  "html": const LibraryInfo(
+      "html/dartium/html_dartium.dart",
+      categories: "Client",
+      maturity: Maturity.WEB_STABLE,
+      dart2jsPath: "html/dart2js/html_dart2js.dart"),
+
+  "html_common": const LibraryInfo(
+      "html/html_common/html_common.dart",
+      categories: "Client",
+      maturity: Maturity.WEB_STABLE,
+      dart2jsPath: "html/html_common/html_common_dart2js.dart",
+      documented: false,
+      implementation: true),
+};
+''';
+}
+
+@reflectiveTest
+class SDKLibrariesReaderTest extends EngineTestCase {
+  /**
+   * The resource provider used by these tests.
+   */
+  MemoryResourceProvider resourceProvider;
+
+  @override
+  void setUp() {
+    resourceProvider = new MemoryResourceProvider();
+  }
+
+  void test_readFrom_dart2js() {
+    LibraryMap libraryMap = new SdkLibrariesReader(true).readFromFile(
+        resourceProvider.getFile("/libs.dart"),
+        r'''
+final Map<String, LibraryInfo> LIBRARIES = const <String, LibraryInfo> {
+  'first' : const LibraryInfo(
+    'first/first.dart',
+    categories: 'Client',
+    documented: true,
+    platforms: VM_PLATFORM,
+    dart2jsPath: 'first/first_dart2js.dart'),
+};''');
+    expect(libraryMap, isNotNull);
+    expect(libraryMap.size(), 1);
+    SdkLibrary first = libraryMap.getLibrary("dart:first");
+    expect(first, isNotNull);
+    expect(first.category, "Client");
+    expect(first.path, "first/first_dart2js.dart");
+    expect(first.shortName, "dart:first");
+    expect(first.isDart2JsLibrary, false);
+    expect(first.isDocumented, true);
+    expect(first.isImplementation, false);
+    expect(first.isVmLibrary, true);
+  }
+
+  void test_readFrom_empty() {
+    LibraryMap libraryMap = new SdkLibrariesReader(false)
+        .readFromFile(resourceProvider.getFile("/libs.dart"), "");
+    expect(libraryMap, isNotNull);
+    expect(libraryMap.size(), 0);
+  }
+
+  void test_readFrom_normal() {
+    LibraryMap libraryMap = new SdkLibrariesReader(false).readFromFile(
+        resourceProvider.getFile("/libs.dart"),
+        r'''
+final Map<String, LibraryInfo> LIBRARIES = const <String, LibraryInfo> {
+  'first' : const LibraryInfo(
+    'first/first.dart',
+    categories: 'Client',
+    documented: true,
+    platforms: VM_PLATFORM),
+
+  'second' : const LibraryInfo(
+    'second/second.dart',
+    categories: 'Server',
+    documented: false,
+    implementation: true,
+    platforms: 0),
+};''');
+    expect(libraryMap, isNotNull);
+    expect(libraryMap.size(), 2);
+    SdkLibrary first = libraryMap.getLibrary("dart:first");
+    expect(first, isNotNull);
+    expect(first.category, "Client");
+    expect(first.path, "first/first.dart");
+    expect(first.shortName, "dart:first");
+    expect(first.isDart2JsLibrary, false);
+    expect(first.isDocumented, true);
+    expect(first.isImplementation, false);
+    expect(first.isVmLibrary, true);
+    SdkLibrary second = libraryMap.getLibrary("dart:second");
+    expect(second, isNotNull);
+    expect(second.category, "Server");
+    expect(second.path, "second/second.dart");
+    expect(second.shortName, "dart:second");
+    expect(second.isDart2JsLibrary, false);
+    expect(second.isDocumented, false);
+    expect(second.isImplementation, true);
+    expect(second.isVmLibrary, false);
+  }
+}
diff --git a/pkg/analyzer/test/src/dart/sdk/test_all.dart b/pkg/analyzer/test/src/dart/sdk/test_all.dart
new file mode 100644
index 0000000..8052c9e
--- /dev/null
+++ b/pkg/analyzer/test/src/dart/sdk/test_all.dart
@@ -0,0 +1,18 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library analyzer.test.src.dart.sdk.test_all;
+
+import 'package:unittest/unittest.dart';
+
+import '../../../utils.dart';
+import 'sdk_test.dart' as sdk;
+
+/// Utility for manually running all tests.
+main() {
+  initializeTestEnvironment();
+  group('sdk tests', () {
+    sdk.main();
+  });
+}
diff --git a/pkg/analyzer/test/src/dart/test_all.dart b/pkg/analyzer/test/src/dart/test_all.dart
index 15a0849..26e34d3 100644
--- a/pkg/analyzer/test/src/dart/test_all.dart
+++ b/pkg/analyzer/test/src/dart/test_all.dart
@@ -10,6 +10,7 @@
 import 'ast/test_all.dart' as ast;
 import 'constant/test_all.dart' as constant;
 import 'element/test_all.dart' as element;
+import 'sdk/test_all.dart' as sdk;
 
 /// Utility for manually running all tests.
 main() {
@@ -18,5 +19,6 @@
     ast.main();
     constant.main();
     element.main();
+    sdk.main();
   });
 }
diff --git a/pkg/analyzer/test/src/summary/index_unit_test.dart b/pkg/analyzer/test/src/summary/index_unit_test.dart
index 1bf2cf5..f6851c8 100644
--- a/pkg/analyzer/test/src/summary/index_unit_test.dart
+++ b/pkg/analyzer/test/src/summary/index_unit_test.dart
@@ -1134,12 +1134,34 @@
    */
   int _findElementId(Element element) {
     int unitId = _getUnitId(element);
-    ElementInfo info = PackageIndexAssembler.newElementInfo(unitId, element);
+    // Prepare the element that was put into the index.
+    IndexElementInfo info = new IndexElementInfo(element);
+    element = info.element;
+    // Prepare element's name components.
+    int unitMemberId = _getStringId(PackageIndexAssembler.NULL_STRING);
+    int classMemberId = _getStringId(PackageIndexAssembler.NULL_STRING);
+    int parameterId = _getStringId(PackageIndexAssembler.NULL_STRING);
+    for (Element e = element; e != null; e = e.enclosingElement) {
+      if (e.enclosingElement is CompilationUnitElement) {
+        unitMemberId = _getStringId(e.name);
+      }
+    }
+    for (Element e = element; e != null; e = e.enclosingElement) {
+      if (e.enclosingElement is ClassElement) {
+        classMemberId = _getStringId(e.name);
+      }
+    }
+    if (element is ParameterElement) {
+      parameterId = _getStringId(element.name);
+    }
+    // Find the element's id.
     for (int elementId = 0;
         elementId < packageIndex.elementUnits.length;
         elementId++) {
       if (packageIndex.elementUnits[elementId] == unitId &&
-          packageIndex.elementOffsets[elementId] == info.offset &&
+          packageIndex.elementNameUnitMemberIds[elementId] == unitMemberId &&
+          packageIndex.elementNameClassMemberIds[elementId] == classMemberId &&
+          packageIndex.elementNameParameterIds[elementId] == parameterId &&
           packageIndex.elementKinds[elementId] == info.kind) {
         return elementId;
       }
diff --git a/pkg/analyzer/test/src/summary/resynthesize_ast_test.dart b/pkg/analyzer/test/src/summary/resynthesize_ast_test.dart
index 4321f0d..420d515 100644
--- a/pkg/analyzer/test/src/summary/resynthesize_ast_test.dart
+++ b/pkg/analyzer/test/src/summary/resynthesize_ast_test.dart
@@ -157,6 +157,12 @@
 
   @override
   @failingTest
+  void test_constructors_inferenceFBounded() {
+    super.test_constructors_inferenceFBounded();
+  }
+
+  @override
+  @failingTest
   void test_constructors_inferFromArguments() {
     // TODO(jmesserly): does this need to be implemented in AST summaries?
     // The test might need a change as well to not be based on local variable
diff --git a/pkg/analyzer/test/src/summary/summarize_ast_test.dart b/pkg/analyzer/test/src/summary/summarize_ast_test.dart
index 60b30a8..0ac5099 100644
--- a/pkg/analyzer/test/src/summary/summarize_ast_test.dart
+++ b/pkg/analyzer/test/src/summary/summarize_ast_test.dart
@@ -375,7 +375,7 @@
         linkerInputs.getUnit,
         true);
     linkedLibraries.forEach(assembler.addLinkedLibrary);
-    linkerInputs._uriToUnit.forEach((String uri, UnlinkedUnitBuilder unit) {
+    linkerInputs._uriToUnit.forEach((String uri, UnlinkedUnit unit) {
       // Note: it doesn't matter what we store for the hash because it isn't
       // used in these tests.
       assembler.addUnlinkedUnitWithHash(uri, unit, 'HASH');
diff --git a/pkg/analyzer/test/src/task/incremental_element_builder_test.dart b/pkg/analyzer/test/src/task/incremental_element_builder_test.dart
index 27427dc..56f174e 100644
--- a/pkg/analyzer/test/src/task/incremental_element_builder_test.dart
+++ b/pkg/analyzer/test/src/task/incremental_element_builder_test.dart
@@ -42,6 +42,38 @@
     return newCode.substring(node.offset, node.end);
   }
 
+  test_classDelta_annotation_add() {
+    var helper = new _ClassDeltaHelper('A');
+    _buildOldUnit(r'''
+class A {}
+''');
+    helper.initOld(oldUnit);
+    expect(helper.element.metadata, isEmpty);
+    _buildNewUnit(r'''
+@deprecated
+class A {}
+''');
+    helper.initNew(newUnit, unitDelta);
+    expect(helper.delta.hasAnnotationChanges, isTrue);
+    expect(helper.element.metadata, hasLength(1));
+  }
+
+  test_classDelta_annotation_remove() {
+    var helper = new _ClassDeltaHelper('A');
+    _buildOldUnit(r'''
+@deprecated
+class A {}
+''');
+    helper.initOld(oldUnit);
+    expect(helper.element.metadata, hasLength(1));
+    _buildNewUnit(r'''
+class A {}
+''');
+    helper.initNew(newUnit, unitDelta);
+    expect(helper.delta.hasAnnotationChanges, isTrue);
+    expect(helper.element.metadata, isEmpty);
+  }
+
   test_classDelta_constructor_0to1() {
     var helper = new _ClassDeltaHelper('A');
     _buildOldUnit(r'''
@@ -438,6 +470,7 @@
     FieldElement newFieldElementB = newFieldsB[0].name.staticElement;
     expect(newFieldElementB.name, 'bbb');
     // verify delta
+    expect(helper.delta.hasAnnotationChanges, isFalse);
     expect(helper.delta.addedConstructors, isEmpty);
     expect(helper.delta.removedConstructors, isEmpty);
     expect(helper.delta.addedAccessors,
@@ -480,6 +513,56 @@
     expect(helper.delta.removedMethods, isEmpty);
   }
 
+  test_classDelta_field_syntheticAndNot_renameNonSynthetic() {
+    var helper = new _ClassDeltaHelper('A');
+    _buildOldUnit(r'''
+class A {
+  int foo;
+  int get foo => 1;
+}
+''');
+    helper.initOld(oldUnit);
+    FieldDeclaration oldFieldDeclNode = helper.oldMembers[0];
+    VariableDeclaration oldFieldNode = oldFieldDeclNode.fields.variables.single;
+    FieldElement oldFieldElement = oldFieldNode.name.staticElement;
+    _buildNewUnit(r'''
+class A {
+  int _foo;
+  int get foo => 1;
+}
+''');
+    helper.initNew(newUnit, unitDelta);
+    // nodes
+    FieldDeclaration newFieldDeclNode = helper.newMembers[0];
+    VariableDeclaration newFieldNode = newFieldDeclNode.fields.variables.single;
+    MethodDeclaration getterNode = helper.newMembers[1];
+    expect(getterNode, same(helper.oldMembers[1]));
+    // elements
+    FieldElement newFieldElement = newFieldNode.name.staticElement;
+    PropertyAccessorElement getterElement = getterNode.element;
+    expect(newFieldElement.name, '_foo');
+    expect(
+        helper.element.fields,
+        unorderedMatches(
+            [same(newFieldElement), same(getterElement.variable)]));
+    expect(
+        helper.element.accessors,
+        unorderedMatches([
+          same(newFieldElement.getter),
+          same(newFieldElement.setter),
+          same(getterElement)
+        ]));
+    // verify delta
+    expect(helper.delta.addedConstructors, isEmpty);
+    expect(helper.delta.removedConstructors, isEmpty);
+    expect(helper.delta.addedAccessors,
+        unorderedEquals([newFieldElement.getter, newFieldElement.setter]));
+    expect(helper.delta.removedAccessors,
+        [oldFieldElement.getter, oldFieldElement.setter]);
+    expect(helper.delta.addedMethods, isEmpty);
+    expect(helper.delta.removedMethods, isEmpty);
+  }
+
   test_classDelta_getter_add() {
     var helper = new _ClassDeltaHelper('A');
     _buildOldUnit(r'''
@@ -2051,6 +2134,7 @@
     // Compare properties.
     _verifyEqual('$desc name', expected.name, actual.name);
     _verifyEqual('$desc nameOffset', expected.nameOffset, actual.nameOffset);
+    _verifyEqual('$desc isSynthetic', expected.isSynthetic, actual.isSynthetic);
     if (expected is ElementImpl && actual is ElementImpl) {
       _verifyEqual('$desc codeOffset', expected.codeOffset, actual.codeOffset);
       _verifyEqual('$desc codeLength', expected.codeLength, actual.codeLength);
@@ -2077,6 +2161,12 @@
       _verifyElement(expected.getter, actual.getter, '$desc getter');
       _verifyElement(expected.setter, actual.setter, '$desc setter');
     }
+    // Compare implicit properties.
+    if (expected is PropertyAccessorElement &&
+        actual is PropertyAccessorElement &&
+        !expected.isSynthetic) {
+      _verifyElement(expected.variable, actual.variable, '$desc variable');
+    }
     // Compare parameters.
     if (expected is ExecutableElement && actual is ExecutableElement) {
       List<ParameterElement> actualParameters = actual.parameters;
diff --git a/pkg/analyzer/test/src/task/strong/inferred_type_test.dart b/pkg/analyzer/test/src/task/strong/inferred_type_test.dart
index feef92f..741659a 100644
--- a/pkg/analyzer/test/src/task/strong/inferred_type_test.dart
+++ b/pkg/analyzer/test/src/task/strong/inferred_type_test.dart
@@ -588,6 +588,24 @@
 ''');
   }
 
+  void test_constructors_inferenceFBounded() {
+    // Regression for https://github.com/dart-lang/sdk/issues/26990
+    var unit = checkFile('''
+class Clonable<T> {}
+
+class Pair<T extends Clonable<T>, U extends Clonable<U>> {
+  T t;
+  U u;
+  Pair(this.t, this.u);
+  Pair._();
+  Pair<U, T> get reversed => /*info:INFERRED_TYPE_ALLOCATION*/new Pair(u, t);
+}
+final x = /*info:INFERRED_TYPE_ALLOCATION*/new Pair._();
+    ''');
+    var x = unit.topLevelVariables[0];
+    expect(x.type.toString(), 'Pair<Clonable<dynamic>, Clonable<dynamic>>');
+  }
+
   void test_constructors_inferFromArguments() {
     var unit = checkFile('''
 class C<T> {
@@ -633,6 +651,23 @@
     expect(unit.topLevelVariables[0].type.toString(), 'C<int>');
   }
 
+  void test_constructors_inferFromArguments_constWithUpperBound() {
+    // Regression for https://github.com/dart-lang/sdk/issues/26993
+    checkFile('''
+class C<T extends num> {
+  final T x;
+  const C(this.x);
+}
+class D<T extends num> {
+  const D();
+}
+void f() {
+  const c = /*info:INFERRED_TYPE_ALLOCATION*/const C(0);
+  const D<int> d = /*info:INFERRED_TYPE_ALLOCATION*/const D();
+}
+    ''');
+  }
+
   void test_constructors_inferFromArguments_factory() {
     var unit = checkFile('''
 class C<T> {
@@ -734,6 +769,18 @@
     expect(unit.topLevelVariables[0].type.toString(), 'C<int>');
   }
 
+  void test_constructors_reverseTypeParameters() {
+    // Regression for https://github.com/dart-lang/sdk/issues/26990
+    checkFile('''
+class Pair<T, U> {
+  T t;
+  U u;
+  Pair(this.t, this.u);
+  Pair<U, T> get reversed => /*info:INFERRED_TYPE_ALLOCATION*/new Pair(u, t);
+}
+    ''');
+  }
+
   void test_doNotInferOverriddenFieldsThatExplicitlySayDynamic_infer() {
     checkFile('''
 class A {
diff --git a/pkg/analyzer/test/src/task/strong/non_null_checker_test.dart b/pkg/analyzer/test/src/task/strong/non_null_checker_test.dart
new file mode 100644
index 0000000..ac056c2
--- /dev/null
+++ b/pkg/analyzer/test/src/task/strong/non_null_checker_test.dart
@@ -0,0 +1,66 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// These tests are for an experimental feature that treats Dart primitive types
+// (int, bool, double, etc.) as non-nullable. This file is not evidence for an
+// intention to officially support non-nullable primitives in Dart (or general
+// NNBD, for that matter) so don't get too crazy about it.
+
+library analyzer.test.src.task.non_null_primitives.checker_test;
+
+import '../../../reflective_tests.dart';
+import '../strong/strong_test_helper.dart';
+
+void main() {
+  initStrongModeTests();
+  runReflectiveTests(NonNullCheckerTest);
+}
+
+@reflectiveTest
+class NonNullCheckerTest {
+  // Tests simple usage of ints as iterators for a loop. Not directly related to
+  // non-nullability, but if it is implemented this should be more efficient,
+  // since languages.length will not be null-checked on every iteration.
+  void test_forLoop() {
+    checkFile('''
+class MyList {
+  int length;
+  MyList() {
+    length = 6;
+  }
+  String operator [](int i) {
+    return <String>["Dart", "Java", "JS", "C", "C++", "C#"][i];
+  }
+}
+
+main() {
+  var languages = new MyList();
+  for (int i = 0; i < languages.length; ++i) {
+    print(languages[i]);
+  }
+}
+''');
+  }
+
+  void test_nullableTypes() {
+    // By default x can be set to null.
+    checkFile('int x = null;');
+  }
+
+  void test_nonnullableTypes() {
+    // If `int`s are non-nullable, then this code should throw an error.
+    addFile('int x;');
+    addFile('int x = /*error:INVALID_ASSIGNMENT*/null;');
+    addFile('int x = 0;');
+    addFile('''
+int x = 0;
+
+main() {
+  x = 1;
+  x = /*error:INVALID_ASSIGNMENT*/null;
+}
+''');
+    check(nonnullableTypes: <String>['dart:core,int']);
+  }
+}
diff --git a/pkg/analyzer/test/src/task/strong/strong_test_helper.dart b/pkg/analyzer/test/src/task/strong/strong_test_helper.dart
index 82829eb..9c36094 100644
--- a/pkg/analyzer/test/src/task/strong/strong_test_helper.dart
+++ b/pkg/analyzer/test/src/task/strong/strong_test_helper.dart
@@ -54,7 +54,10 @@
 /// the file text.
 ///
 /// Returns the main resolved library. This can be used for further checks.
-CompilationUnit check({bool implicitCasts: true, bool implicitDynamic: true}) {
+CompilationUnit check(
+    {bool implicitCasts: true,
+    bool implicitDynamic: true,
+    List<String> nonnullableTypes: AnalysisOptionsImpl.NONNULLABLE_TYPES}) {
   _checkCalled = true;
 
   expect(files.getFile('/main.dart').exists, true,
@@ -68,8 +71,9 @@
   options.strongModeHints = true;
   options.implicitCasts = implicitCasts;
   options.implicitDynamic = implicitDynamic;
+  options.nonnullableTypes = nonnullableTypes;
   var mockSdk = new MockSdk();
-  mockSdk.context.analysisOptions.strongMode = true;
+  (mockSdk.context.analysisOptions as AnalysisOptionsImpl).strongMode = true;
   context.sourceFactory =
       new SourceFactory([new DartUriResolver(mockSdk), uriResolver]);
 
diff --git a/pkg/analyzer/test/stress/for_git_repository.dart b/pkg/analyzer/test/stress/for_git_repository.dart
new file mode 100644
index 0000000..ee8dab2
--- /dev/null
+++ b/pkg/analyzer/test/stress/for_git_repository.dart
@@ -0,0 +1,634 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library analyzer.test.stress.limited_invalidation;
+
+import 'dart:async';
+import 'dart:io';
+
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/dart/element/type.dart';
+import 'package:analyzer/file_system/file_system.dart' as fs;
+import 'package:analyzer/file_system/physical_file_system.dart';
+import 'package:analyzer/src/context/builder.dart';
+import 'package:analyzer/src/context/cache.dart';
+import 'package:analyzer/src/context/context.dart';
+import 'package:analyzer/src/dart/ast/utilities.dart';
+import 'package:analyzer/src/dart/element/member.dart';
+import 'package:analyzer/src/generated/engine.dart';
+import 'package:analyzer/src/generated/error.dart';
+import 'package:analyzer/src/generated/sdk.dart';
+import 'package:analyzer/src/generated/sdk_io.dart';
+import 'package:analyzer/src/generated/source.dart';
+import 'package:analyzer/src/generated/utilities_collection.dart';
+import 'package:analyzer/src/task/dart.dart';
+import 'package:analyzer/task/general.dart';
+import 'package:analyzer/task/model.dart';
+import 'package:path/path.dart' as path;
+import 'package:unittest/unittest.dart';
+
+main() {
+  new StressTest().run();
+}
+
+void _failTypeMismatch(Object actual, Object expected, {String reason}) {
+  String message = 'Actual $actual is ${actual.runtimeType}, '
+      'but expected $expected is ${expected.runtimeType}';
+  if (reason != null) {
+    message += ' $reason';
+  }
+  fail(message);
+}
+
+void _logPrint(String message) {
+  DateTime time = new DateTime.now();
+  print('$time: $message');
+}
+
+class FileInfo {
+  final String path;
+  final int modification;
+
+  FileInfo(this.path, this.modification);
+}
+
+class FolderDiff {
+  final List<String> added;
+  final List<String> changed;
+  final List<String> removed;
+
+  FolderDiff(this.added, this.changed, this.removed);
+
+  bool get isEmpty => added.isEmpty && changed.isEmpty && removed.isEmpty;
+  bool get isNotEmpty => !isEmpty;
+
+  @override
+  String toString() {
+    return '[added=$added, changed=$changed, removed=$removed]';
+  }
+}
+
+class FolderInfo {
+  final String path;
+  final List<FileInfo> files = <FileInfo>[];
+
+  FolderInfo(this.path) {
+    List<FileSystemEntity> entities =
+        new Directory(path).listSync(recursive: true);
+    for (FileSystemEntity entity in entities) {
+      if (entity is File) {
+        String path = entity.path;
+        if (path.contains('packages') || path.contains('.pub')) {
+          continue;
+        }
+        if (path.endsWith('.dart')) {
+          files.add(new FileInfo(
+              path, entity.lastModifiedSync().millisecondsSinceEpoch));
+        }
+      }
+    }
+  }
+
+  FolderDiff diff(FolderInfo oldFolder) {
+    Map<String, FileInfo> toMap(FolderInfo folder) {
+      Map<String, FileInfo> map = <String, FileInfo>{};
+      folder.files.forEach((file) {
+        map[file.path] = file;
+      });
+      return map;
+    }
+    Map<String, FileInfo> newFiles = toMap(this);
+    Map<String, FileInfo> oldFiles = toMap(oldFolder);
+    Set<String> addedPaths = newFiles.keys.toSet()..removeAll(oldFiles.keys);
+    Set<String> removedPaths = oldFiles.keys.toSet()..removeAll(newFiles.keys);
+    List<String> changedPaths = <String>[];
+    newFiles.forEach((path, newFile) {
+      FileInfo oldFile = oldFiles[path];
+      if (oldFile != null && oldFile.modification != newFile.modification) {
+        changedPaths.add(path);
+      }
+    });
+    return new FolderDiff(
+        addedPaths.toList(), changedPaths, removedPaths.toList());
+  }
+}
+
+class GitException {
+  final String message;
+  final String stdout;
+  final String stderr;
+
+  GitException(this.message)
+      : stdout = null,
+        stderr = null;
+
+  GitException.forProcessResult(this.message, ProcessResult processResult)
+      : stdout = processResult.stdout,
+        stderr = processResult.stderr;
+
+  @override
+  String toString() => '$message\n$stdout\n$stderr\n';
+}
+
+class GitRepository {
+  final String path;
+
+  GitRepository(this.path);
+
+  Future checkout(String hash) async {
+    // TODO(scheglov) use for updating only some files
+    if (hash.endsWith('hash')) {
+      List<String> filePaths = <String>[
+        '/Users/user/full/path/one.dart',
+        '/Users/user/full/path/two.dart',
+      ];
+      for (var filePath in filePaths) {
+        await Process.run('git', <String>['checkout', '-f', hash, filePath],
+            workingDirectory: path);
+      }
+      return;
+    }
+    ProcessResult processResult = await Process
+        .run('git', <String>['checkout', '-f', hash], workingDirectory: path);
+    _throwIfNotSuccess(processResult);
+  }
+
+  Future<List<GitRevision>> getRevisions({String after}) async {
+    List<String> args = <String>['log', '--format=%ct %H %s'];
+    if (after != null) {
+      args.add('--after=$after');
+    }
+    ProcessResult processResult =
+        await Process.run('git', args, workingDirectory: path);
+    _throwIfNotSuccess(processResult);
+    String output = processResult.stdout;
+    List<String> logLines = output.split('\n');
+    List<GitRevision> revisions = <GitRevision>[];
+    for (String logLine in logLines) {
+      int index1 = logLine.indexOf(' ');
+      if (index1 != -1) {
+        int index2 = logLine.indexOf(' ', index1 + 1);
+        if (index2 != -1) {
+          int timestamp = int.parse(logLine.substring(0, index1));
+          String hash = logLine.substring(index1 + 1, index2);
+          String message = logLine.substring(index2).trim();
+          revisions.add(new GitRevision(timestamp, hash, message));
+        }
+      }
+    }
+    return revisions;
+  }
+
+  void removeIndexLock() {
+    File file = new File('$path/.git/index.lock');
+    if (file.existsSync()) {
+      file.deleteSync();
+    }
+  }
+
+  Future resetHard() async {
+    ProcessResult processResult = await Process
+        .run('git', <String>['reset', '--hard'], workingDirectory: path);
+    _throwIfNotSuccess(processResult);
+  }
+
+  void _throwIfNotSuccess(ProcessResult processResult) {
+    if (processResult.exitCode != 0) {
+      throw new GitException.forProcessResult(
+          'Unable to run "git log".', processResult);
+    }
+  }
+}
+
+class GitRevision {
+  final int timestamp;
+  final String hash;
+  final String message;
+
+  GitRevision(this.timestamp, this.hash, this.message);
+
+  @override
+  String toString() {
+    DateTime dateTime =
+        new DateTime.fromMillisecondsSinceEpoch(timestamp * 1000, isUtc: true)
+            .toLocal();
+    return '$dateTime|$hash|$message|';
+  }
+}
+
+class StressTest {
+  String repoPath = '/Users/scheglov/tmp/limited-invalidation/path';
+  String folderPath = '/Users/scheglov/tmp/limited-invalidation/path';
+//  String repoPath = '/Users/scheglov/tmp/limited-invalidation/async';
+//  String folderPath = '/Users/scheglov/tmp/limited-invalidation/async';
+//  String repoPath = '/Users/scheglov/tmp/limited-invalidation/sdk';
+//  String folderPath = '/Users/scheglov/tmp/limited-invalidation/sdk/pkg/analyzer';
+
+  fs.ResourceProvider resourceProvider;
+  path.Context pathContext;
+  DartSdkManager sdkManager;
+  ContentCache contentCache;
+
+  AnalysisContextImpl expectedContext;
+  AnalysisContextImpl actualContext;
+
+  Set<Element> currentRevisionValidatedElements = new Set<Element>();
+
+  void createContexts() {
+    assert(expectedContext == null);
+    assert(actualContext == null);
+    resourceProvider = PhysicalResourceProvider.INSTANCE;
+    pathContext = resourceProvider.pathContext;
+    sdkManager = new DartSdkManager(
+        DirectoryBasedDartSdk.defaultSdkDirectory.getAbsolutePath(),
+        false,
+        (_) => DirectoryBasedDartSdk.defaultSdk);
+    contentCache = new ContentCache();
+    ContextBuilder builder =
+        new ContextBuilder(resourceProvider, sdkManager, contentCache);
+    builder.defaultOptions = new AnalysisOptionsImpl();
+    expectedContext = builder.buildContext(folderPath);
+    actualContext = builder.buildContext(folderPath);
+    expectedContext.analysisOptions =
+        new AnalysisOptionsImpl.from(expectedContext.analysisOptions)
+          ..incremental = true;
+    actualContext.analysisOptions =
+        new AnalysisOptionsImpl.from(actualContext.analysisOptions)
+          ..incremental = true
+          ..finerGrainedInvalidation = true;
+    print('Created contexts');
+  }
+
+  run() async {
+    GitRepository repository = new GitRepository(repoPath);
+
+    // Recover.
+    repository.removeIndexLock();
+    await repository.resetHard();
+
+    await repository.checkout('master');
+    List<GitRevision> revisions =
+        await repository.getRevisions(after: '2016-01-01');
+    revisions = revisions.reversed.toList();
+    // TODO(scheglov) Use to compare two revisions.
+//    List<GitRevision> revisions = [
+//      new GitRevision(0, '99517a162cbabf3d3afbdb566df3fe2b18cd4877', 'aaa'),
+//      new GitRevision(0, '2ef00b0c3d0182b5e4ea5ca55fd00b9d038ae40d', 'bbb'),
+//    ];
+    FolderInfo oldFolder = null;
+    for (GitRevision revision in revisions) {
+      print(revision);
+      await repository.checkout(revision.hash);
+
+      // Run "pub get".
+      if (!new File('$folderPath/pubspec.yaml').existsSync()) {
+        continue;
+      }
+      {
+        ProcessResult processResult = await Process.run(
+            '/Users/scheglov/Applications/dart-sdk/bin/pub', <String>['get'],
+            workingDirectory: folderPath);
+        if (processResult.exitCode != 0) {
+          _logPrint('Pub get failed.');
+          _logPrint(processResult.stdout);
+          _logPrint(processResult.stderr);
+          continue;
+        }
+        _logPrint('\tpub get OK');
+      }
+      FolderInfo newFolder = new FolderInfo(folderPath);
+
+      if (expectedContext == null) {
+        createContexts();
+        _applyChanges(
+            newFolder.files.map((file) => file.path).toList(), [], []);
+        _analyzeContexts();
+      }
+
+      if (oldFolder != null) {
+        FolderDiff diff = newFolder.diff(oldFolder);
+        print('    $diff');
+        if (diff.isNotEmpty) {
+          _applyChanges(diff.added, diff.changed, diff.removed);
+          _analyzeContexts();
+        }
+      }
+      oldFolder = newFolder;
+      print('\n');
+      print('\n');
+    }
+  }
+
+  /**
+   * Perform analysis tasks up to 512 times and assert that it was enough.
+   */
+  void _analyzeAll_assertFinished(AnalysisContext context,
+      [int maxIterations = 1000000]) {
+    for (int i = 0; i < maxIterations; i++) {
+      List<ChangeNotice> notice = context.performAnalysisTask().changeNotices;
+      if (notice == null) {
+        return;
+      }
+    }
+    throw new StateError(
+        "performAnalysisTask failed to terminate after analyzing all sources");
+  }
+
+  void _analyzeContexts() {
+    {
+      Stopwatch sw = new Stopwatch()..start();
+      _analyzeAll_assertFinished(expectedContext);
+      print('    analyze(expected):    ${sw.elapsedMilliseconds}');
+    }
+    {
+      Stopwatch sw = new Stopwatch()..start();
+      _analyzeAll_assertFinished(actualContext);
+      print('    analyze(actual): ${sw.elapsedMilliseconds}');
+    }
+    _validateContexts();
+  }
+
+  void _applyChanges(
+      List<String> added, List<String> changed, List<String> removed) {
+    ChangeSet changeSet = new ChangeSet();
+    added.map(_pathToSource).forEach(changeSet.addedSource);
+    removed.map(_pathToSource).forEach(changeSet.removedSource);
+    changed.map(_pathToSource).forEach(changeSet.changedSource);
+    changed.forEach((path) => new File(path).readAsStringSync());
+    {
+      Stopwatch sw = new Stopwatch()..start();
+      expectedContext.applyChanges(changeSet);
+      print('    apply(expected):    ${sw.elapsedMilliseconds}');
+    }
+    {
+      Stopwatch sw = new Stopwatch()..start();
+      actualContext.applyChanges(changeSet);
+      print('    apply(actual): ${sw.elapsedMilliseconds}');
+    }
+  }
+
+  Source _pathToSource(String path) {
+    fs.File file = resourceProvider.getFile(path);
+    return _createSourceInContext(expectedContext, file);
+  }
+
+  void _validateContexts() {
+    currentRevisionValidatedElements.clear();
+    MapIterator<AnalysisTarget, CacheEntry> iterator =
+        expectedContext.privateAnalysisCachePartition.iterator();
+    while (iterator.moveNext()) {
+      AnalysisTarget target = iterator.key;
+      CacheEntry entry = iterator.value;
+      if (target is NonExistingSource) {
+        continue;
+      }
+      _validateEntry(target, entry);
+    }
+  }
+
+  void _validateElements(
+      Element actualValue, Element expectedValue, Set visited) {
+    if (actualValue == null && expectedValue == null) {
+      return;
+    }
+    if (!currentRevisionValidatedElements.add(expectedValue)) {
+      return;
+    }
+    if (!visited.add(expectedValue)) {
+      return;
+    }
+    List<Element> sortElements(List<Element> elements) {
+      elements = elements.toList();
+      elements.sort((a, b) {
+        if (a.nameOffset != b.nameOffset) {
+          return a.nameOffset - b.nameOffset;
+        }
+        return a.name.compareTo(b.name);
+      });
+      return elements;
+    }
+    void validateSortedElements(
+        List<Element> actualElements, List<Element> expectedElements) {
+      expect(actualElements, hasLength(expectedElements.length));
+      actualElements = sortElements(actualElements);
+      expectedElements = sortElements(expectedElements);
+      for (int i = 0; i < expectedElements.length; i++) {
+        _validateElements(actualElements[i], expectedElements[i], visited);
+      }
+    }
+    expect(actualValue?.runtimeType, expectedValue?.runtimeType);
+    expect(actualValue.nameOffset, expectedValue.nameOffset);
+    expect(actualValue.name, expectedValue.name);
+    if (expectedValue is ClassElement) {
+      var actualElement = actualValue as ClassElement;
+      validateSortedElements(actualElement.accessors, expectedValue.accessors);
+      validateSortedElements(
+          actualElement.constructors, expectedValue.constructors);
+      validateSortedElements(actualElement.fields, expectedValue.fields);
+      validateSortedElements(actualElement.methods, expectedValue.methods);
+    }
+    if (expectedValue is CompilationUnitElement) {
+      var actualElement = actualValue as CompilationUnitElement;
+      validateSortedElements(actualElement.accessors, expectedValue.accessors);
+      validateSortedElements(actualElement.functions, expectedValue.functions);
+      validateSortedElements(actualElement.types, expectedValue.types);
+      validateSortedElements(
+          actualElement.functionTypeAliases, expectedValue.functionTypeAliases);
+      validateSortedElements(
+          actualElement.topLevelVariables, expectedValue.topLevelVariables);
+    }
+    if (expectedValue is ExecutableElement) {
+      var actualElement = actualValue as ExecutableElement;
+      validateSortedElements(
+          actualElement.parameters, expectedValue.parameters);
+      _validateTypes(
+          actualElement.returnType, expectedValue.returnType, visited);
+    }
+  }
+
+  void _validateEntry(AnalysisTarget target, CacheEntry expectedEntry) {
+    CacheEntry actualEntry =
+        actualContext.privateAnalysisCachePartition.get(target);
+    if (actualEntry == null) {
+      return;
+    }
+    print('  (${target.runtimeType})  $target');
+    for (ResultDescriptor result in expectedEntry.nonInvalidResults) {
+      var expectedData = expectedEntry.getResultDataOrNull(result);
+      var actualData = actualEntry.getResultDataOrNull(result);
+      if (expectedData?.state == CacheState.INVALID) {
+        expectedData = null;
+      }
+      if (actualData?.state == CacheState.INVALID) {
+        actualData = null;
+      }
+      if (actualData == null) {
+        if (result != CONTENT &&
+            result != LIBRARY_ELEMENT4 &&
+            result != LIBRARY_ELEMENT5 &&
+            result != READY_LIBRARY_ELEMENT6 &&
+            result != READY_LIBRARY_ELEMENT7) {
+          Source targetSource = target.source;
+          if (targetSource != null &&
+              targetSource.fullName.startsWith(folderPath)) {
+            fail('No ResultData $result for $target');
+          }
+        }
+        continue;
+      }
+      Object expectedValue = expectedData.value;
+      Object actualValue = actualData.value;
+      print('    $result  ${expectedValue?.runtimeType}');
+      _validateResult(target, result, actualValue, expectedValue);
+    }
+  }
+
+  void _validatePairs(AnalysisTarget target, ResultDescriptor result,
+      List actualList, List expectedList) {
+    if (expectedList == null) {
+      expect(actualList, isNull);
+      return;
+    }
+    expect(actualList, isNotNull);
+    expect(actualList, hasLength(expectedList.length));
+    for (int i = 0; i < expectedList.length; i++) {
+      Object expected = expectedList[i];
+      Object actual = actualList[i];
+      _validateResult(target, result, actual, expected);
+    }
+  }
+
+  void _validateResult(AnalysisTarget target, ResultDescriptor result,
+      Object actualValue, Object expectedValue) {
+    if (expectedValue is bool) {
+      expect(actualValue, expectedValue, reason: '$result of $target');
+    }
+    if (expectedValue is CompilationUnit) {
+      expect(actualValue, new isInstanceOf<CompilationUnit>());
+      new _AstValidator().isEqualNodes(expectedValue, actualValue);
+    }
+    if (expectedValue is Element) {
+      expect(actualValue, new isInstanceOf<Element>());
+      _validateElements(actualValue, expectedValue, new Set.identity());
+    }
+    if (expectedValue is List) {
+      if (actualValue is List) {
+        _validatePairs(target, result, actualValue, expectedValue);
+      } else {
+        _failTypeMismatch(actualValue, expectedValue);
+      }
+    }
+    if (expectedValue is AnalysisError) {
+      if (actualValue is AnalysisError) {
+        expect(actualValue.source, expectedValue.source);
+        expect(actualValue.offset, expectedValue.offset);
+        expect(actualValue.message, expectedValue.message);
+      } else {
+        _failTypeMismatch(actualValue, expectedValue);
+      }
+    }
+  }
+
+  void _validateTypes(DartType actualType, DartType expectedType, Set visited) {
+    if (!visited.add(expectedType)) {
+      return;
+    }
+    expect(actualType?.runtimeType, expectedType?.runtimeType);
+    _validateElements(actualType.element, expectedType.element, visited);
+  }
+
+  /**
+   * Create and return a source representing the given [file] within the given
+   * [context].
+   */
+  static Source _createSourceInContext(AnalysisContext context, fs.File file) {
+    Source source = file.createSource();
+    if (context == null) {
+      return source;
+    }
+    Uri uri = context.sourceFactory.restoreUri(source);
+    return file.createSource(uri);
+  }
+}
+
+/**
+ * Compares tokens and ASTs, and built elements of declared identifiers.
+ */
+class _AstValidator extends AstComparator {
+  @override
+  bool isEqualNodes(AstNode expected, AstNode actual) {
+    // TODO(scheglov) skip comments for now
+    // [ElementBuilder.visitFunctionExpression] in resolver_test.dart
+    // Going from c4493869ca19ef9ba6bd35d3d42e1209eb3b7e63
+    // to         3977c9f2274df35df6332a65af9973fd6517bc12
+    // With files:
+    //  '/Users/scheglov/tmp/limited-invalidation/sdk/pkg/analyzer/lib/src/generated/resolver.dart',
+    //  '/Users/scheglov/tmp/limited-invalidation/sdk/pkg/analyzer/lib/src/dart/element/builder.dart',
+    //  '/Users/scheglov/tmp/limited-invalidation/sdk/pkg/analyzer/test/generated/resolver_test.dart',
+    if (expected is CommentReference) {
+      return true;
+    }
+    // Compare nodes.
+    bool result = super.isEqualNodes(expected, actual);
+    if (!result) {
+      fail('|$actual| != expected |$expected|');
+    }
+    // Verify that identifiers have equal elements and types.
+    if (expected is SimpleIdentifier && actual is SimpleIdentifier) {
+      _verifyElements(actual.staticElement, expected.staticElement,
+          '$expected staticElement');
+      _verifyElements(actual.propagatedElement, expected.propagatedElement,
+          '$expected staticElement');
+      _verifyTypes(
+          actual.staticType, expected.staticType, '$expected staticType');
+      _verifyTypes(actual.propagatedType, expected.propagatedType,
+          '$expected propagatedType');
+      _verifyElements(actual.staticParameterElement,
+          expected.staticParameterElement, '$expected staticParameterElement');
+      _verifyElements(
+          actual.propagatedParameterElement,
+          expected.propagatedParameterElement,
+          '$expected propagatedParameterElement');
+    }
+    return true;
+  }
+
+  void _verifyElements(Element actual, Element expected, String desc) {
+    if (expected == null && actual == null) {
+      return;
+    }
+    if (expected is MultiplyDefinedElement &&
+        actual is MultiplyDefinedElement) {
+      return;
+    }
+    while (expected is Member) {
+      if (actual is Member) {
+        actual = (actual as Member).baseElement;
+        expected = (expected as Member).baseElement;
+      } else {
+        _failTypeMismatch(actual, expected, reason: desc);
+      }
+    }
+    expect(actual, equals(expected), reason: desc);
+  }
+
+  void _verifyTypes(DartType actual, DartType expected, String desc) {
+    _verifyElements(actual?.element, expected?.element, '$desc element');
+    if (expected is InterfaceType) {
+      if (actual is InterfaceType) {
+        List<DartType> actualArguments = actual.typeArguments;
+        List<DartType> expectedArguments = expected.typeArguments;
+        expect(
+            actualArguments,
+            pairwiseCompare(expectedArguments, (a, b) {
+              _verifyTypes(a, b, '$desc typeArguments');
+              return true;
+            }, 'elements'));
+      } else {
+        _failTypeMismatch(actual, expected);
+      }
+    }
+  }
+}
diff --git a/pkg/analyzer_cli/.analysis_options b/pkg/analyzer_cli/.analysis_options
index 78831a9..dc60267 100644
--- a/pkg/analyzer_cli/.analysis_options
+++ b/pkg/analyzer_cli/.analysis_options
@@ -1,3 +1,4 @@
 analyzer:
+  strong-mode: true
   exclude:
     - 'test/data'
diff --git a/pkg/analyzer_cli/lib/src/build_mode.dart b/pkg/analyzer_cli/lib/src/build_mode.dart
index f79e401..1883318 100644
--- a/pkg/analyzer_cli/lib/src/build_mode.dart
+++ b/pkg/analyzer_cli/lib/src/build_mode.dart
@@ -69,7 +69,7 @@
     try {
       // Add in the dart-sdk argument if `dartSdkPath` is not null, otherwise it
       // will try to find the currently installed sdk.
-      var arguments = new List.from(request.arguments);
+      var arguments = new List<String>.from(request.arguments);
       if (dartSdkPath != null &&
           !arguments.any((arg) => arg.startsWith('--dart-sdk'))) {
         arguments.add('--dart-sdk=$dartSdkPath');
diff --git a/pkg/analyzer_cli/lib/src/driver.dart b/pkg/analyzer_cli/lib/src/driver.dart
index 46316b7..da11426 100644
--- a/pkg/analyzer_cli/lib/src/driver.dart
+++ b/pkg/analyzer_cli/lib/src/driver.dart
@@ -772,15 +772,12 @@
         exitCode = batchResult.ordinal;
       }
       // Prepare arguments.
-      var args;
-      {
-        var lineArgs = line.split(new RegExp('\\s+'));
-        args = new List<String>();
-        args.addAll(sharedArgs);
-        args.addAll(lineArgs);
-        args.remove('-b');
-        args.remove('--batch');
-      }
+      var lineArgs = line.split(new RegExp('\\s+'));
+      var args = new List<String>();
+      args.addAll(sharedArgs);
+      args.addAll(lineArgs);
+      args.remove('-b');
+      args.remove('--batch');
       // Analyze single set of arguments.
       try {
         totalTests++;
diff --git a/pkg/analyzer_cli/lib/src/options.dart b/pkg/analyzer_cli/lib/src/options.dart
index 030f1bf..2ad8bc4 100644
--- a/pkg/analyzer_cli/lib/src/options.dart
+++ b/pkg/analyzer_cli/lib/src/options.dart
@@ -166,7 +166,7 @@
         buildMode = args['build-mode'],
         buildModePersistentWorker = args['persistent_worker'],
         buildSummaryFallback = args['build-summary-fallback'],
-        buildSummaryInputs = args['build-summary-input'],
+        buildSummaryInputs = args['build-summary-input'] as List<String>,
         buildSummaryOnly = args['build-summary-only'],
         buildSummaryOnlyAst = args['build-summary-only-ast'],
         buildSummaryOnlyDiet = args['build-summary-only-diet'],
diff --git a/pkg/analyzer_cli/test/driver_test.dart b/pkg/analyzer_cli/test/driver_test.dart
index e549603..58b5c1a 100644
--- a/pkg/analyzer_cli/test/driver_test.dart
+++ b/pkg/analyzer_cli/test/driver_test.dart
@@ -518,7 +518,7 @@
 }
 
 class TestProcessor extends OptionsProcessor {
-  Map<String, YamlNode> options;
+  Map<String, Object> options;
   Exception exception;
 
   @override
@@ -527,8 +527,7 @@
   }
 
   @override
-  void optionsProcessed(
-      AnalysisContext context, Map<String, YamlNode> options) {
+  void optionsProcessed(AnalysisContext context, Map<String, Object> options) {
     this.options = options;
   }
 }
diff --git a/pkg/compiler/lib/src/constant_system_dart.dart b/pkg/compiler/lib/src/constant_system_dart.dart
index a19e003..c42ca74 100644
--- a/pkg/compiler/lib/src/constant_system_dart.dart
+++ b/pkg/compiler/lib/src/constant_system_dart.dart
@@ -8,7 +8,7 @@
 import 'constants/constant_system.dart';
 import 'constants/values.dart';
 import 'dart_types.dart';
-import 'tree/tree.dart' show DartString;
+import 'tree/dartstring.dart' show DartString;
 
 const DART_CONSTANT_SYSTEM = const DartConstantSystem();
 
diff --git a/pkg/compiler/lib/src/constants/constant_system.dart b/pkg/compiler/lib/src/constants/constant_system.dart
index e278612..07787fd 100644
--- a/pkg/compiler/lib/src/constants/constant_system.dart
+++ b/pkg/compiler/lib/src/constants/constant_system.dart
@@ -7,7 +7,7 @@
 import '../dart_types.dart';
 import '../compiler.dart' show Compiler;
 import '../resolution/operators.dart';
-import '../tree/tree.dart' show DartString;
+import '../tree/dartstring.dart' show DartString;
 import 'values.dart';
 
 abstract class Operation {
diff --git a/pkg/compiler/lib/src/constants/expressions.dart b/pkg/compiler/lib/src/constants/expressions.dart
index 9eb3fdc..2ea05a8 100644
--- a/pkg/compiler/lib/src/constants/expressions.dart
+++ b/pkg/compiler/lib/src/constants/expressions.dart
@@ -16,7 +16,7 @@
         PrefixElement,
         VariableElement;
 import '../resolution/operators.dart';
-import '../tree/tree.dart' show DartString;
+import '../tree/dartstring.dart' show DartString;
 import '../universe/call_structure.dart' show CallStructure;
 import 'evaluation.dart';
 import 'values.dart';
diff --git a/pkg/compiler/lib/src/constants/values.dart b/pkg/compiler/lib/src/constants/values.dart
index 62749bf..fbda202 100644
--- a/pkg/compiler/lib/src/constants/values.dart
+++ b/pkg/compiler/lib/src/constants/values.dart
@@ -9,7 +9,7 @@
 import '../dart_types.dart';
 import '../elements/elements.dart'
     show FieldElement, FunctionElement, PrefixElement;
-import '../tree/tree.dart' hide unparse;
+import '../tree/dartstring.dart';
 import '../util/util.dart' show Hashing;
 
 abstract class ConstantValueVisitor<R, A> {
diff --git a/pkg/compiler/lib/src/deferred_load.dart b/pkg/compiler/lib/src/deferred_load.dart
index b45d3012..b3668c1 100644
--- a/pkg/compiler/lib/src/deferred_load.dart
+++ b/pkg/compiler/lib/src/deferred_load.dart
@@ -36,7 +36,6 @@
 import 'resolution/resolution.dart' show AnalyzableElementX;
 import 'resolution/tree_elements.dart' show TreeElements;
 import 'tree/tree.dart' as ast;
-import 'tree/tree.dart' show Import, Node;
 import 'universe/use.dart' show StaticUse, TypeUse, TypeUseKind;
 import 'universe/world_impact.dart'
     show ImpactUseCase, WorldImpact, WorldImpactVisitorImpl;
@@ -93,8 +92,7 @@
   /// DeferredLibrary from dart:async
   ClassElement get deferredLibraryClass => compiler.deferredLibraryClass;
 
-  /// A synthetic [Import] representing the loading of the main
-  /// program.
+  /// A synthetic import representing the loading of the main program.
   final _DeferredImport _fakeMainImport = const _DeferredImport();
 
   /// The OutputUnit that will be loaded when the program starts.
@@ -235,7 +233,7 @@
     return imports.every((ImportElement import) => import.isDeferred);
   }
 
-  /// Returns a [Link] of every [Import] that imports [element] into [library].
+  /// Returns every [ImportElement] that imports [element] into [library].
   Iterable<ImportElement> _getImports(Element element, LibraryElement library) {
     if (element.isClassMember) {
       element = element.enclosingClass;
@@ -347,8 +345,8 @@
         // implicit constant expression are seen that we should be able to add
         // (like primitive constant literals like `true`, `"foo"` and `0`).
         // See dartbug.com/26406 for context.
-        treeElements
-            .forEachConstantNode((Node node, ConstantExpression expression) {
+        treeElements.forEachConstantNode(
+            (ast.Node node, ConstantExpression expression) {
           if (compiler.serialization.isDeserialized(analyzableElement)) {
             if (!expression.isImplicit && !expression.isPotential) {
               // Enforce evaluation of [expression].
diff --git a/pkg/compiler/lib/src/inferrer/type_graph_inferrer.dart b/pkg/compiler/lib/src/inferrer/type_graph_inferrer.dart
index f8ae6ea..4f185c2 100644
--- a/pkg/compiler/lib/src/inferrer/type_graph_inferrer.dart
+++ b/pkg/compiler/lib/src/inferrer/type_graph_inferrer.dart
@@ -15,8 +15,8 @@
 import '../elements/elements.dart';
 import '../js_backend/js_backend.dart' show Annotations, JavaScriptBackend;
 import '../resolution/tree_elements.dart' show TreeElementMapping;
-import '../tree/tree.dart' as ast
-    show DartString, Node, LiteralBool, TryStatement;
+import '../tree/tree.dart' as ast show Node, LiteralBool, TryStatement;
+import '../tree/dartstring.dart' show DartString;
 import '../types/constants.dart' show computeTypeMask;
 import '../types/types.dart'
     show ContainerTypeMask, MapTypeMask, TypeMask, TypesInferrer;
@@ -227,7 +227,7 @@
 
   TypeInformation nonNullEmptyType;
 
-  TypeInformation stringLiteralType(ast.DartString value) {
+  TypeInformation stringLiteralType(DartString value) {
     return new StringLiteralTypeInformation(
         value, compiler.typesTask.stringType);
   }
diff --git a/pkg/compiler/lib/src/inferrer/type_graph_nodes.dart b/pkg/compiler/lib/src/inferrer/type_graph_nodes.dart
index dedb4e2..1a6842f 100644
--- a/pkg/compiler/lib/src/inferrer/type_graph_nodes.dart
+++ b/pkg/compiler/lib/src/inferrer/type_graph_nodes.dart
@@ -14,7 +14,8 @@
 import '../dart_types.dart' show DartType, FunctionType, TypeKind;
 import '../elements/elements.dart';
 import '../native/native.dart' as native;
-import '../tree/tree.dart' as ast show DartString, Node, LiteralBool, Send;
+import '../tree/tree.dart' as ast show Node, LiteralBool, Send;
+import '../tree/dartstring.dart' show DartString;
 import '../types/types.dart'
     show
         ContainerTypeMask,
@@ -1209,7 +1210,7 @@
 }
 
 class StringLiteralTypeInformation extends ConcreteTypeInformation {
-  final ast.DartString value;
+  final DartString value;
 
   StringLiteralTypeInformation(value, TypeMask mask)
       : super(new ValueTypeMask(mask, new StringConstantValue(value))),
diff --git a/pkg/compiler/lib/src/js_backend/constant_system_javascript.dart b/pkg/compiler/lib/src/js_backend/constant_system_javascript.dart
index bfd156e..4bbf530 100644
--- a/pkg/compiler/lib/src/js_backend/constant_system_javascript.dart
+++ b/pkg/compiler/lib/src/js_backend/constant_system_javascript.dart
@@ -11,7 +11,7 @@
 import '../core_types.dart' show CoreTypes;
 import '../dart_types.dart';
 import '../elements/elements.dart' show ClassElement, FieldElement;
-import '../tree/tree.dart' show DartString, LiteralDartString;
+import '../tree/dartstring.dart' show DartString, LiteralDartString;
 import 'js_backend.dart';
 
 const JAVA_SCRIPT_CONSTANT_SYSTEM = const JavaScriptConstantSystem();
diff --git a/pkg/compiler/lib/src/js_emitter/constant_ordering.dart b/pkg/compiler/lib/src/js_emitter/constant_ordering.dart
index 27651c2..57ce762 100644
--- a/pkg/compiler/lib/src/js_emitter/constant_ordering.dart
+++ b/pkg/compiler/lib/src/js_emitter/constant_ordering.dart
@@ -8,7 +8,7 @@
 
 import '../dart_types.dart';
 import '../elements/elements.dart' show Element, Elements, FieldElement;
-import '../tree/tree.dart' show DartString;
+import '../tree/dartstring.dart' show DartString;
 import '../js_backend/js_backend.dart' show SyntheticConstantKind;
 
 /// A canonical but arbrary ordering of constants. The ordering is 'stable'
diff --git a/pkg/compiler/lib/src/ssa/optimize.dart b/pkg/compiler/lib/src/ssa/optimize.dart
index d89f9de..80f5e16 100644
--- a/pkg/compiler/lib/src/ssa/optimize.dart
+++ b/pkg/compiler/lib/src/ssa/optimize.dart
@@ -14,7 +14,7 @@
 import '../js_backend/backend_helpers.dart' show BackendHelpers;
 import '../js_backend/js_backend.dart';
 import '../native/native.dart' as native;
-import '../tree/tree.dart' as ast;
+import '../tree/dartstring.dart' as ast;
 import '../types/types.dart';
 import '../universe/selector.dart' show Selector;
 import '../universe/side_effects.dart' show SideEffects;
diff --git a/pkg/compiler/lib/src/string_validator.dart b/pkg/compiler/lib/src/string_validator.dart
index 1965695..866d0f0 100644
--- a/pkg/compiler/lib/src/string_validator.dart
+++ b/pkg/compiler/lib/src/string_validator.dart
@@ -10,7 +10,8 @@
 
 import 'common.dart';
 import 'tokens/token.dart' show Token;
-import 'tree/tree.dart';
+import 'tree/nodes.dart' show StringQuoting;
+import 'tree/dartstring.dart' show DartString;
 import 'util/characters.dart';
 
 class StringValidator {
diff --git a/runtime/BUILD.gn b/runtime/BUILD.gn
index 499fc42..df10d3a 100644
--- a/runtime/BUILD.gn
+++ b/runtime/BUILD.gn
@@ -205,7 +205,6 @@
     "--quiet",
     "--output", rebase_path(output, root_build_dir),
     "--input", rebase_path("vm/version_in.cc", root_build_dir),
-    "--ignore_svn_revision",
   ]
 }
 
diff --git a/runtime/bin/BUILD.gn b/runtime/bin/BUILD.gn
index 2e92fe3..099686e 100644
--- a/runtime/bin/BUILD.gn
+++ b/runtime/bin/BUILD.gn
@@ -219,8 +219,6 @@
                 "scope",
                 [ "io_impl_sources.gypi" ])
 
-if (!defined(is_fuchsia) || (current_toolchain == host_toolchain)) {
-
 executable("gen_snapshot") {
   configs += ["..:dart_config",
               "..:dart_product_config",
@@ -255,6 +253,13 @@
   include_dirs = [
     "..",
   ]
+
+  if (is_mac) {
+    libs = [
+      "CoreFoundation.framework",
+      "CoreServices.framework"
+    ]
+  }
 }
 
 # A source set for the implementation of 'dart:io' library
@@ -298,8 +303,6 @@
   ]
 }
 
-}  # current_toolchain == host_toolchain
-
 source_set("libdart_embedder_noio") {
   configs += ["..:dart_config",
               "..:dart_product_config",
diff --git a/runtime/bin/builtin_impl_sources.gypi b/runtime/bin/builtin_impl_sources.gypi
index 2e6ae0c..ac6ee92 100644
--- a/runtime/bin/builtin_impl_sources.gypi
+++ b/runtime/bin/builtin_impl_sources.gypi
@@ -13,6 +13,7 @@
     'crypto_fuchsia.cc',
     'crypto_linux.cc',
     'crypto_macos.cc',
+    'crypto_test.cc',
     'crypto_win.cc',
     'builtin_common.cc',
     'dartutils.cc',
diff --git a/runtime/bin/crypto_fuchsia.cc b/runtime/bin/crypto_fuchsia.cc
index 9423f7c..04c5f22 100644
--- a/runtime/bin/crypto_fuchsia.cc
+++ b/runtime/bin/crypto_fuchsia.cc
@@ -7,20 +7,23 @@
 
 #include "bin/crypto.h"
 
+#include <magenta/syscalls.h>
+
 namespace dart {
 namespace bin {
 
 bool Crypto::GetRandomBytes(intptr_t count, uint8_t* buffer) {
-  uint32_t num;
   intptr_t read = 0;
   while (read < count) {
-    if (rand_r(&num) != 0) {
+    const intptr_t remaining = count - read;
+    const intptr_t len =
+        (MX_CPRNG_DRAW_MAX_LEN < remaining) ? MX_CPRNG_DRAW_MAX_LEN
+                                            : remaining;
+    const mx_ssize_t res = mx_cprng_draw(buffer + read, len);
+    if (res == ERR_INVALID_ARGS) {
       return false;
     }
-    for (int i = 0; i < 4 && read < count; i++) {
-      buffer[read] = num >> (i * 8);
-      read++;
-    }
+    read += res;
   }
   return true;
 }
diff --git a/runtime/bin/crypto_test.cc b/runtime/bin/crypto_test.cc
new file mode 100644
index 0000000..65a2ac3
--- /dev/null
+++ b/runtime/bin/crypto_test.cc
@@ -0,0 +1,21 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+#include "bin/crypto.h"
+#include "platform/assert.h"
+#include "platform/globals.h"
+#include "vm/unit_test.h"
+
+namespace dart {
+namespace bin {
+
+TEST_CASE(GetRandomBytes) {
+  const intptr_t kNumRandomBytes = 127;
+  uint8_t buf[kNumRandomBytes];
+  const bool res = Crypto::GetRandomBytes(kNumRandomBytes, buf);
+  EXPECT(res);
+}
+
+}  // namespace bin
+}  // namespace dart
diff --git a/runtime/bin/file.cc b/runtime/bin/file.cc
index 43e1944..a3dcd7f 100644
--- a/runtime/bin/file.cc
+++ b/runtime/bin/file.cc
@@ -113,6 +113,7 @@
 void FUNCTION_NAME(File_Close)(Dart_NativeArguments args) {
   File* file = GetFile(args);
   ASSERT(file != NULL);
+  file->Close();
   file->DeleteWeakHandle(Dart_CurrentIsolate());
   file->Release();
 
diff --git a/runtime/bin/file_linux.cc b/runtime/bin/file_linux.cc
index eab92d5..4f61db1 100644
--- a/runtime/bin/file_linux.cc
+++ b/runtime/bin/file_linux.cc
@@ -39,7 +39,8 @@
 
 
 File::~File() {
-  if (!IsClosed()) {
+  if (!IsClosed() &&
+      handle_->fd() != STDOUT_FILENO && handle_->fd() != STDERR_FILENO) {
     Close();
   }
   delete handle_;
diff --git a/runtime/bin/file_macos.cc b/runtime/bin/file_macos.cc
index a43b14e..38699cd 100644
--- a/runtime/bin/file_macos.cc
+++ b/runtime/bin/file_macos.cc
@@ -41,7 +41,8 @@
 
 
 File::~File() {
-  if (!IsClosed()) {
+  if (!IsClosed() &&
+      handle_->fd() != STDOUT_FILENO && handle_->fd() != STDERR_FILENO) {
     Close();
   }
   delete handle_;
diff --git a/runtime/bin/file_win.cc b/runtime/bin/file_win.cc
index 8d45a17..f487a88 100644
--- a/runtime/bin/file_win.cc
+++ b/runtime/bin/file_win.cc
@@ -38,7 +38,8 @@
 
 
 File::~File() {
-  if (!IsClosed()) {
+  if (!IsClosed() &&
+      handle_->fd() != _fileno(stdout) && handle_->fd() != _fileno(stderr)) {
     Close();
   }
   delete handle_;
diff --git a/runtime/bin/fuchsia_vm_tests.txt b/runtime/bin/fuchsia_vm_tests.txt
index 665cf38..0cbf30a9 100644
--- a/runtime/bin/fuchsia_vm_tests.txt
+++ b/runtime/bin/fuchsia_vm_tests.txt
@@ -1,3 +1,4 @@
+GetRandomBytes
 CircularLinkedList
 Read
 FileLength
@@ -511,6 +512,8 @@
 IsolateReload_PendingStaticCall_DefinedToNSM
 IsolateReload_PendingStaticCall_NSMToDefined
 IsolateReload_PendingSuperCall
+IsolateReload_TearOff_Equality
+IsolateReload_TearOff_List_Set
 IsolateReload_EnumEquality
 IsolateReload_EnumIdentical
 IsolateReload_EnumReorderIdentical
@@ -524,6 +527,18 @@
 IsolateReload_DirectSubclasses_Success
 IsolateReload_DirectSubclasses_GhostSubclass
 IsolateReload_DirectSubclasses_Failure
+IsolateReload_ChangeInstanceFormat0
+IsolateReload_ChangeInstanceFormat1
+IsolateReload_ChangeInstanceFormat2
+IsolateReload_ChangeInstanceFormat3
+IsolateReload_ChangeInstanceFormat4
+IsolateReload_ChangeInstanceFormat5
+IsolateReload_ChangeInstanceFormat6
+IsolateReload_ChangeInstanceFormat7
+IsolateReload_NoLibsModified
+IsolateReload_MainLibModified
+IsolateReload_ImportedLibModified
+IsolateReload_PrefixImportedLibModified
 IsolateCurrent
 IsolateSpawn
 StackLimitInterrupts
diff --git a/runtime/bin/main.cc b/runtime/bin/main.cc
index 0c6b8b7..a90c1a4 100644
--- a/runtime/bin/main.cc
+++ b/runtime/bin/main.cc
@@ -452,6 +452,26 @@
 }
 
 
+static bool ProcessHotReloadRollbackTestModeOption(
+      const char* arg,
+      CommandLineOptions* vm_options) {
+  // Identity reload.
+  vm_options->AddArgument("--identity_reload");
+  // Start reloading quickly.
+  vm_options->AddArgument("--reload_every=4");
+  // Reload from optimized and unoptimized code.
+  vm_options->AddArgument("--reload_every_optimized=false");
+  // Reload less frequently as time goes on.
+  vm_options->AddArgument("--reload_every_back_off");
+  // Ensure that every isolate has reloaded once before exiting.
+  vm_options->AddArgument("--check_reloaded");
+  // Force all reloads to fail and execute the rollback code.
+  vm_options->AddArgument("--reload_force_rollback");
+
+  return true;
+}
+
+
 static struct {
   const char* option_name;
   bool (*process)(const char* option, CommandLineOptions* vm_options);
@@ -477,6 +497,7 @@
   { "--use-blobs", ProcessUseBlobsOption },
   { "--trace-loading", ProcessTraceLoadingOption },
   { "--hot-reload-test-mode", ProcessHotReloadTestModeOption },
+  { "--hot-reload-rollback-test-mode", ProcessHotReloadRollbackTestModeOption },
   { NULL, NULL }
 };
 
diff --git a/runtime/bin/platform_fuchsia.cc b/runtime/bin/platform_fuchsia.cc
index ace3c37..198521b 100644
--- a/runtime/bin/platform_fuchsia.cc
+++ b/runtime/bin/platform_fuchsia.cc
@@ -28,7 +28,7 @@
 
 
 int Platform::NumberOfProcessors() {
-  return mxr_get_nprocs();
+  return mxr_get_nprocs_conf();
 }
 
 
diff --git a/runtime/bin/run_vm_tests_fuchsia.cc b/runtime/bin/run_vm_tests_fuchsia.cc
index 431b162..43185ac 100644
--- a/runtime/bin/run_vm_tests_fuchsia.cc
+++ b/runtime/bin/run_vm_tests_fuchsia.cc
@@ -21,8 +21,12 @@
 // command line argument which is the path to a file containing a list of tests
 // to run, one per line.
 
+// TODO(zra): Make this a command line argument
 const char* kRunVmTestsPath = "/boot/bin/dart_vm_tests";
 
+// The simulator only has 512MB;
+const intptr_t kOldGenHeapSizeMB = 256;
+
 // Tests that are invalid, wedge, or cause panics.
 const char* kSkip[] = {
   // These expect a file to exist that we aren't putting in the image.
@@ -63,6 +67,8 @@
   // No realpath.
   "Dart2JSCompilerStats",
   "Dart2JSCompileAll",
+  // Uses too much memory.
+  "PrintJSON",
 };
 
 // Expected to fail/crash.
@@ -103,11 +109,11 @@
   "TimelinePauses_BeginEnd",
   // Needs NativeSymbolResolver
   "Service_PersistentHandles",
-  // Need to investigate:
+  // Crashes in realloc:
   "FindCodeObject",
-  "ThreadIterator_AddFindRemove",
-  "PrintJSON",
   "SourceReport_Coverage_AllFunctions_ForceCompile",
+  // pthread TLS destructors are not run.
+  "ThreadIterator_AddFindRemove",
 };
 
 
@@ -139,10 +145,16 @@
 
 
 static int run_test(const char* test_name) {
-  const intptr_t kArgc = 2;
-  const char* argv[3];
+  const intptr_t kArgc = 3;
+  const char* argv[kArgc];
+
+  char old_gen_arg[64];
+  snprintf(old_gen_arg, sizeof(old_gen_arg), "--old_gen_heap_size=%ld",
+      kOldGenHeapSizeMB);
+
   argv[0] = kRunVmTestsPath;
-  argv[1] = test_name;
+  argv[1] = old_gen_arg;
+  argv[2] = test_name;
 
   mx_handle_t p = launchpad_launch(argv[0], kArgc, argv);
   if (p < 0) {
diff --git a/runtime/bin/secure_socket_boringssl.cc b/runtime/bin/secure_socket_boringssl.cc
index 0fd1c9e..def3aae 100644
--- a/runtime/bin/secure_socket_boringssl.cc
+++ b/runtime/bin/secure_socket_boringssl.cc
@@ -800,10 +800,14 @@
   // PEM_read_bio_X509 reads PEM-encoded certificates from a bio (in our case,
   // backed by a memory buffer), and returns X509 objects, one by one.
   // When the end of the bio is reached, it returns null.
-  while ((root_cert = PEM_read_bio_X509(roots_bio, NULL, NULL, NULL))) {
+  while ((root_cert = PEM_read_bio_X509(roots_bio, NULL, NULL, NULL)) != NULL) {
     X509_STORE_add_cert(store, root_cert);
   }
   BIO_free(roots_bio);
+  // If there is an error here, it must be the error indicating that we are done
+  // reading PEM certificates.
+  ASSERT((ERR_peek_error() == 0) || NoPEMStartLine());
+  ERR_clear_error();
 #endif  // defined(TARGET_OS_ANDROID)
 }
 
diff --git a/runtime/bin/vmservice/loader.dart b/runtime/bin/vmservice/loader.dart
index bf5af11..8af63b5 100644
--- a/runtime/bin/vmservice/loader.dart
+++ b/runtime/bin/vmservice/loader.dart
@@ -891,7 +891,7 @@
   isolateEmbedderData.values.toList().forEach((IsolateLoaderState ils) {
     ils.cleanup();
     assert(ils.sp != null);
-    _sendResourceResponse(ils.sp, 1, null, null, message);
+    _sendResourceResponse(ils.sp, 1, null, null, null, message);
   });
 }
 
diff --git a/runtime/lib/vmservice.cc b/runtime/lib/vmservice.cc
index 584ceb8..b4a8b14 100644
--- a/runtime/lib/vmservice.cc
+++ b/runtime/lib/vmservice.cc
@@ -416,8 +416,8 @@
 
   intptr_t archive_size = archive.Length();
 
-  const Array& result_list = Array::Handle(thread->zone(),
-    Array::New(2 * archive_size));
+  Dart_Handle result_list = Dart_NewList(2 * archive_size);
+  ASSERT(!Dart_IsError(result_list));
 
   intptr_t idx = 0;
   while (archive.HasMore()) {
@@ -438,14 +438,11 @@
     Dart_NewWeakPersistentHandle(
         dart_contents, contents, contents_length, ContentsFinalizer);
 
-    result_list.SetAt(idx, Api::UnwrapStringHandle(
-        thread->zone(), dart_filename));
-    result_list.SetAt(idx + 1, Api::UnwrapExternalTypedDataHandle(
-        thread->zone(), dart_contents));
+    Dart_ListSetAt(result_list, idx, dart_filename);
+    Dart_ListSetAt(result_list, (idx + 1), dart_contents);
     idx += 2;
   }
-
-  return result_list.raw();
+  return Api::UnwrapArrayHandle(thread->zone(), result_list).raw();
 #else
   return Object::null();
 #endif
diff --git a/runtime/observatory/lib/cpu_profile.dart b/runtime/observatory/lib/cpu_profile.dart
index c8a2b53..5ebd9a5 100644
--- a/runtime/observatory/lib/cpu_profile.dart
+++ b/runtime/observatory/lib/cpu_profile.dart
@@ -5,6 +5,7 @@
 library cpu_profiler;
 
 import 'dart:typed_data';
+import 'package:observatory/models.dart' as M;
 import 'package:observatory/service.dart';
 import 'package:observatory/utils.dart';
 
diff --git a/runtime/observatory/lib/debugger.dart b/runtime/observatory/lib/debugger.dart
index 628b2a9..c62ce0b 100644
--- a/runtime/observatory/lib/debugger.dart
+++ b/runtime/observatory/lib/debugger.dart
@@ -5,6 +5,7 @@
 library debugger;
 
 import 'dart:async';
+import 'package:observatory/models.dart' as M;
 import 'package:observatory/service.dart';
 
 part 'src/debugger/debugger.dart';
diff --git a/runtime/observatory/lib/elements.dart b/runtime/observatory/lib/elements.dart
index 4d9786e..6e2f4f8 100644
--- a/runtime/observatory/lib/elements.dart
+++ b/runtime/observatory/lib/elements.dart
@@ -2,10 +2,9 @@
 
 // Export elements.
 export 'package:observatory/src/elements/action_link.dart';
-export 'package:observatory/src/elements/class_ref.dart';
+export 'package:observatory/src/elements/class_ref_as_value.dart';
 export 'package:observatory/src/elements/class_tree.dart';
 export 'package:observatory/src/elements/class_view.dart';
-export 'package:observatory/src/elements/code_ref.dart';
 export 'package:observatory/src/elements/code_view.dart';
 export 'package:observatory/src/elements/context_ref.dart';
 export 'package:observatory/src/elements/context_view.dart';
@@ -16,10 +15,7 @@
 export 'package:observatory/src/elements/eval_link.dart';
 export 'package:observatory/src/elements/field_ref.dart';
 export 'package:observatory/src/elements/field_view.dart';
-export 'package:observatory/src/elements/flag_list.dart';
-export 'package:observatory/src/elements/function_ref.dart';
 export 'package:observatory/src/elements/function_view.dart';
-export 'package:observatory/src/elements/general_error.dart';
 export 'package:observatory/src/elements/heap_map.dart';
 export 'package:observatory/src/elements/heap_profile.dart';
 export 'package:observatory/src/elements/heap_snapshot.dart';
@@ -32,7 +28,7 @@
 export 'package:observatory/src/elements/isolate_summary.dart';
 export 'package:observatory/src/elements/isolate_view.dart';
 export 'package:observatory/src/elements/json_view.dart';
-export 'package:observatory/src/elements/library_ref.dart';
+export 'package:observatory/src/elements/library_ref_as_value.dart';
 export 'package:observatory/src/elements/library_view.dart';
 export 'package:observatory/src/elements/logging.dart';
 export 'package:observatory/src/elements/megamorphiccache_view.dart';
@@ -46,7 +42,6 @@
 export 'package:observatory/src/elements/persistent_handles.dart';
 export 'package:observatory/src/elements/ports.dart';
 export 'package:observatory/src/elements/script_inset.dart';
-export 'package:observatory/src/elements/script_ref.dart';
 export 'package:observatory/src/elements/script_view.dart';
 export 'package:observatory/src/elements/service_ref.dart';
 export 'package:observatory/src/elements/service_view.dart';
@@ -56,10 +51,24 @@
 
 import 'dart:async';
 
+import 'package:observatory/src/elements/class_ref.dart';
+import 'package:observatory/src/elements/class_ref_wrapper.dart';
+import 'package:observatory/src/elements/code_ref.dart';
+import 'package:observatory/src/elements/code_ref_wrapper.dart';
+import 'package:observatory/src/elements/containers/virtual_collection.dart';
+import 'package:observatory/src/elements/containers/virtual_tree.dart';
 import 'package:observatory/src/elements/curly_block.dart';
 import 'package:observatory/src/elements/curly_block_wrapper.dart';
+import 'package:observatory/src/elements/error_ref.dart';
+import 'package:observatory/src/elements/error_ref_wrapper.dart';
+import 'package:observatory/src/elements/flag_list.dart';
+import 'package:observatory/src/elements/function_ref.dart';
+import 'package:observatory/src/elements/function_ref_wrapper.dart';
+import 'package:observatory/src/elements/general_error.dart';
 import 'package:observatory/src/elements/isolate_ref.dart';
 import 'package:observatory/src/elements/isolate_ref_wrapper.dart';
+import 'package:observatory/src/elements/library_ref.dart';
+import 'package:observatory/src/elements/library_ref_wrapper.dart';
 import 'package:observatory/src/elements/nav/bar.dart';
 import 'package:observatory/src/elements/nav/class_menu.dart';
 import 'package:observatory/src/elements/nav/class_menu_wrapper.dart';
@@ -81,14 +90,27 @@
 import 'package:observatory/src/elements/nav/top_menu_wrapper.dart';
 import 'package:observatory/src/elements/nav/vm_menu.dart';
 import 'package:observatory/src/elements/nav/vm_menu_wrapper.dart';
+import 'package:observatory/src/elements/script_ref.dart';
+import 'package:observatory/src/elements/script_ref_wrapper.dart';
+import 'package:observatory/src/elements/source_link.dart';
+import 'package:observatory/src/elements/source_link_wrapper.dart';
 import 'package:observatory/src/elements/view_footer.dart';
 import 'package:observatory/src/elements/vm_connect_target.dart';
 import 'package:observatory/src/elements/vm_connect.dart';
 
 export 'package:observatory/src/elements/helpers/rendering_queue.dart';
 
+export 'package:observatory/src/elements/class_ref.dart';
+export 'package:observatory/src/elements/code_ref.dart';
+export 'package:observatory/src/elements/containers/virtual_collection.dart';
+export 'package:observatory/src/elements/containers/virtual_tree.dart';
 export 'package:observatory/src/elements/curly_block.dart';
+export 'package:observatory/src/elements/error_ref.dart';
+export 'package:observatory/src/elements/flag_list.dart';
+export 'package:observatory/src/elements/function_ref.dart';
+export 'package:observatory/src/elements/general_error.dart';
 export 'package:observatory/src/elements/isolate_ref.dart';
+export 'package:observatory/src/elements/library_ref.dart';
 export 'package:observatory/src/elements/nav/bar.dart';
 export 'package:observatory/src/elements/nav/class_menu.dart';
 export 'package:observatory/src/elements/nav/isolate_menu.dart';
@@ -101,6 +123,8 @@
 export 'package:observatory/src/elements/nav/refresh.dart';
 export 'package:observatory/src/elements/nav/top_menu.dart';
 export 'package:observatory/src/elements/nav/vm_menu.dart';
+export 'package:observatory/src/elements/script_ref.dart';
+export 'package:observatory/src/elements/source_link.dart';
 export 'package:observatory/src/elements/view_footer.dart';
 export 'package:observatory/src/elements/vm_connect_target.dart';
 export 'package:observatory/src/elements/vm_connect.dart';
@@ -108,10 +132,22 @@
 // Even though this function does not invoke any asynchronous operation
 // it is marked as async to allow future backward compatible changes.
 Future initElements() async {
+  ClassRefElement.tag.ensureRegistration();
+  ClassRefElementWrapper.tag.ensureRegistration();
+  CodeRefElement.tag.ensureRegistration();
+  CodeRefElementWrapper.tag.ensureRegistration();
   CurlyBlockElement.tag.ensureRegistration();
   CurlyBlockElementWrapper.tag.ensureRegistration();
+  ErrorRefElement.tag.ensureRegistration();
+  ErrorRefElementWrapper.tag.ensureRegistration();
+  FlagListElement.tag.ensureRegistration();
+  FunctionRefElement.tag.ensureRegistration();
+  FunctionRefElementWrapper.tag.ensureRegistration();
+  GeneralErrorElement.tag.ensureRegistration();
   IsolateRefElement.tag.ensureRegistration();
   IsolateRefElementWrapper.tag.ensureRegistration();
+  LibraryRefElement.tag.ensureRegistration();
+  LibraryRefElementWrapper.tag.ensureRegistration();
   NavBarElement.tag.ensureRegistration();
   NavClassMenuElement.tag.ensureRegistration();
   NavClassMenuElementWrapper.tag.ensureRegistration();
@@ -133,7 +169,13 @@
   NavTopMenuElementWrapper.tag.ensureRegistration();
   NavVMMenuElement.tag.ensureRegistration();
   NavVMMenuElementWrapper.tag.ensureRegistration();
+  ScriptRefElement.tag.ensureRegistration();
+  ScriptRefElementWrapper.tag.ensureRegistration();
+  SourceLinkElement.tag.ensureRegistration();
+  SourceLinkElementWrapper.tag.ensureRegistration();
   ViewFooterElement.tag.ensureRegistration();
+  VirtualCollectionElement.tag.ensureRegistration();
+  VirtualTreeElement.tag.ensureRegistration();
   VMConnectElement.tag.ensureRegistration();
   VMConnectTargetElement.tag.ensureRegistration();
 }
diff --git a/runtime/observatory/lib/elements.html b/runtime/observatory/lib/elements.html
index 731c907..ed5c73c 100644
--- a/runtime/observatory/lib/elements.html
+++ b/runtime/observatory/lib/elements.html
@@ -1,8 +1,7 @@
 <link rel="import" href="src/elements/action_link.html">
-<link rel="import" href="src/elements/class_ref.html">
+<link rel="import" href="src/elements/class_ref_as_value.html">
 <link rel="import" href="src/elements/class_tree.html">
 <link rel="import" href="src/elements/class_view.html">
-<link rel="import" href="src/elements/code_ref.html">
 <link rel="import" href="src/elements/code_view.html">
 <link rel="import" href="src/elements/cpu_profile.html">
 <link rel="import" href="src/elements/debugger.html">
@@ -11,10 +10,7 @@
 <link rel="import" href="src/elements/eval_link.html">
 <link rel="import" href="src/elements/field_ref.html">
 <link rel="import" href="src/elements/field_view.html">
-<link rel="import" href="src/elements/flag_list.html">
-<link rel="import" href="src/elements/function_ref.html">
 <link rel="import" href="src/elements/function_view.html">
-<link rel="import" href="src/elements/general_error.html">
 <link rel="import" href="src/elements/heap_map.html">
 <link rel="import" href="src/elements/instance_ref.html">
 <link rel="import" href="src/elements/instance_view.html">
@@ -25,7 +21,7 @@
 <link rel="import" href="src/elements/isolate_summary.html">
 <link rel="import" href="src/elements/isolate_view.html">
 <link rel="import" href="src/elements/json_view.html">
-<link rel="import" href="src/elements/library_ref.html">
+<link rel="import" href="src/elements/library_ref_as_value.html">
 <link rel="import" href="src/elements/library_view.html">
 <link rel="import" href="src/elements/logging.html">
 <link rel="import" href="src/elements/megamorphiccache_view.html">
@@ -38,7 +34,6 @@
 <link rel="import" href="src/elements/persistent_handles.html">
 <link rel="import" href="src/elements/ports.html">
 <link rel="import" href="src/elements/script_inset.html">
-<link rel="import" href="src/elements/script_ref.html">
 <link rel="import" href="src/elements/script_view.html">
 <link rel="import" href="src/elements/service_ref.html">
 <link rel="import" href="src/elements/timeline_page.html">
diff --git a/runtime/observatory/lib/mocks.dart b/runtime/observatory/lib/mocks.dart
index facf17f..2535fa0 100644
--- a/runtime/observatory/lib/mocks.dart
+++ b/runtime/observatory/lib/mocks.dart
@@ -11,8 +11,11 @@
 part 'src/mocks/exceptions/connection_exception.dart';
 
 part 'src/mocks/objects/error.dart';
+part 'src/mocks/objects/code.dart';
 part 'src/mocks/objects/event.dart';
 part 'src/mocks/objects/class.dart';
+part 'src/mocks/objects/flag.dart';
+part 'src/mocks/objects/function.dart';
 part 'src/mocks/objects/isolate.dart';
 part 'src/mocks/objects/library.dart';
 part 'src/mocks/objects/notification.dart';
@@ -22,5 +25,7 @@
 part 'src/mocks/objects/vm.dart';
 
 part 'src/mocks/repositories/crash_dump.dart';
+part 'src/mocks/repositories/flag.dart';
 part 'src/mocks/repositories/notification.dart';
+part 'src/mocks/repositories/script.dart';
 part 'src/mocks/repositories/target.dart';
diff --git a/runtime/observatory/lib/models.dart b/runtime/observatory/lib/models.dart
index 878a72c..6fa8853 100644
--- a/runtime/observatory/lib/models.dart
+++ b/runtime/observatory/lib/models.dart
@@ -9,11 +9,14 @@
 part 'src/models/exceptions.dart';
 
 part 'src/models/objects/class.dart';
+part 'src/models/objects/code.dart';
 part 'src/models/objects/breakpoint.dart';
 part 'src/models/objects/error.dart';
 part 'src/models/objects/event.dart';
 part 'src/models/objects/extension_data.dart';
+part 'src/models/objects/flag.dart';
 part 'src/models/objects/frame.dart';
+part 'src/models/objects/function.dart';
 part 'src/models/objects/instance.dart';
 part 'src/models/objects/isolate.dart';
 part 'src/models/objects/library.dart';
@@ -25,6 +28,9 @@
 part 'src/models/objects/timeline_event.dart';
 part 'src/models/objects/vm.dart';
 
+part 'src/models/repository.dart';
 part 'src/models/repositories/crash_dump.dart';
+part 'src/models/repositories/flag.dart';
 part 'src/models/repositories/notification.dart';
+part 'src/models/repositories/script.dart';
 part 'src/models/repositories/target.dart';
diff --git a/runtime/observatory/lib/repositories.dart b/runtime/observatory/lib/repositories.dart
index 4e7cd44..feeb8f2 100644
--- a/runtime/observatory/lib/repositories.dart
+++ b/runtime/observatory/lib/repositories.dart
@@ -8,9 +8,12 @@
 import 'dart:convert';
 import 'dart:html';
 import 'package:observatory/models.dart' as M;
+import 'package:observatory/service.dart' as S;
 import 'package:observatory/service_common.dart' as SC;
 import 'package:observatory/utils.dart';
 
+part 'src/repositories/flag.dart';
 part 'src/repositories/notification.dart';
+part 'src/repositories/script.dart';
 part 'src/repositories/settings.dart';
 part 'src/repositories/target.dart';
diff --git a/runtime/observatory/lib/src/app/page.dart b/runtime/observatory/lib/src/app/page.dart
index 0129c34..980fcfa 100644
--- a/runtime/observatory/lib/src/app/page.dart
+++ b/runtime/observatory/lib/src/app/page.dart
@@ -84,7 +84,7 @@
   void onInstall() {
     if (element == null) {
       // Lazily create page.
-      element = new Element.tag('general-error');
+      element = new GeneralErrorElement(app.notifications, queue: app.queue);
     }
   }
 
@@ -92,17 +92,7 @@
     assert(element != null);
     assert(canVisit(uri));
 
-    /*
-    if (uri.path == '') {
-      // Nothing requested.
-      return;
-    }
-    */
-
-    if (element != null) {
-      GeneralErrorElement serviceElement = element;
-      serviceElement.message = "Path '${uri.path}' not found";
-    }
+    (element as GeneralErrorElement).message = "Path '${uri.path}' not found";
   }
 
   /// Catch all.
@@ -111,14 +101,14 @@
 
 /// Top-level vm info page.
 class VMPage extends SimplePage {
-  VMPage(app) : super('vm', 'service-view', app);
+  VMPage(app) : super('vm', 'vm-view', app);
 
   void _visit(Uri uri) {
     super._visit(uri);
     app.vm.reload().then((vm) {
       if (element != null) {
-        ServiceObjectViewElement serviceElement = element;
-        serviceElement.object = vm;
+        VMViewElement serviceElement = element;
+        serviceElement.vm = vm;
       }
     }).catchError((e, stack) {
       Logger.root.severe('VMPage visit error: $e');
@@ -131,16 +121,16 @@
 class FlagsPage extends SimplePage {
   FlagsPage(app) : super('flags', 'flag-list', app);
 
+  @override
+  onInstall() {
+    element = new FlagListElement(app.vm,
+        app.vm.changes.map((_) => new VMUpdateEventMock(vm: app.vm)),
+        new FlagsRepository(),
+        app.notifications);
+  }
+
   void _visit(Uri uri) {
     super._visit(uri);
-    app.vm.getFlagList().then((flags) {
-      if (element != null) {
-        FlagListElement serviceElement = element;
-        serviceElement.flagList = flags;
-      }
-    }).catchError((e, stack) {
-      Logger.root.severe('FlagsPage visit error: $e\n$stack');
-    });
   }
 }
 
diff --git a/runtime/observatory/lib/src/cpu_profile/cpu_profile.dart b/runtime/observatory/lib/src/cpu_profile/cpu_profile.dart
index fb63fba..a572279 100644
--- a/runtime/observatory/lib/src/cpu_profile/cpu_profile.dart
+++ b/runtime/observatory/lib/src/cpu_profile/cpu_profile.dart
@@ -133,7 +133,7 @@
       if (!profileCode.code.isDartCode) {
         continue;
       }
-      if (profileCode.code.kind == CodeKind.Stub) {
+      if (profileCode.code.kind == M.CodeKind.stub) {
         continue;
       }
       if (!profileCode.code.isOptimized) {
@@ -150,7 +150,7 @@
       if (!profileCode.code.isDartCode) {
         continue;
       }
-      if (profileCode.code.kind == CodeKind.Stub) {
+      if (profileCode.code.kind == M.CodeKind.stub) {
         continue;
       }
       // If the code's function isn't this function.
@@ -418,9 +418,9 @@
 
     code.profile = this;
 
-    if (code.kind == CodeKind.Stub) {
+    if (code.kind == M.CodeKind.stub) {
       attributes.add('stub');
-    } else if (code.kind == CodeKind.Dart) {
+    } else if (code.kind == M.CodeKind.dart) {
       if (code.isNative) {
         attributes.add('ffi');  // Not to be confused with a C function.
       } else {
@@ -434,9 +434,9 @@
       } else {
         attributes.add('unoptimized');
       }
-    } else if (code.kind == CodeKind.Tag) {
+    } else if (code.kind == M.CodeKind.tag) {
       attributes.add('tag');
-    } else if (code.kind == CodeKind.Native) {
+    } else if (code.kind == M.CodeKind.native) {
       attributes.add('native');
     }
     inclusiveTicks = int.parse(data['inclusiveTicks']);
@@ -537,7 +537,7 @@
   // Does this function have an unoptimized version of itself?
   bool hasUnoptimizedCode() {
     for (var profileCode in profileCodes) {
-      if (profileCode.code.kind == CodeKind.Stub) {
+      if (profileCode.code.kind == M.CodeKind.stub) {
         continue;
       }
       if (!profileCode.code.isDartCode) {
@@ -553,7 +553,7 @@
   // Has this function been inlined in another function?
   bool isInlined() {
     for (var profileCode in profileCodes) {
-      if (profileCode.code.kind == CodeKind.Stub) {
+      if (profileCode.code.kind == M.CodeKind.stub) {
         continue;
       }
       if (!profileCode.code.isDartCode) {
@@ -568,13 +568,13 @@
   }
 
   void _addKindBasedAttributes(Set<String> attribs) {
-    if (function.kind == FunctionKind.kTag) {
+    if (function.kind == M.FunctionKind.tag) {
       attribs.add('tag');
-    } else if (function.kind == FunctionKind.kStub) {
+    } else if (function.kind == M.FunctionKind.stub) {
       attribs.add('stub');
-    } else if (function.kind == FunctionKind.kNative) {
+    } else if (function.kind == M.FunctionKind.native) {
       attribs.add('native');
-    } else if (function.kind.isSynthetic()) {
+    } else if (M.isSyntheticFunction(function.kind)) {
       attribs.add('synthetic');
     } else if (function.isNative) {
       attribs.add('ffi');  // Not to be confused with a C function.
diff --git a/runtime/observatory/lib/src/debugger/debugger_location.dart b/runtime/observatory/lib/src/debugger/debugger_location.dart
index ac3a9bf..d1b4054 100644
--- a/runtime/observatory/lib/src/debugger/debugger_location.dart
+++ b/runtime/observatory/lib/src/debugger/debugger_location.dart
@@ -233,7 +233,7 @@
         for (var cls in classes) {
           assert(cls.loaded);
           for (var function in cls.functions) {
-            if (function.kind == FunctionKind.kConstructor) {
+            if (function.kind == M.FunctionKind.constructor) {
               // Constructor names are class-qualified.
               if (match.group(0) == function.name) {
                 functions.add(function);
@@ -314,7 +314,7 @@
         var completions = [];
         for (var cls in classes) {
           for (var function in cls.functions) {
-            if (function.kind == FunctionKind.kConstructor) {
+            if (function.kind == M.FunctionKind.constructor) {
               if (function.name.startsWith(match.group(0))) {
                 completions.add(function.name);
               }
diff --git a/runtime/observatory/lib/src/elements/class_ref.dart b/runtime/observatory/lib/src/elements/class_ref.dart
index b8895c6..d9940fb 100644
--- a/runtime/observatory/lib/src/elements/class_ref.dart
+++ b/runtime/observatory/lib/src/elements/class_ref.dart
@@ -4,33 +4,57 @@
 
 library class_ref_element;
 
-import 'package:observatory/service.dart';
-import 'package:polymer/polymer.dart';
-import 'service_ref.dart';
+import 'dart:html';
 import 'dart:async';
+import 'package:observatory/models.dart' as M
+  show IsolateRef, ClassRef;
+import 'package:observatory/src/elements/helpers/rendering_scheduler.dart';
+import 'package:observatory/src/elements/helpers/tag.dart';
+import 'package:observatory/src/elements/helpers/uris.dart';
 
-@CustomTag('class-ref')
-class ClassRefElement extends ServiceRefElement {
-  @observable bool asValue = false;
+class ClassRefElement extends HtmlElement implements Renderable {
+  static const tag = const Tag<ClassRefElement>('class-ref-wrapped');
+
+  RenderingScheduler<ClassRefElement> _r;
+
+  Stream<RenderedEvent<ClassRefElement>> get onRendered => _r.onRendered;
+
+  M.IsolateRef _isolate;
+  M.ClassRef _class;
+
+  M.IsolateRef get isolate => _isolate;
+  M.ClassRef get cls => _class;
+
+  factory ClassRefElement(M.IsolateRef isolate, M.ClassRef cls,
+      {RenderingQueue queue}) {
+    assert(isolate != null);
+    assert(cls != null);
+    ClassRefElement e = document.createElement(tag.name);
+    e._r = new RenderingScheduler(e, queue: queue);
+    e._isolate = isolate;
+    e._class = cls;
+    return e;
+  }
 
   ClassRefElement.created() : super.created();
 
-  String makeExpandKey(String key) {
-    return '${expandKey}/${key}';
+  @override
+  void attached() {
+    super.attached();
+    _r.enable();
   }
 
-  dynamic expander() {
-    return expandEvent;
+  @override
+  void detached() {
+    super.detached();
+    _r.disable(notify: true);
+    children = [];
   }
 
-  void expandEvent(bool expand, Function onDone) {
-    if (expand) {
-      Class cls = ref;
-      cls.reload().then((result) {
-        return Future.wait(cls.fields.map((field) => field.reload()));
-      }).whenComplete(onDone);
-    } else {
-      onDone();
-    }
+  void render() {
+    children = [
+      new AnchorElement(href: Uris.inspect(_isolate, object: _class))
+        ..text = _class.name
+    ];
   }
-}
\ No newline at end of file
+}
diff --git a/runtime/observatory/lib/src/elements/class_ref_as_value.dart b/runtime/observatory/lib/src/elements/class_ref_as_value.dart
new file mode 100644
index 0000000..7e129f8
--- /dev/null
+++ b/runtime/observatory/lib/src/elements/class_ref_as_value.dart
@@ -0,0 +1,35 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library class_ref_as_value_element;
+
+import 'package:observatory/service.dart';
+import 'package:polymer/polymer.dart';
+import 'service_ref.dart';
+import 'dart:async';
+
+@CustomTag('class-ref-as-value')
+class ClassRefAsValueElement extends ServiceRefElement {
+
+  ClassRefAsValueElement.created() : super.created();
+
+  String makeExpandKey(String key) {
+    return '${expandKey}/${key}';
+  }
+
+  dynamic expander() {
+    return expandEvent;
+  }
+
+  void expandEvent(bool expand, Function onDone) {
+    if (expand) {
+      Class cls = ref;
+      cls.reload().then((result) {
+        return Future.wait(cls.fields.map((field) => field.reload()));
+      }).whenComplete(onDone);
+    } else {
+      onDone();
+    }
+  }
+}
diff --git a/runtime/observatory/lib/src/elements/class_ref.html b/runtime/observatory/lib/src/elements/class_ref_as_value.html
similarity index 70%
rename from runtime/observatory/lib/src/elements/class_ref.html
rename to runtime/observatory/lib/src/elements/class_ref_as_value.html
index 1ffe1d1..a148981 100644
--- a/runtime/observatory/lib/src/elements/class_ref.html
+++ b/runtime/observatory/lib/src/elements/class_ref_as_value.html
@@ -1,8 +1,7 @@
 <link rel="import" href="../../../../packages/polymer/polymer.html">
-
 <link rel="import" href="service_ref.html">
 
-<polymer-element name="class-ref">
+<polymer-element name="class-ref-as-value">
   <template>
     <link rel="stylesheet" href="css/shared.css">
     <style>
@@ -12,9 +11,8 @@
         line-height: 150%;
       }
     </style><!--
-    --><a on-click="{{ goto }}" _href="{{ url }}">{{ ref.name }}</a><!--
-    --><template if="{{ asValue }}">
-      <curly-block callback="{{ expander() }}" expandKey="{{ expandKey }}">
+    --><class-ref ref="{{ ref }}"></class-ref><!--
+    --><curly-block callback="{{ expander() }}" expandKey="{{ expandKey }}">
         <div class="indented">
           <template repeat="{{ field in ref.fields }}">
             <template if="{{ field.isStatic }}">
@@ -25,9 +23,8 @@
             </template>
           </template>
         </div>
-      </curly-block>
-    </template><!--
+      </curly-block><!--
   --></template>
 </polymer-element>
 
-<script type="application/dart" src="class_ref.dart"></script>
+<script type="application/dart" src="class_ref_as_value.dart"></script>
diff --git a/runtime/observatory/lib/src/elements/class_ref_wrapper.dart b/runtime/observatory/lib/src/elements/class_ref_wrapper.dart
new file mode 100644
index 0000000..daa15b7
--- /dev/null
+++ b/runtime/observatory/lib/src/elements/class_ref_wrapper.dart
@@ -0,0 +1,56 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:html';
+
+import 'package:observatory/app.dart';
+import 'package:observatory/service_html.dart' show Class;
+import 'package:observatory/src/elements/class_ref.dart';
+import 'package:observatory/src/elements/helpers/tag.dart';
+import 'package:observatory/src/elements/shims/binding.dart';
+
+@bindable
+class ClassRefElementWrapper extends HtmlElement {
+
+  static const binder = const Binder<ClassRefElementWrapper>(const {
+      'ref': #ref
+    });
+
+  static const tag = const Tag<ClassRefElementWrapper>('class-ref');
+
+  Class _class;
+  Class get ref => _class;
+  void set ref(Class ref) { _class = ref; render(); }
+
+  ClassRefElementWrapper.created() : super.created() {
+    binder.registerCallback(this);
+    createShadowRoot();
+    render();
+  }
+
+  @override
+  void attached() {
+    super.attached();
+    render();
+  }
+
+  void render() {
+    shadowRoot.children = [];
+    if (ref == null) return;
+
+    shadowRoot.children = [
+      new StyleElement()
+        ..text = '''
+        class-ref-wrapped > a[href]:hover {
+            text-decoration: underline;
+        }
+        class-ref-wrapped > a[href] {
+            color: #0489c3;
+            text-decoration: none;
+        }''',
+      new ClassRefElement(_class.isolate, _class,
+          queue: ObservatoryApplication.app.queue)
+    ];
+  }
+}
diff --git a/runtime/observatory/lib/src/elements/class_tree.html b/runtime/observatory/lib/src/elements/class_tree.html
index 94e43f7..e2fbb32 100644
--- a/runtime/observatory/lib/src/elements/class_tree.html
+++ b/runtime/observatory/lib/src/elements/class_tree.html
@@ -1,5 +1,4 @@
 <link rel="import" href="../../../../packages/polymer/polymer.html">
-<link rel="import" href="class_ref.html">
 
 <polymer-element name="class-tree">
   <template>
diff --git a/runtime/observatory/lib/src/elements/class_view.html b/runtime/observatory/lib/src/elements/class_view.html
index df003cd..94efab1 100644
--- a/runtime/observatory/lib/src/elements/class_view.html
+++ b/runtime/observatory/lib/src/elements/class_view.html
@@ -4,11 +4,8 @@
 <link rel="import" href="eval_box.html">
 <link rel="import" href="eval_link.html">
 <link rel="import" href="field_ref.html">
-<link rel="import" href="function_ref.html">
 <link rel="import" href="instance_ref.html">
-<link rel="import" href="library_ref.html">
 <link rel="import" href="script_inset.html">
-<link rel="import" href="script_ref.html">
 
 <polymer-element name="class-view">
   <template>
diff --git a/runtime/observatory/lib/src/elements/code_ref.dart b/runtime/observatory/lib/src/elements/code_ref.dart
index 88464de..bead036 100644
--- a/runtime/observatory/lib/src/elements/code_ref.dart
+++ b/runtime/observatory/lib/src/elements/code_ref.dart
@@ -4,31 +4,59 @@
 
 library code_ref_element;
 
-import 'package:polymer/polymer.dart';
-import 'service_ref.dart';
-import 'package:observatory/service.dart';
+import 'dart:html';
+import 'dart:async';
+import 'package:observatory/models.dart' as M
+  show IsolateRef, CodeRef, isSyntheticCode;
+import 'package:observatory/src/elements/helpers/rendering_scheduler.dart';
+import 'package:observatory/src/elements/helpers/tag.dart';
+import 'package:observatory/src/elements/helpers/uris.dart';
 
-@CustomTag('code-ref')
-class CodeRefElement extends ServiceRefElement {
-  CodeRefElement.created() : super.created();
+class CodeRefElement extends HtmlElement implements Renderable {
+  static const tag = const Tag<CodeRefElement>('code-ref-wrapped');
 
-  Code get code => ref;
+  RenderingScheduler<CodeRefElement> _r;
 
-  refChanged(oldValue) {
-    super.refChanged(oldValue);
-    _updateShadowDom();
+  Stream<RenderedEvent<CodeRefElement>> get onRendered => _r.onRendered;
+
+  M.IsolateRef _isolate;
+  M.CodeRef _code;
+
+  M.IsolateRef get isolate => _isolate;
+  M.CodeRef get code => _code;
+
+  factory CodeRefElement(M.IsolateRef isolate, M.CodeRef code,
+      {RenderingQueue queue}) {
+    assert(isolate != null);
+    assert(code != null);
+    CodeRefElement e = document.createElement(tag.name);
+    e._r = new RenderingScheduler(e, queue: queue);
+    e._isolate = isolate;
+    e._code = code;
+    return e;
   }
 
-  void _updateShadowDom() {
-    clearShadowRoot();
-    if (code == null) {
-      return;
-    }
-    var name = (code.isOptimized ? '*' : '') + code.name;
-    if (code.isDartCode) {
-      insertLinkIntoShadowRoot(name, url, hoverText);
-    } else {
-      insertTextSpanIntoShadowRoot(name);
-    }
+  CodeRefElement.created() : super.created();
+
+  @override
+  void attached() {
+    super.attached();
+    _r.enable();
+  }
+
+  @override
+  void detached() {
+    super.detached();
+    _r.disable(notify: true);
+    children = [];
+  }
+
+  void render() {
+    final name = (_code.isOptimized ? '*' : '') + _code.name;
+    children = [
+      new AnchorElement(href: M.isSyntheticCode(_code.kind) ? null
+          : Uris.inspect(_isolate, object: _code))
+        ..text = name
+    ];
   }
 }
diff --git a/runtime/observatory/lib/src/elements/code_ref.html b/runtime/observatory/lib/src/elements/code_ref.html
deleted file mode 100644
index 4a8c7f5..0000000
--- a/runtime/observatory/lib/src/elements/code_ref.html
+++ /dev/null
@@ -1,8 +0,0 @@
-<link rel="import" href="../../../../packages/polymer/polymer.html">
-<link rel="import" href="service_ref.html">
-
-<polymer-element name="code-ref">
-  <template><link rel="stylesheet" href="css/shared.css"></template>
-</polymer-element>
-
-<script type="application/dart" src="code_ref.dart"></script>
\ No newline at end of file
diff --git a/runtime/observatory/lib/src/elements/code_ref_wrapper.dart b/runtime/observatory/lib/src/elements/code_ref_wrapper.dart
new file mode 100644
index 0000000..503a784
--- /dev/null
+++ b/runtime/observatory/lib/src/elements/code_ref_wrapper.dart
@@ -0,0 +1,56 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:html';
+
+import 'package:observatory/app.dart';
+import 'package:observatory/service_html.dart' show Code;
+import 'package:observatory/src/elements/code_ref.dart';
+import 'package:observatory/src/elements/helpers/tag.dart';
+import 'package:observatory/src/elements/shims/binding.dart';
+
+@bindable
+class CodeRefElementWrapper extends HtmlElement {
+
+  static const binder = const Binder<CodeRefElementWrapper>(const {
+      'ref': #ref
+    });
+
+  static const tag = const Tag<CodeRefElementWrapper>('code-ref');
+
+  Code _code;
+  Code get ref => _code;
+  void set ref(Code ref) { _code = ref; render(); }
+
+  CodeRefElementWrapper.created() : super.created() {
+    binder.registerCallback(this);
+    createShadowRoot();
+    render();
+  }
+
+  @override
+  void attached() {
+    super.attached();
+    render();
+  }
+
+  void render() {
+    shadowRoot.children = [];
+    if (ref == null) return;
+
+    shadowRoot.children = [
+      new StyleElement()
+        ..text = '''
+        code-ref-wrapped > a[href]:hover {
+            text-decoration: underline;
+        }
+        code-ref-wrapped > a[href] {
+            color: #0489c3;
+            text-decoration: none;
+        }''',
+      new CodeRefElement(_code.isolate, _code,
+          queue: ObservatoryApplication.app.queue)
+    ];
+  }
+}
diff --git a/runtime/observatory/lib/src/elements/code_view.html b/runtime/observatory/lib/src/elements/code_view.html
index 10e280c..048024e 100644
--- a/runtime/observatory/lib/src/elements/code_view.html
+++ b/runtime/observatory/lib/src/elements/code_view.html
@@ -1,7 +1,5 @@
 <link rel="import" href="../../../../packages/polymer/polymer.html">
-<link rel="import" href="function_ref.html">
 <link rel="import" href="instance_ref.html">
-<link rel="import" href="script_ref.html">
 
 <polymer-element name="code-view">
   <template>
diff --git a/runtime/observatory/lib/src/elements/containers/virtual_collection.dart b/runtime/observatory/lib/src/elements/containers/virtual_collection.dart
new file mode 100644
index 0000000..36e682c
--- /dev/null
+++ b/runtime/observatory/lib/src/elements/containers/virtual_collection.dart
@@ -0,0 +1,158 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+import 'dart:html';
+import 'package:observatory/src/elements/helpers/rendering_scheduler.dart';
+import 'package:observatory/src/elements/helpers/tag.dart';
+
+typedef HtmlElement VirtualCollectionCreateCallback();
+typedef void VirtualCollectionUpdateCallback(HtmlElement el, dynamic item,
+    int index);
+
+class VirtualCollectionElement extends HtmlElement implements Renderable {
+  static const tag =
+      const Tag<VirtualCollectionElement>('virtual-collection');
+
+  RenderingScheduler<VirtualCollectionElement> _r;
+
+  Stream<RenderedEvent<VirtualCollectionElement>> get onRendered =>
+      _r.onRendered;
+
+  VirtualCollectionCreateCallback _create;
+  VirtualCollectionUpdateCallback _update;
+  double _itemHeight;
+  int _top;
+  int _height;
+  List _items;
+  StreamSubscription _onScrollSubscription;
+  StreamSubscription _onResizeSubscription;
+
+  List get items => _items;
+
+  set items(Iterable value) {
+    _items = new List.unmodifiable(value);
+    _r.dirty();
+  }
+
+
+  factory VirtualCollectionElement(VirtualCollectionCreateCallback create,
+      VirtualCollectionUpdateCallback update, {Iterable items: const [],
+      RenderingQueue queue}) {
+    assert(create != null);
+    assert(update != null);
+    assert(items != null);
+    VirtualCollectionElement e = document.createElement(tag.name);
+    e._r = new RenderingScheduler(e, queue: queue);
+    e._create = create;
+    e._update = update;
+    e._items = new List.unmodifiable(items);
+    return e;
+  }
+
+  VirtualCollectionElement.created() : super.created();
+
+  @override
+  attached() {
+    super.attached();
+    _r.enable();
+    _top = 0;
+    _height = getBoundingClientRect().height;
+    _itemHeight = _computeItemHeight();
+    _onScrollSubscription = onScroll.listen(_onScroll);
+    _onResizeSubscription = window.onResize.listen(_onResize);
+  }
+
+ @override
+  detached() {
+    super.detached();
+    _r.disable(notify: true);
+    children = const [];
+    _onScrollSubscription.cancel();
+    _onResizeSubscription.cancel();
+  }
+
+  final DivElement _scroller = new DivElement()..classes = const ['scroller'];
+  final DivElement _shifter = new DivElement()..classes = const ['shifter'];
+
+  dynamic getItemFromElement(HtmlElement element) {
+    final el_index = _shifter.children.indexOf(element);
+    if (el_index < 0) {
+      return null;
+    }
+    final item_index =
+      _top + el_index - (_shifter.children.length * _inverse_preload).floor();
+    if (0 <= item_index && item_index < items.length) {
+      return _items[item_index];
+    }
+    return null;
+  }
+
+  /// The preloaded element before and after the visible area are:
+  /// 1/preload_size of the number of items in the visble area.
+  /// See shared.css for the "top:-25%;".
+  static const int _preload = 2;
+  /// L = length of all the elements loaded
+  /// l = length of the visible area
+  ///
+  /// L = l + 2 * l / _preload
+  /// l = L * _preload / (_preload + 2)
+  ///
+  /// tail = l / _preload = L * 1 / (_preload + 2) = L * _inverse_preload
+  static const double _inverse_preload = 1 / (_preload + 2);
+
+  void render() {
+    _top = (scrollTop / _itemHeight).floor();
+
+    _scroller.style.height = '${_itemHeight*(_items.length)}px';
+    _shifter.style.top = '${_itemHeight*_top}px';
+    final tail_length = (_height / _itemHeight / _preload).ceil();
+    final length = tail_length * 2 + tail_length * _preload;
+
+    if (_shifter.children.length < length) {
+      while (_shifter.children.length != length) {
+        var e = _create();
+        e..style.display = 'hidden';
+        _shifter.children.add(e);
+      }
+      _shifter.style.height = '${_itemHeight*length}px';
+      children = [
+        _scroller
+          ..children = [_shifter]
+      ];
+    }
+
+    int i = _top - tail_length;
+    for (final HtmlElement e in _shifter.children) {
+      if (0 <= i && i < _items.length) {
+        e..style.display = null;
+        _update(e, _items[i], i);
+      } else {
+        e.style.display = 'hidden';
+      }
+      i++;
+    }
+  }
+
+  double _computeItemHeight() {
+    final c = children;
+    children = [_create()];
+    final height = children[0].getBoundingClientRect().height;
+    children = c;
+    return height;
+  }
+
+  void _onScroll(_) {
+    if(_r.isDirty) return;
+    if ((scrollTop - _top * _itemHeight).abs() >=
+         _shifter.children.length * _inverse_preload * _itemHeight) {
+      _r.dirty();
+    }
+  }
+
+  void _onResize(_) {
+    _height = getBoundingClientRect().height;
+    _r.dirty();
+  }
+}
diff --git a/runtime/observatory/lib/src/elements/containers/virtual_tree.dart b/runtime/observatory/lib/src/elements/containers/virtual_tree.dart
new file mode 100644
index 0000000..78ea96b
--- /dev/null
+++ b/runtime/observatory/lib/src/elements/containers/virtual_tree.dart
@@ -0,0 +1,149 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+import 'dart:html';
+import 'package:observatory/src/elements/containers/virtual_collection.dart';
+import 'package:observatory/src/elements/helpers/rendering_scheduler.dart';
+import 'package:observatory/src/elements/helpers/tag.dart';
+
+typedef HtmlElement VirtualTreeCreateCallback(
+    toggle({bool autoToggleSingleChildNodes, bool autoToggleWholeTree}));
+typedef void VirtualTreeUpdateCallback(HtmlElement el, dynamic item, int depth);
+typedef Iterable<dynamic> VritualTreeGetChildrenCallback(dynamic value);
+
+class VirtualTreeElement extends HtmlElement implements Renderable {
+  static const tag =
+      const Tag<VirtualTreeElement>('virtual-tree', dependencies: const [
+        VirtualCollectionElement.tag
+      ]);
+
+  RenderingScheduler<VirtualTreeElement> _r;
+
+  Stream<RenderedEvent<VirtualTreeElement>> get onRendered => _r.onRendered;
+
+  VritualTreeGetChildrenCallback _children;
+  List _items;
+  List _depths;
+  final Set _expanded = new Set();
+
+  List get items => _items;
+
+  set items(Iterable value) {
+    _items = new List.unmodifiable(value);
+    _expanded.clear();
+    _r.dirty();
+  }
+
+  factory VirtualTreeElement(VirtualTreeCreateCallback create,
+      VirtualTreeUpdateCallback update, VritualTreeGetChildrenCallback children,
+      {Iterable items: const [], RenderingQueue queue}) {
+    assert(create != null);
+    assert(update != null);
+    assert(children != null);
+    assert(items != null);
+    VirtualTreeElement e = document.createElement(tag.name);
+    e._r = new RenderingScheduler(e, queue: queue);
+    e._children = children;
+    e._collection = new VirtualCollectionElement(() {
+      var element;
+      return element = create(({bool autoToggleSingleChildNodes: false,
+          bool autoToggleWholeTree: false}) {
+        var item = e._collection.getItemFromElement(element);
+        if (e.isExpanded(item)) {
+          e.collapse(item, autoCollapseWholeTree: autoToggleWholeTree,
+              autoCollapseSingleChildNodes: autoToggleSingleChildNodes);
+        } else {
+          e.expand(item, autoExpandWholeTree: autoToggleWholeTree,
+              autoExpandSingleChildNodes: autoToggleSingleChildNodes);
+        }
+      });
+    }, (HtmlElement el, dynamic item, int index) {
+      update(el, item, e._depths[index]);
+    }, queue: queue);
+    e._items = new List.unmodifiable(items);
+    return e;
+  }
+
+  VirtualTreeElement.created() : super.created();
+
+  bool isExpanded(item) {
+    return _expanded.contains(item);
+  }
+
+  void expand(item, {bool autoExpandSingleChildNodes : false,
+      bool autoExpandWholeTree: false}) {
+    if (_expanded.add(item)) _r.dirty();
+    if (autoExpandWholeTree) {
+      for (final child in _children(item)) {
+        expand(child, autoExpandWholeTree: true);
+      }
+    } else if (autoExpandSingleChildNodes) {
+      var children = _children(item);
+      while (children.length == 1) {
+        _expanded.add(children.first);
+        children = _children(children.first);
+      }
+    }
+  }
+
+  void collapse(item, {bool autoCollapseSingleChildNodes : false,
+      bool autoCollapseWholeTree: false}) {
+    if (_expanded.remove(item)) _r.dirty();
+    if (autoCollapseWholeTree) {
+      for (final child in _children(item)) {
+        collapse(child, autoCollapseWholeTree: true);
+      }
+    } else if (autoCollapseSingleChildNodes) {
+      var children = _children(item);
+      while (children.length == 1) {
+        _expanded.remove(children.first);
+        children = _children(children.first);
+      }
+    }
+  }
+
+  @override
+  attached() {
+    super.attached();
+    _r.enable();
+  }
+
+ @override
+  detached() {
+    super.detached(); _r.disable(notify: true);
+    children = const [];
+  }
+
+  VirtualCollectionElement _collection;
+
+  void render() {
+    if (children.length == 0) {
+      children = [_collection];
+    }
+    Iterable _toList(item) {
+      if (isExpanded(item)) {
+        Iterable children = _children(item);
+        if (children.isNotEmpty) {
+          return [item]..addAll(children.expand(_toList));
+        }
+      }
+      return [item];
+    }
+    _collection.items = _items.expand(_toList);
+    var depth = 0;
+    Iterable _toDepth(item) {
+      if (isExpanded(item)) {
+        Iterable children = _children(item);
+        if (children.isNotEmpty) {
+          depth++;
+          return children.expand(_toDepth).toList()
+              ..insert(0, --depth);
+        }
+      }
+      return [depth];
+    }
+    _depths = _items.expand(_toDepth).toList();
+  }
+}
diff --git a/runtime/observatory/lib/src/elements/context_view.html b/runtime/observatory/lib/src/elements/context_view.html
index f9a2fbf..f75b548 100644
--- a/runtime/observatory/lib/src/elements/context_view.html
+++ b/runtime/observatory/lib/src/elements/context_view.html
@@ -1,7 +1,5 @@
 <link rel="import" href="../../../../packages/polymer/polymer.html">
-<link rel="import" href="class_ref.html">
 <link rel="import" href="field_ref.html">
-<link rel="import" href="function_ref.html">
 <link rel="import" href="instance_ref.html">
 <link rel="import" href="object_common.html">
 <link rel="import" href="context_ref.html">
diff --git a/runtime/observatory/lib/src/elements/cpu_profile.dart b/runtime/observatory/lib/src/elements/cpu_profile.dart
index 305706a..82f479d 100644
--- a/runtime/observatory/lib/src/elements/cpu_profile.dart
+++ b/runtime/observatory/lib/src/elements/cpu_profile.dart
@@ -7,6 +7,7 @@
 import 'dart:async';
 import 'dart:html';
 import 'observatory_element.dart';
+import 'package:observatory/models.dart' as M;
 import 'package:observatory/service.dart';
 import 'package:observatory/app.dart';
 import 'package:observatory/cpu_profile.dart';
@@ -347,7 +348,7 @@
     makeInfoBox();
     functionRow.children.add(infoBox);
 
-    if (node.profileFunction.function.kind.hasDartCode()) {
+    if (M.hasDartCode(node.profileFunction.function.kind)) {
       infoBox.children.add(div('Code for current node'));
       infoBox.children.add(br());
       var totalTicks = node.totalCodesTicks;
@@ -393,7 +394,7 @@
         'Call stack time' : node.profileFunction.formattedOnStackTime,
     });
 
-    if (node.profileFunction.function.kind.hasDartCode()) {
+    if (M.hasDartCode(node.profileFunction.function.kind)) {
       infoBox.children.add(div('Code containing function'));
       infoBox.children.add(br());
       var totalTicks = profile.sampleCount;
@@ -647,7 +648,7 @@
                           FunctionCallTreeNode node)
       : node = node,
         super(tree, depth) {
-    if ((node.profileFunction.function.kind == FunctionKind.kTag) &&
+    if ((node.profileFunction.function.kind == M.FunctionKind.tag) &&
         (node.profileFunction.normalizedExclusiveTicks == 0) &&
         (node.profileFunction.normalizedInclusiveTicks == 0)) {
     selfPercent = '';
@@ -735,7 +736,7 @@
                       CodeCallTreeNode node)
       : node = node,
         super(tree, depth) {
-    if ((node.profileCode.code.kind == CodeKind.Tag) &&
+    if ((node.profileCode.code.kind == M.CodeKind.tag) &&
         (node.profileCode.normalizedExclusiveTicks == 0) &&
         (node.profileCode.normalizedInclusiveTicks == 0)) {
       selfPercent = '';
diff --git a/runtime/observatory/lib/src/elements/cpu_profile.html b/runtime/observatory/lib/src/elements/cpu_profile.html
index 05fc581..32363c7 100644
--- a/runtime/observatory/lib/src/elements/cpu_profile.html
+++ b/runtime/observatory/lib/src/elements/cpu_profile.html
@@ -1,6 +1,4 @@
 <link rel="import" href="../../../../packages/polymer/polymer.html">
-<link rel="import" href="code_ref.html">
-<link rel="import" href="function_ref.html">
 
 <polymer-element name="sample-buffer-control">
   <template>
diff --git a/runtime/observatory/lib/src/elements/css/shared.css b/runtime/observatory/lib/src/elements/css/shared.css
index 1f32ad4..bd15c93 100644
--- a/runtime/observatory/lib/src/elements/css/shared.css
+++ b/runtime/observatory/lib/src/elements/css/shared.css
@@ -364,8 +364,101 @@
   -webkit-animation: shake 0.5s;
 }
 
+/* class-ref */
+/* TODO(cbernaschina) fix class-ref-wrapped to class-ref when wrapper
+removed */
+
+class-ref-wrapped > a[href]:hover {
+    text-decoration: underline;
+}
+class-ref-wrapped > a[href] {
+    color: #0489c3;
+    text-decoration: none;
+}
+
+/* code-ref */
+/* TODO(cbernaschina) fix code-ref-wrapped to code-ref when wrapper
+removed */
+
+code-ref-wrapped > a[href]:hover {
+  text-decoration: underline;
+}
+code-ref-wrapped > a[href] {
+  color: #0489c3;
+  text-decoration: none;
+}
+
+/* error-ref */
+/* TODO(cbernaschina) fix error-ref-wrapped to error-ref when wrapper
+removed */
+
+error-ref-wrapped > pre {
+  background-color: #f5f5f5;
+  border: 1px solid #ccc;
+  padding: 10px;
+  font-family: consolas, courier, monospace;
+  font-size: 1em;
+  line-height: 1.2em;
+  white-space: pre;
+}
+
+/* flag-list */
+
+flag-list .comment {
+  color: #aaa;
+}
+
+flag-list .flag {
+  padding: 3px 0;
+}
+
+flag-list .name {
+  font-weight: bold;
+  margin-right: 0.7em;
+}
+
+flag-list .value {
+  margin-left: 0.7em;
+}
+
+/* function-ref */
+/* TODO(cbernaschina) fix function-ref-wrapped to function-ref when wrapper
+removed */
+
+function-ref-wrapped > a[href]:hover {
+  text-decoration: underline;
+}
+function-ref-wrapped > a[href] {
+  color: #0489c3;
+  text-decoration: none;
+}
+
+/* isolate-ref */
+/* TODO(cbernaschina) fix isolate-ref-wrapped to isolate-ref when wrapper
+removed */
+
+isolate-ref-wrapped > a[href]:hover {
+  text-decoration: underline;
+}
+isolate-ref-wrapped > a[href] {
+  color: #0489c3;
+  text-decoration: none;
+}
+
+/* library-ref */
+/* TODO(cbernaschina) fix library-ref-wrapped to library-ref when wrapper
+removed */
+
+library-ref-wrapped > a[href]:hover {
+  text-decoration: underline;
+}
+library-ref-wrapped > a[href] {
+  color: #0489c3;
+  text-decoration: none;
+}
+
 /* nav-notify */
-/* TODO(cbernaschina) fix nav-notify-ref-wrapped to nav-notify-ref when wrapper
+/* TODO(cbernaschina) fix nav-notify-wrapped to nav-notify when wrapper
 removed */
 nav-notify-wrapped > div {
   float: right;
@@ -460,6 +553,34 @@
   margin: 0;
 }
 
+/* script-ref */
+/* TODO(cbernaschina) fix script-ref-wrapped to script-ref when wrapper
+removed */
+
+script-ref-wrapped > a[href]:hover {
+    text-decoration: underline;
+}
+
+script-ref-wrapped > a[href] {
+    color: #0489c3;
+    text-decoration: none;
+}
+
+/* source-link */
+/* TODO(cbernaschina) fix source-link-wrapped to source-link when wrapper
+removed */
+
+source-link-wrapped > a[href]:hover {
+    text-decoration: underline;
+}
+
+source-link-wrapped > a[href] {
+    color: #0489c3;
+    text-decoration: none;
+}
+
+
+
 /* view-footer */
 
 view-footer {
@@ -477,6 +598,34 @@
   display: block;
 }
 
+/* virtual-collection */
+
+virtual-collection {
+  display: block;
+  overflow-y: scroll;
+  width: 100%;
+  height: 100%;
+}
+
+virtual-collection .scroller {
+  position: relative;
+  overflow: hidden;
+  background: transparent;
+}
+
+virtual-collection .shifter {
+  background: transparent;
+  position: absolute;
+  top: 0;
+  left: 0;
+  right: 0;
+}
+
+virtual-collection .shifter > * {
+  position: relative;
+  top: -25%;
+}
+
 /* vm-connect-target */
 
 vm-connect-target > button.delete-button {
diff --git a/runtime/observatory/lib/src/elements/debugger.html b/runtime/observatory/lib/src/elements/debugger.html
index 54fee31..42fb892 100644
--- a/runtime/observatory/lib/src/elements/debugger.html
+++ b/runtime/observatory/lib/src/elements/debugger.html
@@ -1,8 +1,6 @@
 <link rel="import" href="../../../../packages/polymer/polymer.html">
-<link rel="import" href="function_ref.html">
 <link rel="import" href="eval_link.html">
 <link rel="import" href="script_inset.html">
-<link rel="import" href="script_ref.html">
 
 <!-- TODO(turnidge): Use core-icon once core_elements work properly in
      devtools -->
diff --git a/runtime/observatory/lib/src/elements/error_ref.dart b/runtime/observatory/lib/src/elements/error_ref.dart
index d69726b..b30dd90 100644
--- a/runtime/observatory/lib/src/elements/error_ref.dart
+++ b/runtime/observatory/lib/src/elements/error_ref.dart
@@ -1,13 +1,52 @@
-// Copyright (c) 2014, the Dart project authors.  Please see the AUTHORS file
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
 library error_ref_element;
 
-import 'package:polymer/polymer.dart';
-import 'service_ref.dart';
+import 'dart:html';
+import 'dart:async';
+import 'package:observatory/models.dart'
+  show ErrorRef;
+import 'package:observatory/src/elements/helpers/tag.dart';
+import 'package:observatory/src/elements/helpers/rendering_scheduler.dart';
 
-@CustomTag('error-ref')
-class ErrorRefElement extends ServiceRefElement {
+class ErrorRefElement extends HtmlElement implements Renderable {
+  static const tag = const Tag<ErrorRefElement>('error-ref-wrapped');
+
+  RenderingScheduler<ErrorRefElement> _r;
+
+  Stream<RenderedEvent<ErrorRefElement>> get onRendered => _r.onRendered;
+
+  ErrorRef _error;
+  ErrorRef get error => _error;
+
+  factory ErrorRefElement(ErrorRef error, {RenderingQueue queue}) {
+    assert(error != null);
+    ErrorRefElement e = document.createElement(tag.name);
+    e._r = new RenderingScheduler<ErrorRefElement>(e, queue: queue);
+    e._error = error;
+    return e;
+  }
+
   ErrorRefElement.created() : super.created();
+
+  @override
+  void attached() {
+    super.attached();
+    _r.enable();
+  }
+
+  @override
+  void detached() {
+    super.detached();
+    children = [];
+    _r.disable(notify: true);
+  }
+
+  void render() {
+    children = [
+      new PreElement()..text = error.message
+    ];
+  }
 }
diff --git a/runtime/observatory/lib/src/elements/error_ref.html b/runtime/observatory/lib/src/elements/error_ref.html
deleted file mode 100644
index a132039..0000000
--- a/runtime/observatory/lib/src/elements/error_ref.html
+++ /dev/null
@@ -1,25 +0,0 @@
-<link rel="import" href="../../../../packages/polymer/polymer.html">
-
-<link rel="import" href="service_ref.html">
-
-<polymer-element name="error-ref">
-  <template>
-    <link rel="stylesheet" href="css/shared.css">
-    <style>
-      .errorBox {
-        background-color: #f5f5f5;
-        border: 1px solid #ccc;
-        padding: 10px;
-        font-family: consolas, courier, monospace;
-        font-size: 1em;
-        line-height: 1.2em;
-        white-space: pre;
-      }
-    </style>
-    <span>
-      <pre class="errorBox">{{ ref.message }}</pre>
-    </span>
-  </template>
-</polymer-element>
-
-<script type="application/dart" src="error_ref.dart"></script>
diff --git a/runtime/observatory/lib/src/elements/error_ref_wrapper.dart b/runtime/observatory/lib/src/elements/error_ref_wrapper.dart
new file mode 100644
index 0000000..4efe939
--- /dev/null
+++ b/runtime/observatory/lib/src/elements/error_ref_wrapper.dart
@@ -0,0 +1,78 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:html';
+
+import 'package:observatory/app.dart';
+import 'package:observatory/mocks.dart' show ErrorRefMock;
+import 'package:observatory/service_html.dart' show ServiceMap, DartError;
+import 'package:observatory/src/elements/error_ref.dart';
+import 'package:observatory/src/elements/helpers/tag.dart';
+import 'package:observatory/src/elements/shims/binding.dart';
+
+class ErrorRefElementWrapper extends HtmlElement {
+
+  static const binder = const Binder<ErrorRefElementWrapper>(const {
+      'ref': #ref
+    });
+
+  static const tag = const Tag<ErrorRefElementWrapper>('error-ref');
+
+  ServiceMap _error;
+  ServiceMap get ref => _error;
+  void set ref(ServiceMap ref) { _error = ref; render(); }
+
+  ErrorRefElementWrapper.created() : super.created() {
+    binder.registerCallback(this);
+    createShadowRoot();
+    render();
+  }
+
+  @override
+  void attached() {
+    super.attached();
+    render();
+  }
+
+  void render() {
+    shadowRoot.children = [];
+    if (_error == null) return;
+
+    if (ref is Map) {
+      shadowRoot.children = [
+        new StyleElement()
+          ..text = '''
+          error-ref-wrapped > pre {
+            background-color: #f5f5f5;
+            border: 1px solid #ccc;
+            padding: 10px;
+            font-family: consolas, courier, monospace;
+            font-size: 1em;
+            line-height: 1.2em;
+            white-space: pre;
+          }
+          ''',
+        new ErrorRefElement(new ErrorRefMock(message: ref['message']))
+      ];
+    } else {
+      shadowRoot.children = [
+        new StyleElement()
+          ..text = '''
+          error-ref-wrapped > pre {
+            background-color: #f5f5f5;
+            border: 1px solid #ccc;
+            padding: 10px;
+            font-family: consolas, courier, monospace;
+            font-size: 1em;
+            line-height: 1.2em;
+            white-space: pre;
+          }
+          ''',
+        new ErrorRefElement(
+                        new ErrorRefMock(message: (ref as DartError).message),
+                        queue: ObservatoryApplication.app.queue)
+      ];
+    }
+  }
+}
diff --git a/runtime/observatory/lib/src/elements/eval_box.html b/runtime/observatory/lib/src/elements/eval_box.html
index eb1e639..96a3f53 100644
--- a/runtime/observatory/lib/src/elements/eval_box.html
+++ b/runtime/observatory/lib/src/elements/eval_box.html
@@ -1,6 +1,5 @@
 <link rel="import" href="../../../../packages/polymer/polymer.html">
 <link rel="import" href="instance_ref.html">
-<link rel="import" href="error_ref.html">
 
 
 <polymer-element name="eval-box">
diff --git a/runtime/observatory/lib/src/elements/eval_link.html b/runtime/observatory/lib/src/elements/eval_link.html
index 38d2981..a55b50b 100644
--- a/runtime/observatory/lib/src/elements/eval_link.html
+++ b/runtime/observatory/lib/src/elements/eval_link.html
@@ -1,6 +1,5 @@
 <link rel="import" href="../../../../packages/polymer/polymer.html">
 <link rel="import" href="instance_ref.html">
-<link rel="import" href="error_ref.html">
 
 
 <polymer-element name="eval-link">
diff --git a/runtime/observatory/lib/src/elements/field_view.html b/runtime/observatory/lib/src/elements/field_view.html
index 4df7b24..8b78538 100644
--- a/runtime/observatory/lib/src/elements/field_view.html
+++ b/runtime/observatory/lib/src/elements/field_view.html
@@ -1,8 +1,5 @@
 <link rel="import" href="../../../../packages/polymer/polymer.html">
-<link rel="import" href="class_ref.html">
 <link rel="import" href="instance_ref.html">
-<link rel="import" href="library_ref.html">
-<link rel="import" href="script_ref.html">
 
 <polymer-element name="field-view">
   <template>
diff --git a/runtime/observatory/lib/src/elements/flag_list.dart b/runtime/observatory/lib/src/elements/flag_list.dart
index f2d1cfc..19d7816 100644
--- a/runtime/observatory/lib/src/elements/flag_list.dart
+++ b/runtime/observatory/lib/src/elements/flag_list.dart
@@ -4,35 +4,148 @@
 
 library flag_list_element;
 
+import 'dart:html';
 import 'dart:async';
-import 'package:polymer/polymer.dart';
-import 'observatory_element.dart';
-import 'package:observatory/service.dart';
+import 'package:observatory/models.dart' as M;
+import 'package:observatory/src/elements/helpers/rendering_scheduler.dart';
+import 'package:observatory/src/elements/helpers/tag.dart';
+import 'package:observatory/src/elements/helpers/uris.dart';
+import 'package:observatory/src/elements/nav/bar.dart';
+import 'package:observatory/src/elements/nav/menu.dart';
+import 'package:observatory/src/elements/nav/notify.dart';
+import 'package:observatory/src/elements/nav/refresh.dart';
+import 'package:observatory/src/elements/nav/top_menu.dart';
+import 'package:observatory/src/elements/nav/vm_menu.dart';
+import 'package:observatory/src/elements/view_footer.dart';
 
-@CustomTag('flag-list')
-class FlagListElement extends ObservatoryElement {
-  @published ServiceMap flagList;
+class FlagListElement extends HtmlElement implements Renderable {
+  static const tag = const Tag<FlagListElement>('flag-list',
+                     dependencies: const [NavBarElement.tag,
+                                          NavMenuElement.tag,
+                                          NavNotifyElement.tag,
+                                          NavRefreshElement.tag,
+                                          NavTopMenuElement.tag,
+                                          NavVMMenuElement.tag,
+                                          ViewFooterElement.tag,]);
 
-  void flagListChanged(oldValue) {
-    modifiedFlags =
-        flagList['flags'].where((flag) => flag['modified']).toList();
-    unmodifiedFlags =
-        flagList['flags'].where((flag) => !flag['modified']).toList();
+  RenderingScheduler _r;
+
+  Stream<RenderedEvent<FlagListElement>> get onRendered => _r.onRendered;
+
+  M.VMRef _vm;
+  Stream<M.VMUpdateEvent> _vmUpdates;
+  M.FlagsRepository _repository;
+  M.NotificationRepository _notifications;
+  Iterable<M.Flag> _flags;
+
+  M.VMRef get vm => _vm;
+
+  factory FlagListElement(M.VMRef vm,
+                          Stream<M.VMUpdateEvent> vmUpdates,
+                          M.FlagsRepository repository,
+                          M.NotificationRepository notifications,
+                          {RenderingQueue queue}) {
+    assert(vm != null);
+    assert(vmUpdates != null);
+    assert(repository != null);
+    assert(notifications != null);
+    FlagListElement e = document.createElement(tag.name);
+    e._r = new RenderingScheduler(e, queue: queue);
+    e._vm = vm;
+    e._vmUpdates = vmUpdates;
+    e._repository = repository;
+    e._notifications = notifications;
+    return e;
   }
 
-  @observable List<ServiceMap> modifiedFlags = new List<ServiceMap>();
-  @observable List<ServiceMap> unmodifiedFlags = new List<ServiceMap>();
-
   FlagListElement.created() : super.created();
 
-  Future refresh() {
-    return flagList.reload();
+  @override
+  void attached() {
+    super.attached();
+    _r.enable();
+    _refresh();
   }
-}
 
-@CustomTag('flag-item')
-class FlagItemElement extends ObservatoryElement {
-  @published ObservableMap flag;
+  @override
+  void detached() {
+    super.detached();
+    children = [];
+    _r.disable(notify: true);
+  }
 
-  FlagItemElement.created() : super.created();
+  void render() {
+    final content = <Element>[];
+    if (_flags == null) {
+      content.add(new HeadingElement.h1()..text = 'Loading Flags...');
+    } else {
+      final modified = _flags.where(_isModified);
+      final unmodified = _flags.where(_isUnmodified);
+
+      if (modified.isNotEmpty) {
+        content.add(new HeadingElement.h1()..text = 'Modified Flags');
+        content.add(new BRElement());
+        content.addAll(modified.expand(_renderFlag));
+        content.add(new HRElement());
+      }
+
+      content.add(new HeadingElement.h1()..text = 'Unmodified Flags');
+      content.add(new BRElement());
+
+      if (unmodified.isEmpty) {
+        content.add(new HeadingElement.h2()..text = 'None');
+      } else {
+        content.addAll(unmodified.expand(_renderFlag));
+      }
+    }
+
+    children = [
+      new NavBarElement(queue: _r.queue)
+        ..children = [
+          new NavTopMenuElement(queue: _r.queue),
+          new NavVMMenuElement(_vm, _vmUpdates, queue: _r.queue),
+          new NavMenuElement('flags', link: Uris.flags(), last: true,
+                             queue: _r.queue),
+          new NavRefreshElement(queue: _r.queue)
+            ..onRefresh.listen((e) async {
+              e.element.disabled = true;
+              try {
+                await _refresh();
+              } finally {
+                e.element.disabled = false;
+              }
+            }),
+          new NavNotifyElement(_notifications, queue: _r.queue)
+        ],
+      new DivElement()
+        ..classes = ['content-centered']
+        ..children = content,
+      new ViewFooterElement(queue: _r.queue)
+    ];
+  }
+
+  Future _refresh() async {
+    _flags = await _repository.list(_vm);
+    _r.dirty();
+  }
+
+  static bool _isModified(M.Flag flag) => flag.modified;
+  static bool _isUnmodified(M.Flag flag) => !flag.modified;
+
+  static List<Element> _renderFlag(M.Flag flag) {
+    return [
+      new SpanElement()..classes = const ['comment']
+        ..text = '// ${flag.comment}',
+      new DivElement()..classes = flag.modified ? const ['flag', 'modified']
+                                                : const ['flag', 'unmodified']
+        ..children = [
+          new SpanElement()..classes = const ['name']
+            ..text = flag.name,
+          new SpanElement()..text = '=',
+          new SpanElement()..classes = const ['value']
+            ..text = flag.valueAsString ?? 'NULL'
+        ],
+      new BRElement(),
+    ];
+  }
 }
diff --git a/runtime/observatory/lib/src/elements/flag_list.html b/runtime/observatory/lib/src/elements/flag_list.html
deleted file mode 100644
index 2c21db0..0000000
--- a/runtime/observatory/lib/src/elements/flag_list.html
+++ /dev/null
@@ -1,53 +0,0 @@
-<link rel="import" href="../../../../packages/polymer/polymer.html">
-
-<polymer-element name="flag-list">
-  <template>
-    <link rel="stylesheet" href="css/shared.css">
-    <nav-bar>
-      <top-nav-menu></top-nav-menu>
-      <vm-nav-menu vm="{{ app.vm }}"></vm-nav-menu>
-      <nav-menu link="{{ makeLink('/flags') }}" anchor="flags" last="{{ true }}"></nav-menu>
-      <nav-refresh callback="{{ refresh }}"></nav-refresh>
-      <nav-notify notifications="{{ app.notifications }}"></nav-notify>
-    </nav-bar>
-
-    <div class="content-centered">
-      <template if="{{ modifiedFlags.isNotEmpty }}">
-        <h1>Modified Flags</h1>
-        <br>
-        <template repeat="{{ flag in modifiedFlags }}">
-          <flag-item flag="{{ flag }}"></flag-item>
-          <br>
-        </template>
-        <hr>
-      </template>
-
-      <h1>Unmodified Flags</h1>
-      <br>
-      <template if="{{ unmodifiedFlags.isEmpty }}">
-        <em>None</em>
-      </template>
-      <template if="{{ unmodifiedFlags.isNotEmpty }}">
-        <template repeat="{{ flag in unmodifiedFlags }}">
-          <flag-item flag="{{ flag }}"></flag-item>
-          <br>
-        </template>
-      </template>
-    </div>
-    <view-footer></view-footer>
-  </template>
-</polymer-element>
-
-<polymer-element name="flag-item">
-  <template>
-    <link rel="stylesheet" href="css/shared.css">
-    <span style="color:#aaa">// {{ flag['comment'] }}</span>
-    <div style="padding: 3px 0">
-      <b>{{ flag['name'] }}</b>
-      &nbsp;=&nbsp;
-      {{ flag['valueAsString'] }}
-    </div>
-  </template>
-</polymer-element>
-
-<script type="application/dart" src="flag_list.dart"></script>
diff --git a/runtime/observatory/lib/src/elements/function_ref.dart b/runtime/observatory/lib/src/elements/function_ref.dart
index d91a512..f6b2ec3 100644
--- a/runtime/observatory/lib/src/elements/function_ref.dart
+++ b/runtime/observatory/lib/src/elements/function_ref.dart
@@ -5,45 +5,82 @@
 library function_ref_element;
 
 import 'dart:html';
-import 'package:polymer/polymer.dart';
-import 'package:observatory/service.dart';
-import 'service_ref.dart';
+import 'dart:async';
+import 'package:observatory/models.dart' as M
+  show IsolateRef, FunctionRef, isSyntheticFunction, ClassRef, ObjectRef;
+import 'package:observatory/src/elements/class_ref.dart';
+import 'package:observatory/src/elements/helpers/rendering_scheduler.dart';
+import 'package:observatory/src/elements/helpers/tag.dart';
+import 'package:observatory/src/elements/helpers/uris.dart';
 
-@CustomTag('function-ref')
-class FunctionRefElement extends ServiceRefElement {
-  @published bool qualified = true;
+class FunctionRefElement extends HtmlElement implements Renderable {
+  static const tag = const Tag<FunctionRefElement>('function-ref-wrapped');
+
+  RenderingScheduler<FunctionRefElement> _r;
+
+  Stream<RenderedEvent<FunctionRefElement>> get onRendered => _r.onRendered;
+
+  M.IsolateRef _isolate;
+  M.FunctionRef _function;
+  bool _qualified;
+
+  M.IsolateRef get isolate => _isolate;
+  M.FunctionRef get function => _function;
+  bool get qualified => _qualified;
+
+  factory FunctionRefElement(M.IsolateRef isolate, M.FunctionRef function,
+      {bool qualified: true, RenderingQueue queue}) {
+    assert(isolate != null);
+    assert(function != null);
+    assert(qualified != null);
+    FunctionRefElement e = document.createElement(tag.name);
+    e._r = new RenderingScheduler(e, queue: queue);
+    e._isolate = isolate;
+    e._function = function;
+    e._qualified = qualified;
+    return e;
+  }
 
   FunctionRefElement.created() : super.created();
 
-  refChanged(oldValue) {
-    super.refChanged(oldValue);
-    _updateShadowDom();
+  @override
+  void attached() {
+    super.attached();
+    _r.enable();
   }
 
-  ServiceFunction get function => ref;
-  void _updateShadowDom() {
-    clearShadowRoot();
-    if (ref == null) {
-      return;
-    }
-    if (!function.kind.isDart()) {
-      insertTextSpanIntoShadowRoot(name);
-      return;
-    }
+  @override
+  void detached() {
+    super.detached();
+    _r.disable(notify: true);
+    children = [];
+  }
+
+  void render() {
+    var content = <Element>[
+      new AnchorElement(href: M.isSyntheticFunction(function.kind) ? null
+        : Uris.inspect(_isolate, object: _function))
+        ..text = _function.name
+    ];
     if (qualified) {
-      if (function.dartOwner is ServiceFunction) {
-        var functionRef = new Element.tag('function-ref');
-        functionRef.ref = function.dartOwner;
-        functionRef.qualified = true;
-        shadowRoot.children.add(functionRef);
-        insertTextSpanIntoShadowRoot('.');
-      } else if (function.dartOwner is Class) {
-        var classRef = new Element.tag('class-ref');
-        classRef.ref = function.dartOwner;
-        shadowRoot.children.add(classRef);
-        insertTextSpanIntoShadowRoot('.');
+      M.ObjectRef owner = _function.dartOwner;
+      while (owner is M.FunctionRef) {
+        M.FunctionRef function = (owner as M.FunctionRef);
+        content.addAll([
+          new SpanElement()..text = '.',
+          new AnchorElement(href: M.isSyntheticFunction(function.kind) ? null
+            : Uris.inspect(_isolate, object: function))
+            ..text = function.name
+        ]);
+        owner = function.dartOwner;
+      }
+      if (owner is M.ClassRef) {
+        content.addAll([
+          new SpanElement()..text = '.',
+          new ClassRefElement(_isolate, owner, queue: _r.queue)
+        ]);
       }
     }
-    insertLinkIntoShadowRoot(name, url, hoverText);
+    children = content.reversed.toList(growable: false);
   }
 }
diff --git a/runtime/observatory/lib/src/elements/function_ref.html b/runtime/observatory/lib/src/elements/function_ref.html
deleted file mode 100644
index 4669386..0000000
--- a/runtime/observatory/lib/src/elements/function_ref.html
+++ /dev/null
@@ -1,9 +0,0 @@
-<link rel="import" href="../../../../packages/polymer/polymer.html">
-<link rel="import" href="class_ref.html">
-<link rel="import" href="service_ref.html">
-
-<polymer-element name="function-ref">
-  <template><link rel="stylesheet" href="css/shared.css"></template>
-</polymer-element>
-
-<script type="application/dart" src="function_ref.dart"></script>
\ No newline at end of file
diff --git a/runtime/observatory/lib/src/elements/function_ref_wrapper.dart b/runtime/observatory/lib/src/elements/function_ref_wrapper.dart
new file mode 100644
index 0000000..e41e43a
--- /dev/null
+++ b/runtime/observatory/lib/src/elements/function_ref_wrapper.dart
@@ -0,0 +1,61 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:html';
+
+import 'package:observatory/app.dart';
+import 'package:observatory/service.dart' show ServiceFunction;
+import 'package:observatory/src/elements/function_ref.dart';
+import 'package:observatory/src/elements/helpers/tag.dart';
+import 'package:observatory/src/elements/shims/binding.dart';
+
+@bindable
+class FunctionRefElementWrapper extends HtmlElement {
+
+  static const binder = const Binder<FunctionRefElementWrapper>(const {
+      'ref': #ref, 'qualified': #qualified
+    });
+
+  static const tag = const Tag<FunctionRefElementWrapper>('function-ref');
+
+  bool _qualified = true;
+  ServiceFunction _function;
+  bool get qualified => _qualified;
+  ServiceFunction get ref => _function;
+  void set qualified(bool qualified) { _qualified = qualified; render(); }
+  void set ref(ServiceFunction ref) { _function = ref; render(); }
+
+  FunctionRefElementWrapper.created() : super.created() {
+    binder.registerCallback(this);
+    createShadowRoot();
+    render();
+  }
+
+  @override
+  void attached() {
+    super.attached();
+    render();
+  }
+
+  void render() {
+    shadowRoot.children = [];
+    if (ref == null) return;
+
+    shadowRoot.children = [
+      new StyleElement()
+        ..text = '''
+        class-ref-wrapped > a[href]:hover,
+        function-ref-wrapped > a[href]:hover {
+            text-decoration: underline;
+        }
+        class-ref-wrapped > a[href],
+        function-ref-wrapped > a[href] {
+            color: #0489c3;
+            text-decoration: none;
+        }''',
+      new FunctionRefElement(_function.isolate, _function, qualified: qualified,
+        queue: ObservatoryApplication.app.queue)
+    ];
+  }
+}
diff --git a/runtime/observatory/lib/src/elements/function_view.html b/runtime/observatory/lib/src/elements/function_view.html
index 70accd2..a196455 100644
--- a/runtime/observatory/lib/src/elements/function_view.html
+++ b/runtime/observatory/lib/src/elements/function_view.html
@@ -1,10 +1,5 @@
 <link rel="import" href="../../../../packages/polymer/polymer.html">
-<link rel="import" href="class_ref.html">
-<link rel="import" href="code_ref.html">
-<link rel="import" href="function_ref.html">
-<link rel="import" href="library_ref.html">
 <link rel="import" href="script_inset.html">
-<link rel="import" href="script_ref.html">
 
 <polymer-element name="function-view">
   <template>
diff --git a/runtime/observatory/lib/src/elements/general_error.dart b/runtime/observatory/lib/src/elements/general_error.dart
index d47ec04..943ba3c 100644
--- a/runtime/observatory/lib/src/elements/general_error.dart
+++ b/runtime/observatory/lib/src/elements/general_error.dart
@@ -1,16 +1,76 @@
-// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
 library general_error_element;
 
-import 'observatory_element.dart';
-import 'package:polymer/polymer.dart';
+import 'dart:html';
+import 'dart:async';
+import 'package:observatory/models.dart' as M;
+import 'package:observatory/src/elements/helpers/tag.dart';
+import 'package:observatory/src/elements/helpers/rendering_scheduler.dart';
+import 'package:observatory/src/elements/nav/bar.dart';
+import 'package:observatory/src/elements/nav/notify.dart';
+import 'package:observatory/src/elements/nav/top_menu.dart';
 
-/// Displays an error message
-@CustomTag('general-error')
-class GeneralErrorElement extends ObservatoryElement {
-  @published String message;
+class GeneralErrorElement extends HtmlElement implements Renderable {
+  static const tag = const Tag<GeneralErrorElement>('general-error',
+                     dependencies: const [NavBarElement.tag,
+                                          NavTopMenuElement.tag,
+                                          NavNotifyElement.tag]);
+
+  RenderingScheduler _r;
+
+  Stream<RenderedEvent<GeneralErrorElement>> get onRendered => _r.onRendered;
+
+  M.NotificationRepository _notifications;
+  String _message;
+
+  String get message => _message;
+
+  set message(String value) => _message = _r.checkAndReact(_message, value);
+
+
+  factory GeneralErrorElement(M.NotificationRepository notifications,
+                           {String message: '', RenderingQueue queue}) {
+    assert(notifications != null);
+    assert(message != null);
+    GeneralErrorElement e = document.createElement(tag.name);
+    e._r = new RenderingScheduler(e, queue: queue);
+    e._message = message;
+    e._notifications = notifications;
+    return e;
+  }
 
   GeneralErrorElement.created() : super.created();
+
+  @override
+  void attached() {
+    super.attached();
+    _r.enable();
+  }
+
+  @override
+  void detached() {
+    super.detached();
+    children = [];
+    _r.disable(notify: true);
+  }
+
+  void render() {
+    children = [
+      new NavBarElement(queue: _r.queue)
+        ..children = [
+          new NavTopMenuElement(last: true, queue: _r.queue),
+          new NavNotifyElement(_notifications, queue: _r.queue)
+        ],
+      new DivElement()..classes = ['content-centered']
+        ..children = [
+          new HeadingElement.h1()..text = 'Error',
+          new BRElement(),
+          new DivElement()..classes = ['well']
+            ..text = message
+        ]
+    ];
+  }
 }
diff --git a/runtime/observatory/lib/src/elements/general_error.html b/runtime/observatory/lib/src/elements/general_error.html
deleted file mode 100644
index ef809d1..0000000
--- a/runtime/observatory/lib/src/elements/general_error.html
+++ /dev/null
@@ -1,18 +0,0 @@
-<link rel="import" href="../../../../packages/polymer/polymer.html">
-
-<polymer-element name="general-error">
-  <template>
-    <link rel="stylesheet" href="css/shared.css">
-    <nav-bar>
-      <top-nav-menu last="{{ true }}"></top-nav-menu>
-      <nav-notify notifications="{{ app.notifications }}"></nav-notify>
-    </nav-bar>
-    <div class="content-centered">
-      <h1>Error</h1>
-      <br>
-      <div class="well">{{ message }}</div>
-    </div>
-  </template>
-</polymer-element>
-
-<script type="application/dart" src="general_error.dart"></script>
diff --git a/runtime/observatory/lib/src/elements/heap_map.html b/runtime/observatory/lib/src/elements/heap_map.html
index 82aad68..d68aed2 100644
--- a/runtime/observatory/lib/src/elements/heap_map.html
+++ b/runtime/observatory/lib/src/elements/heap_map.html
@@ -1,5 +1,4 @@
 <link rel="import" href="../../../../packages/polymer/polymer.html">
-<link rel="import" href="class_ref.html">
 
 <polymer-element name="heap-map">
 <template>
diff --git a/runtime/observatory/lib/src/elements/heap_profile.dart b/runtime/observatory/lib/src/elements/heap_profile.dart
index 9e5b142..3e0116e 100644
--- a/runtime/observatory/lib/src/elements/heap_profile.dart
+++ b/runtime/observatory/lib/src/elements/heap_profile.dart
@@ -6,6 +6,7 @@
 
 import 'dart:async';
 import 'dart:html';
+import 'class_ref_wrapper.dart';
 import 'observatory_element.dart';
 import 'package:charted/charted.dart';
 import 'package:observatory/app.dart';
@@ -252,7 +253,7 @@
 
     var row = classTable.rows[rowIndex];
     // Add class ref.
-    ClassRefElement classRef = tr.children[0].children[0];
+    ClassRefElementWrapper classRef = tr.children[0].children[0];
     classRef.ref = row.values[0];
 
     for (var i = 1; i < row.values.length; i++) {
diff --git a/runtime/observatory/lib/src/elements/heap_profile.html b/runtime/observatory/lib/src/elements/heap_profile.html
index 47ac16b..ece5446 100644
--- a/runtime/observatory/lib/src/elements/heap_profile.html
+++ b/runtime/observatory/lib/src/elements/heap_profile.html
@@ -1,5 +1,4 @@
 <link rel="import" href="../../../../packages/polymer/polymer.html">
-<link rel="import" href="class_ref.html">
 
 <polymer-element name="heap-profile">
 <template>
diff --git a/runtime/observatory/lib/src/elements/heap_snapshot.dart b/runtime/observatory/lib/src/elements/heap_snapshot.dart
index 4894e9f..fbfb9eb 100644
--- a/runtime/observatory/lib/src/elements/heap_snapshot.dart
+++ b/runtime/observatory/lib/src/elements/heap_snapshot.dart
@@ -6,6 +6,7 @@
 
 import 'dart:async';
 import 'dart:html';
+import 'class_ref_wrapper.dart';
 import 'observatory_element.dart';
 import 'package:observatory/app.dart';
 import 'package:observatory/service.dart';
@@ -162,7 +163,7 @@
     gap.style.display = 'inline-block';
     firstColumn.children.add(gap);
 
-    ClassRefElement classRef = new Element.tag("class-ref");
+    ClassRefElementWrapper classRef = new Element.tag("class-ref");
     classRef.ref = isolate.getClassByCid(vertex.cid);
     classRef.style.alignSelf = 'center';
     firstColumn.children.add(classRef);
@@ -296,7 +297,7 @@
       rootName.text = '<root>';
       firstColumn.children.add(rootName);
     } else {
-      ClassRefElement classRef = new Element.tag("class-ref");
+      ClassRefElementWrapper classRef = new Element.tag("class-ref");
       classRef.ref = isolate.getClassByCid(v.cid);
       classRef.style.alignSelf = 'center';
       firstColumn.children.add(classRef);
diff --git a/runtime/observatory/lib/src/elements/heap_snapshot.html b/runtime/observatory/lib/src/elements/heap_snapshot.html
index f7a8bf5..46e73d5 100644
--- a/runtime/observatory/lib/src/elements/heap_snapshot.html
+++ b/runtime/observatory/lib/src/elements/heap_snapshot.html
@@ -1,5 +1,4 @@
 <link rel="import" href="../../../../packages/polymer/polymer.html">
-<link rel="import" href="class_ref.html">
 
 <polymer-element name="heap-snapshot">
 <template>
diff --git a/runtime/observatory/lib/src/elements/helpers/rendering_scheduler.dart b/runtime/observatory/lib/src/elements/helpers/rendering_scheduler.dart
index 562d04b..a2ab155 100644
--- a/runtime/observatory/lib/src/elements/helpers/rendering_scheduler.dart
+++ b/runtime/observatory/lib/src/elements/helpers/rendering_scheduler.dart
@@ -35,9 +35,13 @@
   final T element;
   /// Queue used for rendering operations.
   final RenderingQueue queue;
+  /// Does the element need a new rendering cycle.
+  bool get isDirty => _dirty;
+  /// Is the scheduler enabled.
+  bool get isEnabled => _enabled;
 
   final StreamController<RenderedEvent<T>> _onRendered =
-                            new StreamController<RenderedEvent<T>>.broadcast();
+      new StreamController<RenderedEvent<T>>.broadcast();
   Stream<RenderedEvent<T>> get onRendered => _onRendered.stream;
 
   /// Creates a new scheduler for an element.
diff --git a/runtime/observatory/lib/src/elements/helpers/uris.dart b/runtime/observatory/lib/src/elements/helpers/uris.dart
index 1c9660c..a099bbf 100644
--- a/runtime/observatory/lib/src/elements/helpers/uris.dart
+++ b/runtime/observatory/lib/src/elements/helpers/uris.dart
@@ -13,8 +13,12 @@
     return '#' + new Uri(path: path, queryParameters: parameters).toString();
   }
 
-  static String inspect(M.IsolateRef isolate, {M.ObjectRef object})
-      => _isolatePage('/inspect', isolate, object: object);
+  static String inspect(M.IsolateRef isolate, {M.ObjectRef object, int pos}) {
+    if (pos == null) {
+      return _isolatePage('/inspect', isolate, object: object);
+    }
+    return _isolatePage('/inspect', isolate, object: object) + '---pos=${pos}';
+  }
   static String debugger(M.IsolateRef isolate)
       => _isolatePage('/debugger', isolate);
   static String classTree(M.IsolateRef isolate)
@@ -39,4 +43,5 @@
       => _isolatePage('/logging', isolate);
   static String vm() => '#/vm';
   static String vmConnect() => '#/vm-connect';
+  static String flags() => '#/flags';
 }
diff --git a/runtime/observatory/lib/src/elements/icdata_view.html b/runtime/observatory/lib/src/elements/icdata_view.html
index 9a5cf7b..f087b7e 100644
--- a/runtime/observatory/lib/src/elements/icdata_view.html
+++ b/runtime/observatory/lib/src/elements/icdata_view.html
@@ -1,8 +1,6 @@
 <link rel="import" href="../../../../packages/polymer/polymer.html">
-<link rel="import" href="class_ref.html">
 <link rel="import" href="error_view.html">
 <link rel="import" href="field_ref.html">
-<link rel="import" href="function_ref.html">
 <link rel="import" href="inbound_reference.html">
 <link rel="import" href="instance_ref.html">
 <link rel="import" href="object_common.html">
diff --git a/runtime/observatory/lib/src/elements/instance_view.html b/runtime/observatory/lib/src/elements/instance_view.html
index dd522e5..a28d0d6 100644
--- a/runtime/observatory/lib/src/elements/instance_view.html
+++ b/runtime/observatory/lib/src/elements/instance_view.html
@@ -1,10 +1,8 @@
 <link rel="import" href="../../../../packages/polymer/polymer.html">
-<link rel="import" href="class_ref.html">
 <link rel="import" href="error_view.html">
 <link rel="import" href="eval_box.html">
 <link rel="import" href="eval_link.html">
 <link rel="import" href="field_ref.html">
-<link rel="import" href="function_ref.html">
 <link rel="import" href="inbound_reference.html">
 <link rel="import" href="instance_ref.html">
 <link rel="import" href="object_common.html">
diff --git a/runtime/observatory/lib/src/elements/instructions_view.html b/runtime/observatory/lib/src/elements/instructions_view.html
index 07c5343..4751c55 100644
--- a/runtime/observatory/lib/src/elements/instructions_view.html
+++ b/runtime/observatory/lib/src/elements/instructions_view.html
@@ -1,8 +1,6 @@
 <link rel="import" href="../../../../packages/polymer/polymer.html">
-<link rel="import" href="class_ref.html">
 <link rel="import" href="error_view.html">
 <link rel="import" href="field_ref.html">
-<link rel="import" href="function_ref.html">
 <link rel="import" href="inbound_reference.html">
 <link rel="import" href="instance_ref.html">
 <link rel="import" href="object_common.html">
diff --git a/runtime/observatory/lib/src/elements/isolate_ref_wrapper.dart b/runtime/observatory/lib/src/elements/isolate_ref_wrapper.dart
index 93978c5..369e68a 100644
--- a/runtime/observatory/lib/src/elements/isolate_ref_wrapper.dart
+++ b/runtime/observatory/lib/src/elements/isolate_ref_wrapper.dart
@@ -72,7 +72,14 @@
 
     shadowRoot.children = [
       new StyleElement()
-        ..text = '@import "packages/observatory/src/elements/css/shared.css";',
+        ..text = '''
+        isolate-ref-wrapped > a[href]:hover {
+            text-decoration: underline;
+        }
+        isolate-ref-wrapped > a[href] {
+            color: #0489c3;
+            text-decoration: none;
+        }''',
       new IsolateRefElement(_isolate, _updates,
                                  queue: ObservatoryApplication.app.queue)
     ];
diff --git a/runtime/observatory/lib/src/elements/isolate_summary.html b/runtime/observatory/lib/src/elements/isolate_summary.html
index 7b62b4d..1a0c0a1 100644
--- a/runtime/observatory/lib/src/elements/isolate_summary.html
+++ b/runtime/observatory/lib/src/elements/isolate_summary.html
@@ -1,8 +1,7 @@
 <link rel="import" href="../../../../packages/polymer/polymer.html">
 <link rel="import" href="action_link.html">
-<link rel="import" href="function_ref.html">
 <link rel="import" href="script_inset.html">
-<link rel="import" href="script_ref.html">
+
 <polymer-element name="isolate-summary">
   <template>
     <link rel="stylesheet" href="css/shared.css">
diff --git a/runtime/observatory/lib/src/elements/isolate_view.html b/runtime/observatory/lib/src/elements/isolate_view.html
index a414e3f..16d3150 100644
--- a/runtime/observatory/lib/src/elements/isolate_view.html
+++ b/runtime/observatory/lib/src/elements/isolate_view.html
@@ -1,11 +1,8 @@
 <link rel="import" href="../../../../packages/polymer/polymer.html">
 <link rel="import" href="action_link.html">
 <link rel="import" href="eval_box.html">
-<link rel="import" href="function_ref.html">
 <link rel="import" href="isolate_summary.html">
-<link rel="import" href="library_ref.html">
 <link rel="import" href="script_inset.html">
-<link rel="import" href="script_ref.html">
 
 <polymer-element name="isolate-view">
   <template>
diff --git a/runtime/observatory/lib/src/elements/library_ref.dart b/runtime/observatory/lib/src/elements/library_ref.dart
index 4f65a39..be8918b 100644
--- a/runtime/observatory/lib/src/elements/library_ref.dart
+++ b/runtime/observatory/lib/src/elements/library_ref.dart
@@ -4,33 +4,58 @@
 
 library library_ref_element;
 
-import 'package:observatory/service.dart';
-import 'package:polymer/polymer.dart';
-import 'service_ref.dart';
+import 'dart:html';
 import 'dart:async';
+import 'package:observatory/models.dart' as M
+  show IsolateRef, LibraryRef;
+import 'package:observatory/src/elements/helpers/rendering_scheduler.dart';
+import 'package:observatory/src/elements/helpers/tag.dart';
+import 'package:observatory/src/elements/helpers/uris.dart';
 
-@CustomTag('library-ref')
-class LibraryRefElement extends ServiceRefElement {
-  @observable bool asValue = false;
+class LibraryRefElement extends HtmlElement implements Renderable {
+  static const tag = const Tag<LibraryRefElement>('library-ref-wrapped');
+
+  RenderingScheduler<LibraryRefElement> _r;
+
+  Stream<RenderedEvent<LibraryRefElement>> get onRendered => _r.onRendered;
+
+  M.IsolateRef _isolate;
+  M.LibraryRef _library;
+
+  M.IsolateRef get isolate => _isolate;
+  M.LibraryRef get library => _library;
+
+  factory LibraryRefElement(M.IsolateRef isolate, M.LibraryRef library,
+      {RenderingQueue queue}) {
+    assert(isolate != null);
+    assert(library != null);
+    LibraryRefElement e = document.createElement(tag.name);
+    e._r = new RenderingScheduler(e, queue: queue);
+    e._isolate = isolate;
+    e._library = library;
+    return e;
+  }
 
   LibraryRefElement.created() : super.created();
 
-  String makeExpandKey(String key) {
-    return '${expandKey}/${key}';
+  @override
+  void attached() {
+    super.attached();
+    _r.enable();
   }
 
-  dynamic expander() {
-    return expandEvent;
+  @override
+  void detached() {
+    super.detached();
+    _r.disable(notify: true);
+    children = [];
   }
 
-  void expandEvent(bool expand, Function onDone) {
-    if (expand) {
-      Library lib = ref;
-      lib.reload().then((result) {
-        return Future.wait(lib.variables.map((field) => field.reload()));
-      }).whenComplete(onDone);
-    } else {
-      onDone();
-    }
+  void render() {
+    final name = _library.name;
+    children = [
+      new AnchorElement(href: Uris.inspect(_isolate, object: _library))
+        ..text = (name == null || name.isEmpty) ? 'unnamed' : name
+    ];
   }
 }
diff --git a/runtime/observatory/lib/src/elements/library_ref.html b/runtime/observatory/lib/src/elements/library_ref.html
deleted file mode 100644
index 6e8c7a0..0000000
--- a/runtime/observatory/lib/src/elements/library_ref.html
+++ /dev/null
@@ -1,38 +0,0 @@
-<link rel="import" href="../../../../packages/polymer/polymer.html">
-
-<link rel="import" href="service_ref.html">
-
-<polymer-element name="library-ref">
-  <template>
-    <link rel="stylesheet" href="css/shared.css">
-    <style>
-      .indented {
-      margin-left: 1.5em;
-      font: 400 14px 'Montserrat', sans-serif;
-      line-height: 150%;
-      }
-    </style>
-    <template if="{{ nameIsEmpty }}">
-      <a on-click="{{ goto }}" _href="{{ url }}">unnamed</a>
-    </template>
-    <template if="{{ !nameIsEmpty }}">
-      <a on-click="{{ goto }}" _href="{{ url }}">{{ name }}</a>
-    </template>
-    <template if="{{ asValue }}">
-      <curly-block callback="{{ expander() }}" expandKey="{{ expandKey }}">
-        <div class="indented">
-          <template repeat="{{ field in ref.variables }}">
-            <template if="{{ field.isStatic }}">
-              {{ field.name }}&nbsp;:&nbsp;
-              <any-service-ref ref="{{ field.staticValue }}"
-                               expandKey="{{ makeExpandKey(field.name) }}">
-              </any-service-ref><br>
-            </template>
-          </template>
-        </div>
-      </curly-block>
-    </template>
-  </template>
-</polymer-element>
-
-<script type="application/dart" src="library_ref.dart"></script>
diff --git a/runtime/observatory/lib/src/elements/library_ref_as_value.dart b/runtime/observatory/lib/src/elements/library_ref_as_value.dart
new file mode 100644
index 0000000..6de3313
--- /dev/null
+++ b/runtime/observatory/lib/src/elements/library_ref_as_value.dart
@@ -0,0 +1,34 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library library_ref_as_value_element;
+
+import 'package:observatory/service.dart';
+import 'package:polymer/polymer.dart';
+import 'service_ref.dart';
+import 'dart:async';
+
+@CustomTag('library-ref-as-value')
+class LibraryRefAsValueElement extends ServiceRefElement {
+  LibraryRefAsValueElement.created() : super.created();
+
+  String makeExpandKey(String key) {
+    return '${expandKey}/${key}';
+  }
+
+  dynamic expander() {
+    return expandEvent;
+  }
+
+  void expandEvent(bool expand, Function onDone) {
+    if (expand) {
+      Library lib = ref;
+      lib.reload().then((result) {
+        return Future.wait(lib.variables.map((field) => field.reload()));
+      }).whenComplete(onDone);
+    } else {
+      onDone();
+    }
+  }
+}
diff --git a/runtime/observatory/lib/src/elements/library_ref_as_value.html b/runtime/observatory/lib/src/elements/library_ref_as_value.html
new file mode 100644
index 0000000..49dc900
--- /dev/null
+++ b/runtime/observatory/lib/src/elements/library_ref_as_value.html
@@ -0,0 +1,30 @@
+<link rel="import" href="../../../../packages/polymer/polymer.html">
+<link rel="import" href="service_ref.html">
+
+<polymer-element name="library-ref-as-value">
+  <template>
+    <link rel="stylesheet" href="css/shared.css">
+    <style>
+      .indented {
+      margin-left: 1.5em;
+      font: 400 14px 'Montserrat', sans-serif;
+      line-height: 150%;
+      }
+    </style>
+    <library-ref ref="{{ ref }}"></library-ref>
+    <curly-block callback="{{ expander() }}" expandKey="{{ expandKey }}">
+      <div class="indented">
+        <template repeat="{{ field in ref.variables }}">
+          <template if="{{ field.isStatic }}">
+            {{ field.name }}&nbsp;:&nbsp;
+            <any-service-ref ref="{{ field.staticValue }}"
+                             expandKey="{{ makeExpandKey(field.name) }}">
+            </any-service-ref><br>
+          </template>
+        </template>
+      </div>
+    </curly-block>
+  </template>
+</polymer-element>
+
+<script type="application/dart" src="library_ref_as_value.dart"></script>
diff --git a/runtime/observatory/lib/src/elements/library_ref_wrapper.dart b/runtime/observatory/lib/src/elements/library_ref_wrapper.dart
new file mode 100644
index 0000000..0a2caf4
--- /dev/null
+++ b/runtime/observatory/lib/src/elements/library_ref_wrapper.dart
@@ -0,0 +1,56 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:html';
+
+import 'package:observatory/app.dart';
+import 'package:observatory/service_html.dart' show Library;
+import 'package:observatory/src/elements/library_ref.dart';
+import 'package:observatory/src/elements/helpers/tag.dart';
+import 'package:observatory/src/elements/shims/binding.dart';
+
+@bindable
+class LibraryRefElementWrapper extends HtmlElement {
+
+  static const binder = const Binder<LibraryRefElementWrapper>(const {
+      'ref': #ref
+    });
+
+  static const tag = const Tag<LibraryRefElementWrapper>('library-ref');
+
+  Library _library;
+  Library get ref => _library;
+  void set ref(Library ref) { _library = ref; render(); }
+
+  LibraryRefElementWrapper.created() : super.created() {
+    binder.registerCallback(this);
+    createShadowRoot();
+    render();
+  }
+
+  @override
+  void attached() {
+    super.attached();
+    render();
+  }
+
+  void render() {
+    shadowRoot.children = [];
+    if (ref == null) return;
+
+    shadowRoot.children = [
+      new StyleElement()
+        ..text = '''
+        library-ref-wrapped > a[href]:hover {
+            text-decoration: underline;
+        }
+        library-ref-wrapped > a[href] {
+            color: #0489c3;
+            text-decoration: none;
+        }''',
+      new LibraryRefElement(_library.isolate, _library,
+          queue: ObservatoryApplication.app.queue)
+    ];
+  }
+}
diff --git a/runtime/observatory/lib/src/elements/library_view.html b/runtime/observatory/lib/src/elements/library_view.html
index 97417fa..5368cbf 100644
--- a/runtime/observatory/lib/src/elements/library_view.html
+++ b/runtime/observatory/lib/src/elements/library_view.html
@@ -1,11 +1,7 @@
 <link rel="import" href="../../../../packages/polymer/polymer.html">
-<link rel="import" href="class_ref.html">
 <link rel="import" href="eval_box.html">
 <link rel="import" href="field_ref.html">
-<link rel="import" href="function_ref.html">
 <link rel="import" href="instance_ref.html">
-<link rel="import" href="library_ref.html">
-<link rel="import" href="script_ref.html">
 
 <polymer-element name="library-view">
   <template>
diff --git a/runtime/observatory/lib/src/elements/logging.html b/runtime/observatory/lib/src/elements/logging.html
index 0360c82bf..fc74304 100644
--- a/runtime/observatory/lib/src/elements/logging.html
+++ b/runtime/observatory/lib/src/elements/logging.html
@@ -1,6 +1,4 @@
 <link rel="import" href="../../../../packages/polymer/polymer.html">
-<link rel="import" href="code_ref.html">
-<link rel="import" href="function_ref.html">
 
 <polymer-element name="logging-page">
   <template>
diff --git a/runtime/observatory/lib/src/elements/megamorphiccache_view.html b/runtime/observatory/lib/src/elements/megamorphiccache_view.html
index 720dc29..93f06af 100644
--- a/runtime/observatory/lib/src/elements/megamorphiccache_view.html
+++ b/runtime/observatory/lib/src/elements/megamorphiccache_view.html
@@ -1,8 +1,6 @@
 <link rel="import" href="../../../../packages/polymer/polymer.html">
-<link rel="import" href="class_ref.html">
 <link rel="import" href="error_view.html">
 <link rel="import" href="field_ref.html">
-<link rel="import" href="function_ref.html">
 <link rel="import" href="inbound_reference.html">
 <link rel="import" href="instance_ref.html">
 <link rel="import" href="object_common.html">
diff --git a/runtime/observatory/lib/src/elements/object_common.html b/runtime/observatory/lib/src/elements/object_common.html
index c0167ea..0235248 100644
--- a/runtime/observatory/lib/src/elements/object_common.html
+++ b/runtime/observatory/lib/src/elements/object_common.html
@@ -1,8 +1,6 @@
 <link rel="import" href="../../../../packages/polymer/polymer.html">
-<link rel="import" href="class_ref.html">
 <link rel="import" href="error_view.html">
 <link rel="import" href="field_ref.html">
-<link rel="import" href="function_ref.html">
 <link rel="import" href="inbound_reference.html">
 <link rel="import" href="instance_ref.html">
 <link rel="import" href="eval_link.html">
diff --git a/runtime/observatory/lib/src/elements/object_view.html b/runtime/observatory/lib/src/elements/object_view.html
index 99917f2..406f68e 100644
--- a/runtime/observatory/lib/src/elements/object_view.html
+++ b/runtime/observatory/lib/src/elements/object_view.html
@@ -1,8 +1,6 @@
 <link rel="import" href="../../../../packages/polymer/polymer.html">
-<link rel="import" href="class_ref.html">
 <link rel="import" href="error_view.html">
 <link rel="import" href="field_ref.html">
-<link rel="import" href="function_ref.html">
 <link rel="import" href="inbound_reference.html">
 <link rel="import" href="instance_ref.html">
 <link rel="import" href="object_common.html">
diff --git a/runtime/observatory/lib/src/elements/objectpool_view.html b/runtime/observatory/lib/src/elements/objectpool_view.html
index 1aff2dd..0899734 100644
--- a/runtime/observatory/lib/src/elements/objectpool_view.html
+++ b/runtime/observatory/lib/src/elements/objectpool_view.html
@@ -1,8 +1,6 @@
 <link rel="import" href="../../../../packages/polymer/polymer.html">
-<link rel="import" href="class_ref.html">
 <link rel="import" href="error_view.html">
 <link rel="import" href="field_ref.html">
-<link rel="import" href="function_ref.html">
 <link rel="import" href="inbound_reference.html">
 <link rel="import" href="instance_ref.html">
 <link rel="import" href="object_common.html">
diff --git a/runtime/observatory/lib/src/elements/objectstore_view.html b/runtime/observatory/lib/src/elements/objectstore_view.html
index 01f467b..bbf5efb 100644
--- a/runtime/observatory/lib/src/elements/objectstore_view.html
+++ b/runtime/observatory/lib/src/elements/objectstore_view.html
@@ -1,11 +1,7 @@
 <link rel="import" href="../../../../packages/polymer/polymer.html">
-<link rel="import" href="class_ref.html">
 <link rel="import" href="eval_box.html">
 <link rel="import" href="field_ref.html">
-<link rel="import" href="function_ref.html">
 <link rel="import" href="instance_ref.html">
-<link rel="import" href="library_ref.html">
-<link rel="import" href="script_ref.html">
 
 <polymer-element name="objectstore-view">
   <template>
diff --git a/runtime/observatory/lib/src/elements/script_inset.dart b/runtime/observatory/lib/src/elements/script_inset.dart
index d4f2899..fbbef3a 100644
--- a/runtime/observatory/lib/src/elements/script_inset.dart
+++ b/runtime/observatory/lib/src/elements/script_inset.dart
@@ -9,6 +9,7 @@
 import 'dart:math';
 import 'observatory_element.dart';
 import 'service_ref.dart';
+import 'package:observatory/models.dart' as M;
 import 'package:observatory/service.dart';
 import 'package:observatory/utils.dart';
 import 'package:polymer/polymer.dart';
@@ -929,8 +930,8 @@
     for (var func in script.library.functions) {
       if ((func.location != null) &&
           (func.location.script == script) &&
-          (func.kind != FunctionKind.kImplicitGetterFunction) &&
-          (func.kind != FunctionKind.kImplicitSetterFunction)) {
+          (func.kind != M.FunctionKind.implicitGetter) &&
+          (func.kind != M.FunctionKind.implicitSetter)) {
         // We annotate a field declaration with the field instead of the
         // implicit getter or setter.
         var a = new FunctionDeclarationAnnotation(func, inspectLink(func));
@@ -941,8 +942,8 @@
       for (var func in cls.functions) {
         if ((func.location != null) &&
             (func.location.script == script) &&
-            (func.kind != FunctionKind.kImplicitGetterFunction) &&
-            (func.kind != FunctionKind.kImplicitSetterFunction)) {
+            (func.kind != M.FunctionKind.implicitGetter) &&
+            (func.kind != M.FunctionKind.implicitSetter)) {
           // We annotate a field declaration with the field instead of the
           // implicit getter or setter.
           var a = new FunctionDeclarationAnnotation(func, inspectLink(func));
diff --git a/runtime/observatory/lib/src/elements/script_ref.dart b/runtime/observatory/lib/src/elements/script_ref.dart
index c11f26d..8cc2f68 100644
--- a/runtime/observatory/lib/src/elements/script_ref.dart
+++ b/runtime/observatory/lib/src/elements/script_ref.dart
@@ -4,69 +4,59 @@
 
 library script_ref_element;
 
-import 'package:polymer/polymer.dart';
-import 'package:observatory/service.dart';
-import 'service_ref.dart';
+import 'dart:html';
+import 'dart:async';
+import 'package:observatory/models.dart' as M show IsolateRef, ScriptRef;
+import 'package:observatory/src/elements/helpers/rendering_scheduler.dart';
+import 'package:observatory/src/elements/helpers/tag.dart';
+import 'package:observatory/src/elements/helpers/uris.dart';
 
-@CustomTag('script-ref')
-class ScriptRefElement extends ServiceRefElement {
-  @published int pos;
+class ScriptRefElement extends HtmlElement implements Renderable {
+  static const tag = const Tag<ScriptRefElement>('script-ref-wrapped');
 
-  String get hoverText {
-    if (ref == null) {
-      return super.hoverText;
-    }
-    return ref.vmName;
-  }
+  RenderingScheduler _r;
 
-  void posChanged(oldValue) {
-    _updateProperties(null);
-  }
+  Stream<RenderedEvent<ScriptRefElement>> get onRendered => _r.onRendered;
 
-  void _updateProperties(_) {
-    if (ref != null && ref.loaded) {
-      notifyPropertyChange(#name, 0, 1);
-      notifyPropertyChange(#url, 0, 1);
-    }
-  }
 
-  String get name {
-    if (ref == null) {
-      return super.name;
-    }
-    if ((pos != null) && (pos >= 0)) {
-      if (ref.loaded) {
-        // Script is loaded, get the line number.
-        Script script = ref;
-        return '${super.name}:${script.tokenToLine(pos)}:'
-            '${script.tokenToCol(pos)}';
-      } else {
-        ref.load().then(_updateProperties);
-      }
-    }
-    return super.name;
-  }
+  M.IsolateRef _isolate;
+  M.ScriptRef _script;
 
-  String get url {
-    if (ref == null) {
-      return super.url;
-    }
-    if ((pos != null) && (pos >= 0)) {
-      if (ref.loaded) {
-        return '${super.url}---pos=${pos}';
-      } else {
-        ref.load().then(_updateProperties);
-      }
-    }
-    return super.url;
+  M.IsolateRef get isolate => _isolate;
+  M.ScriptRef get script => _script;
+
+  factory ScriptRefElement(M.IsolateRef isolate, M.ScriptRef script,
+                           {RenderingQueue queue}) {
+    assert(isolate != null);
+    assert(script != null);
+    ScriptRefElement e = document.createElement(tag.name);
+    e._r = new RenderingScheduler(e, queue: queue);
+    e._isolate = isolate;
+    e._script = script;
+    return e;
   }
 
   ScriptRefElement.created() : super.created();
-}
 
-@CustomTag('source-link')
-class SourceLinkElement extends PolymerElement {
-  SourceLinkElement.created() : super.created();
+  @override
+  void attached() {
+    super.attached();
+    assert(script != null);
+    _r.enable();
+  }
 
-  @published SourceLocation location;
+  @override
+  void detached() {
+    super.detached();
+    children = [];
+    _r.disable(notify: true);
+  }
+
+  void render() {
+    children = [
+      new AnchorElement(href: Uris.inspect(isolate, object: script))
+        ..title = script.uri
+        ..text = script.uri.split('/').last
+    ];
+  }
 }
diff --git a/runtime/observatory/lib/src/elements/script_ref.html b/runtime/observatory/lib/src/elements/script_ref.html
deleted file mode 100644
index 7a9f0f1..0000000
--- a/runtime/observatory/lib/src/elements/script_ref.html
+++ /dev/null
@@ -1,22 +0,0 @@
-<link rel="import" href="../../../../packages/polymer/polymer.html">
-
-<link rel="import" href="service_ref.html">
-
-<polymer-element name="script-ref">
-<template>
-  <link rel="stylesheet" href="css/shared.css">
-  <a on-click="{{ goto }}" title="{{ hoverText }}" _href="{{ url }}">{{ name }}</a>
-</template>
-</polymer-element>
-
-<polymer-element name="source-link">
-<template>
-  <template if="{{ location != null }}">
-    <script-ref ref="{{ location.script }}"
-                pos="{{ location.tokenPos }}"></script-ref>
-  </template>
-</template>
-</polymer-element>
-
-
-<script type="application/dart" src="script_ref.dart"></script>
diff --git a/runtime/observatory/lib/src/elements/script_ref_wrapper.dart b/runtime/observatory/lib/src/elements/script_ref_wrapper.dart
new file mode 100644
index 0000000..01f6940
--- /dev/null
+++ b/runtime/observatory/lib/src/elements/script_ref_wrapper.dart
@@ -0,0 +1,56 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:html';
+import 'dart:async';
+
+import 'package:observatory/app.dart';
+import 'package:observatory/service_html.dart' show Script;
+import 'package:observatory/src/elements/script_ref.dart';
+import 'package:observatory/src/elements/helpers/tag.dart';
+import 'package:observatory/src/elements/shims/binding.dart';
+
+@bindable
+class ScriptRefElementWrapper extends HtmlElement {
+  static const binder = const Binder<ScriptRefElementWrapper>(const {
+      'ref': #ref
+    });
+
+  static const tag = const Tag<ScriptRefElementWrapper>('script-ref');
+
+  Script _script;
+  Script get ref => _script;
+  set ref(Script script) { _script = script; render(); }
+
+  ScriptRefElementWrapper.created() : super.created() {
+    binder.registerCallback(this);
+    createShadowRoot();
+    render();
+  }
+
+  @override
+  void attached() {
+    super.attached();
+    render();
+  }
+
+  Future render() async {
+    shadowRoot.children = [];
+    if (_script == null) return;
+
+    shadowRoot.children = [
+      new StyleElement()
+        ..text = '''
+        script-ref-wrapped > a[href]:hover {
+            text-decoration: underline;
+        }
+        script-ref-wrapped > a[href] {
+            color: #0489c3;
+            text-decoration: none;
+        }''',
+      new ScriptRefElement(_script.isolate, _script,
+                                 queue: ObservatoryApplication.app.queue)
+    ];
+  }
+}
diff --git a/runtime/observatory/lib/src/elements/service_ref.dart b/runtime/observatory/lib/src/elements/service_ref.dart
index d368713..e0a28fe 100644
--- a/runtime/observatory/lib/src/elements/service_ref.dart
+++ b/runtime/observatory/lib/src/elements/service_ref.dart
@@ -7,11 +7,18 @@
 import 'dart:html';
 
 import 'package:logging/logging.dart';
+import 'package:observatory/models.dart' as M;
 import 'package:observatory/service.dart';
 import 'package:polymer/polymer.dart';
 
 import 'class_ref.dart';
+import 'class_ref_as_value.dart';
+import 'code_ref.dart';
+import 'error_ref.dart';
+import 'function_ref.dart';
 import 'library_ref.dart';
+import 'library_ref_as_value.dart';
+import 'script_ref.dart';
 import 'observatory_element.dart';
 
 class ServiceRefElement extends ObservatoryElement {
@@ -91,43 +98,49 @@
     var type = ref.type;
     switch (type) {
      case 'Class':
-        ClassRefElement element = new Element.tag('class-ref');
-        element.ref = ref;
-        element.asValue = asValue;
-        return element;
+        if (asValue) {
+          ClassRefAsValueElement element =
+            new Element.tag('class-ref-as-element');
+          element.ref = ref;
+          return element;
+        }
+        return new ClassRefElement(ref.isolate,
+                                   ref as M.ClassRef,
+                                   queue: app.queue);
       case 'Code':
-        ServiceRefElement element = new Element.tag('code-ref');
-        element.ref = ref;
-        return element;
+        return new CodeRefElement(ref.isolate, ref as M.Code, queue: app.queue);
       case 'Context':
         ServiceRefElement element = new Element.tag('context-ref');
         element.ref = ref;
         return element;
       case 'Error':
-        ServiceRefElement element = new Element.tag('error-ref');
-        element.ref = ref;
-        return element;
+        return new ErrorRefElement(ref as M.ErrorRef, queue: app.queue);
       case 'Field':
         ServiceRefElement element = new Element.tag('field-ref');
         element.ref = ref;
         return element;
       case 'Function':
-        ServiceRefElement element = new Element.tag('function-ref');
-        element.ref = ref;
-        return element;
+        return new FunctionRefElement(ref.isolate,
+                                      ref as M.FunctionRef,
+                                      queue: app.queue);
       case 'Library':
-        LibraryRefElement element = new Element.tag('library-ref');
-        element.ref = ref;
-        element.asValue = asValue;
-        return element;
+        if (asValue) {
+          LibraryRefAsValueElement element =
+              new Element.tag('library-ref-as-value');
+          element.ref = ref;
+          return element;
+        }
+        return new LibraryRefElement(ref.isolate,
+                                     ref as M.LibraryRef,
+                                     queue: app.queue);
       case 'Object':
         ServiceRefElement element = new Element.tag('object-ref');
         element.ref = ref;
         return element;
       case 'Script':
-        ServiceRefElement element = new Element.tag('script-ref');
-        element.ref = ref;
-        return element;
+        return new ScriptRefElement(ref.isolate,
+                                    ref as M.ScriptRef,
+                                    queue: app.queue);
       case 'Instance':
       case 'Sentinel':
         ServiceRefElement element = new Element.tag('instance-ref');
diff --git a/runtime/observatory/lib/src/elements/service_view.dart b/runtime/observatory/lib/src/elements/service_view.dart
index c9924a6..0e3ed2d 100644
--- a/runtime/observatory/lib/src/elements/service_view.dart
+++ b/runtime/observatory/lib/src/elements/service_view.dart
@@ -46,10 +46,6 @@
         FieldViewElement element = new Element.tag('field-view');
         element.field = object;
         return element;
-      case 'FlagList':
-        FlagListElement element = new Element.tag('flag-list');
-        element.flagList = object;
-        return element;
       case 'Function':
         FunctionViewElement element = new Element.tag('function-view');
         element.function = object;
diff --git a/runtime/observatory/lib/src/elements/source_link.dart b/runtime/observatory/lib/src/elements/source_link.dart
new file mode 100644
index 0000000..02eec26
--- /dev/null
+++ b/runtime/observatory/lib/src/elements/source_link.dart
@@ -0,0 +1,74 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library source_link_element;
+
+import 'dart:html';
+import 'dart:async';
+import 'package:observatory/models.dart'
+  show IsolateRef, SourceLocation, Script, ScriptRepository;
+import 'package:observatory/src/elements/helpers/rendering_scheduler.dart';
+import 'package:observatory/src/elements/helpers/tag.dart';
+import 'package:observatory/src/elements/helpers/uris.dart';
+
+class SourceLinkElement extends HtmlElement implements Renderable {
+  static const tag = const Tag<SourceLinkElement>('source-link-wrapped');
+
+  RenderingScheduler _r;
+
+  Stream<RenderedEvent<SourceLinkElement>> get onRendered => _r.onRendered;
+
+  IsolateRef _isolate;
+  SourceLocation _location;
+  Script _script;
+  ScriptRepository _repository;
+
+  IsolateRef get isolate => _isolate;
+  SourceLocation get location => _location;
+
+  factory SourceLinkElement(IsolateRef isolate, SourceLocation location,
+      ScriptRepository repository, {RenderingQueue queue}) {
+    assert(isolate != null);
+    assert(location != null);
+    SourceLinkElement e = document.createElement(tag.name);
+    e._r = new RenderingScheduler(e, queue: queue);
+    e._isolate = isolate;
+    e._location = location;
+    e._repository = repository;
+    return e;
+  }
+
+  SourceLinkElement.created() : super.created();
+
+  @override
+  void attached() {
+    super.attached();
+    assert(location != null);
+    _r.enable();
+    _repository.get(_location.script.id).then((script) {
+      _script = script;
+      _r.dirty();
+    });
+  }
+
+  @override
+  void detached() { super.detached(); children = []; _r.disable(notify: true); }
+
+  Future render() async {
+    if (_script == null) {
+      children = [new SpanElement()..text = '<LOADING>'];
+    } else {
+      String label = _script.uri.split('/').last;
+      int token = _location.tokenPos;
+      int line = _script.tokenToLine(token);
+      int column = _script.tokenToCol(token);
+      children = [
+        new AnchorElement(
+            href: Uris.inspect(isolate, object: _script, pos: token))
+          ..title = _script.uri
+          ..text = '${label}:${line}:${column}'
+      ];
+    }
+  }
+}
diff --git a/runtime/observatory/lib/src/elements/source_link_wrapper.dart b/runtime/observatory/lib/src/elements/source_link_wrapper.dart
new file mode 100644
index 0000000..d38d70f
--- /dev/null
+++ b/runtime/observatory/lib/src/elements/source_link_wrapper.dart
@@ -0,0 +1,59 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:html';
+import 'dart:async';
+
+import 'package:observatory/app.dart';
+import 'package:observatory/repositories.dart' show ScriptRepository;
+import 'package:observatory/service_html.dart' show SourceLocation;
+import 'package:observatory/src/elements/source_link.dart';
+import 'package:observatory/src/elements/helpers/tag.dart';
+import 'package:observatory/src/elements/shims/binding.dart';
+
+@bindable
+class SourceLinkElementWrapper extends HtmlElement {
+  static const binder = const Binder<SourceLinkElementWrapper>(const {
+      'location' : #location
+    });
+
+  static const tag = const Tag<SourceLinkElementWrapper>('source-link');
+
+  SourceLocation _location;
+  SourceLocation get location => location;
+  set location(SourceLocation location) { _location = location; render(); }
+
+  SourceLinkElementWrapper.created() : super.created() {
+    binder.registerCallback(this);
+    createShadowRoot();
+    render();
+  }
+
+  @override
+  void attached() {
+    super.attached();
+    render();
+  }
+
+  Future render() async {
+    shadowRoot.children = [];
+    if (_location == null) return;
+
+    ScriptRepository repository = new ScriptRepository(_location.isolate);
+
+    shadowRoot.children = [
+      new StyleElement()
+        ..text = '''
+        source-link-wrapped > a[href]:hover {
+            text-decoration: underline;
+        }
+        source-link-wrapped > a[href] {
+            color: #0489c3;
+            text-decoration: none;
+        }''',
+      new SourceLinkElement(_location.isolate, _location, repository,
+                            queue: ObservatoryApplication.app.queue)
+    ];
+  }
+}
diff --git a/runtime/observatory/lib/src/elements/vm_connect.dart b/runtime/observatory/lib/src/elements/vm_connect.dart
index 8539921..65487cf 100644
--- a/runtime/observatory/lib/src/elements/vm_connect.dart
+++ b/runtime/observatory/lib/src/elements/vm_connect.dart
@@ -16,7 +16,7 @@
 import 'package:observatory/src/elements/view_footer.dart';
 import 'package:observatory/src/elements/vm_connect_target.dart';
 
-class VMConnectElement extends HtmlElement implements Renderable{
+class VMConnectElement extends HtmlElement implements Renderable {
   static const tag = const Tag<VMConnectElement>('vm-connect',
                      dependencies: const [NavBarElement.tag,
                                           NavTopMenuElement.tag,
@@ -67,6 +67,8 @@
   }
 
   void render() {
+    final host = window.location.hostname;
+    final port = window.location.port;
     children = [
       new NavBarElement(queue: _r.queue)
         ..children = [
@@ -125,7 +127,7 @@
                   new PreElement()
                     ..classes = ['well']
                     ..text = 'Request a crash dump with:\n'
-                      '\'curl localhost:8181/_getCrashDump > dump.json\'',
+                      '\'curl $host:$port/_getCrashDump > dump.json\'',
                   new HRElement()
                 ]
             ],
diff --git a/runtime/observatory/lib/src/elements/vm_connect_target.dart b/runtime/observatory/lib/src/elements/vm_connect_target.dart
index 3fa7d12..43a0cec 100644
--- a/runtime/observatory/lib/src/elements/vm_connect_target.dart
+++ b/runtime/observatory/lib/src/elements/vm_connect_target.dart
@@ -15,7 +15,7 @@
   TargetEvent(this.target);
 }
 
-class VMConnectTargetElement extends HtmlElement implements Renderable{
+class VMConnectTargetElement extends HtmlElement implements Renderable {
 
   static const tag =
     const Tag<VMConnectTargetElement>('vm-connect-target');
diff --git a/runtime/observatory/lib/src/elements/vm_view.html b/runtime/observatory/lib/src/elements/vm_view.html
index a078f04..a73d50b 100644
--- a/runtime/observatory/lib/src/elements/vm_view.html
+++ b/runtime/observatory/lib/src/elements/vm_view.html
@@ -1,9 +1,6 @@
 <link rel="import" href="../../../../packages/polymer/polymer.html">
 <link rel="import" href="eval_box.html">
-<link rel="import" href="function_ref.html">
 <link rel="import" href="isolate_summary.html">
-<link rel="import" href="library_ref.html">
-<link rel="import" href="script_ref.html">
 
 <polymer-element name="vm-view">
   <template>
diff --git a/runtime/observatory/lib/src/mocks/objects/code.dart b/runtime/observatory/lib/src/mocks/objects/code.dart
new file mode 100644
index 0000000..d0529ae
--- /dev/null
+++ b/runtime/observatory/lib/src/mocks/objects/code.dart
@@ -0,0 +1,23 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file
+
+part of mocks;
+
+class CodeRefMock implements M.CodeRef {
+  final String id;
+  final String name;
+  final M.CodeKind kind;
+  final bool isOptimized;
+
+  const CodeRefMock({this.id, this.name, this.kind, this.isOptimized: false });
+}
+
+class CodeMock implements M.Code {
+  final String id;
+  final String name;
+  final M.CodeKind kind;
+  final bool isOptimized;
+
+  const CodeMock({this.id, this.name, this.kind, this.isOptimized: false });
+}
diff --git a/runtime/observatory/lib/src/mocks/objects/flag.dart b/runtime/observatory/lib/src/mocks/objects/flag.dart
new file mode 100644
index 0000000..1b250ff
--- /dev/null
+++ b/runtime/observatory/lib/src/mocks/objects/flag.dart
@@ -0,0 +1,14 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file
+
+part of mocks;
+
+class FlagMock implements M.Flag {
+  final String name;
+  final String comment;
+  final bool modified;
+  final String valueAsString;
+
+  const FlagMock({this.name, this.comment, this.modified, this.valueAsString});
+}
diff --git a/runtime/observatory/lib/src/mocks/objects/function.dart b/runtime/observatory/lib/src/mocks/objects/function.dart
new file mode 100644
index 0000000..8a60adf
--- /dev/null
+++ b/runtime/observatory/lib/src/mocks/objects/function.dart
@@ -0,0 +1,31 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file
+
+part of mocks;
+
+class FunctionRefMock implements M.FunctionRef {
+  final String id;
+  final String name;
+  final M.ObjectRef dartOwner;
+  final bool isStatic;
+  final bool isConst;
+  final M.FunctionKind kind;
+
+  const FunctionRefMock({this.id, this.name, this.dartOwner,
+      this.isStatic : false, this.isConst : false, this.kind});
+}
+
+class FunctionMock implements M.Function {
+  final String id;
+  final String name;
+  final M.ObjectRef dartOwner;
+  final bool isStatic;
+  final bool isConst;
+  final M.FunctionKind kind;
+  final M.SourceLocation location;
+  final M.CodeRef code;
+  const FunctionMock({this.id, this.name, this.dartOwner,
+      this.isStatic : false, this.isConst : false, this.kind, this.location,
+      this.code});
+}
diff --git a/runtime/observatory/lib/src/mocks/objects/script.dart b/runtime/observatory/lib/src/mocks/objects/script.dart
index bb264dc..7ce801a 100644
--- a/runtime/observatory/lib/src/mocks/objects/script.dart
+++ b/runtime/observatory/lib/src/mocks/objects/script.dart
@@ -7,6 +7,7 @@
 class ScriptRefMock implements M.ScriptRef {
   final String id;
   final String uri;
+
   const ScriptRefMock({this.id, this.uri});
 }
 
diff --git a/runtime/observatory/lib/src/mocks/objects/source_location.dart b/runtime/observatory/lib/src/mocks/objects/source_location.dart
index 481b44b..1c9c0f2 100644
--- a/runtime/observatory/lib/src/mocks/objects/source_location.dart
+++ b/runtime/observatory/lib/src/mocks/objects/source_location.dart
@@ -8,5 +8,6 @@
   final M.ScriptRef script;
   final int tokenPos;
   final int endTokenPos;
+
   const SourceLocationMock({this.script, this.tokenPos, this.endTokenPos});
 }
diff --git a/runtime/observatory/lib/src/mocks/repositories/flag.dart b/runtime/observatory/lib/src/mocks/repositories/flag.dart
new file mode 100644
index 0000000..1c9c11d
--- /dev/null
+++ b/runtime/observatory/lib/src/mocks/repositories/flag.dart
@@ -0,0 +1,21 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file
+
+part of mocks;
+
+typedef Future<Iterable<M.Flag>> FlagsRepositoryMockCallback(M.VMRef vm);
+
+class FlagsRepositoryMock implements M.FlagsRepository {
+  final FlagsRepositoryMockCallback _list;
+
+  Future<Iterable<M.Flag>> list(M.VMRef vm) {
+    if (_list != null) {
+      return _list(vm);
+    }
+    return new Future.value(const []);
+  }
+
+  FlagsRepositoryMock({FlagsRepositoryMockCallback list})
+    : _list = list;
+}
diff --git a/runtime/observatory/lib/src/mocks/repositories/script.dart b/runtime/observatory/lib/src/mocks/repositories/script.dart
new file mode 100644
index 0000000..7ab9114
--- /dev/null
+++ b/runtime/observatory/lib/src/mocks/repositories/script.dart
@@ -0,0 +1,19 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+part of mocks;
+
+class ScriptRepositoryMock implements M.ScriptRepository {
+  final Map<String, M.Script> scripts;
+
+  bool _invoked = false;
+  bool get invoked => _invoked;
+
+  ScriptRepositoryMock(this.scripts);
+
+  Future<M.Script> get(String id) async {
+    _invoked = true;
+    return scripts[id];
+  }
+}
diff --git a/runtime/observatory/lib/src/models/objects/class.dart b/runtime/observatory/lib/src/models/objects/class.dart
index a2a9007..b9e5f50 100644
--- a/runtime/observatory/lib/src/models/objects/class.dart
+++ b/runtime/observatory/lib/src/models/objects/class.dart
@@ -9,7 +9,7 @@
   String get name;
 }
 
-abstract class Class extends ObjectRef implements ClassRef {
+abstract class Class extends Object implements ClassRef {
   /// The error which occurred during class finalization, if it exists.
   /// [optional]
   ErrorRef get error;
@@ -42,7 +42,7 @@
   /// The mixin type for this class, if any.
   ///
   /// The value will be of the kind: Type. [optional]
-  Iterable<InstanceRef> get mixin;
+  InstanceRef get mixin;
 
   /// A list of fields in this class. Does not include fields from
   /// superclasses.
diff --git a/runtime/observatory/lib/src/models/objects/code.dart b/runtime/observatory/lib/src/models/objects/code.dart
new file mode 100644
index 0000000..1a8758e
--- /dev/null
+++ b/runtime/observatory/lib/src/models/objects/code.dart
@@ -0,0 +1,39 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file
+
+part of models;
+
+enum CodeKind {
+  dart,
+  native,
+  stub,
+  tag,
+  collected
+}
+
+bool isSyntheticCode(CodeKind kind) {
+  switch (kind) {
+    case CodeKind.collected:
+    case CodeKind.native:
+    case CodeKind.tag:
+      return true;
+    default:
+      return false;
+  }
+}
+
+bool isDartCode(CodeKind kind) => !isSyntheticCode(kind);
+
+abstract class CodeRef extends ObjectRef {
+  /// The name of this class.
+  String get name;
+
+  // What kind of code object is this?
+  CodeKind get kind;
+
+  bool get isOptimized;
+}
+
+abstract class Code extends Object implements CodeRef {
+}
diff --git a/runtime/observatory/lib/src/models/objects/flag.dart b/runtime/observatory/lib/src/models/objects/flag.dart
new file mode 100644
index 0000000..3813f88
--- /dev/null
+++ b/runtime/observatory/lib/src/models/objects/flag.dart
@@ -0,0 +1,21 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file
+
+part of models;
+
+abstract class Flag {
+  /// The name of the flag.
+  String get name;
+
+  /// A description of the flag.
+  String get comment;
+
+  /// Has this flag been modified from its default setting?
+  bool get modified;
+
+  /// The value of this flag as a string. [optional]
+  ///
+  /// If this property is absent, then the value of the flag was NULL.
+  String get valueAsString;
+}
diff --git a/runtime/observatory/lib/src/models/objects/function.dart b/runtime/observatory/lib/src/models/objects/function.dart
new file mode 100644
index 0000000..bb763af
--- /dev/null
+++ b/runtime/observatory/lib/src/models/objects/function.dart
@@ -0,0 +1,69 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file
+
+part of models;
+
+enum FunctionKind {
+  regular,
+  closure,
+  getter,
+  setter,
+  constructor,
+  implicitGetter,
+  implicitSetter,
+  implicitStaticFinalGetter,
+  irregexpFunction,
+  staticInitializer,
+  methodExtractor,
+  noSuchMethodDispatcher,
+  invokeFieldDispatcher,
+  collected,
+  native,
+  stub,
+  tag,
+  signatureFunction
+}
+
+bool isSyntheticFunction(FunctionKind kind) {
+  switch (kind) {
+    case FunctionKind.collected:
+    case FunctionKind.native:
+    case FunctionKind.stub:
+    case FunctionKind.tag:
+      return true;
+    default:
+      return false;
+  }
+}
+
+bool isDartFunction(FunctionKind kind) => !isSyntheticFunction(kind);
+bool isStubFunction(FunctionKind kind) => kind == FunctionKind.stub;
+bool hasDartCode(FunctionKind kind) =>
+    isDartFunction(kind) || isStubFunction(kind);
+
+abstract class FunctionRef extends ObjectRef {
+  /// The name of this class.
+  String get name;
+
+  /// The owner of this function, which can be a LibraryRef, ClassRef,
+  /// or a FunctionRef.
+  ObjectRef get dartOwner; // owner
+
+  /// Is this function static?
+  bool get isStatic;
+
+  /// Is this function const?
+  bool get isConst;
+
+  /// The kind of the function.
+  FunctionKind get kind;
+}
+
+abstract class Function extends Object implements FunctionRef {
+  /// The location of this function in the source code. [optional]
+  SourceLocation get location;
+
+  /// The compiled code associated with this function. [optional]
+  CodeRef get code;
+}
diff --git a/runtime/observatory/lib/src/models/repositories/flag.dart b/runtime/observatory/lib/src/models/repositories/flag.dart
new file mode 100644
index 0000000..2bdc018
--- /dev/null
+++ b/runtime/observatory/lib/src/models/repositories/flag.dart
@@ -0,0 +1,9 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file
+
+part of models;
+
+abstract class FlagsRepository {
+  Future<Iterable<Flag>> list(VMRef vm);
+}
diff --git a/runtime/observatory/lib/src/models/repositories/script.dart b/runtime/observatory/lib/src/models/repositories/script.dart
new file mode 100644
index 0000000..e3b54ad
--- /dev/null
+++ b/runtime/observatory/lib/src/models/repositories/script.dart
@@ -0,0 +1,7 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+part of models;
+
+abstract class ScriptRepository extends Repository<Script, String> {}
diff --git a/runtime/observatory/lib/src/models/repository.dart b/runtime/observatory/lib/src/models/repository.dart
new file mode 100644
index 0000000..9aec1fd
--- /dev/null
+++ b/runtime/observatory/lib/src/models/repository.dart
@@ -0,0 +1,9 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+part of models;
+
+abstract class Repository<ObjectT, DescriptorT> {
+  Future<ObjectT> get(DescriptorT id);
+}
diff --git a/runtime/observatory/lib/src/repositories/flag.dart b/runtime/observatory/lib/src/repositories/flag.dart
new file mode 100644
index 0000000..9a644e6
--- /dev/null
+++ b/runtime/observatory/lib/src/repositories/flag.dart
@@ -0,0 +1,34 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file
+
+part of repositories;
+
+class Flag implements M.Flag {
+  final String name;
+  final String comment;
+  final bool modified;
+  final String valueAsString;
+  Flag(this.name, this.comment, this.modified, this.valueAsString) {
+    assert(name != null);
+    assert(comment != null);
+    assert(modified != null);
+  }
+}
+
+class FlagsRepository implements M.FlagsRepository {
+  Future<Iterable<Flag>> list(M.VM vm) async{
+    if (vm is S.VM) {
+      List<Map> flags = ((await vm.getFlagList()) as S.ServiceMap)['flags'];
+      return flags.map(_toFlag);
+    }
+    return const [];
+  }
+
+  static _toFlag(Map map){
+    return new Flag(map['name'],
+                    map['comment'],
+                    map['modified'],
+                    map['valueAsString']);
+  }
+}
diff --git a/runtime/observatory/lib/src/repositories/script.dart b/runtime/observatory/lib/src/repositories/script.dart
new file mode 100644
index 0000000..918de35
--- /dev/null
+++ b/runtime/observatory/lib/src/repositories/script.dart
@@ -0,0 +1,15 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+part of repositories;
+
+class ScriptRepository implements M.ScriptRepository {
+  final S.Isolate isolate;
+
+  ScriptRepository(this.isolate);
+
+  Future<M.Script> get(String id) async {
+    return (await isolate.getObject(id)) as M.Script;
+  }
+}
diff --git a/runtime/observatory/lib/src/service/object.dart b/runtime/observatory/lib/src/service/object.dart
index 85574fe..d2f44d9 100644
--- a/runtime/observatory/lib/src/service/object.dart
+++ b/runtime/observatory/lib/src/service/object.dart
@@ -426,7 +426,7 @@
 
 /// A [SourceLocation] represents a location or range in the source code.
 class SourceLocation extends ServiceObject implements Location,
-                                                          M.SourceLocation {
+                                                      M.SourceLocation {
   Script script;
   int tokenPos;
   int endTokenPos;
@@ -1799,12 +1799,6 @@
   final ObservableMap _map = new ObservableMap();
   static String objectIdRingPrefix = 'objects/';
 
-  bool get canCache {
-    return (_type == 'Class' ||
-            _type == 'Function' ||
-            _type == 'Field') &&
-           !_id.startsWith(objectIdRingPrefix);
-  }
   bool get immutable => false;
 
   ServiceMap._empty(ServiceObjectOwner owner) : super._empty(owner);
@@ -2047,7 +2041,6 @@
 
   // TODO(turnidge): Add state to track if a breakpoint has been
   // removed from the program.  Remove from the cache when deleted.
-  bool get canCache => true;
   bool get immutable => false;
 
   // A unique integer identifier for this breakpoint.
@@ -2146,7 +2139,6 @@
   @reflectable final variables = new ObservableList<Field>();
   @reflectable final functions = new ObservableList<ServiceFunction>();
 
-  bool get canCache => true;
   bool get immutable => false;
 
   bool isDart(String libraryName) {
@@ -2270,7 +2262,6 @@
   @observable Instance superType;
   @observable Instance mixin;
 
-  bool get canCache => true;
   bool get immutable => false;
 
   Class._empty(ServiceObjectOwner owner) : super._empty(owner);
@@ -2405,10 +2396,10 @@
   @observable Instance key;  // If a WeakProperty.
   @observable Instance value;  // If a WeakProperty.
   @observable Breakpoint activationBreakpoint;  // If a Closure.
-  @observable Function oneByteFunction;  // If a RegExp.
-  @observable Function twoByteFunction;  // If a RegExp.
-  @observable Function externalOneByteFunction;  // If a RegExp.
-  @observable Function externalTwoByteFunction;  // If a RegExp.
+  @observable ServiceFunction oneByteFunction;  // If a RegExp.
+  @observable ServiceFunction twoByteFunction;  // If a RegExp.
+  @observable ServiceFunction externalOneByteFunction;  // If a RegExp.
+  @observable ServiceFunction externalTwoByteFunction;  // If a RegExp.
   @observable Instance oneByteBytecode;  // If a RegExp.
   @observable Instance twoByteBytecode;  // If a RegExp.
   @observable bool isCaseSensitive;  // If a RegExp.
@@ -2498,10 +2489,11 @@
 
     isCaseSensitive = map['isCaseSensitive'];
     isMultiLine = map['isMultiLine'];
-    oneByteFunction = map['_oneByteFunction'];
-    twoByteFunction = map['_twoByteFunction'];
-    externalOneByteFunction = map['_externalOneByteFunction'];
-    externalTwoByteFunction = map['_externalTwoByteFunction'];
+    bool isCompiled = map['_oneByteFunction'] is ServiceFunction;
+    oneByteFunction = isCompiled ? map['_oneByteFunction'] : null;
+    twoByteFunction = isCompiled ? map['_twoByteFunction'] : null;
+    externalOneByteFunction = isCompiled ? map['_externalOneByteFunction'] : null;
+    externalTwoByteFunction = isCompiled ? map['_externalTwoByteFunction'] : null;
     oneByteBytecode = map['_oneByteBytecode'];
     twoByteBytecode = map['_twoByteBytecode'];
 
@@ -2604,65 +2596,35 @@
   String toString() => 'Context($length)';
 }
 
-
-// TODO(koda): Sync this with VM.
-class FunctionKind {
-  final String _strValue;
-  FunctionKind._internal(this._strValue);
-  toString() => _strValue;
-  bool isSynthetic() => [kCollected, kNative, kStub, kTag].contains(this);
-  bool isDart() => !isSynthetic();
-  bool isStub() => (this == kStub);
-  bool hasDartCode() => isDart() || isStub();
-  static FunctionKind fromJSON(String value) {
-    switch(value) {
-      case 'RegularFunction': return kRegularFunction;
-      case 'ClosureFunction': return kClosureFunction;
-      case 'GetterFunction': return kGetterFunction;
-      case 'SetterFunction': return kSetterFunction;
-      case 'Constructor': return kConstructor;
-      case 'ImplicitGetter': return kImplicitGetterFunction;
-      case 'ImplicitSetter': return kImplicitSetterFunction;
-      case 'ImplicitStaticFinalGetter': return kImplicitStaticFinalGetter;
-      case 'IrregexpFunction': return kIrregexpFunction;
-      case 'StaticInitializer': return kStaticInitializer;
-      case 'MethodExtractor': return kMethodExtractor;
-      case 'NoSuchMethodDispatcher': return kNoSuchMethodDispatcher;
-      case 'InvokeFieldDispatcher': return kInvokeFieldDispatcher;
-      case 'Collected': return kCollected;
-      case 'Native': return kNative;
-      case 'Stub': return kStub;
-      case 'Tag': return kTag;
-      case 'SignatureFunction': return kSignatureFunction;
-    }
-    Logger.root.severe('Unrecognized function kind: $value');
-    throw new FallThroughError();
+M.FunctionKind stringToFunctionKind(String value) {
+  switch(value) {
+    case 'RegularFunction': return M.FunctionKind.regular;
+    case 'ClosureFunction': return M.FunctionKind.closure;
+    case 'GetterFunction': return M.FunctionKind.getter;
+    case 'SetterFunction': return M.FunctionKind.setter;
+    case 'Constructor': return M.FunctionKind.constructor;
+    case 'ImplicitGetter': return M.FunctionKind.implicitGetter;
+    case 'ImplicitSetter': return M.FunctionKind.implicitSetter;
+    case 'ImplicitStaticFinalGetter':
+      return M.FunctionKind.implicitStaticFinalGetter;
+    case 'IrregexpFunction': return M.FunctionKind.irregexpFunction;
+    case 'StaticInitializer': return M.FunctionKind.staticInitializer;
+    case 'MethodExtractor': return M.FunctionKind.methodExtractor;
+    case 'NoSuchMethodDispatcher': return M.FunctionKind.noSuchMethodDispatcher;
+    case 'InvokeFieldDispatcher': return M.FunctionKind.invokeFieldDispatcher;
+    case 'Collected': return M.FunctionKind.collected;
+    case 'Native': return M.FunctionKind.native;
+    case 'Stub': return M.FunctionKind.stub;
+    case 'Tag': return M.FunctionKind.tag;
+    case 'SignatureFunction': return M.FunctionKind.signatureFunction;
   }
-
-  static FunctionKind kRegularFunction = new FunctionKind._internal('function');
-  static FunctionKind kClosureFunction = new FunctionKind._internal('closure function');
-  static FunctionKind kGetterFunction = new FunctionKind._internal('getter function');
-  static FunctionKind kSetterFunction = new FunctionKind._internal('setter function');
-  static FunctionKind kConstructor = new FunctionKind._internal('constructor');
-  static FunctionKind kImplicitGetterFunction = new FunctionKind._internal('implicit getter function');
-  static FunctionKind kImplicitSetterFunction = new FunctionKind._internal('implicit setter function');
-  static FunctionKind kImplicitStaticFinalGetter = new FunctionKind._internal('implicit static final getter');
-  static FunctionKind kIrregexpFunction = new FunctionKind._internal('ir regexp function');
-  static FunctionKind kStaticInitializer = new FunctionKind._internal('static initializer');
-  static FunctionKind kMethodExtractor = new FunctionKind._internal('method extractor');
-  static FunctionKind kNoSuchMethodDispatcher = new FunctionKind._internal('noSuchMethod dispatcher');
-  static FunctionKind kInvokeFieldDispatcher = new FunctionKind._internal('invoke field dispatcher');
-  static FunctionKind kCollected = new FunctionKind._internal('Collected');
-  static FunctionKind kNative = new FunctionKind._internal('Native');
-  static FunctionKind kTag = new FunctionKind._internal('Tag');
-  static FunctionKind kStub = new FunctionKind._internal('Stub');
-  static FunctionKind kSignatureFunction = new FunctionKind._internal('SignatureFunction');
-  static FunctionKind kUNKNOWN = new FunctionKind._internal('UNKNOWN');
+  Logger.root.severe('Unrecognized function kind: $value');
+  throw new FallThroughError();
 }
 
-class ServiceFunction extends HeapObject {
+class ServiceFunction extends HeapObject implements M.Function {
   // owner is a Library, Class, or ServiceFunction.
-  @observable ServiceObject dartOwner;
+  @observable M.ObjectRef dartOwner;
   @observable Library library;
   @observable bool isStatic;
   @observable bool isConst;
@@ -2674,7 +2636,7 @@
   @observable bool hasIntrinsic;
   @observable bool isRecognized;
   @observable bool isNative;
-  @observable FunctionKind kind;
+  @observable M.FunctionKind kind;
   @observable int deoptimizations;
   @observable String qualifiedName;
   @observable int usageCounter;
@@ -2683,7 +2645,6 @@
   @observable Instance icDataArray;
   @observable Field field;
 
-  bool get canCache => true;
   bool get immutable => false;
 
   ServiceFunction._empty(ServiceObject owner) : super._empty(owner);
@@ -2696,8 +2657,8 @@
     vmName = (map.containsKey('_vmName') ? map['_vmName'] : name);
 
     dartOwner = map['owner'];
-    kind = FunctionKind.fromJSON(map['_kind']);
-    isDart = kind.isDart();
+    kind = stringToFunctionKind(map['_kind']);
+    isDart = M.isDartFunction(kind);
 
     if (dartOwner is ServiceFunction) {
       ServiceFunction ownerFunction = dartOwner;
@@ -3304,7 +3265,6 @@
 class PcDescriptors extends ServiceObject {
   @observable Class clazz;
   @observable int size;
-  bool get canCache => false;
   bool get immutable => true;
   @reflectable final List<PcDescriptor> descriptors =
       new ObservableList<PcDescriptor>();
@@ -3347,7 +3307,6 @@
 class LocalVarDescriptors extends ServiceObject {
   @observable Class clazz;
   @observable int size;
-  bool get canCache => false;
   bool get immutable => true;
   @reflectable final List<LocalVarDescriptor> descriptors =
         new ObservableList<LocalVarDescriptor>();
@@ -3375,7 +3334,6 @@
 }
 
 class ObjectPool extends HeapObject {
-  bool get canCache => false;
   bool get immutable => false;
 
   @observable int length;
@@ -3401,7 +3359,6 @@
   @observable Instance argumentsDescriptor;
   @observable Instance entries;
 
-  bool get canCache => false;
   bool get immutable => false;
 
   ICData._empty(ServiceObjectOwner owner) : super._empty(owner);
@@ -3426,7 +3383,6 @@
   @observable String selector;
   @observable Instance argumentsDescriptor;
 
-  bool get canCache => false;
   bool get immutable => false;
 
   MegamorphicCache._empty(ServiceObjectOwner owner) : super._empty(owner);
@@ -3447,7 +3403,6 @@
 }
 
 class Instructions extends HeapObject {
-  bool get canCache => false;
   bool get immutable => true;
 
   @observable Code code;
@@ -3468,7 +3423,6 @@
 }
 
 class TokenStream extends HeapObject {
-  bool get canCache => false;
   bool get immutable => true;
 
   @observable String privateKey;
@@ -3550,32 +3504,20 @@
   }
 }
 
-class CodeKind {
-  final _value;
-  const CodeKind._internal(this._value);
-  String toString() => '$_value';
-  bool isSynthetic() => [Collected, Native, Tag].contains(this);
-  bool isDart() => !isSynthetic();
-  static CodeKind fromString(String s) {
-    if (s == 'Native') {
-      return Native;
-    } else if (s == 'Dart') {
-      return Dart;
-    } else if (s == 'Collected') {
-      return Collected;
-    } else if (s == 'Tag') {
-      return Tag;
-    } else if (s == 'Stub') {
-      return Stub;
-    }
-    Logger.root.severe("Unrecognized code kind: '$s'");
-    throw new FallThroughError();
+M.CodeKind stringToCodeKind(String s) {
+  if (s == 'Native') {
+    return M.CodeKind.native;
+  } else if (s == 'Dart') {
+    return M.CodeKind.dart;
+  } else if (s == 'Collected') {
+    return M.CodeKind.collected;
+  } else if (s == 'Tag') {
+    return M.CodeKind.tag;
+  } else if (s == 'Stub') {
+    return M.CodeKind.stub;
   }
-  static const Collected = const CodeKind._internal('Collected');
-  static const Dart = const CodeKind._internal('Dart');
-  static const Native = const CodeKind._internal('Native');
-  static const Stub = const CodeKind._internal('Stub');
-  static const Tag = const CodeKind._internal('Tag');
+  Logger.root.severe("Unrecognized code kind: '$s'");
+  throw new FallThroughError();
 }
 
 class CodeInlineInterval {
@@ -3586,8 +3528,8 @@
   CodeInlineInterval(this.start, this.end);
 }
 
-class Code extends HeapObject {
-  @observable CodeKind kind;
+class Code extends HeapObject implements M.Code {
+  @observable M.CodeKind kind;
   @observable ServiceObject objectPool;
   @observable ServiceFunction function;
   @observable Script script;
@@ -3624,7 +3566,7 @@
       // Already done.
       return;
     }
-    if (kind != CodeKind.Dart){
+    if (kind != M.CodeKind.dart){
       return;
     }
     if (function == null) {
@@ -3663,7 +3605,7 @@
     name = m['name'];
     vmName = (m.containsKey('_vmName') ? m['_vmName'] : name);
     isOptimized = m['_optimized'];
-    kind = CodeKind.fromString(m['kind']);
+    kind = stringToCodeKind(m['kind']);
     hasIntrinsic = m['_intrinsic'];
     isNative = m['_native'];
     if (mapIsRef) {
@@ -3683,7 +3625,7 @@
       descriptors = descriptors['members'];
       _processDescriptors(descriptors);
     }
-    hasDisassembly = (instructions.length != 0) && (kind == CodeKind.Dart);
+    hasDisassembly = (instructions.length != 0) && (kind == M.CodeKind.dart);
     inlinedFunctions.clear();
     var inlinedFunctionsTable = m['_inlinedFunctions'];
     var inlinedIntervals = m['_inlinedIntervals'];
@@ -3801,8 +3743,8 @@
     return (address >= startAddress) && (address < endAddress);
   }
 
-  @reflectable bool get isDartCode => (kind == CodeKind.Dart) ||
-                                      (kind == CodeKind.Stub);
+  @reflectable bool get isDartCode => (kind == M.CodeKind.dart) ||
+                                      (kind == M.CodeKind.stub);
 
   String toString() => 'Code($kind, $name)';
 }
@@ -3851,8 +3793,6 @@
 class Socket extends ServiceObject {
   Socket._empty(ServiceObjectOwner owner) : super._empty(owner);
 
-  bool get canCache => true;
-
   ServiceObject socketOwner;
 
   @reflectable bool get isPipe => (kind == SocketKind.Pipe);
@@ -3920,7 +3860,6 @@
   ServiceMetric._empty(ServiceObjectOwner owner) : super._empty(owner) {
   }
 
-  bool get canCache => true;
   bool get immutable => false;
 
   @observable bool recording = false;
diff --git a/runtime/observatory/observatory_sources.gypi b/runtime/observatory/observatory_sources.gypi
index 43099f1..adf1c26 100644
--- a/runtime/observatory/observatory_sources.gypi
+++ b/runtime/observatory/observatory_sources.gypi
@@ -33,19 +33,23 @@
     'lib/src/elements/action_link.dart',
     'lib/src/elements/action_link.html',
     'lib/src/elements/class_ref.dart',
-    'lib/src/elements/class_ref.html',
+    'lib/src/elements/class_ref_wrapper.dart',
+    'lib/src/elements/class_ref_as_value.dart',
+    'lib/src/elements/class_ref_as_value.html',
     'lib/src/elements/class_tree.dart',
     'lib/src/elements/class_tree.html',
     'lib/src/elements/class_view.dart',
     'lib/src/elements/class_view.html',
     'lib/src/elements/code_ref.dart',
-    'lib/src/elements/code_ref.html',
+    'lib/src/elements/code_ref_wrapper.dart',
     'lib/src/elements/code_view.dart',
     'lib/src/elements/code_view.html',
     'lib/src/elements/context_ref.dart',
     'lib/src/elements/context_ref.html',
     'lib/src/elements/context_view.dart',
     'lib/src/elements/context_view.html',
+    'lib/src/elements/containers/virtual_collection.dart',
+    'lib/src/elements/containers/virtual_tree.dart',
     'lib/src/elements/cpu_profile.dart',
     'lib/src/elements/cpu_profile.html',
     'lib/src/elements/css/shared.css',
@@ -54,7 +58,7 @@
     'lib/src/elements/debugger.dart',
     'lib/src/elements/debugger.html',
     'lib/src/elements/error_ref.dart',
-    'lib/src/elements/error_ref.html',
+    'lib/src/elements/error_ref_wrapper.dart',
     'lib/src/elements/error_view.dart',
     'lib/src/elements/error_view.html',
     'lib/src/elements/eval_box.dart',
@@ -66,13 +70,11 @@
     'lib/src/elements/field_view.dart',
     'lib/src/elements/field_view.html',
     'lib/src/elements/flag_list.dart',
-    'lib/src/elements/flag_list.html',
     'lib/src/elements/function_ref.dart',
-    'lib/src/elements/function_ref.html',
+    'lib/src/elements/function_ref_wrapper.dart',
     'lib/src/elements/function_view.dart',
     'lib/src/elements/function_view.html',
     'lib/src/elements/general_error.dart',
-    'lib/src/elements/general_error.html',
     'lib/src/elements/heap_map.dart',
     'lib/src/elements/heap_map.html',
     'lib/src/elements/heap_profile.dart',
@@ -109,7 +111,9 @@
     'lib/src/elements/json_view.dart',
     'lib/src/elements/json_view.html',
     'lib/src/elements/library_ref.dart',
-    'lib/src/elements/library_ref.html',
+    'lib/src/elements/library_ref_wrapper.dart',
+    'lib/src/elements/library_ref_as_value.dart',
+    'lib/src/elements/library_ref_as_value.html',
     'lib/src/elements/library_view.dart',
     'lib/src/elements/library_view.html',
     'lib/src/elements/objectstore_view.dart',
@@ -156,14 +160,16 @@
     'lib/src/elements/ports.html',
     'lib/src/elements/script_inset.dart',
     'lib/src/elements/script_inset.html',
+    'lib/src/elements/script_ref_wrapper.dart',
     'lib/src/elements/script_ref.dart',
-    'lib/src/elements/script_ref.html',
     'lib/src/elements/script_view.dart',
     'lib/src/elements/script_view.html',
     'lib/src/elements/service_ref.dart',
     'lib/src/elements/service_ref.html',
     'lib/src/elements/service_view.dart',
     'lib/src/elements/service_view.html',
+    'lib/src/elements/source_link_wrapper.dart',
+    'lib/src/elements/source_link.dart',
     'lib/src/elements/shims/binding.dart',
     'lib/src/elements/timeline_page.dart',
     'lib/src/elements/timeline_page.html',
@@ -173,9 +179,12 @@
     'lib/src/elements/vm_view.dart',
     'lib/src/elements/vm_view.html',
     'lib/src/mocks/exceptions/connection_exception.dart',
+    'lib/src/mocks/objects/class.dart',
+    'lib/src/mocks/objects/code.dart',
     'lib/src/mocks/objects/error.dart',
     'lib/src/mocks/objects/event.dart',
-    'lib/src/mocks/objects/class.dart',
+    'lib/src/mocks/objects/flag.dart',
+    'lib/src/mocks/objects/function.dart',
     'lib/src/mocks/objects/isolate.dart',
     'lib/src/mocks/objects/library.dart',
     'lib/src/mocks/objects/notification.dart',
@@ -184,15 +193,20 @@
     'lib/src/mocks/objects/target.dart',
     'lib/src/mocks/objects/vm.dart',
     'lib/src/mocks/repositories/crash_dump.dart',
+    'lib/src/mocks/repositories/flag.dart',
+    'lib/src/mocks/repositories/script.dart',
     'lib/src/mocks/repositories/notification.dart',
     'lib/src/mocks/repositories/target.dart',
     'lib/src/models/exceptions.dart',
     'lib/src/models/objects/breakpoint.dart',
     'lib/src/models/objects/class.dart',
+    'lib/src/models/objects/code.dart',
     'lib/src/models/objects/error.dart',
     'lib/src/models/objects/event.dart',
     'lib/src/models/objects/extension_data.dart',
+    'lib/src/models/objects/flag.dart',
     'lib/src/models/objects/frame.dart',
+    'lib/src/models/objects/function.dart',
     'lib/src/models/objects/instance.dart',
     'lib/src/models/objects/isolate.dart',
     'lib/src/models/objects/library.dart',
@@ -204,9 +218,14 @@
     'lib/src/models/objects/timeline_event.dart',
     'lib/src/models/objects/vm.dart',
     'lib/src/models/repositories/crash_dump.dart',
+    'lib/src/models/repositories/flag.dart',
     'lib/src/models/repositories/notification.dart',
+    'lib/src/models/repositories/script.dart',
     'lib/src/models/repositories/target.dart',
+    'lib/src/models/repository.dart',
+    'lib/src/repositories/flag.dart',
     'lib/src/repositories/notification.dart',
+    'lib/src/repositories/script.dart',
     'lib/src/repositories/settings.dart',
     'lib/src/repositories/target.dart',
     'lib/src/service/object.dart',
diff --git a/runtime/observatory/tests/observatory_ui/class_ref/element_test.dart b/runtime/observatory/tests/observatory_ui/class_ref/element_test.dart
new file mode 100644
index 0000000..ef812fd
--- /dev/null
+++ b/runtime/observatory/tests/observatory_ui/class_ref/element_test.dart
@@ -0,0 +1,29 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+import 'dart:html';
+import 'package:unittest/unittest.dart';
+import 'package:observatory/mocks.dart';
+import 'package:observatory/src/elements/class_ref.dart';
+
+main(){
+  ClassRefElement.tag.ensureRegistration();
+
+  final IsolateRefMock isolate = new IsolateRefMock(id: 'i-id', name: 'i-name');
+  final ClassRefMock cls = new ClassRefMock(id: 'c-id', name: 'c-name');
+  test('instantiation', () {
+    final ClassRefElement e = new ClassRefElement(isolate, cls);
+    expect(e, isNotNull, reason: 'element correctly created');
+    expect(e.isolate, equals(isolate));
+    expect(e.cls, equals(cls));
+  });
+  test('elements created after attachment', () async {
+    final ClassRefElement e = new ClassRefElement(isolate, cls);
+    document.body.append(e);
+    await e.onRendered.first;
+    expect(e.children.length, isNonZero, reason: 'has elements');
+    e.remove();
+    await e.onRendered.first;
+    expect(e.children.length, isZero, reason: 'is empty');
+  });
+}
diff --git a/runtime/observatory/tests/observatory_ui/class_ref/element_test.html b/runtime/observatory/tests/observatory_ui/class_ref/element_test.html
new file mode 100644
index 0000000..f0e956d
--- /dev/null
+++ b/runtime/observatory/tests/observatory_ui/class_ref/element_test.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <meta http-equiv="X-UA-Compatible" content="IE=edge">
+  <meta name="dart.unittest" content="full-stack-traces">
+  <style>
+     .unittest-table { font-family:monospace; border:1px; }
+     .unittest-pass { background: #6b3;}
+     .unittest-fail { background: #d55;}
+     .unittest-error { background: #a11;}
+  </style>
+  <script src="/packages/web_components/webcomponents.js"></script>
+  <script src="/packages/web_components/dart_support.js"></script>
+</head>
+<body>
+  <script type="text/javascript"
+      src="/root_dart/tools/testing/dart/test_controller.js"></script>
+  %TEST_SCRIPTS%
+</body>
+</html>
diff --git a/runtime/observatory/tests/observatory_ui/code_ref/element_test.dart b/runtime/observatory/tests/observatory_ui/code_ref/element_test.dart
new file mode 100644
index 0000000..0e2c9ee
--- /dev/null
+++ b/runtime/observatory/tests/observatory_ui/code_ref/element_test.dart
@@ -0,0 +1,29 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+import 'dart:html';
+import 'package:unittest/unittest.dart';
+import 'package:observatory/mocks.dart';
+import 'package:observatory/src/elements/code_ref.dart';
+
+main(){
+  CodeRefElement.tag.ensureRegistration();
+
+  final IsolateRefMock isolate = new IsolateRefMock(id: 'i-id', name: 'i-name');
+  final CodeRefMock code = new CodeRefMock(id: 'c-id', name: 'c-name');
+  test('instantiation', () {
+    final CodeRefElement e = new CodeRefElement(isolate, code);
+    expect(e, isNotNull, reason: 'element correctly created');
+    expect(e.isolate, equals(isolate));
+    expect(e.code, equals(code));
+  });
+  test('elements created after attachment', () async {
+    final CodeRefElement e = new CodeRefElement(isolate, code);
+    document.body.append(e);
+    await e.onRendered.first;
+    expect(e.children.length, isNonZero, reason: 'has elements');
+    e.remove();
+    await e.onRendered.first;
+    expect(e.children.length, isZero, reason: 'is empty');
+  });
+}
diff --git a/runtime/observatory/tests/observatory_ui/code_ref/element_test.html b/runtime/observatory/tests/observatory_ui/code_ref/element_test.html
new file mode 100644
index 0000000..f0e956d
--- /dev/null
+++ b/runtime/observatory/tests/observatory_ui/code_ref/element_test.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <meta http-equiv="X-UA-Compatible" content="IE=edge">
+  <meta name="dart.unittest" content="full-stack-traces">
+  <style>
+     .unittest-table { font-family:monospace; border:1px; }
+     .unittest-pass { background: #6b3;}
+     .unittest-fail { background: #d55;}
+     .unittest-error { background: #a11;}
+  </style>
+  <script src="/packages/web_components/webcomponents.js"></script>
+  <script src="/packages/web_components/dart_support.js"></script>
+</head>
+<body>
+  <script type="text/javascript"
+      src="/root_dart/tools/testing/dart/test_controller.js"></script>
+  %TEST_SCRIPTS%
+</body>
+</html>
diff --git a/runtime/observatory/tests/observatory_ui/error_ref/element_test.dart b/runtime/observatory/tests/observatory_ui/error_ref/element_test.dart
new file mode 100644
index 0000000..0495656
--- /dev/null
+++ b/runtime/observatory/tests/observatory_ui/error_ref/element_test.dart
@@ -0,0 +1,31 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+import 'dart:html';
+import 'package:unittest/unittest.dart';
+import 'package:observatory/models.dart';
+import 'package:observatory/mocks.dart';
+import 'package:observatory/src/elements/error_ref.dart';
+
+main() {
+  ErrorRefElement.tag.ensureRegistration();
+
+  final ErrorRef ref = new ErrorRefMock(id: 'id', message: 'fixed-error-m');
+  test('instantiation', () {
+    final ErrorRefElement e = new ErrorRefElement(ref);
+    expect(e, isNotNull, reason: 'element correctly created');
+    expect(e.error, equals(ref));
+  });
+  test('elements created after attachment', () async {
+    final ErrorRefElement e = new ErrorRefElement(ref);
+    document.body.append(e);
+    await e.onRendered.first;
+    expect(e.children.length, isNonZero, reason: 'has elements');
+    expect(e.innerHtml.contains(ref.message), isTrue,
+      reason: 'no message in the component');
+    e.remove();
+    await e.onRendered.first;
+    expect(e.children.length, isZero,
+      reason: 'is empty');
+  });
+}
diff --git a/runtime/observatory/tests/observatory_ui/error_ref/element_test.html b/runtime/observatory/tests/observatory_ui/error_ref/element_test.html
new file mode 100644
index 0000000..f0e956d
--- /dev/null
+++ b/runtime/observatory/tests/observatory_ui/error_ref/element_test.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <meta http-equiv="X-UA-Compatible" content="IE=edge">
+  <meta name="dart.unittest" content="full-stack-traces">
+  <style>
+     .unittest-table { font-family:monospace; border:1px; }
+     .unittest-pass { background: #6b3;}
+     .unittest-fail { background: #d55;}
+     .unittest-error { background: #a11;}
+  </style>
+  <script src="/packages/web_components/webcomponents.js"></script>
+  <script src="/packages/web_components/dart_support.js"></script>
+</head>
+<body>
+  <script type="text/javascript"
+      src="/root_dart/tools/testing/dart/test_controller.js"></script>
+  %TEST_SCRIPTS%
+</body>
+</html>
diff --git a/runtime/observatory/tests/observatory_ui/flag_list/element_test.dart b/runtime/observatory/tests/observatory_ui/flag_list/element_test.dart
new file mode 100644
index 0000000..e88dea6
--- /dev/null
+++ b/runtime/observatory/tests/observatory_ui/flag_list/element_test.dart
@@ -0,0 +1,60 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+import 'dart:html';
+import 'dart:async';
+import 'package:unittest/unittest.dart';
+import 'package:observatory/mocks.dart';
+import 'package:observatory/src/elements/flag_list.dart';
+import 'package:observatory/src/elements/nav/notify.dart';
+
+main() {
+  FlagListElement.tag.ensureRegistration();
+
+  final nTag = NavNotifyElement.tag.name;
+  const vm = const VMMock(name: 'vm');
+  final stream = new StreamController().stream;
+
+  group('instantiation', () {
+    test('default', () {
+      final FlagListElement e = new FlagListElement(vm, stream,
+          new FlagsRepositoryMock(),
+          new NotificationRepositoryMock());
+      expect(e, isNotNull, reason: 'element correctly created');
+    });
+  });
+  group('elements', () {
+    test('created after attachment', () async {
+      const modified = const [
+        const FlagMock(name: 'f1', comment: 'c1', modified: true),
+      ];
+      const unmodifed = const [
+        const FlagMock(name: 'f2', comment: 'c2', modified: false),
+        const FlagMock(name: 'f3', comment: 'c3', modified: false),
+      ];
+      final flags = new List.unmodifiable([]..addAll(modified)
+                                            ..addAll(unmodifed));
+      final FlagListElement e = new FlagListElement(vm, stream,
+          new FlagsRepositoryMock(list: expectAsync((input) async {
+            expect(input, equals(vm));
+            return flags;
+          }, count: 1)), new NotificationRepositoryMock());
+      document.body.append(e);
+      await e.onRendered.first;
+      expect(e.children.length, isNonZero, reason: 'has elements');
+      expect(e.querySelectorAll(nTag).length, equals(1));
+      expect(e.querySelectorAll('.flag').length, equals(flags.length));
+      expect(e.querySelectorAll('.flag.modified').length,
+          equals(modified.length));
+      expect(e.querySelectorAll('.flag.unmodified').length,
+          equals(unmodifed.length));
+      expect(e.querySelectorAll('.flag').length, equals(flags.length));
+      expect(e.querySelectorAll('.comment').length, equals(flags.length));
+      expect(e.querySelectorAll('.name').length, equals(flags.length));
+      expect(e.querySelectorAll('.value').length, equals(flags.length));
+      e.remove();
+      await e.onRendered.first;
+      expect(e.children.length, isZero, reason: 'is empty');
+    });
+  });
+}
diff --git a/runtime/observatory/tests/observatory_ui/flag_list/element_test.html b/runtime/observatory/tests/observatory_ui/flag_list/element_test.html
new file mode 100644
index 0000000..f0e956d
--- /dev/null
+++ b/runtime/observatory/tests/observatory_ui/flag_list/element_test.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <meta http-equiv="X-UA-Compatible" content="IE=edge">
+  <meta name="dart.unittest" content="full-stack-traces">
+  <style>
+     .unittest-table { font-family:monospace; border:1px; }
+     .unittest-pass { background: #6b3;}
+     .unittest-fail { background: #d55;}
+     .unittest-error { background: #a11;}
+  </style>
+  <script src="/packages/web_components/webcomponents.js"></script>
+  <script src="/packages/web_components/dart_support.js"></script>
+</head>
+<body>
+  <script type="text/javascript"
+      src="/root_dart/tools/testing/dart/test_controller.js"></script>
+  %TEST_SCRIPTS%
+</body>
+</html>
diff --git a/runtime/observatory/tests/observatory_ui/function_ref/element_test.dart b/runtime/observatory/tests/observatory_ui/function_ref/element_test.dart
new file mode 100644
index 0000000..a647d3d
--- /dev/null
+++ b/runtime/observatory/tests/observatory_ui/function_ref/element_test.dart
@@ -0,0 +1,30 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+import 'dart:html';
+import 'package:unittest/unittest.dart';
+import 'package:observatory/mocks.dart';
+import 'package:observatory/src/elements/function_ref.dart';
+
+main(){
+  FunctionRefElement.tag.ensureRegistration();
+
+  final IsolateRefMock isolate = new IsolateRefMock(id: 'i-id', name: 'i-name');
+  final FunctionRefMock function = new FunctionRefMock(id: 'f-id',
+      name: 'f-name');
+  test('instantiation', () {
+    final FunctionRefElement e = new FunctionRefElement(isolate, function);
+    expect(e, isNotNull, reason: 'element correctly created');
+    expect(e.isolate, equals(isolate));
+    expect(e.function, equals(function));
+  });
+  test('elements created after attachment', () async {
+    final FunctionRefElement e = new FunctionRefElement(isolate, function);
+    document.body.append(e);
+    await e.onRendered.first;
+    expect(e.children.length, isNonZero, reason: 'has elements');
+    e.remove();
+    await e.onRendered.first;
+    expect(e.children.length, isZero, reason: 'is empty');
+  });
+}
diff --git a/runtime/observatory/tests/observatory_ui/function_ref/element_test.html b/runtime/observatory/tests/observatory_ui/function_ref/element_test.html
new file mode 100644
index 0000000..f0e956d
--- /dev/null
+++ b/runtime/observatory/tests/observatory_ui/function_ref/element_test.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <meta http-equiv="X-UA-Compatible" content="IE=edge">
+  <meta name="dart.unittest" content="full-stack-traces">
+  <style>
+     .unittest-table { font-family:monospace; border:1px; }
+     .unittest-pass { background: #6b3;}
+     .unittest-fail { background: #d55;}
+     .unittest-error { background: #a11;}
+  </style>
+  <script src="/packages/web_components/webcomponents.js"></script>
+  <script src="/packages/web_components/dart_support.js"></script>
+</head>
+<body>
+  <script type="text/javascript"
+      src="/root_dart/tools/testing/dart/test_controller.js"></script>
+  %TEST_SCRIPTS%
+</body>
+</html>
diff --git a/runtime/observatory/tests/observatory_ui/general_error/element_test.dart b/runtime/observatory/tests/observatory_ui/general_error/element_test.dart
new file mode 100644
index 0000000..31a9031
--- /dev/null
+++ b/runtime/observatory/tests/observatory_ui/general_error/element_test.dart
@@ -0,0 +1,61 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+import 'dart:html';
+import 'package:unittest/unittest.dart';
+import 'package:observatory/mocks.dart';
+import 'package:observatory/src/elements/general_error.dart';
+import 'package:observatory/src/elements/nav/notify.dart';
+
+main() {
+  GeneralErrorElement.tag.ensureRegistration();
+
+  final nTag = NavNotifyElement.tag.name;
+  final notifications = new NotificationRepositoryMock();
+  final String message = 'content-of-the-message';
+
+  group('instantiation', () {
+    test('default', () {
+      final GeneralErrorElement e = new GeneralErrorElement(notifications);
+      expect(e, isNotNull, reason: 'element correctly created');
+      expect(e.message, isNotNull, reason: 'message should not be null');
+      expect(e.message, equals(''), reason: 'message should be empty');
+    });
+    test('message', () {
+      final GeneralErrorElement e = new GeneralErrorElement(notifications,
+          message: message);
+      expect(e, isNotNull, reason: 'element correctly created');
+      expect(e.message, isNotNull, reason: 'message should not be null');
+      expect(e.message, equals(message), reason: 'message should be the same');
+    });
+  });
+  group('elements', () {
+    test('created after attachment', () async {
+      final GeneralErrorElement e = new GeneralErrorElement(notifications);
+      document.body.append(e);
+      await e.onRendered.first;
+      expect(e.children.length, isNonZero, reason: 'has elements');
+      expect(e.querySelectorAll(nTag).length, equals(1));
+      e.remove();
+      await e.onRendered.first;
+      expect(e.children.length, isZero, reason: 'is empty');
+    });
+    test('react to message change', () async {
+      final GeneralErrorElement e = new GeneralErrorElement(notifications);
+      document.body.append(e);
+      await e.onRendered.first;
+      expect(e.innerHtml.contains(message), isFalse,
+          reason: 'should not contain');
+      e.message = message;
+      await e.onRendered.first;
+      expect(e.innerHtml.contains(message), isTrue,
+          reason: 'should contain');
+      e.message = '';
+      await e.onRendered.first;
+      expect(e.innerHtml.contains(message), isFalse,
+          reason: 'should not contain');
+      e.remove();
+      await e.onRendered.first;
+    });
+  });
+}
diff --git a/runtime/observatory/tests/observatory_ui/general_error/element_test.html b/runtime/observatory/tests/observatory_ui/general_error/element_test.html
new file mode 100644
index 0000000..f0e956d
--- /dev/null
+++ b/runtime/observatory/tests/observatory_ui/general_error/element_test.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <meta http-equiv="X-UA-Compatible" content="IE=edge">
+  <meta name="dart.unittest" content="full-stack-traces">
+  <style>
+     .unittest-table { font-family:monospace; border:1px; }
+     .unittest-pass { background: #6b3;}
+     .unittest-fail { background: #d55;}
+     .unittest-error { background: #a11;}
+  </style>
+  <script src="/packages/web_components/webcomponents.js"></script>
+  <script src="/packages/web_components/dart_support.js"></script>
+</head>
+<body>
+  <script type="text/javascript"
+      src="/root_dart/tools/testing/dart/test_controller.js"></script>
+  %TEST_SCRIPTS%
+</body>
+</html>
diff --git a/runtime/observatory/tests/observatory_ui/isolate_ref/element_test.dart b/runtime/observatory/tests/observatory_ui/isolate_ref/element_test.dart
new file mode 100644
index 0000000..c7d64a4
--- /dev/null
+++ b/runtime/observatory/tests/observatory_ui/isolate_ref/element_test.dart
@@ -0,0 +1,69 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+import 'dart:html';
+import 'dart:async';
+import 'package:unittest/unittest.dart';
+import 'package:observatory/models.dart';
+import 'package:observatory/mocks.dart';
+import 'package:observatory/src/elements/isolate_ref.dart';
+
+main(){
+  IsolateRefElement.tag.ensureRegistration();
+
+  StreamController<IsolateUpdateEvent> updatesController;
+  final IsolateRefMock ref = new IsolateRefMock(id: 'id', name: 'old-name');
+  final IsolateMock obj = new IsolateMock(id: 'id', name: 'new-name');
+  setUp(() {
+    updatesController = new StreamController<IsolateUpdateEvent>();
+  });
+  group('instantiation', () {
+    test('IsolateRef', () {
+      final IsolateRefElement e = new IsolateRefElement(ref,
+                                      updatesController.stream);
+      expect(e, isNotNull, reason: 'element correctly created');
+      expect(e.isolate, equals(ref));
+    });
+    test('Isolate', () {
+      final IsolateRefElement e = new IsolateRefElement(obj,
+                                      updatesController.stream);
+      expect(e, isNotNull, reason: 'element correctly created');
+      expect(e.isolate, equals(obj));
+    });
+  });
+  test('elements created after attachment', () async {
+    final IsolateRefElement e = new IsolateRefElement(ref,
+                                    updatesController.stream);
+    document.body.append(e);
+    await e.onRendered.first;
+    expect(e.children.length, isNonZero, reason: 'has elements');
+    e.remove();
+    await e.onRendered.first;
+    expect(e.children.length, isZero, reason: 'is empty');
+  });
+  group('updates', () {
+    test('are correctly listen', () async {
+      final IsolateRefElement e = new IsolateRefElement(ref,
+                                      updatesController.stream);
+      expect(updatesController.hasListener, isFalse);
+      document.body.append(e);
+      await e.onRendered.first;
+      expect(updatesController.hasListener, isTrue);
+      e.remove();
+      await e.onRendered.first;
+      expect(updatesController.hasListener, isFalse);
+    });
+    test('have effects', () async {
+      final IsolateRefElement e = new IsolateRefElement(ref,
+                                      updatesController.stream);
+      document.body.append(e);
+      await e.onRendered.first;
+      expect(e.innerHtml.contains(ref.id), isTrue);
+      updatesController.add(new IsolateUpdateEventMock(isolate: obj));
+      await e.onRendered.first;
+      expect(e.innerHtml.contains(ref.name), isFalse);
+      expect(e.innerHtml.contains(obj.name), isTrue);
+      e.remove();
+    });
+  });
+}
diff --git a/runtime/observatory/tests/observatory_ui/isolate_ref/element_test.html b/runtime/observatory/tests/observatory_ui/isolate_ref/element_test.html
new file mode 100644
index 0000000..f0e956d
--- /dev/null
+++ b/runtime/observatory/tests/observatory_ui/isolate_ref/element_test.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <meta http-equiv="X-UA-Compatible" content="IE=edge">
+  <meta name="dart.unittest" content="full-stack-traces">
+  <style>
+     .unittest-table { font-family:monospace; border:1px; }
+     .unittest-pass { background: #6b3;}
+     .unittest-fail { background: #d55;}
+     .unittest-error { background: #a11;}
+  </style>
+  <script src="/packages/web_components/webcomponents.js"></script>
+  <script src="/packages/web_components/dart_support.js"></script>
+</head>
+<body>
+  <script type="text/javascript"
+      src="/root_dart/tools/testing/dart/test_controller.js"></script>
+  %TEST_SCRIPTS%
+</body>
+</html>
diff --git a/runtime/observatory/tests/observatory_ui/library_ref/element_test.dart b/runtime/observatory/tests/observatory_ui/library_ref/element_test.dart
new file mode 100644
index 0000000..cb33f6b
--- /dev/null
+++ b/runtime/observatory/tests/observatory_ui/library_ref/element_test.dart
@@ -0,0 +1,29 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+import 'dart:html';
+import 'package:unittest/unittest.dart';
+import 'package:observatory/mocks.dart';
+import 'package:observatory/src/elements/library_ref.dart';
+
+main(){
+  LibraryRefElement.tag.ensureRegistration();
+
+  final IsolateRefMock isolate = new IsolateRefMock(id: 'i-id', name: 'i-name');
+  final LibraryRefMock library = new LibraryRefMock(id: 'c-id', name: 'c-name');
+  test('instantiation', () {
+    final LibraryRefElement e = new LibraryRefElement(isolate, library);
+    expect(e, isNotNull, reason: 'element correctly created');
+    expect(e.isolate, equals(isolate));
+    expect(e.library, equals(library));
+  });
+  test('elements created after attachment', () async {
+    final LibraryRefElement e = new LibraryRefElement(isolate, library);
+    document.body.append(e);
+    await e.onRendered.first;
+    expect(e.children.length, isNonZero, reason: 'has elements');
+    e.remove();
+    await e.onRendered.first;
+    expect(e.children.length, isZero, reason: 'is empty');
+  });
+}
diff --git a/runtime/observatory/tests/observatory_ui/library_ref/element_test.html b/runtime/observatory/tests/observatory_ui/library_ref/element_test.html
new file mode 100644
index 0000000..f0e956d
--- /dev/null
+++ b/runtime/observatory/tests/observatory_ui/library_ref/element_test.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <meta http-equiv="X-UA-Compatible" content="IE=edge">
+  <meta name="dart.unittest" content="full-stack-traces">
+  <style>
+     .unittest-table { font-family:monospace; border:1px; }
+     .unittest-pass { background: #6b3;}
+     .unittest-fail { background: #d55;}
+     .unittest-error { background: #a11;}
+  </style>
+  <script src="/packages/web_components/webcomponents.js"></script>
+  <script src="/packages/web_components/dart_support.js"></script>
+</head>
+<body>
+  <script type="text/javascript"
+      src="/root_dart/tools/testing/dart/test_controller.js"></script>
+  %TEST_SCRIPTS%
+</body>
+</html>
diff --git a/runtime/observatory/tests/observatory_ui/script_ref/element_test.dart b/runtime/observatory/tests/observatory_ui/script_ref/element_test.dart
new file mode 100644
index 0000000..eda7d49
--- /dev/null
+++ b/runtime/observatory/tests/observatory_ui/script_ref/element_test.dart
@@ -0,0 +1,38 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+import 'dart:html';
+import 'package:unittest/unittest.dart';
+import 'package:observatory/mocks.dart';
+import 'package:observatory/models.dart' as M;
+import 'package:observatory/src/elements/script_ref.dart';
+
+main() {
+  ScriptRefElement.tag.ensureRegistration();
+
+  final M.IsolateRef isolate = const IsolateRefMock(id: 'isolate-id');
+  final M.ScriptRef ref = const ScriptRefMock(id: 'script-id',
+                                  uri: 'package/filename.dart');
+  group('instantiation', () {
+    test('no position', () {
+      final ScriptRefElement e = new ScriptRefElement(isolate, ref);
+      expect(e, isNotNull, reason: 'element correctly created');
+      expect(e.isolate, equals(isolate));
+      expect(e.script, equals(ref));
+    });
+  });
+  test('elements created after attachment', () async {
+    final ScriptRefElement e = new ScriptRefElement(isolate, ref);
+    document.body.append(e);
+    await e.onRendered.first;
+    expect(e.children.length, isNonZero, reason: 'has elements');
+    expect(e.innerHtml.contains(isolate.id), isTrue,
+      reason: 'no message in the component');
+    expect(e.innerHtml.contains('filename.dart'), isTrue,
+      reason: 'no message in the component');
+    e.remove();
+    await e.onRendered.first;
+    expect(e.children.length, isZero,
+      reason: 'is empty');
+  });
+}
diff --git a/runtime/observatory/tests/observatory_ui/script_ref/element_test.html b/runtime/observatory/tests/observatory_ui/script_ref/element_test.html
new file mode 100644
index 0000000..f0e956d
--- /dev/null
+++ b/runtime/observatory/tests/observatory_ui/script_ref/element_test.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <meta http-equiv="X-UA-Compatible" content="IE=edge">
+  <meta name="dart.unittest" content="full-stack-traces">
+  <style>
+     .unittest-table { font-family:monospace; border:1px; }
+     .unittest-pass { background: #6b3;}
+     .unittest-fail { background: #d55;}
+     .unittest-error { background: #a11;}
+  </style>
+  <script src="/packages/web_components/webcomponents.js"></script>
+  <script src="/packages/web_components/dart_support.js"></script>
+</head>
+<body>
+  <script type="text/javascript"
+      src="/root_dart/tools/testing/dart/test_controller.js"></script>
+  %TEST_SCRIPTS%
+</body>
+</html>
diff --git a/runtime/observatory/tests/observatory_ui/source_link/element_test.dart b/runtime/observatory/tests/observatory_ui/source_link/element_test.dart
new file mode 100644
index 0000000..2d4cfba
--- /dev/null
+++ b/runtime/observatory/tests/observatory_ui/source_link/element_test.dart
@@ -0,0 +1,46 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+import 'dart:html';
+import 'package:unittest/unittest.dart';
+import 'package:observatory/mocks.dart';
+import 'package:observatory/models.dart' as M;
+import 'package:observatory/src/elements/source_link.dart';
+
+main() {
+  SourceLinkElement.tag.ensureRegistration();
+
+  final M.IsolateRef isolate = const IsolateRefMock(id: 'isolate-id');
+  final M.Script script = new  ScriptMock(id: 'script-id',
+                                  uri: 'package/filename.dart',
+                                  tokenToLine: (int token) => 1,
+                                  tokenToCol: (int token) => 2);
+  final M.SourceLocation location = new SourceLocationMock(script: script,
+                                  tokenPos: 0, endTokenPos: 1);
+  M.ScriptRepository repository;
+  setUp(() {
+    repository = new ScriptRepositoryMock({ 'script-id': script });
+  });
+  test('instantiation', () {
+    final SourceLinkElement e = new SourceLinkElement(isolate, location,
+                                                               repository);
+    expect(e, isNotNull, reason: 'element correctly created');
+    expect(e.isolate, equals(isolate));
+    expect(e.location, equals(location));
+  });
+  test('elements created after attachment', () async {
+    final SourceLinkElement e = new SourceLinkElement(isolate, location,
+                                                               repository);
+    document.body.append(e);
+    await e.onRendered.first;
+    expect(e.children.length, isNonZero, reason: 'has elements');
+    expect(e.innerHtml.contains(isolate.id), isTrue,
+      reason: 'no message in the component');
+    expect(e.innerHtml.contains('filename.dart'), isTrue,
+      reason: 'no message in the component');
+    e.remove();
+    await e.onRendered.first;
+    expect(e.children.length, isZero,
+      reason: 'is empty');
+  });
+}
diff --git a/runtime/observatory/tests/observatory_ui/source_link/element_test.html b/runtime/observatory/tests/observatory_ui/source_link/element_test.html
new file mode 100644
index 0000000..f0e956d
--- /dev/null
+++ b/runtime/observatory/tests/observatory_ui/source_link/element_test.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <meta http-equiv="X-UA-Compatible" content="IE=edge">
+  <meta name="dart.unittest" content="full-stack-traces">
+  <style>
+     .unittest-table { font-family:monospace; border:1px; }
+     .unittest-pass { background: #6b3;}
+     .unittest-fail { background: #d55;}
+     .unittest-error { background: #a11;}
+  </style>
+  <script src="/packages/web_components/webcomponents.js"></script>
+  <script src="/packages/web_components/dart_support.js"></script>
+</head>
+<body>
+  <script type="text/javascript"
+      src="/root_dart/tools/testing/dart/test_controller.js"></script>
+  %TEST_SCRIPTS%
+</body>
+</html>
diff --git a/runtime/observatory/tests/service/dev_fs_weird_char_test.dart b/runtime/observatory/tests/service/dev_fs_weird_char_test.dart
new file mode 100644
index 0000000..9ee2412
--- /dev/null
+++ b/runtime/observatory/tests/service/dev_fs_weird_char_test.dart
@@ -0,0 +1,57 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+// VMOptions=--error_on_bad_type --error_on_bad_override
+
+import 'dart:convert';
+import 'package:observatory/service_io.dart';
+import 'package:unittest/unittest.dart';
+import 'test_helper.dart';
+
+var tests = [
+  // Write a file with the ? character in the filename.
+  (VM vm) async {
+    var fsId = 'test';
+    var filePath = '/foo/bar?dat';
+    var fileContents = BASE64.encode(UTF8.encode('fileContents'));
+
+    var result;
+    // Create DevFS.
+    result = await vm.invokeRpcNoUpgrade('_createDevFS', { 'fsName': fsId });
+    expect(result['type'], equals('FileSystem'));
+    expect(result['name'], equals(fsId));
+    expect(result['uri'], new isInstanceOf<String>());
+
+    // Write the file.
+    result = await vm.invokeRpcNoUpgrade('_writeDevFSFile', {
+        'fsName': fsId,
+        'path': filePath,
+        'fileContents': fileContents
+    });
+    expect(result['type'], equals('Success'));
+
+    // Read the file back.
+    result = await vm.invokeRpcNoUpgrade('_readDevFSFile', {
+        'fsName': fsId,
+        'path': filePath,
+    });
+    expect(result['type'], equals('FSFile'));
+    expect(result['fileContents'], equals(fileContents));
+
+    // List all the files in the file system.
+    result = await vm.invokeRpcNoUpgrade('_listDevFSFiles', {
+        'fsName': fsId,
+    });
+    expect(result['type'], equals('FSFileList'));
+    expect(result['files'].length, equals(1));
+    expect(result['files'][0]['name'], equals('/foo/bar?dat'));
+
+    // Delete DevFS.
+    result = await vm.invokeRpcNoUpgrade('_deleteDevFS', {
+        'fsName': fsId,
+    });
+    expect(result['type'], equals('Success'));
+  },
+];
+
+main(args) async => runVMTests(args, tests);
diff --git a/runtime/observatory/tests/service/regexp_function_test.dart b/runtime/observatory/tests/service/regexp_function_test.dart
new file mode 100644
index 0000000..4736266
--- /dev/null
+++ b/runtime/observatory/tests/service/regexp_function_test.dart
@@ -0,0 +1,60 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+// VMOptions=
+// VMOptions=--interpret_irregexp
+
+import 'package:observatory/service_io.dart';
+import 'package:unittest/unittest.dart';
+import 'test_helper.dart';
+
+var regex0;
+var regex;
+
+void script() {
+  // Check the internal NUL doesn't trip up the name scrubbing in the vm.
+  regex0 = new RegExp("with internal \u{0} NUL");
+  regex = new RegExp(r"(\w+)");
+  String str = "Parse my string";
+  Iterable<Match> matches = regex.allMatches(str);  // Run to generate bytecode.
+  expect(matches.length, equals(3));
+}
+
+var tests = [
+
+(Isolate isolate) async {
+  Library lib = isolate.rootLibrary;
+  await lib.load();
+
+  Field field0 = lib.variables.singleWhere((v) => v.name == 'regex0');
+  await field0.load();  // No crash due to embedded NUL.
+
+  Field field = lib.variables.singleWhere((v) => v.name == 'regex');
+  await field.load();
+  Instance regex = field.staticValue;
+  expect(regex.isInstance, isTrue);
+  expect(regex.isRegExp, isTrue);
+  await regex.load();
+
+  if (regex.oneByteFunction == null) {
+    // Running with interpreted regexp.
+    var b1 = await regex.oneByteBytecode.load();
+    expect(b1.isTypedData, isTrue);
+    var b2 = await regex.twoByteBytecode.load();
+    expect(b2.isTypedData, isFalse);  // No two-byte string subject was used.
+  } else {
+    // Running with compiled regexp.
+    var f1 = await regex.oneByteFunction.load();
+    expect(f1 is ServiceFunction, isTrue);
+    var f2 = await regex.twoByteFunction.load();
+    expect(f2 is ServiceFunction, isTrue);
+    var f3 = await regex.externalOneByteFunction.load();
+    expect(f3 is ServiceFunction, isTrue);
+    var f4 = await regex.externalTwoByteFunction.load();
+    expect(f4 is ServiceFunction, isTrue);
+  }
+}
+
+];
+
+main(args) => runIsolateTests(args, tests, testeeBefore: script);
diff --git a/runtime/observatory/tests/service/service.status b/runtime/observatory/tests/service/service.status
index 0e627a0..8e9cc6c 100644
--- a/runtime/observatory/tests/service/service.status
+++ b/runtime/observatory/tests/service/service.status
@@ -55,6 +55,9 @@
 get_cpu_profile_timeline_rpc_test: RuntimeError # Profiling unimplemented.
 implicit_getter_setter_test: RuntimeError # Field guards unimplemented.
 
-[ $hot_reload ]
+[ $hot_reload || $hot_reload_rollback ]
 # Skip all service tests because random reloads interfere.
 *: SkipByDesign # The service tests should run without being reloaded.
+
+[ $system == windows ]
+dev_fs_weird_char_test: Skip # Windows disallows question mark in paths
\ No newline at end of file
diff --git a/runtime/observatory/tests/service/test_helper.dart b/runtime/observatory/tests/service/test_helper.dart
index 15b1de4..4828557 100644
--- a/runtime/observatory/tests/service/test_helper.dart
+++ b/runtime/observatory/tests/service/test_helper.dart
@@ -333,6 +333,7 @@
         var pid = process.process.pid;
         var wait = new Duration(seconds: 10);
         print("Testee has pid $pid, waiting $wait before continuing");
+        sleep(wait);
       }
       serviceWebsocketAddress = 'ws://localhost:$port/ws';
       serviceHttpAddress = 'http://localhost:$port';
diff --git a/runtime/platform/text_buffer.cc b/runtime/platform/text_buffer.cc
index 9cbb577..5b4cc05 100644
--- a/runtime/platform/text_buffer.cc
+++ b/runtime/platform/text_buffer.cc
@@ -57,6 +57,7 @@
   buf_[msg_len_] = '\0';
 }
 
+
 intptr_t TextBuffer::Printf(const char* format, ...) {
   va_list args;
   va_start(args, format);
@@ -79,6 +80,7 @@
   return len;
 }
 
+
 // Write a UTF-32 code unit so it can be read by a JSON parser in a string
 // literal. Use official encoding from JSON specification. http://json.org/
 void TextBuffer::EscapeAndAddCodeUnit(uint32_t codeunit) {
@@ -119,6 +121,7 @@
   }
 }
 
+
 // Write an incomplete UTF-16 code unit so it can be read by a JSON parser in a
 // string literal.
 void TextBuffer::EscapeAndAddUTF16CodeUnit(uint16_t codeunit) {
diff --git a/runtime/tests/vm/vm.status b/runtime/tests/vm/vm.status
index 364613f..ebb0df9 100644
--- a/runtime/tests/vm/vm.status
+++ b/runtime/tests/vm/vm.status
@@ -157,6 +157,6 @@
 # This test is meaningless for DBC as allocation stubs are not used.
 cc/RegenerateAllocStubs: Skip
 
-[ $hot_reload ]
+[ $hot_reload || $hot_reload_rollback ]
 dart/spawn_shutdown_test: Skip # We can shutdown an isolate before it reloads.
 dart/spawn_infinite_loop_test: Skip # We can shutdown an isolate before it reloads.
diff --git a/runtime/vm/become.cc b/runtime/vm/become.cc
index a4d9fd1..accca31 100644
--- a/runtime/vm/become.cc
+++ b/runtime/vm/become.cc
@@ -148,17 +148,50 @@
 };
 
 
+// On IA32, object pointers are embedded directly in the instruction stream,
+// which is normally write-protected, so we need to make it temporarily writable
+// to forward the pointers. On all other architectures, object pointers are
+// accessed through ObjectPools.
+#if defined(TARGET_ARCH_IA32)
+class WritableCodeLiteralsScope : public ValueObject {
+ public:
+  explicit WritableCodeLiteralsScope(Heap* heap) : heap_(heap) {
+    if (FLAG_write_protect_code) {
+      heap_->WriteProtectCode(false);
+    }
+  }
+
+  ~WritableCodeLiteralsScope() {
+    if (FLAG_write_protect_code) {
+      heap_->WriteProtectCode(true);
+    }
+  }
+
+ private:
+  Heap* heap_;
+};
+#else
+class WritableCodeLiteralsScope : public ValueObject {
+ public:
+  explicit WritableCodeLiteralsScope(Heap* heap) { }
+  ~WritableCodeLiteralsScope() { }
+};
+#endif
+
+
 void Become::MakeDummyObject(const Instance& instance) {
   // Make the forward pointer point to itself.
   // This is needed to distinguish it from a real forward object.
   ForwardObjectTo(instance.raw(), instance.raw());
 }
 
+
 static bool IsDummyObject(RawObject* object) {
   if (!object->IsForwardingCorpse()) return false;
   return GetForwardedObject(object) == object;
 }
 
+
 void Become::ElementsForwardIdentity(const Array& before, const Array& after) {
   Thread* thread = Thread::Current();
   Isolate* isolate = thread->isolate();
@@ -210,9 +243,12 @@
     isolate->VisitWeakPersistentHandles(&handle_visitor);
 
     //   Heap pointers (may require updating the remembered set)
-    ForwardHeapPointersVisitor object_visitor(&pointer_visitor);
-    heap->VisitObjects(&object_visitor);
-    pointer_visitor.VisitingObject(NULL);
+    {
+      WritableCodeLiteralsScope writable_code(heap);
+      ForwardHeapPointersVisitor object_visitor(&pointer_visitor);
+      heap->VisitObjects(&object_visitor);
+      pointer_visitor.VisitingObject(NULL);
+    }
 
 #if !defined(PRODUCT)
     tds.SetNumArguments(2);
diff --git a/runtime/vm/code_generator.cc b/runtime/vm/code_generator.cc
index b0b3a9c1..bc9689c 100644
--- a/runtime/vm/code_generator.cc
+++ b/runtime/vm/code_generator.cc
@@ -1357,13 +1357,13 @@
   }
   if (do_reload) {
 #ifndef PRODUCT
+    JSONStream js;
     // Maybe adjust the rate of future reloads.
     isolate->MaybeIncreaseReloadEveryNStackOverflowChecks();
     // Issue a reload.
-    isolate->ReloadSources(true /* force_reload */);
-    const Error& error = Error::Handle(isolate->sticky_reload_error());
-    if (!error.IsNull()) {
-      FATAL1("*** Isolate reload failed: %s\n", error.ToErrorCString());
+    bool success = isolate->ReloadSources(&js, true /* force_reload */);
+    if (!success) {
+      FATAL1("*** Isolate reload failed:\n%s\n", js.ToCString());
     }
 #endif
   }
diff --git a/runtime/vm/find_code_object_test.cc b/runtime/vm/find_code_object_test.cc
index b7e437b..2f53147 100644
--- a/runtime/vm/find_code_object_test.cc
+++ b/runtime/vm/find_code_object_test.cc
@@ -13,19 +13,20 @@
 
 namespace dart {
 
-VM_TEST_CASE(FindCodeObject) {
 #if defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_X64)
-  const int kLoopCount = 50000;
-  const int kScriptSize = 512 * KB;
+static const int kScriptSize = 512 * KB;
+static const int kLoopCount = 50000;
 #elif defined(TARGET_ARCH_DBC)
-  const int kLoopCount = 60000;
-  const int kScriptSize = 1 * MB;
+static const int kScriptSize = 1 * MB;
+static const int kLoopCount = 60000;
 #else
-  const int kLoopCount = 25000;
-  const int kScriptSize = 512 * KB;
+static const int kScriptSize = 512 * KB;
+static const int kLoopCount = 25000;
 #endif
+static char scriptChars[kScriptSize];
+
+VM_TEST_CASE(FindCodeObject) {
   const int kNumFunctions = 1024;
-  char scriptChars[kScriptSize];
 
   // Get access to the code index table.
   Isolate* isolate = Isolate::Current();
diff --git a/runtime/vm/isolate.cc b/runtime/vm/isolate.cc
index 27a3529..32dc967 100644
--- a/runtime/vm/isolate.cc
+++ b/runtime/vm/isolate.cc
@@ -660,12 +660,6 @@
 
 MessageHandler::MessageStatus IsolateMessageHandler::ProcessUnhandledException(
     const Error& result) {
-  NOT_IN_PRODUCT(
-    if (I->IsReloading()) {
-      I->ReportReloadError(result);
-      return kOK;
-    }
-  )
   // Generate the error and stacktrace strings for the error message.
   String& exc_str = String::Handle(T->zone());
   String& stacktrace_str = String::Handle(T->zone());
@@ -827,7 +821,6 @@
       tag_table_(GrowableObjectArray::null()),
       deoptimized_code_array_(GrowableObjectArray::null()),
       sticky_error_(Error::null()),
-      sticky_reload_error_(Error::null()),
       background_compiler_(NULL),
       background_compiler_disabled_depth_(0),
       pending_service_extension_calls_(GrowableObjectArray::null()),
@@ -1090,26 +1083,28 @@
 
 
 #ifndef PRODUCT
-void Isolate::ReportReloadError(const Error& error) {
-  ASSERT(IsReloading());
-  reload_context_->AbortReload(error);
-}
-
-
-void Isolate::ReloadSources(bool force_reload,
+bool Isolate::ReloadSources(JSONStream* js,
+                            bool force_reload,
                             bool dont_delete_reload_context) {
-  // TODO(asiva): Add verification of canonical objects.
   ASSERT(!IsReloading());
   has_attempted_reload_ = true;
-  reload_context_ = new IsolateReloadContext(this);
-  reload_context_->StartReload(force_reload);
-  // TODO(asiva): Add verification of canonical objects.
-  if (dont_delete_reload_context) {
-    // Unit tests use the reload context later. Caller is responsible
-    // for deleting the context.
-    return;
+  reload_context_ = new IsolateReloadContext(this, js);
+  reload_context_->Reload(force_reload);
+  bool success = !reload_context_->reload_aborted();
+  if (!dont_delete_reload_context) {
+    DeleteReloadContext();
   }
-  DeleteReloadContext();
+#if defined(DEBUG)
+  if (success) {
+    return success;
+    Thread* thread = Thread::Current();
+    Isolate* isolate = thread->isolate();
+    isolate->heap()->CollectAllGarbage();
+    VerifyCanonicalVisitor check_canonical(thread);
+    isolate->heap()->IterateObjects(&check_canonical);
+  }
+#endif  // DEBUG
+  return success;
 }
 
 
@@ -1123,13 +1118,7 @@
 void Isolate::DoneFinalizing() {
   NOT_IN_PRODUCT(
     if (IsReloading()) {
-      reload_context_->FinishReload();
-      if (reload_context_->has_error()) {
-        // Remember the reload error.
-        sticky_reload_error_ = reload_context_->error();
-      } else {
-        reload_context_->ReportSuccess();
-      }
+      reload_context_->FinalizeLoading();
     }
   )
 }
@@ -1505,7 +1494,8 @@
     ASSERT(thread->isolate() == isolate);
     StackZone zone(thread);
     HandleScope handle_scope(thread);
-#if defined(DEBUG)
+    // TODO(27003): Enable for precompiled.
+#if defined(DEBUG) && !defined(DART_PRECOMPILED_RUNTIME)
     if (!isolate->HasAttemptedReload()) {
       isolate->heap()->CollectAllGarbage();
       VerifyCanonicalVisitor check_canonical(thread);
@@ -1831,9 +1821,6 @@
   visitor->VisitPointer(
         reinterpret_cast<RawObject**>(&sticky_error_));
 
-  visitor->VisitPointer(
-        reinterpret_cast<RawObject**>(&sticky_reload_error_));
-
   // Visit the pending service extension calls.
   visitor->VisitPointer(
       reinterpret_cast<RawObject**>(&pending_service_extension_calls_));
@@ -2094,11 +2081,6 @@
 }
 
 
-void Isolate::clear_sticky_reload_error() {
-  sticky_reload_error_ = Error::null();
-}
-
-
 void Isolate::set_pending_service_extension_calls(
       const GrowableObjectArray& value) {
   pending_service_extension_calls_ = value.raw();
diff --git a/runtime/vm/isolate.h b/runtime/vm/isolate.h
index 9c55cf3..2e603f1 100644
--- a/runtime/vm/isolate.h
+++ b/runtime/vm/isolate.h
@@ -249,7 +249,8 @@
 
   // By default the reload context is deleted. This parameter allows
   // the caller to delete is separately if it is still needed.
-  void ReloadSources(bool force_reload,
+  bool ReloadSources(JSONStream* js,
+                     bool force_reload,
                      bool dont_delete_reload_context = false);
 
   bool MakeRunnable();
@@ -482,8 +483,6 @@
 
   bool CanReload() const;
 
-  void ReportReloadError(const Error& error);
-
   void set_last_reload_timestamp(int64_t value) {
     last_reload_timestamp_ = value;
   }
@@ -539,9 +538,6 @@
   RawError* sticky_error() const { return sticky_error_; }
   void clear_sticky_error();
 
-  RawError* sticky_reload_error() const { return sticky_reload_error_; }
-  void clear_sticky_reload_error();
-
   bool compilation_allowed() const { return compilation_allowed_; }
   void set_compilation_allowed(bool allowed) {
     compilation_allowed_ = allowed;
@@ -771,8 +767,6 @@
 
   RawError* sticky_error_;
 
-  RawError* sticky_reload_error_;
-
   // Background compilation.
   BackgroundCompiler* background_compiler_;
   intptr_t background_compiler_disabled_depth_;
diff --git a/runtime/vm/isolate_reload.cc b/runtime/vm/isolate_reload.cc
index f174406..e635a7b 100644
--- a/runtime/vm/isolate_reload.cc
+++ b/runtime/vm/isolate_reload.cc
@@ -32,6 +32,8 @@
 DEFINE_FLAG(bool, reload_every_optimized, true, "Only from optimized code.");
 DEFINE_FLAG(bool, reload_every_back_off, false,
             "Double the --reload-every value after each reload.");
+DEFINE_FLAG(bool, reload_force_rollback, false,
+            "Force all reloads to fail and rollback.");
 DEFINE_FLAG(bool, check_reloaded, false,
             "Assert that an isolate has reloaded at least once.")
 #ifndef PRODUCT
@@ -45,11 +47,11 @@
                                    #name)
 
 
-InstanceMorpher::InstanceMorpher(const Class& from, const Class& to)
-  : from_(from), to_(to), mapping_() {
+InstanceMorpher::InstanceMorpher(Zone* zone, const Class& from, const Class& to)
+  : from_(from), to_(to), mapping_(zone, 0) {
   ComputeMapping();
-  before_ = new ZoneGrowableArray<const Instance*>();
-  after_ = new ZoneGrowableArray<const Instance*>();
+  before_ = new(zone) ZoneGrowableArray<const Instance*>(zone, 0);
+  after_ = new(zone) ZoneGrowableArray<const Instance*>(zone, 0);
   ASSERT(from_.id() == to_.id());
   cid_ = from_.id();
 }
@@ -165,10 +167,10 @@
 
 void InstanceMorpher::AppendTo(JSONArray* array) {
   JSONObject jsobj(array);
-  jsobj.AddProperty("type", "Morpher");
+  jsobj.AddProperty("type", "ShapeChangeMapping");
   jsobj.AddProperty("class", to_);
-  jsobj.AddProperty("instances", before()->length());
-  JSONArray map(&jsobj, "mapping");
+  jsobj.AddProperty("instanceCount", before()->length());
+  JSONArray map(&jsobj, "fieldOffsetMappings");
   for (int i = 0; i < mapping_.length(); i += 2) {
     JSONArray pair(&map);
     pair.AddValue(mapping_.At(i));
@@ -200,7 +202,7 @@
   JSONObject jsobj(array);
   jsobj.AddProperty("type", "ReasonForCancelling");
   const String& message = String::Handle(ToString());
-  jsobj.AddProperty("message", message);
+  jsobj.AddProperty("message", message.ToCString());
 }
 
 
@@ -209,15 +211,15 @@
   jsobj.AddProperty("type", "ReasonForCancelling");
   jsobj.AddProperty("class", from_);
   const String& message = String::Handle(ToString());
-  jsobj.AddProperty("message", message);
+  jsobj.AddProperty("message", message.ToCString());
 }
 
+
 RawError* IsolateReloadContext::error() const {
-  ASSERT(has_error());
+  ASSERT(reload_aborted());
   // Report the first error to the surroundings.
   const Error& error =
       Error::Handle(reasons_to_cancel_reload_.At(0)->ToError());
-  OS::Print("[[%s]]\n", error.ToCString());
   return error.raw();
 }
 
@@ -355,16 +357,21 @@
 }
 
 
-IsolateReloadContext::IsolateReloadContext(Isolate* isolate)
-    : start_time_micros_(OS::GetCurrentMonotonicMicros()),
+IsolateReloadContext::IsolateReloadContext(Isolate* isolate,
+                                           JSONStream* js)
+    : zone_(Thread::Current()->zone()),
+      start_time_micros_(OS::GetCurrentMonotonicMicros()),
       reload_timestamp_(OS::GetCurrentTimeMillis()),
       isolate_(isolate),
       reload_skipped_(false),
+      reload_aborted_(false),
+      reload_finalized_(false),
+      js_(js),
       saved_num_cids_(-1),
       saved_class_table_(NULL),
       num_saved_libs_(-1),
-      instance_morphers_(),
-      reasons_to_cancel_reload_(),
+      instance_morphers_(zone_, 0),
+      reasons_to_cancel_reload_(zone_, 0),
       cid_mapper_(),
       modified_libs_(NULL),
       script_uri_(String::null()),
@@ -380,6 +387,7 @@
   // NOTE: DO NOT ALLOCATE ANY RAW OBJECTS HERE. The IsolateReloadContext is not
   // associated with the isolate yet and if a GC is triggered here the raw
   // objects will not be properly accounted for.
+  ASSERT(zone_ != NULL);
 }
 
 
@@ -405,8 +413,8 @@
 
 class Aborted : public ReasonForCancelling {
  public:
-  explicit Aborted(const Error& error)
-      : ReasonForCancelling(), error_(error) { }
+  explicit Aborted(Zone* zone, const Error& error)
+      : ReasonForCancelling(zone), error_(error) { }
 
  private:
   const Error& error_;
@@ -418,7 +426,8 @@
 };
 
 
-void IsolateReloadContext::StartReload(bool force_reload) {
+// NOTE: This function returns *after* FinalizeLoading is called.
+void IsolateReloadContext::Reload(bool force_reload) {
   TIMELINE_SCOPE(Reload);
   Thread* thread = Thread::Current();
   ASSERT(isolate() == thread->isolate());
@@ -433,10 +442,12 @@
   if (!modified_libs_->Contains(root_lib.index())) {
     ASSERT(modified_libs_->IsEmpty());
     reload_skipped_ = true;
-    TIR_Print("Skipping reload.  No libraries were modified\n");
+    TIR_Print("---- SKIPPING RELOAD (No libraries were modified)\n");
     return;
   }
 
+  TIR_Print("---- STARTING RELOAD\n");
+
   // Preallocate storage for maps.
   old_classes_set_storage_ =
       HashTables::New<UnorderedHashSet<ClassMapTraits> >(4);
@@ -455,11 +466,6 @@
   // Disable the background compiler while we are performing the reload.
   BackgroundCompiler::Disable();
 
-  if (FLAG_write_protect_code) {
-    // Disable code page write protection while we are reloading.
-    I->heap()->WriteProtectCode(false);
-  }
-
   // Ensure all functions on the stack have unoptimized code.
   EnsuredUnoptimizedCodeForStack();
   // Deoptimize all code that had optimizing decisions that are dependent on
@@ -469,6 +475,25 @@
   DeoptimizeDependentCode();
   Checkpoint();
 
+  // WEIRD CONTROL FLOW BEGINS.
+  //
+  // The flow of execution until we return from the tag handler can be complex.
+  //
+  // On a successful load, the following will occur:
+  //   1) Tag Handler is invoked and the embedder is in control.
+  //   2) All sources and libraries are loaded.
+  //   3) Dart_FinalizeLoading is called by the embedder.
+  //   4) Dart_FinalizeLoading invokes IsolateReloadContext::FinalizeLoading
+  //      and we are temporarily back in control.
+  //      This is where we validate the reload and commit or reject.
+  //   5) Dart_FinalizeLoading invokes Dart code related to deferred libraries.
+  //   6) The tag handler returns and we move on.
+  //
+  // Even after a successful reload the Dart code invoked in (5) can result
+  // in an Unwind error or an UnhandledException error. This error will be
+  // returned by the tag handler. The tag handler can return other errors,
+  // for example, top level parse errors. We want to capture these errors while
+  // propagating the UnwindError or an UnhandledException error.
   Object& result = Object::Handle(thread->zone());
   {
     TransitionVMToNative transition(thread);
@@ -480,9 +505,22 @@
                                    Api::NewHandle(thread, root_lib_url.raw()));
     result = Api::UnwrapHandle(retval);
   }
+  //
+  // WEIRD CONTROL FLOW ENDS.
+
+  BackgroundCompiler::Enable();
+
+  if (result.IsUnwindError() ||
+      result.IsUnhandledException()) {
+    // If the tag handler returns with an UnwindError or an UnhandledException
+    // error, propagate it and give up.
+    Exceptions::PropagateError(Error::Cast(result));
+    UNREACHABLE();
+  }
+
+  // Other errors (e.g. a parse error) are captured by the reload system.
   if (result.IsError()) {
-    const Error& error = Error::Cast(result);
-    AddReasonForCancelling(new Aborted(error));
+    FinalizeFailedLoad(Error::Cast(result));
   }
 }
 
@@ -513,12 +551,15 @@
 }
 
 
-void IsolateReloadContext::FinishReload() {
+// FinalizeLoading will be called *before* Reload() returns but will not be
+// called if the embedder fails to load sources.
+void IsolateReloadContext::FinalizeLoading() {
   if (reload_skipped_) {
     return;
   }
+  ASSERT(!reload_finalized_);
   BuildLibraryMapping();
-  TIR_Print("---- DONE FINALIZING\n");
+  TIR_Print("---- LOAD SUCCEEDED\n");
   if (ValidateReload()) {
     Commit();
     PostCommit();
@@ -531,48 +572,63 @@
   // not remove dead subclasses.  Rebuild the direct subclass
   // information from scratch.
   RebuildDirectSubclasses();
+  CommonFinalizeTail();
+}
 
-  if (FLAG_write_protect_code) {
-    // Re-enable code page write protection.
-    I->heap()->WriteProtectCode(true);
+
+// FinalizeFailedLoad will be called *before* Reload() returns and will only
+// be called if the embedder fails to load sources.
+void IsolateReloadContext::FinalizeFailedLoad(const Error& error) {
+  TIR_Print("---- LOAD FAILED, ABORTING RELOAD\n");
+  AddReasonForCancelling(new Aborted(zone_, error));
+  ReportReasonsForCancelling();
+  if (!reload_finalized_) {
+    Rollback();
   }
+  CommonFinalizeTail();
+}
 
-  BackgroundCompiler::Enable();
 
-  if (FLAG_trace_reload) {
-    JSONStream stream;
-    ReportOnJSON(&stream);
-    OS::Print("\nJSON report:\n  %s\n", stream.ToCString());
-  }
+void IsolateReloadContext::CommonFinalizeTail() {
+  ReportOnJSON(js_);
+  reload_finalized_ = true;
 }
 
 
 void IsolateReloadContext::ReportOnJSON(JSONStream* stream) {
+  // Clear the buffer.
+  stream->buffer()->Clear();
   JSONObject jsobj(stream);
-  jsobj.AddProperty("type", "Reload");
-  jsobj.AddProperty("succeeded", !HasReasonsForCancelling());
-  if (HasReasonsForCancelling()) {
-    JSONArray array(&jsobj, "reasons");
-    for (intptr_t i = 0; i < reasons_to_cancel_reload_.length(); i++) {
-      ReasonForCancelling* reason = reasons_to_cancel_reload_.At(i);
-      reason->AppendTo(&array);
-    }
-  } else {
-    JSONArray array(&jsobj, "changes");
-    for (intptr_t i = 0; i < instance_morphers_.length(); i++) {
-      instance_morphers_.At(i)->AppendTo(&array);
+  jsobj.AddProperty("type", "ReloadReport");
+  jsobj.AddProperty("success", !HasReasonsForCancelling());
+  {
+    JSONObject details(&jsobj, "details");
+    if (HasReasonsForCancelling()) {
+      // Reload was rejected.
+      JSONArray array(&jsobj, "notices");
+      for (intptr_t i = 0; i < reasons_to_cancel_reload_.length(); i++) {
+        ReasonForCancelling* reason = reasons_to_cancel_reload_.At(i);
+        reason->AppendTo(&array);
+      }
+    } else {
+      // Reload was successful.
+      const GrowableObjectArray& libs =
+          GrowableObjectArray::Handle(object_store()->libraries());
+      const intptr_t final_library_count = libs.Length();
+      const intptr_t loaded_library_count =
+          final_library_count - num_saved_libs_;
+      details.AddProperty("savedLibraryCount", num_saved_libs_);
+      details.AddProperty("loadedLibraryCount", loaded_library_count);
+      details.AddProperty("finalLibraryCount", final_library_count);
+      JSONArray array(&jsobj, "shapeChangeMappings");
+      for (intptr_t i = 0; i < instance_morphers_.length(); i++) {
+        instance_morphers_.At(i)->AppendTo(&array);
+      }
     }
   }
 }
 
 
-void IsolateReloadContext::AbortReload(const Error& error) {
-  AddReasonForCancelling(new Aborted(error));
-  ReportReasonsForCancelling();
-  Rollback();
-}
-
-
 void IsolateReloadContext::EnsuredUnoptimizedCodeForStack() {
   TIMELINE_SCOPE(EnsuredUnoptimizedCodeForStack);
   StackFrameIterator it(StackFrameIterator::kDontValidateFrames);
@@ -709,12 +765,13 @@
 
   // Construct the imported-by graph.
   ZoneGrowableArray<ZoneGrowableArray<intptr_t>* >* imported_by =
-      new ZoneGrowableArray<ZoneGrowableArray<intptr_t>* >(num_libs);
+      new(zone_) ZoneGrowableArray<ZoneGrowableArray<intptr_t>* >(
+          zone_, num_libs);
   imported_by->SetLength(num_libs);
   for (intptr_t i = 0; i < num_libs; i++) {
-    (*imported_by)[i] = new ZoneGrowableArray<intptr_t>();
+    (*imported_by)[i] = new(zone_) ZoneGrowableArray<intptr_t>(zone_, 0);
   }
-  Array& imports = Array::Handle();
+  Array& ports = Array::Handle();
   Namespace& ns = Namespace::Handle();
   Library& target = Library::Handle();
 
@@ -727,9 +784,19 @@
     }
 
     // Add imports to the import-by graph.
-    imports = lib.imports();
-    for (intptr_t import_idx = 0; import_idx < imports.Length(); import_idx++) {
-      ns ^= imports.At(import_idx);
+    ports = lib.imports();
+    for (intptr_t import_idx = 0; import_idx < ports.Length(); import_idx++) {
+      ns ^= ports.At(import_idx);
+      if (!ns.IsNull()) {
+        target = ns.library();
+        (*imported_by)[target.index()]->Add(lib.index());
+      }
+    }
+
+    // Add exports to the import-by graph.
+    ports = lib.exports();
+    for (intptr_t export_idx = 0; export_idx < ports.Length(); export_idx++) {
+      ns ^= ports.At(export_idx);
       if (!ns.IsNull()) {
         target = ns.library();
         (*imported_by)[target.index()]->Add(lib.index());
@@ -744,10 +811,10 @@
       entry = entries.GetNext();
       if (entry.IsLibraryPrefix()) {
         prefix ^= entry.raw();
-        imports = prefix.imports();
-        for (intptr_t import_idx = 0; import_idx < imports.Length();
+        ports = prefix.imports();
+        for (intptr_t import_idx = 0; import_idx < ports.Length();
              import_idx++) {
-          ns ^= imports.At(import_idx);
+          ns ^= ports.At(import_idx);
           if (!ns.IsNull()) {
             target = ns.library();
             (*imported_by)[target.index()]->Add(lib.index());
@@ -784,7 +851,7 @@
 
 void IsolateReloadContext::CheckpointLibraries() {
   TIMELINE_SCOPE(CheckpointLibraries);
-
+  TIR_Print("---- CHECKPOINTING LIBRARIES\n");
   // Save the root library in case we abort the reload.
   const Library& root_lib =
       Library::Handle(object_store()->root_library());
@@ -884,6 +951,7 @@
 
 
 void IsolateReloadContext::Rollback() {
+  TIR_Print("---- ROLLING BACK");
   RollbackClasses();
   RollbackLibraries();
 }
@@ -927,7 +995,7 @@
 
 void IsolateReloadContext::Commit() {
   TIMELINE_SCOPE(Commit);
-  TIR_Print("---- COMMITTING REVERSE MAP\n");
+  TIR_Print("---- COMMITTING RELOAD\n");
 
   // Note that the object heap contains before and after instances
   // used for morphing. It is therefore important that morphing takes
@@ -947,9 +1015,8 @@
     // Copy static field values from the old classes to the new classes.
     // Patch fields and functions in the old classes so that they retain
     // the old script.
-    Class& cls = Class::Handle();
+    Class& old_cls = Class::Handle();
     Class& new_cls = Class::Handle();
-
     UnorderedHashMap<ClassMapTraits> class_map(class_map_storage_);
 
     {
@@ -957,15 +1024,16 @@
       while (it.MoveNext()) {
         const intptr_t entry = it.Current();
         new_cls = Class::RawCast(class_map.GetKey(entry));
-        cls = Class::RawCast(class_map.GetPayload(entry, 0));
-        if (new_cls.raw() != cls.raw()) {
-          ASSERT(new_cls.is_enum_class() == cls.is_enum_class());
+        old_cls = Class::RawCast(class_map.GetPayload(entry, 0));
+        if (new_cls.raw() != old_cls.raw()) {
+          ASSERT(new_cls.is_enum_class() == old_cls.is_enum_class());
           if (new_cls.is_enum_class() && new_cls.is_finalized()) {
-            new_cls.ReplaceEnum(cls);
+            new_cls.ReplaceEnum(old_cls);
           } else {
-            new_cls.CopyStaticFieldValues(cls);
+            new_cls.CopyStaticFieldValues(old_cls);
           }
-          cls.PatchFieldsAndFunctions();
+          old_cls.PatchFieldsAndFunctions();
+          old_cls.MigrateImplicitStaticClosures(this, new_cls);
         }
       }
     }
@@ -1094,6 +1162,7 @@
 
 
 void IsolateReloadContext::AddReasonForCancelling(ReasonForCancelling* reason) {
+  reload_aborted_ = true;
   reasons_to_cancel_reload_.Add(reason);
 }
 
@@ -1105,7 +1174,7 @@
 
 
 void IsolateReloadContext::ReportReasonsForCancelling() {
-  ASSERT(HasReasonsForCancelling());
+  ASSERT(FLAG_reload_force_rollback || HasReasonsForCancelling());
   for (int i = 0; i < reasons_to_cancel_reload_.length(); i++) {
     reasons_to_cancel_reload_.At(i)->Report(this);
   }
@@ -1194,7 +1263,9 @@
 
 bool IsolateReloadContext::ValidateReload() {
   TIMELINE_SCOPE(ValidateReload);
-  if (has_error()) return false;
+  if (reload_aborted()) return false;
+
+  TIR_Print("---- VALIDATING RELOAD\n");
 
   // Validate libraries.
   {
@@ -1232,7 +1303,7 @@
     map.Release();
   }
 
-  return !HasReasonsForCancelling();
+  return !FLAG_reload_force_rollback && !HasReasonsForCancelling();
 }
 
 
diff --git a/runtime/vm/isolate_reload.h b/runtime/vm/isolate_reload.h
index a479aae..213a988 100644
--- a/runtime/vm/isolate_reload.h
+++ b/runtime/vm/isolate_reload.h
@@ -52,7 +52,7 @@
 
 class InstanceMorpher : public ZoneAllocated {
  public:
-  InstanceMorpher(const Class& from, const Class& to);
+  InstanceMorpher(Zone* zone, const Class& from, const Class& to);
   virtual ~InstanceMorpher() {}
 
   // Called on each instance that needs to be morphed.
@@ -93,7 +93,7 @@
 
 class ReasonForCancelling : public ZoneAllocated {
  public:
-  ReasonForCancelling() {}
+  explicit ReasonForCancelling(Zone* zone) {}
   virtual ~ReasonForCancelling() {}
 
   // Reports a reason for cancelling reload.
@@ -117,8 +117,8 @@
 // Abstract class for also capturing the from_ and to_ class.
 class ClassReasonForCancelling : public ReasonForCancelling {
  public:
-  ClassReasonForCancelling(const Class& from, const Class& to)
-      : from_(from), to_(to) { }
+  ClassReasonForCancelling(Zone* zone, const Class& from, const Class& to)
+      : ReasonForCancelling(zone), from_(from), to_(to) { }
 
   void AppendTo(JSONArray* array);
 
@@ -130,32 +130,36 @@
 
 class IsolateReloadContext {
  public:
-  explicit IsolateReloadContext(Isolate* isolate);
+  explicit IsolateReloadContext(Isolate* isolate,
+                                JSONStream* js);
   ~IsolateReloadContext();
 
-  void StartReload(bool force_reload);
-  void FinishReload();
-  void AbortReload(const Error& error);
+  void Reload(bool force_reload);
 
-  RawLibrary* saved_root_library() const;
-
-  RawGrowableObjectArray* saved_libraries() const;
-
-  // Report back through the observatory channels.
-  void ReportError(const Error& error);
-  void ReportSuccess();
+  // All zone allocated objects must be allocated from this zone.
+  Zone* zone() const { return zone_; }
 
   bool reload_skipped() const { return reload_skipped_; }
-
-  bool has_error() const { return HasReasonsForCancelling(); }
+  bool reload_aborted() const { return reload_aborted_; }
   RawError* error() const;
-
   int64_t reload_timestamp() const { return reload_timestamp_; }
 
+  static Dart_FileModifiedCallback file_modified_callback() {
+    return file_modified_callback_;
+  }
+  static void SetFileModifiedCallback(Dart_FileModifiedCallback callback) {
+    file_modified_callback_ = callback;
+  }
+
   static bool IsSameField(const Field& a, const Field& b);
   static bool IsSameLibrary(const Library& a_lib, const Library& b_lib);
   static bool IsSameClass(const Class& a, const Class& b);
 
+ private:
+  RawLibrary* saved_root_library() const;
+
+  RawGrowableObjectArray* saved_libraries() const;
+
   RawClass* FindOriginalClass(const Class& cls);
 
   bool IsDirty(const Library& lib);
@@ -193,14 +197,22 @@
     return !instance_morphers_.is_empty();
   }
 
-  static Dart_FileModifiedCallback file_modified_callback() {
-    return file_modified_callback_;
-  }
-  static void SetFileModifiedCallback(Dart_FileModifiedCallback callback) {
-    file_modified_callback_ = callback;
-  }
+  // NOTE: FinalizeLoading will be called *before* Reload() returns. This
+  // function will not be called if the embedder does not call
+  // Dart_FinalizeLoading.
+  void FinalizeLoading();
 
- private:
+  // NOTE: FinalizeFailedLoad will be called *before* Reload returns. This
+  // function will not be called if the embedder calls Dart_FinalizeLoading.
+  void FinalizeFailedLoad(const Error& error);
+
+  // Called by both FinalizeLoading and FinalizeFailedLoad.
+  void CommonFinalizeTail();
+
+  // Report back through the observatory channels.
+  void ReportError(const Error& error);
+  void ReportSuccess();
+
   void set_saved_root_library(const Library& value);
 
   void set_saved_libraries(const GrowableObjectArray& value);
@@ -248,10 +260,16 @@
   void ResetMegamorphicCaches();
   void InvalidateWorld();
 
+  // The zone used for all reload related allocations.
+  Zone* zone_;
+
   int64_t start_time_micros_;
   int64_t reload_timestamp_;
   Isolate* isolate_;
   bool reload_skipped_;
+  bool reload_aborted_;
+  bool reload_finalized_;
+  JSONStream* js_;
 
   intptr_t saved_num_cids_;
   RawClass** saved_class_table_;
@@ -322,7 +340,10 @@
 
   friend class Isolate;
   friend class Class;  // AddStaticFieldMapping, AddEnumBecomeMapping.
+  friend class Library;
   friend class ObjectLocator;
+  friend class MarkFunctionsForRecompilation;  // IsDirty.
+  friend class ReasonForCancelling;
 
   static Dart_FileModifiedCallback file_modified_callback_;
 };
diff --git a/runtime/vm/isolate_reload_test.cc b/runtime/vm/isolate_reload_test.cc
index 46774c7..070897e 100644
--- a/runtime/vm/isolate_reload_test.cc
+++ b/runtime/vm/isolate_reload_test.cc
@@ -784,51 +784,57 @@
 
 
 TEST_CASE(IsolateReload_LibraryLookup) {
+  const char* kImportScript =
+      "importedFunc() => 'a';\n";
+  TestCase::AddTestLib("test:lib1", kImportScript);
+
   const char* kScript =
       "main() {\n"
       "  return importedFunc();\n"
       "}\n";
-
   Dart_Handle result;
-
   Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL);
   EXPECT_VALID(lib);
   EXPECT_ERROR(SimpleInvokeError(lib, "main"), "importedFunc");
 
-  // Fail to find 'test:importable_lib' in the isolate.
-  result = Dart_LookupLibrary(NewString("test:importable_lib"));
+  // Fail to find 'test:lib1' in the isolate.
+  result = Dart_LookupLibrary(NewString("test:lib1"));
   EXPECT(Dart_IsError(result));
 
   const char* kReloadScript =
-      "import 'test:importable_lib';\n"
+      "import 'test:lib1';\n"
       "main() {\n"
       "  return importedFunc();\n"
       "}\n";
 
-  // Reload and add 'test:importable_lib' to isolate.
+  // Reload and add 'test:lib1' to isolate.
   lib = TestCase::ReloadTestScript(kReloadScript);
   EXPECT_VALID(lib);
   EXPECT_STREQ("a", SimpleInvokeStr(lib, "main"));
 
-  // Find 'test:importable_lib' in the isolate.
-  result = Dart_LookupLibrary(NewString("test:importable_lib"));
+  // Find 'test:lib1' in the isolate.
+  result = Dart_LookupLibrary(NewString("test:lib1"));
   EXPECT(Dart_IsLibrary(result));
 
   // Reload and remove 'dart:math' from isolate.
   lib = TestCase::ReloadTestScript(kScript);
   EXPECT_VALID(lib);
 
-  // Fail to find 'test:importable_lib' in the isolate.
-  result = Dart_LookupLibrary(NewString("test:importable_lib"));
+  // Fail to find 'test:lib1' in the isolate.
+  result = Dart_LookupLibrary(NewString("test:lib1"));
   EXPECT(Dart_IsError(result));
 }
 
 
 TEST_CASE(IsolateReload_LibraryHide) {
-  // Import 'test:importable_lib' with importedFunc hidden. Will result in an
+  const char* kImportScript =
+      "importedFunc() => 'a';\n";
+  TestCase::AddTestLib("test:lib1", kImportScript);
+
+  // Import 'test:lib1' with importedFunc hidden. Will result in an
   // error.
   const char* kScript =
-      "import 'test:importable_lib' hide importedFunc;\n"
+      "import 'test:lib1' hide importedFunc;\n"
       "main() {\n"
       "  return importedFunc();\n"
       "}\n";
@@ -839,9 +845,9 @@
   EXPECT_VALID(lib);
   EXPECT_ERROR(SimpleInvokeError(lib, "main"), "importedFunc");
 
-  // Import 'test:importable_lib'.
+  // Import 'test:lib1'.
   const char* kReloadScript =
-      "import 'test:importable_lib';\n"
+      "import 'test:lib1';\n"
       "main() {\n"
       "  return importedFunc();\n"
       "}\n";
@@ -853,10 +859,15 @@
 
 
 TEST_CASE(IsolateReload_LibraryShow) {
-  // Import 'test:importable_lib' with importedIntFunc visible. Will result in
+  const char* kImportScript =
+      "importedFunc() => 'a';\n"
+      "importedIntFunc() => 4;\n";
+  TestCase::AddTestLib("test:lib1", kImportScript);
+
+  // Import 'test:lib1' with importedIntFunc visible. Will result in
   // an error when 'main' is invoked.
   const char* kScript =
-      "import 'test:importable_lib' show importedIntFunc;\n"
+      "import 'test:lib1' show importedIntFunc;\n"
       "main() {\n"
       "  return importedFunc();\n"
       "}\n"
@@ -873,10 +884,10 @@
   // Results in an error.
   EXPECT_ERROR(SimpleInvokeError(lib, "main"), "importedFunc");
 
-  // Import 'test:importable_lib' with importedFunc visible. Will result in
+  // Import 'test:lib1' with importedFunc visible. Will result in
   // an error when 'mainInt' is invoked.
   const char* kReloadScript =
-      "import 'test:importable_lib' show importedFunc;\n"
+      "import 'test:lib1' show importedFunc;\n"
       "main() {\n"
       "  return importedFunc();\n"
       "}\n"
@@ -897,9 +908,13 @@
 // Verifies that we clear the ICs for the functions live on the stack in a way
 // that is compatible with the fast path smi stubs.
 TEST_CASE(IsolateReload_SmiFastPathStubs) {
+  const char* kImportScript =
+      "importedIntFunc() => 4;\n";
+  TestCase::AddTestLib("test:lib1", kImportScript);
+
   const char* kScript =
       "import 'test:isolate_reload_helper';\n"
-      "import 'test:importable_lib' show importedIntFunc;\n"
+      "import 'test:lib1' show importedIntFunc;\n"
       "main() {\n"
       "  var x = importedIntFunc();\n"
       "  var y = importedIntFunc();\n"
@@ -921,8 +936,14 @@
 // Verifies that we assign the correct patch classes for imported
 // mixins when we reload.
 TEST_CASE(IsolateReload_ImportedMixinFunction) {
+  const char* kImportScript =
+      "class ImportedMixin {\n"
+      "  mixinFunc() => 'mixin';\n"
+      "}\n";
+  TestCase::AddTestLib("test:lib1", kImportScript);
+
   const char* kScript =
-      "import 'test:importable_lib' show ImportedMixin;\n"
+      "import 'test:lib1' show ImportedMixin;\n"
       "class A extends Object with ImportedMixin {\n"
       "}"
       "var func = new A().mixinFunc;\n"
@@ -936,7 +957,7 @@
   EXPECT_STREQ("mixin", SimpleInvokeStr(lib, "main"));
 
   const char* kReloadScript =
-      "import 'test:importable_lib' show ImportedMixin;\n"
+      "import 'test:lib1' show ImportedMixin;\n"
       "class A extends Object with ImportedMixin {\n"
       "}"
       "var func;\n"
@@ -1289,7 +1310,7 @@
 }
 
 
-TEST_CASE(IsolateReload_TearOff_Equality) {
+TEST_CASE(IsolateReload_TearOff_Instance_Equality) {
   const char* kScript =
       "import 'test:isolate_reload_helper';\n"
       "class C {\n"
@@ -1328,6 +1349,80 @@
 }
 
 
+TEST_CASE(IsolateReload_TearOff_Class_Identity) {
+  const char* kScript =
+      "import 'test:isolate_reload_helper';\n"
+      "class C {\n"
+      "  static foo() => 'old';\n"
+      "}\n"
+      "getFoo() => C.foo;\n"
+      "main() {\n"
+      "  var f1 = getFoo();\n"
+      "  reloadTest();\n"
+      "  var f2 = getFoo();\n"
+      "  return '${f1()} ${f2()} ${f1 == f2} ${identical(f1, f2)}';\n"
+      "}\n";
+
+  Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL);
+  EXPECT_VALID(lib);
+
+  const char* kReloadScript =
+      "import 'test:isolate_reload_helper';\n"
+      "class C {\n"
+      "  static foo() => 'new';\n"
+      "}\n"
+      "getFoo() => C.foo;\n"
+      "main() {\n"
+      "  var f1 = getFoo();\n"
+      "  reloadTest();\n"
+      "  var f2 = getFoo();\n"
+      "  return '${f1()} ${f2()} ${f1 == f2} ${identical(f1, f2)}';\n"
+      "}\n";
+
+  TestCase::SetReloadTestScript(kReloadScript);
+
+  EXPECT_STREQ("new new true true", SimpleInvokeStr(lib, "main"));
+
+  lib = TestCase::GetReloadErrorOrRootLibrary();
+  EXPECT_VALID(lib);
+}
+
+
+TEST_CASE(IsolateReload_TearOff_Library_Identity) {
+  const char* kScript =
+      "import 'test:isolate_reload_helper';\n"
+      "foo() => 'old';\n"
+      "getFoo() => foo;\n"
+      "main() {\n"
+      "  var f1 = getFoo();\n"
+      "  reloadTest();\n"
+      "  var f2 = getFoo();\n"
+      "  return '${f1()} ${f2()} ${f1 == f2} ${identical(f1, f2)}';\n"
+      "}\n";
+
+  Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL);
+  EXPECT_VALID(lib);
+
+  const char* kReloadScript =
+      "import 'test:isolate_reload_helper';\n"
+      "foo() => 'new';\n"
+      "getFoo() => foo;\n"
+      "main() {\n"
+      "  var f1 = getFoo();\n"
+      "  reloadTest();\n"
+      "  var f2 = getFoo();\n"
+      "  return '${f1()} ${f2()} ${f1 == f2} ${identical(f1, f2)}';\n"
+      "}\n";
+
+  TestCase::SetReloadTestScript(kReloadScript);
+
+  EXPECT_STREQ("new new true true", SimpleInvokeStr(lib, "main"));
+
+  lib = TestCase::GetReloadErrorOrRootLibrary();
+  EXPECT_VALID(lib);
+}
+
+
 TEST_CASE(IsolateReload_TearOff_List_Set) {
   const char* kScript =
       "import 'test:isolate_reload_helper';\n"
@@ -2231,10 +2326,10 @@
 TEST_CASE(IsolateReload_NoLibsModified) {
   const char* kImportScript =
       "importedFunc() => 'fancy';";
-  TestCase::SetImportableTestLibScript(kImportScript);
+  TestCase::AddTestLib("test:lib1", kImportScript);
 
   const char* kScript =
-      "import 'test:importable_lib';\n"
+      "import 'test:lib1';\n"
       "main() {\n"
       "  return importedFunc() + ' feast';\n"
       "}\n";
@@ -2245,10 +2340,10 @@
 
   const char* kReloadImportScript =
       "importedFunc() => 'bossy';";
-  TestCase::SetImportableTestLibScript(kReloadImportScript);
+  TestCase::AddTestLib("test:lib1", kReloadImportScript);
 
   const char* kReloadScript =
-      "import 'test:importable_lib';\n"
+      "import 'test:lib1';\n"
       "main() {\n"
       "  return importedFunc() + ' pants';\n"
       "}\n";
@@ -2274,10 +2369,10 @@
 TEST_CASE(IsolateReload_MainLibModified) {
   const char* kImportScript =
       "importedFunc() => 'fancy';";
-  TestCase::SetImportableTestLibScript(kImportScript);
+  TestCase::AddTestLib("test:lib1", kImportScript);
 
   const char* kScript =
-      "import 'test:importable_lib';\n"
+      "import 'test:lib1';\n"
       "main() {\n"
       "  return importedFunc() + ' feast';\n"
       "}\n";
@@ -2288,10 +2383,10 @@
 
   const char* kReloadImportScript =
       "importedFunc() => 'bossy';";
-  TestCase::SetImportableTestLibScript(kReloadImportScript);
+  TestCase::AddTestLib("test:lib1", kReloadImportScript);
 
   const char* kReloadScript =
-      "import 'test:importable_lib';\n"
+      "import 'test:lib1';\n"
       "main() {\n"
       "  return importedFunc() + ' pants';\n"
       "}\n";
@@ -2307,7 +2402,7 @@
 
 
 static bool ImportModifiedCallback(const char* url, int64_t since) {
-  if (strcmp(url, "test:importable_lib") == 0) {
+  if (strcmp(url, "test:lib1") == 0) {
     return true;
   }
   return false;
@@ -2317,10 +2412,10 @@
 TEST_CASE(IsolateReload_ImportedLibModified) {
   const char* kImportScript =
       "importedFunc() => 'fancy';";
-  TestCase::SetImportableTestLibScript(kImportScript);
+  TestCase::AddTestLib("test:lib1", kImportScript);
 
   const char* kScript =
-      "import 'test:importable_lib';\n"
+      "import 'test:lib1';\n"
       "main() {\n"
       "  return importedFunc() + ' feast';\n"
       "}\n";
@@ -2331,10 +2426,10 @@
 
   const char* kReloadImportScript =
       "importedFunc() => 'bossy';";
-  TestCase::SetImportableTestLibScript(kReloadImportScript);
+  TestCase::AddTestLib("test:lib1", kReloadImportScript);
 
   const char* kReloadScript =
-      "import 'test:importable_lib';\n"
+      "import 'test:lib1';\n"
       "main() {\n"
       "  return importedFunc() + ' pants';\n"
       "}\n";
@@ -2352,10 +2447,10 @@
 TEST_CASE(IsolateReload_PrefixImportedLibModified) {
   const char* kImportScript =
       "importedFunc() => 'fancy';";
-  TestCase::SetImportableTestLibScript(kImportScript);
+  TestCase::AddTestLib("test:lib1", kImportScript);
 
   const char* kScript =
-      "import 'test:importable_lib' as cobra;\n"
+      "import 'test:lib1' as cobra;\n"
       "main() {\n"
       "  return cobra.importedFunc() + ' feast';\n"
       "}\n";
@@ -2366,10 +2461,10 @@
 
   const char* kReloadImportScript =
       "importedFunc() => 'bossy';";
-  TestCase::SetImportableTestLibScript(kReloadImportScript);
+  TestCase::AddTestLib("test:lib1", kReloadImportScript);
 
   const char* kReloadScript =
-      "import 'test:importable_lib' as cobra;\n"
+      "import 'test:lib1' as cobra;\n"
       "main() {\n"
       "  return cobra.importedFunc() + ' pants';\n"
       "}\n";
@@ -2385,6 +2480,52 @@
 }
 
 
+static bool ExportModifiedCallback(const char* url, int64_t since) {
+  if (strcmp(url, "test:exportlib") == 0) {
+    return true;
+  }
+  return false;
+}
+
+
+TEST_CASE(IsolateReload_ExportedLibModified) {
+  const char* kImportScript =
+      "export 'test:exportlib';";
+  TestCase::AddTestLib("test:importlib", kImportScript);
+
+  const char* kExportScript =
+      "exportedFunc() => 'fancy';";
+  TestCase::AddTestLib("test:exportlib", kExportScript);
+
+  const char* kScript =
+      "import 'test:importlib';\n"
+      "main() {\n"
+      "  return exportedFunc() + ' feast';\n"
+      "}\n";
+
+  Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL);
+  EXPECT_VALID(lib);
+  EXPECT_STREQ("fancy feast", SimpleInvokeStr(lib, "main"));
+
+  const char* kReloadExportScript =
+      "exportedFunc() => 'bossy';";
+  TestCase::AddTestLib("test:exportlib", kReloadExportScript);
+
+  const char* kReloadScript =
+      "import 'test:importlib';\n"
+      "main() {\n"
+      "  return exportedFunc() + ' pants';\n"
+      "}\n";
+
+  Dart_SetFileModifiedCallback(&ExportModifiedCallback);
+  lib = TestCase::ReloadTestScript(kReloadScript);
+  EXPECT_VALID(lib);
+  Dart_SetFileModifiedCallback(NULL);
+
+  // Modification of an exported library propagates.
+  EXPECT_STREQ("bossy pants", SimpleInvokeStr(lib, "main"));
+}
+
 #endif  // !PRODUCT
 
 }  // namespace dart
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index 2f062f1..0506fa7 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -15325,6 +15325,12 @@
   const Class& cls = Class::Handle(zone, this->clazz());
   SafepointMutexLocker ml(isolate->constant_canonicalization_mutex());
   result ^= cls.LookupCanonicalInstance(zone, *this);
+  // TODO(johnmccutchan) : Temporary workaround for issue (26988).
+  if ((result.raw() != raw()) &&
+      isolate->HasAttemptedReload() &&
+      (GetClassId() == kImmutableArrayCid)) {
+    return true;
+  }
   return (result.raw() == this->raw());
 }
 #endif  // DEBUG
diff --git a/runtime/vm/object.h b/runtime/vm/object.h
index 802bf513..e9c9280 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -1401,6 +1401,8 @@
   void ReplaceEnum(const Class& old_enum) const;
   void CopyStaticFieldValues(const Class& old_cls) const;
   void PatchFieldsAndFunctions() const;
+  void MigrateImplicitStaticClosures(IsolateReloadContext* context,
+                                     const Class& new_cls) const;
   void CopyCanonicalConstants(const Class& old_cls) const;
   void CopyCanonicalType(const Class& old_cls) const;
   void CheckReload(const Class& replacement,
diff --git a/runtime/vm/object_reload.cc b/runtime/vm/object_reload.cc
index c646dd6..ec79c6b 100644
--- a/runtime/vm/object_reload.cc
+++ b/runtime/vm/object_reload.cc
@@ -232,7 +232,10 @@
   String& enum_ident = String::Handle();
   Instance& old_enum_value = Instance::Handle(zone);
   Instance& enum_value = Instance::Handle(zone);
-
+  // The E.values array.
+  Instance& old_enum_values = Instance::Handle(zone);
+  // The E.values array.
+  Instance& enum_values = Instance::Handle(zone);
   Array& enum_map_storage = Array::Handle(zone,
       HashTables::New<UnorderedHashMap<EnumMapTraits> >(4));
   ASSERT(!enum_map_storage.IsNull());
@@ -251,6 +254,7 @@
         continue;
       }
       if (enum_ident.Equals(Symbols::Values())) {
+        old_enum_values = field.StaticValue();
         // Non-enum instance.
         continue;
       }
@@ -279,6 +283,7 @@
         continue;
       }
       if (enum_ident.Equals(Symbols::Values())) {
+        enum_values = field.StaticValue();
         // Non-enum instance.
         continue;
       }
@@ -302,6 +307,11 @@
     enum_map_storage = enum_map.Release().raw();
   }
 
+  // Map the old E.values array to the new E.values array.
+  ASSERT(!old_enum_values.IsNull());
+  ASSERT(!enum_values.IsNull());
+  reload_context->AddEnumBecomeMapping(old_enum_values, enum_values);
+
   if (enums_deleted && FLAG_trace_reload_verbose) {
     // TODO(johnmccutchan): Add this to the reload 'notices' list.
     VTIR_Print("The following enum values were deleted and are forever lost in "
@@ -363,10 +373,36 @@
 }
 
 
+void Class::MigrateImplicitStaticClosures(IsolateReloadContext* irc,
+                                          const Class& new_cls) const {
+  const Array& funcs = Array::Handle(functions());
+  Function& old_func = Function::Handle();
+  String& selector = String::Handle();
+  Function& new_func = Function::Handle();
+  Instance& old_closure = Instance::Handle();
+  Instance& new_closure = Instance::Handle();
+  for (intptr_t i = 0; i < funcs.Length(); i++) {
+    old_func ^= funcs.At(i);
+    if (old_func.is_static() &&
+      old_func.HasImplicitClosureFunction()) {
+      selector = old_func.name();
+      new_func = new_cls.LookupFunction(selector);
+      if (!new_func.IsNull() && new_func.is_static()) {
+        old_func = old_func.ImplicitClosureFunction();
+        old_closure = old_func.ImplicitStaticClosure();
+        new_func = new_func.ImplicitClosureFunction();
+        new_closure = new_func.ImplicitStaticClosure();
+        irc->AddBecomeMapping(old_closure, new_closure);
+      }
+    }
+  }
+}
+
+
 class EnumClassConflict : public ClassReasonForCancelling {
  public:
-  EnumClassConflict(const Class& from, const Class& to)
-      : ClassReasonForCancelling(from, to) { }
+  EnumClassConflict(Zone* zone, const Class& from, const Class& to)
+      : ClassReasonForCancelling(zone, from, to) { }
 
   RawString* ToString() {
     return String::NewFormatted(
@@ -380,20 +416,27 @@
 
 class EnsureFinalizedError : public ClassReasonForCancelling {
  public:
-  EnsureFinalizedError(const Class& from, const Class& to, const Error& error)
-      : ClassReasonForCancelling(from, to), error_(error) { }
+  EnsureFinalizedError(Zone* zone,
+                       const Class& from,
+                       const Class& to,
+                       const Error& error)
+      : ClassReasonForCancelling(zone, from, to), error_(error) { }
 
  private:
   const Error& error_;
 
   RawError* ToError() { return error_.raw(); }
+
+  RawString* ToString() {
+    return String::New(error_.ToErrorCString());
+  }
 };
 
 
 class NativeFieldsConflict : public ClassReasonForCancelling {
  public:
-  NativeFieldsConflict(const Class& from, const Class& to)
-      : ClassReasonForCancelling(from, to) { }
+  NativeFieldsConflict(Zone* zone, const Class& from, const Class& to)
+      : ClassReasonForCancelling(zone, from, to) { }
 
  private:
   RawString* ToString() {
@@ -405,8 +448,8 @@
 
 class TypeParametersChanged : public ClassReasonForCancelling {
  public:
-  TypeParametersChanged(const Class& from, const Class& to)
-      : ClassReasonForCancelling(from, to) {}
+  TypeParametersChanged(Zone* zone, const Class& from, const Class& to)
+      : ClassReasonForCancelling(zone, from, to) {}
 
   RawString* ToString() {
     return String::NewFormatted(
@@ -427,8 +470,8 @@
 
 class PreFinalizedConflict :  public ClassReasonForCancelling {
  public:
-  PreFinalizedConflict(const Class& from, const Class& to)
-      : ClassReasonForCancelling(from, to) {}
+  PreFinalizedConflict(Zone* zone, const Class& from, const Class& to)
+      : ClassReasonForCancelling(zone, from, to) {}
 
  private:
   RawString* ToString() {
@@ -442,8 +485,8 @@
 
 class InstanceSizeConflict :  public ClassReasonForCancelling {
  public:
-  InstanceSizeConflict(const Class& from, const Class& to)
-      : ClassReasonForCancelling(from, to) {}
+  InstanceSizeConflict(Zone* zone, const Class& from, const Class& to)
+      : ClassReasonForCancelling(zone, from, to) {}
 
  private:
   RawString* ToString() {
@@ -460,10 +503,11 @@
 
 class UnimplementedDeferredLibrary : public ReasonForCancelling {
  public:
-  UnimplementedDeferredLibrary(const Library& from,
+  UnimplementedDeferredLibrary(Zone* zone,
+                               const Library& from,
                                const Library& to,
                                const String& name)
-      : ReasonForCancelling(), from_(from), to_(to), name_(name) {}
+      : ReasonForCancelling(zone), from_(from), to_(to), name_(name) {}
 
  private:
   const Library& from_;
@@ -489,7 +533,8 @@
   // Class cannot change enum property.
   if (is_enum_class() != replacement.is_enum_class()) {
     context->AddReasonForCancelling(
-        new EnumClassConflict(*this, replacement));
+        new(context->zone())
+            EnumClassConflict(context->zone(), *this, replacement));
     return;
   }
 
@@ -499,16 +544,19 @@
         Error::Handle(replacement.EnsureIsFinalized(Thread::Current()));
     if (!error.IsNull()) {
       context->AddReasonForCancelling(
-          new EnsureFinalizedError(*this, replacement, error));
+          new(context->zone())
+              EnsureFinalizedError(context->zone(), *this, replacement, error));
       return;  // No reason to check other properties.
     }
+    ASSERT(replacement.is_finalized());
     TIR_Print("Finalized replacement class for %s\n", ToCString());
   }
 
   // Native field count cannot change.
   if (num_native_fields() != replacement.num_native_fields()) {
       context->AddReasonForCancelling(
-          new NativeFieldsConflict(*this, replacement));
+          new(context->zone())
+              NativeFieldsConflict(context->zone(), *this, replacement));
       return;
   }
 
@@ -575,11 +623,14 @@
       AbstractType::Handle(replacement.DeclarationType());
   if (!dt.Equals(replacement_dt)) {
     context->AddReasonForCancelling(
-        new TypeParametersChanged(*this, replacement));
+        new(context->zone())
+            TypeParametersChanged(context->zone(), *this, replacement));
     return false;
   }
   if (RequiresInstanceMorphing(replacement)) {
-    context->AddInstanceMorpher(new InstanceMorpher(*this, replacement));
+    context->AddInstanceMorpher(
+        new(context->zone())
+            InstanceMorpher(context->zone(), *this, replacement));
   }
   return true;
 }
@@ -590,13 +641,15 @@
   // The replacement class must also prefinalized.
   if (!replacement.is_prefinalized()) {
       context->AddReasonForCancelling(
-          new PreFinalizedConflict(*this, replacement));
+          new(context->zone())
+              PreFinalizedConflict(context->zone(), *this, replacement));
       return false;
   }
   // Check the instance sizes are equal.
   if (instance_size() != replacement.instance_size()) {
       context->AddReasonForCancelling(
-          new InstanceSizeConflict(*this, replacement));
+          new(context->zone())
+              InstanceSizeConflict(context->zone(), *this, replacement));
       return false;
   }
   return true;
@@ -614,7 +667,9 @@
     if (prefix.is_deferred_load()) {
       const String& prefix_name = String::Handle(prefix.name());
       context->AddReasonForCancelling(
-          new UnimplementedDeferredLibrary(*this, replacement, prefix_name));
+          new(context->zone())
+              UnimplementedDeferredLibrary(context->zone(),
+                                           *this, replacement, prefix_name));
       return;
     }
   }
diff --git a/runtime/vm/parser.cc b/runtime/vm/parser.cc
index d11536b..fc3e0f9 100644
--- a/runtime/vm/parser.cc
+++ b/runtime/vm/parser.cc
@@ -8724,16 +8724,20 @@
 
   // Parse stream expression.
   ExpectToken(Token::kIN);
+
+  // Open a block for the iterator variable and the try-finally statement
+  // that contains the loop. Ensure that the block starts at a different
+  // token position than the following loop block. Both blocks can allocate
+  // contexts and if they have a matching token position range,
+  // it can be an issue (cf. bug 26941).
+  OpenBlock();
+  const Block* await_for_block = current_block_;
+
   const TokenPosition stream_expr_pos = TokenPos();
   AstNode* stream_expr =
       ParseAwaitableExpr(kAllowConst, kConsumeCascades, NULL);
   ExpectToken(Token::kRPAREN);
 
-  // Open a block for the iterator variable and the try-finally
-  // statement that contains the loop.
-  OpenBlock();
-  const Block* loop_block = current_block_;
-
   // Build creation of implicit StreamIterator.
   // var :for-in-iter = new StreamIterator(stream_expr).
   const Class& stream_iterator_cls =
@@ -8983,8 +8987,8 @@
                          try_index,
                          finally_clause);
 
-  ASSERT(current_block_ == loop_block);
-  loop_block->statements->Add(try_catch_node);
+  ASSERT(current_block_ == await_for_block);
+  await_for_block->statements->Add(try_catch_node);
 
   return CloseBlock();  // Implicit block around while loop.
 }
diff --git a/runtime/vm/precompiler.cc b/runtime/vm/precompiler.cc
index dc0edb5..657af55 100644
--- a/runtime/vm/precompiler.cc
+++ b/runtime/vm/precompiler.cc
@@ -516,6 +516,70 @@
     if (!changed_) {
       TraceConstFunctions();
     }
+    CollectCallbackFields();
+  }
+}
+
+
+void Precompiler::CollectCallbackFields() {
+  Library& lib = Library::Handle(Z);
+  Class& cls = Class::Handle(Z);
+  Class& subcls = Class::Handle(Z);
+  Array& fields = Array::Handle(Z);
+  Field& field = Field::Handle(Z);
+  Function& function = Function::Handle(Z);
+  Function& dispatcher = Function::Handle(Z);
+  Array& args_desc = Array::Handle(Z);
+  AbstractType& field_type = AbstractType::Handle(Z);
+  String& field_name = String::Handle(Z);
+  GrowableArray<intptr_t> cids;
+
+  for (intptr_t i = 0; i < libraries_.Length(); i++) {
+    lib ^= libraries_.At(i);
+    ClassDictionaryIterator it(lib, ClassDictionaryIterator::kIteratePrivate);
+    while (it.HasNext()) {
+      cls = it.GetNextClass();
+
+      if (!cls.is_allocated()) continue;
+
+      fields = cls.fields();
+      for (intptr_t k = 0; k < fields.Length(); k++) {
+        field ^= fields.At(k);
+        if (field.is_static()) continue;
+        field_type = field.type();
+        if (!field_type.IsFunctionType()) continue;
+        field_name = field.name();
+        if (!IsSent(field_name)) continue;
+        // Create arguments descriptor with fixed parameters from
+        // signature of field_type.
+        function = Type::Cast(field_type).signature();
+        if (function.HasOptionalParameters()) continue;
+        if (FLAG_trace_precompiler) {
+          THR_Print("Found callback field %s\n", field_name.ToCString());
+        }
+        args_desc =
+            ArgumentsDescriptor::New(function.num_fixed_parameters());
+        cids.Clear();
+        if (T->cha()->ConcreteSubclasses(cls, &cids)) {
+          for (intptr_t j = 0; j < cids.length(); ++j) {
+            subcls ^= I->class_table()->At(cids[j]);
+            if (subcls.is_allocated()) {
+              // Add dispatcher to cls.
+              dispatcher = subcls.GetInvocationDispatcher(
+                  field_name,
+                  args_desc,
+                  RawFunction::kInvokeFieldDispatcher,
+                  /* create_if_absent = */ true);
+              if (FLAG_trace_precompiler) {
+                THR_Print("Added invoke-field-dispatcher for %s to %s\n",
+                          field_name.ToCString(), subcls.ToCString());
+              }
+              AddFunction(dispatcher);
+            }
+          }
+        }
+      }
+    }
   }
 }
 
@@ -1319,7 +1383,7 @@
       functions = cls.functions();
       for (intptr_t j = 0; j < functions.Length(); j++) {
         function ^= functions.At(j);
-        bool retain = function.HasCode();
+        bool retain = enqueued_functions_.Lookup(&function) != NULL;
         if (!retain && function.HasImplicitClosureFunction()) {
           // It can happen that all uses of an implicit closure inline their
           // target function, leaving the target function uncompiled. Keep
@@ -1339,7 +1403,7 @@
   closures = isolate()->object_store()->closure_functions();
   for (intptr_t j = 0; j < closures.Length(); j++) {
     function ^= closures.At(j);
-    bool retain = function.HasCode();
+    bool retain = enqueued_functions_.Lookup(&function) != NULL;
     if (retain) {
       AddTypesOf(function);
 
diff --git a/runtime/vm/precompiler.h b/runtime/vm/precompiler.h
index 5cae27e..ad7f0ca 100644
--- a/runtime/vm/precompiler.h
+++ b/runtime/vm/precompiler.h
@@ -299,6 +299,7 @@
   void ProcessFunction(const Function& function);
   void CheckForNewDynamicFunctions();
   void TraceConstFunctions();
+  void CollectCallbackFields();
 
   void TraceForRetainedFunctions();
   void DropFunctions();
diff --git a/runtime/vm/profiler.cc b/runtime/vm/profiler.cc
index 165822e..21b8bf8 100644
--- a/runtime/vm/profiler.cc
+++ b/runtime/vm/profiler.cc
@@ -335,11 +335,11 @@
   char* native_symbol_name =
       NativeSymbolResolver::LookupSymbolName(pc, &start);
   if (native_symbol_name == NULL) {
-    OS::Print("Frame[%" Pd "] = `unknown symbol` [0x%" Px "]\n",
-              frame_index, pc);
+    OS::PrintErr("Frame[%" Pd "] = `unknown symbol` [0x%" Px "]\n",
+                 frame_index, pc);
   } else {
-    OS::Print("Frame[%" Pd "] = `%s` [0x%" Px "]\n",
-              frame_index, native_symbol_name, pc);
+    OS::PrintErr("Frame[%" Pd "] = `%s` [0x%" Px "]\n",
+                 frame_index, native_symbol_name, pc);
     NativeSymbolResolver::FreeSymbolName(native_symbol_name);
   }
 }
@@ -351,8 +351,8 @@
   if (code.IsNull()) {
     DumpStackFrame(frame_index, pc);
   } else {
-    OS::Print("Frame[%" Pd "] = Dart:`%s` [0x%" Px "]\n",
-              frame_index, code.ToCString(), pc);
+    OS::PrintErr("Frame[%" Pd "] = Dart:`%s` [0x%" Px "]\n",
+                 frame_index, code.ToCString(), pc);
   }
 }
 
@@ -959,9 +959,9 @@
 
   const bool exited_dart_code = thread->HasExitedDartCode();
 
-  OS::Print("Dumping %s stack trace for thread %" Px "\n",
-            native_stack_trace ? "native" : "dart-only",
-            OSThread::ThreadIdToIntPtr(os_thread->trace_id()));
+  OS::PrintErr("Dumping %s stack trace for thread %" Px "\n",
+               native_stack_trace ? "native" : "dart-only",
+               OSThread::ThreadIdToIntPtr(os_thread->trace_id()));
 
   uintptr_t sp = Thread::GetCurrentStackPointer();
   uintptr_t fp = 0;
@@ -973,7 +973,7 @@
   uword stack_upper = 0;
 
   if (!InitialRegisterCheck(pc, fp, sp)) {
-    OS::Print(
+    OS::PrintErr(
         "Stack dump aborted because InitialRegisterCheck.\n");
     return;
   }
@@ -983,7 +983,7 @@
                                         sp,
                                         &stack_lower,
                                         &stack_upper)) {
-    OS::Print(
+    OS::PrintErr(
         "Stack dump aborted because GetAndValidateIsolateStackBounds.\n");
     return;
   }
@@ -1014,7 +1014,7 @@
                                               fp,
                                               sp);
   }
-  OS::Print("-- End of DumpStackTrace");
+  OS::PrintErr("-- End of DumpStackTrace");
 }
 
 
diff --git a/runtime/vm/regexp.cc b/runtime/vm/regexp.cc
index f119a25..9edfbf6 100644
--- a/runtime/vm/regexp.cc
+++ b/runtime/vm/regexp.cc
@@ -5251,13 +5251,7 @@
   const intptr_t kParamCount = RegExpMacroAssembler::kParamCount;
 
   Function& fn = Function::Handle(zone, Function::New(
-      // Append the regexp pattern to the function name.
-      String::Handle(zone, Symbols::New(thread,
-          String::Handle(zone, String::Concat(
-              String::Handle(zone, String::Concat(
-                  Symbols::ColonMatcher(),
-                  Symbols::ColonSpace(), Heap::kOld)),
-              String::Handle(regexp.pattern()), Heap::kOld)))),
+      Symbols::ColonMatcher(),
       RawFunction::kIrregexpFunction,
       true,  // Static.
       false,  // Not const.
diff --git a/runtime/vm/service.cc b/runtime/vm/service.cc
index 8ef6e89..c57890a 100644
--- a/runtime/vm/service.cc
+++ b/runtime/vm/service.cc
@@ -2493,18 +2493,8 @@
   const bool force_reload =
       BoolParameter::Parse(js->LookupParam("force"), false);
 
-  isolate->ReloadSources(force_reload);
+  isolate->ReloadSources(js, force_reload);
 
-  const Error& error = Error::Handle(isolate->sticky_reload_error());
-
-  if (error.IsNull()) {
-    PrintSuccess(js);
-  } else {
-    // Clear the sticky error.
-    isolate->clear_sticky_reload_error();
-    js->PrintError(kIsolateReloadFailed,
-                   "Isolate reload failed: %s", error.ToErrorCString());
-  }
   return true;
 }
 
diff --git a/runtime/vm/service_isolate.cc b/runtime/vm/service_isolate.cc
index 19ccf68..c5e2e75 100644
--- a/runtime/vm/service_isolate.cc
+++ b/runtime/vm/service_isolate.cc
@@ -331,7 +331,9 @@
                                                    NULL,
                                                    &error));
     if (isolate == NULL) {
-      OS::PrintErr("vm-service: Isolate creation error: %s\n", error);
+      if (FLAG_trace_service) {
+        OS::PrintErr("vm-service: Isolate creation error: %s\n", error);
+      }
       ServiceIsolate::SetServiceIsolate(NULL);
       ServiceIsolate::FinishedInitializing();
       ServiceIsolate::FinishedExiting();
diff --git a/runtime/vm/symbols.h b/runtime/vm/symbols.h
index 753594c..97d74af 100644
--- a/runtime/vm/symbols.h
+++ b/runtime/vm/symbols.h
@@ -298,7 +298,6 @@
   V(BooleanExpression, "boolean expression")                                   \
   V(MegamorphicMiss, "megamorphic_miss")                                       \
   V(CommaSpace, ", ")                                                          \
-  V(ColonSpace, ": ")                                                          \
   V(RParenArrow, ") => ")                                                      \
   V(SpaceExtendsSpace, " extends ")                                            \
   V(SpaceWhereNewLine, " where\n")                                             \
diff --git a/runtime/vm/unit_test.cc b/runtime/vm/unit_test.cc
index 9c89d9c..a877a1a 100644
--- a/runtime/vm/unit_test.cc
+++ b/runtime/vm/unit_test.cc
@@ -74,37 +74,45 @@
 }
 
 
-static bool IsImportableTestLib(const char* url_name) {
-  const char* kImportTestLibUri = "test:importable_lib";
-  static const intptr_t kImportTestLibUriLen = strlen(kImportTestLibUri);
-  return (strncmp(url_name, kImportTestLibUri, kImportTestLibUriLen) == 0);
+struct TestLibEntry {
+  const char* url;
+  const char* source;
+};
+
+
+static MallocGrowableArray<TestLibEntry>* test_libs_ = NULL;
+
+
+void TestCase::AddTestLib(const char* url, const char* source) {
+  if (test_libs_ == NULL) {
+    test_libs_ = new MallocGrowableArray<TestLibEntry>();
+  }
+  // If the test lib is already added, replace the source.
+  for (intptr_t i = 0; i < test_libs_->length(); i++) {
+    if (strcmp(url, (*test_libs_)[i].url) == 0) {
+      (*test_libs_)[i].source = source;
+      return;
+    }
+  }
+  TestLibEntry entry;
+  entry.url = url;
+  entry.source = source;
+  test_libs_->Add(entry);
 }
 
 
-const char* kDefaultImportableTestLibScript =
-    "importedFunc() => 'a';\n"
-    "importedIntFunc() => 4;\n"
-    "class ImportedMixin {\n"
-    "  mixinFunc() => 'mixin';\n"
-    "}\n";
-const char* importable_test_lib_script = kDefaultImportableTestLibScript;
-
-
-void TestCase::SetImportableTestLibScript(const char* source) {
-  importable_test_lib_script = source;
+const char* TestCase::GetTestLib(const char* url) {
+  if (test_libs_ == NULL) {
+    return NULL;
+  }
+  for (intptr_t i = 0; i < test_libs_->length(); i++) {
+    if (strcmp(url, (*test_libs_)[i].url) == 0) {
+      return (*test_libs_)[i].source;
+    }
+  }
+  return NULL;
 }
 
-
-void TestCase::RestoreImportableTestLibScript() {
-  importable_test_lib_script = kDefaultImportableTestLibScript;
-}
-
-
-static Dart_Handle ImportableTestLibSource() {
-  return DartUtils::NewString(importable_test_lib_script);
-}
-
-
 #ifndef PRODUCT
 static bool IsIsolateReloadTestLib(const char* url_name) {
   const char* kIsolateReloadTestLibUri = "test:isolate_reload_helper";
@@ -204,8 +212,10 @@
       return DartUtils::NewError("Do not know how to load '%s'", url_chars);
     }
   }
-  if (IsImportableTestLib(url_chars)) {
-    return Dart_LoadLibrary(url, Dart_Null(), ImportableTestLibSource(), 0, 0);
+  const char* lib_source = TestCase::GetTestLib(url_chars);
+  if (lib_source != NULL) {
+    Dart_Handle source = Dart_NewStringFromCString(lib_source);
+    return Dart_LoadLibrary(url, Dart_Null(), source, 0, 0);
   }
   NOT_IN_PRODUCT(
   if (IsIsolateReloadTestLib(url_chars)) {
@@ -280,14 +290,21 @@
 
 Dart_Handle TestCase::TriggerReload() {
   Isolate* isolate = Isolate::Current();
-
+  JSONStream js;
+  bool success = false;
   {
     TransitionNativeToVM transition(Thread::Current());
-    isolate->ReloadSources(false,  // force_reload
-                           true);  // dont_delete_reload_context
+    success = isolate->ReloadSources(&js,
+                                     false,  // force_reload
+                                     true);  // dont_delete_reload_context
+    fprintf(stderr, "RELOAD REPORT:\n%s\n", js.ToCString());
   }
 
-  return Dart_FinalizeLoading(false);
+  if (success) {
+    return Dart_FinalizeLoading(false);
+  } else {
+    return Dart_Null();
+  }
 }
 
 
@@ -295,7 +312,7 @@
   Isolate* isolate = Isolate::Current();
 
   if (isolate->reload_context() != NULL &&
-      isolate->reload_context()->has_error()) {
+      isolate->reload_context()->reload_aborted()) {
     // Return a handle to the error.
     return Api::NewHandle(Thread::Current(),
                           isolate->reload_context()->error());
diff --git a/runtime/vm/unit_test.h b/runtime/vm/unit_test.h
index 5a72dbb..8622a4f 100644
--- a/runtime/vm/unit_test.h
+++ b/runtime/vm/unit_test.h
@@ -314,9 +314,8 @@
   // Helper function which reloads the current isolate using |script|.
   static Dart_Handle ReloadTestScript(const char* script);
 
-  // Changes the default importable test lib script.
-  static void SetImportableTestLibScript(const char* source);
-  static void RestoreImportableTestLibScript();
+  static void AddTestLib(const char* url, const char* source);
+  static const char* GetTestLib(const char* url);
 
  private:
   static Dart_Isolate CreateIsolate(const uint8_t* buffer, const char* name);
diff --git a/sdk/lib/html/dart2js/html_dart2js.dart b/sdk/lib/html/dart2js/html_dart2js.dart
index b4f835b..3b0de9d 100644
--- a/sdk/lib/html/dart2js/html_dart2js.dart
+++ b/sdk/lib/html/dart2js/html_dart2js.dart
@@ -11507,11 +11507,11 @@
            another.y <= top + height;
   }
 
-  Point get topLeft => new Point(this.left, this.top);
-  Point get topRight => new Point(this.left + this.width, this.top);
-  Point get bottomRight => new Point(this.left + this.width,
+  Point get topLeft => new Point/*<num>*/(this.left, this.top);
+  Point get topRight => new Point/*<num>*/(this.left + this.width, this.top);
+  Point get bottomRight => new Point/*<num>*/(this.left + this.width,
       this.top + this.height);
-  Point get bottomLeft => new Point(this.left,
+  Point get bottomLeft => new Point/*<num>*/(this.left,
       this.top + this.height);
 
     // To suppress missing implicit constructor warnings.
@@ -13865,13 +13865,13 @@
     bool sameAsParent = identical(current, parent);
     bool foundAsParent = sameAsParent || parent.tagName == 'HTML';
     if (current == null || sameAsParent) {
-      if (foundAsParent) return new Point(0, 0);
+      if (foundAsParent) return new Point/*<num>*/(0, 0);
       throw new ArgumentError("Specified element is not a transitive offset "
           "parent of this element.");
     }
     Element parentOffset = current.offsetParent;
     Point p = Element._offsetToHelper(parentOffset, parent);
-    return new Point(p.x + current.offsetLeft, p.y + current.offsetTop);
+    return new Point/*<num>*/(p.x + current.offsetLeft, p.y + current.offsetTop);
   }
 
   static HtmlDocument _parseDocument;
@@ -24071,14 +24071,14 @@
 
   @DomName('MouseEvent.clientX')
   @DomName('MouseEvent.clientY')
-  Point get client => new Point(_clientX, _clientY);
+  Point get client => new Point/*<num>*/(_clientX, _clientY);
 
   @DomName('MouseEvent.movementX')
   @DomName('MouseEvent.movementY')
   @SupportedBrowser(SupportedBrowser.CHROME)
   @SupportedBrowser(SupportedBrowser.FIREFOX)
   @Experimental()
-  Point get movement => new Point(_movementX, _movementY);
+  Point get movement => new Point/*<num>*/(_movementX, _movementY);
 
   /**
    * The coordinates of the mouse pointer in target node coordinates.
@@ -24091,7 +24091,7 @@
     if (JS('bool', '!!#.offsetX', this)) {
       var x = JS('int', '#.offsetX', this);
       var y = JS('int', '#.offsetY', this);
-      return new Point(x, y);
+      return new Point/*<num>*/(x, y);
     } else {
       // Firefox does not support offsetX.
       if (!(this.target is Element)) {
@@ -24100,21 +24100,21 @@
       }
       Element target = this.target;
       var point = (this.client - target.getBoundingClientRect().topLeft);
-      return new Point(point.x.toInt(), point.y.toInt());
+      return new Point/*<num>*/(point.x.toInt(), point.y.toInt());
     }
   }
 
   @DomName('MouseEvent.screenX')
   @DomName('MouseEvent.screenY')
-  Point get screen => new Point(_screenX, _screenY);
+  Point get screen => new Point/*<num>*/(_screenX, _screenY);
 
   @DomName('MouseEvent.layerX')
   @DomName('MouseEvent.layerY')
-  Point get layer => new Point(_layerX, _layerY);
+  Point get layer => new Point/*<num>*/(_layerX, _layerY);
 
   @DomName('MouseEvent.pageX')
   @DomName('MouseEvent.pageY')
-  Point get page => new Point(_pageX, _pageY);
+  Point get page => new Point/*<num>*/(_pageX, _pageY);
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
@@ -32743,15 +32743,15 @@
 
   @DomName('Touch.clientX')
   @DomName('Touch.clientY')
-  Point get client => new Point(__clientX, __clientY);
+  Point get client => new Point/*<num>*/(__clientX, __clientY);
 
   @DomName('Touch.pageX')
   @DomName('Touch.pageY')
-  Point get page => new Point(__pageX, __pageY);
+  Point get page => new Point/*<num>*/(__pageX, __pageY);
 
   @DomName('Touch.screenX')
   @DomName('Touch.screenY')
-  Point get screen => new Point(__screenX, __screenY);
+  Point get screen => new Point/*<num>*/(__screenX, __screenY);
 
   @DomName('Touch.radiusX')
   @DocsEditable()
@@ -37486,11 +37486,11 @@
            another.y <= top + height;
   }
 
-  Point get topLeft => new Point(this.left, this.top);
-  Point get topRight => new Point(this.left + this.width, this.top);
-  Point get bottomRight => new Point(this.left + this.width,
+  Point get topLeft => new Point/*<num>*/(this.left, this.top);
+  Point get topRight => new Point/*<num>*/(this.left + this.width, this.top);
+  Point get bottomRight => new Point/*<num>*/(this.left + this.width,
       this.top + this.height);
-  Point get bottomLeft => new Point(this.left,
+  Point get bottomLeft => new Point/*<num>*/(this.left,
       this.top + this.height);
 
     // To suppress missing implicit constructor warnings.
diff --git a/sdk/lib/html/dartium/html_dartium.dart b/sdk/lib/html/dartium/html_dartium.dart
index 68ec664..080bfe3 100644
--- a/sdk/lib/html/dartium/html_dartium.dart
+++ b/sdk/lib/html/dartium/html_dartium.dart
@@ -12112,11 +12112,11 @@
            another.y <= top + height;
   }
 
-  Point get topLeft => new Point(this.left, this.top);
-  Point get topRight => new Point(this.left + this.width, this.top);
-  Point get bottomRight => new Point(this.left + this.width,
+  Point get topLeft => new Point/*<num>*/(this.left, this.top);
+  Point get topRight => new Point/*<num>*/(this.left + this.width, this.top);
+  Point get bottomRight => new Point/*<num>*/(this.left + this.width,
       this.top + this.height);
-  Point get bottomLeft => new Point(this.left,
+  Point get bottomLeft => new Point/*<num>*/(this.left,
       this.top + this.height);
 
     // To suppress missing implicit constructor warnings.
@@ -14449,13 +14449,13 @@
     bool sameAsParent = current == parent;
     bool foundAsParent = sameAsParent || parent.tagName == 'HTML';
     if (current == null || sameAsParent) {
-      if (foundAsParent) return new Point(0, 0);
+      if (foundAsParent) return new Point/*<num>*/(0, 0);
       throw new ArgumentError("Specified element is not a transitive offset "
           "parent of this element.");
     }
     Element parentOffset = current.offsetParent;
     Point p = Element._offsetToHelper(parentOffset, parent);
-    return new Point(p.x + current.offsetLeft, p.y + current.offsetTop);
+    return new Point/*<num>*/(p.x + current.offsetLeft, p.y + current.offsetTop);
   }
 
   static HtmlDocument _parseDocument;
@@ -26837,14 +26837,14 @@
 
   @DomName('MouseEvent.clientX')
   @DomName('MouseEvent.clientY')
-  Point get client => new Point(_clientX, _clientY);
+  Point get client => new Point/*<num>*/(_clientX, _clientY);
 
   @DomName('MouseEvent.movementX')
   @DomName('MouseEvent.movementY')
   @SupportedBrowser(SupportedBrowser.CHROME)
   @SupportedBrowser(SupportedBrowser.FIREFOX)
   @Experimental()
-  Point get movement => new Point(_movementX, _movementY);
+  Point get movement => new Point/*<num>*/(_movementX, _movementY);
 
   /**
    * The coordinates of the mouse pointer in target node coordinates.
@@ -26853,19 +26853,19 @@
    * after the event has fired or if the element has CSS transforms affecting
    * it.
    */
-  Point get offset => new Point(_offsetX, _offsetY);
+  Point get offset => new Point/*<num>*/(_offsetX, _offsetY);
 
   @DomName('MouseEvent.screenX')
   @DomName('MouseEvent.screenY')
-  Point get screen => new Point(_screenX, _screenY);
+  Point get screen => new Point/*<num>*/(_screenX, _screenY);
 
   @DomName('MouseEvent.layerX')
   @DomName('MouseEvent.layerY')
-  Point get layer => new Point(_layerX, _layerY);
+  Point get layer => new Point/*<num>*/(_layerX, _layerY);
 
   @DomName('MouseEvent.pageX')
   @DomName('MouseEvent.pageY')
-  Point get page => new Point(_pageX, _pageY);
+  Point get page => new Point/*<num>*/(_pageX, _pageY);
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
@@ -36962,15 +36962,15 @@
 
   @DomName('Touch.clientX')
   @DomName('Touch.clientY')
-  Point get client => new Point(__clientX, __clientY);
+  Point get client => new Point/*<num>*/(__clientX, __clientY);
 
   @DomName('Touch.pageX')
   @DomName('Touch.pageY')
-  Point get page => new Point(__pageX, __pageY);
+  Point get page => new Point/*<num>*/(__pageX, __pageY);
 
   @DomName('Touch.screenX')
   @DomName('Touch.screenY')
-  Point get screen => new Point(__screenX, __screenY);
+  Point get screen => new Point/*<num>*/(__screenX, __screenY);
 
   @DomName('Touch.radiusX')
   @DocsEditable()
@@ -37662,10 +37662,10 @@
     if ((blob_OR_source_OR_stream is Blob || blob_OR_source_OR_stream == null)) {
       return _blink.BlinkURL.instance.createObjectURL_Callback_1_(blob_OR_source_OR_stream);
     }
-    if ((blob_OR_source_OR_stream is MediaSource)) {
+    if ((blob_OR_source_OR_stream is MediaStream)) {
       return _blink.BlinkURL.instance.createObjectURL_Callback_1_(blob_OR_source_OR_stream);
     }
-    if ((blob_OR_source_OR_stream is MediaStream)) {
+    if ((blob_OR_source_OR_stream is MediaSource)) {
       return _blink.BlinkURL.instance.createObjectURL_Callback_1_(blob_OR_source_OR_stream);
     }
     throw new ArgumentError("Incorrect number or type of arguments");
@@ -41794,11 +41794,11 @@
            another.y <= top + height;
   }
 
-  Point get topLeft => new Point(this.left, this.top);
-  Point get topRight => new Point(this.left + this.width, this.top);
-  Point get bottomRight => new Point(this.left + this.width,
+  Point get topLeft => new Point/*<num>*/(this.left, this.top);
+  Point get topRight => new Point/*<num>*/(this.left + this.width, this.top);
+  Point get bottomRight => new Point/*<num>*/(this.left + this.width,
       this.top + this.height);
-  Point get bottomLeft => new Point(this.left,
+  Point get bottomLeft => new Point/*<num>*/(this.left,
       this.top + this.height);
 
     // To suppress missing implicit constructor warnings.
diff --git a/sdk/lib/js/dartium/js_dartium.dart b/sdk/lib/js/dartium/js_dartium.dart
index 4ac1197..a8f0661 100644
--- a/sdk/lib/js/dartium/js_dartium.dart
+++ b/sdk/lib/js/dartium/js_dartium.dart
@@ -642,7 +642,8 @@
       if (isDom || isJsInterop) {
         // TODO(jacobr): verify class implements JavaScriptObject.
         var className = mirrors.MirrorSystem.getName(clazz.simpleName);
-        bool isPrivate = className.startsWith('_');
+        bool isPrivateUserDefinedClass =
+            className.startsWith('_') && !dartLibrary;
         var classNameImpl = '${className}Impl';
         var sbPatch = new StringBuffer();
         if (isJsInterop) {
@@ -715,7 +716,7 @@
           sbPatch.write(
               "  static Type get instanceRuntimeType => ${classNameImpl};\n");
         }
-        if (isPrivate) {
+        if (isPrivateUserDefinedClass) {
           sb.write("""
 class ${escapePrivateClassPrefix}${className} implements $className {}
 """);
@@ -810,6 +811,9 @@
 
   for (var typeMirror in jsInterfaceTypes) {
     mirrors.LibraryMirror libraryMirror = typeMirror.owner;
+    var location = libraryMirror.location;
+    var dartLibrary = location != null && location.sourceUri.scheme == 'dart';
+
     var prefixName;
     if (libraryPrefixes.containsKey(libraryMirror)) {
       prefixName = libraryPrefixes[libraryMirror];
@@ -831,8 +835,9 @@
     var isFunction = typeMirror.isSubtypeOf(functionMirror);
     var isJSObject = typeMirror.isSubtypeOf(jsObjectMirror);
     var className = mirrors.MirrorSystem.getName(typeMirror.simpleName);
-    var isPrivate = className.startsWith('_');
-    if (isPrivate) className = '${escapePrivateClassPrefix}${className}';
+    var isPrivateUserDefinedClass = className.startsWith('_') && !dartLibrary;
+    if (isPrivateUserDefinedClass)
+      className = '${escapePrivateClassPrefix}${className}';
     var fullName = '${prefixName}.${className}';
     (isArray ? implementsArray : implements).add(fullName);
     if (!isArray && !isFunction && !isJSObject) {
diff --git a/sdk/lib/vmservice/devfs.dart b/sdk/lib/vmservice/devfs.dart
index 35af748..4735512 100644
--- a/sdk/lib/vmservice/devfs.dart
+++ b/sdk/lib/vmservice/devfs.dart
@@ -37,10 +37,18 @@
     }
     Uri pathUri;
     try {
-      pathUri = Uri.parse(path);
+      pathUri = new Uri.file(path);
     } on FormatException catch(e) {
       return null;
     }
+
+    try {
+      // Make sure that this pathUri can be converted to a file path.
+      pathUri.toFilePath();
+    } on UnsupportedError catch (e) {
+      return null;
+    }
+
     Uri resolvedUri = uri.resolveUri(pathUri);
     if (!resolvedUri.toString().startsWith(uri.toString())) {
       // Resolved uri must be within the filesystem's base uri.
@@ -313,6 +321,10 @@
       return _encodeFileSystemDoesNotExistError(message, fsName);
     }
     var fileList = await listFiles(fs.uri);
+    // Remove any url-encoding in the filenames.
+    for (int i = 0; i < fileList.length; i++) {
+      fileList[i]['name'] = Uri.decodeFull(fileList[i]['name']);
+    }
     var result = { 'type': 'FSFileList', 'files': fileList };
     return encodeResult(message, result);
   }
diff --git a/tests/co19/co19-runtime.status b/tests/co19/co19-runtime.status
index efbfd7a..bc8772c 100644
--- a/tests/co19/co19-runtime.status
+++ b/tests/co19/co19-runtime.status
@@ -193,7 +193,7 @@
 [ $compiler == precompiler && $runtime == dart_precompiled && $arch == simarm ]
 LibTest/typed_data/Float32x4/operator_division_A01_t02: RuntimeError # Issue #26675
 
-[ $hot_reload ]
+[ $hot_reload || $hot_reload_rollback ]
 Language/Expressions/Assignment/prefix_object_t02: Crash # Requires deferred libraries
 Language/Expressions/Constants/constant_constructor_t03: Crash # Requires deferred libraries
 Language/Expressions/Constants/identifier_denotes_a_constant_t06: Crash # Requires deferred libraries
diff --git a/tests/isolate/isolate.status b/tests/isolate/isolate.status
index 1902a62..ab8dec3 100644
--- a/tests/isolate/isolate.status
+++ b/tests/isolate/isolate.status
@@ -208,7 +208,7 @@
 [ $compiler == precompiler && $runtime == dart_precompiled && $system == android ]
 *: Skip # Issue #26373
 
-[ $hot_reload ]
+[ $hot_reload || $hot_reload_rollback ]
 function_send_test: Pass, Fail # Closure identity
 message3_test/fun: Pass, Fail # Closure identity
 deferred_in_isolate_test: Crash # Requires deferred libraries
diff --git a/tests/language/language.status b/tests/language/language.status
index 34798b6..64c1c4a 100644
--- a/tests/language/language.status
+++ b/tests/language/language.status
@@ -246,7 +246,7 @@
 vm/optimized_guarded_field_isolates_test: Skip # Issue #26373
 issue23244_test: Skip # Issue #26373
 
-[ $hot_reload ]
+[ $hot_reload || $hot_reload_rollback ]
 static_closure_identical_test: Pass, Fail # Closure identity
 cha_deopt1_test: Crash # Requires deferred libraries
 cha_deopt2_test: Crash # Requires deferred libraries
diff --git a/tests/lib/lib.status b/tests/lib/lib.status
index 37f4f1e..469b3b3 100644
--- a/tests/lib/lib.status
+++ b/tests/lib/lib.status
@@ -374,19 +374,13 @@
 # version.
 mirrors/accessor_cache_overflow_test: Skip
 
-[ $hot_reload ]
+[ $hot_reload || $hot_reload_rollback ]
+async/multiple_timer_test: Pass, Fail # Timing related
+math/double_pow_test: RuntimeError, Pass, Fail # Issue 26887
 async/stream_transformer_test: Pass, Fail # Closure identity
 mirrors/closurization_equivalence_test: SkipByDesign # Method equality
 mirrors/fake_function_with_call_test: SkipByDesign # Method equality
 
-async/multiple_timer_test: Pass, Fail # Timing related
-
-mirrors/generic_bounded_by_type_parameter_test/02: Fail # Type equality - Issue 26869
-mirrors/typedef_reflected_type_test/01: Fail # Type equality - Issue 26869
-mirrors/generic_bounded_test/02: Fail # Type equality - Issue 26869
-mirrors/generic_bounded_by_type_parameter_test/02: Fail # Type equality - Issue 26869
-mirrors/typedef_reflected_type_test/01: Fail # Type equality - Issue 26869
-
 mirrors/library_enumeration_deferred_loading_test: Crash # Deferred loading
 mirrors/library_imports_deferred_test: Crash # Deferred loading
 mirrors/library_import_deferred_loading_test: Crash # Deferred loading
@@ -396,7 +390,8 @@
 mirrors/deferred_mirrors_metatarget_test: Crash # Deferred loading
 mirrors/load_library_test: Crash # Deferred loading
 
+[ $hot_reload ]
 mirrors/metadata_scope_test/none: Fail # Constant equality - Issue 26868
-
-typed_data/float32x4_unbox_regress_test: Pass, Crash # Issue 26888
-math/double_pow_test: Pass, Fail # Issue 26887
+mirrors/generic_bounded_test/02: Fail # Type equality - Issue 26869
+mirrors/typedef_reflected_type_test/01: Fail # Type equality - Issue 26869
+mirrors/generic_bounded_by_type_parameter_test/02: Fail # Type equality - Issue 26869
diff --git a/tests/standalone/io/issue_26954_test.dart b/tests/standalone/io/issue_26954_test.dart
new file mode 100644
index 0000000..5e8738b
--- /dev/null
+++ b/tests/standalone/io/issue_26954_test.dart
@@ -0,0 +1,35 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:convert';
+import 'dart:io';
+
+final List<int> _UTF8_PLS_CERTIFICATE = UTF8.encode('''
+-----BEGIN CERTIFICATE-----
+MIIDZDCCAkygAwIBAgIBATANBgkqhkiG9w0BAQsFADAgMR4wHAYDVQQDDBVpbnRl
+cm1lZGlhdGVhdXRob3JpdHkwHhcNMTUxMDI3MTAyNjM1WhcNMjUxMDI0MTAyNjM1
+WjAUMRIwEAYDVQQDDAlsb2NhbGhvc3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
+ggEKAoIBAQCkg/Qr8RQeLTOSgCkyiEX2ztgkgscX8hKGHEHdvlkmVK3JVEIIwkvu
+/Y9LtHZUia3nPAgqEEbexzTENZjSCcC0V6I2XW/e5tIE3rO0KLZyhtZhN/2SfJ6p
+KbOh0HLr1VtkKJGp1tzUmHW/aZI32pK60ZJ/N917NLPCJpCaL8+wHo3+w3oNqln6
+oJsfgxy9SUM8Bsc9WMYKMUdqLO1QKs1A5YwqZuO7Mwj+4LY2QDixC7Ua7V9YAPo2
+1SBeLvMCHbYxSPCuxcZ/kDkgax/DF9u7aZnGhMImkwBka0OQFvpfjKtTIuoobTpe
+PAG7MQYXk4RjnjdyEX/9XAQzvNo1CDObAgMBAAGjgbQwgbEwPAYDVR0RBDUwM4IJ
+bG9jYWxob3N0ggkxMjcuMC4wLjGCAzo6MYcEfwAAAYcQAAAAAAAAAAAAAAAAAAAA
+ATAMBgNVHRMBAf8EAjAAMB0GA1UdDgQWBBSvhJo6taTggJQBukEvMo/PDk8tKTAf
+BgNVHSMEGDAWgBS98L4T5RaIToE3DkBRsoeWPil0eDAOBgNVHQ8BAf8EBAMCA6gw
+EwYDVR0lBAwwCgYIKwYBBQUHAwEwDQYJKoZIhvcNAQELBQADggEBAHLOt0mL2S4A
+B7vN7KsfQeGlVgZUVlEjem6kqBh4fIzl4CsQuOO8oJ0FlO1z5JAIo98hZinymJx1
+phBVpyGIKakT/etMH0op5evLe9dD36VA3IM/FEv5ibk35iGnPokiJXIAcdHd1zam
+YaTHRAnZET5S03+7BgRTKoRuszhbvuFz/vKXaIAnVNOF4Gf2NUJ/Ax7ssJtRkN+5
+UVxe8TZVxzgiRv1uF6NTr+J8PDepkHCbJ6zEQNudcFKAuC56DN1vUe06gRDrNbVq
+2JHEh4pRfMpdsPCrS5YHBjVq/XHtFHgwDR6g0WTwSUJvDeM4OPQY5f61FB0JbFza
+PkLkXmoIod8=
+-----END CERTIFICATE-----''');
+
+main() {
+  // create context for establishing socket later
+  final _context = SecurityContext.defaultContext;
+  _context.useCertificateChainBytes(_UTF8_PLS_CERTIFICATE);
+}
diff --git a/tests/standalone/io/stdio_implicit_close_script.dart b/tests/standalone/io/stdio_implicit_close_script.dart
new file mode 100644
index 0000000..4be58a88
--- /dev/null
+++ b/tests/standalone/io/stdio_implicit_close_script.dart
@@ -0,0 +1,20 @@
+// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "dart:io";
+
+void main(List<String> arguments) {
+  // Access stdout and stderr so that the system grabs a handle to it. This
+  // initializes some internal structures.
+  if (stdout.hashCode == -1234 && stderr.hashCode == (stderr.hashCode + 1)) {
+    throw "we have other problems.";
+  }
+
+  if (arguments.contains("stdout")) {
+    stdout.close();
+  }
+  if (arguments.contains("stderr")) {
+    stderr.close();
+  }
+}
diff --git a/tests/standalone/io/stdio_implicit_close_test.dart b/tests/standalone/io/stdio_implicit_close_test.dart
new file mode 100644
index 0000000..dc67f0e
--- /dev/null
+++ b/tests/standalone/io/stdio_implicit_close_test.dart
@@ -0,0 +1,56 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "package:async_helper/async_helper.dart";
+import "package:expect/expect.dart";
+import "dart:convert";
+import "dart:io";
+
+void test({bool closeStdout, bool closeStderr}) {
+  var scriptFile = "stdio_implicit_close_script.dart";
+  var script = Platform.script.resolve(scriptFile).toFilePath();
+
+  // Relying on these flags to print something specific on stdout and stderr
+  // is brittle, but otherwise we would need to add our own flag.
+  var arguments = [
+      "--print-metrics",  // Prints on stderr.
+      "--timing",         // Prints on stdout.
+      script,
+  ];
+  if (closeStdout) arguments.add("stdout");
+  if (closeStderr) arguments.add("stderr");
+
+  asyncStart();
+  Process.run(Platform.executable,
+              arguments,
+              stdoutEncoding: ASCII,
+              stderrEncoding: ASCII).then((result) {
+                  print(result.stdout);
+                  print(result.stderr);
+    Expect.equals(0, result.exitCode);
+
+    if (closeStdout) {
+      Expect.equals("", result.stdout);
+    } else {
+      Expect.isTrue(result.stdout.contains("Timing for"));
+    }
+
+    if (closeStderr) {
+      Expect.equals("", result.stderr);
+    } else {
+      Expect.isTrue(result.stderr.contains("Printing metrics"));
+    }
+
+    asyncEnd();
+  });
+}
+
+void main() {
+  asyncStart();
+  test(closeStdout: false, closeStderr: false);
+  test(closeStdout: false, closeStderr: true);
+  test(closeStdout: true, closeStderr: false);
+  test(closeStdout: true, closeStderr: true);
+  asyncEnd();
+}
diff --git a/tests/standalone/standalone.status b/tests/standalone/standalone.status
index ff14249..3476560 100644
--- a/tests/standalone/standalone.status
+++ b/tests/standalone/standalone.status
@@ -252,6 +252,7 @@
 io/http_client_stays_alive_test: Skip # Platform.executable
 io/print_sync_test: Skip # Platform.executable
 io/signals_test: Skip # Platform.executable
+io/stdio_implicit_close_test: Skip # Platform.executable
 io/stdio_nonblocking_test: Skip # Platform.executable
 io/regress_7191_test: Skip # Platform.executable
 io/secure_unauthorized_test: Skip # Platform.executable
@@ -287,6 +288,7 @@
 no_support_il_printer_test: SkipByDesign
 no_support_service_test: SkipByDesign
 no_support_timeline_test: SkipByDesign
+io/stdio_implicit_close_test: Skip # SkipByDesign
 
 # Following tests are skipped on dart_app as package mapping is not supported.
 [ $runtime == dart_precompiled || $runtime == dart_app ]
@@ -322,7 +324,7 @@
 [ $runtime == vm || $runtime == dart_app || $runtime == dart_precompiled ]
 deferred_transitive_import_error_test: Skip # Contains intentional errors.
 
-[ $hot_reload ]
+[ $hot_reload || $hot_reload_rollback ]
 deferred_transitive_import_error_test: Crash # Uses deferred imports.
 package/*: SkipByDesign # Launches VMs in interesting ways.
 
diff --git a/tests/utils/utils.status b/tests/utils/utils.status
index 66ec0d2..e2df361 100644
--- a/tests/utils/utils.status
+++ b/tests/utils/utils.status
@@ -21,6 +21,6 @@
 dummy_compiler_test: Crash # Issue 24485
 recursive_import_test: Crash # Issue 24485
 
-[ $hot_reload ]
+[ $hot_reload || $hot_reload_rollback ]
 recursive_import_test: Skip # Running dart2js under frequent reloads is slow.
 dummy_compiler_test: Skip # Running dart2js under frequent reloads is slow.
diff --git a/tools/VERSION b/tools/VERSION
index 064bcd1..3eb18d8 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 1
 MINOR 19
 PATCH 0
-PRERELEASE 2
-PRERELEASE_PATCH 3
+PRERELEASE 3
+PRERELEASE_PATCH 0
diff --git a/tools/build.py b/tools/build.py
index 055b19a..a27dd41 100755
--- a/tools/build.py
+++ b/tools/build.py
@@ -60,7 +60,7 @@
       default=utils.GuessArchitecture())
   result.add_option("--os",
     help='Target OSs (comma-separated).',
-    metavar='[all,host,android,fuchsia]',
+    metavar='[all,host,android]',
     default='host')
   result.add_option("-t", "--toolchain",
     help='Cross-compiler toolchain path',
@@ -109,11 +109,11 @@
       return False
   options.os = [ProcessOsOption(os_name) for os_name in options.os]
   for os_name in options.os:
-    if not os_name in ['android', 'freebsd', 'fuchsia', 'linux', 'macos', 'win32']:
+    if not os_name in ['android', 'freebsd', 'linux', 'macos', 'win32']:
       print "Unknown os %s" % os_name
       return False
     if os_name != HOST_OS:
-      if os_name != 'android' and os_name != 'fuchsia':
+      if os_name != 'android':
         print "Unsupported target os %s" % os_name
         return False
       if not HOST_OS in ['linux']:
@@ -148,13 +148,6 @@
     if arch == 'x64':
       return os.path.join(android_toolchain, 'x86_64-linux-android')
 
-  if target_os == 'fuchsia':
-    fuchsia_toolchain = GetFuchsiaToolchainDir(HOST_OS, arch)
-    if arch == 'arm64':
-      return os.path.join(fuchsia_toolchain, 'aarch64-elf')
-    if arch == 'x64':
-      return os.path.join(fuchsia_toolchain, 'x86_64-elf')
-
   # If no cross compiler is specified, only try to figure one out on Linux.
   if not HOST_OS in ['linux']:
     raise Exception('Unless --toolchain is used cross-building is only '
@@ -182,8 +175,6 @@
   linker = ""
   if target_os == 'android':
     linker = os.path.join(DART_ROOT, 'tools', 'android_link.py')
-  elif target_os == 'fuchsia':
-    linker = os.path.join(DART_ROOT, 'tools', 'fuchsia_link.py')
   elif toolchainprefix:
     linker = toolchainprefix + "-g++"
 
@@ -235,28 +226,6 @@
   return android_toolchain
 
 
-def GetFuchsiaToolchainDir(host_os, target_arch):
-  global THIRD_PARTY_ROOT
-  if host_os not in ['linux']:
-    raise Exception('Unsupported host os %s' % host_os)
-  if target_arch not in ['x64', 'arm64',]:
-    raise Exception('Unsupported target architecture %s' % target_arch)
-
-  # Set up path to the Android NDK.
-  CheckDirExists(THIRD_PARTY_ROOT, 'third party tools')
-  fuchsia_tools = os.path.join(THIRD_PARTY_ROOT, 'fuchsia_tools')
-  CheckDirExists(fuchsia_tools, 'Fuchsia tools')
-
-  toolchain_arch = 'x86_64-elf-5.3.0-Linux-x86_64'
-  if target_arch == 'arm64':
-    toolchain_arch = 'aarch64-elf-5.3.0-Linux-x86_64'
-  fuchsia_toolchain = os.path.join(
-      fuchsia_tools, 'toolchains', toolchain_arch, 'bin')
-  CheckDirExists(fuchsia_toolchain, 'Fuchsia toolchain')
-
-  return fuchsia_toolchain
-
-
 def Execute(args):
   process = subprocess.Popen(args)
   process.wait()
diff --git a/tools/dom/templates/html/dart2js/impl_MouseEvent.darttemplate b/tools/dom/templates/html/dart2js/impl_MouseEvent.darttemplate
index 8077fb0..f5b7e1b 100644
--- a/tools/dom/templates/html/dart2js/impl_MouseEvent.darttemplate
+++ b/tools/dom/templates/html/dart2js/impl_MouseEvent.darttemplate
@@ -24,14 +24,14 @@
 
   @DomName('MouseEvent.clientX')
   @DomName('MouseEvent.clientY')
-  Point get client => new Point(_clientX, _clientY);
+  Point get client => new Point/*<num>*/(_clientX, _clientY);
 
   @DomName('MouseEvent.movementX')
   @DomName('MouseEvent.movementY')
   @SupportedBrowser(SupportedBrowser.CHROME)
   @SupportedBrowser(SupportedBrowser.FIREFOX)
   @Experimental()
-  Point get movement => new Point(_movementX, _movementY);
+  Point get movement => new Point/*<num>*/(_movementX, _movementY);
 
   /**
    * The coordinates of the mouse pointer in target node coordinates.
@@ -44,7 +44,7 @@
     if (JS('bool', '!!#.offsetX', this)) {
       var x = JS('int', '#.offsetX', this);
       var y = JS('int', '#.offsetY', this);
-      return new Point(x, y);
+      return new Point/*<num>*/(x, y);
     } else {
       // Firefox does not support offsetX.
       if (!(this.target is Element)) {
@@ -53,19 +53,19 @@
       }
       Element target = this.target;
       var point = (this.client - target.getBoundingClientRect().topLeft);
-      return new Point(point.x.toInt(), point.y.toInt());
+      return new Point/*<num>*/(point.x.toInt(), point.y.toInt());
     }
   }
 
   @DomName('MouseEvent.screenX')
   @DomName('MouseEvent.screenY')
-  Point get screen => new Point(_screenX, _screenY);
+  Point get screen => new Point/*<num>*/(_screenX, _screenY);
 
   @DomName('MouseEvent.layerX')
   @DomName('MouseEvent.layerY')
-  Point get layer => new Point(_layerX, _layerY);
+  Point get layer => new Point/*<num>*/(_layerX, _layerY);
 
   @DomName('MouseEvent.pageX')
   @DomName('MouseEvent.pageY')
-  Point get page => new Point(_pageX, _pageY);
+  Point get page => new Point/*<num>*/(_pageX, _pageY);
 }
diff --git a/tools/dom/templates/html/dartium/impl_MouseEvent.darttemplate b/tools/dom/templates/html/dartium/impl_MouseEvent.darttemplate
index 1b2bbc8..229afe6 100644
--- a/tools/dom/templates/html/dartium/impl_MouseEvent.darttemplate
+++ b/tools/dom/templates/html/dartium/impl_MouseEvent.darttemplate
@@ -43,14 +43,14 @@
 
   @DomName('MouseEvent.clientX')
   @DomName('MouseEvent.clientY')
-  Point get client => new Point(_clientX, _clientY);
+  Point get client => new Point/*<num>*/(_clientX, _clientY);
 
   @DomName('MouseEvent.movementX')
   @DomName('MouseEvent.movementY')
   @SupportedBrowser(SupportedBrowser.CHROME)
   @SupportedBrowser(SupportedBrowser.FIREFOX)
   @Experimental()
-  Point get movement => new Point(_movementX, _movementY);
+  Point get movement => new Point/*<num>*/(_movementX, _movementY);
 
   /**
    * The coordinates of the mouse pointer in target node coordinates.
@@ -59,17 +59,17 @@
    * after the event has fired or if the element has CSS transforms affecting
    * it.
    */
-  Point get offset => new Point(_offsetX, _offsetY);
+  Point get offset => new Point/*<num>*/(_offsetX, _offsetY);
 
   @DomName('MouseEvent.screenX')
   @DomName('MouseEvent.screenY')
-  Point get screen => new Point(_screenX, _screenY);
+  Point get screen => new Point/*<num>*/(_screenX, _screenY);
 
   @DomName('MouseEvent.layerX')
   @DomName('MouseEvent.layerY')
-  Point get layer => new Point(_layerX, _layerY);
+  Point get layer => new Point/*<num>*/(_layerX, _layerY);
 
   @DomName('MouseEvent.pageX')
   @DomName('MouseEvent.pageY')
-  Point get page => new Point(_pageX, _pageY);
+  Point get page => new Point/*<num>*/(_pageX, _pageY);
 }
diff --git a/tools/dom/templates/html/impl/impl_ClientRect.darttemplate b/tools/dom/templates/html/impl/impl_ClientRect.darttemplate
index 22f115e..f52240a 100644
--- a/tools/dom/templates/html/impl/impl_ClientRect.darttemplate
+++ b/tools/dom/templates/html/impl/impl_ClientRect.darttemplate
@@ -89,11 +89,11 @@
            another.y <= top + height;
   }
 
-  Point get topLeft => new Point(this.left, this.top);
-  Point get topRight => new Point(this.left + this.width, this.top);
-  Point get bottomRight => new Point(this.left + this.width,
+  Point get topLeft => new Point/*<num>*/(this.left, this.top);
+  Point get topRight => new Point/*<num>*/(this.left + this.width, this.top);
+  Point get bottomRight => new Point/*<num>*/(this.left + this.width,
       this.top + this.height);
-  Point get bottomLeft => new Point(this.left,
+  Point get bottomLeft => new Point/*<num>*/(this.left,
       this.top + this.height);
 
   $!MEMBERS}
diff --git a/tools/dom/templates/html/impl/impl_DOMRectReadOnly.darttemplate b/tools/dom/templates/html/impl/impl_DOMRectReadOnly.darttemplate
index b17b5bc..e9bf8a6 100644
--- a/tools/dom/templates/html/impl/impl_DOMRectReadOnly.darttemplate
+++ b/tools/dom/templates/html/impl/impl_DOMRectReadOnly.darttemplate
@@ -89,11 +89,11 @@
            another.y <= top + height;
   }
 
-  Point get topLeft => new Point(this.left, this.top);
-  Point get topRight => new Point(this.left + this.width, this.top);
-  Point get bottomRight => new Point(this.left + this.width,
+  Point get topLeft => new Point/*<num>*/(this.left, this.top);
+  Point get topRight => new Point/*<num>*/(this.left + this.width, this.top);
+  Point get bottomRight => new Point/*<num>*/(this.left + this.width,
       this.top + this.height);
-  Point get bottomLeft => new Point(this.left,
+  Point get bottomLeft => new Point/*<num>*/(this.left,
       this.top + this.height);
 
   $!MEMBERS}
diff --git a/tools/dom/templates/html/impl/impl_Element.darttemplate b/tools/dom/templates/html/impl/impl_Element.darttemplate
index c9ef54a..e89c912 100644
--- a/tools/dom/templates/html/impl/impl_Element.darttemplate
+++ b/tools/dom/templates/html/impl/impl_Element.darttemplate
@@ -1272,13 +1272,13 @@
 $endif
     bool foundAsParent = sameAsParent || parent.tagName == 'HTML';
     if (current == null || sameAsParent) {
-      if (foundAsParent) return new Point(0, 0);
+      if (foundAsParent) return new Point/*<num>*/(0, 0);
       throw new ArgumentError("Specified element is not a transitive offset "
           "parent of this element.");
     }
     Element parentOffset = current.offsetParent;
     Point p = Element._offsetToHelper(parentOffset, parent);
-    return new Point(p.x + current.offsetLeft, p.y + current.offsetTop);
+    return new Point/*<num>*/(p.x + current.offsetLeft, p.y + current.offsetTop);
   }
 
   static HtmlDocument _parseDocument;
diff --git a/tools/dom/templates/html/impl/impl_Touch.darttemplate b/tools/dom/templates/html/impl/impl_Touch.darttemplate
index 889485d..a23e2f5 100644
--- a/tools/dom/templates/html/impl/impl_Touch.darttemplate
+++ b/tools/dom/templates/html/impl/impl_Touch.darttemplate
@@ -32,15 +32,15 @@
 
   @DomName('Touch.clientX')
   @DomName('Touch.clientY')
-  Point get client => new Point(__clientX, __clientY);
+  Point get client => new Point/*<num>*/(__clientX, __clientY);
 
   @DomName('Touch.pageX')
   @DomName('Touch.pageY')
-  Point get page => new Point(__pageX, __pageY);
+  Point get page => new Point/*<num>*/(__pageX, __pageY);
 
   @DomName('Touch.screenX')
   @DomName('Touch.screenY')
-  Point get screen => new Point(__screenX, __screenY);
+  Point get screen => new Point/*<num>*/(__screenX, __screenY);
 
   @DomName('Touch.radiusX')
   @DocsEditable()
diff --git a/tools/fuchsia_link.py b/tools/fuchsia_link.py
deleted file mode 100755
index 74936b0..0000000
--- a/tools/fuchsia_link.py
+++ /dev/null
@@ -1,127 +0,0 @@
-#!/usr/bin/env python
-
-# Copyright (c) 2016 The Dart Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-"""
-This script performs the final link step for Fuchsia NDK executables.
-Usage:
-./fuchsia_link {arm,arm64,ia32} {executable,library,shared_library}
-               {host,target} [linker args]
-"""
-
-import os
-import subprocess
-import sys
-
-# Figure out where we are.
-SCRIPT_DIR = os.path.dirname(sys.argv[0])
-DART_ROOT = os.path.realpath(os.path.join(SCRIPT_DIR, '..'))
-THIRD_PARTY_ROOT = os.path.join(DART_ROOT, 'third_party')
-
-
-def CheckDirExists(path, docstring):
-  if not os.path.isdir(path):
-    raise Exception('Could not find %s directory %s'
-          % (docstring, path))
-
-
-def execute(args):
-  process = subprocess.Popen(args)
-  process.wait()
-  return process.returncode
-
-
-def main():
-  if len(sys.argv) < 5:
-    raise Exception(sys.argv[0] + " failed: not enough arguments")
-
-  # gyp puts -shared first in a shared_library link. Remove it.
-  if sys.argv[1] == '-shared':
-    sys.argv.remove('-shared')
-
-  # Grab the command line arguments.
-  target_arch = sys.argv[1]
-  link_type = sys.argv[2]
-  link_target = sys.argv[3]
-  link_args = sys.argv[4:]
-
-  # Check arguments.
-  if target_arch not in ['arm64', 'x64',]:
-    raise Exception(sys.argv[0] +
-        " first argument must be 'arm64', or 'x64'")
-  if link_type not in ['executable', 'library', 'shared_library']:
-    raise Exception(sys.argv[0] +
-      " second argument must be 'executable' or 'library' or 'shared_library'")
-  if link_target not in ['host', 'target']:
-    raise Exception(sys.argv[0] + " third argument must be 'host' or 'target'")
-
-  # TODO(zra): Figure out how to link a shared library with the
-  # cross-compilers. For now, we disable it by generating empty files
-  # for the results. We disable it here to avoid inspecting the OS type in
-  # the gyp files.
-  if link_type == 'shared_library':
-    print "NOT linking shared library for Fuchsia."
-    o_index = link_args.index('-o')
-    output = os.path.join(DART_ROOT, link_args[o_index + 1])
-    open(output, 'a').close()
-    sys.exit(0)
-
-  # Set up path to the Fuchsia NDK.
-  CheckDirExists(THIRD_PARTY_ROOT, 'third party tools')
-  fuchsia_tools = os.path.join(THIRD_PARTY_ROOT, 'fuchsia_tools')
-  CheckDirExists(fuchsia_tools, 'Fuchsia tools')
-
-  # Set up the directory of the Fuchsia NDK cross-compiler toolchain.
-  toolchain_arch = 'x86_64-elf-5.3.0-Linux-x86_64'
-  if target_arch == 'arm64':
-    toolchain_arch = 'aarch64-elf-5.3.0-Linux-x86_64'
-  fuchsia_toolchain = os.path.join(
-      fuchsia_tools, 'toolchains', toolchain_arch, 'bin')
-  CheckDirExists(fuchsia_toolchain, 'Fuchsia toolchain')
-
-  # Set up the path to the linker executable.
-  fuchsia_linker = os.path.join(fuchsia_toolchain, 'x86_64-elf-g++')
-  if target_arch == 'arm64':
-    fuchsia_linker = os.path.join(fuchsia_toolchain, 'aarch64-elf-c++')
-
-  # Grab the path to libgcc.a, which we must explicitly add to the link,
-  # by invoking the cross-compiler with the -print-libgcc-file-name flag.
-  fuchsia_gcc = os.path.join(fuchsia_toolchain, 'x86_64-elf-gcc')
-  if target_arch == 'arm64':
-    fuchsia_gcc = os.path.join(fuchsia_toolchain, 'aarch64-elf-gcc')
-  fuchsia_libgcc = subprocess.check_output(
-      [fuchsia_gcc, '-print-libgcc-file-name']).strip()
-
-  # Set up the path to the system root directory, which is where we'll find the
-  # Fuchsia specific system includes and libraries.
-  fuchsia_sysroot = os.path.join(fuchsia_tools, 'sysroot', 'x86_64')
-  if target_arch == 'arm64':
-    fuchsia_sysroot = os.path.join(fuchsia_tools, 'sysroot', 'arm64')
-  CheckDirExists(fuchsia_sysroot, 'Fuchsia sysroot')
-  fuchsia_lib = os.path.join(fuchsia_sysroot, 'usr', 'lib')
-  crtn_fuchsia = os.path.join(fuchsia_lib, 'crtn.o')
-
-  if link_target == 'target':
-    # Add and remove libraries as listed in configurations_fuchsia.gypi
-    libs_to_rm = ['-lrt', '-lpthread']
-    libs_to_add = [fuchsia_libgcc, '-lc', '-ldl', '-lm']
-
-    # Add crtn_fuchsia to end if we are linking an executable.
-    if link_type == 'executable':
-      libs_to_add.extend([crtn_fuchsia])
-
-    link_args = [i for i in link_args if i not in libs_to_rm]
-    link_args.extend(libs_to_add)
-
-    link_args.insert(0, fuchsia_linker)
-  else:
-    link_args.extend(['-ldl', '-lrt'])
-    link_args.insert(0, 'g++')
-
-  print ' '.join(link_args)
-  sys.exit(execute(link_args))
-
-if __name__ == '__main__':
-  main()
diff --git a/tools/gyp/configurations.gypi b/tools/gyp/configurations.gypi
index 267be04..29f457e 100644
--- a/tools/gyp/configurations.gypi
+++ b/tools/gyp/configurations.gypi
@@ -41,7 +41,6 @@
   },
   'includes': [
     'configurations_android.gypi',
-    'configurations_fuchsia.gypi',
     'configurations_make.gypi',
     'configurations_xcode.gypi',
     'configurations_msvs.gypi',
@@ -730,21 +729,6 @@
         ],
       },
 
-      # Fuchsia configurations. The configuration names explicitly include
-      # 'Fuchsia' because we are cross-building from Linux, and, when building
-      # the standalone VM, we cannot inspect the gyp built-in 'OS' variable to
-      # figure out that we are building for Fuchsia. Since we have not re-run
-      # gyp, it will still be 'linux'.
-      'ProductFuchsiaX64': {
-        'inherit_from': [
-          'Dart_Base', 'Dart_x64_Base', 'Dart_Product',
-          'Dart_Fuchsia_Base',
-          'Dart_Fuchsia_x64_Base',
-          'Dart_Fuchsia_Product',
-        ],
-      },
-
-
       # Android configurations. The configuration names explicitly include
       # 'Android' because we are cross-building from Linux, and, when building
       # the standalone VM, we cannot inspect the gyp built-in 'OS' variable to
diff --git a/tools/gyp/configurations_fuchsia.gypi b/tools/gyp/configurations_fuchsia.gypi
deleted file mode 100644
index 5b291d3..0000000
--- a/tools/gyp/configurations_fuchsia.gypi
+++ /dev/null
@@ -1,152 +0,0 @@
-# Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
-# for details. All rights reserved. Use of this source code is governed by a
-# BSD-style license that can be found in the LICENSE file.
-
-# Definitions for building standalone Dart binaries to run on Fuchsia.
-
-{
-  'variables': {
-    'fuchsia_tools': '<(PRODUCT_DIR)/../../third_party/fuchsia_tools/',
-  },  # variables
-  'target_defaults': {
-    'configurations': {
-      'Dart_Fuchsia_Base': {
-        'abstract': 1,
-        'cflags': [
-          '-Werror',
-          '<@(common_gcc_warning_flags)',
-          '-Wnon-virtual-dtor',
-          '-Wvla',
-          '-Woverloaded-virtual',
-          '-g3',
-          '-ggdb3',
-          '-fno-rtti',
-          '-fno-exceptions',
-          '-fstack-protector',
-          '-Wa,--noexecstack',
-        ],
-        'target_conditions': [
-          ['_toolset=="target"', {
-            'cflags!': [
-              '-pthread',  # Not supported by Android toolchain.
-            ],
-          }],
-        ],
-      },
-      'Dart_Fuchsia_Debug': {
-        'abstract': 1,
-        'defines': [
-          'DEBUG',
-        ],
-        'cflags': [
-          '-fno-omit-frame-pointer',
-        ],
-      },
-      'Dart_Fuchsia_Release': {
-        'abstract': 1,
-        'defines': [
-          'NDEBUG',
-        ],
-        'cflags!': [
-          '-O2',
-          '-Os',
-        ],
-        'cflags': [
-          '-fno-omit-frame-pointer',
-          '-fdata-sections',
-          '-ffunction-sections',
-          '-O3',
-        ],
-      },
-      'Dart_Fuchsia_Product': {
-        'abstract': 1,
-        'defines': [
-          'NDEBUG',
-          'PRODUCT',
-        ],
-        'cflags!': [
-          '-O2',
-          '-Os',
-        ],
-        'cflags': [
-          '-fdata-sections',
-          '-ffunction-sections',
-          '-O3',
-        ],
-      },
-      'Dart_Fuchsia_x64_Base': {
-        'abstract': 1,
-        'variables': {
-          'fuchsia_sysroot': '<(fuchsia_tools)/sysroot/x86_64',
-          'fuchsia_include': '<(fuchsia_sysroot)/usr/include',
-          'fuchsia_lib': '<(fuchsia_sysroot)/usr/lib',
-        },
-        'target_conditions': [
-          ['_toolset=="target"', {
-            'defines': [
-              'TARGET_OS_FUCHSIA',
-            ],
-            'cflags': [
-              '--sysroot=<(fuchsia_sysroot)',
-              '-I<(fuchsia_include)',
-              '-fno-threadsafe-statics',
-            ],
-            'ldflags': [
-              'x64', '>(_type)', 'target',
-              '-nostdlib',
-              '-T<(fuchsia_sysroot)/usr/user.ld',
-              '-L<(fuchsia_lib)',
-              '-Wl,-z,noexecstack',
-              '-Wl,-z,now',
-              '-Wl,-z,relro',
-              '<(fuchsia_lib)/crt1.o',
-              '<(fuchsia_lib)/crti.o',
-            ],
-            'ldflags!': [
-              '-pthread',
-            ],
-          }],
-          ['_toolset=="host"', {
-            'cflags': [ '-pthread' ],
-            'ldflags': [ '-pthread' ],
-          }],
-        ],
-      },
-      'Dart_Fuchsia_arm64_Base': {
-        'abstract': 1,
-        'variables': {
-          'fuchsia_sysroot': '<(fuchsia_tools)/sysroot/arm64',
-          'fuchsia_include': '<(fuchsia_sysroot)/usr/include',
-          'fuchsia_lib': '<(fuchsia_sysroot)/usr/lib',
-        },
-        'target_conditions': [
-          ['_toolset=="target"', {
-            'defines': [
-              'TARGET_OS_FUCHSIA',
-            ],
-            'cflags': [
-              '--sysroot=<(fuchsia_sysroot)',
-              '-I<(fuchsia_include)',
-              '-fno-threadsafe-statics',
-            ],
-            'ldflags': [
-              'arm64', '>(_type)', 'target',
-              '-nostdlib',
-              '-L<(fuchsia_lib)',
-              '-Wl,-z,noexecstack',
-              '-Wl,-z,now',
-              '-Wl,-z,relro',
-            ],
-            'ldflags!': [
-              '-pthread',
-            ],
-          }],
-          ['_toolset=="host"', {
-            'cflags': [ '-pthread' ],
-            'ldflags': [ '-pthread' ],
-          }],
-        ],
-      },  # Dart_Fuchsia_arm64_Base
-    },  # configurations
-  },  # target_defaults
-}
diff --git a/tools/testing/dart/compiler_configuration.dart b/tools/testing/dart/compiler_configuration.dart
index 1747731..bf6db43 100644
--- a/tools/testing/dart/compiler_configuration.dart
+++ b/tools/testing/dart/compiler_configuration.dart
@@ -54,6 +54,7 @@
     bool useCps = configuration['cps_ir'];
     bool useBlobs = configuration['use_blobs'];
     bool hotReload = configuration['hot_reload'];
+    bool hotReloadRollback = configuration['hot_reload_rollback'];
 
     switch (compiler) {
       case 'dart2analyzer':
@@ -91,7 +92,8 @@
             isChecked: isChecked,
             isHostChecked: isHostChecked,
             useSdk: useSdk,
-            hotReload: hotReload);
+            hotReload: hotReload,
+            hotReloadRollback: hotReloadRollback);
       default:
         throw "Unknown compiler '$compiler'";
     }
@@ -152,16 +154,19 @@
 /// The "none" compiler.
 class NoneCompilerConfiguration extends CompilerConfiguration {
   final bool hotReload;
+  final bool hotReloadRollback;
 
   NoneCompilerConfiguration(
       {bool isDebug, bool isChecked, bool isHostChecked, bool useSdk,
-       bool hotReload})
+       bool hotReload,
+       bool hotReloadRollback})
       : super._subclass(
             isDebug: isDebug,
             isChecked: isChecked,
             isHostChecked: isHostChecked,
             useSdk: useSdk),
-        this.hotReload = hotReload;
+        this.hotReload = hotReload,
+        this.hotReloadRollback = hotReloadRollback;
 
   bool get hasCompiler => false;
 
@@ -180,6 +185,8 @@
     }
     if (hotReload) {
       args.add('--hot-reload-test-mode');
+    } else if (hotReloadRollback) {
+      args.add('--hot-reload-rollback-test-mode');
     }
     return args
       ..addAll(vmOptions)
diff --git a/tools/testing/dart/runtime_configuration.dart b/tools/testing/dart/runtime_configuration.dart
index 8c10e10..8983cc5 100644
--- a/tools/testing/dart/runtime_configuration.dart
+++ b/tools/testing/dart/runtime_configuration.dart
@@ -70,7 +70,7 @@
   RuntimeConfiguration._subclass();
 
   int computeTimeoutMultiplier(
-      {String mode, bool isChecked: false, String arch}) {
+      {String mode, bool isChecked: false, bool isReload: false, String arch}) {
     return 1;
   }
 
@@ -164,7 +164,7 @@
   DartVmRuntimeConfiguration() : super._subclass();
 
   int computeTimeoutMultiplier(
-      {String mode, bool isChecked: false, String arch}) {
+      {String mode, bool isChecked: false, bool isReload: false, String arch}) {
     int multiplier = 1;
     switch (arch) {
       case 'simarm':
@@ -183,6 +183,9 @@
     }
     if (mode == 'debug') {
       multiplier *= 2;
+      if (isReload) {
+        multiplier *= 2;
+      }
     }
     return multiplier;
   }
@@ -192,13 +195,14 @@
 /// program named Dump Render Tree, hence the name.
 class DrtRuntimeConfiguration extends DartVmRuntimeConfiguration {
   int computeTimeoutMultiplier(
-      {String mode, bool isChecked: false, String arch}) {
+      {String mode, bool isChecked: false, bool isReload: false, String arch}) {
     return 4 // Allow additional time for browser testing to run.
         // TODO(ahe): We might need to distinquish between DRT for running
         // JavaScript and Dart code.  I'm not convinced the inherited timeout
         // multiplier is relevant for JavaScript.
         *
-        super.computeTimeoutMultiplier(mode: mode, isChecked: isChecked);
+        super.computeTimeoutMultiplier(
+            mode: mode, isChecked: isChecked, isReload: isReload);
   }
 }
 
diff --git a/tools/testing/dart/test_options.dart b/tools/testing/dart/test_options.dart
index ee9c107..6f76125 100644
--- a/tools/testing/dart/test_options.dart
+++ b/tools/testing/dart/test_options.dart
@@ -190,6 +190,11 @@
           'hot_reload', 'Run hot reload stress tests', ['--hot-reload'], [],
           false, type: 'bool'),
       new _TestOptionSpecification(
+          'hot_reload_rollback',
+          'Run hot reload rollback stress tests', ['--hot-reload-rollback'],
+          [],
+          false, type: 'bool'),
+      new _TestOptionSpecification(
           'use_blobs',
           'Use mmap instead of shared libraries for precompilation',
           ['--use-blobs'], [], false, type: 'bool'),
@@ -819,12 +824,15 @@
 
     // Adjust default timeout based on mode, compiler, and sometimes runtime.
     if (configuration['timeout'] == -1) {
+      var isReload = configuration['hot_reload'] ||
+                     configuration['hot_reload_rollback'];
       int compilerMulitiplier =
           new CompilerConfiguration(configuration).computeTimeoutMultiplier();
       int runtimeMultiplier = new RuntimeConfiguration(configuration)
           .computeTimeoutMultiplier(
               mode: configuration['mode'],
               isChecked: configuration['checked'],
+              isReload: isReload,
               arch: configuration['arch']);
       configuration['timeout'] = 60 * compilerMulitiplier * runtimeMultiplier;
     }
diff --git a/tools/testing/dart/test_suite.dart b/tools/testing/dart/test_suite.dart
index 5dfbd39..2c4b541 100644
--- a/tools/testing/dart/test_suite.dart
+++ b/tools/testing/dart/test_suite.dart
@@ -300,7 +300,7 @@
       return;
     }
 
-    if (configuration['hot_reload']) {
+    if (configuration['hot_reload'] || configuration['hot_reload_rollback']) {
       // Handle reload special cases.
       if (expectations.contains(Expectation.COMPILETIME_ERROR)) {
         // Running a test that expects a compilation error with hot reloading
@@ -850,7 +850,8 @@
                             buildDir,
                             suiteDir,
                             createTestCase,
-                            configuration['hot_reload']));
+                            (configuration['hot_reload'] ||
+                             configuration['hot_reload_rollback'])));
     } else {
       createTestCase(filePath, filePath, optionsFromFile['hasCompileError'],
           optionsFromFile['hasRuntimeError'],
diff --git a/tools/update_ddc_dep.py b/tools/update_ddc_dep.py
new file mode 100755
index 0000000..d3a3979
--- /dev/null
+++ b/tools/update_ddc_dep.py
@@ -0,0 +1,135 @@
+#!/usr/bin/python
+
+# Update ddc dep automatically.
+
+import optparse
+import os
+import re
+from subprocess import Popen, PIPE
+import sys
+
+# Instructions:
+#
+# To run locally:
+#  (a) Create and change to a directory to run the updater in:
+#  mkdir /usr/local/google/home/$USER/ddc_deps_updater
+#
+#  (b) Test by running (Ctrl-C to quit):
+#      > ./update_ddc_deps.py
+#
+#  (c) Run periodical update:
+#      > while true; do ./update_ddc_deps.py --force ; sleep 300 ; done
+
+########################################################################
+# Actions
+########################################################################
+
+def write_file(filename, content):
+  f = open(filename, "w")
+  f.write(content)
+  f.close()
+
+def run_cmd(cmd):
+  print "\n[%s]\n$ %s" % (os.getcwd(), " ".join(cmd))
+  pipe = Popen(cmd, stdout=PIPE, stderr=PIPE)
+  output = pipe.communicate()
+  if pipe.returncode == 0:
+    return output[0]
+  else:
+    print output[1]
+    print "FAILED. RET_CODE=%d" % pipe.returncode
+    sys.exit(pipe.returncode)
+
+def main():
+  option_parser = optparse.OptionParser()
+  option_parser.add_option(
+      '',
+      '--force',
+      help="Push DEPS update to server without prompting",
+      action="store_true",
+      dest="force")
+  options, args = option_parser.parse_args()
+
+  target = 'ddc'
+  repo = 'dev_compiler'
+  repo_name = 'git@github.com:dart-lang/sdk.git'
+  ddc_repo_name = 'git@github.com:dart-lang/%s.git' % (repo)
+  repo_branch = 'origin/master'
+  repo_branch_parts = repo_branch.split('/')
+
+  root_dir = "/usr/local/google/home/%s/ddc_deps_updater" % (os.environ["USER"])
+  src_dir = "%s/sdk" % (root_dir)
+  ddc_dir = "%s/%s" % (root_dir, repo)
+  deps_file = src_dir + '/DEPS'
+
+  os.putenv("GIT_PAGER", "")
+
+  if not os.path.exists(src_dir):
+    print run_cmd(['git', 'clone', repo_name])
+
+  if not os.path.exists(ddc_dir):
+    print run_cmd(['git', 'clone', ddc_repo_name])
+
+  os.chdir(ddc_dir)
+  run_cmd(['git', 'fetch'])
+
+  os.chdir(src_dir)
+  run_cmd(['git', 'fetch'])
+  run_cmd(['git', 'stash'])
+  run_cmd(['git', 'checkout', '-B', repo_branch_parts[1], repo_branch])
+
+  # parse DEPS
+  deps = run_cmd(['cat', deps_file])
+  rev_num = {}
+  revision = '%s_rev":\s*"@(.+)"' % (repo)
+  rev_num = re.search(revision, deps).group(1)
+
+  # update repos
+  all_revs = []
+  os.chdir(ddc_dir)
+
+  output = run_cmd(["git", "log",  "--pretty=%H", "%s..HEAD" % (rev_num),
+      "origin/master"])
+  commits = output.split('\n')
+  if not commits or len(commits[0]) < 10:
+    print "DEPS is up-to-date."
+    sys.exit(0)
+
+  revision = commits[0]
+
+  history = run_cmd(["git", "log",  "--format=short", "%s..HEAD" % (rev_num),
+      "origin/master"])
+
+  print "Pending DEPS update: %s" % (revision)
+
+  # make the next DEPS update
+  os.chdir(src_dir)
+  run_cmd(['rm', deps_file])
+
+  pattern = re.compile('%s_rev":\s*"@(.+)"' % (repo))
+  new_deps = pattern.sub('%s_rev": "@%s"' % (repo, revision), deps)
+  write_file(deps_file, new_deps)
+
+  commit_log = 'DEPS AutoUpdate: %s\n\n' % (repo)
+  commit_log += history
+
+  write_file('commit_log.txt', commit_log)
+  run_cmd(['git', 'add', deps_file])
+
+  print run_cmd(['git', 'diff', 'HEAD'])
+  print
+  print "Commit log:"
+  print "---------------------------------------------"
+  print commit_log
+  print "---------------------------------------------"
+
+  if not options.force:
+    print "Ready to push; press Enter to continue or Control-C to abort..."
+    sys.stdin.readline()
+  print run_cmd(['git', 'commit', '-F', 'commit_log.txt'])
+  print run_cmd(['git', 'push', repo_branch_parts[0], repo_branch_parts[1]])
+  print "Done."
+
+
+if '__main__' == __name__:
+  main()
diff --git a/tools/utils.py b/tools/utils.py
index 496b499..0611bdd 100644
--- a/tools/utils.py
+++ b/tools/utils.py
@@ -268,7 +268,7 @@
           (target_os != GuessOS()))
 
 def GetBuildConf(mode, arch, conf_os=None):
-  if conf_os == 'android' or conf_os == 'fuchsia':
+  if conf_os == 'android':
     return '%s%s%s' % (GetBuildMode(mode), conf_os.title(), arch.upper())
   else:
     # Ask for a cross build if the host and target architectures don't match.