Version 1.9.0-dev.10.5

svn merge -c 44256 https://dart.googlecode.com/svn/branches/bleeding_edge trunk
svn merge -c 44278 https://dart.googlecode.com/svn/branches/bleeding_edge trunk
svn merge -c 44279 https://dart.googlecode.com/svn/branches/bleeding_edge trunk
svn merge -c 44296 https://dart.googlecode.com/svn/branches/bleeding_edge trunk
svn merge -c 44306 https://dart.googlecode.com/svn/branches/bleeding_edge trunk
svn merge -c 44307 https://dart.googlecode.com/svn/branches/bleeding_edge trunk
svn merge -c 44308 https://dart.googlecode.com/svn/branches/bleeding_edge trunk
svn merge -c 44335 https://dart.googlecode.com/svn/branches/bleeding_edge trunk
svn merge -c 44336 https://dart.googlecode.com/svn/branches/bleeding_edge trunk
svn merge -c 44337 https://dart.googlecode.com/svn/branches/bleeding_edge trunk
svn merge -c 44338 https://dart.googlecode.com/svn/branches/bleeding_edge trunk
svn merge -c 44339 https://dart.googlecode.com/svn/branches/bleeding_edge trunk
svn merge -c 44341 https://dart.googlecode.com/svn/branches/bleeding_edge trunk
svn merge -c 44345 https://dart.googlecode.com/svn/branches/bleeding_edge trunk
svn merge -c 44346 https://dart.googlecode.com/svn/branches/bleeding_edge trunk
svn merge -c 44347 https://dart.googlecode.com/svn/branches/bleeding_edge trunk
svn merge -c 44352 https://dart.googlecode.com/svn/branches/bleeding_edge trunk
svn merge -c 44371 https://dart.googlecode.com/svn/branches/bleeding_edge trunk
svn merge -c 44375 https://dart.googlecode.com/svn/branches/bleeding_edge trunk
svn merge -c 44376 https://dart.googlecode.com/svn/branches/bleeding_edge trunk
svn merge -c 44377 https://dart.googlecode.com/svn/branches/bleeding_edge trunk
svn merge -c 44381 https://dart.googlecode.com/svn/branches/bleeding_edge trunk
svn merge -c 44383 https://dart.googlecode.com/svn/branches/bleeding_edge trunk
svn merge -c 44384 https://dart.googlecode.com/svn/branches/bleeding_edge trunk
svn merge -c 44386 https://dart.googlecode.com/svn/branches/bleeding_edge trunk
svn merge -c 44388 https://dart.googlecode.com/svn/branches/bleeding_edge trunk

Merged patch from:
https://code.google.com/p/dart/issues/detail?id=22734

git-svn-id: http://dart.googlecode.com/svn/trunk@44394 260f80e4-7a28-3924-810f-c04153c831b5
diff --git a/pkg/analysis_server/lib/src/analysis_server.dart b/pkg/analysis_server/lib/src/analysis_server.dart
index 922f2ad..8168764 100644
--- a/pkg/analysis_server/lib/src/analysis_server.dart
+++ b/pkg/analysis_server/lib/src/analysis_server.dart
@@ -367,26 +367,7 @@
    * path.
    */
   AnalysisContext getAnalysisContext(String path) {
-    // try to find a containing context
-    Folder containingFolder = null;
-    for (Folder folder in folderMap.keys) {
-      if (folder.path == path || folder.contains(path)) {
-        if (containingFolder == null) {
-          containingFolder = folder;
-        } else if (containingFolder.path.length < folder.path.length) {
-          containingFolder = folder;
-        }
-      }
-    }
-    if (containingFolder != null) {
-      return folderMap[containingFolder];
-    }
-    Resource resource = resourceProvider.getResource(path);
-    if (resource is Folder) {
-      return null;
-    }
-    // check if there is a context that analyzed this source
-    return getAnalysisContextForSource(_getSourceWithoutContext(path));
+    return getContextSourcePair(path).context;
   }
 
   /**
@@ -412,6 +393,67 @@
   }
 
   /**
+   * Return the primary [ContextSourcePair] representing the given [path].
+   *
+   * The [AnalysisContext] of this pair will be the context that explicitly
+   * contains the path, if any such context exists, otherwise it will be the
+   * first context that implicitly analyzes it.
+   *
+   * If the [path] is not analyzed by any context, a [ContextSourcePair] with
+   * `null` context and `file` [Source] is returned.
+   *
+   * If the [path] dosn't represent a file, `null` is returned as a [Source].
+   *
+   * Does not return `null`.
+   */
+  ContextSourcePair getContextSourcePair(String path) {
+    // try SDK
+    {
+      Uri uri = resourceProvider.pathContext.toUri(path);
+      Source sdkSource = defaultSdk.fromFileUri(uri);
+      if (sdkSource != null) {
+        AnalysisContext anyContext = folderMap.values.first;
+        return new ContextSourcePair(anyContext, sdkSource);
+      }
+    }
+    // try to find the deep-most containing context
+    Resource resource = resourceProvider.getResource(path);
+    File file = resource is File ? resource : null;
+    {
+      Folder containingFolder = null;
+      AnalysisContext containingContext = null;
+      folderMap.forEach((Folder folder, AnalysisContext context) {
+        if (folder.isOrContains(path)) {
+          if (containingFolder == null ||
+              containingFolder.path.length < folder.path.length) {
+            containingFolder = folder;
+            containingContext = context;
+          }
+        }
+      });
+      if (containingContext != null) {
+        Source source = file != null
+            ? ContextManager.createSourceInContext(containingContext, file)
+            : null;
+        return new ContextSourcePair(containingContext, source);
+      }
+    }
+    // try to find a context that analysed the file
+    for (AnalysisContext context in folderMap.values) {
+      Source source = file != null
+          ? ContextManager.createSourceInContext(context, file)
+          : null;
+      SourceKind kind = context.getKindOf(source);
+      if (kind != SourceKind.UNKNOWN) {
+        return new ContextSourcePair(context, source);
+      }
+    }
+    // file-based source
+    Source fileSource = file != null ? file.createSource() : null;
+    return new ContextSourcePair(null, fileSource);
+  }
+
+  /**
    * Returns [Element]s at the given [offset] of the given [file].
    *
    * May be empty if cannot be resolved, but not `null`.
@@ -460,37 +502,18 @@
    * the current state.
    */
   AnalysisErrorInfo getErrors(String file) {
-    // prepare AnalysisContext
-    AnalysisContext context = getAnalysisContext(file);
+    ContextSourcePair contextSource = getContextSourcePair(file);
+    AnalysisContext context = contextSource.context;
+    Source source = contextSource.source;
     if (context == null) {
       return null;
     }
-    // prepare Source
-    Source source = getSource(file);
-    if (context.getKindOf(source) == SourceKind.UNKNOWN) {
+    if (!source.exists()) {
       return null;
     }
-    // get errors for the file
     return context.getErrors(source);
   }
 
-  /**
-   * Returns resolved [AstNode]s at the given [offset] of the given [file].
-   *
-   * May be empty, but not `null`.
-   */
-  List<AstNode> getNodesAtOffset(String file, int offset) {
-    List<CompilationUnit> units = getResolvedCompilationUnits(file);
-    List<AstNode> nodes = <AstNode>[];
-    for (CompilationUnit unit in units) {
-      AstNode node = new NodeLocator.con1(offset).searchWithin(unit);
-      if (node != null) {
-        nodes.add(node);
-      }
-    }
-    return nodes;
-  }
-
 // TODO(brianwilkerson) Add the following method after 'prioritySources' has
 // been added to InternalAnalysisContext.
 //  /**
@@ -509,19 +532,37 @@
 //  }
 
   /**
+   * Returns resolved [AstNode]s at the given [offset] of the given [file].
+   *
+   * May be empty, but not `null`.
+   */
+  List<AstNode> getNodesAtOffset(String file, int offset) {
+    List<CompilationUnit> units = getResolvedCompilationUnits(file);
+    List<AstNode> nodes = <AstNode>[];
+    for (CompilationUnit unit in units) {
+      AstNode node = new NodeLocator.con1(offset).searchWithin(unit);
+      if (node != null) {
+        nodes.add(node);
+      }
+    }
+    return nodes;
+  }
+
+  /**
    * Returns resolved [CompilationUnit]s of the Dart file with the given [path].
    *
    * May be empty, but not `null`.
    */
   List<CompilationUnit> getResolvedCompilationUnits(String path) {
     List<CompilationUnit> units = <CompilationUnit>[];
+    ContextSourcePair contextSource = getContextSourcePair(path);
     // prepare AnalysisContext
-    AnalysisContext context = getAnalysisContext(path);
+    AnalysisContext context = contextSource.context;
     if (context == null) {
       return units;
     }
     // add a unit for each unit/library combination
-    Source unitSource = getSource(path);
+    Source unitSource = contextSource.source;
     List<Source> librarySources = context.getLibrariesContaining(unitSource);
     for (Source librarySource in librarySources) {
       CompilationUnit unit =
@@ -535,50 +576,6 @@
   }
 
   /**
-   * Returns the [CompilationUnit] of the Dart file with the given [path] that
-   * should be used to resend notifications for already resolved unit.
-   * Returns `null` if the file is not a part of any context, library has not
-   * been yet resolved, or any problem happened.
-   */
-  CompilationUnit getResolvedCompilationUnitToResendNotification(String path) {
-    // prepare AnalysisContext
-    AnalysisContext context = getAnalysisContext(path);
-    if (context == null) {
-      return null;
-    }
-    // prepare sources
-    Source unitSource = getSource(path);
-    List<Source> librarySources = context.getLibrariesContaining(unitSource);
-    if (librarySources.isEmpty) {
-      return null;
-    }
-    // if library has not been resolved yet, the unit will be resolved later
-    Source librarySource = librarySources[0];
-    if (context.getLibraryElement(librarySource) == null) {
-      return null;
-    }
-    // if library has been already resolved, resolve unit
-    return context.resolveCompilationUnit2(unitSource, librarySource);
-  }
-
-  /**
-   * Return the [Source] of the Dart file with the given [path].
-   */
-  Source getSource(String path) {
-    // try SDK
-    {
-      Uri uri = resourceProvider.pathContext.toUri(path);
-      Source sdkSource = defaultSdk.fromFileUri(uri);
-      if (sdkSource != null) {
-        return sdkSource;
-      }
-    }
-    // file-based source
-    File file = resourceProvider.getResource(path);
-    return ContextManager.createSourceInContext(getAnalysisContext(path), file);
-  }
-
-  /**
    * Handle a [request] that was read from the communication channel.
    */
   void handleRequest(Request request) {
@@ -852,16 +849,17 @@
       Set<String> todoFiles =
           oldFiles != null ? newFiles.difference(oldFiles) : newFiles;
       for (String file in todoFiles) {
-        Source source = getSource(file);
+        ContextSourcePair contextSource = getContextSourcePair(file);
         // prepare context
-        AnalysisContext context = getAnalysisContext(file);
+        AnalysisContext context = contextSource.context;
         if (context == null) {
           continue;
         }
         // Dart unit notifications.
         if (AnalysisEngine.isDartFileName(file)) {
+          Source source = contextSource.source;
           CompilationUnit dartUnit =
-              getResolvedCompilationUnitToResendNotification(file);
+              _getResolvedCompilationUnitToResendNotification(context, source);
           if (dartUnit != null) {
             switch (service) {
               case AnalysisService.HIGHLIGHTS:
@@ -875,6 +873,7 @@
                 sendAnalysisNotificationOccurrences(this, file, dartUnit);
                 break;
               case AnalysisService.OUTLINE:
+                AnalysisContext context = dartUnit.element.context;
                 LineInfo lineInfo = context.getLineInfo(source);
                 sendAnalysisNotificationOutline(this, file, lineInfo, dartUnit);
                 break;
@@ -901,9 +900,11 @@
     Map<AnalysisContext, List<Source>> sourceMap =
         new HashMap<AnalysisContext, List<Source>>();
     List<String> unanalyzed = new List<String>();
+    Source firstSource = null;
     files.forEach((file) {
-      AnalysisContext preferredContext = getAnalysisContext(file);
-      Source source = getSource(file);
+      ContextSourcePair contextSource = getContextSourcePair(file);
+      AnalysisContext preferredContext = contextSource.context;
+      Source source = contextSource.source;
       bool contextFound = false;
       for (AnalysisContext context in folderMap.values) {
         if (context == preferredContext ||
@@ -912,6 +913,9 @@
           contextFound = true;
         }
       }
+      if (firstSource == null) {
+        firstSource = source;
+      }
       if (!contextFound) {
         unanalyzed.add(file);
       }
@@ -933,7 +937,6 @@
       schedulePerformAnalysisOperation(context);
     });
     operationQueue.reschedule();
-    Source firstSource = files.length > 0 ? getSource(files[0]) : null;
     _onPriorityChangeController.add(new PriorityChangeEvent(firstSource));
   }
 
@@ -962,8 +965,9 @@
 
   void test_flushResolvedUnit(String file) {
     if (AnalysisEngine.isDartFileName(file)) {
-      AnalysisContextImpl context = getAnalysisContext(file);
-      Source source = getSource(file);
+      ContextSourcePair contextSource = getContextSourcePair(file);
+      AnalysisContextImpl context = contextSource.context;
+      Source source = contextSource.source;
       DartEntry dartEntry = context.getReadableSourceEntryOrNull(source);
       dartEntry.flushAstStructures();
     }
@@ -989,7 +993,8 @@
    */
   void updateContent(String id, Map<String, dynamic> changes) {
     changes.forEach((file, change) {
-      Source source = getSource(file);
+      ContextSourcePair contextSource = getContextSourcePair(file);
+      Source source = contextSource.source;
       operationQueue.sourceAboutToChange(source);
       // Prepare the new contents.
       String oldContents = overlayState.getContents(source);
@@ -1020,29 +1025,32 @@
       overlayState.setContents(source, newContents);
       // Update all contexts.
       for (InternalAnalysisContext context in folderMap.values) {
-        if (context.handleContentsChanged(
-            source, oldContents, newContents, true)) {
-          schedulePerformAnalysisOperation(context);
-        } else {
-          // When the client sends any change for a source, we should resend
-          // subscribed notifications, even if there were no changes in the
-          // source contents.
-          // TODO(scheglov) consider checking if there are subscriptions.
-          if (AnalysisEngine.isDartFileName(file)) {
-            List<CompilationUnit> dartUnits =
-                context.ensureResolvedDartUnits(source);
-            if (dartUnits != null) {
-              AnalysisErrorInfo errorInfo = context.getErrors(source);
-              for (var dartUnit in dartUnits) {
-                scheduleNotificationOperations(this, file, errorInfo.lineInfo,
-                    context, null, dartUnit, errorInfo.errors);
-                scheduleIndexOperation(this, file, context, dartUnit);
+        List<Source> sources = context.getSourcesWithFullName(file);
+        sources.forEach((Source source) {
+          if (context.handleContentsChanged(
+              source, oldContents, newContents, true)) {
+            schedulePerformAnalysisOperation(context);
+          } else {
+            // When the client sends any change for a source, we should resend
+            // subscribed notifications, even if there were no changes in the
+            // source contents.
+            // TODO(scheglov) consider checking if there are subscriptions.
+            if (AnalysisEngine.isDartFileName(file)) {
+              List<CompilationUnit> dartUnits =
+                  context.ensureResolvedDartUnits(source);
+              if (dartUnits != null) {
+                AnalysisErrorInfo errorInfo = context.getErrors(source);
+                for (var dartUnit in dartUnits) {
+                  scheduleNotificationOperations(this, file, errorInfo.lineInfo,
+                      context, null, dartUnit, errorInfo.errors);
+                  scheduleIndexOperation(this, file, context, dartUnit);
+                }
+              } else {
+                schedulePerformAnalysisOperation(context);
               }
-            } else {
-              schedulePerformAnalysisOperation(context);
             }
           }
-        }
+        });
       }
     });
   }
@@ -1073,21 +1081,24 @@
   }
 
   /**
-   * Return the [Source] of the Dart file with the given [path], assuming that
-   * we do not know the context in which the path should be interpreted.
+   * Returns the [CompilationUnit] of the Dart file with the given [source] that
+   * should be used to resend notifications for already resolved unit.
+   * Returns `null` if the file is not a part of any context, library has not
+   * been yet resolved, or any problem happened.
    */
-  Source _getSourceWithoutContext(String path) {
-    // try SDK
-    {
-      Uri uri = resourceProvider.pathContext.toUri(path);
-      Source sdkSource = defaultSdk.fromFileUri(uri);
-      if (sdkSource != null) {
-        return sdkSource;
-      }
+  CompilationUnit _getResolvedCompilationUnitToResendNotification(
+      AnalysisContext context, Source source) {
+    List<Source> librarySources = context.getLibrariesContaining(source);
+    if (librarySources.isEmpty) {
+      return null;
     }
-    // file-based source
-    File file = resourceProvider.getResource(path);
-    return file.createSource();
+    // if library has not been resolved yet, the unit will be resolved later
+    Source librarySource = librarySources[0];
+    if (context.getLibraryElement(librarySource) == null) {
+      return null;
+    }
+    // if library has been already resolved, resolve unit
+    return context.resolveCompilationUnit2(source, librarySource);
   }
 
   /**
@@ -1156,6 +1167,27 @@
 }
 
 /**
+ * Information about a file - an [AnalysisContext] that analyses the file,
+ * and the [Source] representing the file in this context.
+ */
+class ContextSourcePair {
+  /**
+   * A context that analysis the file.
+   * May be `null` if the file is not analyzed by any context.
+   */
+  final AnalysisContext context;
+
+  /**
+   * The source that corresponds to the file.
+   * May be `null` if the file is not a regular file.
+   * If the file cannot be found in the [context], then it has a `file` uri.
+   */
+  final Source source;
+
+  ContextSourcePair(this.context, this.source);
+}
+
+/**
  * A [PriorityChangeEvent] indicates the set the priority files has changed.
  */
 class PriorityChangeEvent {
diff --git a/pkg/analysis_server/lib/src/context_manager.dart b/pkg/analysis_server/lib/src/context_manager.dart
index 8af64b3..ec26ccb 100644
--- a/pkg/analysis_server/lib/src/context_manager.dart
+++ b/pkg/analysis_server/lib/src/context_manager.dart
@@ -18,6 +18,7 @@
 import 'package:analyzer/src/generated/source_io.dart';
 import 'package:path/path.dart' as pathos;
 import 'package:watcher/watcher.dart';
+import 'package:analyzer/src/generated/java_engine.dart';
 
 /**
  * The name of `packages` folders.
@@ -301,7 +302,14 @@
     if (info.excludesResource(folder) || folder.shortName.startsWith('.')) {
       return;
     }
-    List<Resource> children = folder.getChildren();
+    List<Resource> children = null;
+    try {
+      children = folder.getChildren();
+    } on FileSystemException {
+      // The directory either doesn't exist or cannot be read. Either way, there
+      // are no children that need to be added.
+      return;
+    }
     for (Resource child in children) {
       String path = child.path;
       // ignore excluded files or folders
@@ -393,11 +401,16 @@
     }
     // try to find subfolders with pubspec files
     List<_ContextInfo> children = <_ContextInfo>[];
-    for (Resource child in folder.getChildren()) {
-      if (child is Folder) {
-        List<_ContextInfo> childContexts = _createContexts(child, true);
-        children.addAll(childContexts);
+    try {
+      for (Resource child in folder.getChildren()) {
+        if (child is Folder) {
+          List<_ContextInfo> childContexts = _createContexts(child, true);
+          children.addAll(childContexts);
+        }
       }
+    } on FileSystemException {
+      // The directory either doesn't exist or cannot be read. Either way, there
+      // are no subfolders that need to be added.
     }
     // no pubspec, done
     if (withPubspecOnly) {
@@ -427,8 +440,8 @@
    */
   void _destroyContext(Folder folder) {
     _contexts[folder].changeSubscription.cancel();
-    _contexts.remove(folder);
     removeContext(folder);
+    _contexts.remove(folder);
   }
 
   /**
@@ -466,6 +479,10 @@
   }
 
   void _handleWatchEvent(Folder folder, _ContextInfo info, WatchEvent event) {
+    // TODO(brianwilkerson) If a file is explicitly included in one context
+    // but implicitly referenced in another context, we will only send a
+    // changeSet to the context that explicitly includes the file (because
+    // that's the only context that's watching the file).
     _instrumentationService.logWatchEvent(
         folder.path, event.path, event.type.toString());
     String path = event.path;
@@ -509,19 +526,23 @@
           _mergeContext(info);
           return;
         }
-        Source source = info.sources[path];
-        if (source != null) {
+        List<Source> sources = info.context.getSourcesWithFullName(path);
+        if (!sources.isEmpty) {
           ChangeSet changeSet = new ChangeSet();
-          changeSet.removedSource(source);
+          sources.forEach((Source source) {
+            changeSet.removedSource(source);
+          });
           applyChangesToContext(folder, changeSet);
           info.sources.remove(path);
         }
         break;
       case ChangeType.MODIFY:
-        Source source = info.sources[path];
-        if (source != null) {
+        List<Source> sources = info.context.getSourcesWithFullName(path);
+        if (!sources.isEmpty) {
           ChangeSet changeSet = new ChangeSet();
-          changeSet.changedSource(source);
+          sources.forEach((Source source) {
+            changeSet.changedSource(source);
+          });
           applyChangesToContext(folder, changeSet);
         }
         break;
@@ -612,6 +633,9 @@
     if (context == null) {
       return source;
     }
+    if (context.sourceFactory == null) {
+      return null;
+    }
     Uri uri = context.sourceFactory.restoreUri(source);
     return file.createSource(uri);
   }
diff --git a/pkg/analysis_server/lib/src/domain_completion.dart b/pkg/analysis_server/lib/src/domain_completion.dart
index e6bb328..affe17c 100644
--- a/pkg/analysis_server/lib/src/domain_completion.dart
+++ b/pkg/analysis_server/lib/src/domain_completion.dart
@@ -174,8 +174,9 @@
         new CompletionGetSuggestionsParams.fromRequest(request);
     // schedule completion analysis
     String completionId = (_nextCompletionId++).toString();
-    AnalysisContext context = server.getAnalysisContext(params.file);
-    Source source = server.getSource(params.file);
+    ContextSourcePair contextSource = server.getContextSourcePair(params.file);
+    AnalysisContext context = contextSource.context;
+    Source source = contextSource.source;
     recordRequest(performance, context, source, params.offset);
     if (manager == null) {
       manager = completionManagerFor(context, source);
diff --git a/pkg/analysis_server/lib/src/domain_execution.dart b/pkg/analysis_server/lib/src/domain_execution.dart
index d3323c7..08ff54e 100644
--- a/pkg/analysis_server/lib/src/domain_execution.dart
+++ b/pkg/analysis_server/lib/src/domain_execution.dart
@@ -114,7 +114,8 @@
         return new Response.invalidParameter(
             request, 'file', 'Must not refer to a directory');
       }
-      Source source = server.getSource(file);
+      ContextSourcePair contextSource = server.getContextSourcePair(file);
+      Source source = contextSource.source;
       uri = context.sourceFactory.restoreUri(source).toString();
       return new ExecutionMapUriResult(uri: uri).toResponse(request.id);
     } else if (uri != null) {
@@ -157,6 +158,9 @@
         return;
       }
       AnalysisContext context = server.getAnalysisContext(filePath);
+      if (context == null) {
+        return;
+      }
       if (AnalysisEngine.isDartFileName(filePath)) {
         ExecutableKind kind = ExecutableKind.NOT_EXECUTABLE;
         if (context.isClientLibrary(source)) {
diff --git a/pkg/analysis_server/lib/src/edit/edit_domain.dart b/pkg/analysis_server/lib/src/edit/edit_domain.dart
index bc23ad5..edf92e7 100644
--- a/pkg/analysis_server/lib/src/edit/edit_domain.dart
+++ b/pkg/analysis_server/lib/src/edit/edit_domain.dart
@@ -58,12 +58,14 @@
     EditFormatParams params = new EditFormatParams.fromRequest(request);
     String file = params.file;
 
-    engine.AnalysisContext context = server.getAnalysisContext(file);
+    ContextSourcePair contextSource = server.getContextSourcePair(file);
+
+    engine.AnalysisContext context = contextSource.context;
     if (context == null) {
       return new Response.formatInvalidFile(request);
     }
 
-    Source source = server.getSource(file);
+    Source source = contextSource.source;
     engine.TimestampedData<String> contents;
     try {
       contents = context.getContents(source);
@@ -485,8 +487,9 @@
       }
     }
     if (kind == RefactoringKind.MOVE_FILE) {
-      engine.AnalysisContext context = server.getAnalysisContext(file);
-      Source source = server.getSource(file);
+      ContextSourcePair contextSource = server.getContextSourcePair(file);
+      engine.AnalysisContext context = contextSource.context;
+      Source source = contextSource.source;
       refactoring = new MoveFileRefactoring(
           server.resourceProvider.pathContext, searchEngine, context, source);
     }
diff --git a/pkg/analysis_server/lib/src/operation/operation_analysis.dart b/pkg/analysis_server/lib/src/operation/operation_analysis.dart
index aa751e3..ecbb97c 100644
--- a/pkg/analysis_server/lib/src/operation/operation_analysis.dart
+++ b/pkg/analysis_server/lib/src/operation/operation_analysis.dart
@@ -24,7 +24,9 @@
  */
 void scheduleIndexOperation(AnalysisServer server, String file,
     AnalysisContext context, CompilationUnit dartUnit) {
-  server.addOperation(new _DartIndexOperation(context, file, dartUnit));
+  if (server.index != null) {
+    server.addOperation(new _DartIndexOperation(context, file, dartUnit));
+  }
 }
 
 /**
@@ -34,16 +36,6 @@
 void scheduleNotificationOperations(AnalysisServer server, String file,
     LineInfo lineInfo, AnalysisContext context, CompilationUnit parsedDartUnit,
     CompilationUnit resolvedDartUnit, List<AnalysisError> errors) {
-  // Only send notifications if the current context is the preferred
-  // context for the file.  This avoids redundant notification messages
-  // being sent to the client (see dartbug.com/22210).
-  // TODO(paulberry): note that there is a small risk that this will cause
-  // notifications to be lost if the preferred context for a file changes
-  // while analysis is in progress (e.g. because the client sent an
-  // analysis.setAnalysisRoots message).
-  if (server.getAnalysisContext(file) != context) {
-    return;
-  }
   // Dart
   CompilationUnit dartUnit =
       resolvedDartUnit != null ? resolvedDartUnit : parsedDartUnit;
@@ -246,8 +238,7 @@
   }
 
   void _updateIndex(AnalysisServer server, List<ChangeNotice> notices) {
-    Index index = server.index;
-    if (index == null) {
+    if (server.index == null) {
       return;
     }
     for (ChangeNotice notice in notices) {
diff --git a/pkg/analysis_server/test/analysis_server_test.dart b/pkg/analysis_server/test/analysis_server_test.dart
index 94f5e40..bd78f9f 100644
--- a/pkg/analysis_server/test/analysis_server_test.dart
+++ b/pkg/analysis_server/test/analysis_server_test.dart
@@ -14,6 +14,7 @@
 import 'package:analyzer/file_system/file_system.dart';
 import 'package:analyzer/file_system/memory_file_system.dart';
 import 'package:analyzer/instrumentation/instrumentation.dart';
+import 'package:analyzer/source/package_map_resolver.dart';
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/java_engine.dart';
 import 'package:analyzer/src/generated/source.dart';
@@ -34,6 +35,7 @@
   MockServerChannel channel;
   AnalysisServer server;
   MemoryResourceProvider resourceProvider;
+  MockPackageMapProvider packageMapProvider;
 
   /**
    * Verify that getAnalysisContextForSource returns the correct contexts even
@@ -112,10 +114,10 @@
   void setUp() {
     channel = new MockServerChannel();
     resourceProvider = new MemoryResourceProvider();
-    server = new AnalysisServer(channel, resourceProvider,
-        new MockPackageMapProvider(), null, new AnalysisServerOptions(),
-        new MockSdk(), InstrumentationService.NULL_SERVICE,
-        rethrowExceptions: true);
+    packageMapProvider = new MockPackageMapProvider();
+    server = new AnalysisServer(channel, resourceProvider, packageMapProvider,
+        null, new AnalysisServerOptions(), new MockSdk(),
+        InstrumentationService.NULL_SERVICE, rethrowExceptions: true);
   }
 
   Future test_contextDisposed() {
@@ -131,34 +133,6 @@
     });
   }
 
-  test_getAnalysisContext_nested() {
-    String dir1Path = '/dir1';
-    String dir2Path = dir1Path + '/dir2';
-    String filePath = dir2Path + '/file.dart';
-    Folder dir1 = resourceProvider.newFolder(dir1Path);
-    Folder dir2 = resourceProvider.newFolder(dir2Path);
-    resourceProvider.newFile(filePath, 'library lib;');
-
-    AnalysisContext context1 = AnalysisEngine.instance.createAnalysisContext();
-    AnalysisContext context2 = AnalysisEngine.instance.createAnalysisContext();
-    server.folderMap[dir1] = context1;
-    server.folderMap[dir2] = context2;
-
-    expect(server.getAnalysisContext(filePath), context2);
-  }
-
-  test_getAnalysisContext_simple() {
-    String dirPath = '/dir';
-    String filePath = dirPath + '/file.dart';
-    Folder dir = resourceProvider.newFolder(dirPath);
-    resourceProvider.newFile(filePath, 'library lib;');
-
-    AnalysisContext context = AnalysisEngine.instance.createAnalysisContext();
-    server.folderMap[dir] = context;
-
-    expect(server.getAnalysisContext(filePath), context);
-  }
-
   Future test_contextsChangedEvent() {
     resourceProvider.newFolder('/foo');
 
@@ -246,51 +220,67 @@
     });
   }
 
-  /**
-   * Test that having multiple analysis contexts analyze the same file doesn't
-   * cause that file to receive duplicate notifications when it's modified.
-   */
-  Future test_no_duplicate_notifications() async {
-    // Subscribe to STATUS so we'll know when analysis is done.
-    server.serverServices = [ServerService.STATUS].toSet();
-    resourceProvider.newFolder('/foo');
-    resourceProvider.newFolder('/bar');
-    resourceProvider.newFile('/foo/foo.dart', 'import "../bar/bar.dart";');
-    File bar = resourceProvider.newFile('/bar/bar.dart', 'library bar;');
-    server.setAnalysisRoots('0', ['/foo', '/bar'], [], {});
-    Map<AnalysisService, Set<String>> subscriptions =
-        <AnalysisService, Set<String>>{};
-    for (AnalysisService service in AnalysisService.VALUES) {
-      subscriptions[service] = <String>[bar.path].toSet();
-    }
-    server.setAnalysisSubscriptions(subscriptions);
-    await pumpEventQueue(100);
-    expect(server.statusAnalyzing, isFalse);
-    channel.notificationsReceived.clear();
-    server.updateContent(
-        '0', {bar.path: new AddContentOverlay('library bar; void f() {}')});
-    await pumpEventQueue(100);
-    expect(server.statusAnalyzing, isFalse);
-    expect(channel.notificationsReceived, isNotEmpty);
-    Set<String> notificationTypesReceived = new Set<String>();
-    for (Notification notification in channel.notificationsReceived) {
-      String notificationType = notification.event;
-      switch (notificationType) {
-        case 'server.status':
-        case 'analysis.errors':
-          // It's normal for these notifications to be sent multiple times.
-          break;
-        case 'analysis.outline':
-          // It's normal for this notification to be sent twice.
-          // TODO(paulberry): why?
-          break;
-        default:
-          if (!notificationTypesReceived.add(notificationType)) {
-            fail('Notification type $notificationType received more than once');
-          }
-          break;
-      }
-    }
+  test_getContextSourcePair_nested() {
+    String dir1Path = '/dir1';
+    String dir2Path = dir1Path + '/dir2';
+    String filePath = dir2Path + '/file.dart';
+    Folder dir1 = resourceProvider.newFolder(dir1Path);
+    Folder dir2 = resourceProvider.newFolder(dir2Path);
+    resourceProvider.newFile(filePath, 'library lib;');
+
+    AnalysisContext context1 = AnalysisEngine.instance.createAnalysisContext();
+    AnalysisContext context2 = AnalysisEngine.instance.createAnalysisContext();
+    _configureSourceFactory(context1);
+    _configureSourceFactory(context2);
+    server.folderMap[dir1] = context1;
+    server.folderMap[dir2] = context2;
+
+    ContextSourcePair pair = server.getContextSourcePair(filePath);
+    Source source = pair.source;
+    expect(pair.context, same(context2));
+    expect(source, isNotNull);
+    expect(source.uri.scheme, 'file');
+    expect(source.fullName, filePath);
+  }
+
+  test_getContextSourcePair_package_inRoot() {
+    String rootPath = '/my_package';
+    String filePath = rootPath + '/lib/file.dart';
+    Folder rootFolder = resourceProvider.newFolder(rootPath);
+    resourceProvider.newFile(filePath, 'library lib;');
+
+    packageMapProvider.packageMap = <String, List<Folder>>{
+      'my_package': <Folder>[rootFolder]
+    };
+
+    AnalysisContext context = AnalysisEngine.instance.createAnalysisContext();
+    _configureSourceFactory(context);
+    server.folderMap[rootFolder] = context;
+
+    ContextSourcePair pair = server.getContextSourcePair(filePath);
+    Source source = pair.source;
+    expect(pair.context, same(context));
+    expect(source, isNotNull);
+    expect(source.uri.scheme, 'package');
+    expect(source.fullName, filePath);
+  }
+
+  test_getContextSourcePair_simple() {
+    String dirPath = '/dir';
+    String filePath = dirPath + '/file.dart';
+    Folder dir = resourceProvider.newFolder(dirPath);
+    resourceProvider.newFile(filePath, 'library lib;');
+
+    AnalysisContext context = AnalysisEngine.instance.createAnalysisContext();
+    _configureSourceFactory(context);
+    server.folderMap[dir] = context;
+
+    ContextSourcePair pair = server.getContextSourcePair(filePath);
+    Source source = pair.source;
+    expect(pair.context, same(context));
+    expect(source, isNotNull);
+    expect(source.uri.scheme, 'file');
+    expect(source.fullName, filePath);
   }
 
   Future test_prioritySourcesChangedEvent() {
@@ -394,6 +384,14 @@
       expect(response.error, isNotNull);
     });
   }
+
+  void _configureSourceFactory(AnalysisContext context) {
+    var resourceUriResolver = new ResourceUriResolver(resourceProvider);
+    var packageUriResolver = new PackageMapUriResolver(
+        resourceProvider, packageMapProvider.packageMap);
+    context.sourceFactory =
+        new SourceFactory([packageUriResolver, resourceUriResolver]);
+  }
 }
 
 class EchoHandler implements RequestHandler {
diff --git a/pkg/analysis_server/test/context_manager_test.dart b/pkg/analysis_server/test/context_manager_test.dart
index eab479f..61a3c09 100644
--- a/pkg/analysis_server/test/context_manager_test.dart
+++ b/pkg/analysis_server/test/context_manager_test.dart
@@ -847,6 +847,11 @@
   int now = 0;
 
   /**
+   * The analysis context that was created.
+   */
+  AnalysisContextImpl currentContext;
+
+  /**
    * Map from context to the timestamp when the context was created.
    */
   Map<String, int> currentContextTimestamps = <String, int>{};
@@ -888,10 +893,10 @@
     currentContextFilePaths[path] = <String, int>{};
     currentContextSources[path] = new HashSet<Source>();
     currentContextPackageUriResolvers[path] = packageUriResolver;
-    AnalysisContextImpl context = new AnalysisContextImpl();
-    context.sourceFactory = new SourceFactory(
+    currentContext = new AnalysisContextImpl();
+    currentContext.sourceFactory = new SourceFactory(
         packageUriResolver == null ? [] : [packageUriResolver]);
-    return context;
+    return currentContext;
   }
 
   @override
@@ -913,6 +918,8 @@
       expect(filePaths, contains(source.fullName));
       filePaths[source.fullName] = now;
     }
+
+    currentContext.applyChanges(changeSet);
   }
 
   void assertContextFiles(String contextPath, List<String> expectedFiles) {
diff --git a/pkg/analysis_server/test/domain_analysis_test.dart b/pkg/analysis_server/test/domain_analysis_test.dart
index d13a5a0..a41e086 100644
--- a/pkg/analysis_server/test/domain_analysis_test.dart
+++ b/pkg/analysis_server/test/domain_analysis_test.dart
@@ -24,6 +24,7 @@
   groupSep = ' | ';
 
   runReflectiveTests(AnalysisDomainTest);
+  runReflectiveTests(SetSubscriptionsTest);
 
   MockServerChannel serverChannel;
   MemoryResourceProvider resourceProvider;
@@ -40,7 +41,6 @@
   });
 
   group('updateContent', testUpdateContent);
-  group('setSubscriptions', test_setSubscriptions);
 
   group('AnalysisDomainHandler', () {
     group('setAnalysisRoots', () {
@@ -144,69 +144,6 @@
   });
 }
 
-void test_setSubscriptions() {
-  test('before analysis', () {
-    AnalysisTestHelper helper = new AnalysisTestHelper();
-    // subscribe
-    helper.addAnalysisSubscriptionHighlights(helper.testFile);
-    // create project
-    helper.createSingleFileProject('int V = 42;');
-    // wait, there are highlight regions
-    helper.onAnalysisComplete.then((_) {
-      var highlights = helper.getHighlights(helper.testFile);
-      expect(highlights, isNotEmpty);
-    });
-  });
-
-  test('after analysis', () {
-    AnalysisTestHelper helper = new AnalysisTestHelper();
-    // create project
-    helper.createSingleFileProject('int V = 42;');
-    // wait, no regions initially
-    return helper.onAnalysisComplete.then((_) {
-      var highlights = helper.getHighlights(helper.testFile);
-      expect(highlights, isEmpty);
-      // subscribe
-      helper.addAnalysisSubscriptionHighlights(helper.testFile);
-      // wait, has regions
-      return helper.onAnalysisComplete.then((_) {
-        var highlights = helper.getHighlights(helper.testFile);
-        expect(highlights, isNotEmpty);
-      });
-    });
-  });
-
-  test('after analysis, no such file', () {
-    AnalysisTestHelper helper = new AnalysisTestHelper();
-    helper.createSingleFileProject('int V = 42;');
-    return helper.onAnalysisComplete.then((_) {
-      String noFile = '/no-such-file.dart';
-      helper.addAnalysisSubscriptionHighlights(noFile);
-      return helper.onAnalysisComplete.then((_) {
-        var highlights = helper.getHighlights(noFile);
-        expect(highlights, isEmpty);
-      });
-    });
-  });
-
-  test('after analysis, SDK file', () {
-    AnalysisTestHelper helper = new AnalysisTestHelper();
-    helper.createSingleFileProject('''
-main() {
-  print(42);
-}
-''');
-    return helper.onAnalysisComplete.then((_) {
-      String file = '/lib/core/core.dart';
-      helper.addAnalysisSubscriptionNavigation(file);
-      return helper.onAnalysisComplete.then((_) {
-        var navigationRegions = helper.getNavigation(file);
-        expect(navigationRegions, isNotEmpty);
-      });
-    });
-  });
-}
-
 testUpdateContent() {
   test('bad type', () {
     AnalysisTestHelper helper = new AnalysisTestHelper();
@@ -607,3 +544,130 @@
     return code as String;
   }
 }
+
+@reflectiveTest
+class SetSubscriptionsTest extends AbstractAnalysisTest {
+  Map<String, List<HighlightRegion>> filesHighlights = {};
+
+  void processNotification(Notification notification) {
+    if (notification.event == ANALYSIS_HIGHLIGHTS) {
+      var params = new AnalysisHighlightsParams.fromNotification(notification);
+      filesHighlights[params.file] = params.regions;
+    }
+  }
+
+  test_afterAnalysis() async {
+    addTestFile('int V = 42;');
+    createProject();
+    // wait for analysis, no results initially
+    await waitForTasksFinished();
+    expect(filesHighlights[testFile], isNull);
+    // subscribe
+    addAnalysisSubscription(AnalysisService.HIGHLIGHTS, testFile);
+    await server.onAnalysisComplete;
+    // there are results
+    expect(filesHighlights[testFile], isNotEmpty);
+  }
+
+  test_afterAnalysis_noSuchFile() async {
+    String file = '/no-such-file.dart';
+    addTestFile('// no matter');
+    createProject();
+    // wait for analysis, no results initially
+    await waitForTasksFinished();
+    expect(filesHighlights[testFile], isNull);
+    // subscribe
+    addAnalysisSubscription(AnalysisService.HIGHLIGHTS, file);
+    await server.onAnalysisComplete;
+    // there are results
+    expect(filesHighlights[file], isNull);
+  }
+
+  test_afterAnalysis_packageFile_external() async {
+    String pkgFile = '/packages/pkgA/lib/libA.dart';
+    resourceProvider.newFile(pkgFile, '''
+library lib_a;
+class A {}
+''');
+    packageMapProvider.packageMap = {
+      'pkgA': [(resourceProvider.newFolder('/packages/pkgA/lib'))]
+    };
+    //
+    addTestFile('''
+import 'package:pkgA/libA.dart';
+main() {
+  new A();
+}
+''');
+    createProject();
+    // wait for analysis, no results initially
+    await waitForTasksFinished();
+    expect(filesHighlights[pkgFile], isNull);
+    // subscribe
+    addAnalysisSubscription(AnalysisService.HIGHLIGHTS, pkgFile);
+    await server.onAnalysisComplete;
+    // there are results
+    expect(filesHighlights[pkgFile], isNotEmpty);
+  }
+
+  test_afterAnalysis_packageFile_inRoot() async {
+    String pkgA = '/pkgA';
+    String pkgB = '/pkgA';
+    String pkgFileA = '$pkgA/lib/libA.dart';
+    String pkgFileB = '$pkgA/lib/libB.dart';
+    resourceProvider.newFile(pkgFileA, '''
+library lib_a;
+class A {}
+''');
+    resourceProvider.newFile(pkgFileB, '''
+import 'package:pkgA/libA.dart';
+main() {
+  new A();
+}
+''');
+    packageMapProvider.packageMap = {
+      'pkgA': [
+        resourceProvider.newFolder('$pkgA/lib'),
+        resourceProvider.newFolder('$pkgB/lib')
+      ]
+    };
+    // add 'pkgA' and 'pkgB' as projects
+    {
+      resourceProvider.newFolder(projectPath);
+      handleSuccessfulRequest(
+          new AnalysisSetAnalysisRootsParams([pkgA, pkgB], []).toRequest('0'));
+    }
+    // wait for analysis, no results initially
+    await waitForTasksFinished();
+    expect(filesHighlights[pkgFileA], isNull);
+    // subscribe
+    addAnalysisSubscription(AnalysisService.HIGHLIGHTS, pkgFileA);
+    await server.onAnalysisComplete;
+    // there are results
+    expect(filesHighlights[pkgFileA], isNotEmpty);
+  }
+
+  test_afterAnalysis_sdkFile() async {
+    String file = '/lib/core/core.dart';
+    addTestFile('// no matter');
+    createProject();
+    // wait for analysis, no results initially
+    await waitForTasksFinished();
+    expect(filesHighlights[file], isNull);
+    // subscribe
+    addAnalysisSubscription(AnalysisService.HIGHLIGHTS, file);
+    await server.onAnalysisComplete;
+    // there are results
+    expect(filesHighlights[file], isNotEmpty);
+  }
+
+  test_beforeAnalysis() async {
+    addTestFile('int V = 42;');
+    createProject();
+    // subscribe
+    addAnalysisSubscription(AnalysisService.HIGHLIGHTS, testFile);
+    // wait for analysis
+    await waitForTasksFinished();
+    expect(filesHighlights[testFile], isNotEmpty);
+  }
+}
diff --git a/pkg/analysis_server/test/domain_completion_test.dart b/pkg/analysis_server/test/domain_completion_test.dart
index 83dd415..20f6a41 100644
--- a/pkg/analysis_server/test/domain_completion_test.dart
+++ b/pkg/analysis_server/test/domain_completion_test.dart
@@ -192,8 +192,9 @@
     sendRequest(testFile);
     return pumpEventQueue().then((_) {
       expect(completionDomain.manager, isNotNull);
+      ContextSourcePair contextSource = server.getContextSourcePair(testFile2);
       ChangeSet changeSet = new ChangeSet();
-      changeSet.changedSource(server.getSource(testFile2));
+      changeSet.changedSource(contextSource.source);
       completionDomain.sourcesChanged(new SourcesChangedEvent(changeSet));
       expect(completionDomain.manager, isNull);
     });
@@ -617,9 +618,16 @@
       : super(channel, resourceProvider, packageMapProvider, index,
           analysisServerOptions, defaultSdk, instrumentationService);
 
+  @override
   AnalysisContext getAnalysisContext(String path) {
     return mockContext;
   }
+
+  @override
+  ContextSourcePair getContextSourcePair(String path) {
+    ContextSourcePair pair = super.getContextSourcePair(path);
+    return new ContextSourcePair(mockContext, pair.source);
+  }
 }
 
 /**
diff --git a/pkg/analysis_server/test/mock_sdk.dart b/pkg/analysis_server/test/mock_sdk.dart
index 1967994..504ecd9 100644
--- a/pkg/analysis_server/test/mock_sdk.dart
+++ b/pkg/analysis_server/test/mock_sdk.dart
@@ -223,10 +223,9 @@
     for (SdkLibrary library in LIBRARIES) {
       String libraryPath = library.path;
       if (filePath.replaceAll('\\', '/') == libraryPath) {
-        String path = library.shortName;
         try {
           resource.File file = provider.getResource(uri.path);
-          Uri dartUri = new Uri(scheme: 'dart', path: path);
+          Uri dartUri = Uri.parse(library.shortName);
           return file.createSource(dartUri);
         } catch (exception) {
           return null;
diff --git a/pkg/analysis_server/test/services/completion/common_usage_computer_test.dart b/pkg/analysis_server/test/services/completion/common_usage_computer_test.dart
index 5f2354d..a1d86e0 100644
--- a/pkg/analysis_server/test/services/completion/common_usage_computer_test.dart
+++ b/pkg/analysis_server/test/services/completion/common_usage_computer_test.dart
@@ -21,6 +21,7 @@
 import '../../analysis_abstract.dart';
 import '../../mocks.dart';
 import '../../reflective_tests.dart';
+import 'package:analysis_server/src/analysis_server.dart' show ContextSourcePair;
 
 main() {
   groupSep = ' | ';
@@ -94,8 +95,9 @@
     CompletionDomainHandler domainHandler = new CompletionDomainHandler(server);
     handler = domainHandler;
 
-    AnalysisContext context = server.getAnalysisContext(params.file);
-    Source source = server.getSource(params.file);
+    ContextSourcePair contextSource = server.getContextSourcePair(params.file);
+    AnalysisContext context = contextSource.context;
+    Source source = contextSource.source;
     DartCompletionManager completionManager = new DartCompletionManager(context,
         server.searchEngine, source, new DartCompletionCache(context, source),
         null, new CommonUsageComputer(selectorRelevance));
diff --git a/pkg/analyzer/lib/file_system/memory_file_system.dart b/pkg/analyzer/lib/file_system/memory_file_system.dart
index 7f4f954..da68f08 100644
--- a/pkg/analyzer/lib/file_system/memory_file_system.dart
+++ b/pkg/analyzer/lib/file_system/memory_file_system.dart
@@ -252,15 +252,32 @@
  * An in-memory implementation of [Source].
  */
 class _MemoryFileSource extends Source {
-  final _MemoryFile _file;
+  /**
+   * Map from encoded URI/filepath pair to a unique integer identifier.  This
+   * identifier is used for equality tests and hash codes.
+   *
+   * The URI and filepath are joined into a pair by separating them with an '@'
+   * character.
+   */
+  static final Map<String, int> _idTable = new HashMap<String, int>();
+
+  final _MemoryFile file;
 
   final Uri uri;
 
-  _MemoryFileSource(this._file, this.uri);
+  /**
+   * The unique ID associated with this [_MemoryFileSource].
+   */
+  final int id;
+
+  _MemoryFileSource(_MemoryFile file, Uri uri)
+      : uri = uri,
+        file = file,
+        id = _idTable.putIfAbsent('$uri@${file.path}', () => _idTable.length);
 
   @override
   TimestampedData<String> get contents {
-    return new TimestampedData<String>(modificationStamp, _file._content);
+    return new TimestampedData<String>(modificationStamp, file._content);
   }
 
   @override
@@ -269,10 +286,10 @@
   }
 
   @override
-  String get fullName => _file.path;
+  String get fullName => file.path;
 
   @override
-  int get hashCode => _file.hashCode;
+  int get hashCode => id;
 
   @override
   bool get isInSystemLibrary => uriKind == UriKind.DART_URI;
@@ -280,14 +297,14 @@
   @override
   int get modificationStamp {
     try {
-      return _file.modificationStamp;
+      return file.modificationStamp;
     } on FileSystemException catch (e) {
       return -1;
     }
   }
 
   @override
-  String get shortName => _file.shortName;
+  String get shortName => file.shortName;
 
   @override
   UriKind get uriKind {
@@ -304,14 +321,11 @@
 
   @override
   bool operator ==(other) {
-    if (other is _MemoryFileSource) {
-      return other._file == _file;
-    }
-    return false;
+    return other is _MemoryFileSource && other.id == id;
   }
 
   @override
-  bool exists() => _file.exists;
+  bool exists() => file.exists;
 
   @override
   Uri resolveRelativeUri(Uri relativeUri) {
@@ -319,7 +333,7 @@
   }
 
   @override
-  String toString() => _file.toString();
+  String toString() => file.toString();
 }
 
 /**
diff --git a/pkg/analyzer/lib/src/analyzer_impl.dart b/pkg/analyzer/lib/src/analyzer_impl.dart
index 849356f..a9f72a3 100644
--- a/pkg/analyzer/lib/src/analyzer_impl.dart
+++ b/pkg/analyzer/lib/src/analyzer_impl.dart
@@ -144,31 +144,48 @@
     return _analyzeSync(printMode);
   }
 
-  void prepareAnalysisContext(JavaFile sourceFile, Source source) {
+  Source computeLibrarySource() {
+    JavaFile sourceFile = new JavaFile(sourcePath);
+    Source source = sdk.fromFileUri(sourceFile.toURI());
+    if (source != null) {
+      return source;
+    }
+    source = new FileBasedSource.con2(sourceFile.toURI(), sourceFile);
+    Uri uri = context.sourceFactory.restoreUri(source);
+    if (uri == null) {
+      return source;
+    }
+    return new FileBasedSource.con2(uri, sourceFile);
+  }
+
+  /**
+   * Create and return the source factory to be used by the analysis context.
+   */
+  SourceFactory createSourceFactory() {
     List<UriResolver> resolvers = [
       new CustomUriResolver(options.customUrlMappings),
-      new DartUriResolver(sdk),
-      new FileUriResolver()
+      new DartUriResolver(sdk)
     ];
-    // maybe add package resolver
-    {
-      JavaFile packageDirectory;
-      if (options.packageRootPath != null) {
-        packageDirectory = new JavaFile(options.packageRootPath);
-        resolvers.add(new PackageUriResolver([packageDirectory]));
-      } else {
-        PubPackageMapProvider pubPackageMapProvider =
-            new PubPackageMapProvider(PhysicalResourceProvider.INSTANCE, sdk);
-        PackageMapInfo packageMapInfo = pubPackageMapProvider.computePackageMap(
-            PhysicalResourceProvider.INSTANCE.getResource('.'));
-        Map<String, List<Folder>> packageMap = packageMapInfo.packageMap;
-        if (packageMap != null) {
-          resolvers.add(new PackageMapUriResolver(
-              PhysicalResourceProvider.INSTANCE, packageMap));
-        }
+    if (options.packageRootPath != null) {
+      JavaFile packageDirectory = new JavaFile(options.packageRootPath);
+      resolvers.add(new PackageUriResolver([packageDirectory]));
+    } else {
+      PubPackageMapProvider pubPackageMapProvider =
+          new PubPackageMapProvider(PhysicalResourceProvider.INSTANCE, sdk);
+      PackageMapInfo packageMapInfo = pubPackageMapProvider.computePackageMap(
+          PhysicalResourceProvider.INSTANCE.getResource('.'));
+      Map<String, List<Folder>> packageMap = packageMapInfo.packageMap;
+      if (packageMap != null) {
+        resolvers.add(new PackageMapUriResolver(
+            PhysicalResourceProvider.INSTANCE, packageMap));
       }
     }
-    sourceFactory = new SourceFactory(resolvers);
+    resolvers.add(new FileUriResolver());
+    return new SourceFactory(resolvers);
+  }
+
+  void prepareAnalysisContext() {
+    sourceFactory = createSourceFactory();
     context = AnalysisEngine.instance.createAnalysisContext();
     context.sourceFactory = sourceFactory;
     Map<String, String> definedVariables = options.definedVariables;
@@ -191,9 +208,11 @@
     contextOptions.generateSdkErrors = options.showSdkWarnings;
     context.analysisOptions = contextOptions;
 
+    librarySource = computeLibrarySource();
+
     // Create and add a ChangeSet
     ChangeSet changeSet = new ChangeSet();
-    changeSet.addedSource(source);
+    changeSet.addedSource(librarySource);
     context.applyChanges(changeSet);
   }
 
@@ -222,12 +241,8 @@
     if (sourcePath == null) {
       throw new ArgumentError("sourcePath cannot be null");
     }
-    JavaFile sourceFile = new JavaFile(sourcePath);
-    Uri uri = getUri(sourceFile);
-    librarySource = new FileBasedSource.con2(uri, sourceFile);
-
     // prepare context
-    prepareAnalysisContext(sourceFile, librarySource);
+    prepareAnalysisContext();
   }
 
   /// The async version of the analysis
@@ -403,24 +418,6 @@
   }
 
   /**
-   * Returns the [Uri] for the given input file.
-   *
-   * Usually it is a `file:` [Uri], but if [file] is located in the `lib`
-   * directory of the [sdk], then returns a `dart:` [Uri].
-   */
-  static Uri getUri(JavaFile file) {
-    // may be file in SDK
-    {
-      Source source = sdk.fromFileUri(file.toURI());
-      if (source != null) {
-        return source.uri;
-      }
-    }
-    // some generic file
-    return file.toURI();
-  }
-
-  /**
    * Convert [sourcePath] into an absolute path.
    */
   static String _normalizeSourcePath(String sourcePath) {
diff --git a/pkg/analyzer/lib/src/generated/engine.dart b/pkg/analyzer/lib/src/generated/engine.dart
index 4625d2c..399959c 100644
--- a/pkg/analyzer/lib/src/generated/engine.dart
+++ b/pkg/analyzer/lib/src/generated/engine.dart
@@ -451,6 +451,12 @@
   void set sourceFactory(SourceFactory factory);
 
   /**
+   * Returns a type provider for this context or throws [AnalysisException] if
+   * `dart:core` or `dart:async` cannot be resolved.
+   */
+  TypeProvider get typeProvider;
+
+  /**
    * Add the given listener to the list of objects that are to be notified when various analysis
    * results are produced in this context.
    *
@@ -781,6 +787,12 @@
   ht.HtmlUnit getResolvedHtmlUnit(Source htmlSource);
 
   /**
+   * Return a list of the sources being analyzed in this context whose full path
+   * is equal to the given [path].
+   */
+  List<Source> getSourcesWithFullName(String path);
+
+  /**
    * Return `true` if the given source is known to be the defining compilation unit of a
    * library that can be run on a client (references 'dart:html', either directly or indirectly).
    *
@@ -1121,7 +1133,8 @@
   void set analysisOptions(AnalysisOptions options) {
     bool needsRecompute = this._options.analyzeFunctionBodiesPredicate !=
             options.analyzeFunctionBodiesPredicate ||
-            this._options.generateImplicitErrors != options.generateImplicitErrors ||
+        this._options.generateImplicitErrors !=
+            options.generateImplicitErrors ||
         this._options.generateSdkErrors != options.generateSdkErrors ||
         this._options.dart2jsHint != options.dart2jsHint ||
         (this._options.hint && !options.hint) ||
@@ -1147,7 +1160,7 @@
     }
     this._options.analyzeFunctionBodiesPredicate =
         options.analyzeFunctionBodiesPredicate;
-        this._options.generateImplicitErrors = options.generateImplicitErrors;
+    this._options.generateImplicitErrors = options.generateImplicitErrors;
     this._options.generateSdkErrors = options.generateSdkErrors;
     this._options.dart2jsHint = options.dart2jsHint;
     this._options.hint = options.hint;
@@ -2158,6 +2171,18 @@
   }
 
   @override
+  List<Source> getSourcesWithFullName(String path) {
+    List<Source> sources = <Source>[];
+    MapIterator<Source, SourceEntry> iterator = _cache.iterator();
+    while (iterator.moveNext()) {
+      if (iterator.key.fullName == path) {
+        sources.add(iterator.key);
+      }
+    }
+    return sources;
+  }
+
+  @override
   bool handleContentsChanged(
       Source source, String originalContents, String newContents, bool notify) {
     SourceEntry sourceEntry = _cache.get(source);
@@ -2619,20 +2644,6 @@
   }
 
   /**
-   * Return `true` if errors should be produced for the given [source]. The
-   * [dartEntry] associated with the source is passed in for efficiency.
-   */
-  bool _shouldErrorsBeAnalyzed(Source source, DartEntry dartEntry) {
-    if (source.isInSystemLibrary) {
-      return _generateSdkErrors;
-    } else if (!dartEntry.explicitlyAdded) {
-      return _generateImplicitErrors;
-    } else {
-      return true;
-    }
-  }
-
-  /**
    * Visit all entries of the content cache.
    */
   void visitContentCache(ContentCacheVisitor visitor) {
@@ -4323,6 +4334,28 @@
     }
   }
 
+  /**
+   * Record the results produced by performing a [task] and return the cache
+   * entry associated with the results.
+   */
+  DartEntry _recordBuildUnitElementTask(BuildUnitElementTask task) {
+    Source source = task.source;
+    Source library = task.library;
+    DartEntry dartEntry = _cache.get(source);
+    CaughtException thrownException = task.exception;
+    if (thrownException != null) {
+      dartEntry.recordBuildElementErrorInLibrary(library, thrownException);
+      throw new AnalysisException('<rethrow>', thrownException);
+    }
+    dartEntry.setValueInLibrary(DartEntry.BUILT_UNIT, library, task.unit);
+    dartEntry.setValueInLibrary(
+        DartEntry.BUILT_ELEMENT, library, task.unitElement);
+    ChangeNoticeImpl notice = _getNotice(source);
+    LineInfo lineInfo = dartEntry.getValue(SourceEntry.LINE_INFO);
+    notice.setErrors(dartEntry.allErrors, lineInfo);
+    return dartEntry;
+  }
+
 //  /**
 //   * Notify all of the analysis listeners that the given source is no longer included in the set of
 //   * sources that are being analyzed.
@@ -4402,28 +4435,6 @@
 //  }
 
   /**
-   * Record the results produced by performing a [task] and return the cache
-   * entry associated with the results.
-   */
-  DartEntry _recordBuildUnitElementTask(BuildUnitElementTask task) {
-    Source source = task.source;
-    Source library = task.library;
-    DartEntry dartEntry = _cache.get(source);
-    CaughtException thrownException = task.exception;
-    if (thrownException != null) {
-      dartEntry.recordBuildElementErrorInLibrary(library, thrownException);
-      throw new AnalysisException('<rethrow>', thrownException);
-    }
-    dartEntry.setValueInLibrary(DartEntry.BUILT_UNIT, library, task.unit);
-    dartEntry.setValueInLibrary(
-        DartEntry.BUILT_ELEMENT, library, task.unitElement);
-    ChangeNoticeImpl notice = _getNotice(source);
-    LineInfo lineInfo = dartEntry.getValue(SourceEntry.LINE_INFO);
-    notice.setErrors(dartEntry.allErrors, lineInfo);
-    return dartEntry;
-  }
-
-  /**
    * Given a cache entry and a library element, record the library element and other information
    * gleaned from the element in the cache entry.
    *
@@ -4819,6 +4830,20 @@
   }
 
   /**
+   * Return `true` if errors should be produced for the given [source]. The
+   * [dartEntry] associated with the source is passed in for efficiency.
+   */
+  bool _shouldErrorsBeAnalyzed(Source source, DartEntry dartEntry) {
+    if (source.isInSystemLibrary) {
+      return _generateSdkErrors;
+    } else if (!dartEntry.explicitlyAdded) {
+      return _generateImplicitErrors;
+    } else {
+      return true;
+    }
+  }
+
+  /**
    * Create an entry for the newly added [source] and invalidate any sources
    * that referenced the source before it existed.
    *
diff --git a/pkg/analyzer/lib/src/generated/incremental_resolver.dart b/pkg/analyzer/lib/src/generated/incremental_resolver.dart
index 4a45619..5832ef8 100644
--- a/pkg/analyzer/lib/src/generated/incremental_resolver.dart
+++ b/pkg/analyzer/lib/src/generated/incremental_resolver.dart
@@ -472,14 +472,18 @@
       } else {
         _assertEquals(nodeDefault.toSource(), element.defaultValueCode);
       }
+      _assertCompatibleParameter(node.parameter, element);
     } else if (node is FieldFormalParameter) {
       _assertTrue(element.isInitializingFormal);
+      _assertCompatibleParameters(node.parameters, element.parameters);
     } else if (node is FunctionTypedFormalParameter) {
+      _assertFalse(element.isInitializingFormal);
       _assertTrue(element.type is FunctionType);
       FunctionType elementType = element.type;
       _assertCompatibleParameters(node.parameters, element.parameters);
       _assertSameType(node.returnType, elementType.returnType);
     } else if (node is SimpleFormalParameter) {
+      _assertFalse(element.isInitializingFormal);
       _assertSameType(node.type, element.type);
     }
   }
@@ -1250,7 +1254,8 @@
           }
           // fail if a comment change outside the bodies
           if (firstPair.kind == _TokenDifferenceKind.COMMENT) {
-            if (beginOffsetOld <= oldNode.offset || beginOffsetNew <= newNode.offset) {
+            if (beginOffsetOld <= oldNode.offset ||
+                beginOffsetNew <= newNode.offset) {
               logger.log('Failure: comment outside a function body.');
               return false;
             }
diff --git a/pkg/analyzer/test/generated/engine_test.dart b/pkg/analyzer/test/generated/engine_test.dart
index 35e9660..0949de7 100644
--- a/pkg/analyzer/test/generated/engine_test.dart
+++ b/pkg/analyzer/test/generated/engine_test.dart
@@ -1280,6 +1280,26 @@
     expect(_context.sourceFactory, same(_sourceFactory));
   }
 
+  void test_getSourcesWithFullName() {
+    String filePath = '/foo/lib/file.dart';
+    List<Source> expected = <Source>[];
+    ChangeSet changeSet = new ChangeSet();
+
+    TestSourceWithUri source1 =
+        new TestSourceWithUri(filePath, Uri.parse('file://$filePath'));
+    expected.add(source1);
+    changeSet.addedSource(source1);
+
+    TestSourceWithUri source2 =
+        new TestSourceWithUri(filePath, Uri.parse('package:foo/file.dart'));
+    expected.add(source2);
+    changeSet.addedSource(source2);
+
+    _context.applyChanges(changeSet);
+    expect(
+        _context.getSourcesWithFullName(filePath), unorderedEquals(expected));
+  }
+
   void test_getStatistics() {
     AnalysisContextStatistics statistics = _context.statistics;
     expect(statistics, isNotNull);
@@ -5649,6 +5669,11 @@
     return null;
   }
   @override
+  List<Source> getSourcesWithFullName(String path) {
+    fail("Unexpected invocation of getSourcesWithFullName");
+    return null;
+  }
+  @override
   bool handleContentsChanged(
       Source source, String originalContents, String newContents, bool notify) {
     fail("Unexpected invocation of handleContentsChanged");
@@ -5713,6 +5738,7 @@
   void setContents(Source source, String contents) {
     fail("Unexpected invocation of setContents");
   }
+
   @override
   void visitCacheItems(void callback(Source source, SourceEntry dartEntry,
       DataDescriptor rowDesc, CacheState state)) {
diff --git a/pkg/analyzer/test/generated/incremental_resolver_test.dart b/pkg/analyzer/test/generated/incremental_resolver_test.dart
index 3eb51e3..3c57a97 100644
--- a/pkg/analyzer/test/generated/incremental_resolver_test.dart
+++ b/pkg/analyzer/test/generated/incremental_resolver_test.dart
@@ -589,6 +589,118 @@
 ''');
   }
 
+  void test_false_fieldFormalParameter_add() {
+    _assertDoesNotMatch(r'''
+class A {
+  final field;
+  A(field);
+}
+''', r'''
+class A {
+  final field;
+  A(this.field);
+}
+''');
+  }
+
+  void test_false_fieldFormalParameter_add_function() {
+    _assertDoesNotMatch(r'''
+class A {
+  final field;
+  A(field(a));
+}
+''', r'''
+class A {
+  final field;
+  A(this.field(a));
+}
+''');
+  }
+
+  void test_false_fieldFormalParameter_parameters_add() {
+    _assertDoesNotMatch(r'''
+class A {
+  final field;
+  A(this.field(a));
+}
+''', r'''
+class A {
+  final field;
+  A(this.field(a, b));
+}
+''');
+  }
+
+  void test_false_fieldFormalParameter_parameters_remove() {
+    _assertDoesNotMatch(r'''
+class A {
+  final field;
+  A(this.field(a, b));
+}
+''', r'''
+class A {
+  final field;
+  A(this.field(a));
+}
+''');
+  }
+
+  void test_false_fieldFormalParameter_parameters_typeEdit() {
+    _assertDoesNotMatch(r'''
+class A {
+  final field;
+  A(this.field(int p));
+}
+''', r'''
+class A {
+  final field;
+  A(this.field(String p));
+}
+''');
+  }
+
+  void test_false_fieldFormalParameter_remove_default() {
+    _assertDoesNotMatch(r'''
+class A {
+  final field;
+  A([this.field = 0]);
+}
+''', r'''
+class A {
+  final field;
+  A([field = 0]);
+}
+''');
+  }
+
+  void test_false_fieldFormalParameter_remove_function() {
+    _assertDoesNotMatch(r'''
+class A {
+  final field;
+  A(this.field(a));
+}
+''', r'''
+class A {
+  final field;
+  A(field(a));
+}
+''');
+  }
+
+  void test_false_fieldFormalParameter_remove_normal() {
+    _assertDoesNotMatch(r'''
+class A {
+  final field;
+  A(this.field);
+}
+''', r'''
+class A {
+  final field;
+  A(field);
+}
+''');
+  }
+
   void test_false_fieldFormalParameterElement_wasSimple() {
     _assertDoesNotMatch(r'''
 class A {
@@ -1718,6 +1830,20 @@
 ''');
   }
 
+  void test_true_fieldFormalParameter_function() {
+    _assertMatches(r'''
+class A {
+  final field;
+  A(this.field(int a, String b));
+}
+''', r'''
+class A {
+  final field;
+  A(this.field(int a, String b));
+}
+''');
+  }
+
   void test_true_functionTypeAlias_list_reorder() {
     _assertMatches(r'''
 typedef A(int pa);
@@ -2843,6 +2969,23 @@
 ''');
   }
 
+  void test_endOfLineComment_localFunction_inTopLevelVariable() {
+    _resolveUnit(r'''
+typedef int Binary(one, two, three);
+
+int Global = f((a, b, c) {
+  return 0; // Some comment
+});
+''');
+    _updateAndValidate(r'''
+typedef int Binary(one, two, three);
+
+int Global = f((a, b, c) {
+  return 0; // Some  comment
+});
+''');
+  }
+
   void test_endOfLineComment_outBody_add() {
     _resolveUnit(r'''
 main() {
@@ -2892,23 +3035,6 @@
 ''', expectedSuccess: false);
   }
 
-  void test_endOfLineComment_localFunction_inTopLevelVariable() {
-    _resolveUnit(r'''
-typedef int Binary(one, two, three);
-
-int Global = f((a, b, c) {
-  return 0; // Some comment
-});
-''');
-    _updateAndValidate(r'''
-typedef int Binary(one, two, three);
-
-int Global = f((a, b, c) {
-  return 0; // Some  comment
-});
-''');
-  }
-
   void test_endOfLineComment_remove() {
     _resolveUnit(r'''
 main() {
diff --git a/pkg/analyzer/test/generated/test_support.dart b/pkg/analyzer/test/generated/test_support.dart
index c59d375..e5a05d0 100644
--- a/pkg/analyzer/test/generated/test_support.dart
+++ b/pkg/analyzer/test/generated/test_support.dart
@@ -615,3 +615,32 @@
     _contents = value;
   }
 }
+
+class TestSourceWithUri extends TestSource {
+  final Uri uri;
+
+  TestSourceWithUri(String path, this.uri, [String content])
+      : super(path, content);
+
+  UriKind get uriKind {
+    if (uri == null) {
+      return UriKind.FILE_URI;
+    } else if (uri.scheme == 'dart') {
+      return UriKind.DART_URI;
+    } else if (uri.scheme == 'package') {
+      return UriKind.PACKAGE_URI;
+    }
+    return UriKind.FILE_URI;
+  }
+
+  bool operator ==(Object other) {
+    if (other is TestSource) {
+      return other.uri == uri;
+    }
+    return false;
+  }
+
+  Uri resolveRelativeUri(Uri uri) {
+    return this.uri.resolveUri(uri);
+  }
+}
diff --git a/pkg/analyzer/test/src/task/driver_test.dart b/pkg/analyzer/test/src/task/driver_test.dart
index 9a7afd9..f82d327 100644
--- a/pkg/analyzer/test/src/task/driver_test.dart
+++ b/pkg/analyzer/test/src/task/driver_test.dart
@@ -709,6 +709,11 @@
   }
 
   @override
+  List<Source> getSourcesWithFullName(String path) {
+    return baseContext.getSourcesWithFullName(path);
+  }
+
+  @override
   bool handleContentsChanged(
       Source source, String originalContents, String newContents, bool notify) {
     return baseContext.handleContentsChanged(
diff --git a/pkg/compiler/lib/src/js/rewrite_async.dart b/pkg/compiler/lib/src/js/rewrite_async.dart
index c2863c5..6540829 100644
--- a/pkg/compiler/lib/src/js/rewrite_async.dart
+++ b/pkg/compiler/lib/src/js/rewrite_async.dart
@@ -2412,7 +2412,10 @@
   @override
   bool visitSwitch(js.Switch node) {
     loopsAndSwitches.add(node);
-    bool result = visit(node.key);
+    // If the key has an `await` expression, do not transform the
+    // body of the switch.
+    visit(node.key);
+    bool result = false;
     for (js.SwitchClause clause in node.cases) {
       if (visit(clause)) result = true;
     }
diff --git a/runtime/bin/builtin.dart b/runtime/bin/builtin.dart
index f5eec7e..d8c586c 100644
--- a/runtime/bin/builtin.dart
+++ b/runtime/bin/builtin.dart
@@ -116,7 +116,15 @@
 
 // Corelib 'Uri.base' implementation.
 Uri _uriBase() {
-  return new Uri.file(_getCurrentDirectoryPath() + "/");
+  // We are not using Dircetory.current here to limit the dependency
+  // on dart:io. This code is the same as:
+  //   return new Uri.file(Directory.current.path + "/");
+  var result = _getCurrentDirectoryPath();
+  if (result is OSError) {
+    throw new FileSystemException(
+        "Getting current working directory failed", "", result);
+  }
+  return new Uri.file(result + "/");
 }
 
 _getUriBaseClosure() => _uriBase;
diff --git a/runtime/lib/core_patch.dart b/runtime/lib/core_patch.dart
index 810eb31..5a26fc5 100644
--- a/runtime/lib/core_patch.dart
+++ b/runtime/lib/core_patch.dart
@@ -24,6 +24,7 @@
   // below can access it because it uses the same name suffix.
   static const List<String> _enum_names = null;
   String toString() => _enum_names[index];
+  int get hashCode => _enum_names[index].hashCode;
 }
 
 
diff --git a/runtime/lib/isolate_patch.dart b/runtime/lib/isolate_patch.dart
index 84928be..cd71ced 100644
--- a/runtime/lib/isolate_patch.dart
+++ b/runtime/lib/isolate_patch.dart
@@ -335,6 +335,11 @@
   static const _RESUME = 2;
   static const _PING = 3;
   static const _KILL = 4;
+  static const _ADD_EXIT = 5;
+  static const _DEL_EXIT = 6;
+  static const _ADD_ERROR = 7;
+  static const _DEL_ERROR = 8;
+  static const _ERROR_FATAL = 9;
 
 
   static void _spawnFunction(SendPort readyPort, Function topLevelFunction,
@@ -367,15 +372,28 @@
   }
 
   /* patch */ void addOnExitListener(SendPort responsePort) {
-    throw new UnsupportedError("addOnExitListener");
+    var msg = new List(3)
+        ..[0] = 0  // Make room for OOB message type.
+        ..[1] = _ADD_EXIT
+        ..[2] = responsePort;
+    _sendOOB(controlPort, msg);
   }
 
   /* patch */ void removeOnExitListener(SendPort responsePort) {
-    throw new UnsupportedError("removeOnExitListener");
+    var msg = new List(3)
+        ..[0] = 0  // Make room for OOB message type.
+        ..[1] = _DEL_EXIT
+        ..[2] = responsePort;
+    _sendOOB(controlPort, msg);
   }
 
   /* patch */ void setErrorsFatal(bool errorsAreFatal) {
-    throw new UnsupportedError("setErrorsFatal");
+    var msg = new List(4)
+      ..[0] = 0  // Make room for OOB message type.
+      ..[1] = _ERROR_FATAL
+      ..[2] = terminateCapability
+      ..[3] = errorsAreFatal;
+    _sendOOB(controlPort, msg);
   }
 
   /* patch */ void kill([int priority = BEFORE_NEXT_EVENT]) {
@@ -397,11 +415,19 @@
   }
 
   /* patch */ void addErrorListener(SendPort port) {
-    throw new UnsupportedError("addErrorListener");
+    var msg = new List(3)
+        ..[0] = 0  // Make room for OOB message type.
+        ..[1] = _ADD_ERROR
+        ..[2] = port;
+    _sendOOB(controlPort, msg);
   }
 
   /* patch */ void removeErrorListener(SendPort port) {
-    throw new UnsupportedError("removeErrorListener");
+    var msg = new List(3)
+        ..[0] = 0  // Make room for OOB message type.
+        ..[1] = _DEL_ERROR
+        ..[2] = port;
+    _sendOOB(controlPort, msg);
   }
 
   static Isolate _getCurrentIsolate() {
diff --git a/runtime/vm/ast_transformer.cc b/runtime/vm/ast_transformer.cc
index 87c6170..3acd1d0 100644
--- a/runtime/vm/ast_transformer.cc
+++ b/runtime/vm/ast_transformer.cc
@@ -540,37 +540,26 @@
 
 
 void AwaitTransformer::VisitLoadLocalNode(LoadLocalNode* node) {
-  LocalVariable* result = AddToPreambleNewTempVar(
-      new(Z) LoadLocalNode(node->token_pos(), &node->local()));
-  result_ = new(Z) LoadLocalNode(Scanner::kNoSourcePos, result);
+  result_ = node;
 }
 
 
 void AwaitTransformer::VisitStoreLocalNode(StoreLocalNode* node) {
   AstNode* new_value = Transform(node->value());
-  LocalVariable* result = AddToPreambleNewTempVar(
-      new(Z) StoreLocalNode(node->token_pos(),
-                            &node->local(),
-                            new_value));
-  result_ = new(Z) LoadLocalNode(Scanner::kNoSourcePos, result);
+  result_ = new(Z) StoreLocalNode(node->token_pos(), &node->local(), new_value);
 }
 
 
 void AwaitTransformer::VisitLoadStaticFieldNode(LoadStaticFieldNode* node) {
-  LocalVariable* result = AddToPreambleNewTempVar(
-      new(Z) LoadStaticFieldNode(node->token_pos(),
-                                 node->field()));
-  result_ = new(Z) LoadLocalNode(Scanner::kNoSourcePos, result);
+  result_ = node;
 }
 
 
 void AwaitTransformer::VisitStoreStaticFieldNode(StoreStaticFieldNode* node) {
   AstNode* new_value = Transform(node->value());
-  LocalVariable* result = AddToPreambleNewTempVar(
-      new(Z) StoreStaticFieldNode(node->token_pos(),
-                                  node->field(),
-                                  new_value));
-  result_ = new(Z) LoadLocalNode(Scanner::kNoSourcePos, result);
+  result_ = new(Z) StoreStaticFieldNode(node->token_pos(),
+                                        node->field(),
+                                        new_value);
 }
 
 
@@ -612,7 +601,18 @@
 
 
 void AwaitTransformer::VisitLetNode(LetNode* node) {
-  // TODO(mlippautz): Check initializers and their temps.
+  // Add all the initializer nodes and their temporary variables
+  // to the preamble. The temporary variables will be captured
+  // as a side effect of being added to a scope, and the subsequent
+  // nodes that are added to the preample can access them.
+  for (intptr_t i = 0; i < node->num_temps(); i++) {
+    preamble_->scope()->AddVariable(node->TempAt(i));
+    AstNode* new_init_val = Transform(node->InitializerAt(i));
+    preamble_->Add(new(Z) StoreLocalNode(node->token_pos(),
+                   node->TempAt(i),
+                   new_init_val));
+  }
+  // The transformed LetNode does not have any temporary variables.
   LetNode* result = new(Z) LetNode(node->token_pos());
   for (intptr_t i = 0; i < node->nodes().length(); i++) {
     result->AddNode(Transform(node->nodes()[i]));
diff --git a/runtime/vm/class_finalizer.cc b/runtime/vm/class_finalizer.cc
index 93815ca..a7468b9 100644
--- a/runtime/vm/class_finalizer.cc
+++ b/runtime/vm/class_finalizer.cc
@@ -2098,8 +2098,7 @@
   ASSERT(!mixin_type.IsNull());
   ASSERT(mixin_type.HasResolvedTypeClass());
   const Class& mixin_cls = Class::Handle(isolate, mixin_type.type_class());
-  const Error& error = Error::Handle(mixin_cls.EnsureIsFinalized(isolate));
-  ASSERT(error.IsNull());
+  FinalizeClass(mixin_cls);
   // If the mixin is a mixin application alias class, there are no members to
   // apply here. A new synthesized class representing the aliased mixin
   // application class was inserted in the super chain of this mixin application
diff --git a/runtime/vm/intermediate_language_x64.cc b/runtime/vm/intermediate_language_x64.cc
index 16af510..ee1a43b 100644
--- a/runtime/vm/intermediate_language_x64.cc
+++ b/runtime/vm/intermediate_language_x64.cc
@@ -5873,7 +5873,7 @@
 LocationSummary* BinaryUint32OpInstr::MakeLocationSummary(Zone* zone,
                                                           bool opt) const {
   const intptr_t kNumInputs = 2;
-  const intptr_t kNumTemps = (op_kind() == Token::kMUL) ? 1 : 0;
+  const intptr_t kNumTemps = 0;
   LocationSummary* summary = new(zone) LocationSummary(
       zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
   summary->set_in(0, Location::RequiresRegister());
diff --git a/runtime/vm/isolate.cc b/runtime/vm/isolate.cc
index 5b26207..214956a 100644
--- a/runtime/vm/isolate.cc
+++ b/runtime/vm/isolate.cc
@@ -123,13 +123,21 @@
   virtual Isolate* isolate() const { return isolate_; }
 
  private:
-  // Keep in sync with isolate_patch.dart.
+  // Keep both these enums in sync with isolate_patch.dart.
+  // The different Isolate API message types.
   enum {
     kPauseMsg = 1,
     kResumeMsg = 2,
     kPingMsg = 3,
     kKillMsg = 4,
-
+    kAddExitMsg = 5,
+    kDelExitMsg = 6,
+    kAddErrorMsg = 7,
+    kDelErrorMsg = 8,
+    kErrorFatalMsg = 9,
+  };
+  // The different Isolate API message priorities for ping and kill messages.
+  enum {
     kImmediateAction = 0,
     kBeforeNextEventAction = 1,
     kAsEventAction = 2
@@ -164,8 +172,8 @@
   if (message.Length() < 2) return true;
   const Object& type = Object::Handle(I, message.At(1));
   if (!type.IsSmi()) return true;
-  const Smi& msg_type = Smi::Cast(type);
-  switch (msg_type.Value()) {
+  const intptr_t msg_type = Smi::Cast(type).Value();
+  switch (msg_type) {
     case kPauseMsg: {
       // [ OOB, kPauseMsg, pause capability, resume capability ]
       if (message.Length() != 4) return true;
@@ -252,6 +260,45 @@
       }
       break;
     }
+    case kAddExitMsg:
+    case kDelExitMsg:
+    case kAddErrorMsg:
+    case kDelErrorMsg: {
+      // [ OOB, msg, listener port ]
+      if (message.Length() != 3) return true;
+      const Object& obj = Object::Handle(I, message.At(2));
+      if (!obj.IsSendPort()) return true;
+      const SendPort& listener = SendPort::Cast(obj);
+      switch (msg_type) {
+        case kAddExitMsg:
+          I->AddExitListener(listener);
+          break;
+        case kDelExitMsg:
+          I->RemoveExitListener(listener);
+          break;
+        case kAddErrorMsg:
+          I->AddErrorListener(listener);
+          break;
+        case kDelErrorMsg:
+          I->RemoveErrorListener(listener);
+          break;
+        default:
+          UNREACHABLE();
+      }
+      break;
+    }
+    case kErrorFatalMsg: {
+      // [ OOB, kErrorFatalMsg, terminate capability, val ]
+      if (message.Length() != 4) return true;
+      // Check that the terminate capability has been passed correctly.
+      Object& obj = Object::Handle(I, message.At(2));
+      if (!I->VerifyTerminateCapability(obj)) return true;
+      // Get the value to be set.
+      obj = message.At(3);
+      if (!obj.IsBool()) return true;
+      I->SetErrorsFatal(Bool::Cast(obj).value());
+      break;
+    }
 #if defined(DEBUG)
     // Malformed OOB messages are silently ignored in release builds.
     default:
@@ -417,8 +464,35 @@
     Dart_ExitScope();
   }
 
-  I->object_store()->set_sticky_error(result);
-  return false;
+  // Generate the error and stacktrace strings for the error message.
+  String& exc_str = String::Handle(I);
+  String& stacktrace_str = String::Handle(I);
+  if (result.IsUnhandledException()) {
+    const UnhandledException& uhe = UnhandledException::Cast(result);
+    const Instance& exception = Instance::Handle(I, uhe.exception());
+    Object& tmp = Object::Handle(I);
+    tmp = DartLibraryCalls::ToString(exception);
+    if (!tmp.IsString()) {
+      tmp = String::New(exception.ToCString());
+    }
+    exc_str ^= tmp.raw();
+
+    const Instance& stacktrace = Instance::Handle(I, uhe.stacktrace());
+    tmp = DartLibraryCalls::ToString(stacktrace);
+    if (!tmp.IsString()) {
+      tmp = String::New(stacktrace.ToCString());
+    }
+    stacktrace_str ^= tmp.raw();;
+  } else {
+    exc_str = String::New(result.ToErrorCString());
+  }
+  I->NotifyErrorListeners(exc_str, stacktrace_str);
+
+  if (I->ErrorsFatal()) {
+    I->object_store()->set_sticky_error(result);
+    return false;
+  }
+  return true;
 }
 
 
@@ -449,6 +523,7 @@
       origin_id_(0),
       pause_capability_(0),
       terminate_capability_(0),
+      errors_fatal_(true),
       heap_(NULL),
       object_store_(NULL),
       top_exit_frame_info_(0),
@@ -514,6 +589,7 @@
       main_port_(0),
       pause_capability_(0),
       terminate_capability_(0),
+      errors_fatal_(true),
       heap_(NULL),
       object_store_(NULL),
       top_exit_frame_info_(0),
@@ -869,7 +945,7 @@
 
 bool Isolate::AddResumeCapability(const Capability& capability) {
   // Ensure a limit for the number of resume capabilities remembered.
-  static const intptr_t kMaxResumeCapabilities = kSmiMax / (6*kWordSize);
+  static const intptr_t kMaxResumeCapabilities = kSmiMax / (6 * kWordSize);
 
   const GrowableObjectArray& caps = GrowableObjectArray::Handle(
       this, object_store()->resume_capabilities());
@@ -917,6 +993,148 @@
 }
 
 
+// TODO(iposva): Remove duplicated code and start using some hash based
+// structure instead of these linear lookups.
+void Isolate::AddExitListener(const SendPort& listener) {
+  // Ensure a limit for the number of listeners remembered.
+  static const intptr_t kMaxListeners = kSmiMax / (6 * kWordSize);
+
+  const GrowableObjectArray& listeners = GrowableObjectArray::Handle(
+       this, object_store()->exit_listeners());
+  SendPort& current = SendPort::Handle(this);
+  intptr_t insertion_index = -1;
+  for (intptr_t i = 0; i < listeners.Length(); i++) {
+    current ^= listeners.At(i);
+    if (current.IsNull()) {
+      if (insertion_index < 0) {
+        insertion_index = i;
+      }
+    } else if (current.Id() == listener.Id()) {
+      return;
+    }
+  }
+  if (insertion_index < 0) {
+    if (listeners.Length() >= kMaxListeners) {
+      // Cannot grow the array of listeners beyond its max. Additional
+      // listeners are ignored. In practice will never happen as we will
+      // run out of memory beforehand.
+      return;
+    }
+    listeners.Add(listener);
+  } else {
+    listeners.SetAt(insertion_index, listener);
+  }
+}
+
+
+void Isolate::RemoveExitListener(const SendPort& listener) {
+  const GrowableObjectArray& listeners = GrowableObjectArray::Handle(
+      this, object_store()->exit_listeners());
+  SendPort& current = SendPort::Handle(this);
+  for (intptr_t i = 0; i < listeners.Length(); i++) {
+    current ^= listeners.At(i);
+    if (!current.IsNull() && (current.Id() == listener.Id())) {
+      // Remove the matching listener from the list.
+      current = SendPort::null();
+      listeners.SetAt(i, current);
+      return;
+    }
+  }
+}
+
+
+void Isolate::NotifyExitListeners() {
+  const GrowableObjectArray& listeners = GrowableObjectArray::Handle(
+      this, this->object_store()->exit_listeners());
+  if (listeners.IsNull()) return;
+
+  SendPort& listener = SendPort::Handle(this);
+  for (intptr_t i = 0; i < listeners.Length(); i++) {
+    listener ^= listeners.At(i);
+    if (!listener.IsNull()) {
+      Dart_Port port_id = listener.Id();
+      uint8_t* data = NULL;
+      intptr_t len = 0;
+      SerializeObject(Object::null_instance(), &data, &len, false);
+      Message* msg = new Message(port_id, data, len, Message::kNormalPriority);
+      PortMap::PostMessage(msg);
+    }
+  }
+}
+
+
+void Isolate::AddErrorListener(const SendPort& listener) {
+  // Ensure a limit for the number of listeners remembered.
+  static const intptr_t kMaxListeners = kSmiMax / (6 * kWordSize);
+
+  const GrowableObjectArray& listeners = GrowableObjectArray::Handle(
+      this, object_store()->error_listeners());
+  SendPort& current = SendPort::Handle(this);
+  intptr_t insertion_index = -1;
+  for (intptr_t i = 0; i < listeners.Length(); i++) {
+    current ^= listeners.At(i);
+    if (current.IsNull()) {
+      if (insertion_index < 0) {
+        insertion_index = i;
+      }
+    } else if (current.Id() == listener.Id()) {
+      return;
+    }
+  }
+  if (insertion_index < 0) {
+    if (listeners.Length() >= kMaxListeners) {
+      // Cannot grow the array of listeners beyond its max. Additional
+      // listeners are ignored. In practice will never happen as we will
+      // run out of memory beforehand.
+      return;
+    }
+    listeners.Add(listener);
+  } else {
+    listeners.SetAt(insertion_index, listener);
+  }
+}
+
+
+void Isolate::RemoveErrorListener(const SendPort& listener) {
+  const GrowableObjectArray& listeners = GrowableObjectArray::Handle(
+      this, object_store()->error_listeners());
+  SendPort& current = SendPort::Handle(this);
+  for (intptr_t i = 0; i < listeners.Length(); i++) {
+    current ^= listeners.At(i);
+    if (!current.IsNull() && (current.Id() == listener.Id())) {
+      // Remove the matching listener from the list.
+      current = SendPort::null();
+      listeners.SetAt(i, current);
+      return;
+    }
+  }
+}
+
+
+void Isolate::NotifyErrorListeners(const String& msg,
+                                   const String& stacktrace) {
+  const GrowableObjectArray& listeners = GrowableObjectArray::Handle(
+      this, this->object_store()->error_listeners());
+  if (listeners.IsNull()) return;
+
+  const Array& arr = Array::Handle(this, Array::New(2));
+  arr.SetAt(0, msg);
+  arr.SetAt(1, stacktrace);
+  SendPort& listener = SendPort::Handle(this);
+  for (intptr_t i = 0; i < listeners.Length(); i++) {
+    listener ^= listeners.At(i);
+    if (!listener.IsNull()) {
+      Dart_Port port_id = listener.Id();
+      uint8_t* data = NULL;
+      intptr_t len = 0;
+      SerializeObject(arr, &data, &len, false);
+      Message* msg = new Message(port_id, data, len, Message::kNormalPriority);
+      PortMap::PostMessage(msg);
+    }
+  }
+}
+
+
 static void StoreError(Isolate* isolate, const Object& obj) {
   ASSERT(obj.IsError());
   isolate->object_store()->set_sticky_error(Error::Cast(obj));
@@ -1149,6 +1367,11 @@
     StackZone stack_zone(this);
     HandleScope handle_scope(this);
 
+    // Notify exit listeners that this isolate is shutting down.
+    if (object_store() != NULL) {
+      NotifyExitListeners();
+    }
+
     // Clean up debugger resources.
     debugger()->Shutdown();
 
diff --git a/runtime/vm/isolate.h b/runtime/vm/isolate.h
index 5d61b05..5953fb2 100644
--- a/runtime/vm/isolate.h
+++ b/runtime/vm/isolate.h
@@ -74,6 +74,7 @@
 class RawInt32x4;
 class RawUserTag;
 class SampleBuffer;
+class SendPort;
 class Simulator;
 class StackResource;
 class StackZone;
@@ -410,6 +411,17 @@
   bool AddResumeCapability(const Capability& capability);
   bool RemoveResumeCapability(const Capability& capability);
 
+  void AddExitListener(const SendPort& listener);
+  void RemoveExitListener(const SendPort& listener);
+  void NotifyExitListeners();
+
+  void AddErrorListener(const SendPort& listener);
+  void RemoveErrorListener(const SendPort& listener);
+  void NotifyErrorListeners(const String& msg, const String& stacktrace);
+
+  bool ErrorsFatal() const { return errors_fatal_; }
+  void SetErrorsFatal(bool val) { errors_fatal_ = val; }
+
   Random* random() { return &random_; }
 
   Simulator* simulator() const { return simulator_; }
@@ -674,6 +686,7 @@
   Dart_Port origin_id_;  // Isolates created by spawnFunc have some origin id.
   uint64_t pause_capability_;
   uint64_t terminate_capability_;
+  bool errors_fatal_;
   Heap* heap_;
   ObjectStore* object_store_;
   uword top_exit_frame_info_;
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index 718a227..ea3c6d9 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -4911,7 +4911,8 @@
 
 
 RawTypeArguments* TypeArguments::CloneUninstantiated(
-    const Class& new_owner) const {
+    const Class& new_owner,
+    GrowableObjectArray* trail) const {
   ASSERT(!IsNull());
   ASSERT(IsFinalized());
   ASSERT(!IsInstantiated());
@@ -4922,7 +4923,7 @@
   for (intptr_t i = 0; i < num_types; i++) {
     type = TypeAt(i);
     if (!type.IsInstantiated()) {
-      type = type.CloneUninstantiated(new_owner);
+      type = type.CloneUninstantiated(new_owner, trail);
     }
     clone.SetTypeAt(i, type);
   }
@@ -14199,7 +14200,8 @@
 
 
 RawAbstractType* AbstractType::CloneUninstantiated(
-    const Class& new_owner) const {
+    const Class& new_owner,
+    GrowableObjectArray* trail) const {
   // AbstractType is an abstract class.
   UNREACHABLE();
   return NULL;
@@ -14911,16 +14913,29 @@
 }
 
 
-RawAbstractType* Type::CloneUninstantiated(const Class& new_owner) const {
+RawAbstractType* Type::CloneUninstantiated(const Class& new_owner,
+                                           GrowableObjectArray* trail) const {
   ASSERT(IsFinalized());
   ASSERT(!IsMalformed());
   if (IsInstantiated()) {
     return raw();
   }
-  TypeArguments& type_args = TypeArguments::Handle(arguments());
-  type_args = type_args.CloneUninstantiated(new_owner);
+  // We may recursively encounter a type already being cloned, because we clone
+  // the upper bounds of its uninstantiated type arguments in the same pass.
+  Type& clone = Type::Handle();
+  clone ^= OnlyBuddyInTrail(trail);
+  if (!clone.IsNull()) {
+    return clone.raw();
+  }
   const Class& type_cls = Class::Handle(type_class());
-  const Type& clone = Type::Handle(Type::New(type_cls, type_args, token_pos()));
+  clone = Type::New(type_cls, TypeArguments::Handle(), token_pos());
+  TypeArguments& type_args = TypeArguments::Handle(arguments());
+  // Upper bounds of uninstantiated type arguments may form a cycle.
+  if (type_args.IsRecursive() || !type_args.IsInstantiated()) {
+    AddOnlyBuddyToTrail(&trail, clone);
+  }
+  type_args = type_args.CloneUninstantiated(new_owner, trail);
+  clone.set_arguments(type_args);
   clone.SetIsFinalized();
   return clone.raw();
 }
@@ -15199,7 +15214,7 @@
   ASSERT(!ref_type.IsTypeRef());
   AbstractType& instantiated_ref_type = AbstractType::Handle();
   instantiated_ref_type = ref_type.InstantiateFrom(
-        instantiator_type_arguments, bound_error, trail);
+      instantiator_type_arguments, bound_error, trail);
   ASSERT(!instantiated_ref_type.IsTypeRef());
   instantiated_type_ref = TypeRef::New(instantiated_ref_type);
   AddOnlyBuddyToTrail(&trail, instantiated_type_ref);
@@ -15207,6 +15222,24 @@
 }
 
 
+RawTypeRef* TypeRef::CloneUninstantiated(const Class& new_owner,
+                                         GrowableObjectArray* trail) const {
+  TypeRef& cloned_type_ref = TypeRef::Handle();
+  cloned_type_ref ^= OnlyBuddyInTrail(trail);
+  if (!cloned_type_ref.IsNull()) {
+    return cloned_type_ref.raw();
+  }
+  AbstractType& ref_type = AbstractType::Handle(type());
+  ASSERT(!ref_type.IsTypeRef());
+  AbstractType& cloned_ref_type = AbstractType::Handle();
+  cloned_ref_type = ref_type.CloneUninstantiated(new_owner, trail);
+  ASSERT(!cloned_ref_type.IsTypeRef());
+  cloned_type_ref = TypeRef::New(cloned_ref_type);
+  AddOnlyBuddyToTrail(&trail, cloned_type_ref);
+  return cloned_type_ref.raw();
+}
+
+
 void TypeRef::set_type(const AbstractType& value) const {
   ASSERT(value.HasResolvedTypeClass());
   ASSERT(!value.IsTypeRef());
@@ -15463,10 +15496,11 @@
 
 
 RawAbstractType* TypeParameter::CloneUninstantiated(
-    const Class& new_owner) const {
+    const Class& new_owner,
+    GrowableObjectArray* trail) const {
   ASSERT(IsFinalized());
   AbstractType& upper_bound = AbstractType::Handle(bound());
-  upper_bound = upper_bound.CloneUninstantiated(new_owner);
+  upper_bound = upper_bound.CloneUninstantiated(new_owner, trail);
   const Class& old_owner = Class::Handle(parameterized_class());
   const intptr_t new_index = index() +
       new_owner.NumTypeArguments() - old_owner.NumTypeArguments();
@@ -15702,16 +15736,17 @@
 
 
 RawAbstractType* BoundedType::CloneUninstantiated(
-    const Class& new_owner) const {
+    const Class& new_owner,
+    GrowableObjectArray* trail) const {
   if (IsInstantiated()) {
     return raw();
   }
   AbstractType& bounded_type = AbstractType::Handle(type());
-  bounded_type = bounded_type.CloneUninstantiated(new_owner);
+  bounded_type = bounded_type.CloneUninstantiated(new_owner, trail);
   AbstractType& upper_bound = AbstractType::Handle(bound());
-  upper_bound = upper_bound.CloneUninstantiated(new_owner);
+  upper_bound = upper_bound.CloneUninstantiated(new_owner, trail);
   TypeParameter& type_param =  TypeParameter::Handle(type_parameter());
-  type_param ^= type_param.CloneUninstantiated(new_owner);
+  type_param ^= type_param.CloneUninstantiated(new_owner, trail);
   return BoundedType::New(bounded_type, upper_bound, type_param);
 }
 
diff --git a/runtime/vm/object.h b/runtime/vm/object.h
index b4002ce..0b0eb5e 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -1596,7 +1596,9 @@
   // Clone this type argument vector and clone all uninstantiated type
   // arguments, changing the class owner of type parameters.
   // Instantiated type arguments are shared.
-  RawTypeArguments* CloneUninstantiated(const Class& new_owner) const;
+  RawTypeArguments* CloneUninstantiated(
+      const Class& new_owner,
+      GrowableObjectArray* trail = NULL) const;
 
   // Canonicalize only if instantiated, otherwise returns 'this'.
   RawTypeArguments* Canonicalize(GrowableObjectArray* trail = NULL) const;
@@ -4891,7 +4893,9 @@
   // but belonging to the new owner class.
   // Apply recursively to type arguments, i.e. instantiated type arguments of
   // an uninstantiated type are not cloned, but shared.
-  virtual RawAbstractType* CloneUninstantiated(const Class& new_owner) const;
+  virtual RawAbstractType* CloneUninstantiated(
+      const Class& new_owner,
+      GrowableObjectArray* trail = NULL) const;
 
   virtual RawInstance* CheckAndCanonicalize(const char** error_str) const {
     return Canonicalize();
@@ -5053,7 +5057,9 @@
       Error* malformed_error,
       GrowableObjectArray* trail = NULL) const;
   virtual RawAbstractType* CloneUnfinalized() const;
-  virtual RawAbstractType* CloneUninstantiated(const Class& new_owner) const;
+  virtual RawAbstractType* CloneUninstantiated(
+      const Class& new_owner,
+      GrowableObjectArray* trail = NULL) const;
   virtual RawAbstractType* Canonicalize(
       GrowableObjectArray* trail = NULL) const;
 
@@ -5172,6 +5178,9 @@
       const TypeArguments& instantiator_type_arguments,
       Error* bound_error,
       GrowableObjectArray* trail = NULL) const;
+  virtual RawTypeRef* CloneUninstantiated(
+      const Class& new_owner,
+      GrowableObjectArray* trail = NULL) const;
   virtual RawAbstractType* Canonicalize(
       GrowableObjectArray* trail = NULL) const;
 
@@ -5253,7 +5262,9 @@
       Error* bound_error,
       GrowableObjectArray* trail = NULL) const;
   virtual RawAbstractType* CloneUnfinalized() const;
-  virtual RawAbstractType* CloneUninstantiated(const Class& new_owner) const;
+  virtual RawAbstractType* CloneUninstantiated(
+      const Class& new_owner,
+      GrowableObjectArray* trail = NULL) const;
   virtual RawAbstractType* Canonicalize(
       GrowableObjectArray* trail = NULL) const {
     return raw();
@@ -5338,7 +5349,9 @@
       Error* bound_error,
       GrowableObjectArray* trail = NULL) const;
   virtual RawAbstractType* CloneUnfinalized() const;
-  virtual RawAbstractType* CloneUninstantiated(const Class& new_owner) const;
+  virtual RawAbstractType* CloneUninstantiated(
+      const Class& new_owner,
+      GrowableObjectArray* trail = NULL) const;
   virtual RawAbstractType* Canonicalize(
       GrowableObjectArray* trail = NULL) const {
     return raw();
diff --git a/runtime/vm/object_store.cc b/runtime/vm/object_store.cc
index 985f0b5..7ba0aba 100644
--- a/runtime/vm/object_store.cc
+++ b/runtime/vm/object_store.cc
@@ -75,6 +75,8 @@
     pending_functions_(GrowableObjectArray::null()),
     pending_deferred_loads_(GrowableObjectArray::null()),
     resume_capabilities_(GrowableObjectArray::null()),
+    exit_listeners_(GrowableObjectArray::null()),
+    error_listeners_(GrowableObjectArray::null()),
     sticky_error_(Error::null()),
     empty_context_(Context::null()),
     stack_overflow_(Instance::null()),
@@ -125,6 +127,8 @@
   this->pending_deferred_loads_ = GrowableObjectArray::New();
 
   this->resume_capabilities_ = GrowableObjectArray::New();
+  this->exit_listeners_ = GrowableObjectArray::New();
+  this->error_listeners_ = GrowableObjectArray::New();
 
   Object& result = Object::Handle();
   const Library& library = Library::Handle(Library::CoreLibrary());
diff --git a/runtime/vm/object_store.h b/runtime/vm/object_store.h
index 23dad67..8d1519a 100644
--- a/runtime/vm/object_store.h
+++ b/runtime/vm/object_store.h
@@ -342,6 +342,14 @@
     return resume_capabilities_;
   }
 
+  RawGrowableObjectArray* exit_listeners() const {
+    return exit_listeners_;
+  }
+
+  RawGrowableObjectArray* error_listeners() const {
+    return error_listeners_;
+  }
+
   RawError* sticky_error() const { return sticky_error_; }
   void set_sticky_error(const Error& value) {
     ASSERT(!value.IsNull());
@@ -488,6 +496,8 @@
   RawGrowableObjectArray* pending_functions_;
   RawGrowableObjectArray* pending_deferred_loads_;
   RawGrowableObjectArray* resume_capabilities_;
+  RawGrowableObjectArray* exit_listeners_;
+  RawGrowableObjectArray* error_listeners_;
   RawError* sticky_error_;
   RawContext* empty_context_;
   RawInstance* stack_overflow_;
diff --git a/runtime/vm/parser.cc b/runtime/vm/parser.cc
index e57d0a9..f79e6d4 100644
--- a/runtime/vm/parser.cc
+++ b/runtime/vm/parser.cc
@@ -4649,6 +4649,13 @@
   to_string_func = to_string_func.Clone(cls);
   enum_members.AddFunction(to_string_func);
 
+  // Clone the hashCode getter function from the helper class.
+  Function& hash_code_func = Function::Handle(I,
+      helper_class.LookupDynamicFunctionAllowPrivate(Symbols::hashCode()));
+  ASSERT(!hash_code_func.IsNull());
+  hash_code_func = hash_code_func.Clone(cls);
+  enum_members.AddFunction(hash_code_func);
+
   cls.AddFields(enum_members.fields());
   const Array& functions =
       Array::Handle(Z, Array::MakeArray(enum_members.functions()));
@@ -5523,7 +5530,13 @@
     accessor_end_pos = TokenPos();
     ExpectToken(Token::kRBRACE);
   } else if (CurrentToken() == Token::kARROW) {
+    if (is_getter && ((func_modifier & RawFunction::kGeneratorBit) != 0)) {
+      ReportError(modifier_pos,
+                  "=> style getter may not be sync* or async* generator");
+    }
     ConsumeToken();
+    BoolScope allow_await(&this->await_is_keyword_,
+                          func_modifier != RawFunction::kNoModifier);
     SkipExpr();
     accessor_end_pos = TokenPos();
     ExpectSemicolon();
@@ -6076,11 +6089,12 @@
   TryStack* try_statement = PopTry();
   ASSERT(try_stack_ == NULL);  // We popped the outermost try block.
 
-  // Finally block: closing the stream and returning. (Note: the return
-  // is necessary otherwise the back-end will append a rethrow of the
-  // current exception.)
+  // Finally block: closing the stream and returning. Instead of simply
+  // returning, create an await state and suspend. There may be outstanding
+  // calls to schedule the generator body. This suspension ensures that we
+  // do not repeat any code of the generator body.
   // :controller.close();
-  // return;
+  // suspend;
   // We need to inline this code in all recorded exit points.
   intptr_t node_index = 0;
   SequenceNode* finally_clause = NULL;
@@ -6094,8 +6108,13 @@
             Symbols::Close(),
             no_args));
 
-    ReturnNode* return_node = new(Z) ReturnNode(Scanner::kNoSourcePos);
-    current_block_->statements->Add(return_node);
+    // Suspend after the close.
+    AwaitMarkerNode* await_marker = new(Z) AwaitMarkerNode();
+    await_marker->set_scope(current_block_->scope);
+    current_block_->statements->Add(await_marker);
+    ReturnNode* continuation_ret = new(Z) ReturnNode(try_end_pos);
+    continuation_ret->set_return_type(ReturnNode::kContinuationTarget);
+    current_block_->statements->Add(continuation_ret);
 
     finally_clause = CloseBlock();
     AstNode* node_to_inline = try_statement->GetNodeToInlineFinally(node_index);
@@ -8613,7 +8632,7 @@
     ExpectToken(Token::kRPAREN);
     return NULL;
   }
-  AstNode* condition = ParseExpr(kAllowConst, kConsumeCascades);
+  AstNode* condition = ParseAwaitableExpr(kAllowConst, kConsumeCascades, NULL);
   const intptr_t condition_end = TokenPos();
   ExpectToken(Token::kRPAREN);
   condition = InsertClosureCallNodes(condition);
@@ -10703,7 +10722,7 @@
         if (primary_node->primary().IsFunction()) {
           left = LoadClosure(primary_node);
         } else if (primary_node->primary().IsTypeParameter()) {
-          if (current_function().is_static()) {
+          if (ParsingStaticMember()) {
             const String& name = String::ZoneHandle(Z,
                 TypeParameter::Cast(primary_node->primary()).name());
             ReportError(primary_pos,
@@ -10789,7 +10808,7 @@
           ASSERT(!type.IsMalformed());
           array = new(Z) TypeNode(primary_pos, type);
         } else if (primary_node->primary().IsTypeParameter()) {
-          if (current_function().is_static()) {
+          if (ParsingStaticMember()) {
             const String& name = String::ZoneHandle(Z,
                 TypeParameter::Cast(primary_node->primary()).name());
             ReportError(primary_pos,
@@ -10857,7 +10876,7 @@
         } else if (primary_node->primary().IsTypeParameter()) {
           const String& name = String::ZoneHandle(Z,
               TypeParameter::Cast(primary_node->primary()).name());
-          if (current_function().is_static()) {
+          if (ParsingStaticMember()) {
             // Treat as this.T(), because T is in scope.
             ReportError(primary_pos,
                         "cannot access type parameter '%s' "
@@ -10903,7 +10922,7 @@
           ASSERT(!type.IsMalformed());
           left = new(Z) TypeNode(primary_pos, type);
         } else if (primary_node->primary().IsTypeParameter()) {
-          if (current_function().is_static()) {
+          if (ParsingStaticMember()) {
             const String& name = String::ZoneHandle(Z,
                 TypeParameter::Cast(primary_node->primary()).name());
             ReportError(primary_pos,
diff --git a/tests/compiler/dart2js/async_await_js_transform_test.dart b/tests/compiler/dart2js/async_await_js_transform_test.dart
index c301f6a..2483ceb 100644
--- a/tests/compiler/dart2js/async_await_js_transform_test.dart
+++ b/tests/compiler/dart2js/async_await_js_transform_test.dart
@@ -1015,4 +1015,52 @@
   }
   return thenHelper(null, __body, __completer, null);
 }""");
+  testTransform("""
+  function(l) async {
+    switch(await l) {
+      case 1:
+        print(1);
+        break;
+      case 2:
+        print(1);
+        // Fallthrough
+      default:
+        print(2);
+        break;
+    }
+  }""", """
+function(l) {
+  var __goto = 0, __completer = new Completer(), __handler = 1, __currentError;
+  function __body(__errorCode, __result) {
+    if (__errorCode === 1) {
+      __currentError = __result;
+      __goto = __handler;
+    }
+    while (true)
+      switch (__goto) {
+        case 0:
+          // Function start
+          __goto = 2;
+          return thenHelper(l, __body, __completer);
+        case 2:
+          // returning from await.
+          switch (__result) {
+            case 1:
+              print(1);
+              break;
+            case 2:
+              print(1);
+            default:
+              print(2);
+              break;
+          }
+          // implicit return
+          return thenHelper(null, 0, __completer, null);
+        case 1:
+          // rethrow
+          return thenHelper(__currentError, 1, __completer);
+      }
+  }
+  return thenHelper(null, __body, __completer, null);
+}""");
 }
diff --git a/tests/isolate/handle_error2_test.dart b/tests/isolate/handle_error2_test.dart
index 8a72a0e..8f5df26 100644
--- a/tests/isolate/handle_error2_test.dart
+++ b/tests/isolate/handle_error2_test.dart
@@ -47,7 +47,6 @@
 main(){
   asyncStart();
   RawReceivePort reply = new RawReceivePort(null);
-  RawReceivePort reply2 = new RawReceivePort(null);
   // Create two isolates waiting for commands, with errors non-fatal.
   Future iso1 = spawn(isomain1);
   Future iso2 = spawn(isomain1);
diff --git a/tests/isolate/handle_error3_test.dart b/tests/isolate/handle_error3_test.dart
index f992df0..6e76625 100644
--- a/tests/isolate/handle_error3_test.dart
+++ b/tests/isolate/handle_error3_test.dart
@@ -92,7 +92,7 @@
         case 2:
           Expect.equals(new RangeError.value(37).toString(), "$error");
           state2++;
-          reply.close();
+          reply2.close();
           isolate2.removeErrorListener(errorPort2.sendPort);
           errorPort2.close();
           asyncEnd();
diff --git a/tests/isolate/isolate.status b/tests/isolate/isolate.status
index 30a218e..bfacb76 100644
--- a/tests/isolate/isolate.status
+++ b/tests/isolate/isolate.status
@@ -11,16 +11,9 @@
 
 [ $compiler == none || $compiler == dart2dart ]
 compile_time_error_test/01: Skip # Issue 12587
-ondone_test: Fail         # Not implemented yet
 ping_test: Skip           # Resolve test issues
 ping_pause_test: Skip     # Resolve test issues
-kill_test: Fail           # Not implemented yet
-kill2_test: Fail          # Not implemented yet
-kill3_test: Fail          # Not implemented yet
-kill_self_test: Fail      # Not implemented yet
-handle_error_test: Fail   # Not implemented yet
-handle_error2_test: Fail  # Not implemented yet
-handle_error3_test: Fail  # Not implemented yet
+kill3_test: Pass, Fail    # Bad test: expects total message order
 
 message3_test/constList_identical: RuntimeError # Issue 21816
 message3_test/constMap: RuntimeError  # Issue 21816
@@ -113,6 +106,14 @@
 spawn_uri_missing_test: SkipSlow # Times out.
 isolate_current_test: Fail, OK # Issue 13921 Dom isolates don't support spawnFunction
 function_send_test: Fail, OK  # 13921 Dom isolates don't support spawnFunction
+ondone_test: Fail, OK  # 13921 Dom isolates don't support spawnFunction
+kill_test: Fail, OK  # 13921 Dom isolates don't support spawnFunction
+kill2_test: Fail, OK  # 13921 Dom isolates don't support spawnFunction
+kill3_test: Fail, OK  # 13921 Dom isolates don't support spawnFunction
+kill_self_test: Fail, OK  # 13921 Dom isolates don't support spawnFunction
+handle_error_test: Fail, OK  # 13921 Dom isolates don't support spawnFunction
+handle_error2_test: Fail, OK  # 13921 Dom isolates don't support spawnFunction
+handle_error3_test: Fail, OK  # 13921 Dom isolates don't support spawnFunction
 
 [ $compiler == dartanalyzer || $compiler == dart2analyzer ]
 browser/typed_data_message_test: StaticWarning
diff --git a/tests/isolate/message_enum_test.dart b/tests/isolate/message_enum_test.dart
new file mode 100644
index 0000000..7dbaec3
--- /dev/null
+++ b/tests/isolate/message_enum_test.dart
@@ -0,0 +1,27 @@
+// 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.
+
+// SharedOptions=--enable-enum
+
+import 'package:expect/expect.dart';
+import "dart:isolate";
+
+enum Foo { BAR, BAZ }
+
+main() {
+  var p;
+  p = new RawReceivePort((map) {
+    Expect.equals(1, map.keys.length);
+    Expect.equals(42, map.values.first);
+    var key = map.keys.first;
+    Expect.equals(42, map[key]);
+    p.close();
+  });
+  Isolate.spawn(sendIt, p.sendPort);
+}
+
+void sendIt(port) {
+  var map = { Foo.BAR: 42 };
+  port.send(map);
+}
diff --git a/tests/language/async_await_syntax_test.dart b/tests/language/async_await_syntax_test.dart
index b1affb9..2b28e47 100644
--- a/tests/language/async_await_syntax_test.dart
+++ b/tests/language/async_await_syntax_test.dart
@@ -58,6 +58,9 @@
 get sync* {}                                 /// a12b: compile-time error
 get async {}                                 /// a12c: ok
 get async* {}                                /// a12d: compile-time error
+get a12e sync* => null;                      /// a12e: compile-time error
+get a12f async* => null;                     /// a12f: compile-time error
+get a12g async => null;                      /// a12g: ok
 
 int sync;                                    /// a13a: ok
 int sync*;                                   /// a13b: compile-time error
@@ -123,6 +126,9 @@
   get sync* {}                                 /// b12b: compile-time error
   get async {}                                 /// b12c: ok
   get async* {}                                /// b12d: compile-time error
+  get b12e sync* => null;                      /// b12e: compile-time error
+  get b12f async* => null;                     /// b12f: compile-time error
+  get b12g async => null;                      /// b12g: ok
 
   int sync;                                    /// b13a: ok
   int sync*;                                   /// b13b: compile-time error
@@ -219,6 +225,9 @@
   a = sync;   /// a12b: continued
   a = async;  /// a12c: continued
   a = async;  /// a12d: continued
+  a = a12e;   /// a12e: continued
+  a = a12f;   /// a12f: continued
+  a = a12g;   /// a12g: continued
   a = sync;   /// a13a: continued
   a = sync;   /// a13b: continued
   a = async;  /// a13c: continued
@@ -258,6 +267,9 @@
   a = c.sync;   /// b12b: continued
   a = c.async;  /// b12c: continued
   a = c.async;  /// b12d: continued
+  a = c.b12e;   /// b12e: continued
+  a = c.b12f;   /// b12f: continued
+  a = c.b12g;   /// b12g: continued
   a = c.sync;   /// b13a: continued
   a = c.sync;   /// b13b: continued
   a = c.async;  /// b13c: continued
diff --git a/tests/language/async_switch_test.dart b/tests/language/async_switch_test.dart
index 5e70ad6..1e37321 100644
--- a/tests/language/async_switch_test.dart
+++ b/tests/language/async_switch_test.dart
@@ -50,6 +50,20 @@
   return k;
 }
 
+foo4(value) async {
+  int k = 0;
+  switch(await value) {
+    case 1:
+      k += 1;
+      break;
+    case 2:
+      k += 2;
+      return 2 + k;
+    default: k = 2; /// withDefault: ok
+  }
+  return k;
+}
+
 futureOf(a) async => await a;
 
 test() async {
@@ -65,6 +79,10 @@
   Expect.equals(4, await foo3(2));
   Expect.equals(2, await foo3(3)); /// withDefault: ok
   Expect.equals(0, await foo3(3)); /// none: ok
+  Expect.equals(1, await foo4(futureOf(1)));
+  Expect.equals(4, await foo4(futureOf(2)));
+  Expect.equals(2, await foo4(futureOf(3))); /// withDefault: ok
+  Expect.equals(0, await foo4(futureOf(3))); /// none: ok
 }
 
 void main() {
diff --git a/tests/language/async_throw_in_catch_test.dart b/tests/language/async_throw_in_catch_test.dart
index b3ecbab..6117a26 100644
--- a/tests/language/async_throw_in_catch_test.dart
+++ b/tests/language/async_throw_in_catch_test.dart
@@ -439,7 +439,7 @@
 }
 
 runTest(expectedTrace, fun, [expectedError]) async {
-  Tracer tracer = new Tracer(expectedTrace);
+  Tracer tracer = new Tracer(expectedTrace, expectedTrace);
   try {
     await fun(tracer);
   } catch (error) {
diff --git a/tests/language/await_postfix_expr_test.dart b/tests/language/await_postfix_expr_test.dart
new file mode 100644
index 0000000..fbec643
--- /dev/null
+++ b/tests/language/await_postfix_expr_test.dart
@@ -0,0 +1,47 @@
+// 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:async";
+import "package:expect/expect.dart";
+import "package:async_helper/async_helper.dart";
+
+
+post0(a) async {
+  return await a++;
+}
+
+post1(a) async {
+  return await a++ + await a++;
+}
+
+pref0(a) async {
+  return await ++a;
+}
+
+pref1(a) async {
+  return await ++a + await ++a;
+}
+
+sum(a) async {
+  var s = 0;
+  for (int i = 0; i < a.length; /* nothing */) {
+    s += a[await i++];
+  }
+  return s;
+}
+
+test() async {
+  Expect.equals(10, await post0(10));
+  Expect.equals(21, await post1(10));
+  Expect.equals(11, await pref0(10));
+  Expect.equals(23, await pref1(10));
+  Expect.equals(10, await sum([1, 2, 3, 4]));
+}
+
+main() {
+  asyncStart();
+  test().then((_) {
+    asyncEnd();
+  });
+}
diff --git a/tests/language/language.status b/tests/language/language.status
index 98c131d..194f526 100644
--- a/tests/language/language.status
+++ b/tests/language/language.status
@@ -43,12 +43,9 @@
 
 [ $compiler == none || ($compiler == dart2dart && $builder_tag != new_backend) ]
 async_throw_in_catch_test: Crash, RuntimeError # Issue 21404 or it could be a test error
-asyncstar_throw_in_catch_test: RuntimeError # Issue 21404
 
 [ $compiler == none && ($runtime == drt || $runtime == dartium|| $runtime == ContentShellOnAndroid) ]
 async_throw_in_catch_test: Timeout, Fail # Issue 21404 or it could be a test error
-asyncstar_throw_in_catch_test: RuntimeError # Issue 21404
-
 
 [ $compiler == none && $runtime == vm ]
 class_keyword_test/02: MissingCompileTimeError # Issue 13627
diff --git a/tests/language/language_analyzer.status b/tests/language/language_analyzer.status
index a74ffd94..cc4d7a4 100644
--- a/tests/language/language_analyzer.status
+++ b/tests/language/language_analyzer.status
@@ -63,7 +63,6 @@
 mixin_super_constructor_named_test/01: MissingCompileTimeError # Issue 19576
 mixin_super_constructor_positionals_test/01: MissingCompileTimeError # Issue 19576
 reify_typevar_static_test/00: MissingCompileTimeError # Issue 21565
-reify_typevar_static_test/01: MissingCompileTimeError # Issue 21565
 
 # Please add new failing tests before this line.
 # Section below is for invalid tests.
diff --git a/tests/language/language_analyzer2.status b/tests/language/language_analyzer2.status
index bf70695..9694935 100644
--- a/tests/language/language_analyzer2.status
+++ b/tests/language/language_analyzer2.status
@@ -25,7 +25,7 @@
 external_test/25: Fail
 constructor_duplicate_final_test/03: Fail
 reify_typevar_static_test/00: MissingCompileTimeError # Issue 21565
-reify_typevar_static_test/01: MissingCompileTimeError # Issue 21565
+regress_22700_test: Crash # Issue 22700
 
 # Please add new failing tests before this line.
 # Section below is for invalid tests.
diff --git a/tests/language/language_dart2js.status b/tests/language/language_dart2js.status
index aead0c9..122beb3 100644
--- a/tests/language/language_dart2js.status
+++ b/tests/language/language_dart2js.status
@@ -11,6 +11,8 @@
 await_for_test: Skip # Jsshell does not provide periodic timers, Issue 7728
 
 [ $compiler == dart2js || $compiler == dart2dart ]
+regress_22700_test: CompileTimeError # Issue 22700
+reify_typevar_static_test/01: CompileTimeError # Issue 22700
 symbol_literal_test/*: Fail # Issue 21825
 constructor_duplicate_final_test/01: Fail # Issue 13363
 constructor_duplicate_final_test/02: Fail # Issue 13363
@@ -53,6 +55,7 @@
 vm/*: Skip # Issue 12699
 
 [ $compiler == dart2js && $checked ]
+await_postfix_expr_test: Fail # Issue 22742
 type_variable_bounds_test/02: Fail # Issue 12702
 type_variable_bounds2_test/01: Fail # Issue 12702
 type_variable_bounds2_test/04: Fail # Issue 12702
@@ -182,7 +185,6 @@
 label_test: Skip
 
 [ $compiler == dart2dart && $builder_tag == new_backend ]
-asyncstar_throw_in_catch_test: RuntimeError # Issue 21404
 async_await_syntax_test/a03a: CompileTimeError # Issue 21404
 async_await_syntax_test/a03b: CompileTimeError # Issue 21404
 async_await_syntax_test/a11d: CompileTimeError # Issue 21404
diff --git a/tests/language/regress_22666_test.dart b/tests/language/regress_22666_test.dart
new file mode 100644
index 0000000..bd19d39
--- /dev/null
+++ b/tests/language/regress_22666_test.dart
@@ -0,0 +1,9 @@
+// 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:collection';
+
+class A extends Object with LinkedListEntry<A> { }
+
+main() => new A();
diff --git a/tests/language/regress_22700_test.dart b/tests/language/regress_22700_test.dart
new file mode 100644
index 0000000..0be42f3
--- /dev/null
+++ b/tests/language/regress_22700_test.dart
@@ -0,0 +1,30 @@
+// 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 "package:expect/expect.dart";
+
+class WrapT<T> {
+  Type get type => T;
+}
+
+printAndCheck(t) {
+  print(t);
+  Expect.equals(String, t);
+}
+
+class MyClass<T> {
+  factory MyClass.works() {
+    Type t = new WrapT<T>().type;
+    printAndCheck(t);
+  }
+
+  factory MyClass.works2() {
+    printAndCheck(T);
+  }
+}
+
+main() {
+  new MyClass<String>.works();
+  new MyClass<String>.works2();
+}
diff --git a/tests/language/regress_22719_test.dart b/tests/language/regress_22719_test.dart
new file mode 100644
index 0000000..e6cf84d
--- /dev/null
+++ b/tests/language/regress_22719_test.dart
@@ -0,0 +1,31 @@
+// 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:collection';
+import 'package:expect/expect.dart';
+
+abstract class A {
+}
+
+abstract class B extends Object with IterableMixin<int> {
+  Iterator<int> get iterator;
+}
+
+abstract class C extends A with IterableMixin<int> implements B {
+  final list = [1,2,3,4,5];
+  Iterator<int> get iterator => list.iterator;
+}
+
+class D extends C {
+}
+
+void main() {
+  var d = new D();
+  var expected = 1;
+  for(var i in d) {
+    Expect.equals(expected, i);
+    expected += 1;
+  }
+}
+
diff --git a/tests/language/regress_22728_test.dart b/tests/language/regress_22728_test.dart
new file mode 100644
index 0000000..b4f32c5
--- /dev/null
+++ b/tests/language/regress_22728_test.dart
@@ -0,0 +1,25 @@
+// 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 'package:expect/expect.dart';
+
+bool assertsChecked() {
+  bool checked = false;
+  try {
+    assert(false);
+  } on AssertionError catch (error) {
+    checked = true;
+  }
+  return checked;
+}
+
+main() async {
+  bool fault = false;
+  try {
+    assert(await false);
+  } on AssertionError catch (error) {
+    fault = true;
+  }
+  Expect.equals(assertsChecked(), fault);
+}
diff --git a/tests/language/reify_typevar_static_test.dart b/tests/language/reify_typevar_static_test.dart
index 05d9a39..ed510f0 100644
--- a/tests/language/reify_typevar_static_test.dart
+++ b/tests/language/reify_typevar_static_test.dart
@@ -12,7 +12,7 @@
     b ? T :                                /// 00: compile-time error
     null;
   factory C.factoryConstructor(bool b) => new C(
-    b ? T :                                /// 01: compile-time error
+    b ? T :                                /// 01: ok
     null);
   C.redirectingConstructor(bool b) : this(
     b ? T :                                /// 02: ok
diff --git a/tests/language/vm/regress_22693_vm_test.dart b/tests/language/vm/regress_22693_vm_test.dart
new file mode 100644
index 0000000..1cd07f9
--- /dev/null
+++ b/tests/language/vm/regress_22693_vm_test.dart
@@ -0,0 +1,13 @@
+// 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.
+// Test location summary for Uint32 multiplication.
+// VMOptions=--optimization-counter-threshold=10 --no-use-osr
+
+const MASK = 0xFFFFFFFF;
+
+uint32Mul(x, y) => (x * y) & MASK;
+
+main() {
+  for (var i = 0; i < 20; i++) uint32Mul((1 << 63) - 1, 1);
+}
diff --git a/tests/lib/mirrors/enum_test.dart b/tests/lib/mirrors/enum_test.dart
index 7b265a0..815d167 100644
--- a/tests/lib/mirrors/enum_test.dart
+++ b/tests/lib/mirrors/enum_test.dart
@@ -46,6 +46,7 @@
     'Variable(s(SPADES) in s(Suite), static, final)',
     'Variable(s(HEARTS) in s(Suite), static, final)',
     'Variable(s(values) in s(Suite), static, final)',
+    'Method(s(hashCode) in s(Suite), getter)',
     'Method(s(toString) in s(Suite))'],
    reflectClass(Suite).declarations.values
        .where((d) => !d.isPrivate).map(stringify));
diff --git a/tools/VERSION b/tools/VERSION
index 9f2b03f..fa3745a 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -28,4 +28,4 @@
 MINOR 9
 PATCH 0
 PRERELEASE 10
-PRERELEASE_PATCH 4
+PRERELEASE_PATCH 5