Version 2.0.0-dev.41.0

Merge commit 'bd6f28f4c73dce33427aa7236d939292c1e5ff5f' into dev
diff --git a/.packages b/.packages
index f306f3b..2b26bb9 100644
--- a/.packages
+++ b/.packages
@@ -17,7 +17,7 @@
 barback:third_party/pkg/barback/lib
 bazel_worker:third_party/pkg/bazel_worker/lib
 boolean_selector:third_party/pkg/boolean_selector/lib
-browser:pkg/browser/lib
+browser:third_party/pkg/browser/lib
 charcode:third_party/pkg/charcode/lib
 charted:third_party/observatory_pub_packages/packages/charted/lib
 cli_util:third_party/pkg/cli_util/lib
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 1522229..3db5bcd 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,11 +1,35 @@
+## 2.0.0-dev.41.0
+
+### Tool Changes
+
+#### Pub
+
+* Pub will now automatically retry HTTP requests that fail with an IO error
+  ([issue 1826][pub#1826]).
+
+* `pub deps` now includes the SDK version. This makes the output more helpful
+  when included in bug reports ([issue 1827][pub#1827]).
+
+* `build` and `serve` now print a deprecation warning pointing users to
+  https://webdev.dartlang.org/dart-2 ([issue 1823][pub#1823]).
+
+[pub#1823]: https://github.com/dart-lang/pub/issues/1823
+[pub#1826]: https://github.com/dart-lang/pub/issues/1826
+[pub#1827]: https://github.com/dart-lang/pub/issues/1827
+
 ## 2.0.0-dev.40.0
 
+### Core library changes
+
+* The Web libraries were re-genereated using Chrome 63 WebIDLs.
+  See https://github.com/dart-lang/sdk/wiki/Chrome-63-Dart-Web-Libraries for
+  details.
+
 ## 2.0.0-dev.39.0
 ### Tool Changes
 #### Pub
-  * fixed bug in dart2js transformer when using the common front-end.
 
-## 2.0.0-dev.38.0
+* fixed bug in dart2js transformer when using the common front-end.
 
 ## 2.0.0-dev.37.0
 ### Tool Changes
diff --git a/DEPS b/DEPS
index e30ca30..35dcf73 100644
--- a/DEPS
+++ b/DEPS
@@ -68,6 +68,7 @@
   "crypto_tag" : "@2.0.2+1",
   "csslib_tag" : "@0.14.1",
   "dart2js_info_tag" : "@0.5.5+1",
+  "browser_tag" : "@0.10.0+2",
 
   # Note: updates to dart_style have to be coordinated carefully with
   # the infrastructure-team so that the internal formatter in
@@ -99,7 +100,7 @@
   "isolate_tag": "@1.1.0",
   "jinja2_rev": "@2222b31554f03e62600cd7e383376a7c187967a1",
   "json_rpc_2_tag": "@2.0.6",
-  "linter_tag": "@0.1.44",
+  "linter_tag": "@0.1.45",
   "logging_tag": "@0.11.3+1",
   "markdown_tag": "@1.1.1",
   "matcher_tag": "@0.12.1+4",
@@ -115,7 +116,7 @@
   "ply_rev": "@604b32590ffad5cbb82e4afef1d305512d06ae93",
   "pool_tag": "@1.3.4",
   "protobuf_tag": "@0.7.1",
-  "pub_rev": "@dbe8be2bb8bca9b26ba7bd583272c62f9a0153fd",
+  "pub_rev": "@875d35005a7d33f367d70a3e31e9d3bad5d1ebd8",
   "pub_semver_tag": "@1.3.2",
   "quiver_tag": "@5aaa3f58c48608af5b027444d561270b53f15dbf",
   "resource_rev":"@af5a5bf65511943398146cf146e466e5f0b95cb9",
@@ -207,6 +208,9 @@
   Var("dart_root") + "/third_party/pkg/boolean_selector":
       Var("dart_git") + "boolean_selector.git" +
       Var("boolean_selector_tag"),
+  Var("dart_root") + "/third_party/pkg/browser":
+      Var("dart_git") + "browser.git" +
+      Var("browser_tag"),
   Var("dart_root") + "/third_party/pkg/charcode":
       Var("dart_git") + "charcode.git" + Var("charcode_tag"),
   Var("dart_root") + "/third_party/pkg/cli_util":
diff --git a/pkg/analysis_server/doc/api.html b/pkg/analysis_server/doc/api.html
index 87a23ef..2338bbe 100644
--- a/pkg/analysis_server/doc/api.html
+++ b/pkg/analysis_server/doc/api.html
@@ -3920,7 +3920,7 @@
       An enumeration of the kinds of refactorings that can be created.
     </p>
     
-  <dl><dt class="value">CONVERT_GETTER_TO_METHOD</dt><dt class="value">CONVERT_METHOD_TO_GETTER</dt><dt class="value">EXTRACT_LOCAL_VARIABLE</dt><dt class="value">EXTRACT_METHOD</dt><dt class="value">INLINE_LOCAL_VARIABLE</dt><dt class="value">INLINE_METHOD</dt><dt class="value">MOVE_FILE</dt><dt class="value">RENAME</dt><dt class="value">SORT_MEMBERS</dt></dl></dd><dt class="typeDefinition"><a name="type_RefactoringMethodParameter">RefactoringMethodParameter: object</a></dt><dd>
+  <dl><dt class="value">CONVERT_GETTER_TO_METHOD</dt><dt class="value">CONVERT_METHOD_TO_GETTER</dt><dt class="value">EXTRACT_LOCAL_VARIABLE</dt><dt class="value">EXTRACT_METHOD</dt><dt class="value">EXTRACT_WIDGET</dt><dt class="value">INLINE_LOCAL_VARIABLE</dt><dt class="value">INLINE_METHOD</dt><dt class="value">MOVE_FILE</dt><dt class="value">RENAME</dt><dt class="value">SORT_MEMBERS</dt></dl></dd><dt class="typeDefinition"><a name="type_RefactoringMethodParameter">RefactoringMethodParameter: object</a></dt><dd>
     
     <p>
       A description of a parameter in a method refactoring.
@@ -4501,6 +4501,7 @@
   
   
   
+  
 <dl><dt class="refactoring">CONVERT_GETTER_TO_METHOD</dt><dd>
     <p>
       Convert a getter into a method by removing the keyword get
@@ -4684,6 +4685,24 @@
           expression or statements used to initiate the
           refactoring will always be replaced.
         </p>
+      </dd></dl></dd><dt class="refactoring">EXTRACT_WIDGET</dt><dd>
+    <p>
+      Create a new class that extends either StatelessWidget or StatefulWidget,
+      whose build() method is the widget creation expression, or a method
+      returning a Flutter widget, at the specified offset.
+    </p>
+    
+    
+  <h4>Feedback:</h4><dl></dl><h4>Options:</h4><dl><dt class="field"><b>name: String</b></dt><dd>
+        
+        <p>
+          The name that the widget class should be given.
+        </p>
+      </dd><dt class="field"><b>stateful: bool</b></dt><dd>
+        
+        <p>
+          True if a StatefulWidget should be created.
+        </p>
       </dd></dl></dd><dt class="refactoring">INLINE_LOCAL_VARIABLE</dt><dd>
     <p>
       Inline the initializer expression of a local variable in
@@ -4818,7 +4837,7 @@
   TODO: TBD
 </p>
 <h2 class="domain"><a name="index">Index</a></h2>
-<h3>Domains</h3><h4>server (<a href="#domain_server">↑</a>)</h4><div class="subindex"><h5>Requests</h5><ul><li><a href="#request_server.getVersion">getVersion</a></li><li><a href="#request_server.shutdown">shutdown</a></li><li><a href="#request_server.setSubscriptions">setSubscriptions</a></li></ul><h5>Notifications</h5><div class="subindex"><ul><li><a href="#notification_server.connected">connected</a></li><li><a href="#notification_server.error">error</a></li><li><a href="#notification_server.status">status</a></li></ul></div></div><h4>analysis (<a href="#domain_analysis">↑</a>)</h4><div class="subindex"><h5>Requests</h5><ul><li><a href="#request_analysis.getErrors">getErrors</a></li><li><a href="#request_analysis.getHover">getHover</a></li><li><a href="#request_analysis.getLibraryDependencies">getLibraryDependencies</a></li><li><a href="#request_analysis.getNavigation">getNavigation</a></li><li><a href="#request_analysis.getReachableSources">getReachableSources</a></li><li><a href="#request_analysis.reanalyze">reanalyze</a></li><li><a href="#request_analysis.setAnalysisRoots">setAnalysisRoots</a></li><li><a href="#request_analysis.setGeneralSubscriptions">setGeneralSubscriptions</a></li><li><a href="#request_analysis.setPriorityFiles">setPriorityFiles</a></li><li><a href="#request_analysis.setSubscriptions">setSubscriptions</a></li><li><a href="#request_analysis.updateContent">updateContent</a></li><li><a href="#request_analysis.updateOptions">updateOptions</a></li></ul><h5>Notifications</h5><div class="subindex"><ul><li><a href="#notification_analysis.analyzedFiles">analyzedFiles</a></li><li><a href="#notification_analysis.closingLabels">closingLabels</a></li><li><a href="#notification_analysis.errors">errors</a></li><li><a href="#notification_analysis.flushResults">flushResults</a></li><li><a href="#notification_analysis.folding">folding</a></li><li><a href="#notification_analysis.highlights">highlights</a></li><li><a href="#notification_analysis.implemented">implemented</a></li><li><a href="#notification_analysis.invalidate">invalidate</a></li><li><a href="#notification_analysis.navigation">navigation</a></li><li><a href="#notification_analysis.occurrences">occurrences</a></li><li><a href="#notification_analysis.outline">outline</a></li><li><a href="#notification_analysis.overrides">overrides</a></li></ul></div></div><h4>completion (<a href="#domain_completion">↑</a>)</h4><div class="subindex"><h5>Requests</h5><ul><li><a href="#request_completion.getSuggestions">getSuggestions</a></li></ul><h5>Notifications</h5><div class="subindex"><ul><li><a href="#notification_completion.results">results</a></li></ul></div></div><h4>search (<a href="#domain_search">↑</a>)</h4><div class="subindex"><h5>Requests</h5><ul><li><a href="#request_search.findElementReferences">findElementReferences</a></li><li><a href="#request_search.findMemberDeclarations">findMemberDeclarations</a></li><li><a href="#request_search.findMemberReferences">findMemberReferences</a></li><li><a href="#request_search.findTopLevelDeclarations">findTopLevelDeclarations</a></li><li><a href="#request_search.getTypeHierarchy">getTypeHierarchy</a></li></ul><h5>Notifications</h5><div class="subindex"><ul><li><a href="#notification_search.results">results</a></li></ul></div></div><h4>edit (<a href="#domain_edit">↑</a>)</h4><div class="subindex"><h5>Requests</h5><ul><li><a href="#request_edit.format">format</a></li><li><a href="#request_edit.getAssists">getAssists</a></li><li><a href="#request_edit.getAvailableRefactorings">getAvailableRefactorings</a></li><li><a href="#request_edit.getFixes">getFixes</a></li><li><a href="#request_edit.getRefactoring">getRefactoring</a></li><li><a href="#request_edit.sortMembers">sortMembers</a></li><li><a href="#request_edit.organizeDirectives">organizeDirectives</a></li></ul></div><h4>execution (<a href="#domain_execution">↑</a>)</h4><div class="subindex"><h5>Requests</h5><ul><li><a href="#request_execution.createContext">createContext</a></li><li><a href="#request_execution.deleteContext">deleteContext</a></li><li><a href="#request_execution.mapUri">mapUri</a></li><li><a href="#request_execution.setSubscriptions">setSubscriptions</a></li></ul><h5>Notifications</h5><div class="subindex"><ul><li><a href="#notification_execution.launchData">launchData</a></li></ul></div></div><h4>diagnostic (<a href="#domain_diagnostic">↑</a>)</h4><div class="subindex"><h5>Requests</h5><ul><li><a href="#request_diagnostic.getDiagnostics">getDiagnostics</a></li><li><a href="#request_diagnostic.getServerPort">getServerPort</a></li></ul></div><h3>Types (<a href="#types">↑</a>)</h3><div class="subindex"><ul><li><a href="#type_AddContentOverlay">AddContentOverlay</a></li><li><a href="#type_AnalysisError">AnalysisError</a></li><li><a href="#type_AnalysisErrorFixes">AnalysisErrorFixes</a></li><li><a href="#type_AnalysisErrorSeverity">AnalysisErrorSeverity</a></li><li><a href="#type_AnalysisErrorType">AnalysisErrorType</a></li><li><a href="#type_AnalysisOptions">AnalysisOptions</a></li><li><a href="#type_AnalysisService">AnalysisService</a></li><li><a href="#type_AnalysisStatus">AnalysisStatus</a></li><li><a href="#type_ChangeContentOverlay">ChangeContentOverlay</a></li><li><a href="#type_ClosingLabel">ClosingLabel</a></li><li><a href="#type_CompletionId">CompletionId</a></li><li><a href="#type_CompletionSuggestion">CompletionSuggestion</a></li><li><a href="#type_CompletionSuggestionKind">CompletionSuggestionKind</a></li><li><a href="#type_ContextData">ContextData</a></li><li><a href="#type_Element">Element</a></li><li><a href="#type_ElementDeclaration">ElementDeclaration</a></li><li><a href="#type_ElementKind">ElementKind</a></li><li><a href="#type_ExecutableFile">ExecutableFile</a></li><li><a href="#type_ExecutableKind">ExecutableKind</a></li><li><a href="#type_ExecutionContextId">ExecutionContextId</a></li><li><a href="#type_ExecutionService">ExecutionService</a></li><li><a href="#type_FileKind">FileKind</a></li><li><a href="#type_FilePath">FilePath</a></li><li><a href="#type_FoldingKind">FoldingKind</a></li><li><a href="#type_FoldingRegion">FoldingRegion</a></li><li><a href="#type_GeneralAnalysisService">GeneralAnalysisService</a></li><li><a href="#type_HighlightRegion">HighlightRegion</a></li><li><a href="#type_HighlightRegionType">HighlightRegionType</a></li><li><a href="#type_HoverInformation">HoverInformation</a></li><li><a href="#type_ImplementedClass">ImplementedClass</a></li><li><a href="#type_ImplementedMember">ImplementedMember</a></li><li><a href="#type_ImportedElements">ImportedElements</a></li><li><a href="#type_KytheEntry">KytheEntry</a></li><li><a href="#type_KytheVName">KytheVName</a></li><li><a href="#type_LinkedEditGroup">LinkedEditGroup</a></li><li><a href="#type_LinkedEditSuggestion">LinkedEditSuggestion</a></li><li><a href="#type_LinkedEditSuggestionKind">LinkedEditSuggestionKind</a></li><li><a href="#type_Location">Location</a></li><li><a href="#type_NavigationRegion">NavigationRegion</a></li><li><a href="#type_NavigationTarget">NavigationTarget</a></li><li><a href="#type_Occurrences">Occurrences</a></li><li><a href="#type_Outline">Outline</a></li><li><a href="#type_OverriddenMember">OverriddenMember</a></li><li><a href="#type_Override">Override</a></li><li><a href="#type_Position">Position</a></li><li><a href="#type_PostfixTemplateDescriptor">PostfixTemplateDescriptor</a></li><li><a href="#type_PubStatus">PubStatus</a></li><li><a href="#type_RefactoringFeedback">RefactoringFeedback</a></li><li><a href="#type_RefactoringKind">RefactoringKind</a></li><li><a href="#type_RefactoringMethodParameter">RefactoringMethodParameter</a></li><li><a href="#type_RefactoringMethodParameterKind">RefactoringMethodParameterKind</a></li><li><a href="#type_RefactoringOptions">RefactoringOptions</a></li><li><a href="#type_RefactoringProblem">RefactoringProblem</a></li><li><a href="#type_RefactoringProblemSeverity">RefactoringProblemSeverity</a></li><li><a href="#type_RemoveContentOverlay">RemoveContentOverlay</a></li><li><a href="#type_RequestError">RequestError</a></li><li><a href="#type_RequestErrorCode">RequestErrorCode</a></li><li><a href="#type_SearchId">SearchId</a></li><li><a href="#type_SearchResult">SearchResult</a></li><li><a href="#type_SearchResultKind">SearchResultKind</a></li><li><a href="#type_ServerService">ServerService</a></li><li><a href="#type_SourceChange">SourceChange</a></li><li><a href="#type_SourceEdit">SourceEdit</a></li><li><a href="#type_SourceFileEdit">SourceFileEdit</a></li><li><a href="#type_TypeHierarchyItem">TypeHierarchyItem</a></li></ul></div><h3>Refactorings (<a href="#refactorings">↑</a>)</h3><div class="subindex"><ul><li><a href="#refactoring_CONVERT_GETTER_TO_METHOD">CONVERT_GETTER_TO_METHOD</a></li><li><a href="#refactoring_CONVERT_METHOD_TO_GETTER">CONVERT_METHOD_TO_GETTER</a></li><li><a href="#refactoring_EXTRACT_LOCAL_VARIABLE">EXTRACT_LOCAL_VARIABLE</a></li><li><a href="#refactoring_EXTRACT_METHOD">EXTRACT_METHOD</a></li><li><a href="#refactoring_INLINE_LOCAL_VARIABLE">INLINE_LOCAL_VARIABLE</a></li><li><a href="#refactoring_INLINE_METHOD">INLINE_METHOD</a></li><li><a href="#refactoring_MOVE_FILE">MOVE_FILE</a></li><li><a href="#refactoring_RENAME">RENAME</a></li></ul></div>
+<h3>Domains</h3><h4>server (<a href="#domain_server">↑</a>)</h4><div class="subindex"><h5>Requests</h5><ul><li><a href="#request_server.getVersion">getVersion</a></li><li><a href="#request_server.shutdown">shutdown</a></li><li><a href="#request_server.setSubscriptions">setSubscriptions</a></li></ul><h5>Notifications</h5><div class="subindex"><ul><li><a href="#notification_server.connected">connected</a></li><li><a href="#notification_server.error">error</a></li><li><a href="#notification_server.status">status</a></li></ul></div></div><h4>analysis (<a href="#domain_analysis">↑</a>)</h4><div class="subindex"><h5>Requests</h5><ul><li><a href="#request_analysis.getErrors">getErrors</a></li><li><a href="#request_analysis.getHover">getHover</a></li><li><a href="#request_analysis.getLibraryDependencies">getLibraryDependencies</a></li><li><a href="#request_analysis.getNavigation">getNavigation</a></li><li><a href="#request_analysis.getReachableSources">getReachableSources</a></li><li><a href="#request_analysis.reanalyze">reanalyze</a></li><li><a href="#request_analysis.setAnalysisRoots">setAnalysisRoots</a></li><li><a href="#request_analysis.setGeneralSubscriptions">setGeneralSubscriptions</a></li><li><a href="#request_analysis.setPriorityFiles">setPriorityFiles</a></li><li><a href="#request_analysis.setSubscriptions">setSubscriptions</a></li><li><a href="#request_analysis.updateContent">updateContent</a></li><li><a href="#request_analysis.updateOptions">updateOptions</a></li></ul><h5>Notifications</h5><div class="subindex"><ul><li><a href="#notification_analysis.analyzedFiles">analyzedFiles</a></li><li><a href="#notification_analysis.closingLabels">closingLabels</a></li><li><a href="#notification_analysis.errors">errors</a></li><li><a href="#notification_analysis.flushResults">flushResults</a></li><li><a href="#notification_analysis.folding">folding</a></li><li><a href="#notification_analysis.highlights">highlights</a></li><li><a href="#notification_analysis.implemented">implemented</a></li><li><a href="#notification_analysis.invalidate">invalidate</a></li><li><a href="#notification_analysis.navigation">navigation</a></li><li><a href="#notification_analysis.occurrences">occurrences</a></li><li><a href="#notification_analysis.outline">outline</a></li><li><a href="#notification_analysis.overrides">overrides</a></li></ul></div></div><h4>completion (<a href="#domain_completion">↑</a>)</h4><div class="subindex"><h5>Requests</h5><ul><li><a href="#request_completion.getSuggestions">getSuggestions</a></li></ul><h5>Notifications</h5><div class="subindex"><ul><li><a href="#notification_completion.results">results</a></li></ul></div></div><h4>search (<a href="#domain_search">↑</a>)</h4><div class="subindex"><h5>Requests</h5><ul><li><a href="#request_search.findElementReferences">findElementReferences</a></li><li><a href="#request_search.findMemberDeclarations">findMemberDeclarations</a></li><li><a href="#request_search.findMemberReferences">findMemberReferences</a></li><li><a href="#request_search.findTopLevelDeclarations">findTopLevelDeclarations</a></li><li><a href="#request_search.getTypeHierarchy">getTypeHierarchy</a></li></ul><h5>Notifications</h5><div class="subindex"><ul><li><a href="#notification_search.results">results</a></li></ul></div></div><h4>edit (<a href="#domain_edit">↑</a>)</h4><div class="subindex"><h5>Requests</h5><ul><li><a href="#request_edit.format">format</a></li><li><a href="#request_edit.getAssists">getAssists</a></li><li><a href="#request_edit.getAvailableRefactorings">getAvailableRefactorings</a></li><li><a href="#request_edit.getFixes">getFixes</a></li><li><a href="#request_edit.getRefactoring">getRefactoring</a></li><li><a href="#request_edit.sortMembers">sortMembers</a></li><li><a href="#request_edit.organizeDirectives">organizeDirectives</a></li></ul></div><h4>execution (<a href="#domain_execution">↑</a>)</h4><div class="subindex"><h5>Requests</h5><ul><li><a href="#request_execution.createContext">createContext</a></li><li><a href="#request_execution.deleteContext">deleteContext</a></li><li><a href="#request_execution.mapUri">mapUri</a></li><li><a href="#request_execution.setSubscriptions">setSubscriptions</a></li></ul><h5>Notifications</h5><div class="subindex"><ul><li><a href="#notification_execution.launchData">launchData</a></li></ul></div></div><h4>diagnostic (<a href="#domain_diagnostic">↑</a>)</h4><div class="subindex"><h5>Requests</h5><ul><li><a href="#request_diagnostic.getDiagnostics">getDiagnostics</a></li><li><a href="#request_diagnostic.getServerPort">getServerPort</a></li></ul></div><h3>Types (<a href="#types">↑</a>)</h3><div class="subindex"><ul><li><a href="#type_AddContentOverlay">AddContentOverlay</a></li><li><a href="#type_AnalysisError">AnalysisError</a></li><li><a href="#type_AnalysisErrorFixes">AnalysisErrorFixes</a></li><li><a href="#type_AnalysisErrorSeverity">AnalysisErrorSeverity</a></li><li><a href="#type_AnalysisErrorType">AnalysisErrorType</a></li><li><a href="#type_AnalysisOptions">AnalysisOptions</a></li><li><a href="#type_AnalysisService">AnalysisService</a></li><li><a href="#type_AnalysisStatus">AnalysisStatus</a></li><li><a href="#type_ChangeContentOverlay">ChangeContentOverlay</a></li><li><a href="#type_ClosingLabel">ClosingLabel</a></li><li><a href="#type_CompletionId">CompletionId</a></li><li><a href="#type_CompletionSuggestion">CompletionSuggestion</a></li><li><a href="#type_CompletionSuggestionKind">CompletionSuggestionKind</a></li><li><a href="#type_ContextData">ContextData</a></li><li><a href="#type_Element">Element</a></li><li><a href="#type_ElementDeclaration">ElementDeclaration</a></li><li><a href="#type_ElementKind">ElementKind</a></li><li><a href="#type_ExecutableFile">ExecutableFile</a></li><li><a href="#type_ExecutableKind">ExecutableKind</a></li><li><a href="#type_ExecutionContextId">ExecutionContextId</a></li><li><a href="#type_ExecutionService">ExecutionService</a></li><li><a href="#type_FileKind">FileKind</a></li><li><a href="#type_FilePath">FilePath</a></li><li><a href="#type_FoldingKind">FoldingKind</a></li><li><a href="#type_FoldingRegion">FoldingRegion</a></li><li><a href="#type_GeneralAnalysisService">GeneralAnalysisService</a></li><li><a href="#type_HighlightRegion">HighlightRegion</a></li><li><a href="#type_HighlightRegionType">HighlightRegionType</a></li><li><a href="#type_HoverInformation">HoverInformation</a></li><li><a href="#type_ImplementedClass">ImplementedClass</a></li><li><a href="#type_ImplementedMember">ImplementedMember</a></li><li><a href="#type_ImportedElements">ImportedElements</a></li><li><a href="#type_KytheEntry">KytheEntry</a></li><li><a href="#type_KytheVName">KytheVName</a></li><li><a href="#type_LinkedEditGroup">LinkedEditGroup</a></li><li><a href="#type_LinkedEditSuggestion">LinkedEditSuggestion</a></li><li><a href="#type_LinkedEditSuggestionKind">LinkedEditSuggestionKind</a></li><li><a href="#type_Location">Location</a></li><li><a href="#type_NavigationRegion">NavigationRegion</a></li><li><a href="#type_NavigationTarget">NavigationTarget</a></li><li><a href="#type_Occurrences">Occurrences</a></li><li><a href="#type_Outline">Outline</a></li><li><a href="#type_OverriddenMember">OverriddenMember</a></li><li><a href="#type_Override">Override</a></li><li><a href="#type_Position">Position</a></li><li><a href="#type_PostfixTemplateDescriptor">PostfixTemplateDescriptor</a></li><li><a href="#type_PubStatus">PubStatus</a></li><li><a href="#type_RefactoringFeedback">RefactoringFeedback</a></li><li><a href="#type_RefactoringKind">RefactoringKind</a></li><li><a href="#type_RefactoringMethodParameter">RefactoringMethodParameter</a></li><li><a href="#type_RefactoringMethodParameterKind">RefactoringMethodParameterKind</a></li><li><a href="#type_RefactoringOptions">RefactoringOptions</a></li><li><a href="#type_RefactoringProblem">RefactoringProblem</a></li><li><a href="#type_RefactoringProblemSeverity">RefactoringProblemSeverity</a></li><li><a href="#type_RemoveContentOverlay">RemoveContentOverlay</a></li><li><a href="#type_RequestError">RequestError</a></li><li><a href="#type_RequestErrorCode">RequestErrorCode</a></li><li><a href="#type_SearchId">SearchId</a></li><li><a href="#type_SearchResult">SearchResult</a></li><li><a href="#type_SearchResultKind">SearchResultKind</a></li><li><a href="#type_ServerService">ServerService</a></li><li><a href="#type_SourceChange">SourceChange</a></li><li><a href="#type_SourceEdit">SourceEdit</a></li><li><a href="#type_SourceFileEdit">SourceFileEdit</a></li><li><a href="#type_TypeHierarchyItem">TypeHierarchyItem</a></li></ul></div><h3>Refactorings (<a href="#refactorings">↑</a>)</h3><div class="subindex"><ul><li><a href="#refactoring_CONVERT_GETTER_TO_METHOD">CONVERT_GETTER_TO_METHOD</a></li><li><a href="#refactoring_CONVERT_METHOD_TO_GETTER">CONVERT_METHOD_TO_GETTER</a></li><li><a href="#refactoring_EXTRACT_LOCAL_VARIABLE">EXTRACT_LOCAL_VARIABLE</a></li><li><a href="#refactoring_EXTRACT_METHOD">EXTRACT_METHOD</a></li><li><a href="#refactoring_EXTRACT_WIDGET">EXTRACT_WIDGET</a></li><li><a href="#refactoring_INLINE_LOCAL_VARIABLE">INLINE_LOCAL_VARIABLE</a></li><li><a href="#refactoring_INLINE_METHOD">INLINE_METHOD</a></li><li><a href="#refactoring_MOVE_FILE">MOVE_FILE</a></li><li><a href="#refactoring_RENAME">RENAME</a></li></ul></div>
 
 
 </body></html>
\ No newline at end of file
diff --git a/pkg/analysis_server/lib/protocol/protocol_generated.dart b/pkg/analysis_server/lib/protocol/protocol_generated.dart
index c5873a5..3a6949a 100644
--- a/pkg/analysis_server/lib/protocol/protocol_generated.dart
+++ b/pkg/analysis_server/lib/protocol/protocol_generated.dart
@@ -10893,6 +10893,158 @@
 }
 
 /**
+ * extractWidget feedback
+ *
+ * {
+ * }
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+class ExtractWidgetFeedback extends RefactoringFeedback {
+  ExtractWidgetFeedback();
+
+  factory ExtractWidgetFeedback.fromJson(
+      JsonDecoder jsonDecoder, String jsonPath, Object json) {
+    if (json == null) {
+      json = {};
+    }
+    if (json is Map) {
+      return new ExtractWidgetFeedback();
+    } else {
+      throw jsonDecoder.mismatch(jsonPath, "extractWidget feedback", json);
+    }
+  }
+
+  @override
+  Map<String, dynamic> toJson() {
+    Map<String, dynamic> result = {};
+    return result;
+  }
+
+  @override
+  String toString() => json.encode(toJson());
+
+  @override
+  bool operator ==(other) {
+    if (other is ExtractWidgetFeedback) {
+      return true;
+    }
+    return false;
+  }
+
+  @override
+  int get hashCode {
+    int hash = 0;
+    return JenkinsSmiHash.finish(hash);
+  }
+}
+
+/**
+ * extractWidget options
+ *
+ * {
+ *   "name": String
+ *   "stateful": bool
+ * }
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+class ExtractWidgetOptions extends RefactoringOptions {
+  String _name;
+
+  bool _stateful;
+
+  /**
+   * The name that the widget class should be given.
+   */
+  String get name => _name;
+
+  /**
+   * The name that the widget class should be given.
+   */
+  void set name(String value) {
+    assert(value != null);
+    this._name = value;
+  }
+
+  /**
+   * True if a StatefulWidget should be created.
+   */
+  bool get stateful => _stateful;
+
+  /**
+   * True if a StatefulWidget should be created.
+   */
+  void set stateful(bool value) {
+    assert(value != null);
+    this._stateful = value;
+  }
+
+  ExtractWidgetOptions(String name, bool stateful) {
+    this.name = name;
+    this.stateful = stateful;
+  }
+
+  factory ExtractWidgetOptions.fromJson(
+      JsonDecoder jsonDecoder, String jsonPath, Object json) {
+    if (json == null) {
+      json = {};
+    }
+    if (json is Map) {
+      String name;
+      if (json.containsKey("name")) {
+        name = jsonDecoder.decodeString(jsonPath + ".name", json["name"]);
+      } else {
+        throw jsonDecoder.mismatch(jsonPath, "name");
+      }
+      bool stateful;
+      if (json.containsKey("stateful")) {
+        stateful =
+            jsonDecoder.decodeBool(jsonPath + ".stateful", json["stateful"]);
+      } else {
+        throw jsonDecoder.mismatch(jsonPath, "stateful");
+      }
+      return new ExtractWidgetOptions(name, stateful);
+    } else {
+      throw jsonDecoder.mismatch(jsonPath, "extractWidget options", json);
+    }
+  }
+
+  factory ExtractWidgetOptions.fromRefactoringParams(
+      EditGetRefactoringParams refactoringParams, Request request) {
+    return new ExtractWidgetOptions.fromJson(
+        new RequestDecoder(request), "options", refactoringParams.options);
+  }
+
+  @override
+  Map<String, dynamic> toJson() {
+    Map<String, dynamic> result = {};
+    result["name"] = name;
+    result["stateful"] = stateful;
+    return result;
+  }
+
+  @override
+  String toString() => json.encode(toJson());
+
+  @override
+  bool operator ==(other) {
+    if (other is ExtractWidgetOptions) {
+      return name == other.name && stateful == other.stateful;
+    }
+    return false;
+  }
+
+  @override
+  int get hashCode {
+    int hash = 0;
+    hash = JenkinsSmiHash.combine(hash, name.hashCode);
+    hash = JenkinsSmiHash.combine(hash, stateful.hashCode);
+    return JenkinsSmiHash.finish(hash);
+  }
+}
+
+/**
  * FileKind
  *
  * enum {
diff --git a/pkg/analysis_server/lib/src/context_manager.dart b/pkg/analysis_server/lib/src/context_manager.dart
index 7f56676..c827e0f 100644
--- a/pkg/analysis_server/lib/src/context_manager.dart
+++ b/pkg/analysis_server/lib/src/context_manager.dart
@@ -647,16 +647,16 @@
   /**
    * Process [options] for the given context [info].
    */
-  void processOptionsForDriver(ContextInfo info,
-      AnalysisOptionsImpl analysisOptions, Map<String, Object> options) {
+  void processOptionsForDriver(
+      ContextInfo info, AnalysisOptionsImpl analysisOptions, YamlMap options) {
     if (options == null) {
       return;
     }
 
     // Check for embedded options.
-    Map embeddedOptions = _getEmbeddedOptions(info);
+    YamlMap embeddedOptions = _getEmbeddedOptions(info);
     if (embeddedOptions != null) {
-      options = _toStringMap(new Merger().merge(embeddedOptions, options));
+      options = new Merger().merge(embeddedOptions, options);
     }
 
     applyToAnalysisOptions(analysisOptions, options);
@@ -1127,8 +1127,8 @@
     ContextInfo info = new ContextInfo(this, parent, folder, packagesFile,
         normalizedPackageRoots[folder.path], disposition);
 
-    File optionsFile = null;
-    Map<String, Object> optionMap = null;
+    File optionsFile;
+    YamlMap optionMap;
     try {
       AnalysisOptionsProvider provider =
           _createAnalysisOptionsProvider(disposition.packages);
@@ -1306,7 +1306,7 @@
   /// skipped.
   ///
   /// Returns null if there are no embedded/configured options.
-  Map _getEmbeddedOptions(ContextInfo info) {
+  YamlMap _getEmbeddedOptions(ContextInfo info) {
     Map embeddedOptions = null;
     EmbedderYamlLocator locator =
         info.disposition.getEmbedderLocator(resourceProvider);
@@ -1630,25 +1630,6 @@
     return false;
   }
 
-  /**
-   * If the given [object] is a map, and all of the keys in the map are strings,
-   * return a map containing the same mappings. Otherwise, return `null`.
-   */
-  Map<String, Object> _toStringMap(Object object) {
-    if (object is Map) {
-      Map<String, Object> stringMap = new HashMap<String, Object>();
-      for (var key in object.keys) {
-        if (key is String) {
-          stringMap[key] = object[key];
-        } else {
-          return null;
-        }
-      }
-      return stringMap;
-    }
-    return null;
-  }
-
   void _updateContextPackageUriResolver(Folder contextFolder) {
     ContextInfo info = getContextInfoFor(contextFolder);
     AnalysisDriver driver = info.analysisDriver;
diff --git a/pkg/analysis_server/lib/src/edit/edit_domain.dart b/pkg/analysis_server/lib/src/edit/edit_domain.dart
index 7e96426..3d0f6d2 100644
--- a/pkg/analysis_server/lib/src/edit/edit_domain.dart
+++ b/pkg/analysis_server/lib/src/edit/edit_domain.dart
@@ -25,6 +25,7 @@
 import 'package:analysis_server/src/services/correction/status.dart';
 import 'package:analysis_server/src/services/refactoring/refactoring.dart';
 import 'package:analysis_server/src/services/search/search_engine.dart';
+import 'package:analyzer/dart/analysis/session.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/ast/standard_resolution_map.dart';
 import 'package:analyzer/dart/element/element.dart';
@@ -207,11 +208,9 @@
   }
 
   Future getFixes(Request request) async {
-    var params = new EditGetFixesParams.fromRequest(request);
+    EditGetFixesParams params = new EditGetFixesParams.fromRequest(request);
     String file = params.file;
     int offset = params.offset;
-
-    List<AnalysisErrorFixes> errorFixesList = <AnalysisErrorFixes>[];
     //
     // Allow plugins to start computing fixes.
     //
@@ -228,29 +227,12 @@
     //
     // Compute fixes associated with server-generated errors.
     //
-    AnalysisResult result = await server.getAnalysisResult(file);
-    if (result != null) {
-      CompilationUnit unit = result.unit;
-      LineInfo lineInfo = result.lineInfo;
-      int requestLine = lineInfo.getLocation(offset).lineNumber;
-      for (engine.AnalysisError error in result.errors) {
-        int errorLine = lineInfo.getLocation(error.offset).lineNumber;
-        if (errorLine == requestLine) {
-          var context = new _DartFixContextImpl(server.resourceProvider,
-              result.driver, new AstProviderForDriver(driver), unit, error);
-          List<Fix> fixes =
-              await new DefaultFixContributor().internalComputeFixes(context);
-          if (fixes.isNotEmpty) {
-            fixes.sort(Fix.SORT_BY_RELEVANCE);
-            AnalysisError serverError =
-                newAnalysisError_fromEngine(lineInfo, error);
-            AnalysisErrorFixes errorFixes = new AnalysisErrorFixes(serverError);
-            errorFixesList.add(errorFixes);
-            fixes.forEach((fix) {
-              errorFixes.fixes.add(fix.change);
-            });
-          }
-        }
+    List<AnalysisErrorFixes> errorFixesList = null;
+    while (errorFixesList == null) {
+      try {
+        errorFixesList = await _computeServerErrorFixes(driver, file, offset);
+      } on InconsistentAnalysisException {
+        // Loop around to try again to compute the fixes.
       }
     }
     //
@@ -531,6 +513,41 @@
         new EditSortMembersResult(fileEdit).toResponse(request.id));
   }
 
+  /**
+   * Compute and return the fixes associated with server-generated errors.
+   */
+  Future<List<AnalysisErrorFixes>> _computeServerErrorFixes(
+      AnalysisDriver driver, String file, int offset) async {
+    List<AnalysisErrorFixes> errorFixesList = <AnalysisErrorFixes>[];
+    AnalysisResult result = await server.getAnalysisResult(file);
+    if (result != null) {
+      CompilationUnit unit = result.unit;
+      LineInfo lineInfo = result.lineInfo;
+      int requestLine = lineInfo.getLocation(offset).lineNumber;
+      for (engine.AnalysisError error in result.errors) {
+        int errorLine = lineInfo.getLocation(error.offset).lineNumber;
+        if (errorLine == requestLine) {
+          AstProvider astProvider = new AstProviderForDriver(driver);
+          DartFixContext context = new _DartFixContextImpl(
+              server.resourceProvider, result.driver, astProvider, unit, error);
+          List<Fix> fixes =
+              await new DefaultFixContributor().internalComputeFixes(context);
+          if (fixes.isNotEmpty) {
+            fixes.sort(Fix.SORT_BY_RELEVANCE);
+            AnalysisError serverError =
+                newAnalysisError_fromEngine(lineInfo, error);
+            AnalysisErrorFixes errorFixes = new AnalysisErrorFixes(serverError);
+            errorFixesList.add(errorFixes);
+            fixes.forEach((fix) {
+              errorFixes.fixes.add(fix.change);
+            });
+          }
+        }
+      }
+    }
+    return errorFixesList;
+  }
+
   Response _getAvailableRefactorings(Request request) {
     _getAvailableRefactoringsImpl(request);
     return Response.DELAYED_RESPONSE;
diff --git a/pkg/analysis_server/lib/src/protocol/protocol_internal.dart b/pkg/analysis_server/lib/src/protocol/protocol_internal.dart
index 19c6740..a36fc49 100644
--- a/pkg/analysis_server/lib/src/protocol/protocol_internal.dart
+++ b/pkg/analysis_server/lib/src/protocol/protocol_internal.dart
@@ -193,6 +193,9 @@
   if (kind == RefactoringKind.EXTRACT_METHOD) {
     return new ExtractMethodFeedback.fromJson(jsonDecoder, jsonPath, json);
   }
+  if (kind == RefactoringKind.EXTRACT_WIDGET) {
+    return new ExtractWidgetFeedback.fromJson(jsonDecoder, jsonPath, json);
+  }
   if (kind == RefactoringKind.INLINE_LOCAL_VARIABLE) {
     return new InlineLocalVariableFeedback.fromJson(
         jsonDecoder, jsonPath, json);
@@ -218,6 +221,9 @@
   if (kind == RefactoringKind.EXTRACT_METHOD) {
     return new ExtractMethodOptions.fromJson(jsonDecoder, jsonPath, json);
   }
+  if (kind == RefactoringKind.EXTRACT_WIDGET) {
+    return new ExtractWidgetOptions.fromJson(jsonDecoder, jsonPath, json);
+  }
   if (kind == RefactoringKind.INLINE_METHOD) {
     return new InlineMethodOptions.fromJson(jsonDecoder, jsonPath, json);
   }
diff --git a/pkg/analysis_server/lib/src/services/correction/assist_internal.dart b/pkg/analysis_server/lib/src/services/correction/assist_internal.dart
index 446edf9..15b3600 100644
--- a/pkg/analysis_server/lib/src/services/correction/assist_internal.dart
+++ b/pkg/analysis_server/lib/src/services/correction/assist_internal.dart
@@ -22,6 +22,7 @@
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/src/dart/analysis/driver.dart';
+import 'package:analyzer/src/dart/analysis/session_helper.dart';
 import 'package:analyzer/src/dart/ast/token.dart';
 import 'package:analyzer/src/dart/ast/utilities.dart';
 import 'package:analyzer/src/generated/java_core.dart';
@@ -46,6 +47,16 @@
    */
   AnalysisDriver driver;
 
+  /**
+   * The analysis session to be used to create the change builder.
+   */
+  AnalysisSession session;
+
+  /**
+   * The helper wrapper around the [session].
+   */
+  AnalysisSessionHelper sessionHelper;
+
   Source source;
   String file;
 
@@ -68,10 +79,10 @@
 
   TypeProvider _typeProvider;
 
-  final Map<String, LibraryElement> libraryCache = {};
-
   AssistProcessor(DartAssistContext dartContext) {
     driver = dartContext.analysisDriver;
+    session = driver.currentSession;
+    sessionHelper = new AnalysisSessionHelper(session);
     // source
     source = dartContext.source;
     file = dartContext.source.fullName;
@@ -95,11 +106,6 @@
    */
   String get eol => utils.endOfLine;
 
-  /**
-   * Return the analysis session to be used to create the change builder.
-   */
-  AnalysisSession get session => driver.currentSession;
-
   TypeProvider get typeProvider {
     if (_typeProvider == null) {
       _typeProvider = unitElement.context.typeProvider;
@@ -1394,10 +1400,13 @@
     }));
     buildText = SourceEdit.applySequence(buildText, buildTextEdits.reversed);
 
-    var statefulWidgetClass =
-        await _getExportedClass(flutter.WIDGETS_LIBRARY_URI, 'StatefulWidget');
+    var statefulWidgetClass = await sessionHelper.getClass(
+        flutter.WIDGETS_LIBRARY_URI, 'StatefulWidget');
     var stateClass =
-        await _getExportedClass(flutter.WIDGETS_LIBRARY_URI, 'State');
+        await sessionHelper.getClass(flutter.WIDGETS_LIBRARY_URI, 'State');
+    if (statefulWidgetClass == null || stateClass == null) {
+      return;
+    }
     var stateType = stateClass.type.instantiate([widgetClassElement.type]);
 
     DartChangeBuilder changeBuilder = new DartChangeBuilder(session);
@@ -1658,7 +1667,10 @@
     ClassElement parentClassElement;
     if (parentLibraryUri != null && parentClassName != null) {
       parentClassElement =
-          await _getExportedClass(parentLibraryUri, parentClassName);
+          await sessionHelper.getClass(parentLibraryUri, parentClassName);
+      if (parentClassElement == null) {
+        return;
+      }
     }
 
     DartChangeBuilder changeBuilder = new DartChangeBuilder(session);
@@ -1735,9 +1747,12 @@
         @required String parentLibraryUri,
         @required String parentClassName}) async {
       ClassElement parentClassElement =
-          await _getExportedClass(parentLibraryUri, parentClassName);
+          await sessionHelper.getClass(parentLibraryUri, parentClassName);
       ClassElement widgetClassElement =
-          await _getExportedClass(flutter.WIDGETS_LIBRARY_URI, 'Widget');
+          await sessionHelper.getClass(flutter.WIDGETS_LIBRARY_URI, 'Widget');
+      if (parentClassElement == null || widgetClassElement == null) {
+        return;
+      }
 
       DartChangeBuilder changeBuilder = new DartChangeBuilder(session);
       await changeBuilder.addFileEdit(file, (DartFileEditBuilder builder) {
@@ -2968,20 +2983,6 @@
     }
   }
 
-  /// Return the [ClassElement] with the given [className] that is exported
-  /// from the library with the given [libraryUri], or `null` if the libary
-  /// does not export a class with such name.
-  Future<ClassElement> _getExportedClass(
-      String libraryUri, String className) async {
-    var libraryElement = await session.getLibraryByUri(libraryUri);
-    var element = libraryElement.exportNamespace.get(className);
-    if (element is ClassElement) {
-      return element;
-    } else {
-      return null;
-    }
-  }
-
   /**
    * Returns the text of the given node in the unit.
    */
diff --git a/pkg/analysis_server/lib/src/services/correction/fix_internal.dart b/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
index 7c28a08..bb4a3b3 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
@@ -514,16 +514,36 @@
     } else if (parent is VariableDeclaration && target == parent.initializer) {
       toType = parent.name.staticType;
     } else {
+      // TODO(brianwilkerson) Handle function arguments.
       return;
     }
-    // TODO(brianwilkerson) I think it's more efficient to invoke `cast` before
-    // invoking `toList()`, so check to see whether the cast should be inserted
-    // before the end of the expression.
-    // TODO(brianwilkerson) We should not produce a fix if the target is an
-    // invocation of the `cast` method.
+    // TODO(brianwilkerson) Handle `toSet` in a manner similar to the below.
+    if (_isToListMethodInvocation(target)) {
+      Expression targetTarget = (target as MethodInvocation).target;
+      if (targetTarget != null) {
+        DartType targetTargetType = targetTarget.staticType;
+        if (_isDartCoreIterable(targetTargetType) ||
+            _isDartCoreList(targetTargetType) ||
+            _isDartCoreMap(targetTargetType) ||
+            _isDartCoreSet(targetTargetType)) {
+          target = targetTarget;
+          fromType = targetTargetType;
+        }
+      }
+    }
+    if (target is AsExpression) {
+      // TODO(brianwilkerson) Consider updating the right operand.
+      return;
+    }
     bool needsParentheses = target.precedence < 15;
-    if ((_isDartCoreList(fromType) && _isDartCoreList(toType)) ||
+    if (((_isDartCoreIterable(fromType) || _isDartCoreList(fromType)) &&
+            _isDartCoreList(toType)) ||
         (_isDartCoreSet(fromType) && _isDartCoreSet(toType))) {
+      if (_isCastMethodInvocation(target)) {
+        // TODO(brianwilkerson) Consider updating the type arguments to the
+        // `cast` invocation.
+        return;
+      }
       DartChangeBuilder changeBuilder = new DartChangeBuilder(session);
       await changeBuilder.addFileEdit(file, (DartFileEditBuilder builder) {
         if (needsParentheses) {
@@ -540,6 +560,11 @@
       });
       _addFixFromBuilder(changeBuilder, DartFixKind.ADD_EXPLICIT_CAST);
     } else if (_isDartCoreMap(fromType) && _isDartCoreMap(toType)) {
+      if (_isCastMethodInvocation(target)) {
+        // TODO(brianwilkerson) Consider updating the type arguments to the
+        // `cast` invocation.
+        return;
+      }
       DartChangeBuilder changeBuilder = new DartChangeBuilder(session);
       await changeBuilder.addFileEdit(file, (DartFileEditBuilder builder) {
         if (needsParentheses) {
@@ -3428,38 +3453,50 @@
     return node is SimpleIdentifier && node.name == 'await';
   }
 
-  bool _isDartCoreList(DartType type) {
-    if (type is! InterfaceType) {
+  bool _isCastMethodElement(MethodElement method) {
+    if (method.name != 'cast') {
       return false;
     }
-    ClassElement element = type.element;
-    if (element == null) {
-      return false;
-    }
-    return element.name == "List" && element.library.isDartCore;
+    ClassElement definingClass = method.enclosingElement;
+    return _isDartCoreIterableElement(definingClass) ||
+        _isDartCoreListElement(definingClass) ||
+        _isDartCoreMapElement(definingClass) ||
+        _isDartCoreSetElement(definingClass);
   }
 
-  bool _isDartCoreMap(DartType type) {
-    if (type is! InterfaceType) {
-      return false;
+  bool _isCastMethodInvocation(Expression expression) {
+    if (expression is MethodInvocation) {
+      Element element = expression.methodName.staticElement;
+      return element is MethodElement && _isCastMethodElement(element);
     }
-    ClassElement element = type.element;
-    if (element == null) {
-      return false;
-    }
-    return element.name == "Map" && element.library.isDartCore;
+    return false;
   }
 
-  bool _isDartCoreSet(DartType type) {
-    if (type is! InterfaceType) {
-      return false;
-    }
-    ClassElement element = type.element;
-    if (element == null) {
-      return false;
-    }
-    return element.name == "Set" && element.library.isDartCore;
-  }
+  bool _isDartCoreIterable(DartType type) =>
+      type is InterfaceType && _isDartCoreIterableElement(type.element);
+
+  bool _isDartCoreIterableElement(ClassElement element) =>
+      element != null &&
+      element.name == "Iterable" &&
+      element.library.isDartCore;
+
+  bool _isDartCoreList(DartType type) =>
+      type is InterfaceType && _isDartCoreListElement(type.element);
+
+  bool _isDartCoreListElement(ClassElement element) =>
+      element != null && element.name == "List" && element.library.isDartCore;
+
+  bool _isDartCoreMap(DartType type) =>
+      type is InterfaceType && _isDartCoreMapElement(type.element);
+
+  bool _isDartCoreMapElement(ClassElement element) =>
+      element != null && element.name == "Map" && element.library.isDartCore;
+
+  bool _isDartCoreSet(DartType type) =>
+      type is InterfaceType && _isDartCoreSetElement(type.element);
+
+  bool _isDartCoreSetElement(ClassElement element) =>
+      element != null && element.name == "Set" && element.library.isDartCore;
 
   bool _isLibSrcPath(String path) {
     List<String> parts = resourceProvider.pathContext.split(path);
@@ -3495,6 +3532,23 @@
     return true;
   }
 
+  bool _isToListMethodElement(MethodElement method) {
+    if (method.name != 'toList') {
+      return false;
+    }
+    ClassElement definingClass = method.enclosingElement;
+    return _isDartCoreIterableElement(definingClass) ||
+        _isDartCoreListElement(definingClass);
+  }
+
+  bool _isToListMethodInvocation(Expression expression) {
+    if (expression is MethodInvocation) {
+      Element element = expression.methodName.staticElement;
+      return element is MethodElement && _isToListMethodElement(element);
+    }
+    return false;
+  }
+
   /**
    * Removes any [ParenthesizedExpression] enclosing [expr].
    *
diff --git a/pkg/analysis_server/lib/src/services/refactoring/extract_widget.dart b/pkg/analysis_server/lib/src/services/refactoring/extract_widget.dart
new file mode 100644
index 0000000..fae6127
--- /dev/null
+++ b/pkg/analysis_server/lib/src/services/refactoring/extract_widget.dart
@@ -0,0 +1,426 @@
+// Copyright (c) 2018, 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:analysis_server/src/protocol_server.dart' hide Element;
+import 'package:analysis_server/src/services/correction/status.dart';
+import 'package:analysis_server/src/services/correction/util.dart';
+import 'package:analysis_server/src/services/refactoring/naming_conventions.dart';
+import 'package:analysis_server/src/services/refactoring/refactoring.dart';
+import 'package:analysis_server/src/services/refactoring/refactoring_internal.dart';
+import 'package:analysis_server/src/services/search/search_engine.dart';
+import 'package:analysis_server/src/utilities/flutter.dart';
+import 'package:analyzer/analyzer.dart';
+import 'package:analyzer/dart/analysis/session.dart';
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/dart/element/type.dart';
+import 'package:analyzer/src/dart/analysis/session_helper.dart';
+import 'package:analyzer/src/generated/source.dart' show SourceRange;
+import 'package:analyzer_plugin/utilities/change_builder/change_builder_dart.dart';
+import 'package:analyzer_plugin/utilities/range_factory.dart';
+
+/// [ExtractWidgetRefactoring] implementation.
+class ExtractWidgetRefactoringImpl extends RefactoringImpl
+    implements ExtractWidgetRefactoring {
+  final SearchEngine searchEngine;
+  final AnalysisSessionHelper sessionHelper;
+  final CompilationUnit unit;
+  final int offset;
+
+  CompilationUnitElement unitElement;
+  LibraryElement libraryElement;
+  CorrectionUtils utils;
+
+  ClassElement classBuildContext;
+  ClassElement classStatefulWidget;
+  ClassElement classStatelessWidget;
+  ClassElement classWidget;
+
+  @override
+  String name;
+
+  @override
+  bool stateful = false;
+
+  /// If [offset] is in a class, the node of this class, `null` otherwise.
+  ClassDeclaration _enclosingClassNode;
+
+  /// If [offset] is in a class, the element of this class, `null` otherwise.
+  ClassElement _enclosingClassElement;
+
+  /// The [CompilationUnitMember] that encloses the [offset].
+  CompilationUnitMember _enclosingUnitMember;
+
+  /// The widget creation expression to extract.
+  InstanceCreationExpression _expression;
+
+  /// The method returning widget to extract.
+  MethodDeclaration _method;
+
+  /// The parameters for the new widget class - referenced fields of the
+  /// [_enclosingClassElement], local variables referenced by [_expression],
+  /// and [_method] parameters.
+  List<_Parameter> _parameters = [];
+
+  ExtractWidgetRefactoringImpl(
+      this.searchEngine, AnalysisSession session, this.unit, this.offset)
+      : sessionHelper = new AnalysisSessionHelper(session) {
+    unitElement = unit.element;
+    libraryElement = unitElement.library;
+    utils = new CorrectionUtils(unit);
+  }
+
+  @override
+  String get refactoringName {
+    return 'Extract Widget';
+  }
+
+  @override
+  Future<RefactoringStatus> checkFinalConditions() async {
+    RefactoringStatus result = new RefactoringStatus();
+    result.addStatus(validateClassName(name));
+    return result;
+  }
+
+  @override
+  Future<RefactoringStatus> checkInitialConditions() async {
+    RefactoringStatus result = new RefactoringStatus();
+
+    result.addStatus(_checkSelection());
+    if (result.hasFatalError) {
+      return result;
+    }
+
+    _enclosingUnitMember = (_expression ?? _method).getAncestor(
+        (n) => n is CompilationUnitMember && n.parent is CompilationUnit);
+
+    result.addStatus(await _initializeParameters());
+    result.addStatus(await _initializeClasses());
+
+    return result;
+  }
+
+  @override
+  RefactoringStatus checkName() {
+    return validateClassName(name);
+  }
+
+  @override
+  Future<SourceChange> createChange() async {
+    String file = unitElement.source.fullName;
+    var changeBuilder = new DartChangeBuilder(sessionHelper.session);
+    await changeBuilder.addFileEdit(file, (builder) {
+      if (_expression != null) {
+        builder.addReplacement(range.node(_expression), (builder) {
+          _writeWidgetInstantiation(builder);
+        });
+      } else {
+        _removeMethodDeclaration(builder);
+        _replaceInvocationsWithInstantiations(builder);
+      }
+
+      _writeWidgetDeclaration(builder);
+    });
+    return changeBuilder.sourceChange;
+  }
+
+  @override
+  bool requiresPreview() => false;
+
+  /// Checks if [offset] is a widget creation expression that can be extracted.
+  RefactoringStatus _checkSelection() {
+    AstNode node = new NodeLocator2(offset, offset).searchWithin(unit);
+
+    // Find the enclosing class.
+    _enclosingClassNode = node?.getAncestor((n) => n is ClassDeclaration);
+    _enclosingClassElement = _enclosingClassNode?.element;
+
+    // new MyWidget(...)
+    if (node is InstanceCreationExpression && isWidgetCreation(node)) {
+      _expression = node;
+      return new RefactoringStatus();
+    }
+
+    // Widget myMethod(...) { ... }
+    for (; node != null; node = node.parent) {
+      if (node is FunctionBody) {
+        break;
+      }
+      if (node is MethodDeclaration) {
+        DartType returnType = node.returnType?.type;
+        if (isWidgetType(returnType) && node.body != null) {
+          _method = node;
+          return new RefactoringStatus();
+        }
+        break;
+      }
+    }
+
+    // Invalid selection.
+    return new RefactoringStatus.fatal(
+        'Can only extract a widget expression or a method returning widget.');
+  }
+
+  Future<RefactoringStatus> _initializeClasses() async {
+    var result = new RefactoringStatus();
+
+    Future<ClassElement> getClass(String name) async {
+      const uri = 'package:flutter/widgets.dart';
+      var element = await sessionHelper.getClass(uri, name);
+      if (element == null) {
+        result.addFatalError("Unable to find '$name' in $uri");
+      }
+      return element;
+    }
+
+    classBuildContext = await getClass('BuildContext');
+    classStatelessWidget = await getClass('StatelessWidget');
+    classStatefulWidget = await getClass('StatefulWidget');
+    classWidget = await getClass('Widget');
+
+    return result;
+  }
+
+  /// Prepare referenced local variables and fields, that should be turned
+  /// into the widget class fields and constructor parameters.
+  Future<RefactoringStatus> _initializeParameters() async {
+    _ParametersCollector collector;
+    if (_expression != null) {
+      SourceRange localRange = range.node(_expression);
+      collector = new _ParametersCollector(_enclosingClassElement, localRange);
+      _expression.accept(collector);
+    }
+    if (_method != null) {
+      SourceRange localRange = range.node(_method);
+      collector = new _ParametersCollector(_enclosingClassElement, localRange);
+      _method.body.accept(collector);
+    }
+
+    _parameters
+      ..clear()
+      ..addAll(collector.parameters);
+
+    // We added fields, now add the method parameters.
+    if (_method != null) {
+      for (var parameter in _method.parameters.parameters) {
+        if (parameter is NormalFormalParameter) {
+          _parameters.add(new _Parameter(
+              parameter.identifier.name, parameter.element.type,
+              isMethodParameter: true));
+        }
+      }
+    }
+
+    return collector.status;
+  }
+
+  /// Remove the [_method] declaration.
+  void _removeMethodDeclaration(DartFileEditBuilder builder) {
+    SourceRange methodRange = range.node(_method);
+    SourceRange linesRange =
+        utils.getLinesRange(methodRange, skipLeadingEmptyLines: true);
+    builder.addDeletion(linesRange);
+  }
+
+  /// Replace invocations of the [_method] with instantiations of the new
+  /// widget class.
+  void _replaceInvocationsWithInstantiations(DartFileEditBuilder builder) {
+    var collector = new _MethodInvocationsCollector(_method.element);
+    _enclosingClassNode.accept(collector);
+    for (var invocation in collector.invocations) {
+      builder.addReplacement(
+        range.startEnd(invocation, invocation.argumentList.leftParenthesis),
+        (builder) {
+          builder.write('new $name(');
+
+          // Insert field references.
+          for (var parameter in _parameters) {
+            if (parameter.isMethodParameter) {
+              break;
+            }
+            if (parameter != _parameters.first) {
+              builder.write(', ');
+            }
+            builder.write(parameter.name);
+          }
+
+          // Separate references to fields and method arguments.
+          if (_parameters.isNotEmpty &&
+              invocation.argumentList.arguments.isNotEmpty) {
+            builder.write(', ');
+          }
+        },
+      );
+    }
+  }
+
+  /// Write declaration of the new widget class.
+  void _writeWidgetDeclaration(DartFileEditBuilder builder) {
+    builder.addInsertion(_enclosingUnitMember.end, (builder) {
+      builder.writeln();
+      builder.writeln();
+      builder.writeClassDeclaration(
+        name,
+        superclass: classStatelessWidget.type,
+        membersWriter: () {
+          if (_parameters.isNotEmpty) {
+            // Add the fields for the parameters.
+            for (var parameter in _parameters) {
+              builder.write('  ');
+              builder.writeFieldDeclaration(parameter.name,
+                  isFinal: true, type: parameter.type);
+              builder.writeln();
+            }
+            builder.writeln();
+
+            // Add the constructor.
+            builder.write('  ');
+            builder.writeConstructorDeclaration(name,
+                fieldNames: _parameters.map((e) => e.name).toList());
+            builder.writeln();
+            builder.writeln();
+          }
+
+          // Widget build(BuildContext context) { ... }
+          builder.writeln('  @override');
+          builder.write('  ');
+          builder.writeFunctionDeclaration(
+            'build',
+            returnType: classWidget.type,
+            parameterWriter: () {
+              builder.writeParameter('context', type: classBuildContext.type);
+            },
+            bodyWriter: () {
+              if (_expression != null) {
+                String indentOld = utils.getLinePrefix(_expression.offset);
+                String indentNew = '    ';
+
+                String code = utils.getNodeText(_expression);
+                code = code.replaceAll(
+                    new RegExp('^$indentOld', multiLine: true), indentNew);
+
+                builder.writeln('{');
+
+                builder.write('    return ');
+                builder.write(code);
+                builder.writeln(';');
+
+                builder.writeln('  }');
+              } else {
+                String code = utils.getNodeText(_method.body);
+                builder.writeln(code);
+              }
+            },
+          );
+        },
+      );
+    });
+  }
+
+  /// Write instantiation of the new widget class.
+  void _writeWidgetInstantiation(DartEditBuilder builder) {
+    builder.write('new $name(');
+
+    for (var parameter in _parameters) {
+      if (parameter != _parameters.first) {
+        builder.write(', ');
+      }
+      builder.write(parameter.name);
+    }
+
+    builder.write(')');
+  }
+}
+
+class _MethodInvocationsCollector extends RecursiveAstVisitor<void> {
+  final MethodElement methodElement;
+  final List<MethodInvocation> invocations = [];
+
+  _MethodInvocationsCollector(this.methodElement);
+
+  @override
+  void visitMethodInvocation(MethodInvocation node) {
+    if (node.methodName?.staticElement == methodElement) {
+      invocations.add(node);
+    } else {
+      super.visitMethodInvocation(node);
+    }
+  }
+}
+
+class _Parameter {
+  final String name;
+  final DartType type;
+
+  /// Whether the parameter is a parameter of the method being extracted.
+  final bool isMethodParameter;
+
+  _Parameter(this.name, this.type, {this.isMethodParameter = false});
+}
+
+class _ParametersCollector extends RecursiveAstVisitor<void> {
+  final ClassElement enclosingClass;
+  final SourceRange expressionRange;
+
+  final RefactoringStatus status = new RefactoringStatus();
+  final List<_Parameter> parameters = [];
+
+  List<ClassElement> enclosingClasses;
+
+  _ParametersCollector(this.enclosingClass, this.expressionRange);
+
+  @override
+  void visitSimpleIdentifier(SimpleIdentifier node) {
+    Element element = node.staticElement;
+    if (element == null) {
+      return;
+    }
+    String elementName = element.displayName;
+
+    DartType type;
+    if (element is MethodElement) {
+      if (_isMemberOfEnclosingClass(element)) {
+        status.addError(
+            "Reference to an enclosing class method cannot be extracted.");
+      }
+    } else if (element is LocalVariableElement) {
+      if (!expressionRange.contains(element.nameOffset)) {
+        if (node.inSetterContext()) {
+          status.addError("Write to '$elementName' cannot be extracted.");
+        } else {
+          type = element.type;
+        }
+      }
+    } else if (element is PropertyAccessorElement) {
+      PropertyInducingElement field = element.variable;
+      if (_isMemberOfEnclosingClass(field)) {
+        if (node.inSetterContext()) {
+          status.addError("Write to '$elementName' cannot be extracted.");
+        } else {
+          type = field.type;
+        }
+      }
+    }
+
+    if (type != null) {
+      parameters.add(new _Parameter(elementName, type));
+    }
+  }
+
+  /// Return `true` if the given [element] is a member of the [enclosingClass]
+  /// or one of its supertypes, interfaces, or mixins.
+  bool _isMemberOfEnclosingClass(Element element) {
+    if (enclosingClass != null) {
+      if (enclosingClasses == null) {
+        enclosingClasses = <ClassElement>[]
+          ..add(enclosingClass)
+          ..addAll(enclosingClass.allSupertypes.map((t) => t.element));
+      }
+      return enclosingClasses.contains(element.enclosingElement);
+    }
+    return false;
+  }
+}
diff --git a/pkg/analysis_server/lib/src/services/refactoring/refactoring.dart b/pkg/analysis_server/lib/src/services/refactoring/refactoring.dart
index 1e51c6f..e336845 100644
--- a/pkg/analysis_server/lib/src/services/refactoring/refactoring.dart
+++ b/pkg/analysis_server/lib/src/services/refactoring/refactoring.dart
@@ -9,6 +9,7 @@
 import 'package:analysis_server/src/services/refactoring/convert_method_to_getter.dart';
 import 'package:analysis_server/src/services/refactoring/extract_local.dart';
 import 'package:analysis_server/src/services/refactoring/extract_method.dart';
+import 'package:analysis_server/src/services/refactoring/extract_widget.dart';
 import 'package:analysis_server/src/services/refactoring/inline_local.dart';
 import 'package:analysis_server/src/services/refactoring/inline_method.dart';
 import 'package:analysis_server/src/services/refactoring/rename_class_member.dart';
@@ -19,6 +20,7 @@
 import 'package:analysis_server/src/services/refactoring/rename_local.dart';
 import 'package:analysis_server/src/services/refactoring/rename_unit_member.dart';
 import 'package:analysis_server/src/services/search/search_engine.dart';
+import 'package:analyzer/dart/analysis/session.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/src/dart/element/ast_provider.dart';
@@ -220,6 +222,43 @@
 }
 
 /**
+ * [Refactoring] to extract a widget creation expression or a method returning
+ * a widget, into a new stateless or stateful widget.
+ */
+abstract class ExtractWidgetRefactoring implements Refactoring {
+  /**
+   * Returns a new [ExtractWidgetRefactoring] instance.
+   */
+  factory ExtractWidgetRefactoring(SearchEngine searchEngine,
+      AnalysisSession session, CompilationUnit unit, int offset) {
+    return new ExtractWidgetRefactoringImpl(
+        searchEngine, session, unit, offset);
+  }
+
+  /**
+   * The name that the class should be given.
+   */
+  void set name(String name);
+
+  /**
+   * Set to `true` if a subclass of `StatefulWidget` should be extracted,
+   * otherwise a subclass of `StatelessWidget` will be extracted.
+   */
+  void set stateful(bool stateful);
+
+  /**
+   * Validates that the [name] is a valid identifier and is appropriate for a
+   * class.
+   *
+   * It does not perform all the checks (such as checking for conflicts with any
+   * existing names in any of the scopes containing the current name), as many
+   * of these checks require search engine. Use [checkFinalConditions] for this
+   * level of checking.
+   */
+  RefactoringStatus checkName();
+}
+
+/**
  * [Refactoring] to inline a local [VariableElement].
  */
 abstract class InlineLocalRefactoring implements Refactoring {
diff --git a/pkg/analysis_server/test/context_manager_test.dart b/pkg/analysis_server/test/context_manager_test.dart
index b9727e8..f97f086 100644
--- a/pkg/analysis_server/test/context_manager_test.dart
+++ b/pkg/analysis_server/test/context_manager_test.dart
@@ -1816,6 +1816,12 @@
 @reflectiveTest
 class ContextManagerWithNewOptionsTest extends ContextManagerWithOptionsTest {
   String get optionsFileName => AnalysisEngine.ANALYSIS_OPTIONS_YAML_FILE;
+
+  @failingTest
+  test_analysis_options_parse_failure() async {
+    // We have lost the ability to detect errors of this form.
+    return super.test_analysis_options_parse_failure();
+  }
 }
 
 @reflectiveTest
@@ -2172,6 +2178,27 @@
     expect(errorProcessors, isEmpty);
   }
 
+  test_non_analyzable_files_not_considered() async {
+    // Set up project and get a reference to the driver.
+    manager.setRoots(<String>[projPath], <String>[], <String, String>{});
+    Folder projectFolder = resourceProvider.newFolder(projPath);
+    var drivers = manager.getDriversInAnalysisRoot(projectFolder);
+    expect(drivers, hasLength(1));
+
+    // Add the driver to the manager so that it will receive the events.
+    manager.driverMap[projectFolder] = drivers[0];
+
+    // Ensure adding a file that shouldn't be analyzed is not picked up.
+    newFile('$projPath/test.txt');
+    await pumpEventQueue();
+    expect(drivers[0].hasFilesToAnalyze, false);
+
+    // Ensure modifying a file that shouldn't be analyzed is not picked up.
+    modifyFile('$projPath/test.txt', 'new content');
+    await pumpEventQueue();
+    expect(drivers[0].hasFilesToAnalyze, false);
+  }
+
   @failingTest
   test_optionsFile_update_strongMode() async {
     // It appears that this fails because we are not correctly updating the
@@ -2432,27 +2459,6 @@
     await new Future.delayed(new Duration(milliseconds: 1));
     expect(callbacks.watchEvents, hasLength(1));
   }
-
-  test_non_analyzable_files_not_considered() async {
-    // Set up project and get a reference to the driver.
-    manager.setRoots(<String>[projPath], <String>[], <String, String>{});
-    Folder projectFolder = resourceProvider.newFolder(projPath);
-    var drivers = manager.getDriversInAnalysisRoot(projectFolder);
-    expect(drivers, hasLength(1));
-
-    // Add the driver to the manager so that it will receive the events.
-    manager.driverMap[projectFolder] = drivers[0];
-
-    // Ensure adding a file that shouldn't be analyzed is not picked up.
-    newFile('$projPath/test.txt');
-    await pumpEventQueue();
-    expect(drivers[0].hasFilesToAnalyze, false);
-
-    // Ensure modifying a file that shouldn't be analyzed is not picked up.
-    modifyFile('$projPath/test.txt', 'new content');
-    await pumpEventQueue();
-    expect(drivers[0].hasFilesToAnalyze, false);
-  }
 }
 
 class TestContextManagerCallbacks extends ContextManagerCallbacks {
diff --git a/pkg/analysis_server/test/integration/support/protocol_matchers.dart b/pkg/analysis_server/test/integration/support/protocol_matchers.dart
index ae078f3..42db016 100644
--- a/pkg/analysis_server/test/integration/support/protocol_matchers.dart
+++ b/pkg/analysis_server/test/integration/support/protocol_matchers.dart
@@ -1098,6 +1098,7 @@
  *   CONVERT_METHOD_TO_GETTER
  *   EXTRACT_LOCAL_VARIABLE
  *   EXTRACT_METHOD
+ *   EXTRACT_WIDGET
  *   INLINE_LOCAL_VARIABLE
  *   INLINE_METHOD
  *   MOVE_FILE
@@ -1110,6 +1111,7 @@
   "CONVERT_METHOD_TO_GETTER",
   "EXTRACT_LOCAL_VARIABLE",
   "EXTRACT_METHOD",
+  "EXTRACT_WIDGET",
   "INLINE_LOCAL_VARIABLE",
   "INLINE_METHOD",
   "MOVE_FILE",
@@ -2463,6 +2465,27 @@
         }));
 
 /**
+ * extractWidget feedback
+ *
+ * {
+ * }
+ */
+final Matcher isExtractWidgetFeedback = new LazyMatcher(
+    () => new MatchesJsonObject("extractWidget feedback", null));
+
+/**
+ * extractWidget options
+ *
+ * {
+ *   "name": String
+ *   "stateful": bool
+ * }
+ */
+final Matcher isExtractWidgetOptions = new LazyMatcher(() =>
+    new MatchesJsonObject(
+        "extractWidget options", {"name": isString, "stateful": isBool}));
+
+/**
  * flutter.outline params
  *
  * {
diff --git a/pkg/analysis_server/test/services/correction/fix_test.dart b/pkg/analysis_server/test/services/correction/fix_test.dart
index 486a6a6..0f23257 100644
--- a/pkg/analysis_server/test/services/correction/fix_test.dart
+++ b/pkg/analysis_server/test/services/correction/fix_test.dart
@@ -416,7 +416,7 @@
     await assertHasFix(DartFixKind.ADD_EXPLICIT_CAST, '''
 f(List<A> a) {
   List<B> b;
-  b = a.where((e) => e is B).toList().cast<B>();
+  b = a.where((e) => e is B).cast<B>().toList();
 }
 class A {}
 class B {}
@@ -484,6 +484,29 @@
 ''');
   }
 
+  test_addExplicitCast_BAD_as() async {
+    await resolveTestUnit('''
+f(A a) {
+  C c = a as B;
+}
+class A {}
+class B {}
+class C {}
+''');
+    await assertNoFix(DartFixKind.ADD_EXPLICIT_CAST);
+  }
+
+  test_addExplicitCast_BAD_cast() async {
+    await resolveTestUnit('''
+f(List<A> a) {
+  List<B> b = a.cast<A>();
+}
+class A {}
+class B {}
+''');
+    await assertNoFix(DartFixKind.ADD_EXPLICIT_CAST);
+  }
+
   test_addExplicitCast_declaration_general() async {
     await resolveTestUnit('''
 f(A a) {
@@ -511,7 +534,7 @@
 ''');
     await assertHasFix(DartFixKind.ADD_EXPLICIT_CAST, '''
 f(List<A> a) {
-  List<B> b = a.where((e) => e is B).toList().cast<B>();
+  List<B> b = a.where((e) => e is B).cast<B>().toList();
 }
 class A {}
 class B {}
diff --git a/pkg/analysis_server/test/services/refactoring/extract_widget_test.dart b/pkg/analysis_server/test/services/refactoring/extract_widget_test.dart
new file mode 100644
index 0000000..98bdf4e
--- /dev/null
+++ b/pkg/analysis_server/test/services/refactoring/extract_widget_test.dart
@@ -0,0 +1,827 @@
+// Copyright (c) 2018, 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:analysis_server/src/services/correction/status.dart';
+import 'package:analysis_server/src/services/refactoring/extract_widget.dart';
+import 'package:analysis_server/src/services/refactoring/refactoring.dart';
+import 'package:analyzer_plugin/protocol/protocol_common.dart';
+import 'package:test/test.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'abstract_refactoring.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(ExtractWidgetTest);
+  });
+}
+
+@reflectiveTest
+class ExtractWidgetTest extends RefactoringTest {
+  ExtractWidgetRefactoringImpl refactoring;
+
+  test_checkAllConditions_selection() async {
+    addFlutterPackage();
+    await indexTestUnit('''
+import 'package:flutter/material.dart';
+class C {}
+''');
+    _createRefactoringForStringOffset('class C');
+
+    RefactoringStatus status = await refactoring.checkAllConditions();
+    assertRefactoringStatus(status, RefactoringProblemSeverity.FATAL);
+  }
+
+  test_checkName() async {
+    addFlutterPackage();
+    await indexTestUnit('''
+import 'package:flutter/material.dart';
+
+class MyWidget extends StatelessWidget {
+  @override
+  Widget build(BuildContext context) {
+    return new Text('AAA');
+  }
+}
+''');
+    _createRefactoringForStringOffset('new Text');
+
+    // null
+    refactoring.name = null;
+    assertRefactoringStatus(
+        refactoring.checkName(), RefactoringProblemSeverity.FATAL,
+        expectedMessage: 'Class name must not be null.');
+
+    // empty
+    refactoring.name = '';
+    assertRefactoringStatus(
+        refactoring.checkName(), RefactoringProblemSeverity.FATAL,
+        expectedMessage: 'Class name must not be empty.');
+
+    // OK
+    refactoring.name = 'Test';
+    assertRefactoringStatusOK(refactoring.checkName());
+  }
+
+  test_expression() async {
+    addFlutterPackage();
+    await indexTestUnit('''
+import 'package:flutter/material.dart';
+
+class MyWidget extends StatelessWidget {
+  @override
+  Widget build(BuildContext context) {
+    return new Row(
+      children: <Widget>[
+        new Column(
+          children: <Widget>[
+            new Text('AAA'),
+            new Text('BBB'),
+          ],
+        ),
+        new Text('CCC'),
+        new Text('DDD'),
+      ],
+    );
+  }
+}
+''');
+    _createRefactoringForStringOffset('new Column');
+
+    await _assertSuccessfulRefactoring('''
+import 'package:flutter/material.dart';
+
+class MyWidget extends StatelessWidget {
+  @override
+  Widget build(BuildContext context) {
+    return new Row(
+      children: <Widget>[
+        new Test(),
+        new Text('CCC'),
+        new Text('DDD'),
+      ],
+    );
+  }
+}
+
+class Test extends StatelessWidget {
+  @override
+  Widget build(BuildContext context) {
+    return new Column(
+      children: <Widget>[
+        new Text('AAA'),
+        new Text('BBB'),
+      ],
+    );
+  }
+}
+''');
+  }
+
+  test_expression_localFunction() async {
+    addFlutterPackage();
+    await indexTestUnit('''
+import 'package:flutter/material.dart';
+
+Widget main() {
+  Widget foo() {
+    return new Row(
+      children: <Widget>[
+        new Text('AAA'),
+        new Text('BBB'),
+      ],
+    );
+  }
+  return foo();
+}
+''');
+    _createRefactoringForStringOffset('new Text');
+
+    await _assertSuccessfulRefactoring('''
+import 'package:flutter/material.dart';
+
+Widget main() {
+  Widget foo() {
+    return new Row(
+      children: <Widget>[
+        new Test(),
+        new Text('BBB'),
+      ],
+    );
+  }
+  return foo();
+}
+
+class Test extends StatelessWidget {
+  @override
+  Widget build(BuildContext context) {
+    return new Text('AAA');
+  }
+}
+''');
+  }
+
+  test_expression_topFunction() async {
+    addFlutterPackage();
+    await indexTestUnit('''
+import 'package:flutter/material.dart';
+
+Widget main() {
+  return new Row(
+    children: <Widget>[
+      new Text('AAA'),
+      new Text('BBB'),
+    ],
+  );
+}
+''');
+    _createRefactoringForStringOffset('new Text');
+
+    await _assertSuccessfulRefactoring('''
+import 'package:flutter/material.dart';
+
+Widget main() {
+  return new Row(
+    children: <Widget>[
+      new Test(),
+      new Text('BBB'),
+    ],
+  );
+}
+
+class Test extends StatelessWidget {
+  @override
+  Widget build(BuildContext context) {
+    return new Text('AAA');
+  }
+}
+''');
+  }
+
+  test_invocation_enclosingClass() async {
+    addFlutterPackage();
+    await indexTestUnit(r'''
+import 'package:flutter/material.dart';
+
+class MyWidget extends StatelessWidget {
+  @override
+  Widget build(BuildContext context) {
+    return new GestureDetector(
+      child: new Text(''),
+      onTap: () {
+        foo();
+      },
+    );
+  }
+
+  void foo() {}
+}
+''');
+    _createRefactoringForStringOffset('new GestureDetector');
+
+    RefactoringStatus status = await refactoring.checkAllConditions();
+    assertRefactoringStatus(status, RefactoringProblemSeverity.ERROR);
+  }
+
+  test_invocation_enclosingSuperClass() async {
+    addFlutterPackage();
+    await indexTestUnit(r'''
+import 'package:flutter/material.dart';
+
+abstract class MyInterface {
+  void foo();
+}
+
+abstract class MyWidget extends StatelessWidget implements MyInterface {
+  @override
+  Widget build(BuildContext context) {
+    return new GestureDetector(
+      child: new Text(''),
+      onTap: () {
+        foo();
+      },
+    );
+  }
+}
+''');
+    _createRefactoringForStringOffset('new GestureDetector');
+
+    RefactoringStatus status = await refactoring.checkAllConditions();
+    assertRefactoringStatus(status, RefactoringProblemSeverity.ERROR);
+  }
+
+  test_invocation_otherClass() async {
+    addFlutterPackage();
+    await indexTestUnit(r'''
+import 'package:flutter/material.dart';
+
+class C {
+  void foo() {}
+}
+
+class MyWidget extends StatelessWidget {
+  C c = new C();
+
+  @override
+  Widget build(BuildContext context) {
+    return new GestureDetector(
+      child: new Text(''),
+      onTap: () {
+        c.foo();
+      },
+    );
+  }
+}
+''');
+    _createRefactoringForStringOffset('new GestureDetector');
+
+    await _assertSuccessfulRefactoring('''
+import 'package:flutter/material.dart';
+
+class C {
+  void foo() {}
+}
+
+class MyWidget extends StatelessWidget {
+  C c = new C();
+
+  @override
+  Widget build(BuildContext context) {
+    return new Test(c);
+  }
+}
+
+class Test extends StatelessWidget {
+  final C c;
+
+  Test(this.c);
+
+  @override
+  Widget build(BuildContext context) {
+    return new GestureDetector(
+      child: new Text(''),
+      onTap: () {
+        c.foo();
+      },
+    );
+  }
+}
+''');
+  }
+
+  test_method() async {
+    addFlutterPackage();
+    await indexTestUnit('''
+import 'package:flutter/material.dart';
+
+class MyWidget extends StatelessWidget {
+  @override
+  Widget build(BuildContext context) {
+    return createColumn();
+  }
+  
+  Widget createColumn() {
+    var a = new Text('AAA');
+    var b = new Text('BBB');
+    return new Column(
+      children: <Widget>[a, b],
+    );
+  }
+}
+''');
+    _createRefactoringForStringOffset('createColumn() {');
+
+    await _assertSuccessfulRefactoring('''
+import 'package:flutter/material.dart';
+
+class MyWidget extends StatelessWidget {
+  @override
+  Widget build(BuildContext context) {
+    return new Test();
+  }
+}
+
+class Test extends StatelessWidget {
+  @override
+  Widget build(BuildContext context) {
+    var a = new Text('AAA');
+    var b = new Text('BBB');
+    return new Column(
+      children: <Widget>[a, b],
+    );
+  }
+}
+''');
+  }
+
+  test_method_parameters() async {
+    addFlutterPackage();
+    await indexTestUnit(r'''
+import 'package:flutter/material.dart';
+
+class MyWidget extends StatelessWidget {
+  String foo;
+
+  @override
+  Widget build(BuildContext context) {
+    int bar = 1;
+    return new Row(
+      children: <Widget>[
+        createColumn('aaa', bar),
+        createColumn('bbb', 2),
+      ],
+    );
+  }
+  
+  Widget createColumn(String p1, int p2) {
+    var a = new Text('$foo $p1');
+    var b = new Text('$p2');
+    return new Column(
+      children: <Widget>[a, b],
+    );
+  }
+}
+''');
+    _createRefactoringForStringOffset('createColumn(String');
+
+    await _assertSuccessfulRefactoring(r'''
+import 'package:flutter/material.dart';
+
+class MyWidget extends StatelessWidget {
+  String foo;
+
+  @override
+  Widget build(BuildContext context) {
+    int bar = 1;
+    return new Row(
+      children: <Widget>[
+        new Test(foo, 'aaa', bar),
+        new Test(foo, 'bbb', 2),
+      ],
+    );
+  }
+}
+
+class Test extends StatelessWidget {
+  final String foo;
+  final String p1;
+  final int p2;
+
+  Test(this.foo, this.p1, this.p2);
+
+  @override
+  Widget build(BuildContext context) {
+    var a = new Text('$foo $p1');
+    var b = new Text('$p2');
+    return new Column(
+      children: <Widget>[a, b],
+    );
+  }
+}
+''');
+  }
+
+  test_parameters_field_read_enclosingClass() async {
+    addFlutterPackage();
+    await indexTestUnit(r'''
+import 'package:flutter/material.dart';
+
+class MyWidget extends StatelessWidget {
+  String field;
+
+  @override
+  Widget build(BuildContext context) {
+    return new Text(field);
+  }
+}
+''');
+    _createRefactoringForStringOffset('new Text');
+
+    await _assertSuccessfulRefactoring('''
+import 'package:flutter/material.dart';
+
+class MyWidget extends StatelessWidget {
+  String field;
+
+  @override
+  Widget build(BuildContext context) {
+    return new Test(field);
+  }
+}
+
+class Test extends StatelessWidget {
+  final String field;
+
+  Test(this.field);
+
+  @override
+  Widget build(BuildContext context) {
+    return new Text(field);
+  }
+}
+''');
+  }
+
+  test_parameters_field_read_otherClass() async {
+    addFlutterPackage();
+    await indexTestUnit(r'''
+import 'package:flutter/material.dart';
+
+class C {
+  String field;
+}
+
+class MyWidget extends StatelessWidget {
+  C c = new C();
+
+  @override
+  Widget build(BuildContext context) {
+    return new Text(c.field);
+  }
+}
+''');
+    _createRefactoringForStringOffset('new Text');
+
+    await _assertSuccessfulRefactoring('''
+import 'package:flutter/material.dart';
+
+class C {
+  String field;
+}
+
+class MyWidget extends StatelessWidget {
+  C c = new C();
+
+  @override
+  Widget build(BuildContext context) {
+    return new Test(c);
+  }
+}
+
+class Test extends StatelessWidget {
+  final C c;
+
+  Test(this.c);
+
+  @override
+  Widget build(BuildContext context) {
+    return new Text(c.field);
+  }
+}
+''');
+  }
+
+  test_parameters_field_read_topLevelVariable() async {
+    addFlutterPackage();
+    await indexTestUnit(r'''
+import 'package:flutter/material.dart';
+
+String field;
+
+class MyWidget extends StatelessWidget {
+  @override
+  Widget build(BuildContext context) {
+    return new Text(field);
+  }
+}
+''');
+    _createRefactoringForStringOffset('new Text');
+
+    await _assertSuccessfulRefactoring('''
+import 'package:flutter/material.dart';
+
+String field;
+
+class MyWidget extends StatelessWidget {
+  @override
+  Widget build(BuildContext context) {
+    return new Test();
+  }
+}
+
+class Test extends StatelessWidget {
+  @override
+  Widget build(BuildContext context) {
+    return new Text(field);
+  }
+}
+''');
+  }
+
+  test_parameters_field_write_enclosingClass() async {
+    addFlutterPackage();
+    await indexTestUnit(r'''
+import 'package:flutter/material.dart';
+
+class MyWidget extends StatelessWidget {
+  String field;
+
+  @override
+  Widget build(BuildContext context) {
+    return new GestureDetector(
+      child: new Text(''),
+      onTap: () {
+        field = '';
+      },
+    );
+  }
+}
+''');
+    _createRefactoringForStringOffset('new GestureDetector');
+
+    RefactoringStatus status = await refactoring.checkAllConditions();
+    assertRefactoringStatus(status, RefactoringProblemSeverity.ERROR);
+  }
+
+  test_parameters_field_write_enclosingSuperClass() async {
+    addFlutterPackage();
+    await indexTestUnit(r'''
+import 'package:flutter/material.dart';
+
+abstract class MySuperWidget extends StatelessWidget {
+  String field;
+}
+
+class MyWidget extends MySuperWidget {
+  @override
+  Widget build(BuildContext context) {
+    return new GestureDetector(
+      child: new Text(''),
+      onTap: () {
+        field = '';
+      },
+    );
+  }
+}
+''');
+    _createRefactoringForStringOffset('new GestureDetector');
+
+    RefactoringStatus status = await refactoring.checkAllConditions();
+    assertRefactoringStatus(status, RefactoringProblemSeverity.ERROR);
+  }
+
+  test_parameters_field_write_otherClass() async {
+    addFlutterPackage();
+    await indexTestUnit(r'''
+import 'package:flutter/material.dart';
+
+class C {
+  String field;
+}
+
+class MyWidget extends StatelessWidget {
+  C c = new C();
+
+  @override
+  Widget build(BuildContext context) {
+    return new GestureDetector(
+      child: new Text(''),
+      onTap: () {
+        c.field = '';
+      },
+    );
+  }
+}
+''');
+    _createRefactoringForStringOffset('new GestureDetector');
+
+    await _assertSuccessfulRefactoring('''
+import 'package:flutter/material.dart';
+
+class C {
+  String field;
+}
+
+class MyWidget extends StatelessWidget {
+  C c = new C();
+
+  @override
+  Widget build(BuildContext context) {
+    return new Test(c);
+  }
+}
+
+class Test extends StatelessWidget {
+  final C c;
+
+  Test(this.c);
+
+  @override
+  Widget build(BuildContext context) {
+    return new GestureDetector(
+      child: new Text(''),
+      onTap: () {
+        c.field = '';
+      },
+    );
+  }
+}
+''');
+  }
+
+  test_parameters_local_read_enclosingScope() async {
+    addFlutterPackage();
+    await indexTestUnit(r'''
+import 'package:flutter/material.dart';
+
+class MyWidget extends StatelessWidget {
+  @override
+  Widget build(BuildContext context) {
+    String local;
+    return new Text(local);
+  }
+}
+''');
+    _createRefactoringForStringOffset('new Text');
+
+    await _assertSuccessfulRefactoring('''
+import 'package:flutter/material.dart';
+
+class MyWidget extends StatelessWidget {
+  @override
+  Widget build(BuildContext context) {
+    String local;
+    return new Test(local);
+  }
+}
+
+class Test extends StatelessWidget {
+  final String local;
+
+  Test(this.local);
+
+  @override
+  Widget build(BuildContext context) {
+    return new Text(local);
+  }
+}
+''');
+  }
+
+  test_parameters_local_write_enclosingScope() async {
+    addFlutterPackage();
+    await indexTestUnit(r'''
+import 'package:flutter/material.dart';
+
+class MyWidget extends StatelessWidget {
+  @override
+  Widget build(BuildContext context) {
+    String local;
+    return new GestureDetector(
+      child: new Text(''),
+      onTap: () {
+        local = '';
+      },
+    );
+  }
+}
+''');
+    _createRefactoringForStringOffset('new GestureDetector');
+
+    RefactoringStatus status = await refactoring.checkAllConditions();
+    assertRefactoringStatus(status, RefactoringProblemSeverity.ERROR);
+  }
+
+  test_parameters_readField_readLocal() async {
+    addFlutterPackage();
+    await indexTestUnit(r'''
+import 'package:flutter/material.dart';
+
+class MyWidget extends StatelessWidget {
+  String field;
+
+  @override
+  Widget build(BuildContext context) {
+    String local;
+    return new Column(
+      children: <Widget>[
+        new Text(field),
+        new Text(local),
+      ],
+    );
+  }
+}
+''');
+    _createRefactoringForStringOffset('new Column');
+
+    await _assertSuccessfulRefactoring('''
+import 'package:flutter/material.dart';
+
+class MyWidget extends StatelessWidget {
+  String field;
+
+  @override
+  Widget build(BuildContext context) {
+    String local;
+    return new Test(field, local);
+  }
+}
+
+class Test extends StatelessWidget {
+  final String field;
+  final String local;
+
+  Test(this.field, this.local);
+
+  @override
+  Widget build(BuildContext context) {
+    return new Column(
+      children: <Widget>[
+        new Text(field),
+        new Text(local),
+      ],
+    );
+  }
+}
+''');
+  }
+
+  test_refactoringName() async {
+    addFlutterPackage();
+    await indexTestUnit('''
+import 'package:flutter/material.dart';
+
+class MyWidget extends StatelessWidget {
+  @override
+  Widget build(BuildContext context) {
+    return new Text('AAA');
+  }
+}
+''');
+    _createRefactoringForStringOffset('new Text');
+    expect(refactoring.refactoringName, 'Extract Widget');
+  }
+
+  Future<void> _assertRefactoringChange(String expectedCode) async {
+    SourceChange refactoringChange = await refactoring.createChange();
+    this.refactoringChange = refactoringChange;
+    assertTestChangeResult(expectedCode);
+  }
+
+  /**
+   * Checks that all conditions are OK and the result of applying the change
+   * to [testUnit] is [expectedCode].
+   */
+  Future<void> _assertSuccessfulRefactoring(String expectedCode) async {
+    await assertRefactoringConditionsOK();
+    await _assertRefactoringChange(expectedCode);
+  }
+
+  void _createRefactoring(int offset) {
+    refactoring = new ExtractWidgetRefactoring(
+        searchEngine, driver.currentSession, testUnit, offset);
+    refactoring.name = 'Test';
+  }
+
+  /**
+   * Creates a new refactoring in [refactoring] at the offset of the given
+   * [search] pattern.
+   */
+  void _createRefactoringForStringOffset(String search) {
+    int offset = findOffset(search);
+    _createRefactoring(offset);
+  }
+}
diff --git a/pkg/analysis_server/test/services/refactoring/test_all.dart b/pkg/analysis_server/test/services/refactoring/test_all.dart
index b845a98..9a75af9 100644
--- a/pkg/analysis_server/test/services/refactoring/test_all.dart
+++ b/pkg/analysis_server/test/services/refactoring/test_all.dart
@@ -8,6 +8,7 @@
 import 'convert_method_to_getter_test.dart' as convert_method_to_getter_test;
 import 'extract_local_test.dart' as extract_local_test;
 import 'extract_method_test.dart' as extract_method_test;
+import 'extract_widget_test.dart' as extract_widget_test;
 import 'inline_local_test.dart' as inline_local_test;
 import 'inline_method_test.dart' as inline_method_test;
 import 'naming_conventions_test.dart' as naming_conventions_test;
@@ -26,6 +27,7 @@
     convert_method_to_getter_test.main();
     extract_local_test.main();
     extract_method_test.main();
+    extract_widget_test.main();
     inline_local_test.main();
     inline_method_test.main();
     naming_conventions_test.main();
diff --git a/pkg/analysis_server/tool/spec/generated/java/types/ExtractWidgetFeedback.java b/pkg/analysis_server/tool/spec/generated/java/types/ExtractWidgetFeedback.java
new file mode 100644
index 0000000..e429a61
--- /dev/null
+++ b/pkg/analysis_server/tool/spec/generated/java/types/ExtractWidgetFeedback.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2018, 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.
+ *
+ * This file has been automatically generated.  Please do not edit it manually.
+ * To regenerate the file, use the script "pkg/analysis_server/tool/spec/generate_files".
+ */
+package org.dartlang.analysis.server.protocol;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import com.google.common.collect.Lists;
+import com.google.dart.server.utilities.general.JsonUtilities;
+import com.google.dart.server.utilities.general.ObjectUtilities;
+import com.google.gson.JsonArray;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonPrimitive;
+import org.apache.commons.lang3.builder.HashCodeBuilder;
+import java.util.ArrayList;
+import java.util.Iterator;
+import org.apache.commons.lang3.StringUtils;
+
+/**
+ * @coverage dart.server.generated.types
+ */
+@SuppressWarnings("unused")
+public class ExtractWidgetFeedback extends RefactoringFeedback {
+
+  public static final ExtractWidgetFeedback[] EMPTY_ARRAY = new ExtractWidgetFeedback[0];
+
+  public static final List<ExtractWidgetFeedback> EMPTY_LIST = Lists.newArrayList();
+
+  /**
+   * Constructor for {@link ExtractWidgetFeedback}.
+   */
+  public ExtractWidgetFeedback() {
+  }
+
+  @Override
+  public boolean equals(Object obj) {
+    if (obj instanceof ExtractWidgetFeedback) {
+      ExtractWidgetFeedback other = (ExtractWidgetFeedback) obj;
+      return
+        true;
+    }
+    return false;
+  }
+
+  public static ExtractWidgetFeedback fromJson(JsonObject jsonObject) {
+    return new ExtractWidgetFeedback();
+  }
+
+  public static List<ExtractWidgetFeedback> fromJsonArray(JsonArray jsonArray) {
+    if (jsonArray == null) {
+      return EMPTY_LIST;
+    }
+    ArrayList<ExtractWidgetFeedback> list = new ArrayList<ExtractWidgetFeedback>(jsonArray.size());
+    Iterator<JsonElement> iterator = jsonArray.iterator();
+    while (iterator.hasNext()) {
+      list.add(fromJson(iterator.next().getAsJsonObject()));
+    }
+    return list;
+  }
+
+  @Override
+  public int hashCode() {
+    HashCodeBuilder builder = new HashCodeBuilder();
+    return builder.toHashCode();
+  }
+
+  public JsonObject toJson() {
+    JsonObject jsonObject = new JsonObject();
+    return jsonObject;
+  }
+
+  @Override
+  public String toString() {
+    StringBuilder builder = new StringBuilder();
+    builder.append("[");
+    builder.append("]");
+    return builder.toString();
+  }
+
+}
diff --git a/pkg/analysis_server/tool/spec/generated/java/types/ExtractWidgetOptions.java b/pkg/analysis_server/tool/spec/generated/java/types/ExtractWidgetOptions.java
new file mode 100644
index 0000000..355f9e3
--- /dev/null
+++ b/pkg/analysis_server/tool/spec/generated/java/types/ExtractWidgetOptions.java
@@ -0,0 +1,138 @@
+/*
+ * Copyright (c) 2018, 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.
+ *
+ * This file has been automatically generated.  Please do not edit it manually.
+ * To regenerate the file, use the script "pkg/analysis_server/tool/spec/generate_files".
+ */
+package org.dartlang.analysis.server.protocol;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import com.google.common.collect.Lists;
+import com.google.dart.server.utilities.general.JsonUtilities;
+import com.google.dart.server.utilities.general.ObjectUtilities;
+import com.google.gson.JsonArray;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonPrimitive;
+import org.apache.commons.lang3.builder.HashCodeBuilder;
+import java.util.ArrayList;
+import java.util.Iterator;
+import org.apache.commons.lang3.StringUtils;
+
+/**
+ * @coverage dart.server.generated.types
+ */
+@SuppressWarnings("unused")
+public class ExtractWidgetOptions extends RefactoringOptions {
+
+  public static final ExtractWidgetOptions[] EMPTY_ARRAY = new ExtractWidgetOptions[0];
+
+  public static final List<ExtractWidgetOptions> EMPTY_LIST = Lists.newArrayList();
+
+  /**
+   * The name that the widget class should be given.
+   */
+  private String name;
+
+  /**
+   * True if a StatefulWidget should be created.
+   */
+  private boolean stateful;
+
+  /**
+   * Constructor for {@link ExtractWidgetOptions}.
+   */
+  public ExtractWidgetOptions(String name, boolean stateful) {
+    this.name = name;
+    this.stateful = stateful;
+  }
+
+  @Override
+  public boolean equals(Object obj) {
+    if (obj instanceof ExtractWidgetOptions) {
+      ExtractWidgetOptions other = (ExtractWidgetOptions) obj;
+      return
+        ObjectUtilities.equals(other.name, name) &&
+        other.stateful == stateful;
+    }
+    return false;
+  }
+
+  public static ExtractWidgetOptions fromJson(JsonObject jsonObject) {
+    String name = jsonObject.get("name").getAsString();
+    boolean stateful = jsonObject.get("stateful").getAsBoolean();
+    return new ExtractWidgetOptions(name, stateful);
+  }
+
+  public static List<ExtractWidgetOptions> fromJsonArray(JsonArray jsonArray) {
+    if (jsonArray == null) {
+      return EMPTY_LIST;
+    }
+    ArrayList<ExtractWidgetOptions> list = new ArrayList<ExtractWidgetOptions>(jsonArray.size());
+    Iterator<JsonElement> iterator = jsonArray.iterator();
+    while (iterator.hasNext()) {
+      list.add(fromJson(iterator.next().getAsJsonObject()));
+    }
+    return list;
+  }
+
+  /**
+   * The name that the widget class should be given.
+   */
+  public String getName() {
+    return name;
+  }
+
+  /**
+   * True if a StatefulWidget should be created.
+   */
+  public boolean stateful() {
+    return stateful;
+  }
+
+  @Override
+  public int hashCode() {
+    HashCodeBuilder builder = new HashCodeBuilder();
+    builder.append(name);
+    builder.append(stateful);
+    return builder.toHashCode();
+  }
+
+  /**
+   * The name that the widget class should be given.
+   */
+  public void setName(String name) {
+    this.name = name;
+  }
+
+  /**
+   * True if a StatefulWidget should be created.
+   */
+  public void setStateful(boolean stateful) {
+    this.stateful = stateful;
+  }
+
+  public JsonObject toJson() {
+    JsonObject jsonObject = new JsonObject();
+    jsonObject.addProperty("name", name);
+    jsonObject.addProperty("stateful", stateful);
+    return jsonObject;
+  }
+
+  @Override
+  public String toString() {
+    StringBuilder builder = new StringBuilder();
+    builder.append("[");
+    builder.append("name=");
+    builder.append(name + ", ");
+    builder.append("stateful=");
+    builder.append(stateful);
+    builder.append("]");
+    return builder.toString();
+  }
+
+}
diff --git a/pkg/analysis_server/tool/spec/generated/java/types/RefactoringKind.java b/pkg/analysis_server/tool/spec/generated/java/types/RefactoringKind.java
index 8ea691e..5a6fa35 100644
--- a/pkg/analysis_server/tool/spec/generated/java/types/RefactoringKind.java
+++ b/pkg/analysis_server/tool/spec/generated/java/types/RefactoringKind.java
@@ -23,6 +23,8 @@
 
   public static final String EXTRACT_METHOD = "EXTRACT_METHOD";
 
+  public static final String EXTRACT_WIDGET = "EXTRACT_WIDGET";
+
   public static final String INLINE_LOCAL_VARIABLE = "INLINE_LOCAL_VARIABLE";
 
   public static final String INLINE_METHOD = "INLINE_METHOD";
diff --git a/pkg/analysis_server/tool/spec/spec_input.html b/pkg/analysis_server/tool/spec/spec_input.html
index a151081..dcccfc0 100644
--- a/pkg/analysis_server/tool/spec/spec_input.html
+++ b/pkg/analysis_server/tool/spec/spec_input.html
@@ -4237,6 +4237,29 @@
       </field>
     </options>
   </refactoring>
+  <refactoring kind="EXTRACT_WIDGET">
+    <p>
+      Create a new class that extends either StatelessWidget or StatefulWidget,
+      whose build() method is the widget creation expression, or a method
+      returning a Flutter widget, at the specified offset.
+    </p>
+    <feedback>
+    </feedback>
+    <options>
+      <field name="name">
+        <ref>String</ref>
+        <p>
+          The name that the widget class should be given.
+        </p>
+      </field>
+      <field name="stateful">
+        <ref>bool</ref>
+        <p>
+          True if a StatefulWidget should be created.
+        </p>
+      </field>
+    </options>
+  </refactoring>
   <refactoring kind="INLINE_LOCAL_VARIABLE">
     <p>
       Inline the initializer expression of a local variable in
diff --git a/pkg/analyzer/CHANGELOG.md b/pkg/analyzer/CHANGELOG.md
index 4745a4f..9aff4bc 100644
--- a/pkg/analyzer/CHANGELOG.md
+++ b/pkg/analyzer/CHANGELOG.md
@@ -1,3 +1,38 @@
+## 0.31.2-alpha.1
+
+* Don't expect type arguments for class type parameters of static methods.
+  (#32396)
+* Beginnings of changes to make analyzer code --preview-dart-2 safe, though
+  this version is not vetted for that.
+* Infer type arguments in constructor redirections (#30855)
+* Report errors on "as void" and "is void".
+* Fix instantiating typedefs to bounds (#32114)
+* preview-dart-2 implies strong-mode now and other preview-dart-2 fixes.
+* Store method invocation arguments in summaries when needed for inference (partial fix for #32394)
+* Fix top-level inference and implicit creation (#32397)
+* Do not hint when only a responsive asset exists (#32250)
+* Do not hint when using a deprecated parameter in the defining function
+  (#32468)
+* Fix parsing of super expressions (#32393)
+* Disable conflicting generics test in the task model (#32421)
+* Change how we find analysis roots (#31343, #31344)
+* Fix problem with AST re-writing interacting poorly with inference (#32342)
+* Disallow if a class inconsistently implements a generic interface.
+* Infer void for operator[]= return in task mode for DDC (#32241)
+* Finish and improve mixin type inference in the analyzer (#32146, #32353, #32372)
+* Many enhancements to getElementDeclarations() (#29510, #32495)
+* Remove hint when there's no return from a Future<void> and async method.
+* Add a code range to ElementDeclaration (#29510)
+* Many, many fasta parser changes and improvements.
+* Add missing void annotation (#32161)
+* Add more null-aware hints (#32239)
+* Fix implicit new/const computation (#32221)
+* Treat invocations on dynamic as unknown, except for return type of == (#32173)
+* Fix crash in generic function type argument of unresolved class (#32162)
+* Fix path formatting on windows (#32095)
+* front_end implementation of mixin type inference (#31984)
+* analysis_options no longer breaks some properties (#31345)
+
 ## 0.31.2-alpha.0
 
 * front_end handling of callable classes (#32064)
diff --git a/pkg/analyzer/lib/dart/analysis/session.dart b/pkg/analyzer/lib/dart/analysis/session.dart
index b7ab961..8e58253 100644
--- a/pkg/analyzer/lib/dart/analysis/session.dart
+++ b/pkg/analyzer/lib/dart/analysis/session.dart
@@ -105,10 +105,7 @@
  * might be inconsistent with any previously returned results.
  */
 class InconsistentAnalysisException extends AnalysisException {
-  /**
-   * Initialize a newly created exception to have the given [message] and
-   * [cause].
-   */
-  InconsistentAnalysisException([String message, CaughtException cause])
-      : super(message, cause);
+  InconsistentAnalysisException()
+      : super('Requested result might be inconsistent with previously '
+            'returned results');
 }
diff --git a/pkg/analyzer/lib/exception/exception.dart b/pkg/analyzer/lib/exception/exception.dart
index 8014115..876d432 100644
--- a/pkg/analyzer/lib/exception/exception.dart
+++ b/pkg/analyzer/lib/exception/exception.dart
@@ -27,7 +27,7 @@
 
   String toString() {
     StringBuffer buffer = new StringBuffer();
-    buffer.write("AnalysisException: ");
+    buffer.write('$runtimeType: ');
     buffer.writeln(message);
     if (cause != null) {
       buffer.write('Caused by ');
diff --git a/pkg/analyzer/lib/plugin/options.dart b/pkg/analyzer/lib/plugin/options.dart
index e0ce5f4..e259428 100644
--- a/pkg/analyzer/lib/plugin/options.dart
+++ b/pkg/analyzer/lib/plugin/options.dart
@@ -4,8 +4,6 @@
 
 /// Support for client code that wants to consume options contributed to the
 /// analysis options file.
-library analyzer.plugin.options;
-
 import 'package:analyzer/error/listener.dart';
 import 'package:yaml/yaml.dart';
 
@@ -41,5 +39,5 @@
 ///
 abstract class OptionsValidator {
   /// Validate [options], reporting any errors to the given [reporter].
-  void validate(ErrorReporter reporter, Map<String, YamlNode> options);
+  void validate(ErrorReporter reporter, YamlMap options);
 }
diff --git a/pkg/analyzer/lib/source/analysis_options_provider.dart b/pkg/analyzer/lib/source/analysis_options_provider.dart
index 40b53e7..550f3e3 100644
--- a/pkg/analyzer/lib/source/analysis_options_provider.dart
+++ b/pkg/analyzer/lib/source/analysis_options_provider.dart
@@ -27,10 +27,10 @@
   /// Recursively merge options referenced by an include directive
   /// and remove the include directive from the resulting options map.
   /// Return an empty options map if the file does not exist.
-  Map<String, YamlNode> getOptions(Folder root, {bool crawlUp: false}) {
+  YamlMap getOptions(Folder root, {bool crawlUp: false}) {
     File optionsFile = getOptionsFile(root, crawlUp: crawlUp);
     if (optionsFile == null) {
-      return const <String, YamlNode>{};
+      return new YamlMap();
     }
     return getOptionsFromFile(optionsFile);
   }
@@ -62,7 +62,7 @@
   /// Recursively merge options referenced by an include directive
   /// and remove the include directive from the resulting options map.
   /// Return an empty options map if the file does not exist.
-  Map<String, YamlNode> getOptionsFromFile(File file) {
+  YamlMap getOptionsFromFile(File file) {
     return getOptionsFromSource(new FileSource(file));
   }
 
@@ -70,10 +70,9 @@
   /// Recursively merge options referenced by an include directive
   /// and remove the include directive from the resulting options map.
   /// Return an empty options map if the file does not exist.
-  Map<String, YamlNode> getOptionsFromSource(Source source) {
-    Map<String, YamlNode> options =
-        getOptionsFromString(_readAnalysisOptions(source));
-    YamlNode node = options.remove(AnalyzerOptions.include);
+  YamlMap getOptionsFromSource(Source source) {
+    YamlMap options = getOptionsFromString(_readAnalysisOptions(source));
+    YamlNode node = getValue(options, AnalyzerOptions.include);
     if (sourceFactory != null && node is YamlScalar) {
       var path = node.value;
       if (path is String) {
@@ -88,55 +87,21 @@
   /// An include directive, if present, will be left as-is,
   /// and the referenced options will NOT be merged into the result.
   /// Return an empty options map if the source is null.
-  Map<String, YamlNode> getOptionsFromString(String optionsSource) {
-    Map<String, YamlNode> options = <String, YamlNode>{};
+  YamlMap getOptionsFromString(String optionsSource) {
     if (optionsSource == null) {
-      return options;
+      return new YamlMap();
     }
-
-    YamlNode safelyLoadYamlNode() {
-      try {
-        return loadYamlNode(optionsSource);
-      } on YamlException catch (e) {
-        throw new OptionsFormatException(e.message, e.span);
-      } catch (e) {
-        throw new OptionsFormatException('Unable to parse YAML document.');
+    try {
+      YamlNode doc = loadYamlNode(optionsSource);
+      if (doc is YamlMap) {
+        return doc;
       }
+      return new YamlMap();
+    } on YamlException catch (e) {
+      throw new OptionsFormatException(e.message, e.span);
+    } catch (e) {
+      throw new OptionsFormatException('Unable to parse YAML document.');
     }
-
-    YamlNode doc = safelyLoadYamlNode();
-
-    // Empty options.
-    if (doc is YamlScalar && doc.value == null) {
-      return options;
-    }
-    if ((doc != null) && (doc is! YamlMap)) {
-      throw new OptionsFormatException(
-          'Bad options file format (expected map, got ${doc.runtimeType})',
-          doc.span);
-    }
-    if (doc is YamlMap) {
-      doc.nodes.forEach((k, YamlNode v) {
-        var key;
-        if (k is YamlScalar) {
-          key = k.value;
-        }
-        if (key is! String) {
-          throw new OptionsFormatException(
-              'Bad options file format (expected String scope key, '
-              'got ${k.runtimeType})',
-              (k ?? doc).span);
-        }
-        if (v != null && v is! YamlNode) {
-          throw new OptionsFormatException(
-              'Bad options file format (expected Node value, '
-              'got ${v.runtimeType}: `${v.toString()}`)',
-              doc.span);
-        }
-        options[key] = v;
-      });
-    }
-    return options;
   }
 
   /// Merge the given options contents where the values in [defaults] may be
@@ -151,8 +116,7 @@
   ///   * maps are merged recursively.
   ///   * if map values cannot be merged, the overriding value is taken.
   ///
-  Map<String, YamlNode> merge(
-          Map<String, YamlNode> defaults, Map<String, YamlNode> overrides) =>
+  YamlMap merge(YamlMap defaults, YamlMap overrides) =>
       new Merger().mergeMap(defaults, overrides);
 
   /// Read the contents of [source] as a string.
diff --git a/pkg/analyzer/lib/source/error_processor.dart b/pkg/analyzer/lib/source/error_processor.dart
index a4a6f77..153f42e 100644
--- a/pkg/analyzer/lib/source/error_processor.dart
+++ b/pkg/analyzer/lib/source/error_processor.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-library analyzer.source.error_processor;
-
 import 'package:analyzer/error/error.dart';
 import 'package:analyzer/src/error/codes.dart';
 import 'package:analyzer/src/generated/engine.dart';
@@ -28,7 +26,7 @@
   ///     new ErrorConfig({'missing_return' : 'error'});
   /// will create a processor config that turns `missing_return` hints into
   /// errors.
-  ErrorConfig(Object codeMap) {
+  ErrorConfig(YamlNode codeMap) {
     _processMap(codeMap);
   }
 
@@ -45,20 +43,13 @@
     }
   }
 
-  void _processMap(Object codes) {
+  void _processMap(YamlNode codes) {
     if (codes is YamlMap) {
-      // TODO(pq): stop traversing nodes and unify w/ standard map handling
       codes.nodes.forEach((k, v) {
         if (k is YamlScalar && v is YamlScalar) {
           _process(k.value, v.value);
         }
       });
-    } else if (codes is Map) {
-      codes.forEach((k, v) {
-        if (k is String) {
-          _process(k, v);
-        }
-      });
     }
   }
 
diff --git a/pkg/analyzer/lib/src/context/builder.dart b/pkg/analyzer/lib/src/context/builder.dart
index ea45784..4162aa8 100644
--- a/pkg/analyzer/lib/src/context/builder.dart
+++ b/pkg/analyzer/lib/src/context/builder.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-library analyzer.src.context.context_builder;
-
 import 'dart:collection';
 import 'dart:core';
 
@@ -435,7 +433,7 @@
 
     AnalysisOptionsImpl options = createDefaultOptions();
     File optionsFile = getOptionsFile(path);
-    Map<String, YamlNode> optionMap;
+    YamlMap optionMap;
 
     if (optionsFile != null) {
       try {
diff --git a/pkg/analyzer/lib/src/dart/analysis/driver.dart b/pkg/analyzer/lib/src/dart/analysis/driver.dart
index 43a1d47..5c6e63d 100644
--- a/pkg/analyzer/lib/src/dart/analysis/driver.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/driver.dart
@@ -326,6 +326,9 @@
 
   /**
    * The current analysis session.
+   *
+   * TODO(brianwilkerson) Create a new session when the current session might
+   * produce inconsistent results.
    */
   AnalysisSessionImpl _currentSession;
 
@@ -353,7 +356,7 @@
         _sourceFactory = sourceFactory.clone(),
         _sdkBundle = sdkBundle,
         _externalSummaries = externalSummaries {
-    _createNewSession();
+    _currentSession = new AnalysisSessionImpl(this);
     _onResults = _resultController.stream.asBroadcastStream();
     _testView = new AnalysisDriverTestView(this);
     _createFileTracker();
@@ -1119,7 +1122,6 @@
    * of state.
    */
   void _changeHook() {
-    _createNewSession();
     _priorityResults.clear();
     _scheduler.notify(this);
   }
@@ -1385,13 +1387,6 @@
   }
 
   /**
-   * Create a new analysis session, so invalidating the current one.
-   */
-  void _createNewSession() {
-    _currentSession = new AnalysisSessionImpl(this);
-  }
-
-  /**
    * Fill [_salt] with data.
    */
   void _fillSalt() {
diff --git a/pkg/analyzer/lib/src/dart/analysis/session.dart b/pkg/analyzer/lib/src/dart/analysis/session.dart
index 9125b01..8704035 100644
--- a/pkg/analyzer/lib/src/dart/analysis/session.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/session.dart
@@ -150,9 +150,6 @@
    */
   void _fillUriToLibraryCache(LibraryElement library) {
     Source source = library.source;
-    if (source == null) {
-      print('zzzzz');
-    }
     String uri = source.uri.toString();
     if (_uriToLibraryCache[uri] == null) {
       _uriToLibraryCache[uri] = library;
diff --git a/pkg/analyzer/lib/src/dart/analysis/session_helper.dart b/pkg/analyzer/lib/src/dart/analysis/session_helper.dart
new file mode 100644
index 0000000..1644e8f
--- /dev/null
+++ b/pkg/analyzer/lib/src/dart/analysis/session_helper.dart
@@ -0,0 +1,32 @@
+// Copyright (c) 2018, 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:analyzer/dart/analysis/session.dart';
+import 'package:analyzer/dart/element/element.dart';
+
+/// A wrapper around [AnalysisSession] that provides additional utilities.
+///
+/// The methods in this class that return analysis results will throw an
+/// [InconsistentAnalysisException] if the result to be returned might be
+/// inconsistent with any previously returned results.
+class AnalysisSessionHelper {
+  final AnalysisSession session;
+
+  AnalysisSessionHelper(this.session);
+
+  /// Return the [ClassElement] with the given [className] that is exported
+  /// from the library with the given [libraryUri], or `null` if the library
+  /// does not export a class with such name.
+  Future<ClassElement> getClass(String libraryUri, String className) async {
+    var libraryElement = await session.getLibraryByUri(libraryUri);
+    var element = libraryElement.exportNamespace.get(className);
+    if (element is ClassElement) {
+      return element;
+    } else {
+      return null;
+    }
+  }
+}
diff --git a/pkg/analyzer/lib/src/fasta/ast_builder.dart b/pkg/analyzer/lib/src/fasta/ast_builder.dart
index 2ca77de..14b817f 100644
--- a/pkg/analyzer/lib/src/fasta/ast_builder.dart
+++ b/pkg/analyzer/lib/src/fasta/ast_builder.dart
@@ -22,12 +22,7 @@
 import 'package:front_end/src/fasta/scanner.dart' hide StringToken;
 import 'package:front_end/src/scanner/errors.dart' show translateErrorToken;
 import 'package:front_end/src/scanner/token.dart'
-    show
-        StringToken,
-        SyntheticBeginToken,
-        SyntheticStringToken,
-        SyntheticToken,
-        CommentToken;
+    show StringToken, SyntheticBeginToken, SyntheticStringToken, SyntheticToken;
 
 import 'package:front_end/src/fasta/problems.dart' show unhandled;
 import 'package:front_end/src/fasta/messages.dart'
@@ -205,7 +200,7 @@
       String value = unescapeString(token.lexeme);
       push(ast.simpleStringLiteral(token, value));
     } else {
-      List parts = popList(1 + interpolationCount * 2);
+      List<Object> parts = popTypedList(1 + interpolationCount * 2);
       Token first = parts.first;
       Token last = parts.last;
       Quote quote = analyzeQuote(first.lexeme);
@@ -250,7 +245,7 @@
   void handleStringJuxtaposition(int literalCount) {
     debugEvent("StringJuxtaposition");
 
-    push(ast.adjacentStrings(popList(literalCount)));
+    push(ast.adjacentStrings(popTypedList(literalCount)));
   }
 
   void endArguments(int count, Token leftParenthesis, Token rightParenthesis) {
@@ -258,7 +253,7 @@
     assert(optional(')', rightParenthesis));
     debugEvent("Arguments");
 
-    List expressions = popList(count);
+    List<Expression> expressions = popTypedList(count);
     ArgumentList arguments =
         ast.argumentList(leftParenthesis, expressions, rightParenthesis);
     push(ast.methodInvocation(null, null, null, null, arguments));
@@ -382,7 +377,7 @@
     assert(optional('}', rightBracket));
     debugEvent("BlockFunctionBody");
 
-    List statements = popList(count);
+    List<Statement> statements = popTypedList(count);
     if (leftBracket != null) {
       exitLocalScope();
     }
@@ -542,7 +537,7 @@
     assert(optional(':', colon));
     debugEvent("Initializers");
 
-    List<Object> initializerObjects = popList(count) ?? const [];
+    List<Object> initializerObjects = popTypedList(count) ?? const [];
     if (!isFullAst) return;
 
     push(colon);
@@ -608,7 +603,7 @@
     debugEvent("VariableInitializer");
 
     Expression initializer = pop();
-    Identifier identifier = pop();
+    SimpleIdentifier identifier = pop();
     // TODO(ahe): Don't push initializers, instead install them.
     push(ast.variableDeclaration(identifier, assignmentOperator, initializer));
   }
@@ -676,7 +671,7 @@
     assert(optionalOrNull(';', semicolon));
     debugEvent("VariablesDeclaration");
 
-    List<VariableDeclaration> variables = popList(count);
+    List<VariableDeclaration> variables = popTypedList(count);
     _Modifiers modifiers = pop(NullValue.Modifiers);
     TypeAnnotation type = pop();
     Token keyword = modifiers?.finalConstOrVarKeyword;
@@ -703,7 +698,7 @@
     assert(optional('}', rightBracket));
     debugEvent("Block");
 
-    List<Statement> statements = popList(count) ?? <Statement>[];
+    List<Statement> statements = popTypedList(count) ?? <Statement>[];
     exitLocalScope();
     push(ast.block(leftBracket, statements, rightBracket));
   }
@@ -722,7 +717,7 @@
     debugEvent("ForStatement");
 
     Statement body = pop();
-    List<Expression> updates = popList(updateExpressionCount);
+    List<Expression> updates = popTypedList(updateExpressionCount);
     Statement conditionStatement = pop();
     Object initializerPart = pop();
     exitLocalScope();
@@ -766,7 +761,7 @@
     assert(optional(']', rightBracket));
     debugEvent("LiteralList");
 
-    List<Expression> expressions = popList(count);
+    List<Expression> expressions = popTypedList(count);
     TypeArgumentList typeArguments = pop();
     push(ast.listLiteral(
         constKeyword, typeArguments, leftBracket, expressions, rightBracket));
@@ -819,7 +814,7 @@
     assert(optional('}', rightBracket));
     debugEvent("LiteralMap");
 
-    List<MapLiteralEntry> entries = popList(count) ?? <MapLiteralEntry>[];
+    List<MapLiteralEntry> entries = popTypedList(count) ?? <MapLiteralEntry>[];
     TypeArgumentList typeArguments = pop();
     push(ast.mapLiteral(
         constKeyword, typeArguments, leftBracket, entries, rightBracket));
@@ -838,7 +833,7 @@
     assert(optional('#', hashToken));
     debugEvent("LiteralSymbol");
 
-    List<Token> components = popList(tokenCount);
+    List<Token> components = popTypedList(tokenCount);
     push(ast.symbolLiteral(hashToken, components));
   }
 
@@ -1006,7 +1001,7 @@
     debugEvent("OptionalFormalParameters");
 
     push(new _OptionalFormalParameters(
-        popList(count), leftDelimeter, rightDelimeter));
+        popTypedList(count), leftDelimeter, rightDelimeter));
   }
 
   void handleValuedFormalParameter(Token equals, Token token) {
@@ -1103,7 +1098,7 @@
     Comment comment = _findComment(metadata,
         thisKeyword ?? typeOrFunctionTypedParameter?.beginToken ?? nameToken);
 
-    FormalParameter node;
+    NormalFormalParameter node;
     if (typeOrFunctionTypedParameter is FunctionTypedFormalParameter) {
       // This is a temporary AST node that was constructed in
       // [endFunctionTypedFormalParameter]. We now deconstruct it and create
@@ -1153,16 +1148,17 @@
     }
 
     ParameterKind analyzerKind = _toAnalyzerParameterKind(kind);
+    FormalParameter parameter = node;
     if (analyzerKind != ParameterKind.REQUIRED) {
-      node = ast.defaultFormalParameter(
+      parameter = ast.defaultFormalParameter(
           node, analyzerKind, defaultValue?.separator, defaultValue?.value);
     } else if (defaultValue != null) {
       // An error is reported if a required parameter has a default value.
       // Record it as named parameter for recovery.
-      node = ast.defaultFormalParameter(node, ParameterKind.NAMED,
+      parameter = ast.defaultFormalParameter(node, ParameterKind.NAMED,
           defaultValue.separator, defaultValue.value);
     }
-    push(node);
+    push(parameter);
   }
 
   @override
@@ -1188,7 +1184,7 @@
     assert(optional(')', rightParen));
     debugEvent("FormalParameters");
 
-    List rawParameters = popList(count) ?? const <Object>[];
+    List<Object> rawParameters = popTypedList(count) ?? const <Object>[];
     List<FormalParameter> parameters = <FormalParameter>[];
     Token leftDelimiter;
     Token rightDelimiter;
@@ -1211,7 +1207,7 @@
     assert(optional('}', rightBracket));
     debugEvent("SwitchBlock");
 
-    List<List<SwitchMember>> membersList = popList(caseCount);
+    List<List<SwitchMember>> membersList = popTypedList(caseCount);
     exitBreakTarget();
     exitLocalScope();
     List<SwitchMember> members =
@@ -1250,9 +1246,9 @@
         : optional(':', colonAfterDefault));
     debugEvent("SwitchCase");
 
-    List<Statement> statements = popList(statementCount);
-    List<SwitchMember> members = popList(expressionCount) ?? [];
-    List<Label> labels = popList(labelCount);
+    List<Statement> statements = popTypedList(statementCount);
+    List<SwitchMember> members = popTypedList(expressionCount) ?? [];
+    List<Label> labels = popTypedList(labelCount);
     if (defaultKeyword != null) {
       members.add(ast.switchDefault(
           <Label>[], defaultKeyword, colonAfterDefault, <Statement>[]));
@@ -1338,7 +1334,7 @@
     debugEvent("TryStatement");
 
     Block finallyBlock = popIfNotNull(finallyKeyword);
-    List<CatchClause> catchClauses = popList(catchCount);
+    List<CatchClause> catchClauses = popTypedList(catchCount);
     Block body = pop();
     push(ast.tryStatement(
         tryKeyword, body, catchClauses, finallyKeyword, finallyBlock));
@@ -1460,7 +1456,7 @@
     if (count == 0) {
       push(NullValue.Modifiers);
     } else {
-      push(new _Modifiers(popList(count)));
+      push(new _Modifiers(popTypedList(count)));
     }
   }
 
@@ -1621,7 +1617,7 @@
     assert(firstIdentifier.isIdentifier);
     debugEvent("DottedName");
 
-    List<SimpleIdentifier> components = popList(count);
+    List<SimpleIdentifier> components = popTypedList(count);
     push(ast.dottedName(components));
   }
 
@@ -1674,14 +1670,14 @@
   void endConditionalUris(int count) {
     debugEvent("ConditionalUris");
 
-    push(popList(count) ?? NullValue.ConditionalUris);
+    push(popTypedList<Configuration>(count) ?? NullValue.ConditionalUris);
   }
 
   @override
   void handleIdentifierList(int count) {
     debugEvent("IdentifierList");
 
-    push(popList(count) ?? NullValue.IdentifierList);
+    push(popTypedList<SimpleIdentifier>(count) ?? NullValue.IdentifierList);
   }
 
   @override
@@ -1703,9 +1699,15 @@
   }
 
   @override
+  void endCombinators(int count) {
+    debugEvent("Combinators");
+    push(popTypedList<Combinator>(count) ?? NullValue.Combinators);
+  }
+
+  @override
   void endTypeList(int count) {
     debugEvent("TypeList");
-    push(popList(count) ?? NullValue.TypeList);
+    push(popTypedList<TypeName>(count) ?? NullValue.TypeList);
   }
 
   @override
@@ -1719,8 +1721,9 @@
   }
 
   @override
-  void beginClassDeclaration(Token beginToken, Token name) {
+  void beginClassDeclaration(Token begin, Token abstractToken, Token name) {
     assert(classDeclaration == null);
+    push(new _Modifiers()..abstractKeyword = abstractToken);
   }
 
   @override
@@ -1752,7 +1755,7 @@
     debugEvent("ClassImplements");
 
     if (implementsKeyword != null) {
-      List<TypeName> interfaces = popList(interfacesCount);
+      List<TypeName> interfaces = popTypedList(interfacesCount);
       push(ast.implementsClause(implementsKeyword, interfaces));
     } else {
       push(NullValue.IdentifierList);
@@ -1773,9 +1776,9 @@
     ImplementsClause implementsClause = pop(NullValue.IdentifierList);
     WithClause withClause = pop(NullValue.WithClause);
     ExtendsClause extendsClause = pop(NullValue.ExtendsClause);
+    _Modifiers modifiers = pop();
     TypeParameterList typeParameters = pop();
     SimpleIdentifier name = pop();
-    _Modifiers modifiers = pop();
     Token abstractKeyword = modifiers?.abstractKeyword;
     List<Annotation> metadata = pop();
     Comment comment = _findComment(metadata, classKeyword);
@@ -1835,6 +1838,12 @@
   }
 
   @override
+  void beginNamedMixinApplication(
+      Token begin, Token abstractToken, Token name) {
+    push(new _Modifiers()..abstractKeyword = abstractToken);
+  }
+
+  @override
   void endMixinApplication(Token withKeyword) {
     assert(optionalOrNull('with', withKeyword));
     debugEvent("MixinApplication");
@@ -1862,9 +1871,9 @@
     var superclass = mixinApplication.supertype;
     var withClause = ast.withClause(
         mixinApplication.withKeyword, mixinApplication.mixinTypes);
+    _Modifiers modifiers = pop();
     TypeParameterList typeParameters = pop();
     SimpleIdentifier name = pop();
-    _Modifiers modifiers = pop();
     Token abstractKeyword = modifiers?.abstractKeyword;
     List<Annotation> metadata = pop();
     Comment comment = _findComment(metadata, beginToken);
@@ -1887,7 +1896,7 @@
     debugEvent("LabeledStatement");
 
     Statement statement = pop();
-    List<Label> labels = popList(labelCount);
+    List<Label> labels = popTypedList(labelCount);
     push(ast.labeledStatement(labels, statement));
   }
 
@@ -1968,7 +1977,7 @@
     if (libraryNameOrUri is StringLiteral) {
       uri = libraryNameOrUri;
     } else {
-      name = ast.libraryIdentifier(libraryNameOrUri);
+      name = ast.libraryIdentifier(libraryNameOrUri as List<SimpleIdentifier>);
     }
     List<Annotation> metadata = pop();
     Comment comment = _findComment(metadata, partKeyword);
@@ -2096,10 +2105,11 @@
     SimpleIdentifier name = pop();
     TypeAnnotation returnType = pop();
     TypeParameterList typeParameters = pop();
+    List<Annotation> metadata = pop(NullValue.Metadata);
     FunctionExpression functionExpression =
         ast.functionExpression(typeParameters, parameters, body);
     push(ast.functionDeclarationStatement(ast.functionDeclaration(
-        null, null, null, returnType, null, name, functionExpression)));
+        null, metadata, null, returnType, null, name, functionExpression)));
   }
 
   @override
@@ -2107,13 +2117,17 @@
     debugEvent("FunctionName");
   }
 
-  void endTopLevelFields(int count, Token beginToken, Token semicolon) {
+  void endTopLevelFields(Token staticToken, Token covariantToken,
+      Token varFinalOrConst, int count, Token beginToken, Token semicolon) {
     assert(optional(';', semicolon));
     debugEvent("TopLevelFields");
 
-    List<VariableDeclaration> variables = popList(count);
+    List<VariableDeclaration> variables = popTypedList(count);
     TypeAnnotation type = pop();
-    _Modifiers modifiers = pop();
+    _Modifiers modifiers = new _Modifiers()
+      ..staticKeyword = staticToken
+      ..covariantKeyword = covariantToken
+      ..finalConstOrVarKeyword = varFinalOrConst;
     Token keyword = modifiers?.finalConstOrVarKeyword;
     var variableList =
         ast.variableDeclarationList(null, null, keyword, type, variables);
@@ -2147,7 +2161,7 @@
     assert(optional('>', endToken));
     debugEvent("TypeVariables");
 
-    List<TypeParameter> typeParameters = popList(count);
+    List<TypeParameter> typeParameters = popTypedList(count);
     push(ast.typeParameterList(beginToken, typeParameters, endToken));
   }
 
@@ -2367,8 +2381,15 @@
         // this).
         type = null;
       }
-      declarations.add(ast.genericTypeAlias(comment, metadata, typedefKeyword,
-          name, templateParameters, equals, type, semicolon));
+      declarations.add(ast.genericTypeAlias(
+          comment,
+          metadata,
+          typedefKeyword,
+          name,
+          templateParameters,
+          equals,
+          type as GenericFunctionType,
+          semicolon));
     }
   }
 
@@ -2378,7 +2399,7 @@
     assert(optional('{', leftBrace));
     debugEvent("Enum");
 
-    List<EnumConstantDeclaration> constants = popList(count);
+    List<EnumConstantDeclaration> constants = popTypedList(count);
     SimpleIdentifier name = pop();
     List<Annotation> metadata = pop();
     Comment comment = _findComment(metadata, enumKeyword);
@@ -2392,18 +2413,22 @@
     assert(optional('>', rightBracket));
     debugEvent("TypeArguments");
 
-    List<TypeAnnotation> arguments = popList(count);
+    List<TypeAnnotation> arguments = popTypedList(count);
     push(ast.typeArgumentList(leftBracket, arguments, rightBracket));
   }
 
   @override
-  void endFields(int count, Token beginToken, Token semicolon) {
+  void endFields(Token staticToken, Token covariantToken, Token varFinalOrConst,
+      int count, Token beginToken, Token semicolon) {
     assert(optional(';', semicolon));
     debugEvent("Fields");
 
-    List<VariableDeclaration> variables = popList(count);
+    List<VariableDeclaration> variables = popTypedList(count);
     TypeAnnotation type = pop();
-    _Modifiers modifiers = pop();
+    _Modifiers modifiers = new _Modifiers()
+      ..staticKeyword = staticToken
+      ..covariantKeyword = covariantToken
+      ..finalConstOrVarKeyword = varFinalOrConst;
     var variableList = ast.variableDeclarationList(
         null, null, modifiers?.finalConstOrVarKeyword, type, variables);
     Token covariantKeyword = modifiers?.covariantKeyword;
@@ -2469,7 +2494,7 @@
   void endMetadataStar(int count) {
     debugEvent("MetadataStar");
 
-    push(popList(count) ?? NullValue.Metadata);
+    push(popTypedList<Annotation>(count) ?? NullValue.Metadata);
   }
 
   ParameterKind _toAnalyzerParameterKind(FormalParameterKind type) {
@@ -2810,7 +2835,7 @@
 
   /// Parse a documentation comment. Return the documentation comment that was
   /// parsed, or `null` if there was no comment.
-  Comment _parseDocumentationCommentOpt(CommentToken commentToken) {
+  Comment _parseDocumentationCommentOpt(Token commentToken) {
     List<Token> tokens = <Token>[];
     while (commentToken != null) {
       if (commentToken.lexeme.startsWith('/**') ||
@@ -2894,6 +2919,25 @@
   bool optionalOrNull(String value, Token token) {
     return token == null || identical(value, token.stringValue);
   }
+
+  List<T> popTypedList<T>(int count, [List<T> list]) {
+    if (count == 0) return null;
+    assert(stack.arrayLength >= count);
+
+    final table = stack.array;
+    final length = stack.arrayLength;
+
+    final tailList = list ?? new List<T>.filled(count, null, growable: true);
+    final startIndex = length - count;
+    for (int i = 0; i < count; i++) {
+      final value = table[startIndex + i];
+      tailList[i] = value is NullValue ? null : value;
+      table[startIndex + i] = null;
+    }
+    stack.arrayLength -= count;
+
+    return tailList;
+  }
 }
 
 /// Data structure placed on the stack to represent a mixin application (a
diff --git a/pkg/analyzer/lib/src/generated/utilities_general.dart b/pkg/analyzer/lib/src/generated/utilities_general.dart
index 3cb3393..968cad3 100644
--- a/pkg/analyzer/lib/src/generated/utilities_general.dart
+++ b/pkg/analyzer/lib/src/generated/utilities_general.dart
@@ -2,12 +2,12 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-library analyzer.src.generated.utilities_general;
-
 import 'dart:async';
 import 'dart:collection';
 import 'dart:developer' show UserTag;
 
+import 'package:yaml/yaml.dart';
+
 export 'package:front_end/src/base/jenkins_smi_hash.dart' show JenkinsSmiHash;
 
 /**
@@ -27,6 +27,9 @@
  * value could not be converted.
  */
 bool toBool(Object value) {
+  if (value is YamlScalar) {
+    value = (value as YamlScalar).value;
+  }
   if (value is bool) {
     return value;
   }
diff --git a/pkg/analyzer/lib/src/kernel/ast_from_analyzer.dart b/pkg/analyzer/lib/src/kernel/ast_from_analyzer.dart
deleted file mode 100644
index 558aeb6..0000000
--- a/pkg/analyzer/lib/src/kernel/ast_from_analyzer.dart
+++ /dev/null
@@ -1,3082 +0,0 @@
-// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-library kernel.analyzer.ast_from_analyzer;
-
-import 'package:kernel/ast.dart' as ast;
-import 'package:kernel/frontend/super_initializers.dart';
-import 'package:kernel/log.dart';
-import 'package:kernel/type_algebra.dart';
-import 'package:kernel/transformations/flags.dart';
-import 'package:analyzer/dart/ast/token.dart';
-import 'package:analyzer/dart/element/element.dart';
-import 'package:analyzer/dart/element/type.dart';
-import 'package:analyzer/src/kernel/loader.dart';
-import 'package:analyzer/analyzer.dart';
-import 'package:analyzer/dart/ast/standard_resolution_map.dart';
-import 'package:analyzer/src/generated/parser.dart';
-import 'package:analyzer/src/dart/element/member.dart';
-import 'package:analyzer/src/error/codes.dart';
-import 'package:kernel/frontend/accessors.dart';
-
-/// Provides reference-level access to libraries, classes, and members.
-///
-/// "Reference level" objects are incomplete nodes that have no children but
-/// can be used for linking until the loader promotes the node to a higher
-/// loading level.
-///
-/// The [ReferenceScope] is the most restrictive scope in a hierarchy of scopes
-/// that provide increasing amounts of contextual information.  [TypeScope] is
-/// used when type parameters might be in scope, and [MemberScope] is used when
-/// building the body of a [ast.Member].
-class ReferenceScope {
-  final ReferenceLevelLoader loader;
-
-  ReferenceScope(this.loader);
-
-  bool get strongMode => loader.strongMode;
-
-  ast.Library getLibraryReference(LibraryElement element) {
-    if (element == null) return null;
-    return loader.getLibraryReference(getBaseElement(element));
-  }
-
-  ast.Class getRootClassReference() {
-    return loader.getRootClassReference();
-  }
-
-  ast.Class getClassReference(ClassElement element) {
-    return loader.getClassReference(getBaseElement(element));
-  }
-
-  ast.Member getMemberReference(Element element) {
-    return loader.getMemberReference(getBaseElement(element));
-  }
-
-  static Element getBaseElement(Element element) {
-    while (element is Member) {
-      element = (element as Member).baseElement;
-    }
-    return element;
-  }
-
-  static bool supportsConcreteGet(Element element) {
-    return (element is PropertyAccessorElement &&
-            element.isGetter &&
-            !element.isAbstract) ||
-        element is FieldElement ||
-        element is TopLevelVariableElement ||
-        element is MethodElement && !element.isAbstract ||
-        isTopLevelFunction(element);
-  }
-
-  static bool supportsInterfaceGet(Element element) {
-    return (element is PropertyAccessorElement && element.isGetter) ||
-        element is FieldElement ||
-        element is MethodElement;
-  }
-
-  static bool supportsConcreteSet(Element element) {
-    return (element is PropertyAccessorElement &&
-            element.isSetter &&
-            !element.isAbstract) ||
-        element is FieldElement && !element.isFinal && !element.isConst ||
-        element is TopLevelVariableElement &&
-            !element.isFinal &&
-            !element.isConst;
-  }
-
-  static bool supportsInterfaceSet(Element element) {
-    return (element is PropertyAccessorElement && element.isSetter) ||
-        element is FieldElement && !element.isFinal && !element.isConst;
-  }
-
-  static bool supportsConcreteIndexGet(Element element) {
-    return element is MethodElement &&
-        element.name == '[]' &&
-        !element.isAbstract;
-  }
-
-  static bool supportsInterfaceIndexGet(Element element) {
-    return element is MethodElement && element.name == '[]';
-  }
-
-  static bool supportsConcreteIndexSet(Element element) {
-    return element is MethodElement &&
-        element.name == '[]=' &&
-        !element.isAbstract;
-  }
-
-  static bool supportsInterfaceIndexSet(Element element) {
-    return element is MethodElement && element.name == '[]=';
-  }
-
-  static bool supportsConcreteMethodCall(Element element) {
-    // Note that local functions are not valid targets for method calls because
-    // they are not "methods" or even "procedures" in our AST.
-    return element is MethodElement && !element.isAbstract ||
-        isTopLevelFunction(element) ||
-        element is ConstructorElement && element.isFactory;
-  }
-
-  static bool supportsInterfaceMethodCall(Element element) {
-    return element is MethodElement;
-  }
-
-  static bool supportsConstructorCall(Element element) {
-    return element is ConstructorElement && !element.isFactory;
-  }
-
-  ast.Member _resolveGet(
-      Element element, Element auxiliary, bool predicate(Element element)) {
-    element = desynthesizeGetter(element);
-    if (predicate(element)) return getMemberReference(element);
-    if (element is PropertyAccessorElement && element.isSetter) {
-      // The getter is sometimes stored as the 'corresponding getter' instead
-      // of the 'auxiliary' element.
-      auxiliary ??= element.correspondingGetter;
-    }
-    auxiliary = desynthesizeGetter(auxiliary);
-    if (predicate(auxiliary)) return getMemberReference(auxiliary);
-    return null;
-  }
-
-  ast.Member resolveConcreteGet(Element element, Element auxiliary) {
-    return _resolveGet(element, auxiliary, supportsConcreteGet);
-  }
-
-  ast.Member resolveInterfaceGet(Element element, Element auxiliary) {
-    if (!strongMode) return null;
-    return _resolveGet(element, auxiliary, supportsInterfaceGet);
-  }
-
-  DartType getterTypeOfElement(Element element) {
-    if (element is VariableElement) {
-      return element.type;
-    } else if (element is PropertyAccessorElement && element.isGetter) {
-      return element.returnType;
-    } else {
-      return null;
-    }
-  }
-
-  /// Returns the interface target of a `call` dispatch to the given member.
-  ///
-  /// For example, if the member is a field of type C, the target will be the
-  /// `call` method of class C, if it has such a method.
-  ///
-  /// If the class C has a getter or field named `call`, this method returns
-  /// `null` - the static type system does support typed calls with indirection.
-  ast.Member resolveInterfaceFunctionCall(Element element) {
-    if (!strongMode || element == null) return null;
-    return resolveInterfaceFunctionCallOnType(getterTypeOfElement(element));
-  }
-
-  /// Returns the `call` method of [callee], if it has one, otherwise `null`.
-  ast.Member resolveInterfaceFunctionCallOnType(DartType callee) {
-    return callee is InterfaceType
-        ? resolveInterfaceMethod(callee.getMethod('call'))
-        : null;
-  }
-
-  ast.Member _resolveSet(
-      Element element, Element auxiliary, bool predicate(Element element)) {
-    element = desynthesizeSetter(element);
-    if (predicate(element)) {
-      return getMemberReference(element);
-    }
-    if (element is PropertyAccessorElement && element.isSetter) {
-      // The setter is sometimes stored as the 'corresponding setter' instead
-      // of the 'auxiliary' element.
-      auxiliary ??= element.correspondingGetter;
-    }
-    auxiliary = desynthesizeSetter(auxiliary);
-    if (predicate(auxiliary)) {
-      return getMemberReference(auxiliary);
-    }
-    return null;
-  }
-
-  ast.Member resolveConcreteSet(Element element, Element auxiliary) {
-    return _resolveSet(element, auxiliary, supportsConcreteSet);
-  }
-
-  ast.Member resolveInterfaceSet(Element element, Element auxiliary) {
-    if (!strongMode) return null;
-    return _resolveSet(element, auxiliary, supportsInterfaceSet);
-  }
-
-  ast.Member resolveConcreteIndexGet(Element element, Element auxiliary) {
-    if (supportsConcreteIndexGet(element)) {
-      return getMemberReference(element);
-    }
-    if (supportsConcreteIndexGet(auxiliary)) {
-      return getMemberReference(auxiliary);
-    }
-    return null;
-  }
-
-  ast.Member resolveInterfaceIndexGet(Element element, Element auxiliary) {
-    if (!strongMode) return null;
-    if (supportsInterfaceIndexGet(element)) {
-      return getMemberReference(element);
-    }
-    if (supportsInterfaceIndexGet(auxiliary)) {
-      return getMemberReference(auxiliary);
-    }
-    return null;
-  }
-
-  ast.Member resolveConcreteIndexSet(Element element, Element auxiliary) {
-    if (supportsConcreteIndexSet(element)) {
-      return getMemberReference(element);
-    }
-    if (supportsConcreteIndexSet(auxiliary)) {
-      return getMemberReference(auxiliary);
-    }
-    return null;
-  }
-
-  ast.Member resolveInterfaceIndexSet(Element element, Element auxiliary) {
-    if (!strongMode) return null;
-    if (supportsInterfaceIndexSet(element)) {
-      return getMemberReference(element);
-    }
-    if (supportsInterfaceIndexSet(auxiliary)) {
-      return getMemberReference(auxiliary);
-    }
-    return null;
-  }
-
-  ast.Member resolveConcreteMethod(Element element) {
-    if (supportsConcreteMethodCall(element)) {
-      return getMemberReference(element);
-    }
-    return null;
-  }
-
-  ast.Member resolveInterfaceMethod(Element element) {
-    if (!strongMode) return null;
-    if (supportsInterfaceMethodCall(element)) {
-      return getMemberReference(element);
-    }
-    return null;
-  }
-
-  ast.Constructor resolveConstructor(Element element) {
-    if (supportsConstructorCall(element)) {
-      return getMemberReference(element);
-    }
-    return null;
-  }
-
-  ast.Field resolveField(Element element) {
-    if (element is FieldElement && !element.isSynthetic) {
-      return getMemberReference(element);
-    }
-    return null;
-  }
-
-  /// A static accessor that generates a 'throw NoSuchMethodError' when a
-  /// read or write access could not be resolved.
-  Accessor staticAccess(String name, Element element, [Element auxiliary]) {
-    return new _StaticAccessor(
-        this,
-        name,
-        resolveConcreteGet(element, auxiliary),
-        resolveConcreteSet(element, auxiliary));
-  }
-
-  /// An accessor that generates a 'throw NoSuchMethodError' on both read
-  /// and write access.
-  Accessor unresolvedAccess(String name) {
-    return new _StaticAccessor(this, name, null, null);
-  }
-}
-
-class TypeScope extends ReferenceScope {
-  final Map<TypeParameterElement, ast.TypeParameter> localTypeParameters =
-      <TypeParameterElement, ast.TypeParameter>{};
-  TypeAnnotationBuilder _typeBuilder;
-
-  TypeScope(ReferenceLevelLoader loader) : super(loader) {
-    _typeBuilder = new TypeAnnotationBuilder(this);
-  }
-
-  String get location => '?';
-
-  bool get allowClassTypeParameters => false;
-
-  ast.DartType get defaultTypeParameterBound => getRootClassReference().rawType;
-
-  ast.TypeParameter tryGetTypeParameterReference(TypeParameterElement element) {
-    return localTypeParameters[element] ??
-        loader.tryGetClassTypeParameter(element);
-  }
-
-  ast.TypeParameter getTypeParameterReference(TypeParameterElement element) {
-    return localTypeParameters[element] ??
-        loader.tryGetClassTypeParameter(element) ??
-        (localTypeParameters[element] = new ast.TypeParameter(element.name));
-  }
-
-  ast.TypeParameter makeTypeParameter(TypeParameterElement element,
-      {ast.DartType bound}) {
-    var typeParameter = getTypeParameterReference(element);
-    assert(bound != null);
-    typeParameter.bound = bound;
-    return typeParameter;
-  }
-
-  ast.DartType buildType(DartType type) {
-    return _typeBuilder.buildFromDartType(type);
-  }
-
-  ast.Supertype buildSupertype(DartType type) {
-    if (type is InterfaceType) {
-      var classElement = type.element;
-      if (classElement == null) return getRootClassReference().asRawSupertype;
-      var classNode = getClassReference(classElement);
-      if (classNode.typeParameters.isEmpty ||
-          classNode.typeParameters.length != type.typeArguments.length) {
-        return classNode.asRawSupertype;
-      } else {
-        return new ast.Supertype(classNode,
-            type.typeArguments.map(buildType).toList(growable: false));
-      }
-    }
-    return getRootClassReference().asRawSupertype;
-  }
-
-  ast.DartType buildTypeAnnotation(AstNode node) {
-    return _typeBuilder.build(node);
-  }
-
-  ast.DartType buildOptionalTypeAnnotation(AstNode node) {
-    return node == null ? null : _typeBuilder.build(node);
-  }
-
-  ast.DartType getInferredType(Expression node) {
-    if (!strongMode) return const ast.DynamicType();
-    // TODO: Is this official way to get the strong-mode inferred type?
-    return buildType(node.staticType);
-  }
-
-  ast.DartType getInferredTypeArgument(Expression node, int index) {
-    var type = getInferredType(node);
-    return type is ast.InterfaceType && index < type.typeArguments.length
-        ? type.typeArguments[index]
-        : const ast.DynamicType();
-  }
-
-  ast.DartType getInferredReturnType(Expression node) {
-    var type = getInferredType(node);
-    return type is ast.FunctionType ? type.returnType : const ast.DynamicType();
-  }
-
-  List<ast.DartType> getInferredInvocationTypeArguments(
-      InvocationExpression node) {
-    if (!strongMode) return <ast.DartType>[];
-    ast.DartType inferredFunctionType = buildType(node.staticInvokeType);
-    ast.DartType genericFunctionType = buildType(node.function.staticType);
-    if (genericFunctionType is ast.FunctionType) {
-      if (genericFunctionType.typeParameters.isEmpty) return <ast.DartType>[];
-      // Attempt to unify the two types to obtain a substitution of the type
-      // variables.  If successful, use the substituted types in the order
-      // they occur in the type parameter list.
-      var substitution = unifyTypes(genericFunctionType.withoutTypeParameters,
-          inferredFunctionType, genericFunctionType.typeParameters.toSet());
-      if (substitution != null) {
-        return genericFunctionType.typeParameters
-            .map((p) => substitution[p] ?? const ast.DynamicType())
-            .toList();
-      }
-      return new List<ast.DartType>.filled(
-          genericFunctionType.typeParameters.length, const ast.DynamicType(),
-          growable: true);
-    } else {
-      return <ast.DartType>[];
-    }
-  }
-
-  List<ast.DartType> buildOptionalTypeArgumentList(TypeArgumentList node) {
-    if (node == null) return null;
-    return _typeBuilder.buildList(node.arguments);
-  }
-
-  List<ast.DartType> buildTypeArgumentList(TypeArgumentList node) {
-    return _typeBuilder.buildList(node.arguments);
-  }
-
-  List<ast.TypeParameter> buildOptionalTypeParameterList(TypeParameterList node,
-      {bool strongModeOnly: false}) {
-    if (node == null) return <ast.TypeParameter>[];
-    if (strongModeOnly && !strongMode) return <ast.TypeParameter>[];
-    return node.typeParameters.map(buildTypeParameter).toList();
-  }
-
-  ast.TypeParameter buildTypeParameter(TypeParameter node) {
-    return makeTypeParameter(node.element,
-        bound: buildOptionalTypeAnnotation(node.bound) ??
-            defaultTypeParameterBound);
-  }
-
-  ConstructorElement findDefaultConstructor(ClassElement class_) {
-    for (var constructor in class_.constructors) {
-      // Note: isDefaultConstructor checks if the constructor is suitable for
-      // being invoked without arguments.  It does not imply that it is
-      // synthetic.
-      if (constructor.isDefaultConstructor && !constructor.isFactory) {
-        return constructor;
-      }
-    }
-    return null;
-  }
-
-  ast.FunctionNode buildFunctionInterface(FunctionTypedElement element) {
-    var positional = <ast.VariableDeclaration>[];
-    var named = <ast.VariableDeclaration>[];
-    int requiredParameterCount = 0;
-    // Initialize type parameters in two passes: put them into scope,
-    // and compute the bounds afterwards while they are all in scope.
-    var typeParameters = <ast.TypeParameter>[];
-    var typeParameterElements =
-        element is ConstructorElement && element.isFactory
-            ? element.enclosingElement.typeParameters
-            : element.typeParameters;
-    if (strongMode || element is ConstructorElement) {
-      for (var parameter in typeParameterElements) {
-        var parameterNode = new ast.TypeParameter(parameter.name);
-        typeParameters.add(parameterNode);
-        localTypeParameters[parameter] = parameterNode;
-      }
-    }
-    for (int i = 0; i < typeParameters.length; ++i) {
-      var parameter = typeParameterElements[i];
-      var parameterNode = typeParameters[i];
-      parameterNode.bound = parameter.bound == null
-          ? defaultTypeParameterBound
-          : buildType(parameter.bound);
-    }
-    for (var parameter in element.parameters) {
-      var parameterNode = new ast.VariableDeclaration(parameter.name,
-          type: buildType(parameter.type));
-      if (parameter.isNotOptional) {
-        positional.add(parameterNode);
-        ++requiredParameterCount;
-      } else if (parameter.isOptionalPositional) {
-        positional.add(parameterNode);
-      } else if (parameter.isNamed) {
-        named.add(parameterNode);
-      }
-    }
-    var returnType = element is ConstructorElement
-        ? const ast.VoidType()
-        : buildType(element.returnType);
-    return new ast.FunctionNode(null,
-        typeParameters: typeParameters,
-        positionalParameters: positional,
-        namedParameters: named,
-        requiredParameterCount: requiredParameterCount,
-        returnType: returnType)
-      ..fileOffset = element.nameOffset;
-  }
-}
-
-class ExpressionScope extends TypeScope {
-  ast.Library currentLibrary;
-  final Map<LocalElement, ast.VariableDeclaration> localVariables =
-      <LocalElement, ast.VariableDeclaration>{};
-
-  ExpressionBuilder _expressionBuilder;
-  StatementBuilder _statementBuilder;
-
-  ExpressionScope(ReferenceLevelLoader loader, this.currentLibrary)
-      : super(loader) {
-    assert(currentLibrary != null);
-    _expressionBuilder = new ExpressionBuilder(this);
-    _statementBuilder = new StatementBuilder(this);
-  }
-
-  bool get allowThis => false; // Overridden by MemberScope.
-
-  ast.Name buildName(SimpleIdentifier node) {
-    return new ast.Name(node.name, currentLibrary);
-  }
-
-  ast.Statement buildStatement(Statement node) {
-    return _statementBuilder.build(node);
-  }
-
-  ast.Statement buildOptionalFunctionBody(FunctionBody body) {
-    if (body == null ||
-        body is EmptyFunctionBody ||
-        body is NativeFunctionBody) {
-      return null;
-    }
-    return buildMandatoryFunctionBody(body);
-  }
-
-  ast.Statement buildMandatoryFunctionBody(FunctionBody body) {
-    try {
-      if (body is BlockFunctionBody) {
-        return buildStatement(body.block);
-      } else if (body is ExpressionFunctionBody) {
-        if (bodyHasVoidReturn(body)) {
-          return new ast.ExpressionStatement(buildExpression(body.expression));
-        } else {
-          return new ast.ReturnStatement(buildExpression(body.expression))
-            ..fileOffset = body.expression.offset;
-        }
-      } else {
-        return internalError('Missing function body');
-      }
-    } on _CompilationError catch (e) {
-      return new ast.ExpressionStatement(buildThrowCompileTimeError(e.message));
-    }
-  }
-
-  ast.AsyncMarker getAsyncMarker({bool isAsync: false, bool isStar: false}) {
-    return ast.AsyncMarker.values[(isAsync ? 2 : 0) + (isStar ? 1 : 0)];
-  }
-
-  ast.FunctionNode buildFunctionNode(
-      FormalParameterList formalParameters, FunctionBody body,
-      {TypeName returnType,
-      List<ast.TypeParameter> typeParameters,
-      ast.DartType inferredReturnType}) {
-    // TODO(asgerf): This will in many cases rebuild the interface built by
-    //   TypeScope.buildFunctionInterface.
-    var positional = <ast.VariableDeclaration>[];
-    var named = <ast.VariableDeclaration>[];
-    int requiredParameterCount = 0;
-    var formals = formalParameters?.parameters ?? const <FormalParameter>[];
-    for (var parameter in formals) {
-      var declaration = makeVariableDeclaration(parameter.element,
-          initializer: parameter is DefaultFormalParameter
-              ? buildOptionalTopLevelExpression(parameter.defaultValue)
-              : null,
-          type: buildType(
-              resolutionMap.elementDeclaredByFormalParameter(parameter).type));
-      if (parameter.isRequired) {
-        positional.add(declaration);
-        ++requiredParameterCount;
-        declaration.initializer = null;
-      } else if (parameter.isOptionalPositional) {
-        positional.add(declaration);
-      } else if (parameter.isNamed) {
-        named.add(declaration);
-      }
-    }
-    int offset = formalParameters?.offset ?? body.offset;
-    int endOffset = body.endToken.offset;
-    ast.AsyncMarker asyncMarker =
-        getAsyncMarker(isAsync: body.isAsynchronous, isStar: body.isGenerator);
-    return new ast.FunctionNode(buildOptionalFunctionBody(body),
-        typeParameters: typeParameters,
-        positionalParameters: positional,
-        namedParameters: named,
-        requiredParameterCount: requiredParameterCount,
-        returnType: buildOptionalTypeAnnotation(returnType) ??
-            inferredReturnType ??
-            const ast.DynamicType(),
-        asyncMarker: asyncMarker,
-        dartAsyncMarker: asyncMarker)
-      ..fileOffset = offset
-      ..fileEndOffset = endOffset;
-  }
-
-  ast.Expression buildOptionalTopLevelExpression(Expression node) {
-    return node == null ? null : buildTopLevelExpression(node);
-  }
-
-  ast.Expression buildTopLevelExpression(Expression node) {
-    try {
-      return _expressionBuilder.build(node);
-    } on _CompilationError catch (e) {
-      return buildThrowCompileTimeError(e.message);
-    }
-  }
-
-  ast.Expression buildExpression(Expression node) {
-    return _expressionBuilder.build(node);
-  }
-
-  ast.Expression buildOptionalExpression(Expression node) {
-    return node == null ? null : _expressionBuilder.build(node);
-  }
-
-  Accessor buildLeftHandValue(Expression node) {
-    return _expressionBuilder.buildLeftHandValue(node);
-  }
-
-  ast.Expression buildStringLiteral(Expression node) {
-    List<ast.Expression> parts = <ast.Expression>[];
-    new StringLiteralPartBuilder(this, parts).build(node);
-    return parts.length == 1 && parts[0] is ast.StringLiteral
-        ? parts[0]
-        : new ast.StringConcatenation(parts);
-  }
-
-  ast.Expression buildThis() {
-    return allowThis
-        ? new ast.ThisExpression()
-        : emitCompileTimeError(CompileTimeErrorCode.INVALID_REFERENCE_TO_THIS);
-  }
-
-  ast.Initializer buildInitializer(ConstructorInitializer node) {
-    try {
-      return new InitializerBuilder(this).build(node);
-    } on _CompilationError catch (_) {
-      return new ast.InvalidInitializer();
-    }
-  }
-
-  bool isFinal(Element element) {
-    return element is VariableElement && element.isFinal ||
-        element is FunctionElement;
-  }
-
-  bool isConst(Element element) {
-    return element is VariableElement && element.isConst;
-  }
-
-  ast.VariableDeclaration getVariableReference(LocalElement element) {
-    return localVariables.putIfAbsent(element, () {
-      return new ast.VariableDeclaration(element.name,
-          isFinal: isFinal(element), isConst: isConst(element))
-        ..fileOffset = element.nameOffset;
-    });
-  }
-
-  ast.DartType getInferredVariableType(Element element) {
-    if (!strongMode) return const ast.DynamicType();
-    if (element is FunctionTypedElement) {
-      return buildType(element.type);
-    } else if (element is VariableElement) {
-      return buildType(element.type);
-    } else {
-      log.severe('Unexpected variable element: $element');
-      return const ast.DynamicType();
-    }
-  }
-
-  ast.VariableDeclaration makeVariableDeclaration(LocalElement element,
-      {ast.DartType type, ast.Expression initializer, int equalsOffset}) {
-    var declaration = getVariableReference(element);
-    if (equalsOffset != null) declaration.fileEqualsOffset = equalsOffset;
-    declaration.type = type ?? getInferredVariableType(element);
-    if (initializer != null) {
-      declaration.initializer = initializer..parent = declaration;
-    }
-    return declaration;
-  }
-
-  /// Returns true if [arguments] can be accepted by [target]
-  /// (not taking type checks into account).
-  bool areArgumentsCompatible(
-      FunctionTypedElement target, ast.Arguments arguments) {
-    var positionals = arguments.positional;
-    var parameters = target.parameters;
-    // If the first unprovided parameter is required, there are too few
-    // positional arguments.
-    if (positionals.length < parameters.length &&
-        parameters[positionals.length].isNotOptional) {
-      return false;
-    }
-    // If there are more positional arguments than parameters, or if the last
-    // positional argument corresponds to a named parameter, there are too many
-    // positional arguments.
-    if (positionals.length > parameters.length) return false;
-    if (positionals.isNotEmpty && parameters[positionals.length - 1].isNamed) {
-      return false; // Too many positional arguments.
-    }
-    if (arguments.named.isEmpty) return true;
-    int firstNamedParameter = positionals.length;
-    while (firstNamedParameter < parameters.length &&
-        !parameters[firstNamedParameter].isNamed) {
-      ++firstNamedParameter;
-    }
-    namedLoop:
-    for (int i = 0; i < arguments.named.length; ++i) {
-      String name = arguments.named[i].name;
-      for (int j = firstNamedParameter; j < parameters.length; ++j) {
-        if (parameters[j].isNamed && parameters[j].name == name) {
-          continue namedLoop;
-        }
-      }
-      return false;
-    }
-    return true;
-  }
-
-  /// Throws a NoSuchMethodError corresponding to a call to [memberName] on
-  /// [receiver] with the given [arguments].
-  ///
-  /// If provided, [candidateTarget] provides the expected arity and argument
-  /// names for the best candidate target.
-  ast.Expression buildThrowNoSuchMethodError(
-      ast.Expression receiver, String memberName, ast.Arguments arguments,
-      {Element candidateTarget}) {
-    // TODO(asgerf): When we have better integration with patch files, use
-    //   the internal constructor that provides a more detailed error message.
-    ast.Expression candidateArgumentNames;
-    if (candidateTarget is FunctionTypedElement) {
-      candidateArgumentNames = new ast.ListLiteral(candidateTarget.parameters
-          .map((p) => new ast.StringLiteral(p.name))
-          .toList());
-    } else {
-      candidateArgumentNames = new ast.NullLiteral();
-    }
-    return new ast.Throw(new ast.ConstructorInvocation(
-        loader.getCoreClassConstructorReference('NoSuchMethodError'),
-        new ast.Arguments(<ast.Expression>[
-          receiver,
-          new ast.SymbolLiteral(memberName),
-          new ast.ListLiteral(arguments.positional),
-          new ast.MapLiteral(arguments.named.map((arg) {
-            return new ast.MapEntry(new ast.SymbolLiteral(arg.name), arg.value);
-          }).toList()),
-          candidateArgumentNames
-        ])));
-  }
-
-  ast.Expression buildThrowCompileTimeError(String message) {
-    // The spec does not mandate a specific behavior in face of a compile-time
-    // error.  We just throw a string.  The VM throws an uncatchable exception
-    // for this case.
-    // TOOD(asgerf): Should we add uncatchable exceptions to kernel?
-    return new ast.Throw(new ast.StringLiteral(message));
-  }
-
-  ast.Expression buildThrowCompileTimeErrorFromCode(ErrorCode code,
-      [List arguments]) {
-    return buildThrowCompileTimeError(makeErrorMessage(code, arguments));
-  }
-
-  static final RegExp _errorMessagePattern = new RegExp(r'\{(\d+)\}');
-
-  String makeErrorMessage(ErrorCode error, [List arguments]) {
-    String message = error.message;
-    if (arguments != null) {
-      message = message.replaceAllMapped(_errorMessagePattern, (m) {
-        String numberString = m.group(1);
-        int index = int.parse(numberString);
-        return arguments[index];
-      });
-    }
-    return message;
-  }
-
-  /// Throws an exception that will be caught at the function level, to replace
-  /// the entire function with a throw.
-  emitCompileTimeError(ErrorCode error, [List arguments]) {
-    throw new _CompilationError(makeErrorMessage(error, arguments));
-  }
-
-  ast.Expression buildThrowAbstractClassInstantiationError(String name) {
-    return new ast.Throw(new ast.ConstructorInvocation(
-        loader.getCoreClassConstructorReference(
-            'AbstractClassInstantiationError'),
-        new ast.Arguments(<ast.Expression>[new ast.StringLiteral(name)])));
-  }
-
-  ast.Expression buildThrowFallThroughError() {
-    return new ast.Throw(new ast.ConstructorInvocation(
-        loader.getCoreClassConstructorReference('FallThroughError'),
-        new ast.Arguments.empty()));
-  }
-
-  emitInvalidConstant([ErrorCode error]) {
-    error ??= CompileTimeErrorCode.INVALID_CONSTANT;
-    return emitCompileTimeError(error);
-  }
-
-  internalError(String message) {
-    throw 'Internal error when compiling $location: $message';
-  }
-
-  unsupportedFeature(String feature) {
-    throw new _CompilationError('$feature is not supported');
-  }
-
-  ast.Expression buildAnnotation(Annotation annotation) {
-    Element element = annotation.element;
-    if (annotation.arguments == null) {
-      var target = resolveConcreteGet(element, null);
-      return target == null
-          ? new ast.InvalidExpression(null)
-          : new ast.StaticGet(target);
-    } else if (element is ConstructorElement && element.isConst) {
-      var target = resolveConstructor(element);
-      return target == null
-          ? new ast.InvalidExpression(null)
-          : new ast.ConstructorInvocation(
-              target, _expressionBuilder.buildArguments(annotation.arguments),
-              isConst: true);
-    } else {
-      return new ast.InvalidExpression(null);
-    }
-  }
-
-  void addTransformerFlag(int flags) {
-    // Overridden by MemberScope.
-  }
-
-  /// True if the body of the given method must return nothing.
-  bool hasVoidReturn(ExecutableElement element) {
-    return (strongMode && element.returnType.isVoid) ||
-        (element is PropertyAccessorElement && element.isSetter) ||
-        element.name == '[]=';
-  }
-
-  bool bodyHasVoidReturn(FunctionBody body) {
-    AstNode parent = body.parent;
-    return parent is MethodDeclaration && hasVoidReturn(parent.element) ||
-        parent is FunctionDeclaration && hasVoidReturn(parent.element);
-  }
-}
-
-/// A scope in which class type parameters are in scope, while not in scope
-/// of a specific member.
-class ClassScope extends ExpressionScope {
-  @override
-  bool get allowClassTypeParameters => true;
-
-  ClassScope(ReferenceLevelLoader loader, ast.Library library)
-      : super(loader, library);
-}
-
-/// Translates expressions, statements, and other constructs into [ast] nodes.
-///
-/// Naming convention:
-/// - `buildX` may not be given null as argument (it may crash the compiler).
-/// - `buildOptionalX` returns null or an empty list if given null
-/// - `buildMandatoryX` returns an invalid node if given null.
-class MemberScope extends ExpressionScope {
-  /// A reference to the member currently being upgraded to body level.
-  final ast.Member currentMember;
-
-  MemberScope(ReferenceLevelLoader loader, ast.Member currentMember)
-      : currentMember = currentMember,
-        super(loader, currentMember.enclosingLibrary) {
-    assert(currentMember != null);
-  }
-
-  ast.Class get currentClass => currentMember.enclosingClass;
-
-  bool get allowThis => _memberHasThis(currentMember);
-
-  @override
-  bool get allowClassTypeParameters {
-    return currentMember.isInstanceMember || currentMember is ast.Constructor;
-  }
-
-  /// Returns a string for debugging use, indicating the location of the member
-  /// being built.
-  String get location {
-    var library = currentMember.enclosingLibrary?.importUri ?? '<No Library>';
-    var className = currentMember.enclosingClass == null
-        ? null
-        : (currentMember.enclosingClass?.name ?? '<Anonymous Class>');
-    var member =
-        currentMember.name?.name ?? '<Anonymous ${currentMember.runtimeType}>';
-    return [library, className, member].join('::');
-  }
-
-  bool _memberHasThis(ast.Member member) {
-    return member is ast.Procedure && !member.isStatic ||
-        member is ast.Constructor;
-  }
-
-  void addTransformerFlag(int flags) {
-    currentMember.transformerFlags |= flags;
-  }
-}
-
-class LabelStack {
-  final List<String> labels; // Contains null for unlabeled targets.
-  final LabelStack next;
-  final List<ast.Statement> jumps = <ast.Statement>[];
-  bool isSwitchTarget = false;
-
-  LabelStack(String label, this.next) : labels = <String>[label];
-  LabelStack.unlabeled(this.next) : labels = <String>[null];
-  LabelStack.switchCase(String label, this.next)
-      : isSwitchTarget = true,
-        labels = <String>[label];
-  LabelStack.many(this.labels, this.next);
-}
-
-class StatementBuilder extends GeneralizingAstVisitor<ast.Statement> {
-  final ExpressionScope scope;
-  LabelStack breakStack, continueStack;
-
-  StatementBuilder(this.scope, [this.breakStack, this.continueStack]);
-
-  ast.Statement build(Statement node) {
-    ast.Statement result = node.accept(this);
-    result.fileOffset = _getOffset(node);
-    return result;
-  }
-
-  ast.Statement buildOptional(Statement node) {
-    ast.Statement result = node?.accept(this);
-    result?.fileOffset = _getOffset(node);
-    return result;
-  }
-
-  int _getOffset(AstNode node) {
-    return node.offset;
-  }
-
-  ast.Statement buildInScope(
-      Statement node, LabelStack breakNode, LabelStack continueNode) {
-    var oldBreak = this.breakStack;
-    var oldContinue = this.continueStack;
-    breakStack = breakNode;
-    continueStack = continueNode;
-    var result = build(node);
-    this.breakStack = oldBreak;
-    this.continueStack = oldContinue;
-    return result;
-  }
-
-  void buildBlockMember(Statement node, List<ast.Statement> output) {
-    if (node is LabeledStatement &&
-        node.statement is VariableDeclarationStatement) {
-      // If a variable is labeled, its scope is part of the enclosing block.
-      LabeledStatement labeled = node;
-      node = labeled.statement;
-    }
-    if (node is VariableDeclarationStatement) {
-      VariableDeclarationList list = node.variables;
-      ast.DartType type = scope.buildOptionalTypeAnnotation(list.type);
-      for (VariableDeclaration decl in list.variables) {
-        LocalElement local = decl.element as dynamic; // Cross cast.
-        output.add(scope.makeVariableDeclaration(local,
-            type: type,
-            initializer: scope.buildOptionalExpression(decl.initializer),
-            equalsOffset: decl.equals?.offset));
-      }
-    } else {
-      output.add(build(node));
-    }
-  }
-
-  ast.Statement makeBreakTarget(ast.Statement node, LabelStack stackNode) {
-    if (stackNode.jumps.isEmpty) return node;
-    var labeled = new ast.LabeledStatement(node);
-    for (var jump in stackNode.jumps) {
-      (jump as ast.BreakStatement).target = labeled;
-    }
-    return labeled;
-  }
-
-  LabelStack findLabelTarget(String label, LabelStack stack) {
-    while (stack != null) {
-      if (stack.labels.contains(label)) return stack;
-      stack = stack.next;
-    }
-    return null;
-  }
-
-  ast.Statement visitAssertStatement(AssertStatement node) {
-    return new ast.AssertStatement(scope.buildExpression(node.condition),
-        message: scope.buildOptionalExpression(node.message));
-  }
-
-  ast.Statement visitBlock(Block node) {
-    List<ast.Statement> statements = <ast.Statement>[];
-    for (Statement statement in node.statements) {
-      buildBlockMember(statement, statements);
-    }
-    return new ast.Block(statements);
-  }
-
-  ast.Statement visitBreakStatement(BreakStatement node) {
-    var stackNode = findLabelTarget(node.label?.name, breakStack);
-    if (stackNode == null) {
-      return node.label == null
-          ? scope.emitCompileTimeError(ParserErrorCode.BREAK_OUTSIDE_OF_LOOP)
-          : scope.emitCompileTimeError(
-              CompileTimeErrorCode.LABEL_UNDEFINED, [node.label.name]);
-    }
-    var result = new ast.BreakStatement(null);
-    stackNode.jumps.add(result);
-    return result;
-  }
-
-  ast.Statement visitContinueStatement(ContinueStatement node) {
-    var stackNode = findLabelTarget(node.label?.name, continueStack);
-    if (stackNode == null) {
-      return node.label == null
-          ? scope.emitCompileTimeError(ParserErrorCode.CONTINUE_OUTSIDE_OF_LOOP)
-          : scope.emitCompileTimeError(
-              CompileTimeErrorCode.LABEL_UNDEFINED, [node.label.name]);
-    }
-    var result = stackNode.isSwitchTarget
-        ? new ast.ContinueSwitchStatement(null)
-        : new ast.BreakStatement(null);
-    stackNode.jumps.add(result);
-    return result;
-  }
-
-  void addLoopLabels(Statement loop, LabelStack continueNode) {
-    AstNode parent = loop.parent;
-    if (parent is LabeledStatement) {
-      for (var label in parent.labels) {
-        continueNode.labels.add(label.label.name);
-      }
-    }
-  }
-
-  ast.Statement visitDoStatement(DoStatement node) {
-    LabelStack breakNode = new LabelStack.unlabeled(breakStack);
-    LabelStack continueNode = new LabelStack.unlabeled(continueStack);
-    addLoopLabels(node, continueNode);
-    var body = buildInScope(node.body, breakNode, continueNode);
-    var loop = new ast.DoStatement(makeBreakTarget(body, continueNode),
-        scope.buildExpression(node.condition));
-    return makeBreakTarget(loop, breakNode);
-  }
-
-  ast.Statement visitWhileStatement(WhileStatement node) {
-    LabelStack breakNode = new LabelStack.unlabeled(breakStack);
-    LabelStack continueNode = new LabelStack.unlabeled(continueStack);
-    addLoopLabels(node, continueNode);
-    var body = buildInScope(node.body, breakNode, continueNode);
-    var loop = new ast.WhileStatement(scope.buildExpression(node.condition),
-        makeBreakTarget(body, continueNode));
-    return makeBreakTarget(loop, breakNode);
-  }
-
-  ast.Statement visitEmptyStatement(EmptyStatement node) {
-    return new ast.EmptyStatement();
-  }
-
-  ast.Statement visitExpressionStatement(ExpressionStatement node) {
-    return new ast.ExpressionStatement(scope.buildExpression(node.expression));
-  }
-
-  static String _getLabelName(Label label) {
-    return label.label.name;
-  }
-
-  ast.Statement visitLabeledStatement(LabeledStatement node) {
-    // Only set up breaks here.  Loops handle labeling on their own.
-    var breakNode = new LabelStack.many(
-        node.labels.map(_getLabelName).toList(), breakStack);
-    var body = buildInScope(node.statement, breakNode, continueStack);
-    return makeBreakTarget(body, breakNode);
-  }
-
-  static bool isBreakingExpression(ast.Expression node) {
-    return node is ast.Throw || node is ast.Rethrow;
-  }
-
-  static bool isBreakingStatement(ast.Statement node) {
-    return node is ast.BreakStatement ||
-        node is ast.ContinueSwitchStatement ||
-        node is ast.ReturnStatement ||
-        node is ast.ExpressionStatement &&
-            isBreakingExpression(node.expression);
-  }
-
-  ast.Statement visitSwitchStatement(SwitchStatement node) {
-    // Group all cases into case blocks.  Use parallel lists to collect the
-    // intermediate terms until we are ready to create the AST nodes.
-    LabelStack breakNode = new LabelStack.unlabeled(breakStack);
-    LabelStack continueNode = continueStack;
-    var cases = <ast.SwitchCase>[];
-    var bodies = <List<Statement>>[];
-    var labelToNode = <String, ast.SwitchCase>{};
-    ast.SwitchCase currentCase = null;
-    for (var member in node.members) {
-      if (currentCase != null && currentCase.isDefault) {
-        var error = member is SwitchCase
-            ? ParserErrorCode.SWITCH_HAS_CASE_AFTER_DEFAULT_CASE
-            : ParserErrorCode.SWITCH_HAS_MULTIPLE_DEFAULT_CASES;
-        return scope.emitCompileTimeError(error);
-      }
-      if (currentCase == null) {
-        currentCase = new ast.SwitchCase(<ast.Expression>[], <int>[], null);
-        cases.add(currentCase);
-      }
-      if (member is SwitchCase) {
-        var expression = scope.buildExpression(member.expression);
-        currentCase.expressions.add(expression..parent = currentCase);
-        currentCase.expressionOffsets.add(expression.fileOffset);
-      } else {
-        currentCase.isDefault = true;
-      }
-      for (Label label in member.labels) {
-        continueNode =
-            new LabelStack.switchCase(label.label.name, continueNode);
-        labelToNode[label.label.name] = currentCase;
-      }
-      if (member.statements?.isNotEmpty ?? false) {
-        bodies.add(member.statements);
-        currentCase = null;
-      }
-    }
-    if (currentCase != null) {
-      // Close off a trailing block.
-      bodies.add(const <Statement>[]);
-      currentCase = null;
-    }
-    // Now that the label environment is set up, build the bodies.
-    var oldBreak = this.breakStack;
-    var oldContinue = this.continueStack;
-    this.breakStack = breakNode;
-    this.continueStack = continueNode;
-    for (int i = 0; i < cases.length; ++i) {
-      var blockNodes = <ast.Statement>[];
-      for (var statement in bodies[i]) {
-        buildBlockMember(statement, blockNodes);
-      }
-      if (blockNodes.isEmpty || !isBreakingStatement(blockNodes.last)) {
-        if (i < cases.length - 1) {
-          blockNodes.add(
-              new ast.ExpressionStatement(scope.buildThrowFallThroughError()));
-        } else {
-          var jump = new ast.BreakStatement(null);
-          blockNodes.add(jump);
-          breakNode.jumps.add(jump);
-        }
-      }
-      cases[i].body = new ast.Block(blockNodes)..parent = cases[i];
-    }
-    // Unwind the stack of case labels and bind their jumps to the case target.
-    while (continueNode != oldContinue) {
-      for (var jump in continueNode.jumps) {
-        (jump as ast.ContinueSwitchStatement).target =
-            labelToNode[continueNode.labels.first];
-      }
-      continueNode = continueNode.next;
-    }
-    var expression = scope.buildExpression(node.expression);
-    var result = new ast.SwitchStatement(expression, cases);
-    this.breakStack = oldBreak;
-    this.continueStack = oldContinue;
-    return makeBreakTarget(result, breakNode);
-  }
-
-  ast.Statement visitForStatement(ForStatement node) {
-    List<ast.VariableDeclaration> variables = <ast.VariableDeclaration>[];
-    ast.Expression initialExpression;
-    if (node.variables != null) {
-      VariableDeclarationList list = node.variables;
-      var type = scope.buildOptionalTypeAnnotation(list.type);
-      for (var variable in list.variables) {
-        LocalElement local = variable.element as dynamic; // Cross cast.
-        variables.add(scope.makeVariableDeclaration(local,
-            initializer: scope.buildOptionalExpression(variable.initializer),
-            type: type,
-            equalsOffset: variable.equals?.offset));
-      }
-    } else if (node.initialization != null) {
-      initialExpression = scope.buildExpression(node.initialization);
-    }
-    var breakNode = new LabelStack.unlabeled(breakStack);
-    var continueNode = new LabelStack.unlabeled(continueStack);
-    addLoopLabels(node, continueNode);
-    var body = buildInScope(node.body, breakNode, continueNode);
-    var loop = new ast.ForStatement(
-        variables,
-        scope.buildOptionalExpression(node.condition),
-        node.updaters.map(scope.buildExpression).toList(),
-        makeBreakTarget(body, continueNode));
-    loop = makeBreakTarget(loop, breakNode);
-    if (initialExpression != null) {
-      return new ast.Block(<ast.Statement>[
-        new ast.ExpressionStatement(initialExpression),
-        loop
-      ]);
-    }
-    return loop;
-  }
-
-  DartType iterableElementType(DartType iterable) {
-    if (iterable is InterfaceType) {
-      var iterator = iterable.lookUpInheritedGetter('iterator')?.returnType;
-      if (iterator is InterfaceType) {
-        return iterator.lookUpInheritedGetter('current')?.returnType;
-      }
-    }
-    return null;
-  }
-
-  DartType streamElementType(DartType stream) {
-    if (stream is InterfaceType) {
-      var class_ = stream.element;
-      if (class_.library.isDartAsync &&
-          class_.name == 'Stream' &&
-          stream.typeArguments.length == 1) {
-        return stream.typeArguments[0];
-      }
-    }
-    return null;
-  }
-
-  ast.Statement visitForEachStatement(ForEachStatement node) {
-    ast.VariableDeclaration variable;
-    Accessor leftHand;
-    if (node.loopVariable != null) {
-      DeclaredIdentifier loopVariable = node.loopVariable;
-      variable = scope.makeVariableDeclaration(loopVariable.element,
-          type: scope.buildOptionalTypeAnnotation(loopVariable.type));
-    } else if (node.identifier != null) {
-      leftHand = scope.buildLeftHandValue(node.identifier);
-      variable = new ast.VariableDeclaration(null, isFinal: true);
-      if (scope.strongMode) {
-        var containerType = node.iterable.staticType;
-        DartType elementType = node.awaitKeyword != null
-            ? streamElementType(containerType)
-            : iterableElementType(containerType);
-        if (elementType != null) {
-          variable.type = scope.buildType(elementType);
-        }
-      }
-    }
-    var breakNode = new LabelStack.unlabeled(breakStack);
-    var continueNode = new LabelStack.unlabeled(continueStack);
-    addLoopLabels(node, continueNode);
-    var body = buildInScope(node.body, breakNode, continueNode);
-    if (leftHand != null) {
-      // Desugar
-      //
-      //     for (x in e) BODY
-      //
-      // to
-      //
-      //     for (var tmp in e) {
-      //       x = tmp;
-      //       BODY
-      //     }
-      body = new ast.Block(<ast.Statement>[
-        new ast.ExpressionStatement(leftHand
-            .buildAssignment(new ast.VariableGet(variable), voidContext: true)),
-        body
-      ]);
-    }
-    var loop = new ast.ForInStatement(
-        variable,
-        scope.buildExpression(node.iterable),
-        makeBreakTarget(body, continueNode),
-        isAsync: node.awaitKeyword != null)
-      ..fileOffset = node.offset;
-    return makeBreakTarget(loop, breakNode);
-  }
-
-  ast.Statement visitIfStatement(IfStatement node) {
-    return new ast.IfStatement(scope.buildExpression(node.condition),
-        build(node.thenStatement), buildOptional(node.elseStatement));
-  }
-
-  ast.Statement visitReturnStatement(ReturnStatement node) {
-    return new ast.ReturnStatement(
-        scope.buildOptionalExpression(node.expression));
-  }
-
-  ast.Catch buildCatchClause(CatchClause node) {
-    var exceptionVariable = node.exceptionParameter == null
-        ? null
-        : scope.makeVariableDeclaration(node.exceptionParameter.staticElement);
-    var stackTraceVariable = node.stackTraceParameter == null
-        ? null
-        : scope.makeVariableDeclaration(node.stackTraceParameter.staticElement);
-    return new ast.Catch(exceptionVariable, build(node.body),
-        stackTrace: stackTraceVariable,
-        guard: scope.buildOptionalTypeAnnotation(node.exceptionType) ??
-            const ast.DynamicType());
-  }
-
-  ast.Statement visitTryStatement(TryStatement node) {
-    ast.Statement statement = build(node.body);
-    if (node.catchClauses.isNotEmpty) {
-      statement = new ast.TryCatch(
-          statement, node.catchClauses.map(buildCatchClause).toList());
-    }
-    if (node.finallyBlock != null) {
-      statement = new ast.TryFinally(statement, build(node.finallyBlock));
-    }
-    return statement;
-  }
-
-  ast.Statement visitVariableDeclarationStatement(
-      VariableDeclarationStatement node) {
-    // This is only reached when a variable is declared in non-block level,
-    // because visitBlock intercepts visits to its children.
-    // An example where we hit this case is:
-    //
-    //   if (foo) var x = 5, y = x + 1;
-    //
-    // We wrap these in a block:
-    //
-    //   if (foo) {
-    //     var x = 5;
-    //     var y = x + 1;
-    //   }
-    //
-    // Note that the use of a block here is required by the kernel language,
-    // even if there is only one variable declaration.
-    List<ast.Statement> statements = <ast.Statement>[];
-    buildBlockMember(node, statements);
-    return new ast.Block(statements);
-  }
-
-  ast.Statement visitYieldStatement(YieldStatement node) {
-    return new ast.YieldStatement(scope.buildExpression(node.expression),
-        isYieldStar: node.star != null);
-  }
-
-  ast.Statement visitFunctionDeclarationStatement(
-      FunctionDeclarationStatement node) {
-    var declaration = node.functionDeclaration;
-    var expression = declaration.functionExpression;
-    LocalElement element = declaration.element as dynamic; // Cross cast.
-    return new ast.FunctionDeclaration(
-        scope.makeVariableDeclaration(element,
-            type: scope.buildType(declaration.element.type)),
-        scope.buildFunctionNode(expression.parameters, expression.body,
-            typeParameters: scope.buildOptionalTypeParameterList(
-                expression.typeParameters,
-                strongModeOnly: true),
-            returnType: declaration.returnType))
-      ..fileOffset = node.offset;
-  }
-
-  @override
-  visitStatement(Statement node) {
-    return scope.internalError('Unhandled statement ${node.runtimeType}');
-  }
-}
-
-class ExpressionBuilder
-    extends GeneralizingAstVisitor /* <ast.Expression | Accessor> */ {
-  final ExpressionScope scope;
-  ast.VariableDeclaration cascadeReceiver;
-  ExpressionBuilder(this.scope);
-
-  ast.Expression build(Expression node) {
-    var result = node.accept(this);
-    if (result is Accessor) {
-      result = result.buildSimpleRead();
-    }
-    // For some method invocations we have already set a file offset to
-    // override the default behavior of _getOffset.
-    if (node is! MethodInvocation || result.fileOffset < 0) {
-      result.fileOffset = _getOffset(node);
-    }
-    return result;
-  }
-
-  int _getOffset(AstNode node) {
-    if (node is MethodInvocation) {
-      return node.methodName.offset;
-    } else if (node is InstanceCreationExpression) {
-      return node.constructorName.offset;
-    } else if (node is BinaryExpression) {
-      return node.operator.offset;
-    } else if (node is PrefixedIdentifier) {
-      return node.identifier.offset;
-    } else if (node is AssignmentExpression) {
-      return _getOffset(node.leftHandSide);
-    } else if (node is PropertyAccess) {
-      return node.propertyName.offset;
-    } else if (node is IsExpression) {
-      return node.isOperator.offset;
-    } else if (node is AsExpression) {
-      return node.asOperator.offset;
-    } else if (node is StringLiteral) {
-      // Use a catch-all for StringInterpolation and AdjacentStrings:
-      // the debugger stops at the end.
-      return node.end;
-    } else if (node is IndexExpression) {
-      return node.leftBracket.offset;
-    }
-    return node.offset;
-  }
-
-  Accessor buildLeftHandValue(Expression node) {
-    var result = node.accept(this);
-    if (result is Accessor) {
-      return result;
-    } else {
-      return new ReadOnlyAccessor(result, ast.TreeNode.noOffset);
-    }
-  }
-
-  ast.Expression visitAsExpression(AsExpression node) {
-    return new ast.AsExpression(
-        build(node.expression), scope.buildTypeAnnotation(node.type));
-  }
-
-  ast.Expression visitAssignmentExpression(AssignmentExpression node) {
-    bool voidContext = isInVoidContext(node);
-    String operator = node.operator.value();
-    var leftHand = buildLeftHandValue(node.leftHandSide);
-    var rightHand = build(node.rightHandSide);
-    if (operator == '=') {
-      return leftHand.buildAssignment(rightHand, voidContext: voidContext);
-    } else if (operator == '??=') {
-      return leftHand.buildNullAwareAssignment(
-          rightHand, scope.buildType(node.staticType),
-          voidContext: voidContext);
-    } else {
-      // Cut off the trailing '='.
-      var name = new ast.Name(operator.substring(0, operator.length - 1));
-      return leftHand.buildCompoundAssignment(name, rightHand,
-          offset: node.offset,
-          voidContext: voidContext,
-          interfaceTarget: scope.resolveInterfaceMethod(node.staticElement));
-    }
-  }
-
-  ast.Expression visitAwaitExpression(AwaitExpression node) {
-    return new ast.AwaitExpression(build(node.expression));
-  }
-
-  ast.Arguments buildSingleArgument(Expression node) {
-    return new ast.Arguments(<ast.Expression>[build(node)]);
-  }
-
-  ast.Expression visitBinaryExpression(BinaryExpression node) {
-    String operator = node.operator.value();
-    if (operator == '&&' || operator == '||') {
-      return new ast.LogicalExpression(
-          build(node.leftOperand), operator, build(node.rightOperand));
-    }
-    if (operator == '??') {
-      ast.Expression leftOperand = build(node.leftOperand);
-      if (leftOperand is ast.VariableGet) {
-        return new ast.ConditionalExpression(
-            buildIsNull(leftOperand, offset: node.leftOperand.offset),
-            build(node.rightOperand),
-            new ast.VariableGet(leftOperand.variable),
-            scope.getInferredType(node));
-      } else {
-        var variable = new ast.VariableDeclaration.forValue(leftOperand);
-        return new ast.Let(
-            variable,
-            new ast.ConditionalExpression(
-                buildIsNull(new ast.VariableGet(variable),
-                    offset: leftOperand.fileOffset),
-                build(node.rightOperand),
-                new ast.VariableGet(variable),
-                scope.getInferredType(node)));
-      }
-    }
-    bool isNegated = false;
-    if (operator == '!=') {
-      isNegated = true;
-      operator = '==';
-    }
-    ast.Expression expression;
-    if (node.leftOperand is SuperExpression) {
-      scope.addTransformerFlag(TransformerFlag.superCalls);
-      expression = new ast.SuperMethodInvocation(
-          new ast.Name(operator),
-          buildSingleArgument(node.rightOperand),
-          scope.resolveConcreteMethod(node.staticElement));
-    } else {
-      expression = new ast.MethodInvocation(
-          build(node.leftOperand),
-          new ast.Name(operator),
-          buildSingleArgument(node.rightOperand),
-          scope.resolveInterfaceMethod(node.staticElement));
-    }
-    return isNegated ? new ast.Not(expression) : expression;
-  }
-
-  ast.Expression visitBooleanLiteral(BooleanLiteral node) {
-    return new ast.BoolLiteral(node.value);
-  }
-
-  ast.Expression visitDoubleLiteral(DoubleLiteral node) {
-    return new ast.DoubleLiteral(node.value);
-  }
-
-  ast.Expression visitIntegerLiteral(IntegerLiteral node) {
-    return new ast.IntLiteral(node.value);
-  }
-
-  ast.Expression visitNullLiteral(NullLiteral node) {
-    return new ast.NullLiteral();
-  }
-
-  ast.Expression visitSimpleStringLiteral(SimpleStringLiteral node) {
-    return new ast.StringLiteral(node.value);
-  }
-
-  ast.Expression visitStringLiteral(StringLiteral node) {
-    return scope.buildStringLiteral(node);
-  }
-
-  static Object _getTokenValue(Token token) {
-    return token.value();
-  }
-
-  ast.Expression visitSymbolLiteral(SymbolLiteral node) {
-    String value = node.components.map(_getTokenValue).join('.');
-    return new ast.SymbolLiteral(value);
-  }
-
-  ast.Expression visitCascadeExpression(CascadeExpression node) {
-    var receiver = build(node.target);
-    // If receiver is a variable it would be tempting to reuse it, but it
-    // might be reassigned in one of the cascade sections.
-    var receiverVariable = new ast.VariableDeclaration.forValue(receiver,
-        type: scope.getInferredType(node.target));
-    var oldReceiver = this.cascadeReceiver;
-    cascadeReceiver = receiverVariable;
-    ast.Expression result = new ast.VariableGet(receiverVariable);
-    for (var section in node.cascadeSections.reversed) {
-      var dummy = new ast.VariableDeclaration.forValue(build(section));
-      result = new ast.Let(dummy, result);
-    }
-    cascadeReceiver = oldReceiver;
-    return new ast.Let(receiverVariable, result);
-  }
-
-  ast.Expression makeCascadeReceiver() {
-    assert(cascadeReceiver != null);
-    return new ast.VariableGet(cascadeReceiver);
-  }
-
-  ast.Expression visitConditionalExpression(ConditionalExpression node) {
-    return new ast.ConditionalExpression(
-        build(node.condition),
-        build(node.thenExpression),
-        build(node.elseExpression),
-        scope.getInferredType(node));
-  }
-
-  ast.Expression visitFunctionExpression(FunctionExpression node) {
-    return new ast.FunctionExpression(scope.buildFunctionNode(
-        node.parameters, node.body,
-        typeParameters: scope.buildOptionalTypeParameterList(
-            node.typeParameters,
-            strongModeOnly: true),
-        inferredReturnType: scope.getInferredReturnType(node)));
-  }
-
-  ast.Arguments buildArguments(ArgumentList valueArguments,
-      {TypeArgumentList explicitTypeArguments,
-      List<ast.DartType> inferTypeArguments()}) {
-    var positional = <ast.Expression>[];
-    var named = <ast.NamedExpression>[];
-    for (var argument in valueArguments.arguments) {
-      if (argument is NamedExpression) {
-        named.add(new ast.NamedExpression(
-            argument.name.label.name, build(argument.expression)));
-      } else if (named.isNotEmpty) {
-        return scope.emitCompileTimeError(
-            ParserErrorCode.POSITIONAL_AFTER_NAMED_ARGUMENT);
-      } else {
-        positional.add(build(argument));
-      }
-    }
-    List<ast.DartType> typeArguments;
-    if (explicitTypeArguments != null) {
-      typeArguments = scope.buildTypeArgumentList(explicitTypeArguments);
-    } else if (inferTypeArguments != null) {
-      typeArguments = inferTypeArguments();
-    }
-    return new ast.Arguments(positional, named: named, types: typeArguments);
-  }
-
-  ast.Arguments buildArgumentsForInvocation(InvocationExpression node) {
-    if (scope.strongMode) {
-      return buildArguments(node.argumentList,
-          explicitTypeArguments: node.typeArguments,
-          inferTypeArguments: () =>
-              scope.getInferredInvocationTypeArguments(node));
-    } else {
-      return buildArguments(node.argumentList);
-    }
-  }
-
-  static final ast.Name callName = new ast.Name('call');
-
-  ast.Expression visitFunctionExpressionInvocation(
-      FunctionExpressionInvocation node) {
-    return new ast.MethodInvocation(
-        build(node.function),
-        callName,
-        buildArgumentsForInvocation(node),
-        scope.resolveInterfaceFunctionCallOnType(node.function.staticType));
-  }
-
-  visitPrefixedIdentifier(PrefixedIdentifier node) {
-    switch (ElementKind.of(node.prefix.staticElement)) {
-      case ElementKind.CLASS:
-      case ElementKind.LIBRARY:
-      case ElementKind.PREFIX:
-      case ElementKind.IMPORT:
-        if (node.identifier.staticElement != null) {
-          // Should be resolved to a static access.
-          // Do not invoke 'build', because the identifier should be seen as a
-          // left-hand value or an expression depending on the context.
-          return visitSimpleIdentifier(node.identifier);
-        }
-        // Unresolved access on a class or library.
-        return scope.unresolvedAccess(node.identifier.name);
-
-      case ElementKind.DYNAMIC:
-      case ElementKind.FUNCTION_TYPE_ALIAS:
-      case ElementKind.TYPE_PARAMETER:
-      // TODO: Check with the spec to see exactly when a type literal can be
-      // used in a property access without surrounding parentheses.
-      // For now, just fall through to the property access case.
-
-      case ElementKind.FIELD:
-      case ElementKind.TOP_LEVEL_VARIABLE:
-      case ElementKind.FUNCTION:
-      case ElementKind.METHOD:
-      case ElementKind.GETTER:
-      case ElementKind.SETTER:
-      case ElementKind.LOCAL_VARIABLE:
-      case ElementKind.PARAMETER:
-      case ElementKind.ERROR:
-        Element element = node.identifier.staticElement;
-        Element auxiliary = node.identifier.auxiliaryElements?.staticElement;
-        return PropertyAccessor.make(
-            build(node.prefix),
-            scope.buildName(node.identifier),
-            scope.resolveInterfaceGet(element, auxiliary),
-            scope.resolveInterfaceSet(element, auxiliary));
-
-      case ElementKind.UNIVERSE:
-      case ElementKind.NAME:
-      case ElementKind.CONSTRUCTOR:
-      case ElementKind.EXPORT:
-      case ElementKind.LABEL:
-      default:
-        return scope.internalError(
-            'Unexpected element kind: ${node.prefix.staticElement}');
-    }
-  }
-
-  bool isStatic(Element element) {
-    if (element is ClassMemberElement) {
-      return element.isStatic || element.enclosingElement == null;
-    }
-    if (element is PropertyAccessorElement) {
-      return element.isStatic || element.enclosingElement == null;
-    }
-    if (element is FunctionElement) {
-      return element.isStatic;
-    }
-    return false;
-  }
-
-  visitSimpleIdentifier(SimpleIdentifier node) {
-    Element element = node.staticElement;
-    switch (ElementKind.of(element)) {
-      case ElementKind.CLASS:
-      case ElementKind.DYNAMIC:
-      case ElementKind.FUNCTION_TYPE_ALIAS:
-      case ElementKind.TYPE_PARAMETER:
-        return new ast.TypeLiteral(scope.buildTypeAnnotation(node));
-
-      case ElementKind.ERROR: // This covers the case where nothing was found.
-        if (!scope.allowThis) {
-          return scope.unresolvedAccess(node.name);
-        }
-        return PropertyAccessor.make(
-            scope.buildThis(), scope.buildName(node), null, null);
-
-      case ElementKind.FIELD:
-      case ElementKind.TOP_LEVEL_VARIABLE:
-      case ElementKind.GETTER:
-      case ElementKind.SETTER:
-      case ElementKind.METHOD:
-        Element auxiliary = node.auxiliaryElements?.staticElement;
-        if (isStatic(element)) {
-          return scope.staticAccess(node.name, element, auxiliary);
-        }
-        if (!scope.allowThis) {
-          return scope.unresolvedAccess(node.name);
-        }
-        return PropertyAccessor.make(
-            scope.buildThis(),
-            scope.buildName(node),
-            scope.resolveInterfaceGet(element, auxiliary),
-            scope.resolveInterfaceSet(element, auxiliary));
-
-      case ElementKind.FUNCTION:
-        FunctionElement function = element;
-        if (isTopLevelFunction(function)) {
-          return scope.staticAccess(node.name, function);
-        }
-        if (function == function.library.loadLibraryFunction) {
-          return scope.unsupportedFeature('Deferred loading');
-        }
-        return new VariableAccessor(
-            scope.getVariableReference(function), null, ast.TreeNode.noOffset);
-
-      case ElementKind.LOCAL_VARIABLE:
-      case ElementKind.PARAMETER:
-        VariableElement variable = element;
-        var type = identical(node.staticType, variable.type)
-            ? null
-            : scope.buildType(node.staticType);
-        return new VariableAccessor(
-            scope.getVariableReference(element), type, ast.TreeNode.noOffset);
-
-      case ElementKind.IMPORT:
-      case ElementKind.LIBRARY:
-      case ElementKind.PREFIX:
-        return scope.emitCompileTimeError(
-            CompileTimeErrorCode.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT,
-            [node.name]);
-
-      case ElementKind.COMPILATION_UNIT:
-      case ElementKind.CONSTRUCTOR:
-      case ElementKind.EXPORT:
-      case ElementKind.LABEL:
-      case ElementKind.UNIVERSE:
-      case ElementKind.NAME:
-      default:
-        return scope.internalError('Unexpected element kind: $element');
-    }
-  }
-
-  visitIndexExpression(IndexExpression node) {
-    Element element = node.staticElement;
-    Element auxiliary = node.auxiliaryElements?.staticElement;
-    if (node.isCascaded) {
-      return IndexAccessor.make(
-          makeCascadeReceiver(),
-          build(node.index),
-          scope.resolveInterfaceIndexGet(element, auxiliary),
-          scope.resolveInterfaceIndexSet(element, auxiliary));
-    } else if (node.target is SuperExpression) {
-      scope.addTransformerFlag(TransformerFlag.superCalls);
-      return new SuperIndexAccessor(
-          build(node.index),
-          scope.resolveConcreteIndexGet(element, auxiliary),
-          scope.resolveConcreteIndexSet(element, auxiliary),
-          ast.TreeNode.noOffset);
-    } else {
-      return IndexAccessor.make(
-          build(node.target),
-          build(node.index),
-          scope.resolveInterfaceIndexGet(element, auxiliary),
-          scope.resolveInterfaceIndexSet(element, auxiliary));
-    }
-  }
-
-  /// Follows any number of redirecting factories, returning the effective
-  /// target or `null` if a cycle is found.
-  ///
-  /// The returned element is a [Member] if the type arguments to the effective
-  /// target are different from the original arguments.
-  ConstructorElement getEffectiveFactoryTarget(ConstructorElement element) {
-    ConstructorElement anchor = null;
-    int n = 1;
-    while (element.isFactory && element.redirectedConstructor != null) {
-      element = element.redirectedConstructor;
-      var base = ReferenceScope.getBaseElement(element);
-      if (base == anchor) return null; // Cyclic redirection.
-      if (n & ++n == 0) {
-        anchor = base;
-      }
-    }
-    return element;
-  }
-
-  /// Forces the list of type arguments to have the specified length. If the
-  /// length was changed, all type arguments are changed to `dynamic`.
-  void _coerceTypeArgumentArity(List<ast.DartType> typeArguments, int arity) {
-    if (typeArguments.length != arity) {
-      typeArguments.length = arity;
-      typeArguments.fillRange(0, arity, const ast.DynamicType());
-    }
-  }
-
-  ast.Expression visitInstanceCreationExpression(
-      InstanceCreationExpression node) {
-    ConstructorElement element = node.staticElement;
-    ClassElement classElement = element?.enclosingElement;
-    List<ast.DartType> inferTypeArguments() {
-      var inferredType = scope.getInferredType(node);
-      if (inferredType is ast.InterfaceType) {
-        return inferredType.typeArguments.toList();
-      }
-      int numberOfTypeArguments =
-          classElement == null ? 0 : classElement.typeParameters.length;
-      return new List<ast.DartType>.filled(
-          numberOfTypeArguments, const ast.DynamicType(),
-          growable: true);
-    }
-
-    var arguments = buildArguments(node.argumentList,
-        explicitTypeArguments: node.constructorName.type.typeArguments,
-        inferTypeArguments: inferTypeArguments);
-    ast.Expression noSuchMethodError() {
-      return node.isConst
-          ? scope.emitInvalidConstant()
-          : scope.buildThrowNoSuchMethodError(
-              new ast.NullLiteral(), '${node.constructorName}', arguments,
-              candidateTarget: element);
-    }
-
-    if (element == null) {
-      return noSuchMethodError();
-    }
-    assert(classElement != null);
-    var redirect = getEffectiveFactoryTarget(element);
-    if (redirect == null) {
-      return scope.buildThrowCompileTimeError(
-          CompileTimeErrorCode.RECURSIVE_FACTORY_REDIRECT.message);
-    }
-    if (redirect != element) {
-      ast.InterfaceType returnType = scope.buildType(redirect.returnType);
-      arguments.types
-        ..clear()
-        ..addAll(returnType.typeArguments);
-      element = redirect;
-      classElement = element.enclosingElement;
-    }
-    element = ReferenceScope.getBaseElement(element);
-    if (node.isConst && !element.isConst) {
-      return scope
-          .emitInvalidConstant(CompileTimeErrorCode.CONST_WITH_NON_CONST);
-    }
-    if (classElement.isEnum) {
-      return scope.emitCompileTimeError(CompileTimeErrorCode.INSTANTIATE_ENUM);
-    }
-    _coerceTypeArgumentArity(
-        arguments.types, classElement.typeParameters.length);
-    if (element.isFactory) {
-      ast.Member target = scope.resolveConcreteMethod(element);
-      if (target is ast.Procedure &&
-          scope.areArgumentsCompatible(element, arguments)) {
-        return new ast.StaticInvocation(target, arguments,
-            isConst: node.isConst);
-      } else {
-        return noSuchMethodError();
-      }
-    }
-    if (classElement.isAbstract) {
-      return node.isConst
-          ? scope.emitInvalidConstant()
-          : scope.buildThrowAbstractClassInstantiationError(classElement.name);
-    }
-    ast.Constructor constructor = scope.resolveConstructor(element);
-    if (constructor != null &&
-        scope.areArgumentsCompatible(element, arguments)) {
-      return new ast.ConstructorInvocation(constructor, arguments,
-          isConst: node.isConst);
-    } else {
-      return noSuchMethodError();
-    }
-  }
-
-  ast.Expression visitIsExpression(IsExpression node) {
-    if (node.notOperator != null) {
-      // Put offset on the IsExpression for "is!" cases:
-      // As it is wrapped in a not, it won't get an offset otherwise.
-      return new ast.Not(new ast.IsExpression(
-          build(node.expression), scope.buildTypeAnnotation(node.type))
-        ..fileOffset = _getOffset(node));
-    } else {
-      return new ast.IsExpression(
-          build(node.expression), scope.buildTypeAnnotation(node.type));
-    }
-  }
-
-  /// Emit a method invocation, either as a direct call `o.f(x)` or decomposed
-  /// into a getter and function invocation `o.f.call(x)`.
-  ast.Expression buildDecomposableMethodInvocation(ast.Expression receiver,
-      ast.Name name, ast.Arguments arguments, Element targetElement) {
-    // Try to emit a typed call to an interface method.
-    ast.Procedure targetMethod = scope.resolveInterfaceMethod(targetElement);
-    if (targetMethod != null) {
-      return new ast.MethodInvocation(receiver, name, arguments, targetMethod);
-    }
-    // Try to emit a typed call to getter or field and call the returned
-    // function.
-    ast.Member targetGetter = scope.resolveInterfaceGet(targetElement, null);
-    if (targetGetter != null) {
-      return new ast.MethodInvocation(
-          new ast.PropertyGet(receiver, name, targetGetter),
-          callName,
-          arguments,
-          scope.resolveInterfaceFunctionCall(targetElement));
-    }
-    // Emit a dynamic call.
-    return new ast.MethodInvocation(receiver, name, arguments);
-  }
-
-  ast.Expression visitMethodInvocation(MethodInvocation node) {
-    Element element = node.methodName.staticElement;
-    if (element != null && element == element.library?.loadLibraryFunction) {
-      return scope.unsupportedFeature('Deferred loading');
-    }
-    var target = node.target;
-    if (node.isCascaded) {
-      return buildDecomposableMethodInvocation(
-          makeCascadeReceiver(),
-          scope.buildName(node.methodName),
-          buildArgumentsForInvocation(node),
-          element);
-    } else if (target is SuperExpression) {
-      scope.addTransformerFlag(TransformerFlag.superCalls);
-      return new ast.SuperMethodInvocation(
-          scope.buildName(node.methodName),
-          buildArgumentsForInvocation(node),
-          scope.resolveConcreteMethod(element));
-    } else if (isLocal(element)) {
-      // Set the offset directly: Normally the offset is at the start of the
-      // method, but in this case, because we insert a '.call', we want it at
-      // the end instead.
-      return new ast.MethodInvocation(
-          new ast.VariableGet(scope.getVariableReference(element)),
-          callName,
-          buildArgumentsForInvocation(node),
-          scope.resolveInterfaceFunctionCall(element))
-        ..fileOffset = node.methodName.end;
-    } else if (isStaticMethod(element)) {
-      var method = scope.resolveConcreteMethod(element);
-      var arguments = buildArgumentsForInvocation(node);
-      if (method == null || !scope.areArgumentsCompatible(element, arguments)) {
-        return scope.buildThrowNoSuchMethodError(
-            new ast.NullLiteral(), node.methodName.name, arguments,
-            candidateTarget: element);
-      }
-      return new ast.StaticInvocation(method, arguments);
-    } else if (isStaticVariableOrGetter(element)) {
-      var method = scope.resolveConcreteGet(element, null);
-      if (method == null) {
-        return scope.buildThrowNoSuchMethodError(
-            new ast.NullLiteral(), node.methodName.name, new ast.Arguments([]),
-            candidateTarget: element);
-      }
-      // Set the offset directly: Normally the offset is at the start of the
-      // method, but in this case, because we insert a '.call', we want it at
-      // the end instead.
-      return new ast.MethodInvocation(
-          new ast.StaticGet(method),
-          callName,
-          buildArgumentsForInvocation(node),
-          scope.resolveInterfaceFunctionCall(element))
-        ..fileOffset = node.methodName.end;
-    } else if (target == null && !scope.allowThis ||
-        target is Identifier && target.staticElement is ClassElement ||
-        target is Identifier && target.staticElement is PrefixElement) {
-      return scope.buildThrowNoSuchMethodError(new ast.NullLiteral(),
-          node.methodName.name, buildArgumentsForInvocation(node),
-          candidateTarget: element);
-    } else if (target == null) {
-      return buildDecomposableMethodInvocation(
-          scope.buildThis(),
-          scope.buildName(node.methodName),
-          buildArgumentsForInvocation(node),
-          element);
-    } else if (node.operator.value() == '?.') {
-      var receiver = makeOrReuseVariable(build(target));
-      return makeLet(
-          receiver,
-          new ast.ConditionalExpression(
-              buildIsNull(new ast.VariableGet(receiver)),
-              new ast.NullLiteral(),
-              buildDecomposableMethodInvocation(
-                  new ast.VariableGet(receiver),
-                  scope.buildName(node.methodName),
-                  buildArgumentsForInvocation(node),
-                  element)
-                ..fileOffset = node.methodName.offset,
-              scope.buildType(node.staticType)));
-    } else {
-      return buildDecomposableMethodInvocation(
-          build(node.target),
-          scope.buildName(node.methodName),
-          buildArgumentsForInvocation(node),
-          element);
-    }
-  }
-
-  ast.Expression visitNamedExpression(NamedExpression node) {
-    return scope.internalError('Unexpected named expression');
-  }
-
-  ast.Expression visitParenthesizedExpression(ParenthesizedExpression node) {
-    return build(node.expression);
-  }
-
-  bool isInVoidContext(Expression node) {
-    AstNode parent = node.parent;
-    return parent is ForStatement &&
-            (parent.updaters.contains(node) || parent.initialization == node) ||
-        parent is ExpressionStatement ||
-        parent is ExpressionFunctionBody && scope.bodyHasVoidReturn(parent);
-  }
-
-  ast.Expression visitPostfixExpression(PostfixExpression node) {
-    String operator = node.operator.value();
-    switch (operator) {
-      case '++':
-      case '--':
-        var leftHand = buildLeftHandValue(node.operand);
-        var binaryOperator = new ast.Name(operator[0]);
-        return leftHand.buildPostfixIncrement(binaryOperator,
-            offset: node.operator.offset,
-            voidContext: isInVoidContext(node),
-            interfaceTarget: scope.resolveInterfaceMethod(node.staticElement));
-
-      default:
-        return scope.internalError('Invalid postfix operator $operator');
-    }
-  }
-
-  ast.Expression visitPrefixExpression(PrefixExpression node) {
-    String operator = node.operator.value();
-    switch (operator) {
-      case '-':
-      case '~':
-        var name = new ast.Name(operator == '-' ? 'unary-' : '~');
-        if (node.operand is SuperExpression) {
-          scope.addTransformerFlag(TransformerFlag.superCalls);
-          return new ast.SuperMethodInvocation(name, new ast.Arguments.empty(),
-              scope.resolveConcreteMethod(node.staticElement));
-        }
-        return new ast.MethodInvocation(
-            build(node.operand),
-            name,
-            new ast.Arguments.empty(),
-            scope.resolveInterfaceMethod(node.staticElement));
-
-      case '!':
-        return new ast.Not(build(node.operand));
-
-      case '++':
-      case '--':
-        var leftHand = buildLeftHandValue(node.operand);
-        var binaryOperator = new ast.Name(operator[0]);
-        return leftHand.buildPrefixIncrement(binaryOperator,
-            offset: node.offset,
-            interfaceTarget: scope.resolveInterfaceMethod(node.staticElement));
-
-      default:
-        return scope.internalError('Invalid prefix operator $operator');
-    }
-  }
-
-  visitPropertyAccess(PropertyAccess node) {
-    Element element = node.propertyName.staticElement;
-    Element auxiliary = node.propertyName.auxiliaryElements?.staticElement;
-    var getter = scope.resolveInterfaceGet(element, auxiliary);
-    var setter = scope.resolveInterfaceSet(element, auxiliary);
-    Expression target = node.target;
-    if (node.isCascaded) {
-      return PropertyAccessor.make(makeCascadeReceiver(),
-          scope.buildName(node.propertyName), getter, setter);
-    } else if (node.target is SuperExpression) {
-      scope.addTransformerFlag(TransformerFlag.superCalls);
-      return new SuperPropertyAccessor(
-          scope.buildName(node.propertyName),
-          scope.resolveConcreteGet(element, auxiliary),
-          scope.resolveConcreteSet(element, auxiliary),
-          ast.TreeNode.noOffset);
-    } else if (target is Identifier && target.staticElement is ClassElement) {
-      // Note that this case also covers null-aware static access on a class,
-      // which is equivalent to a regular static access.
-      return scope.staticAccess(node.propertyName.name, element, auxiliary);
-    } else if (node.operator.value() == '?.') {
-      return new NullAwarePropertyAccessor(
-          build(target),
-          scope.buildName(node.propertyName),
-          getter,
-          setter,
-          scope.buildType(node.staticType),
-          ast.TreeNode.noOffset);
-    } else {
-      return PropertyAccessor.make(
-          build(target), scope.buildName(node.propertyName), getter, setter);
-    }
-  }
-
-  ast.Expression visitRethrowExpression(RethrowExpression node) {
-    return new ast.Rethrow();
-  }
-
-  ast.Expression visitSuperExpression(SuperExpression node) {
-    return scope
-        .emitCompileTimeError(CompileTimeErrorCode.SUPER_IN_INVALID_CONTEXT);
-  }
-
-  ast.Expression visitThisExpression(ThisExpression node) {
-    return scope.buildThis();
-  }
-
-  ast.Expression visitThrowExpression(ThrowExpression node) {
-    return new ast.Throw(build(node.expression));
-  }
-
-  ast.Expression visitListLiteral(ListLiteral node) {
-    ast.DartType type = node.typeArguments?.arguments?.isNotEmpty ?? false
-        ? scope.buildTypeAnnotation(node.typeArguments.arguments[0])
-        : scope.getInferredTypeArgument(node, 0);
-    return new ast.ListLiteral(node.elements.map(build).toList(),
-        typeArgument: type, isConst: node.constKeyword != null);
-  }
-
-  ast.Expression visitMapLiteral(MapLiteral node) {
-    ast.DartType key, value;
-    if (node.typeArguments != null && node.typeArguments.arguments.length > 1) {
-      key = scope.buildTypeAnnotation(node.typeArguments.arguments[0]);
-      value = scope.buildTypeAnnotation(node.typeArguments.arguments[1]);
-    } else {
-      key = scope.getInferredTypeArgument(node, 0);
-      value = scope.getInferredTypeArgument(node, 1);
-    }
-    return new ast.MapLiteral(node.entries.map(buildMapEntry).toList(),
-        keyType: key, valueType: value, isConst: node.constKeyword != null);
-  }
-
-  ast.MapEntry buildMapEntry(MapLiteralEntry node) {
-    return new ast.MapEntry(build(node.key), build(node.value));
-  }
-
-  ast.Expression visitExpression(Expression node) {
-    return scope.internalError('Unhandled expression ${node.runtimeType}');
-  }
-}
-
-class StringLiteralPartBuilder extends GeneralizingAstVisitor<Null> {
-  final ExpressionScope scope;
-  final List<ast.Expression> output;
-  StringLiteralPartBuilder(this.scope, this.output);
-
-  void build(Expression node) {
-    node.accept(this);
-  }
-
-  void buildInterpolationElement(InterpolationElement node) {
-    node.accept(this);
-  }
-
-  visitSimpleStringLiteral(SimpleStringLiteral node) {
-    output.add(new ast.StringLiteral(node.value));
-  }
-
-  visitAdjacentStrings(AdjacentStrings node) {
-    node.strings.forEach(build);
-  }
-
-  visitStringInterpolation(StringInterpolation node) {
-    node.elements.forEach(buildInterpolationElement);
-  }
-
-  visitInterpolationString(InterpolationString node) {
-    output.add(new ast.StringLiteral(node.value));
-  }
-
-  visitInterpolationExpression(InterpolationExpression node) {
-    output.add(scope.buildExpression(node.expression));
-  }
-}
-
-class TypeAnnotationBuilder extends GeneralizingAstVisitor<ast.DartType> {
-  final TypeScope scope;
-
-  TypeAnnotationBuilder(this.scope);
-
-  ast.DartType build(AstNode node) {
-    return node.accept(this);
-  }
-
-  List<ast.DartType> buildList(Iterable<AstNode> node) {
-    return node.map(build).toList();
-  }
-
-  /// Replace unbound type variables in [type] with 'dynamic' and convert
-  /// to an [ast.DartType].
-  ast.DartType buildClosedTypeFromDartType(DartType type) {
-    return convertType(type, <TypeParameterElement>[]);
-  }
-
-  /// Convert to an [ast.DartType] and keep type variables.
-  ast.DartType buildFromDartType(DartType type) {
-    return convertType(type, null);
-  }
-
-  /// True if [parameter] should not be reified, because spec mode does not
-  /// currently reify generic method type parameters.
-  bool isUnreifiedTypeParameter(TypeParameterElement parameter) {
-    return !scope.strongMode && parameter.enclosingElement is! ClassElement;
-  }
-
-  /// Converts [type] to an [ast.DartType], while replacing unbound type
-  /// variables with 'dynamic'.
-  ///
-  /// If [boundVariables] is null, no type variables are replaced, otherwise all
-  /// type variables except those in [boundVariables] are replaced.  In other
-  /// words, it represents the bound variables, or "all variables" if omitted.
-  ast.DartType convertType(
-      DartType type, List<TypeParameterElement> boundVariables) {
-    if (type is TypeParameterType) {
-      if (isUnreifiedTypeParameter(type.element)) {
-        return const ast.DynamicType();
-      }
-      if (boundVariables == null || boundVariables.contains(type)) {
-        var typeParameter = scope.tryGetTypeParameterReference(type.element);
-        if (typeParameter == null) {
-          // The analyzer sometimes gives us a type parameter that was not
-          // bound anywhere.  Make sure we do not emit a dangling reference.
-          if (type.element.bound != null) {
-            return convertType(type.element.bound, []);
-          }
-          return const ast.DynamicType();
-        }
-        if (!scope.allowClassTypeParameters &&
-            typeParameter.parent is ast.Class) {
-          return const ast.InvalidType();
-        }
-        return new ast.TypeParameterType(typeParameter);
-      } else {
-        return const ast.DynamicType();
-      }
-    } else if (type is InterfaceType) {
-      var classNode = scope.getClassReference(type.element);
-      if (type.typeArguments.length == 0) {
-        return classNode.rawType;
-      }
-      if (type.typeArguments.length != classNode.typeParameters.length) {
-        log.warning('Type parameter arity error in $type');
-        return const ast.InvalidType();
-      }
-      return new ast.InterfaceType(
-          classNode, convertTypeList(type.typeArguments, boundVariables));
-    } else if (type is FunctionType) {
-      // TODO: Avoid infinite recursion in case of illegal circular typedef.
-      boundVariables?.addAll(type.typeParameters);
-      var positionals =
-          concatenate(type.normalParameterTypes, type.optionalParameterTypes);
-      var result = new ast.FunctionType(
-          convertTypeList(positionals, boundVariables),
-          convertType(type.returnType, boundVariables),
-          typeParameters:
-              convertTypeParameterList(type.typeFormals, boundVariables),
-          namedParameters:
-              convertTypeMap(type.namedParameterTypes, boundVariables),
-          requiredParameterCount: type.normalParameterTypes.length);
-      boundVariables?.removeRange(
-          boundVariables.length - type.typeParameters.length,
-          boundVariables.length);
-      return result;
-    } else if (type.isUndefined) {
-      log.warning('Unresolved type found in ${scope.location}');
-      return const ast.InvalidType();
-    } else if (type.isVoid) {
-      return const ast.VoidType();
-    } else if (type.isDynamic) {
-      return const ast.DynamicType();
-    } else {
-      log.severe('Unexpected DartType: $type');
-      return const ast.InvalidType();
-    }
-  }
-
-  static Iterable<E> concatenate<E>(Iterable<E> x, Iterable<E> y) =>
-      <Iterable<E>>[x, y].expand((z) => z);
-
-  ast.TypeParameter convertTypeParameter(TypeParameterElement typeParameter,
-      List<TypeParameterElement> boundVariables) {
-    return scope.makeTypeParameter(typeParameter,
-        bound: typeParameter.bound == null
-            ? scope.defaultTypeParameterBound
-            : convertType(typeParameter.bound, boundVariables));
-  }
-
-  List<ast.TypeParameter> convertTypeParameterList(
-      Iterable<TypeParameterElement> typeParameters,
-      List<TypeParameterElement> boundVariables) {
-    if (typeParameters.isEmpty) return const <ast.TypeParameter>[];
-    return typeParameters
-        .map((tp) => convertTypeParameter(tp, boundVariables))
-        .toList();
-  }
-
-  List<ast.DartType> convertTypeList(
-      Iterable<DartType> types, List<TypeParameterElement> boundVariables) {
-    if (types.isEmpty) return const <ast.DartType>[];
-    return types.map((t) => convertType(t, boundVariables)).toList();
-  }
-
-  List<ast.NamedType> convertTypeMap(
-      Map<String, DartType> types, List<TypeParameterElement> boundVariables) {
-    if (types.isEmpty) return const <ast.NamedType>[];
-    List<ast.NamedType> result = <ast.NamedType>[];
-    types.forEach((name, type) {
-      result.add(new ast.NamedType(name, convertType(type, boundVariables)));
-    });
-    sortAndRemoveDuplicates(result);
-    return result;
-  }
-
-  ast.DartType visitSimpleIdentifier(SimpleIdentifier node) {
-    Element element = node.staticElement;
-    switch (ElementKind.of(element)) {
-      case ElementKind.CLASS:
-        return scope.getClassReference(element).rawType;
-
-      case ElementKind.DYNAMIC:
-        return const ast.DynamicType();
-
-      case ElementKind.FUNCTION_TYPE_ALIAS:
-        FunctionTypeAliasElement functionType = element;
-        return buildClosedTypeFromDartType(functionType.type);
-
-      case ElementKind.TYPE_PARAMETER:
-        var typeParameter = scope.getTypeParameterReference(element);
-        if (!scope.allowClassTypeParameters &&
-            typeParameter.parent is ast.Class) {
-          return const ast.InvalidType();
-        }
-        if (isUnreifiedTypeParameter(element)) {
-          return const ast.DynamicType();
-        }
-        return new ast.TypeParameterType(typeParameter);
-
-      case ElementKind.COMPILATION_UNIT:
-      case ElementKind.CONSTRUCTOR:
-      case ElementKind.EXPORT:
-      case ElementKind.IMPORT:
-      case ElementKind.LABEL:
-      case ElementKind.LIBRARY:
-      case ElementKind.PREFIX:
-      case ElementKind.UNIVERSE:
-      case ElementKind.ERROR: // This covers the case where nothing was found.
-      case ElementKind.FIELD:
-      case ElementKind.TOP_LEVEL_VARIABLE:
-      case ElementKind.GETTER:
-      case ElementKind.SETTER:
-      case ElementKind.METHOD:
-      case ElementKind.LOCAL_VARIABLE:
-      case ElementKind.PARAMETER:
-      case ElementKind.FUNCTION:
-      case ElementKind.NAME:
-      default:
-        log.severe('Invalid type annotation: $element');
-        return const ast.InvalidType();
-    }
-  }
-
-  visitPrefixedIdentifier(PrefixedIdentifier node) {
-    return build(node.identifier);
-  }
-
-  visitTypeName(TypeName node) {
-    return buildFromDartType(node.type);
-  }
-
-  visitNode(AstNode node) {
-    log.severe('Unexpected type annotation: $node');
-    return new ast.InvalidType();
-  }
-}
-
-class InitializerBuilder extends GeneralizingAstVisitor<ast.Initializer> {
-  final MemberScope scope;
-
-  InitializerBuilder(this.scope);
-
-  ast.Initializer build(ConstructorInitializer node) {
-    return node.accept(this);
-  }
-
-  visitConstructorFieldInitializer(ConstructorFieldInitializer node) {
-    var target = scope.resolveField(node.fieldName.staticElement);
-    if (target == null) {
-      return new ast.InvalidInitializer();
-    }
-    return new ast.FieldInitializer(
-        target, scope.buildExpression(node.expression));
-  }
-
-  visitSuperConstructorInvocation(SuperConstructorInvocation node) {
-    var target = scope.resolveConstructor(node.staticElement);
-    if (target == null) {
-      return new ast.InvalidInitializer();
-    }
-    scope.addTransformerFlag(TransformerFlag.superCalls);
-    return new ast.SuperInitializer(
-        target, scope._expressionBuilder.buildArguments(node.argumentList));
-  }
-
-  visitRedirectingConstructorInvocation(RedirectingConstructorInvocation node) {
-    var target = scope.resolveConstructor(node.staticElement);
-    if (target == null) {
-      return new ast.InvalidInitializer();
-    }
-    return new ast.RedirectingInitializer(
-        target, scope._expressionBuilder.buildArguments(node.argumentList));
-  }
-
-  visitNode(AstNode node) {
-    log.severe('Unexpected constructor initializer: ${node.runtimeType}');
-    return new ast.InvalidInitializer();
-  }
-}
-
-/// A utility to build a function with a static error in its body.
-ast.FunctionNode _brokenFunction() {
-  return new ast.FunctionNode(
-      new ast.ExpressionStatement(new ast.InvalidExpression(null)));
-}
-
-/// Brings a class from hierarchy level to body level.
-//
-// TODO(asgerf): Error recovery during class construction is currently handled
-//   locally, but this can in theory break global invariants in the kernel IR.
-//   To safely compile code with compile-time errors, we may need a recovery
-//   pass to enforce all kernel invariants before it is given to the backend.
-class ClassBodyBuilder extends GeneralizingAstVisitor<Null> {
-  final ClassScope scope;
-  final ExpressionScope annotationScope;
-  final ast.Class currentClass;
-  final ClassElement element;
-  ast.Library get currentLibrary => currentClass.enclosingLibrary;
-
-  ClassBodyBuilder(
-      ReferenceLevelLoader loader, ast.Class currentClass, this.element)
-      : this.currentClass = currentClass,
-        scope = new ClassScope(loader, currentClass.enclosingLibrary),
-        annotationScope =
-            new ExpressionScope(loader, currentClass.enclosingLibrary);
-
-  void build(CompilationUnitMember node) {
-    if (node == null) {
-      buildBrokenClass();
-      return;
-    }
-    node.accept(this);
-  }
-
-  /// Builds an empty class for broken classes that have no AST.
-  ///
-  /// This should only be used to recover from a compile-time error.
-  void buildBrokenClass() {
-    currentClass.name = element.name;
-    currentClass.supertype = scope.getRootClassReference().asRawSupertype;
-    currentClass.constructors.add(new ast.Constructor(_brokenFunction())
-      ..fileOffset = element.nameOffset);
-  }
-
-  void addAnnotations(List<Annotation> annotations) {
-    // Class type parameters are not in scope in the annotation list.
-    for (var annotation in annotations) {
-      currentClass.addAnnotation(annotationScope.buildAnnotation(annotation));
-    }
-  }
-
-  void _buildMemberBody(ast.Member member, Element element, AstNode node) {
-    new MemberBodyBuilder(scope.loader, member, element).build(node);
-  }
-
-  /// True if the given class member should not be emitted, and does not
-  /// correspond to any Kernel member.
-  ///
-  /// This is true for redirecting factories with a resolved target. These are
-  /// always bypassed at the call site.
-  bool _isIgnoredMember(ClassMember node) {
-    if (node is ConstructorDeclaration && node.factoryKeyword != null) {
-      var element = resolutionMap.elementDeclaredByConstructorDeclaration(node);
-      return element.redirectedConstructor != null &&
-          (element.isSynthetic || scope.loader.ignoreRedirectingFactories);
-    } else {
-      return false;
-    }
-  }
-
-  visitClassDeclaration(ClassDeclaration node) {
-    addAnnotations(node.metadata);
-    ast.Class classNode = currentClass;
-    assert(classNode.members.isEmpty); // All members will be added here.
-
-    bool foundConstructor = false;
-    for (var member in node.members) {
-      if (_isIgnoredMember(member)) continue;
-      if (member is FieldDeclaration) {
-        for (var variable in member.fields.variables) {
-          // Ignore fields inserted through error recovery.
-          if (variable.isSynthetic || variable.length == 0) continue;
-          var field = scope.getMemberReference(variable.element);
-          classNode.addMember(field);
-          _buildMemberBody(field, variable.element, variable);
-        }
-      } else {
-        var memberNode = scope.getMemberReference(member.element);
-        classNode.addMember(memberNode);
-        _buildMemberBody(memberNode, member.element, member);
-        if (member is ConstructorDeclaration) {
-          foundConstructor = true;
-        }
-      }
-    }
-
-    if (!foundConstructor) {
-      var defaultConstructor = scope.findDefaultConstructor(node.element);
-      if (defaultConstructor != null) {
-        assert(defaultConstructor.enclosingElement == node.element);
-        if (!defaultConstructor.isSynthetic) {
-          throw 'Non-synthetic default constructor not in list of members. '
-              '$node $element $defaultConstructor';
-        }
-        var memberNode = scope.getMemberReference(defaultConstructor);
-        classNode.addMember(memberNode);
-        buildDefaultConstructor(memberNode, defaultConstructor);
-      }
-    }
-
-    addDefaultInstanceFieldInitializers(classNode);
-  }
-
-  void buildDefaultConstructor(
-      ast.Constructor constructor, ConstructorElement element) {
-    var function = constructor.function;
-    function.body = new ast.EmptyStatement()..parent = function;
-    var class_ = element.enclosingElement;
-    if (class_.supertype != null) {
-      // DESIGN TODO: If the super class is a mixin application, we will link to
-      // a constructor not in the immediate super class.  This is a problem due
-      // to the fact that mixed-in fields come with initializers which need to
-      // be executed by a constructor.  The mixin transformer takes care of
-      // this by making forwarding constructors and the super initializers will
-      // be rewritten to use them (see `transformations/mixin_full_resolution`).
-      var superConstructor =
-          scope.findDefaultConstructor(class_.supertype.element);
-      var target = scope.resolveConstructor(superConstructor);
-      if (target == null) {
-        constructor.initializers
-            .add(new ast.InvalidInitializer()..parent = constructor);
-      } else {
-        var arguments = new ast.Arguments.empty();
-        constructor.initializers.add(
-            new ast.SuperInitializer(target, arguments)..parent = constructor);
-      }
-    }
-  }
-
-  /// Adds initializers to instance fields that are have no initializer and are
-  /// not initialized by all constructors in the class.
-  void addDefaultInstanceFieldInitializers(ast.Class node) {
-    List<ast.Field> uninitializedFields = new List<ast.Field>();
-    for (var field in node.fields) {
-      if (field.initializer != null || field.isStatic) continue;
-      uninitializedFields.add(field);
-    }
-    if (uninitializedFields.isEmpty) return;
-    constructorLoop:
-    for (var constructor in node.constructors) {
-      var remainingFields = uninitializedFields.toSet();
-      for (var initializer in constructor.initializers) {
-        if (initializer is ast.FieldInitializer) {
-          remainingFields.remove(initializer.field);
-        } else if (initializer is ast.RedirectingInitializer) {
-          // The target constructor will be checked in another iteration.
-          continue constructorLoop;
-        }
-      }
-      for (var field in remainingFields) {
-        if (field.initializer == null) {
-          field.initializer = new ast.NullLiteral()..parent = field;
-        }
-      }
-    }
-  }
-
-  /// True for the `values` field of an `enum` class.
-  static bool _isValuesField(FieldElement field) => field.name == 'values';
-
-  /// True for the `index` field of an `enum` class.
-  static bool _isIndexField(FieldElement field) => field.name == 'index';
-
-  visitEnumDeclaration(EnumDeclaration node) {
-    addAnnotations(node.metadata);
-    ast.Class classNode = currentClass;
-
-    var intType = scope.loader.getCoreClassReference('int').rawType;
-    var indexFieldElement = element.fields.firstWhere(_isIndexField);
-    ast.Field indexField = scope.getMemberReference(indexFieldElement);
-    indexField.type = intType;
-    classNode.addMember(indexField);
-
-    var stringType = scope.loader.getCoreClassReference('String').rawType;
-    ast.Field nameField = new ast.Field(
-        new ast.Name('_name', scope.currentLibrary),
-        type: stringType,
-        isFinal: true,
-        fileUri: classNode.fileUri);
-    classNode.addMember(nameField);
-
-    var indexParameter = new ast.VariableDeclaration('index', type: intType);
-    var nameParameter = new ast.VariableDeclaration('name', type: stringType);
-    var function = new ast.FunctionNode(new ast.EmptyStatement(),
-        positionalParameters: [indexParameter, nameParameter]);
-    var superConstructor = scope.loader.getRootClassConstructorReference();
-    var constructor = new ast.Constructor(function,
-        name: new ast.Name(''),
-        isConst: true,
-        initializers: [
-          new ast.FieldInitializer(
-              indexField, new ast.VariableGet(indexParameter)),
-          new ast.FieldInitializer(
-              nameField, new ast.VariableGet(nameParameter)),
-          new ast.SuperInitializer(superConstructor, new ast.Arguments.empty())
-        ])
-      ..fileOffset = element.nameOffset;
-    classNode.addMember(constructor);
-
-    int index = 0;
-    var enumConstantFields = <ast.Field>[];
-    for (var constant in node.constants) {
-      ast.Field field = scope.getMemberReference(constant.element);
-      field.initializer = new ast.ConstructorInvocation(
-          constructor,
-          new ast.Arguments([
-            new ast.IntLiteral(index),
-            new ast.StringLiteral('${classNode.name}.${field.name.name}')
-          ]),
-          isConst: true)
-        ..parent = field;
-      field.type = classNode.rawType;
-      classNode.addMember(field);
-      ++index;
-      enumConstantFields.add(field);
-    }
-
-    // Add the 'values' field.
-    var valuesFieldElement = element.fields.firstWhere(_isValuesField);
-    ast.Field valuesField = scope.getMemberReference(valuesFieldElement);
-    var enumType = classNode.rawType;
-    valuesField.type = new ast.InterfaceType(
-        scope.loader.getCoreClassReference('List'), <ast.DartType>[enumType]);
-    valuesField.initializer = new ast.ListLiteral(
-        enumConstantFields.map(_makeStaticGet).toList(),
-        isConst: true,
-        typeArgument: enumType)
-      ..parent = valuesField;
-    classNode.addMember(valuesField);
-
-    // Add the 'toString()' method.
-    var body = new ast.ReturnStatement(
-        new ast.DirectPropertyGet(new ast.ThisExpression(), nameField));
-    var toStringFunction = new ast.FunctionNode(body, returnType: stringType);
-    var toStringMethod = new ast.Procedure(
-        new ast.Name('toString'), ast.ProcedureKind.Method, toStringFunction,
-        fileUri: classNode.fileUri);
-    classNode.addMember(toStringMethod);
-  }
-
-  visitClassTypeAlias(ClassTypeAlias node) {
-    addAnnotations(node.metadata);
-    assert(node.withClause != null && node.withClause.mixinTypes.isNotEmpty);
-    ast.Class classNode = currentClass;
-    for (var constructor in element.constructors) {
-      var constructorNode = scope.getMemberReference(constructor);
-      classNode.addMember(constructorNode);
-      buildMixinConstructor(constructorNode, constructor);
-    }
-  }
-
-  void buildMixinConstructor(
-      ast.Constructor constructor, ConstructorElement element) {
-    var function = constructor.function;
-    function.body = new ast.EmptyStatement()..parent = function;
-    // Call the corresponding constructor in super class.
-    ClassElement classElement = element.enclosingElement;
-    var targetConstructor = classElement.supertype.element.constructors
-        .firstWhere((c) => c.name == element.name);
-    var positionalArguments = constructor.function.positionalParameters
-        .map(_makeVariableGet)
-        .toList();
-    var namedArguments = constructor.function.namedParameters
-        .map(_makeNamedExpressionFrom)
-        .toList();
-    constructor.initializers.add(new ast.SuperInitializer(
-        scope.getMemberReference(targetConstructor),
-        new ast.Arguments(positionalArguments, named: namedArguments))
-      ..parent = constructor);
-  }
-
-  visitNode(AstNode node) {
-    throw 'Unsupported class declaration: ${node.runtimeType}';
-  }
-}
-
-/// Brings a member from reference level to body level.
-class MemberBodyBuilder extends GeneralizingAstVisitor<Null> {
-  final MemberScope scope;
-  final Element element;
-  ast.Member get currentMember => scope.currentMember;
-
-  MemberBodyBuilder(
-      ReferenceLevelLoader loader, ast.Member member, this.element)
-      : scope = new MemberScope(loader, member);
-
-  void build(AstNode node) {
-    if (node != null) {
-      currentMember.fileEndOffset = node.endToken.offset;
-      node.accept(this);
-    } else {
-      buildBrokenMember();
-    }
-  }
-
-  /// Builds an empty member.
-  ///
-  /// This should only be used to recover from a compile-time error.
-  void buildBrokenMember() {
-    var member = currentMember;
-    member.name = new ast.Name(element.name, scope.currentLibrary);
-    if (member is ast.Procedure) {
-      member.function = _brokenFunction()..parent = member;
-    } else if (member is ast.Constructor) {
-      member.function = _brokenFunction()..parent = member;
-    }
-  }
-
-  void addAnnotations(List<Annotation> annotations) {
-    for (var annotation in annotations) {
-      currentMember.addAnnotation(scope.buildAnnotation(annotation));
-    }
-  }
-
-  void handleNativeBody(FunctionBody body) {
-    if (body is NativeFunctionBody) {
-      currentMember.isExternal = true;
-      currentMember.addAnnotation(new ast.ConstructorInvocation(
-          scope.loader.getCoreClassConstructorReference('ExternalName',
-              library: 'dart:_internal'),
-          new ast.Arguments(<ast.Expression>[
-            new ast.StringLiteral(body.stringLiteral.stringValue)
-          ]),
-          isConst: true));
-    }
-  }
-
-  visitConstructorDeclaration(ConstructorDeclaration node) {
-    if (node.factoryKeyword != null) {
-      buildFactoryConstructor(node);
-    } else {
-      buildGenerativeConstructor(node);
-    }
-  }
-
-  void buildGenerativeConstructor(ConstructorDeclaration node) {
-    if (currentMember is! ast.Constructor) {
-      buildBrokenMember();
-      return;
-    }
-    addAnnotations(node.metadata);
-    ast.Constructor constructor = currentMember;
-    constructor.function = scope.buildFunctionNode(node.parameters, node.body,
-        inferredReturnType: const ast.VoidType())
-      ..parent = constructor;
-    handleNativeBody(node.body);
-    if (node.body is EmptyFunctionBody && !constructor.isExternal) {
-      var function = constructor.function;
-      function.body = new ast.EmptyStatement()..parent = function;
-    }
-    for (var parameter in node.parameters.parameterElements) {
-      if (parameter is FieldFormalParameterElement) {
-        ast.Initializer initializer;
-        if (parameter.field == null) {
-          initializer = new ast.LocalInitializer(
-              new ast.VariableDeclaration.forValue(scope
-                  .buildThrowCompileTimeErrorFromCode(
-                      CompileTimeErrorCode.INITIALIZER_FOR_NON_EXISTENT_FIELD,
-                      [parameter.name])));
-        } else {
-          initializer = new ast.FieldInitializer(
-              scope.getMemberReference(parameter.field),
-              new ast.VariableGet(scope.getVariableReference(parameter)));
-        }
-        constructor.initializers.add(initializer..parent = constructor);
-      }
-    }
-    bool hasExplicitConstructorCall = false;
-    for (var initializer in node.initializers) {
-      var node = scope.buildInitializer(initializer);
-      constructor.initializers.add(node..parent = constructor);
-      if (node is ast.SuperInitializer || node is ast.RedirectingInitializer) {
-        hasExplicitConstructorCall = true;
-      }
-    }
-    ClassElement classElement = resolutionMap
-        .elementDeclaredByConstructorDeclaration(node)
-        .enclosingElement;
-    if (classElement.supertype != null && !hasExplicitConstructorCall) {
-      ConstructorElement targetElement =
-          scope.findDefaultConstructor(classElement.supertype.element);
-      ast.Constructor target = scope.resolveConstructor(targetElement);
-      ast.Initializer initializer = target == null
-          ? new ast.InvalidInitializer()
-          : new ast.SuperInitializer(
-              target, new ast.Arguments(<ast.Expression>[]));
-      constructor.initializers.add(initializer..parent = constructor);
-    } else {
-      moveSuperInitializerLast(constructor);
-    }
-  }
-
-  void buildFactoryConstructor(ConstructorDeclaration node) {
-    if (currentMember is! ast.Procedure) {
-      buildBrokenMember();
-      return;
-    }
-    addAnnotations(node.metadata);
-    ast.Procedure procedure = currentMember;
-    ClassElement classElement = resolutionMap
-        .elementDeclaredByConstructorDeclaration(node)
-        .enclosingElement;
-    ast.Class classNode = procedure.enclosingClass;
-    var types = getFreshTypeParameters(classNode.typeParameters);
-    for (int i = 0; i < classElement.typeParameters.length; ++i) {
-      scope.localTypeParameters[classElement.typeParameters[i]] =
-          types.freshTypeParameters[i];
-    }
-    var inferredReturnType = types.freshTypeParameters.isEmpty
-        ? classNode.rawType
-        : new ast.InterfaceType(
-            classNode,
-            types.freshTypeParameters
-                .map(makeTypeParameterType)
-                .toList(growable: false));
-    var function = scope.buildFunctionNode(node.parameters, node.body,
-        typeParameters: types.freshTypeParameters,
-        inferredReturnType: inferredReturnType);
-    procedure.function = function..parent = procedure;
-    handleNativeBody(node.body);
-    if (node.redirectedConstructor != null) {
-      // Add a new synthetic field to [classNode] for representing factory
-      // constructors. This is used by the new frontend engine to support
-      // resolving source code.
-      //
-      // The synthetic field looks like this:
-      //
-      //     final _redirecting# = [c1, ..., cn];
-      //
-      // Where each c1 ... cn are an instance of [StaticGet] whose target is
-      // the redirecting factory created above. The new frontend engine reads
-      // this field and rewrites them.
-      //
-      // TODO(ahe): Generate the correct factory body instead. This requires
-      // access to default values from other files, we'll probably never do
-      // that in this file, and instead rely on the new compiler for this.
-      var element = resolutionMap.elementDeclaredByConstructorDeclaration(node);
-      assert(!element.isSynthetic);
-      var expression;
-      if (node.element.redirectedConstructor != null) {
-        assert(!scope.loader.ignoreRedirectingFactories);
-        ConstructorElement element = node.element.redirectedConstructor;
-        while (element.isFactory && element.redirectedConstructor != null) {
-          element = element.redirectedConstructor;
-        }
-        ast.Member target = scope.getMemberReference(element);
-        assert(target != null);
-        expression = new ast.Let(
-            new ast.VariableDeclaration.forValue(new ast.StaticGet(target)),
-            new ast.InvalidExpression(null));
-        ast.Name constructors =
-            new ast.Name("_redirecting#", scope.currentLibrary);
-        ast.Field constructorsField;
-        for (ast.Field field in classNode.fields) {
-          if (field.name == constructors) {
-            constructorsField = field;
-            break;
-          }
-        }
-        if (constructorsField == null) {
-          ast.ListLiteral literal = new ast.ListLiteral(<ast.Expression>[]);
-          constructorsField = new ast.Field(constructors,
-              isStatic: true, initializer: literal, fileUri: classNode.fileUri)
-            ..fileOffset = classNode.fileOffset;
-          classNode.addMember(constructorsField);
-        }
-        ast.ListLiteral literal = constructorsField.initializer;
-        literal.expressions.add(new ast.StaticGet(procedure)..parent = literal);
-      } else {
-        var name = node.redirectedConstructor.type.name.name;
-        if (node.redirectedConstructor.name != null) {
-          name += '.' + node.redirectedConstructor.name.name;
-        }
-        // TODO(asgerf): Sometimes a TypeError should be thrown.
-        expression = scope.buildThrowNoSuchMethodError(
-            new ast.NullLiteral(), name, new ast.Arguments.empty());
-      }
-      var function = procedure.function;
-      function.body = new ast.ExpressionStatement(expression)
-        ..parent = function;
-    }
-  }
-
-  visitMethodDeclaration(MethodDeclaration node) {
-    addAnnotations(node.metadata);
-    ast.Procedure procedure = currentMember;
-    procedure.function = scope.buildFunctionNode(node.parameters, node.body,
-        returnType: node.returnType,
-        inferredReturnType: scope.buildType(
-            resolutionMap.elementDeclaredByMethodDeclaration(node).returnType),
-        typeParameters: scope.buildOptionalTypeParameterList(
-            node.typeParameters,
-            strongModeOnly: true))
-      ..parent = procedure;
-    handleNativeBody(node.body);
-  }
-
-  visitVariableDeclaration(VariableDeclaration node) {
-    addAnnotations(node.metadata);
-    ast.Field field = currentMember;
-    field.type = scope.buildType(
-        resolutionMap.elementDeclaredByVariableDeclaration(node).type);
-    if (node.initializer != null) {
-      field.initializer = scope.buildTopLevelExpression(node.initializer)
-        ..parent = field;
-    } else if (field.isStatic) {
-      // Add null initializer to static fields without an initializer.
-      // For instance fields, this is handled when building the class.
-      field.initializer = new ast.NullLiteral()..parent = field;
-    }
-  }
-
-  visitFunctionDeclaration(FunctionDeclaration node) {
-    addAnnotations(node.metadata);
-    var function = node.functionExpression;
-    ast.Procedure procedure = currentMember;
-    procedure.function = scope.buildFunctionNode(
-        function.parameters, function.body,
-        returnType: node.returnType,
-        typeParameters: scope.buildOptionalTypeParameterList(
-            function.typeParameters,
-            strongModeOnly: true))
-      ..parent = procedure;
-    handleNativeBody(function.body);
-  }
-
-  visitNode(AstNode node) {
-    log.severe('Unexpected class or library member: $node');
-  }
-}
-
-/// Internal exception thrown from the expression or statement builder when a
-/// compilation error is found.
-///
-/// This is then caught at the function level to replace the entire function
-/// body (or field initializer) with a throw.
-class _CompilationError {
-  String message;
-
-  _CompilationError(this.message);
-}
-
-/// Constructor alias for [ast.TypeParameterType], use instead of a closure.
-ast.DartType makeTypeParameterType(ast.TypeParameter parameter) {
-  return new ast.TypeParameterType(parameter);
-}
-
-/// Constructor alias for [ast.VariableGet], use instead of a closure.
-ast.VariableGet _makeVariableGet(ast.VariableDeclaration variable) {
-  return new ast.VariableGet(variable);
-}
-
-/// Constructor alias for [ast.StaticGet], use instead of a closure.
-ast.StaticGet _makeStaticGet(ast.Field field) {
-  return new ast.StaticGet(field);
-}
-
-/// Create a named expression with the name and value of the given variable.
-ast.NamedExpression _makeNamedExpressionFrom(ast.VariableDeclaration variable) {
-  return new ast.NamedExpression(variable.name, new ast.VariableGet(variable));
-}
-
-/// A [StaticAccessor] that throws a NoSuchMethodError when a suitable target
-/// could not be resolved.
-class _StaticAccessor extends StaticAccessor {
-  final ExpressionScope scope;
-  final String name;
-
-  _StaticAccessor(
-      this.scope, this.name, ast.Member readTarget, ast.Member writeTarget)
-      : super(readTarget, writeTarget, ast.TreeNode.noOffset);
-
-  @override
-  makeInvalidRead() {
-    return scope.buildThrowNoSuchMethodError(
-        new ast.NullLiteral(), name, new ast.Arguments([]));
-  }
-
-  @override
-  makeInvalidWrite(ast.Expression value) {
-    return scope.buildThrowNoSuchMethodError(
-        new ast.NullLiteral(), name, new ast.Arguments([value]));
-  }
-}
-
-bool isTopLevelFunction(Element element) {
-  return element is FunctionElement &&
-      element.enclosingElement is CompilationUnitElement;
-}
-
-bool isLocalFunction(Element element) {
-  return element is FunctionElement &&
-      element.enclosingElement is! CompilationUnitElement &&
-      element.enclosingElement is! LibraryElement;
-}
-
-bool isLocal(Element element) {
-  return isLocalFunction(element) ||
-      element is LocalVariableElement ||
-      element is ParameterElement;
-}
-
-bool isInstanceMethod(Element element) {
-  return element is MethodElement && !element.isStatic;
-}
-
-bool isStaticMethod(Element element) {
-  return element is MethodElement && element.isStatic ||
-      isTopLevelFunction(element);
-}
-
-bool isStaticVariableOrGetter(Element element) {
-  element = desynthesizeGetter(element);
-  return element is FieldElement && element.isStatic ||
-      element is TopLevelVariableElement;
-}
-
-Element desynthesizeGetter(Element element) {
-  if (element == null || !element.isSynthetic) return element;
-  if (element is PropertyAccessorElement) return element.variable;
-  if (element is FieldElement) return element.getter;
-  return element;
-}
-
-Element desynthesizeSetter(Element element) {
-  if (element == null || !element.isSynthetic) return element;
-  if (element is PropertyAccessorElement) return element.variable;
-  if (element is FieldElement) return element.setter;
-  return element;
-}
-
-void sortAndRemoveDuplicates<T extends Comparable<T>>(List<T> list) {
-  list.sort();
-  int deleted = 0;
-  for (int i = 1; i < list.length; ++i) {
-    var item = list[i];
-    if (list[i - 1].compareTo(item) == 0) {
-      ++deleted;
-    } else if (deleted > 0) {
-      list[i - deleted] = item;
-    }
-  }
-  if (deleted > 0) {
-    list.length -= deleted;
-  }
-}
diff --git a/pkg/analyzer/lib/src/kernel/loader.dart b/pkg/analyzer/lib/src/kernel/loader.dart
deleted file mode 100644
index 73dd076..0000000
--- a/pkg/analyzer/lib/src/kernel/loader.dart
+++ /dev/null
@@ -1,1026 +0,0 @@
-// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-library kernel.analyzer.loader;
-
-import 'dart:async';
-import 'dart:convert';
-import 'dart:io' as io;
-
-import 'package:analyzer/analyzer.dart';
-import 'package:analyzer/dart/element/element.dart';
-import 'package:analyzer/dart/element/type.dart';
-import 'package:analyzer/file_system/file_system.dart';
-import 'package:analyzer/file_system/physical_file_system.dart';
-import 'package:analyzer/source/package_map_resolver.dart';
-import 'package:analyzer/src/dart/element/member.dart';
-import 'package:analyzer/src/dart/scanner/scanner.dart';
-import 'package:analyzer/src/dart/sdk/sdk.dart';
-import 'package:analyzer/src/generated/engine.dart';
-import 'package:analyzer/src/generated/parser.dart';
-import 'package:analyzer/src/generated/sdk.dart';
-import 'package:analyzer/src/generated/source_io.dart';
-import 'package:analyzer/src/summary/summary_sdk.dart';
-import 'package:kernel/application_root.dart';
-import 'package:package_config/discovery.dart';
-import 'package:package_config/packages.dart';
-
-import 'package:kernel/ast.dart' as ast;
-import 'package:kernel/target/targets.dart' show Target;
-import 'package:kernel/type_algebra.dart';
-import 'package:analyzer/src/kernel/ast_from_analyzer.dart';
-
-/// Options passed to the Dart frontend.
-class DartOptions {
-  /// True if user code should be loaded in strong mode.
-  bool strongMode;
-
-  /// True if the Dart SDK should be loaded in strong mode.
-  bool strongModeSdk;
-
-  /// Path to the sdk sources, ignored if sdkSummary is provided.
-  String sdk;
-
-  /// Path to a summary of the sdk sources.
-  String sdkSummary;
-
-  /// Path to the `.packages` file.
-  String packagePath;
-
-  /// Root used to relativize app file-urls, making them machine agnostic.
-  ApplicationRoot applicationRoot;
-
-  Map<Uri, Uri> customUriMappings;
-
-  /// Environment definitions provided via `-Dkey=value`.
-  Map<String, String> declaredVariables;
-
-  DartOptions(
-      {bool strongMode: false,
-      bool strongModeSdk,
-      this.sdk,
-      this.sdkSummary,
-      this.packagePath,
-      ApplicationRoot applicationRoot,
-      Map<Uri, Uri> customUriMappings,
-      Map<String, String> declaredVariables})
-      : this.customUriMappings = customUriMappings ?? <Uri, Uri>{},
-        this.declaredVariables = declaredVariables ?? <String, String>{},
-        this.strongMode = strongMode,
-        this.strongModeSdk = strongModeSdk ?? strongMode,
-        this.applicationRoot = applicationRoot ?? new ApplicationRoot.none();
-}
-
-abstract class ReferenceLevelLoader {
-  ast.Library getLibraryReference(LibraryElement element);
-  ast.Class getClassReference(ClassElement element);
-  ast.Member getMemberReference(Element element);
-  ast.Class getRootClassReference();
-  ast.Constructor getRootClassConstructorReference();
-  ast.Class getCoreClassReference(String className);
-  ast.Constructor getCoreClassConstructorReference(String className,
-      {String constructorName, String library});
-  ast.TypeParameter tryGetClassTypeParameter(TypeParameterElement element);
-  ast.Class getSharedMixinApplicationClass(
-      ast.Library library, ast.Class supertype, ast.Class mixin);
-  bool get strongMode;
-
-  /// Whether or not to include redirecting factories in the output.
-  bool get ignoreRedirectingFactories;
-}
-
-class DartLoader implements ReferenceLevelLoader {
-  final ast.Component component;
-  final ApplicationRoot applicationRoot;
-  final Bimap<ClassElement, ast.Class> _classes =
-      new Bimap<ClassElement, ast.Class>();
-  final Bimap<Element, ast.Member> _members = new Bimap<Element, ast.Member>();
-  final Map<TypeParameterElement, ast.TypeParameter> _classTypeParameters =
-      <TypeParameterElement, ast.TypeParameter>{};
-  final Map<ast.Library, Map<String, ast.Class>> _mixinApplications =
-      <ast.Library, Map<String, ast.Class>>{};
-  final Map<LibraryElement, ast.Library> _libraries =
-      <LibraryElement, ast.Library>{};
-  final AnalysisContext context;
-  LibraryElement _dartCoreLibrary;
-  final List errors = [];
-  final List libraryElements = [];
-
-  /// Classes that have been referenced, and must be promoted to type level
-  /// so as not to expose partially initialized classes.
-  final List<ast.Class> temporaryClassWorklist = [];
-
-  final Map<LibraryElement, List<ClassElement>> mixinLibraryWorklist = {};
-
-  final bool ignoreRedirectingFactories;
-
-  LibraryElement _libraryBeingLoaded = null;
-  ClassElement _classBeingPromotedToMixin = null;
-
-  bool get strongMode => context.analysisOptions.strongMode;
-
-  DartLoader(this.component, DartOptions options, Packages packages,
-      {DartSdk dartSdk,
-      AnalysisContext context,
-      this.ignoreRedirectingFactories: true})
-      : this.context =
-            context ?? createContext(options, packages, dartSdk: dartSdk),
-        this.applicationRoot = options.applicationRoot;
-
-  String getLibraryName(LibraryElement element) {
-    return element.name.isEmpty ? null : element.name;
-  }
-
-  LibraryElement getLibraryElementFromUri(Uri uri) {
-    var source = context.sourceFactory.forUri2(uri);
-    if (source == null) return null;
-    return context.computeLibraryElement(source);
-  }
-
-  ast.Library getLibraryReference(LibraryElement element) {
-    var uri = applicationRoot.relativeUri(element.source.uri);
-    var library = _libraries[element];
-    if (library == null) {
-      library = new ast.Library(uri)
-        ..isExternal = true
-        ..name = getLibraryName(element)
-        ..fileUri = element.source.uri;
-      component.libraries.add(library..parent = component);
-      _libraries[element] = library;
-    }
-    return library;
-  }
-
-  ast.Library getLibraryReferenceFromUri(Uri uri) {
-    return getLibraryReference(getLibraryElementFromUri(uri));
-  }
-
-  void _buildTopLevelMember(
-      ast.Member member, Element element, Declaration astNode) {
-    assert(member.parent != null);
-    new MemberBodyBuilder(this, member, element).build(astNode);
-  }
-
-  /// True if [element] is in the process of being loaded by
-  /// [_buildLibraryBody].
-  ///
-  /// If this is the case, we should avoid adding new members to the classes
-  /// in the library, since the AST builder will rebuild the member lists.
-  bool isLibraryBeingLoaded(LibraryElement element) {
-    return _libraryBeingLoaded == element;
-  }
-
-  bool isClassBeingPromotedToMixin(ClassElement element) {
-    return _classBeingPromotedToMixin == element;
-  }
-
-  void _buildLibraryBody(LibraryElement element, ast.Library library,
-      List<CompilationUnit> units) {
-    assert(_libraryBeingLoaded == null);
-    _libraryBeingLoaded = element;
-    var classes = <ast.Class>[];
-    var procedures = <ast.Procedure>[];
-    var fields = <ast.Field>[];
-
-    void loadClass(NamedCompilationUnitMember declaration) {
-      // [declaration] can be a ClassDeclaration, EnumDeclaration, or a
-      // ClassTypeAlias.
-      ClassElement element = declaration.element;
-      var node = getClassReference(element);
-      promoteToBodyLevel(node, element, declaration);
-      classes.add(node);
-    }
-
-    void loadProcedure(FunctionDeclaration declaration) {
-      var element = declaration.element;
-      var node = getMemberReference(element);
-      _buildTopLevelMember(node, element, declaration);
-      procedures.add(node);
-    }
-
-    void loadField(TopLevelVariableDeclaration declaration) {
-      for (var field in declaration.variables.variables) {
-        var element = field.element;
-        // Ignore fields inserted through error recovery.
-        if (element.name == '') continue;
-        var node = getMemberReference(element);
-        _buildTopLevelMember(node, element, field);
-        fields.add(node);
-      }
-    }
-
-    for (var unit in units) {
-      for (CompilationUnitMember declaration in unit.declarations) {
-        if (declaration is ClassDeclaration ||
-            declaration is EnumDeclaration ||
-            declaration is ClassTypeAlias) {
-          loadClass(declaration);
-        } else if (declaration is FunctionDeclaration) {
-          loadProcedure(declaration);
-        } else if (declaration is TopLevelVariableDeclaration) {
-          loadField(declaration);
-        } else if (declaration is FunctionTypeAlias) {
-          // Nothing to do. Typedefs are handled lazily while constructing type
-          // references.
-        } else {
-          throw "unexpected node: ${declaration.runtimeType} $declaration";
-        }
-      }
-    }
-    libraryElements.add(element);
-    _iterateTemporaryClassWorklist();
-    // Ensure everything is stored in the original declaration order.
-    library.classes
-      ..clear()
-      ..addAll(classes)
-      ..addAll(_mixinApplications[library]?.values ?? const []);
-    library.fields
-      ..clear()
-      ..addAll(fields);
-    library.procedures
-      ..clear()
-      ..addAll(procedures);
-    _libraryBeingLoaded = null;
-  }
-
-  LibraryElement getDartCoreLibrary() {
-    return _dartCoreLibrary ??= _findLibraryElement('dart:core');
-  }
-
-  LibraryElement _findLibraryElement(String uri) {
-    var source = context.sourceFactory.forUri(uri);
-    if (source == null) return null;
-    return context.computeLibraryElement(source);
-  }
-
-  ast.Class getRootClassReference() {
-    return getCoreClassReference('Object');
-  }
-
-  ast.Constructor getRootClassConstructorReference() {
-    var element = getDartCoreLibrary().getType('Object').constructors[0];
-    return getMemberReference(element);
-  }
-
-  ast.Class getCoreClassReference(String className) {
-    return getClassReference(getDartCoreLibrary().getType(className));
-  }
-
-  ast.Constructor getCoreClassConstructorReference(String className,
-      {String constructorName, String library}) {
-    LibraryElement libraryElement =
-        library != null ? _findLibraryElement(library) : getDartCoreLibrary();
-    ClassElement element = libraryElement.getType(className);
-    if (element == null) {
-      throw 'Missing core class $className from ${libraryElement.name}';
-    }
-    var constructor = element.constructors.firstWhere((constructor) {
-      return (constructorName == null)
-          ? (constructor.nameLength == 0)
-          : (constructor.name == constructorName);
-    });
-    return getMemberReference(constructor);
-  }
-
-  ClassElement getClassElement(ast.Class node) {
-    return _classes.inverse[node];
-  }
-
-  void addMixinClassToLibrary(ast.Class class_, ast.Library library) {
-    assert(class_.parent == null);
-    library.addClass(class_);
-    var map =
-        _mixinApplications.putIfAbsent(library, () => <String, ast.Class>{});
-    map[class_.name] = class_;
-  }
-
-  /// Returns the IR for a class, at a temporary loading level.
-  ///
-  /// The returned class has the correct name, flags, type parameter arity,
-  /// and enclosing library.
-  ast.Class getClassReference(ClassElement element) {
-    var classNode = _classes[element];
-    if (classNode != null) return classNode;
-    _classes[element] = classNode = new ast.Class(
-        name: element.name,
-        isAbstract: element.isAbstract,
-        fileUri: element.source.uri)
-      ..fileOffset = element.nameOffset;
-    classNode.level = ast.ClassLevel.Temporary;
-    var library = getLibraryReference(element.library);
-    library.addClass(classNode);
-    // Initialize type parameter list without bounds.
-    for (var parameter in element.typeParameters) {
-      var parameterNode = new ast.TypeParameter(parameter.name);
-      _classTypeParameters[parameter] = parameterNode;
-      classNode.typeParameters.add(parameterNode);
-      parameterNode.parent = classNode;
-    }
-    // Ensure the class is at least promoted to type level before exposing it
-    // to kernel consumers.
-    temporaryClassWorklist.add(classNode);
-    return classNode;
-  }
-
-  /// Ensures the supertypes and type parameter bounds have been generated for
-  /// the given class.
-  void promoteToTypeLevel(ast.Class classNode) {
-    if (classNode.level.index >= ast.ClassLevel.Type.index) return;
-    classNode.level = ast.ClassLevel.Type;
-    var element = getClassElement(classNode);
-    assert(element != null);
-    var library = getLibraryReference(element.library);
-    var scope = new ClassScope(this, library);
-    // Initialize bounds on type parameters.
-    for (int i = 0; i < classNode.typeParameters.length; ++i) {
-      var parameter = element.typeParameters[i];
-      var parameterNode = classNode.typeParameters[i];
-      parameterNode.bound = parameter.bound == null
-          ? scope.defaultTypeParameterBound
-          : scope.buildType(parameter.bound);
-    }
-    // Initialize supertypes.
-    Iterable<InterfaceType> mixins = element.mixins;
-    if (element.isMixinApplication && mixins.isNotEmpty) {
-      classNode.mixedInType = scope.buildSupertype(mixins.last);
-      mixins = mixins.take(mixins.length - 1);
-    }
-    if (element.supertype != null) {
-      ast.Supertype supertype = scope.buildSupertype(element.supertype);
-      bool useSharedMixin = true;
-      for (var mixin in mixins) {
-        var mixinType = scope.buildSupertype(mixin);
-        if (useSharedMixin &&
-            areDistinctUnboundTypeVariables(supertype, mixinType)) {
-          // Use a shared mixin application class for this library.
-          var mixinClass = getSharedMixinApplicationClass(
-              scope.currentLibrary, supertype.classNode, mixinType.classNode);
-          if (mixinClass.fileOffset < 0) {
-            mixinClass.fileOffset = element.nameOffset;
-          }
-          supertype = new ast.Supertype(
-              mixinClass,
-              supertype.typeArguments.length > mixinType.typeArguments.length
-                  ? supertype.typeArguments
-                  : mixinType.typeArguments);
-        } else {
-          // Generate a new class specific for this mixin application.
-          var freshParameters =
-              getFreshTypeParameters(classNode.typeParameters);
-          var mixinClass = new ast.Class(
-              name: '${classNode.name}^${mixinType.classNode.name}',
-              isAbstract: true,
-              typeParameters: freshParameters.freshTypeParameters,
-              supertype: freshParameters.substituteSuper(supertype),
-              mixedInType: freshParameters.substituteSuper(mixinType),
-              fileUri: classNode.fileUri)
-            ..fileOffset = element.nameOffset;
-          mixinClass.level = ast.ClassLevel.Type;
-          addMixinClassToLibrary(mixinClass, classNode.enclosingLibrary);
-          supertype = new ast.Supertype(mixinClass,
-              classNode.typeParameters.map(makeTypeParameterType).toList());
-          // This class cannot be used from anywhere else, so don't try to
-          // generate shared mixin applications using it.
-          useSharedMixin = false;
-        }
-      }
-      classNode.supertype = supertype;
-      for (var implementedType in element.interfaces) {
-        classNode.implementedTypes.add(scope.buildSupertype(implementedType));
-      }
-    }
-  }
-
-  void promoteToHierarchyLevel(ast.Class classNode) {
-    if (classNode.level.index >= ast.ClassLevel.Hierarchy.index) return;
-    promoteToTypeLevel(classNode);
-    classNode.level = ast.ClassLevel.Hierarchy;
-    var element = getClassElement(classNode);
-    if (element != null) {
-      // Ensure all instance members are at present.
-      for (var field in element.fields) {
-        if (!field.isStatic && !field.isSynthetic) {
-          getMemberReference(field);
-        }
-      }
-      for (var accessor in element.accessors) {
-        if (!accessor.isStatic && !accessor.isSynthetic) {
-          getMemberReference(accessor);
-        }
-      }
-      for (var method in element.methods) {
-        if (!method.isStatic && !method.isSynthetic) {
-          getMemberReference(method);
-        }
-      }
-    }
-    for (var supertype in classNode.supers) {
-      promoteToHierarchyLevel(supertype.classNode);
-    }
-  }
-
-  void promoteToMixinLevel(ast.Class classNode, ClassElement element,
-      NamedCompilationUnitMember astNode) {
-    if (classNode.level.index >= ast.ClassLevel.Mixin.index) return;
-    _classBeingPromotedToMixin = element;
-    promoteToHierarchyLevel(classNode);
-    classNode.level = ast.ClassLevel.Mixin;
-    // Clear out the member references that were put in the class.
-    // The AST builder will load them all put back in the right order.
-    classNode..fields.clear()..procedures.clear()..constructors.clear();
-    new ClassBodyBuilder(this, classNode, element).build(astNode);
-    _classBeingPromotedToMixin = null;
-
-    // Ensure mixed-in classes are available.
-    for (var mixin in element.mixins) {
-      _ensureMixinBecomesLoaded(mixin.element);
-    }
-  }
-
-  /// Ensures that [element] eventually becomes loaded at least at mixin level.
-  void _ensureMixinBecomesLoaded(ClassElement element) {
-    if (isClassBeingPromotedToMixin(element)) {
-      return;
-    }
-    var class_ = getClassReference(element);
-    if (class_.level.index >= ast.ClassLevel.Mixin.index) {
-      return;
-    }
-    var list = mixinLibraryWorklist[element.library] ??= <ClassElement>[];
-    list.add(element);
-  }
-
-  void promoteToBodyLevel(ast.Class classNode, ClassElement element,
-      NamedCompilationUnitMember astNode) {
-    if (classNode.level == ast.ClassLevel.Body) return;
-    promoteToMixinLevel(classNode, element, astNode);
-    classNode.level = ast.ClassLevel.Body;
-    // This frontend delivers the same contents for classes at body and mixin
-    // levels, even though as specified, the mixin level does not require all
-    // the static members to be present.  So no additional work is needed.
-  }
-
-  ast.TypeParameter tryGetClassTypeParameter(TypeParameterElement element) {
-    return _classTypeParameters[element];
-  }
-
-  Element getMemberElement(ast.Member node) {
-    return _members.inverse[node];
-  }
-
-  ast.Member getMemberReference(Element element) {
-    assert(element != null);
-    assert(element is! Member); // Use the "base element".
-    return _members[element] ??= _buildMemberReference(element);
-  }
-
-  ast.Member _buildMemberReference(Element element) {
-    assert(element != null);
-    var member = _buildOrphanedMemberReference(element);
-    // Set the parent pointer and store it in the enclosing class or library.
-    // If the enclosing library is being built from the AST, do not add the
-    // member, since the AST builder will put it in there.
-    var parent = element.enclosingElement;
-    if (parent is ClassElement) {
-      var class_ = getClassReference(parent);
-      member.parent = class_;
-      if (!isLibraryBeingLoaded(element.library)) {
-        class_.addMember(member);
-      }
-    } else {
-      var library = getLibraryReference(element.library);
-      member.parent = library;
-      if (!isLibraryBeingLoaded(element.library)) {
-        library.addMember(member);
-      }
-    }
-    return member;
-  }
-
-  ast.Member _buildOrphanedMemberReference(Element element) {
-    assert(element != null);
-    ClassElement classElement = element.enclosingElement is ClassElement
-        ? element.enclosingElement
-        : null;
-    TypeScope scope = classElement != null
-        ? new ClassScope(this, getLibraryReference(element.library))
-        : new TypeScope(this);
-    if (classElement != null) {
-      getClassReference(classElement);
-    }
-    switch (element.kind) {
-      case ElementKind.CONSTRUCTOR:
-        ConstructorElement constructor = element;
-        if (constructor.isFactory) {
-          return new ast.Procedure(
-              _nameOfMember(constructor),
-              ast.ProcedureKind.Factory,
-              scope.buildFunctionInterface(constructor),
-              isAbstract: false,
-              isStatic: true,
-              isExternal: constructor.isExternal,
-              isConst: constructor.isConst,
-              fileUri: element.source.uri)
-            ..fileOffset = element.nameOffset;
-        }
-        return new ast.Constructor(scope.buildFunctionInterface(constructor),
-            name: _nameOfMember(element),
-            isConst: constructor.isConst,
-            isExternal: constructor.isExternal,
-            isSynthetic: constructor.isSynthetic)
-          ..fileOffset = element.nameOffset;
-
-      case ElementKind.FIELD:
-      case ElementKind.TOP_LEVEL_VARIABLE:
-        VariableElement variable = element;
-        return new ast.Field(_nameOfMember(variable),
-            isStatic: variable.isStatic,
-            isFinal: variable.isFinal,
-            isConst: variable.isConst,
-            type: scope.buildType(variable.type),
-            fileUri: element.source.uri)
-          ..fileOffset = element.nameOffset;
-
-      case ElementKind.METHOD:
-      case ElementKind.GETTER:
-      case ElementKind.SETTER:
-      case ElementKind.FUNCTION:
-        if (element is FunctionElement &&
-            element.enclosingElement is! CompilationUnitElement) {
-          throw 'Function $element is nested in ${element.enclosingElement} '
-              'and hence is not a member';
-        }
-        ExecutableElement executable = element;
-        return new ast.Procedure(
-            _nameOfMember(element),
-            _procedureKindOf(executable),
-            scope.buildFunctionInterface(executable),
-            isAbstract: executable.isAbstract,
-            isStatic: executable.isStatic,
-            isExternal: executable.isExternal,
-            fileUri: element.source.uri)
-          ..fileOffset = element.nameOffset;
-
-      default:
-        throw 'Unexpected member kind: $element';
-    }
-  }
-
-  ast.ProcedureKind _procedureKindOf(ExecutableElement element) {
-    if (element is PropertyAccessorElement) {
-      return element.isGetter
-          ? ast.ProcedureKind.Getter
-          : ast.ProcedureKind.Setter;
-    }
-    if (element is MethodElement) {
-      if (element.isOperator) return ast.ProcedureKind.Operator;
-      return ast.ProcedureKind.Method;
-    }
-    if (element is FunctionElement) {
-      return ast.ProcedureKind.Method;
-    }
-    if (element is ConstructorElement) {
-      assert(element.isFactory);
-      return ast.ProcedureKind.Factory;
-    }
-    throw 'Unexpected procedure: $element';
-  }
-
-  ast.Name _nameOfMember(Element element) {
-    // Use 'displayName' to avoid a trailing '=' for setters and 'name' to
-    // ensure unary minus is called 'unary-'.
-    String name =
-        element is PropertyAccessorElement ? element.displayName : element.name;
-    return new ast.Name(name, getLibraryReference(element.library));
-  }
-
-  /// True if the two types have form `C<T1 ... Tm>` and `D<T1 ... Tn>`, and
-  /// `T1 ... TN` are distinct type variables with no upper bound, where
-  /// `N = max(m,n)`.
-  bool areDistinctUnboundTypeVariables(
-      ast.Supertype first, ast.Supertype second) {
-    var seen = new Set<ast.TypeParameter>();
-    if (first.typeArguments.length < second.typeArguments.length) {
-      var tmp = first;
-      first = second;
-      second = tmp;
-    }
-    for (int i = 0; i < first.typeArguments.length; ++i) {
-      var firstArg = first.typeArguments[i];
-      if (!(firstArg is ast.TypeParameterType &&
-          seen.add(firstArg.parameter) &&
-          firstArg.parameter.bound is ast.DynamicType)) {
-        return false;
-      }
-      if (i < second.typeArguments.length &&
-          firstArg != second.typeArguments[i]) {
-        return false;
-      }
-    }
-    return true;
-  }
-
-  /// Returns the canonical mixin application of two classes, instantiated with
-  /// the same list of unbound type variables.
-  ///
-  /// Given two classes:
-  ///     class C<C1 ... Cm>
-  ///     class D<D1 ... Dn>
-  ///
-  /// This creates or reuses a mixin application class in the library of form:
-  ///
-  ///     abstract class C&D<T1 ... TN> = C<T1 ... Tm> with D<T1 ... Tn>
-  ///
-  /// where `N = max(m,n)`.
-  ///
-  /// Such a class can in general contain type errors due to incompatible
-  /// inheritance from `C` and `D`.  This method therefore should only be called
-  /// if a mixin application `C<S1 ... Sm> with D<S1 ... Sn>` is seen, where
-  /// `S1 ... SN` are distinct, unbound type variables.
-  ast.Class getSharedMixinApplicationClass(
-      ast.Library library, ast.Class superclass, ast.Class mixedInClass) {
-    // TODO(asgerf): Avoid potential name clash due to associativity.
-    // As it is, these mixins get the same name:
-    //   (A with B) with C
-    //   A with (B with C)
-    String name = '${superclass.name}&${mixedInClass.name}';
-    return _mixinApplications
-        .putIfAbsent(library, () => <String, ast.Class>{})
-        .putIfAbsent(name, () {
-      var fresh =
-          superclass.typeParameters.length >= mixedInClass.typeParameters.length
-              ? getFreshTypeParameters(superclass.typeParameters)
-              : getFreshTypeParameters(mixedInClass.typeParameters);
-      var typeArguments =
-          fresh.freshTypeParameters.map(makeTypeParameterType).toList();
-      var superArgs = typeArguments.length != superclass.typeParameters.length
-          ? typeArguments.sublist(0, superclass.typeParameters.length)
-          : typeArguments;
-      var mixinArgs = typeArguments.length != mixedInClass.typeParameters.length
-          ? typeArguments.sublist(0, mixedInClass.typeParameters.length)
-          : typeArguments;
-      var result = new ast.Class(
-          name: name,
-          isAbstract: true,
-          typeParameters: fresh.freshTypeParameters,
-          supertype: new ast.Supertype(superclass, superArgs),
-          mixedInType: new ast.Supertype(mixedInClass, mixinArgs),
-          fileUri: library.fileUri);
-      result.level = ast.ClassLevel.Type;
-      library.addClass(result);
-      return result;
-    });
-  }
-
-  String formatErrorMessage(
-      AnalysisError error, String filename, LineInfo lines) {
-    var location = lines.getLocation(error.offset);
-    return '[error] ${error.message} ($filename, '
-        'line ${location.lineNumber}, '
-        'col ${location.columnNumber})';
-  }
-
-  void ensureLibraryIsLoaded(ast.Library node) {
-    _ensureLibraryIsLoaded(node);
-    _iterateMixinLibraryWorklist();
-  }
-
-  void _ensureLibraryIsLoaded(ast.Library node) {
-    if (!node.isExternal) return;
-    node.isExternal = false;
-    var source = context.sourceFactory
-        .forUri2(applicationRoot.absoluteUri(node.importUri));
-    assert(source != null);
-    var element = context.computeLibraryElement(source);
-    var units = <CompilationUnit>[];
-    bool reportErrors = node.importUri.scheme != 'dart';
-    var tree = context.resolveCompilationUnit(source, element);
-    units.add(tree);
-    if (reportErrors) _processErrors(source);
-    for (var part in element.parts) {
-      var source = part.source;
-      units.add(context.resolveCompilationUnit(source, element));
-      if (reportErrors) _processErrors(source);
-    }
-    for (var import in element.imports) {
-      if (import.isDeferred && import.prefix != null) {
-        node.addDependency(new ast.LibraryDependency.deferredImport(
-            getLibraryReference(import.importedLibrary), import.prefix.name));
-      } else {
-        node.addDependency(new ast.LibraryDependency.import(
-            getLibraryReference(import.importedLibrary),
-            name: import.prefix?.name));
-      }
-    }
-    for (var export in element.exports) {
-      node.addDependency(new ast.LibraryDependency.export(
-          getLibraryReference(export.exportedLibrary)));
-    }
-    _buildLibraryBody(element, node, units);
-  }
-
-  void _processErrors(Source source) {
-    LineInfo lines;
-    for (var error in context.computeErrors(source)) {
-      if (error.errorCode is CompileTimeErrorCode ||
-          error.errorCode is ParserErrorCode ||
-          error.errorCode is ScannerErrorCode ||
-          error.errorCode is StrongModeCode) {
-        lines ??= context.computeLineInfo(source);
-        errors.add(formatErrorMessage(error, source.shortName, lines));
-      }
-    }
-  }
-
-  void loadSdkInterface(ast.Component component, Target target) {
-    var requiredSdkMembers = target.requiredSdkClasses;
-    for (var libraryUri in requiredSdkMembers.keys) {
-      var source = context.sourceFactory.forUri2(Uri.parse(libraryUri));
-      var libraryElement = context.computeLibraryElement(source);
-      for (var member in requiredSdkMembers[libraryUri]) {
-        var type = libraryElement.getType(member);
-        if (type == null) {
-          throw 'Could not find $member in $libraryUri';
-        }
-        promoteToTypeLevel(getClassReference(type));
-      }
-    }
-    _iterateTemporaryClassWorklist();
-    _iterateMixinLibraryWorklist();
-  }
-
-  void loadEverything({Target target, bool compileSdk}) {
-    compileSdk ??= true;
-    if (compileSdk) {
-      ensureLibraryIsLoaded(getLibraryReference(getDartCoreLibrary()));
-      if (target != null) {
-        for (var uri in target.extraRequiredLibraries) {
-          var library = _findLibraryElement(uri);
-          if (library == null) {
-            errors.add('Could not find required library $uri');
-            continue;
-          }
-          ensureLibraryIsLoaded(getLibraryReference(library));
-        }
-      }
-    }
-    for (int i = 0; i < component.libraries.length; ++i) {
-      var library = component.libraries[i];
-      if (compileSdk || library.importUri.scheme != 'dart') {
-        ensureLibraryIsLoaded(library);
-      }
-    }
-  }
-
-  /// Builds a list of sources that have been loaded.
-  ///
-  /// This operation may be expensive and should only be used for diagnostics.
-  List<String> getLoadedFileNames() {
-    var list = <String>[];
-    for (var library in component.libraries) {
-      LibraryElement element = context.computeLibraryElement(context
-          .sourceFactory
-          .forUri2(applicationRoot.absoluteUri(library.importUri)));
-      for (var unit in element.units) {
-        list.add(unit.source.fullName);
-      }
-    }
-    return list;
-  }
-
-  void _iterateTemporaryClassWorklist() {
-    while (temporaryClassWorklist.isNotEmpty) {
-      var element = temporaryClassWorklist.removeLast();
-      promoteToTypeLevel(element);
-    }
-  }
-
-  void _iterateMixinLibraryWorklist() {
-    // The worklist groups classes in the same library together so that we
-    // request resolved ASTs for each library only once.
-    while (mixinLibraryWorklist.isNotEmpty) {
-      LibraryElement library = mixinLibraryWorklist.keys.first;
-      _libraryBeingLoaded = library;
-      List<ClassElement> classes = mixinLibraryWorklist.remove(library);
-      for (var class_ in classes) {
-        var classNode = getClassReference(class_);
-        promoteToMixinLevel(classNode, class_, class_.computeNode());
-      }
-      _libraryBeingLoaded = null;
-    }
-    _iterateTemporaryClassWorklist();
-  }
-
-  ast.Procedure _getMainMethod(Uri uri) {
-    Source source = context.sourceFactory.forUri2(uri);
-    LibraryElement library = context.computeLibraryElement(source);
-    var mainElement = library.entryPoint;
-    if (mainElement == null) return null;
-    var mainMember = getMemberReference(mainElement);
-    if (mainMember is ast.Procedure && !mainMember.isAccessor) {
-      return mainMember;
-    }
-    // Top-level 'main' getters are not supported at the moment.
-    return null;
-  }
-
-  ast.Procedure _makeMissingMainMethod(ast.Library library) {
-    var main = new ast.Procedure(
-        new ast.Name('main'),
-        ast.ProcedureKind.Method,
-        new ast.FunctionNode(new ast.ExpressionStatement(new ast.Throw(
-            new ast.StringLiteral('Component has no main method')))),
-        isStatic: true)
-      ..fileUri = library.fileUri;
-    library.addMember(main);
-    return main;
-  }
-
-  void loadComponent(Uri mainLibrary, {Target target, bool compileSdk}) {
-    ast.Library library = getLibraryReferenceFromUri(mainLibrary);
-    ensureLibraryIsLoaded(library);
-    var mainMethod = _getMainMethod(mainLibrary);
-    loadEverything(target: target, compileSdk: compileSdk);
-    if (mainMethod == null) {
-      mainMethod = _makeMissingMainMethod(library);
-    }
-    component.mainMethod = mainMethod;
-    for (LibraryElement libraryElement in libraryElements) {
-      for (CompilationUnitElement compilationUnitElement
-          in libraryElement.units) {
-        var source = compilationUnitElement.source;
-        LineInfo lineInfo = context.computeLineInfo(source);
-        List<int> sourceCode;
-        try {
-          sourceCode =
-              const Utf8Encoder().convert(context.getContents(source).data);
-        } catch (e) {
-          // The source's contents could not be accessed.
-          sourceCode = const <int>[];
-        }
-        component.uriToSource[source.uri] =
-            new ast.Source(lineInfo.lineStarts, sourceCode);
-      }
-    }
-  }
-
-  ast.Library loadLibrary(Uri uri) {
-    ast.Library library = getLibraryReferenceFromUri(uri);
-    ensureLibraryIsLoaded(library);
-    return library;
-  }
-}
-
-class Bimap<K, V> {
-  final Map<K, V> nodeMap = <K, V>{};
-  final Map<V, K> inverse = <V, K>{};
-
-  bool containsKey(K key) => nodeMap.containsKey(key);
-
-  V operator [](K key) => nodeMap[key];
-
-  void operator []=(K key, V value) {
-    assert(!nodeMap.containsKey(key));
-    nodeMap[key] = value;
-    inverse[value] = key;
-  }
-}
-
-/// Creates [DartLoader]s for a given configuration, while reusing the
-/// [DartSdk] and [Packages] object if possible.
-class DartLoaderBatch {
-  Packages packages;
-  DartSdk dartSdk;
-
-  String lastSdk;
-  String lastPackagePath;
-  bool lastStrongMode;
-
-  Future<DartLoader> getLoader(ast.Component component, DartOptions options,
-      {String packageDiscoveryPath}) async {
-    if (dartSdk == null ||
-        lastSdk != options.sdk ||
-        lastStrongMode != options.strongMode) {
-      lastSdk = options.sdk;
-      lastStrongMode = options.strongMode;
-      dartSdk = createDartSdk(options.sdk, strongMode: options.strongModeSdk);
-    }
-    if (packages == null ||
-        lastPackagePath != options.packagePath ||
-        packageDiscoveryPath != null) {
-      lastPackagePath = options.packagePath;
-      packages = await createPackages(options.packagePath,
-          discoveryPath: packageDiscoveryPath);
-    }
-    return new DartLoader(component, options, packages, dartSdk: dartSdk);
-  }
-}
-
-Future<Packages> createPackages(String packagePath,
-    {String discoveryPath}) async {
-  if (packagePath != null) {
-    var absolutePath = new io.File(packagePath).absolute.path;
-    if (await new io.Directory(packagePath).exists()) {
-      return getPackagesDirectory(new Uri.file(absolutePath));
-    } else if (await new io.File(packagePath).exists()) {
-      return loadPackagesFile(new Uri.file(absolutePath));
-    } else {
-      throw 'Packages not found: $packagePath';
-    }
-  }
-  if (discoveryPath != null) {
-    return findPackagesFromFile(Uri.parse(discoveryPath));
-  }
-  return Packages.noPackages;
-}
-
-AnalysisOptions createAnalysisOptions(bool strongMode) {
-  return new AnalysisOptionsImpl()
-    ..strongMode = strongMode
-    ..generateImplicitErrors = false
-    ..generateSdkErrors = false
-    ..preserveComments = false
-    ..hint = false
-    ..enableSuperMixins = true;
-}
-
-DartSdk createDartSdk(String path, {bool strongMode, bool isSummary}) {
-  if (isSummary ?? false) {
-    return new SummaryBasedDartSdk(path, strongMode);
-  }
-  var resources = PhysicalResourceProvider.INSTANCE;
-  return new FolderBasedDartSdk(resources, resources.getFolder(path))
-    ..context
-        .analysisOptions
-        .setCrossContextOptionsFrom(createAnalysisOptions(strongMode));
-}
-
-class CustomUriResolver extends UriResolver {
-  final ResourceUriResolver _resourceUriResolver;
-  final Map<Uri, Uri> _customUrlMappings;
-
-  CustomUriResolver(this._resourceUriResolver, this._customUrlMappings);
-
-  Source resolveAbsolute(Uri uri, [Uri actualUri]) {
-    // TODO(kustermann): Once dartk supports configurable imports we should be
-    // able to get rid of this.
-    if (uri.toString() == 'package:mojo/src/internal_contract.dart') {
-      uri = actualUri = Uri.parse('dart:mojo.internal');
-    }
-
-    Uri baseUri = uri;
-    String relative;
-    String path = uri.path;
-    int index = path.indexOf('/');
-    if (index > 0) {
-      baseUri = uri.replace(path: path.substring(0, index));
-      relative = path.substring(index + 1);
-    }
-    Uri baseMapped = _customUrlMappings[baseUri];
-    if (baseMapped == null) return null;
-
-    Uri mapped = relative != null ? baseMapped.resolve(relative) : baseMapped;
-    return _resourceUriResolver.resolveAbsolute(mapped, actualUri);
-  }
-
-  Uri restoreAbsolute(Source source) {
-    return _resourceUriResolver.restoreAbsolute(source);
-  }
-}
-
-AnalysisContext createContext(DartOptions options, Packages packages,
-    {DartSdk dartSdk}) {
-  bool fromSummary = options.sdkSummary != null;
-  dartSdk ??= createDartSdk(fromSummary ? options.sdkSummary : options.sdk,
-      strongMode: options.strongModeSdk, isSummary: fromSummary);
-
-  var resourceProvider = PhysicalResourceProvider.INSTANCE;
-  var resourceUriResolver = new ResourceUriResolver(resourceProvider);
-  List<UriResolver> resolvers = [];
-  var customUriMappings = options.customUriMappings;
-  if (customUriMappings != null && customUriMappings.length > 0) {
-    resolvers
-        .add(new CustomUriResolver(resourceUriResolver, customUriMappings));
-  }
-  resolvers.add(new DartUriResolver(dartSdk));
-  resolvers.add(resourceUriResolver);
-
-  if (packages != null) {
-    var folderMap = <String, List<Folder>>{};
-    packages.asMap().forEach((String packagePath, Uri uri) {
-      String path = resourceProvider.pathContext.fromUri(uri);
-      folderMap[packagePath] = [resourceProvider.getFolder(path)];
-    });
-    resolvers.add(new PackageMapUriResolver(resourceProvider, folderMap));
-  }
-
-  AnalysisContext context = AnalysisEngine.instance.createAnalysisContext()
-    ..sourceFactory = new SourceFactory(resolvers)
-    ..analysisOptions = createAnalysisOptions(options.strongMode);
-
-  options.declaredVariables.forEach((String name, String value) {
-    context.declaredVariables.define(name, value);
-  });
-
-  return context;
-}
diff --git a/pkg/analyzer/lib/src/lint/analysis.dart b/pkg/analyzer/lib/src/lint/analysis.dart
index dce18a5..5884ac1 100644
--- a/pkg/analyzer/lib/src/lint/analysis.dart
+++ b/pkg/analyzer/lib/src/lint/analysis.dart
@@ -49,6 +49,7 @@
   AnalysisOptionsImpl analysisOptions = new AnalysisOptionsImpl();
   analysisOptions.strongMode = options.strongMode;
   analysisOptions.hint = false;
+  analysisOptions.previewDart2 = options.previewDart2;
   analysisOptions.lint = options.enableLints;
   analysisOptions.generateSdkErrors = options.showSdkWarnings;
   analysisOptions.enableTiming = options.enableTiming;
@@ -82,6 +83,9 @@
   /// Whether to use Dart's Strong Mode analyzer.
   bool strongMode = true;
 
+  /// Whether to use Dart 2.0 features.
+  bool previewDart2 = false;
+
   /// The mock SDK (to speed up testing) or `null` to use the actual SDK.
   DartSdk mockSdk;
 
diff --git a/pkg/analyzer/lib/src/lint/config.dart b/pkg/analyzer/lib/src/lint/config.dart
index f33b3f3..6f5268d 100644
--- a/pkg/analyzer/lib/src/lint/config.dart
+++ b/pkg/analyzer/lib/src/lint/config.dart
@@ -2,16 +2,17 @@
 // 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:analyzer/src/util/yaml.dart';
 import 'package:yaml/yaml.dart';
 
 /**
  * Parse the given map into a lint config.
  */
-LintConfig parseConfig(Map optionsMap) {
+LintConfig parseConfig(YamlMap optionsMap) {
   if (optionsMap != null) {
-    var options = optionsMap['linter'];
+    var options = getValue(optionsMap, 'linter');
     // Quick check of basic contract.
-    if (options is Map) {
+    if (options is YamlMap) {
       return new LintConfig.parseMap(options);
     }
   }
@@ -37,7 +38,8 @@
   factory LintConfig.parse(String source, {String sourceUrl}) =>
       new _LintConfig().._parse(source, sourceUrl: sourceUrl);
 
-  factory LintConfig.parseMap(Map map) => new _LintConfig().._parseMap(map);
+  factory LintConfig.parseMap(YamlMap map) =>
+      new _LintConfig().._parseYaml(map);
 
   List<String> get fileExcludes;
   List<String> get fileIncludes;
@@ -76,14 +78,15 @@
   }
 
   bool asBool(scalar) {
-    if (scalar is bool) {
-      return scalar;
+    Object value = scalar is YamlScalar ? scalar.value : scalar;
+    if (value is bool) {
+      return value;
     }
-    if (scalar is String) {
-      if (scalar == 'true') {
+    if (value is String) {
+      if (value == 'true') {
         return true;
       }
-      if (scalar == 'false') {
+      if (value == 'false') {
         return false;
       }
     }
@@ -91,8 +94,9 @@
   }
 
   String asString(scalar) {
-    if (scalar is String) {
-      return scalar;
+    Object value = scalar is YamlScalar ? scalar.value : scalar;
+    if (value is String) {
+      return value;
     }
     return null;
   }
@@ -112,71 +116,6 @@
     }
   }
 
-  void _parseMap(Map options) {
-    //TODO(pq): unify map parsing.
-    if (options is YamlMap) {
-      _parseYaml(options);
-    } else {
-      _parseRawMap(options);
-    }
-  }
-
-  void _parseRawMap(Map options) {
-    options.forEach((k, v) {
-      if (k is! String) {
-        return;
-      }
-      String key = k;
-      switch (key) {
-        case 'files':
-          if (v is Map) {
-            addAsListOrString(v['include'], fileIncludes);
-            addAsListOrString(v['exclude'], fileExcludes);
-          }
-          break;
-
-        case 'rules':
-          // - unnecessary_getters
-          // - camel_case_types
-          if (v is List) {
-            v.forEach((rule) {
-              var config = new _RuleConfig();
-              config.name = asString(rule);
-              config.args = {'enabled': true};
-              ruleConfigs.add(config);
-            });
-          }
-
-          // {unnecessary_getters: false, camel_case_types: true}
-          if (v is Map) {
-            v.forEach((key, value) {
-              // style_guide: {unnecessary_getters: false, camel_case_types: true}
-              if (value is Map) {
-                value.forEach((rule, args) {
-                  // unnecessary_getters: false
-                  var config = new _RuleConfig();
-                  config.group = key;
-                  config.name = asString(rule);
-                  config.args = parseArgs(args);
-                  ruleConfigs.add(config);
-                });
-              } else {
-                //{unnecessary_getters: false}
-                value = asBool(value);
-                if (value != null) {
-                  var config = new _RuleConfig();
-                  config.name = asString(key);
-                  config.args = {'enabled': value};
-                  ruleConfigs.add(config);
-                }
-              }
-            });
-          }
-          break;
-      }
-    });
-  }
-
   void _parseYaml(YamlMap yaml) {
     yaml.nodes.forEach((k, v) {
       if (k is! YamlScalar) {
@@ -195,8 +134,8 @@
 
           // - unnecessary_getters
           // - camel_case_types
-          if (v is List) {
-            (v as List).forEach((rule) {
+          if (v is YamlList) {
+            v.nodes.forEach((rule) {
               var config = new _RuleConfig();
               config.name = asString(rule);
               config.args = {'enabled': true};
@@ -206,22 +145,22 @@
 
           // style_guide: {unnecessary_getters: false, camel_case_types: true}
           if (v is YamlMap) {
-            v.forEach((key, value) {
+            v.nodes.forEach((key, value) {
               //{unnecessary_getters: false}
-              if (value is bool) {
+              if (asBool(value) != null) {
                 var config = new _RuleConfig();
                 config.name = asString(key);
-                config.args = {'enabled': value};
+                config.args = {'enabled': asBool(value)};
                 ruleConfigs.add(config);
               }
 
               // style_guide: {unnecessary_getters: false, camel_case_types: true}
               if (value is YamlMap) {
-                value.forEach((rule, args) {
+                value.nodes.forEach((rule, args) {
                   // TODO: verify format
                   // unnecessary_getters: false
                   var config = new _RuleConfig();
-                  config.group = key;
+                  config.group = asString(key);
                   config.name = asString(rule);
                   config.args = parseArgs(args);
                   ruleConfigs.add(config);
diff --git a/pkg/analyzer/lib/src/lint/options_rule_validator.dart b/pkg/analyzer/lib/src/lint/options_rule_validator.dart
index 109cdd2..217778a 100644
--- a/pkg/analyzer/lib/src/lint/options_rule_validator.dart
+++ b/pkg/analyzer/lib/src/lint/options_rule_validator.dart
@@ -5,6 +5,7 @@
 import 'package:analyzer/analyzer.dart';
 import 'package:analyzer/plugin/options.dart';
 import 'package:analyzer/src/lint/registry.dart';
+import 'package:analyzer/src/util/yaml.dart';
 import 'package:yaml/yaml.dart';
 
 /**
@@ -24,18 +25,17 @@
   static const linter = 'linter';
   static const rulesKey = 'rules';
   @override
-  List<AnalysisError> validate(
-      ErrorReporter reporter, Map<String, YamlNode> options) {
+  List<AnalysisError> validate(ErrorReporter reporter, YamlMap options) {
     List<AnalysisError> errors = <AnalysisError>[];
-    var node = options[linter];
+    var node = getValue(options, linter);
     if (node is YamlMap) {
-      var rules = node.nodes[rulesKey];
+      var rules = getValue(node, rulesKey);
       validateRules(rules, reporter);
     }
     return errors;
   }
 
-  validateRules(dynamic rules, ErrorReporter reporter) {
+  validateRules(YamlNode rules, ErrorReporter reporter) {
     if (rules is YamlList) {
       Iterable<String> registeredLints =
           Registry.ruleRegistry.map((r) => r.name);
diff --git a/pkg/analyzer/lib/src/pubspec/pubspec_validator.dart b/pkg/analyzer/lib/src/pubspec/pubspec_validator.dart
index e0a25cb..ea14ea6 100644
--- a/pkg/analyzer/lib/src/pubspec/pubspec_validator.dart
+++ b/pkg/analyzer/lib/src/pubspec/pubspec_validator.dart
@@ -100,7 +100,7 @@
    * from the given [contents] using the given [key].
    */
   Map<dynamic, YamlNode> _getDeclaredDependencies(
-      ErrorReporter reporter, Map<String, YamlNode> contents, String key) {
+      ErrorReporter reporter, Map<dynamic, YamlNode> contents, String key) {
     YamlNode field = contents[key];
     if (field == null) {
       return <String, YamlNode>{};
diff --git a/pkg/analyzer/lib/src/task/options.dart b/pkg/analyzer/lib/src/task/options.dart
index 4fae935..c7c83de 100644
--- a/pkg/analyzer/lib/src/task/options.dart
+++ b/pkg/analyzer/lib/src/task/options.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-library analyzer.src.task.options;
-
 import 'dart:collection';
 
 import 'package:analyzer/analyzer.dart';
@@ -34,8 +32,7 @@
 
 final _OptionsProcessor _processor = new _OptionsProcessor();
 
-void applyToAnalysisOptions(
-    AnalysisOptionsImpl options, Map<String, Object> optionMap) {
+void applyToAnalysisOptions(AnalysisOptionsImpl options, YamlMap optionMap) {
   _processor.applyToAnalysisOptions(options, optionMap);
 }
 
@@ -110,7 +107,7 @@
   CompositeValidator(this.validators);
 
   @override
-  void validate(ErrorReporter reporter, Map<String, YamlNode> options) =>
+  void validate(ErrorReporter reporter, YamlMap options) =>
       validators.forEach((v) => v.validate(reporter, options));
 }
 
@@ -170,10 +167,10 @@
   }
 
   @override
-  void validate(ErrorReporter reporter, Map<String, YamlNode> options) {
-    var analyzer = options[AnalyzerOptions.analyzer];
+  void validate(ErrorReporter reporter, YamlMap options) {
+    var analyzer = getValue(options, AnalyzerOptions.analyzer);
     if (analyzer is YamlMap) {
-      var filters = analyzer[AnalyzerOptions.errors];
+      var filters = getValue(analyzer, AnalyzerOptions.errors);
       if (filters is YamlMap) {
         String value;
         filters.nodes.forEach((k, v) {
@@ -251,7 +248,7 @@
         new AnalysisOptionsProvider(sourceFactory);
 
     // Validate the specified options and any included option files
-    void validate(Source source, Map<String, YamlNode> options) {
+    void validate(Source source, YamlMap options) {
       List<AnalysisError> validationErrors =
           new OptionsFileValidator(source).validate(options);
       if (initialIncludeSpan != null && validationErrors.isNotEmpty) {
@@ -273,7 +270,7 @@
         errors.addAll(validationErrors);
       }
 
-      YamlNode node = options[AnalyzerOptions.include];
+      YamlNode node = getValue(options, AnalyzerOptions.include);
       if (node == null) {
         return;
       }
@@ -291,7 +288,7 @@
         return;
       }
       try {
-        Map<String, YamlNode> options =
+        YamlMap options =
             optionsProvider.getOptionsFromString(includedSource.contents.data);
         validate(includedSource, options);
       } on OptionsFormatException catch (e) {
@@ -313,8 +310,7 @@
     }
 
     try {
-      Map<String, YamlNode> options =
-          optionsProvider.getOptionsFromString(content);
+      YamlMap options = optionsProvider.getOptionsFromString(content);
       validate(source, options);
     } on OptionsFormatException catch (e) {
       SourceSpan span = e.span;
@@ -360,10 +356,10 @@
   ErrorBuilder trueOrFalseBuilder = new TrueOrFalseValueErrorBuilder();
 
   @override
-  void validate(ErrorReporter reporter, Map<String, YamlNode> options) {
-    var analyzer = options[AnalyzerOptions.analyzer];
+  void validate(ErrorReporter reporter, YamlMap options) {
+    var analyzer = getValue(options, AnalyzerOptions.analyzer);
     if (analyzer is YamlMap) {
-      var language = analyzer[AnalyzerOptions.language];
+      var language = getValue(analyzer, AnalyzerOptions.language);
       if (language is YamlMap) {
         language.nodes.forEach((k, v) {
           String key, value;
@@ -408,7 +404,7 @@
 
   OptionsFileValidator(this.source);
 
-  List<AnalysisError> validate(Map<String, YamlNode> options) {
+  List<AnalysisError> validate(YamlMap options) {
     RecordingErrorListener recorder = new RecordingErrorListener();
     ErrorReporter reporter = new ErrorReporter(recorder, source);
     if (AnalysisEngine.ANALYSIS_OPTIONS_FILE == source.shortName) {
@@ -429,10 +425,10 @@
   ErrorBuilder trueOrFalseBuilder = new TrueOrFalseValueErrorBuilder();
 
   @override
-  void validate(ErrorReporter reporter, Map<String, YamlNode> options) {
-    var analyzer = options[AnalyzerOptions.analyzer];
+  void validate(ErrorReporter reporter, YamlMap options) {
+    var analyzer = getValue(options, AnalyzerOptions.analyzer);
     if (analyzer is YamlMap) {
-      var v = analyzer.nodes[AnalyzerOptions.strong_mode];
+      var v = getValue(analyzer, AnalyzerOptions.strong_mode);
       if (v is YamlScalar) {
         var value = toLowerCase(v.value);
         if (!AnalyzerOptions.trueOrFalse.contains(value)) {
@@ -476,8 +472,8 @@
   }
 
   @override
-  void validate(ErrorReporter reporter, Map<String, YamlNode> options) {
-    YamlNode node = options[pluginName];
+  void validate(ErrorReporter reporter, YamlMap options) {
+    YamlNode node = getValue(options, pluginName);
     if (node is YamlMap) {
       node.nodes.forEach((k, v) {
         if (k is YamlScalar) {
@@ -507,44 +503,46 @@
   /**
    * Apply the options in the given [optionMap] to the given analysis [options].
    */
-  void applyToAnalysisOptions(
-      AnalysisOptionsImpl options, Map<String, Object> optionMap) {
+  void applyToAnalysisOptions(AnalysisOptionsImpl options, YamlMap optionMap) {
     if (optionMap == null) {
       return;
     }
-    var analyzer = optionMap[AnalyzerOptions.analyzer];
-    if (analyzer is Map) {
+    var analyzer = getValue(optionMap, AnalyzerOptions.analyzer);
+    if (analyzer is YamlMap) {
       // Process strong mode option.
-      var strongMode = analyzer[AnalyzerOptions.strong_mode];
+      var strongMode = getValue(analyzer, AnalyzerOptions.strong_mode);
       _applyStrongOptions(options, strongMode);
 
       // Set filters.
-      var filters = analyzer[AnalyzerOptions.errors];
+      var filters = getValue(analyzer, AnalyzerOptions.errors);
       _applyProcessors(options, filters);
 
       // Process language options.
-      var language = analyzer[AnalyzerOptions.language];
+      var language = getValue(analyzer, AnalyzerOptions.language);
       _applyLanguageOptions(options, language);
 
       // Process excludes.
-      var excludes = analyzer[AnalyzerOptions.exclude];
+      var excludes = getValue(analyzer, AnalyzerOptions.exclude);
       _applyExcludes(options, excludes);
 
       // Process plugins.
-      var names = analyzer[AnalyzerOptions.plugins];
+      var names = getValue(analyzer, AnalyzerOptions.plugins);
       List<String> pluginNames = <String>[];
-      if (names is String) {
-        pluginNames.add(names);
-      } else if (names is List) {
-        for (var element in names) {
-          if (element is String) {
-            pluginNames.add(element);
+      String pluginName = _toString(names);
+      if (pluginName != null) {
+        pluginNames.add(pluginName);
+      } else if (names is YamlList) {
+        for (var element in names.nodes) {
+          String pluginName = _toString(element);
+          if (pluginName != null) {
+            pluginNames.add(pluginName);
           }
         }
-      } else if (names is Map) {
-        for (var key in names.keys) {
-          if (key is String) {
-            pluginNames.add(key);
+      } else if (names is YamlMap) {
+        for (var key in names.nodes.keys) {
+          String pluginName = _toString(key);
+          if (pluginName != null) {
+            pluginNames.add(pluginName);
           }
         }
       }
@@ -561,8 +559,8 @@
     }
   }
 
-  void _applyExcludes(AnalysisOptionsImpl options, Object excludes) {
-    if (excludes is List) {
+  void _applyExcludes(AnalysisOptionsImpl options, YamlNode excludes) {
+    if (excludes is YamlList) {
       List<String> excludeList = toStringList(excludes);
       if (excludeList != null) {
         options.excludePatterns = excludeList;
@@ -582,7 +580,7 @@
     }
   }
 
-  void _applyLanguageOptions(AnalysisOptionsImpl options, Object configs) {
+  void _applyLanguageOptions(AnalysisOptionsImpl options, YamlNode configs) {
     if (configs is YamlMap) {
       configs.nodes.forEach((key, value) {
         if (key is YamlScalar && value is YamlScalar) {
@@ -590,19 +588,16 @@
           _applyLanguageOption(options, feature, value.value);
         }
       });
-    } else if (configs is Map) {
-      configs
-          .forEach((key, value) => _applyLanguageOption(options, key, value));
     }
   }
 
-  void _applyProcessors(AnalysisOptionsImpl options, Object codes) {
+  void _applyProcessors(AnalysisOptionsImpl options, YamlNode codes) {
     ErrorConfig config = new ErrorConfig(codes);
     options.errorProcessors = config.processors;
   }
 
   void _applyStrongModeOption(
-      AnalysisOptionsImpl options, Object feature, Object value) {
+      AnalysisOptionsImpl options, String feature, Object value) {
     bool boolValue = toBool(value);
     if (boolValue != null) {
       if (feature == AnalyzerOptions.declarationCasts) {
@@ -617,7 +612,7 @@
     }
   }
 
-  void _applyStrongOptions(AnalysisOptionsImpl options, Object config) {
+  void _applyStrongOptions(AnalysisOptionsImpl options, YamlNode config) {
     if (config is YamlMap) {
       options.strongMode = true;
       config.nodes.forEach((k, v) {
@@ -625,11 +620,21 @@
           _applyStrongModeOption(options, k.value?.toString(), v.value);
         }
       });
-    } else if (config is Map) {
-      options.strongMode = true;
-      config.forEach((k, v) => _applyStrongModeOption(options, k, v));
     } else {
-      options.strongMode = config is bool ? config : false;
+      bool value = toBool(config);
+      if (value != null) {
+        options.strongMode = value;
+      }
     }
   }
+
+  String _toString(YamlNode node) {
+    if (node is YamlScalar) {
+      var value = node.value;
+      if (value is String) {
+        return value;
+      }
+    }
+    return null;
+  }
 }
diff --git a/pkg/analyzer/lib/src/util/yaml.dart b/pkg/analyzer/lib/src/util/yaml.dart
index 89b6156..cb0175b 100644
--- a/pkg/analyzer/lib/src/util/yaml.dart
+++ b/pkg/analyzer/lib/src/util/yaml.dart
@@ -4,6 +4,20 @@
 
 import 'dart:collection';
 
+import 'package:yaml/src/event.dart';
+import 'package:yaml/yaml.dart';
+
+/// Given a [map], return the value associated with the key whose value matches
+/// the given [key], or `null` if there is no matching key.
+YamlNode getValue(YamlMap map, String key) {
+  for (var k in map.nodes.keys) {
+    if (k is YamlScalar && k.value == key) {
+      return map.nodes[k];
+    }
+  }
+  return null;
+}
+
 /// If all of the elements of [list] are strings, return a list of strings
 /// containing the same elements. Otherwise, return `null`.
 List<String> toStringList(List list) {
@@ -21,6 +35,15 @@
   return stringList;
 }
 
+bool _contains(YamlList l1, YamlNode n2) {
+  for (YamlNode n1 in l1.nodes) {
+    if (n1.value == n2.value) {
+      return true;
+    }
+  }
+  return false;
+}
+
 /// Merges two maps (of yaml) with simple override semantics, suitable for
 /// merging two maps where one map defines default values that are added to
 /// (and possibly overridden) by an overriding map.
@@ -34,40 +57,66 @@
   ///   * maps are merged recursively.
   ///   * if map values cannot be merged, the overriding value is taken.
   ///
-  Object merge(Object o1, Object o2) {
+  YamlNode merge(YamlNode o1, YamlNode o2) {
     // Handle promotion first.
-    if (o1 is List && isMapToBools(o2)) {
-      o1 = new Map.fromIterable(o1, key: (item) => item, value: (item) => true);
-    } else if (isMapToBools(o1) && o2 is List) {
-      o2 = new Map.fromIterable(o2, key: (item) => item, value: (item) => true);
+    YamlMap listToMap(YamlList list) {
+      Map<YamlNode, YamlNode> map = new HashMap<YamlNode,
+          YamlNode>(); // equals: _equals, hashCode: _hashCode
+      ScalarEvent event = new ScalarEvent(null, 'true', ScalarStyle.PLAIN);
+      for (var element in list.nodes) {
+        map[element] = new YamlScalar.internal(true, event);
+      }
+      return new YamlMap.internal(map, null, CollectionStyle.BLOCK);
     }
 
-    if (o1 is Map && o2 is Map) {
+    if (isListOfString(o1) && isMapToBools(o2)) {
+      o1 = listToMap(o1 as YamlList);
+    } else if (isMapToBools(o1) && isListOfString(o2)) {
+      o2 = listToMap(o2 as YamlList);
+    }
+
+    if (o1 is YamlMap && o2 is YamlMap) {
       return mergeMap(o1, o2);
     }
-    if (o1 is List && o2 is List) {
+    if (o1 is YamlList && o2 is YamlList) {
       return mergeList(o1, o2);
     }
-    // Default to override.
-    return o2;
+    // Default to override, unless the overriding value is `null`.
+    return o2 ?? o1;
   }
 
   /// Merge lists, avoiding duplicates.
-  List<E> mergeList<E>(List<E> l1, List<E> l2) =>
-      new List<E>()..addAll(l1)..addAll(l2.where((item) => !l1.contains(item)));
-
-  /// Merge maps (recursively).
-  Map<K, V> mergeMap<K, V>(Map<K, V> m1, Map<K, V> m2) {
-    Map<K, V> merged = new HashMap<K, V>()..addAll(m1);
-    m2.forEach((k, v) {
-      // TODO(brianwilkerson) This fails when merging two Map<String, YamlNode>
-      // objects and the result of `merge` is a HashMap (because the YamlNodes
-      // were YamlMaps.
-      merged[k] = merge(merged[k], v);
-    });
-    return merged;
+  YamlList mergeList(YamlList l1, YamlList l2) {
+    List<YamlNode> list = <YamlNode>[];
+    list.addAll(l1.nodes);
+    for (YamlNode n2 in l2.nodes) {
+      if (!_contains(l1, n2)) {
+        list.add(n2);
+      }
+    }
+    return new YamlList.internal(list, null, CollectionStyle.BLOCK);
   }
 
+  /// Merge maps (recursively).
+  YamlMap mergeMap(YamlMap m1, YamlMap m2) {
+    Map<YamlNode, YamlNode> merged = new HashMap<YamlNode,
+        YamlNode>(); // equals: _equals, hashCode: _hashCode
+    m1.nodes.forEach((k, v) {
+      merged[k] = v;
+    });
+    m2.nodes.forEach((k, v) {
+      YamlScalar mergedKey = merged.keys
+          .firstWhere((key) => key.value == k.value, orElse: () => k);
+      merged[mergedKey] = merge(merged[mergedKey], v);
+    });
+    return new YamlMap.internal(merged, null, CollectionStyle.BLOCK);
+  }
+
+  static bool isListOfString(Object o) =>
+      o is YamlList &&
+      o.nodes.every((e) => e is YamlScalar && e.value is String);
+
   static bool isMapToBools(Object o) =>
-      o is Map && o.values.every((v) => v is bool);
+      o is YamlMap &&
+      o.nodes.values.every((v) => v is YamlScalar && v.value is bool);
 }
diff --git a/pkg/analyzer/test/generated/hint_code_test.dart b/pkg/analyzer/test/generated/hint_code_test.dart
index 0385dba..03c52e1 100644
--- a/pkg/analyzer/test/generated/hint_code_test.dart
+++ b/pkg/analyzer/test/generated/hint_code_test.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-library analyzer.test.generated.hint_code_test;
-
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/error/error.dart';
 import 'package:analyzer/src/error/codes.dart';
@@ -14,6 +12,7 @@
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
+import '../src/util/yaml_test.dart';
 import 'resolver_test_case.dart';
 
 main() {
@@ -3053,13 +3052,15 @@
 
   test_strongMode_downCastCompositeWarn() async {
     AnalysisOptionsImpl options = new AnalysisOptionsImpl();
-    applyToAnalysisOptions(options, {
-      AnalyzerOptions.analyzer: {
-        AnalyzerOptions.errors: {
-          StrongModeCode.DOWN_CAST_COMPOSITE.name: 'warning'
-        },
-      }
-    });
+    applyToAnalysisOptions(
+        options,
+        wrap({
+          AnalyzerOptions.analyzer: {
+            AnalyzerOptions.errors: {
+              StrongModeCode.DOWN_CAST_COMPOSITE.name: 'warning'
+            },
+          }
+        }));
     options.strongMode = true;
     options.strongModeHints = false;
     resetWith(options: options);
diff --git a/pkg/analyzer/test/generated/parser_fasta_listener.dart b/pkg/analyzer/test/generated/parser_fasta_listener.dart
index cf19032..7ffd79f 100644
--- a/pkg/analyzer/test/generated/parser_fasta_listener.dart
+++ b/pkg/analyzer/test/generated/parser_fasta_listener.dart
@@ -114,8 +114,9 @@
   }
 
   @override
-  void beginClassDeclaration(Token beginToken, Token name) {
-    super.beginClassDeclaration(beginToken, name);
+  void beginClassDeclaration(
+      Token beginToken, Token abstractToken, Token name) {
+    super.beginClassDeclaration(beginToken, abstractToken, name);
     begin('ClassDeclaration');
   }
 
@@ -397,8 +398,9 @@
   }
 
   @override
-  void beginNamedMixinApplication(Token beginToken, Token name) {
-    super.beginNamedMixinApplication(beginToken, name);
+  void beginNamedMixinApplication(
+      Token beginToken, Token abstractToken, Token name) {
+    super.beginNamedMixinApplication(beginToken, abstractToken, name);
     begin('NamedMixinApplication');
   }
 
@@ -704,10 +706,12 @@
   }
 
   @override
-  void endFields(int count, Token beginToken, Token endToken) {
+  void endFields(Token staticToken, Token covariantToken, Token varFinalOrConst,
+      int count, Token beginToken, Token endToken) {
     // beginMember --> endFields, endMember
     expectIn('Member');
-    super.endFields(count, beginToken, endToken);
+    super.endFields(staticToken, covariantToken, varFinalOrConst, count,
+        beginToken, endToken);
   }
 
   @override
@@ -999,9 +1003,11 @@
   }
 
   @override
-  void endTopLevelFields(int count, Token beginToken, Token endToken) {
+  void endTopLevelFields(Token staticToken, Token covariantToken,
+      Token varFinalOrConst, int count, Token beginToken, Token endToken) {
     end('TopLevelMember');
-    super.endTopLevelFields(count, beginToken, endToken);
+    super.endTopLevelFields(staticToken, covariantToken, varFinalOrConst, count,
+        beginToken, endToken);
   }
 
   @override
diff --git a/pkg/analyzer/test/generated/parser_fasta_test.dart b/pkg/analyzer/test/generated/parser_fasta_test.dart
index b3465ea..fb9d1c0 100644
--- a/pkg/analyzer/test/generated/parser_fasta_test.dart
+++ b/pkg/analyzer/test/generated/parser_fasta_test.dart
@@ -112,44 +112,6 @@
     with ErrorParserTestMixin {
   @override
   @failingTest
-  void test_expectedInterpolationIdentifier() {
-    // TODO(brianwilkerson) Does not recover.
-    //   RangeError: Value not in range: -1
-    //   dart:core                                                          _StringBase.substring
-    //   package:front_end/src/fasta/quote.dart 130:12                      unescapeLastStringPart
-    //   package:analyzer/src/fasta/ast_builder.dart 187:17                 AstBuilder.endLiteralString
-    //   test/generated/parser_fasta_listener.dart 896:14                   ForwardingTestListener.endLiteralString
-    //   package:front_end/src/fasta/parser/parser.dart 3497:14             Parser.parseSingleLiteralString
-    //   package:front_end/src/fasta/parser/parser.dart 3434:13             Parser.parseLiteralString
-    //   package:front_end/src/fasta/parser/parser.dart 3133:14             Parser.parsePrimary
-    //   package:front_end/src/fasta/parser/parser.dart 3097:14             Parser.parseUnaryExpression
-    //   package:front_end/src/fasta/parser/parser.dart 2968:13             Parser.parsePrecedenceExpression
-    //   package:front_end/src/fasta/parser/parser.dart 2942:11             Parser.parseExpression
-    //   test/generated/parser_fasta_test.dart 2929:39                      ParserProxy._run
-    super.test_expectedInterpolationIdentifier();
-  }
-
-  @override
-  @failingTest
-  void test_expectedInterpolationIdentifier_emptyString() {
-    // TODO(brianwilkerson) Does not recover.
-    //   RangeError: Value not in range: -1
-    //   dart:core                                                          _StringBase.substring
-    //   package:front_end/src/fasta/quote.dart 130:12                      unescapeLastStringPart
-    //   package:analyzer/src/fasta/ast_builder.dart 187:17                 AstBuilder.endLiteralString
-    //   test/generated/parser_fasta_listener.dart 896:14                   ForwardingTestListener.endLiteralString
-    //   package:front_end/src/fasta/parser/parser.dart 3497:14             Parser.parseSingleLiteralString
-    //   package:front_end/src/fasta/parser/parser.dart 3434:13             Parser.parseLiteralString
-    //   package:front_end/src/fasta/parser/parser.dart 3133:14             Parser.parsePrimary
-    //   package:front_end/src/fasta/parser/parser.dart 3097:14             Parser.parseUnaryExpression
-    //   package:front_end/src/fasta/parser/parser.dart 2968:13             Parser.parsePrecedenceExpression
-    //   package:front_end/src/fasta/parser/parser.dart 2942:11             Parser.parseExpression
-    //   test/generated/parser_fasta_test.dart 2929:39                      ParserProxy._run
-    super.test_expectedInterpolationIdentifier_emptyString();
-  }
-
-  @override
-  @failingTest
   void test_expectedListOrMapLiteral() {
     // TODO(brianwilkerson) Does not recover.
     //   type 'IntegerLiteralImpl' is not a subtype of type 'TypedLiteral' in type cast where
@@ -175,22 +137,6 @@
 
   @override
   @failingTest
-  void test_expectedToken_whileMissingInDoStatement() {
-    // TODO(brianwilkerson) Does not recover.
-    //   NoSuchMethodError: Class 'SimpleToken' has no instance getter 'endGroup'.
-    //   Receiver: Instance of 'SimpleToken'
-    //   Tried calling: endGroup
-    //   dart:core                                                          Object.noSuchMethod
-    //   package:front_end/src/fasta/parser/parser.dart 3212:26             Parser.parseParenthesizedExpression
-    //   package:front_end/src/fasta/parser/parser.dart 3781:13             Parser.parseDoWhileStatement
-    //   package:front_end/src/fasta/parser/parser.dart 2756:14             Parser.parseStatementX
-    //   package:front_end/src/fasta/parser/parser.dart 2722:20             Parser.parseStatement
-    //   test/generated/parser_fasta_test.dart 2973:39                      ParserProxy._run
-    super.test_expectedToken_whileMissingInDoStatement();
-  }
-
-  @override
-  @failingTest
   void test_getterInFunction_block_noReturnType() {
     // TODO(brianwilkerson) Does not recover.
     //   type 'ExpressionStatementImpl' is not a subtype of type 'FunctionDeclarationStatement' of 'statement' where
@@ -345,25 +291,6 @@
 
   @override
   @failingTest
-  void test_invalidInterpolationIdentifier_startWithDigit() {
-    // TODO(brianwilkerson) Does not recover.
-    //   RangeError: Value not in range: -1
-    //   dart:core                                                          _StringBase.substring
-    //   package:front_end/src/fasta/quote.dart 130:12                      unescapeLastStringPart
-    //   package:analyzer/src/fasta/ast_builder.dart 181:17                 AstBuilder.endLiteralString
-    //   test/generated/parser_fasta_listener.dart 896:14                   ForwardingTestListener.endLiteralString
-    //   package:front_end/src/fasta/parser/parser.dart 3497:14             Parser.parseSingleLiteralString
-    //   package:front_end/src/fasta/parser/parser.dart 3434:13             Parser.parseLiteralString
-    //   package:front_end/src/fasta/parser/parser.dart 3133:14             Parser.parsePrimary
-    //   package:front_end/src/fasta/parser/parser.dart 3097:14             Parser.parseUnaryExpression
-    //   package:front_end/src/fasta/parser/parser.dart 2968:13             Parser.parsePrecedenceExpression
-    //   package:front_end/src/fasta/parser/parser.dart 2942:11             Parser.parseExpression
-    //   test/generated/parser_fasta_test.dart 3196:39                      ParserProxy._run
-    super.test_invalidInterpolationIdentifier_startWithDigit();
-  }
-
-  @override
-  @failingTest
   void test_invalidOperatorAfterSuper_primaryExpression() {
     // TODO(brianwilkerson) Does not recover.
     //   Expected: true
@@ -681,38 +608,6 @@
 
   @override
   @failingTest
-  void test_missingFunctionParameters_local_nonVoid_block() {
-    // TODO(brianwilkerson) Wrong errors:
-    // Expected 1 errors of type ParserErrorCode.MISSING_FUNCTION_PARAMETERS, found 0
-    super.test_missingFunctionParameters_local_nonVoid_block();
-  }
-
-  @override
-  @failingTest
-  void test_missingFunctionParameters_local_nonVoid_expression() {
-    // TODO(brianwilkerson) Wrong errors:
-    // Expected 1 errors of type ParserErrorCode.MISSING_FUNCTION_PARAMETERS, found 0
-    super.test_missingFunctionParameters_local_nonVoid_expression();
-  }
-
-  @override
-  @failingTest
-  void test_missingFunctionParameters_local_void_block() {
-    // TODO(brianwilkerson) Wrong errors:
-    // Expected 1 errors of type ParserErrorCode.MISSING_FUNCTION_PARAMETERS, found 0
-    super.test_missingFunctionParameters_local_void_block();
-  }
-
-  @override
-  @failingTest
-  void test_missingFunctionParameters_local_void_expression() {
-    // TODO(brianwilkerson) Wrong errors:
-    // Expected 1 errors of type ParserErrorCode.MISSING_FUNCTION_PARAMETERS, found 0
-    super.test_missingFunctionParameters_local_void_expression();
-  }
-
-  @override
-  @failingTest
   void test_missingFunctionParameters_topLevel_void_block() {
     // TODO(brianwilkerson) Wrong errors:
     // Expected 1 errors of type ParserErrorCode.MISSING_FUNCTION_PARAMETERS, found 0
@@ -831,14 +726,6 @@
 
   @override
   @failingTest
-  void test_nonIdentifierLibraryName_library() {
-    // TODO(brianwilkerson) Wrong errors:
-    // Expected 1 errors of type ParserErrorCode.NON_IDENTIFIER_LIBRARY_NAME, found 0
-    super.test_nonIdentifierLibraryName_library();
-  }
-
-  @override
-  @failingTest
   void test_setterInFunction_block() {
     // TODO(brianwilkerson) Wrong errors:
     // Expected 1 errors of type ParserErrorCode.SETTER_IN_FUNCTION, found 0
@@ -1792,20 +1679,6 @@
 
   @override
   @failingTest
-  void test_incompleteLocalVariable_beforeIdentifier() {
-    // TODO(brianwilkerson) reportUnrecoverableErrorWithToken
-    super.test_incompleteLocalVariable_beforeIdentifier();
-  }
-
-  @override
-  @failingTest
-  void test_incompleteLocalVariable_beforeKeyword() {
-    // TODO(brianwilkerson) reportUnrecoverableErrorWithToken
-    super.test_incompleteLocalVariable_beforeKeyword();
-  }
-
-  @override
-  @failingTest
   void test_incompleteTypeArguments_field() {
     // TODO(brianwilkerson) reportUnrecoverableErrorWithToken
     super.test_incompleteTypeArguments_field();
diff --git a/pkg/analyzer/test/generated/parser_test.dart b/pkg/analyzer/test/generated/parser_test.dart
index 353465d..1154211 100644
--- a/pkg/analyzer/test/generated/parser_test.dart
+++ b/pkg/analyzer/test/generated/parser_test.dart
@@ -3076,7 +3076,7 @@
   void test_expectedInterpolationIdentifier() {
     StringLiteral literal = parseExpression("'\$x\$'", errors: [
       fe.Scanner.useFasta
-          ? expectedError(ScannerErrorCode.MISSING_IDENTIFIER, 3, 1)
+          ? expectedError(ScannerErrorCode.MISSING_IDENTIFIER, 4, 1)
           : expectedError(ParserErrorCode.MISSING_IDENTIFIER, 3, 1)
     ]);
     expectNotNullIfNoErrors(literal);
@@ -3130,15 +3130,10 @@
 
   void test_expectedToken_parseStatement_afterVoid() {
     parseStatement("void}", expectedEndOffset: 4);
-    listener.assertErrors(usingFastaParser
-        ? [
-            expectedError(ParserErrorCode.MISSING_STATEMENT, 0, 4),
-            expectedError(ParserErrorCode.EXPECTED_TOKEN, 4, 1)
-          ]
-        : [
-            expectedError(ParserErrorCode.EXPECTED_TOKEN, 4, 1),
-            expectedError(ParserErrorCode.MISSING_IDENTIFIER, 4, 1)
-          ]);
+    listener.assertErrors([
+      expectedError(ParserErrorCode.EXPECTED_TOKEN, 4, 1),
+      expectedError(ParserErrorCode.MISSING_IDENTIFIER, 4, 1)
+    ]);
   }
 
   void test_expectedToken_semicolonMissingAfterExport() {
@@ -3197,7 +3192,7 @@
   void test_expectedToken_whileMissingInDoStatement() {
     parseStatement("do {} (x);");
     listener
-        .assertErrors([expectedError(ParserErrorCode.EXPECTED_TOKEN, 9, 1)]);
+        .assertErrors([expectedError(ParserErrorCode.EXPECTED_TOKEN, 6, 1)]);
   }
 
   void test_expectedTypeName_as() {
@@ -3795,14 +3790,6 @@
     ]);
   }
 
-  void test_initializedVariableInForEach_var() {
-    Statement statement = parseStatement('for (var a = 0 in foo) {}');
-    expectNotNullIfNoErrors(statement);
-    listener.assertErrors([
-      expectedError(ParserErrorCode.INITIALIZED_VARIABLE_IN_FOR_EACH, 11, 1)
-    ]);
-  }
-
   void test_initializedVariableInForEach_annotation() {
     Statement statement = parseStatement('for (@Foo var a = 0 in foo) {}');
     expectNotNullIfNoErrors(statement);
@@ -3832,7 +3819,8 @@
     expectNotNullIfNoErrors(statement);
     listener.assertErrors(usingFastaParser
         ? [
-            expectedError(ParserErrorCode.EXPECTED_TOKEN, 7, 1),
+            expectedError(ParserErrorCode.EXPECTED_TOKEN, 8, 1),
+            expectedError(ParserErrorCode.MISSING_IDENTIFIER, 9, 1),
             expectedError(ParserErrorCode.EXPECTED_TOKEN, 10, 1)
           ]
         : [
@@ -3841,6 +3829,14 @@
           ]);
   }
 
+  void test_initializedVariableInForEach_var() {
+    Statement statement = parseStatement('for (var a = 0 in foo) {}');
+    expectNotNullIfNoErrors(statement);
+    listener.assertErrors([
+      expectedError(ParserErrorCode.INITIALIZED_VARIABLE_IN_FOR_EACH, 11, 1)
+    ]);
+  }
+
   void test_invalidAwaitInFor() {
     Statement statement = parseStatement('await for (; ;) {}');
     expectNotNullIfNoErrors(statement);
@@ -4103,16 +4099,27 @@
     expect(unit, isNotNull);
   }
 
+  void test_localFunction_annotation() {
+    CompilationUnit unit =
+        parseCompilationUnit("class C { m() { @Foo f() {} } }");
+    expect(unit.declarations, hasLength(1));
+    ClassDeclaration declaration = unit.declarations[0];
+    expect(declaration.members, hasLength(1));
+    MethodDeclaration member = declaration.members[0];
+    BlockFunctionBody body = member.body;
+    expect(body.block.statements, hasLength(1));
+    FunctionDeclarationStatement statement = body.block.statements[0];
+    if (usingFastaParser) {
+      expect(statement.functionDeclaration.metadata, hasLength(1));
+      Annotation metadata = statement.functionDeclaration.metadata[0];
+      expect(metadata.name.name, 'Foo');
+    }
+  }
+
   void test_localFunctionDeclarationModifier_abstract() {
     parseCompilationUnit("class C { m() { abstract f() {} } }",
         errors: usingFastaParser
-            ? [
-                expectedError(ParserErrorCode.EXTRANEOUS_MODIFIER, 16, 8),
-                expectedError(
-                    ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE, 25, 1),
-                expectedError(ParserErrorCode.EXPECTED_TOKEN, 26, 1),
-                expectedError(ParserErrorCode.EXPECTED_TOKEN, 32, 1),
-              ]
+            ? [expectedError(ParserErrorCode.EXTRANEOUS_MODIFIER, 16, 8)]
             : [
                 expectedError(
                     ParserErrorCode.LOCAL_FUNCTION_DECLARATION_MODIFIER, 16, 8)
@@ -4122,13 +4129,7 @@
   void test_localFunctionDeclarationModifier_external() {
     parseCompilationUnit("class C { m() { external f() {} } }",
         errors: usingFastaParser
-            ? [
-                expectedError(ParserErrorCode.EXTRANEOUS_MODIFIER, 16, 8),
-                expectedError(
-                    ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE, 25, 1),
-                expectedError(ParserErrorCode.EXPECTED_TOKEN, 26, 1),
-                expectedError(ParserErrorCode.EXPECTED_TOKEN, 32, 1),
-              ]
+            ? [expectedError(ParserErrorCode.EXTRANEOUS_MODIFIER, 16, 8)]
             : [
                 expectedError(
                     ParserErrorCode.LOCAL_FUNCTION_DECLARATION_MODIFIER, 16, 8)
@@ -4148,13 +4149,7 @@
   void test_localFunctionDeclarationModifier_static() {
     parseCompilationUnit("class C { m() { static f() {} } }",
         errors: usingFastaParser
-            ? [
-                expectedError(ParserErrorCode.EXTRANEOUS_MODIFIER, 16, 6),
-                expectedError(
-                    ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE, 23, 1),
-                expectedError(ParserErrorCode.EXPECTED_TOKEN, 24, 1),
-                expectedError(ParserErrorCode.EXPECTED_TOKEN, 30, 1),
-              ]
+            ? [expectedError(ParserErrorCode.EXTRANEOUS_MODIFIER, 16, 6)]
             : [
                 expectedError(
                     ParserErrorCode.LOCAL_FUNCTION_DECLARATION_MODIFIER, 16, 6)
@@ -4388,36 +4383,36 @@
         [expectedError(ParserErrorCode.MISSING_FUNCTION_BODY, 0, 6)]);
   }
 
-  @failingTest
   void test_missingFunctionParameters_local_nonVoid_block() {
     // The parser does not recognize this as a function declaration, so it tries
     // to parse it as an expression statement. It isn't clear what the best
     // error message is in this case.
-    parseStatement("int f { return x;}");
-    listener.assertErrors(
-        [expectedError(ParserErrorCode.MISSING_FUNCTION_PARAMETERS, 4, 1)]);
+    parseStatement("int f { return x;}", expectedEndOffset: 6);
+    listener
+        .assertErrors([expectedError(ParserErrorCode.EXPECTED_TOKEN, 6, 1)]);
   }
 
-  @failingTest
   void test_missingFunctionParameters_local_nonVoid_expression() {
     // The parser does not recognize this as a function declaration, so it tries
     // to parse it as an expression statement. It isn't clear what the best
     // error message is in this case.
     parseStatement("int f => x;");
-    listener.assertErrors(
-        [expectedError(ParserErrorCode.MISSING_FUNCTION_PARAMETERS, 4, 1)]);
+    listener.assertErrors(usingFastaParser
+        ? [expectedError(ParserErrorCode.MISSING_FUNCTION_PARAMETERS, 6, 2)]
+        : [expectedError(ParserErrorCode.EXPECTED_TOKEN, 0, 3)]);
   }
 
   void test_missingFunctionParameters_local_void_block() {
-    parseStatement("void f { return x;}");
-    listener.assertErrors(
-        [expectedError(ParserErrorCode.MISSING_FUNCTION_PARAMETERS, 5, 1)]);
+    parseStatement("void f { return x;}", expectedEndOffset: 7);
+    listener.assertErrors(usingFastaParser
+        ? [expectedError(ParserErrorCode.EXPECTED_TOKEN, 7, 1)]
+        : [expectedError(ParserErrorCode.MISSING_FUNCTION_PARAMETERS, 5, 1)]);
   }
 
   void test_missingFunctionParameters_local_void_expression() {
     parseStatement("void f => x;");
     listener.assertErrors(
-        [expectedError(ParserErrorCode.MISSING_FUNCTION_PARAMETERS, 5, 1)]);
+        [expectedError(ParserErrorCode.MISSING_FUNCTION_PARAMETERS, 7, 2)]);
   }
 
   void test_missingFunctionParameters_topLevel_nonVoid_block() {
@@ -4675,8 +4670,9 @@
 
   void test_missingStatement_afterVoid() {
     parseStatement("void;");
-    listener
-        .assertErrors([expectedError(ParserErrorCode.MISSING_STATEMENT, 0, 4)]);
+    listener.assertErrors(usingFastaParser
+        ? [expectedError(ParserErrorCode.MISSING_IDENTIFIER, 4, 1)]
+        : [expectedError(ParserErrorCode.MISSING_STATEMENT, 4, 1)]);
   }
 
   void test_missingTerminatorForParameterGroup_named() {
@@ -4849,7 +4845,9 @@
 
   void test_nonIdentifierLibraryName_library() {
     CompilationUnit unit = parseCompilationUnit("library 'lib';", errors: [
-      expectedError(ParserErrorCode.NON_IDENTIFIER_LIBRARY_NAME, 8, 5)
+      usingFastaParser
+          ? expectedError(ParserErrorCode.MISSING_IDENTIFIER, 8, 5)
+          : expectedError(ParserErrorCode.NON_IDENTIFIER_LIBRARY_NAME, 8, 5)
     ]);
     expect(unit, isNotNull);
   }
@@ -5547,7 +5545,7 @@
     // this would be a better error message.
     parseStatement("var int x;");
     listener.assertErrors(usingFastaParser
-        ? [expectedError(ParserErrorCode.VAR_AND_TYPE, 4, 3)]
+        ? [expectedError(ParserErrorCode.VAR_AND_TYPE, 0, 3)]
         : [expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 8, 1)]);
   }
 
@@ -13779,6 +13777,24 @@
     expect(identifier.name, name);
   }
 
+  void test_parseLibraryIdentifier_builtin() {
+    String name = "deferred";
+    LibraryIdentifier identifier = parseLibraryIdentifier(name);
+    expectNotNullIfNoErrors(identifier);
+    listener.assertNoErrors();
+    expect(identifier.name, name);
+    expect(identifier.beginToken.type.isBuiltIn, isTrue);
+  }
+
+  void test_parseLibraryIdentifier_pseudo() {
+    String name = "await";
+    LibraryIdentifier identifier = parseLibraryIdentifier(name);
+    expectNotNullIfNoErrors(identifier);
+    listener.assertNoErrors();
+    expect(identifier.name, name);
+    expect(identifier.beginToken.type.isPseudo, isTrue);
+  }
+
   void test_parseOptionalReturnType() {
     // TODO(brianwilkerson) Implement tests for this method.
   }
@@ -15257,8 +15273,17 @@
     expect(statement.finallyBlock, isNotNull);
   }
 
+  void test_parseVariableDeclaration_equals_builtIn() {
+    VariableDeclarationStatement statement = parseStatement('int set = 0;');
+    assertNoErrors();
+    expect(statement.semicolon, isNotNull);
+    VariableDeclarationList variableList = statement.variables;
+    expect(variableList, isNotNull);
+    expect(variableList.variables, hasLength(1));
+  }
+
   void test_parseVariableDeclarationListAfterMetadata_const_noType() {
-    var declarationList = parseVariableDeclarationList('const a');
+    var declarationList = parseVariableDeclarationList('const a = 0');
     assertNoErrors();
     expect(declarationList.keyword.lexeme, 'const');
     expect(declarationList.type, isNull);
@@ -16924,9 +16949,8 @@
     expect(declaration.propertyKeyword, isNotNull);
   }
 
-  @failingTest
   void test_parseGenericTypeAlias_noTypeParameters() {
-    createParser('F = int Function(int);');
+    createParser('typedef F = int Function(int);');
     GenericTypeAlias alias = parseFullCompilationUnitMember();
     expect(alias, isNotNull);
     assertNoErrors();
@@ -16938,9 +16962,8 @@
     expect(alias.semicolon, isNotNull);
   }
 
-  @failingTest
   void test_parseGenericTypeAlias_typeParameters() {
-    createParser('F<T> = T Function(T);');
+    createParser('typedef F<T> = T Function(T);');
     GenericTypeAlias alias = parseFullCompilationUnitMember();
     expect(alias, isNotNull);
     assertNoErrors();
diff --git a/pkg/analyzer/test/generated/utilities_test.dart b/pkg/analyzer/test/generated/utilities_test.dart
index b43805a..c184019 100644
--- a/pkg/analyzer/test/generated/utilities_test.dart
+++ b/pkg/analyzer/test/generated/utilities_test.dart
@@ -2903,7 +2903,7 @@
 
   void test_singleMap_empty() {
     Map<String, String> map = new HashMap<String, String>();
-    MultipleMapIterator<String, String> iterator = _iterator(<Map>[map]);
+    MultipleMapIterator<String, String> iterator = _iterator([map]);
     expect(iterator.moveNext(), isFalse);
     expect(() => iterator.key, throwsStateError);
     expect(() => iterator.value, throwsStateError);
@@ -2939,7 +2939,8 @@
     expect(iterator.moveNext(), isFalse);
   }
 
-  MultipleMapIterator<String, String> _iterator(List<Map> maps) {
+  MultipleMapIterator<String, String> _iterator(
+      List<Map<String, String>> maps) {
     return new MultipleMapIterator<String, String>(maps);
   }
 }
diff --git a/pkg/analyzer/test/source/analysis_options_provider_test.dart b/pkg/analyzer/test/source/analysis_options_provider_test.dart
index 222afd5..1b53283 100644
--- a/pkg/analyzer/test/source/analysis_options_provider_test.dart
+++ b/pkg/analyzer/test/source/analysis_options_provider_test.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-library analyzer.test.source.analysis_options_provider_test;
-
 import 'dart:core';
 
 import 'package:analyzer/file_system/file_system.dart';
@@ -11,11 +9,13 @@
 import 'package:analyzer/source/analysis_options_provider.dart';
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/source.dart';
+import 'package:analyzer/src/util/yaml.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 import 'package:yaml/yaml.dart';
 
 import '../resource_utils.dart';
+import '../src/util/yaml_test.dart';
 
 main() {
   defineReflectiveSuite(() {
@@ -28,7 +28,7 @@
       var defaultOptions = optionsProvider.getOptionsFromString(defaults);
       var overrideOptions = optionsProvider.getOptionsFromString(overrides);
       var merged = optionsProvider.merge(defaultOptions, overrideOptions);
-      expect(merged, optionsProvider.getOptionsFromString(expected));
+      expectEquals(merged, optionsProvider.getOptionsFromString(expected));
     }
 
     group('merging', () {
@@ -138,12 +138,12 @@
   ignore:
     - bar
 ''');
-    Map<String, YamlNode> options = _getOptions('/foo/bar', crawlUp: true);
+    YamlMap options = _getOptions('/foo/bar', crawlUp: true);
     expect(options, hasLength(1));
     {
-      YamlMap analyzer = options['analyzer'];
+      YamlMap analyzer = getValue(options, 'analyzer');
       expect(analyzer, isNotNull);
-      expect(analyzer['ignore'], unorderedEquals(['bar']));
+      expect(getValue(analyzer, 'ignore'), unorderedEquals(['bar']));
     }
   }
 
@@ -159,24 +159,24 @@
   ignore:
     - bar
 ''');
-    Map<String, YamlNode> options = _getOptions('/foo/bar/baz', crawlUp: true);
+    YamlMap options = _getOptions('/foo/bar/baz', crawlUp: true);
     expect(options, hasLength(1));
     {
-      YamlMap analyzer = options['analyzer'];
+      YamlMap analyzer = getValue(options, 'analyzer');
       expect(analyzer, isNotNull);
-      expect(analyzer['ignore'], unorderedEquals(['bar']));
+      expect(getValue(analyzer, 'ignore'), unorderedEquals(['bar']));
     }
   }
 
   void test_getOptions_doesNotExist() {
     pathTranslator.newFolder('/notFile');
-    Map<String, YamlNode> options = _getOptions('/notFile');
+    YamlMap options = _getOptions('/notFile');
     expect(options, isEmpty);
   }
 
   void test_getOptions_empty() {
     pathTranslator.newFile('/$optionsFileName', r'''#empty''');
-    Map<String, YamlNode> options = _getOptions('/');
+    YamlMap options = _getOptions('/');
     expect(options, isNotNull);
     expect(options, isEmpty);
   }
@@ -191,13 +191,13 @@
     pathTranslator.newFile('/$optionsFileName', r'''
 include: foo.include
 ''');
-    Map<String, YamlNode> options = _getOptions('/');
-    expect(options, hasLength(1));
+    YamlMap options = _getOptions('/');
+    expect(options, hasLength(2));
     {
-      YamlMap analyzer = options['analyzer'];
+      YamlMap analyzer = getValue(options, 'analyzer');
       expect(analyzer, hasLength(1));
       {
-        YamlList ignore = analyzer['ignore'];
+        YamlList ignore = getValue(analyzer, 'ignore');
         expect(ignore, hasLength(2));
         expect(ignore[0], 'ignoreme.dart');
         expect(ignore[1], 'sdk_ext/**');
@@ -209,15 +209,14 @@
     pathTranslator.newFile('/$optionsFileName', r'''
 include: /foo.include
 ''');
-    Map<String, YamlNode> options = _getOptions('/');
-    expect(options, hasLength(0));
+    YamlMap options = _getOptions('/');
+    expect(options, hasLength(1));
   }
 
   void test_getOptions_invalid() {
     pathTranslator.newFile('/$optionsFileName', r''':''');
-    expect(() {
-      _getOptions('/');
-    }, throwsException);
+    YamlMap options = _getOptions('/');
+    expect(options, hasLength(1));
   }
 
   void test_getOptions_simple() {
@@ -227,13 +226,13 @@
     - ignoreme.dart
     - 'sdk_ext/**'
 ''');
-    Map<String, YamlNode> options = _getOptions('/');
+    YamlMap options = _getOptions('/');
     expect(options, hasLength(1));
     {
-      YamlMap analyzer = options['analyzer'];
+      YamlMap analyzer = getValue(options, 'analyzer');
       expect(analyzer, hasLength(1));
       {
-        YamlList ignore = analyzer['ignore'];
+        YamlList ignore = getValue(analyzer, 'ignore');
         expect(ignore, hasLength(2));
         expect(ignore[0], 'ignoreme.dart');
         expect(ignore[1], 'sdk_ext/**');
@@ -241,7 +240,7 @@
     }
   }
 
-  Map<String, YamlNode> _getOptions(String posixPath, {bool crawlUp: false}) {
+  YamlMap _getOptions(String posixPath, {bool crawlUp: false}) {
     Resource resource = pathTranslator.getResource(posixPath);
     return provider.getOptions(resource, crawlUp: crawlUp);
   }
diff --git a/pkg/analyzer/test/source/error_processor_test.dart b/pkg/analyzer/test/source/error_processor_test.dart
index 5f632f4..7cf74fc 100644
--- a/pkg/analyzer/test/source/error_processor_test.dart
+++ b/pkg/analyzer/test/source/error_processor_test.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-library analyzer.test.source.error_processor;
-
 import 'package:analyzer/error/error.dart';
 import 'package:analyzer/source/analysis_options_provider.dart';
 import 'package:analyzer/source/error_processor.dart';
@@ -14,9 +12,10 @@
 import 'package:plugin/manager.dart';
 import 'package:plugin/plugin.dart';
 import 'package:test/test.dart';
-import 'package:yaml/src/yaml_node.dart';
+import 'package:yaml/yaml.dart';
 
 import '../generated/test_support.dart';
+import '../src/util/yaml_test.dart';
 
 main() {
   AnalysisError invalid_assignment =
@@ -124,11 +123,11 @@
       });
 
       test('string map', () {
-        var options = {
+        var options = wrap({
           'invalid_assignment': 'unsupported_action', // should be skipped
           'missing_return': 'false',
           'unused_local_variable': 'error'
-        };
+        });
         var errorConfig = new ErrorConfig(options);
         expect(errorConfig.processors, hasLength(2));
 
@@ -170,8 +169,7 @@
 ErrorProcessor processor;
 
 void configureOptions(String options) {
-  Map<String, YamlNode> optionMap =
-      optionsProvider.getOptionsFromString(options);
+  YamlMap optionMap = optionsProvider.getOptionsFromString(options);
   applyToAnalysisOptions(context.analysisOptions, optionMap);
 }
 
diff --git a/pkg/analyzer/test/src/dart/analysis/driver_test.dart b/pkg/analyzer/test/src/dart/analysis/driver_test.dart
index 32df76a..6d12d04 100644
--- a/pkg/analyzer/test/src/dart/analysis/driver_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/driver_test.dart
@@ -6725,26 +6725,6 @@
     expect(x.constantValue.toIntValue(), 1);
   }
 
-  test_currentSession() async {
-    var a = _p('/a.dart');
-
-    provider.newFile(a, 'var V = 1;');
-    await driver.getResult(a);
-
-    var session1 = driver.currentSession;
-    expect(session1, isNotNull);
-
-    provider.updateFile(a, 'var V = 2;');
-    driver.changeFile(a);
-    await driver.getResult(a);
-
-    var session2 = driver.currentSession;
-    expect(session2, isNotNull);
-
-    // We get a new session.
-    expect(session2, isNot(session1));
-  }
-
   test_errors_uriDoesNotExist_export() async {
     addTestFile(r'''
 export 'foo.dart';
diff --git a/pkg/analyzer/test/src/dart/analysis/session_helper_test.dart b/pkg/analyzer/test/src/dart/analysis/session_helper_test.dart
new file mode 100644
index 0000000..47c5338
--- /dev/null
+++ b/pkg/analyzer/test/src/dart/analysis/session_helper_test.dart
@@ -0,0 +1,84 @@
+// Copyright (c) 2018, 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:analyzer/src/dart/analysis/session_helper.dart';
+import 'package:test/test.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'base.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(AnalysisSessionHelperTest);
+  });
+}
+
+@reflectiveTest
+class AnalysisSessionHelperTest extends BaseAnalysisDriverTest {
+  AnalysisSessionHelper sessionHelper;
+
+  @override
+  void setUp() {
+    super.setUp();
+    sessionHelper = new AnalysisSessionHelper(driver.currentSession);
+  }
+
+  test_getClass_defined() async {
+    var path = _p('/c.dart');
+    var file = provider.newFile(path, r'''
+class C {}
+int v = 0;
+''');
+    String uri = file.toUri().toString();
+
+    var element = await sessionHelper.getClass(uri, 'C');
+    expect(element, isNotNull);
+    expect(element.displayName, 'C');
+  }
+
+  test_getClass_defined_notClass() async {
+    var path = _p('/c.dart');
+    var file = provider.newFile(path, r'''
+int v = 0;
+''');
+    String uri = file.toUri().toString();
+
+    var element = await sessionHelper.getClass(uri, 'v');
+    expect(element, isNull);
+  }
+
+  test_getClass_exported() async {
+    var a = _p('/a.dart');
+    var b = _p('/b.dart');
+    provider.newFile(a, r'''
+class A {}
+''');
+    var bFile = provider.newFile(b, r'''
+export 'a.dart';
+''');
+    String bUri = bFile.toUri().toString();
+
+    var element = await sessionHelper.getClass(bUri, 'A');
+    expect(element, isNotNull);
+    expect(element.displayName, 'A');
+  }
+
+  test_getClass_imported() async {
+    var a = _p('/a.dart');
+    var b = _p('/b.dart');
+    provider.newFile(a, r'''
+class A {}
+''');
+    var bFile = provider.newFile(b, r'''
+import 'a.dart';
+''');
+    String bUri = bFile.toUri().toString();
+
+    var element = await sessionHelper.getClass(bUri, 'A');
+    expect(element, isNull);
+  }
+
+  /// Return the [provider] specific path for the given Posix [path].
+  String _p(String path) => provider.convertPath(path);
+}
diff --git a/pkg/analyzer/test/src/dart/analysis/test_all.dart b/pkg/analyzer/test/src/dart/analysis/test_all.dart
index 4563972..0654881 100644
--- a/pkg/analyzer/test/src/dart/analysis/test_all.dart
+++ b/pkg/analyzer/test/src/dart/analysis/test_all.dart
@@ -12,6 +12,7 @@
 import 'mutex_test.dart' as mutex;
 import 'referenced_names_test.dart' as referenced_names;
 import 'search_test.dart' as search_test;
+import 'session_helper_test.dart' as session_helper_test;
 import 'session_test.dart' as session_test;
 
 main() {
@@ -24,6 +25,7 @@
     mutex.main();
     referenced_names.main();
     search_test.main();
+    session_helper_test.main();
     session_test.main();
   }, name: 'analysis');
 }
diff --git a/pkg/analyzer/test/src/fasta/recovery/partial_code/do_statement_test.dart b/pkg/analyzer/test/src/fasta/recovery/partial_code/do_statement_test.dart
index 599953c..b8eb3ff 100644
--- a/pkg/analyzer/test/src/fasta/recovery/partial_code/do_statement_test.dart
+++ b/pkg/analyzer/test/src/fasta/recovery/partial_code/do_statement_test.dart
@@ -55,7 +55,7 @@
                 ParserErrorCode.EXPECTED_TOKEN
               ],
               "do {} while (_s_);",
-              allFailing: true),
+              failing: ['while']),
           new TestDescriptor(
               'while',
               'do {} while',
diff --git a/pkg/analyzer/test/src/fasta/recovery/partial_code/for_statement_test.dart b/pkg/analyzer/test/src/fasta/recovery/partial_code/for_statement_test.dart
index cebc90d..9aac678 100644
--- a/pkg/analyzer/test/src/fasta/recovery/partial_code/for_statement_test.dart
+++ b/pkg/analyzer/test/src/fasta/recovery/partial_code/for_statement_test.dart
@@ -12,32 +12,40 @@
 
 class ForStatementTest extends PartialCodeTest {
   buildAll() {
+    List<String> allExceptEof =
+        PartialCodeTest.statementSuffixes.map((t) => t.name).toList();
     buildTests(
         'for_statement',
         [
+          new TestDescriptor('keyword', 'for', [ParserErrorCode.EXPECTED_TOKEN],
+              'for (;;) {}'),
           new TestDescriptor(
-              'keyword',
-              'for',
+              'emptyParen',
+              'for ()',
               [
+                ParserErrorCode.MISSING_IDENTIFIER,
                 ParserErrorCode.EXPECTED_TOKEN,
+                ParserErrorCode.MISSING_IDENTIFIER,
                 ParserErrorCode.EXPECTED_TOKEN,
-                ParserErrorCode.EXPECTED_TOKEN,
-                ParserErrorCode.EXPECTED_TOKEN,
+                ParserErrorCode.MISSING_IDENTIFIER,
                 ParserErrorCode.EXPECTED_TOKEN
               ],
-              'for (;;) {}',
-              allFailing: true),
+              "for (_s_;_s_;) _s_;",
+              failing: allExceptEof),
           new TestDescriptor(
               'leftParen',
               'for (',
               [
+                ParserErrorCode.MISSING_IDENTIFIER,
                 ParserErrorCode.EXPECTED_TOKEN,
+                ParserErrorCode.MISSING_IDENTIFIER,
                 ParserErrorCode.EXPECTED_TOKEN,
-                ParserErrorCode.EXPECTED_TOKEN,
+                ScannerErrorCode.EXPECTED_TOKEN,
+                ParserErrorCode.MISSING_IDENTIFIER,
                 ParserErrorCode.EXPECTED_TOKEN
               ],
-              "for (;;) {}",
-              allFailing: true),
+              "for (_s_;_s_;) _s_;",
+              failing: allExceptEof),
           new TestDescriptor(
               'var',
               'for (var',
@@ -48,61 +56,79 @@
                 ParserErrorCode.EXPECTED_TOKEN,
                 ParserErrorCode.EXPECTED_TOKEN
               ],
-              "for (var _s_;;) {}",
+              "for (var _s_;;) _s_;",
               allFailing: true),
           new TestDescriptor(
               'varAndIdentifier',
               'for (var i',
               [
                 ParserErrorCode.EXPECTED_TOKEN,
+                ParserErrorCode.MISSING_IDENTIFIER,
                 ParserErrorCode.EXPECTED_TOKEN,
-                ParserErrorCode.EXPECTED_TOKEN,
+                ScannerErrorCode.EXPECTED_TOKEN,
+                ParserErrorCode.MISSING_IDENTIFIER,
                 ParserErrorCode.EXPECTED_TOKEN
               ],
-              "for (var i;;) {}",
-              allFailing: true),
+              "for (var i;_s_;) _s_;",
+              failing: allExceptEof),
           new TestDescriptor(
               'equals',
               'for (var i =',
               [
                 ParserErrorCode.MISSING_IDENTIFIER,
                 ParserErrorCode.EXPECTED_TOKEN,
+                ParserErrorCode.MISSING_IDENTIFIER,
                 ParserErrorCode.EXPECTED_TOKEN,
-                ParserErrorCode.EXPECTED_TOKEN,
+                ScannerErrorCode.EXPECTED_TOKEN,
+                ParserErrorCode.MISSING_IDENTIFIER,
                 ParserErrorCode.EXPECTED_TOKEN
               ],
-              "for (var i = _s_;;) {}",
-              allFailing: true),
+              "for (var i = _s_;_s_;) _s_;",
+              failing: allExceptEof),
           new TestDescriptor(
               'initializer',
               'for (var i = 0',
               [
                 ParserErrorCode.EXPECTED_TOKEN,
+                ParserErrorCode.MISSING_IDENTIFIER,
                 ParserErrorCode.EXPECTED_TOKEN,
-                ParserErrorCode.EXPECTED_TOKEN,
+                ScannerErrorCode.EXPECTED_TOKEN,
+                ParserErrorCode.MISSING_IDENTIFIER,
                 ParserErrorCode.EXPECTED_TOKEN
               ],
-              "for (var i = 0;;) {}",
-              allFailing: true),
+              "for (var i = 0;_s_;) _s_;",
+              failing: allExceptEof),
           new TestDescriptor(
               'firstSemicolon',
               'for (var i = 0;',
               [
+                ParserErrorCode.MISSING_IDENTIFIER,
                 ParserErrorCode.EXPECTED_TOKEN,
-                ParserErrorCode.EXPECTED_TOKEN,
+                ScannerErrorCode.EXPECTED_TOKEN,
+                ParserErrorCode.MISSING_IDENTIFIER,
                 ParserErrorCode.EXPECTED_TOKEN
               ],
-              "for (var i = 0;;) {}",
-              allFailing: true),
+              "for (var i = 0;_s_;) _s_;",
+              failing: allExceptEof),
           new TestDescriptor(
               'secondSemicolon',
               'for (var i = 0;;',
-              [ParserErrorCode.EXPECTED_TOKEN, ParserErrorCode.EXPECTED_TOKEN],
-              "for (var i = 0;;) {}",
-              allFailing: true),
-          new TestDescriptor('rightParen', 'for (var i = 0;;)',
-              [ParserErrorCode.EXPECTED_TOKEN], "for (var i = 0;;) {}",
-              allFailing: true),
+              [
+                ScannerErrorCode.EXPECTED_TOKEN,
+                ParserErrorCode.MISSING_IDENTIFIER,
+                ParserErrorCode.EXPECTED_TOKEN
+              ],
+              "for (var i = 0;;) _s_;",
+              failing: allExceptEof),
+          new TestDescriptor(
+              'rightParen',
+              'for (var i = 0;;)',
+              [
+                ParserErrorCode.MISSING_IDENTIFIER,
+                ParserErrorCode.EXPECTED_TOKEN
+              ],
+              "for (var i = 0;;) _s_;",
+              failing: allExceptEof),
         ],
         PartialCodeTest.statementSuffixes,
         head: 'f() { ',
diff --git a/pkg/analyzer/test/src/fasta/recovery/partial_code/library_directive_test.dart b/pkg/analyzer/test/src/fasta/recovery/partial_code/library_directive_test.dart
index cf68d9c..ba1d480 100644
--- a/pkg/analyzer/test/src/fasta/recovery/partial_code/library_directive_test.dart
+++ b/pkg/analyzer/test/src/fasta/recovery/partial_code/library_directive_test.dart
@@ -12,20 +12,6 @@
 
 class LibraryDirectivesTest extends PartialCodeTest {
   buildAll() {
-    List<String> allExceptEof = <String>[
-      'import',
-      'export',
-      'part',
-      'class',
-      'typedef',
-      'functionVoid',
-      'functionNonVoid',
-      'var',
-      'const',
-      'final',
-      'getter',
-      'setter'
-    ];
     buildTests(
         'library_directive',
         [
@@ -37,7 +23,7 @@
                 ParserErrorCode.EXPECTED_TOKEN
               ],
               'library _s_;',
-              failing: allExceptEof),
+              failing: ['functionNonVoid', 'getter']),
           new TestDescriptor('name', 'library lib',
               [ParserErrorCode.EXPECTED_TOKEN], 'library lib;'),
           new TestDescriptor(
@@ -48,7 +34,7 @@
                 ParserErrorCode.EXPECTED_TOKEN
               ],
               'library lib._s_;',
-              failing: allExceptEof),
+              failing: ['functionNonVoid', 'getter']),
           new TestDescriptor('nameDotName', 'library lib.a',
               [ParserErrorCode.EXPECTED_TOKEN], 'library lib.a;'),
         ],
diff --git a/pkg/analyzer/test/src/fasta/recovery/partial_code/local_variable_test.dart b/pkg/analyzer/test/src/fasta/recovery/partial_code/local_variable_test.dart
index 4c2f010..7a54709 100644
--- a/pkg/analyzer/test/src/fasta/recovery/partial_code/local_variable_test.dart
+++ b/pkg/analyzer/test/src/fasta/recovery/partial_code/local_variable_test.dart
@@ -44,39 +44,12 @@
           new TestDescriptor('constName', 'const a',
               [ParserErrorCode.EXPECTED_TOKEN], "const a;",
               failing: <String>[
-                'assert',
-                'break',
-                'continue',
-                'do',
-                'if',
-                'for',
+                'eof',
                 'labeled',
                 'localFunctionNonVoid',
-                'localFunctionVoid',
-                'localVariable',
-                'switch',
-                'try',
-                'return',
-                'while'
               ]),
           new TestDescriptor('constTypeName', 'const int a',
-              [ParserErrorCode.EXPECTED_TOKEN], "const int a;",
-              failing: <String>[
-                'assert',
-                'break',
-                'continue',
-                'do',
-                'if',
-                'for',
-                'labeled',
-                'localFunctionNonVoid',
-                'localFunctionVoid',
-                'localVariable',
-                'switch',
-                'try',
-                'return',
-                'while'
-              ]),
+              [ParserErrorCode.EXPECTED_TOKEN], "const int a;"),
           new TestDescriptor(
               'constNameComma',
               'const a,',
@@ -157,23 +130,7 @@
               "int _s_;",
               allFailing: true),
           new TestDescriptor(
-              'typeName', 'int a', [ParserErrorCode.EXPECTED_TOKEN], "int a;",
-              failing: [
-                'assert',
-                'break',
-                'continue',
-                'do',
-                'if',
-                'for',
-                'labeled',
-                'localFunctionNonVoid',
-                'localFunctionVoid',
-                'localVariable',
-                'switch',
-                'try',
-                'return',
-                'while'
-              ]),
+              'typeName', 'int a', [ParserErrorCode.EXPECTED_TOKEN], "int a;"),
           new TestDescriptor(
               'var',
               'var',
diff --git a/pkg/analyzer/test/src/lint/config_test.dart b/pkg/analyzer/test/src/lint/config_test.dart
index 44f385d..2b44f9b 100644
--- a/pkg/analyzer/test/src/lint/config_test.dart
+++ b/pkg/analyzer/test/src/lint/config_test.dart
@@ -5,6 +5,8 @@
 import 'package:analyzer/src/lint/config.dart';
 import 'package:test/test.dart';
 
+import '../util/yaml_test.dart';
+
 main() {
   defineTests();
 }
@@ -145,7 +147,7 @@
         };
         options['linter'] = lintOptions;
 
-        var config = parseConfig(options);
+        var config = parseConfig(wrap(options));
         expect(config, isNotNull);
         expect(config.ruleConfigs, hasLength(1));
       });
@@ -157,7 +159,7 @@
         };
         options['linter'] = lintOptions;
 
-        var config = parseConfig(options);
+        var config = parseConfig(wrap(options));
         expect(config, isNotNull);
         expect(config.ruleConfigs, hasLength(1));
       });
@@ -169,7 +171,7 @@
         };
         options['linter'] = lintOptions;
 
-        var config = parseConfig(options);
+        var config = parseConfig(wrap(options));
         expect(config, isNotNull);
         expect(config.ruleConfigs, hasLength(1));
       });
@@ -183,7 +185,7 @@
         };
         options['linter'] = lintOptions;
 
-        var config = parseConfig(options);
+        var config = parseConfig(wrap(options));
         expect(config, isNotNull);
         expect(config.ruleConfigs, hasLength(1));
       });
@@ -197,7 +199,7 @@
         };
         options['linter'] = lintOptions;
 
-        var config = parseConfig(options);
+        var config = parseConfig(wrap(options));
         expect(config, isNotNull);
         expect(config.ruleConfigs, hasLength(1));
       });
diff --git a/pkg/analyzer/test/src/task/options_test.dart b/pkg/analyzer/test/src/task/options_test.dart
index 4d5bb5e..6bec4ec 100644
--- a/pkg/analyzer/test/src/task/options_test.dart
+++ b/pkg/analyzer/test/src/task/options_test.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-library analyzer.test.src.task.options_test;
-
 import 'dart:mirrors';
 
 import 'package:analyzer/analyzer.dart';
@@ -49,7 +47,7 @@
   void configureContext(String optionsSource) =>
       applyToAnalysisOptions(analysisOptions, parseOptions(optionsSource));
 
-  Map<String, YamlNode> parseOptions(String source) =>
+  YamlMap parseOptions(String source) =>
       optionsProvider.getOptionsFromString(source);
 
   test_configure_bad_options_contents() {
@@ -361,7 +359,9 @@
     expect(descriptor, isNotNull);
   }
 
+  @failingTest
   test_perform_bad_yaml() {
+    // We have lost the ability to detect this kind of error.
     String code = r'''
 :
 ''';
@@ -410,7 +410,9 @@
     expect(error.message, contains('other_options.yaml(47..49)'));
   }
 
+  @failingTest
   test_perform_include_bad_yaml() {
+    // We have lost the ability to detect this kind of error.
     newSource('/other_options.yaml', ':');
     String code = r'''
 include: other_options.yaml
@@ -703,7 +705,7 @@
         ]));
   }
 
-  Map<String, YamlNode> _getOptions(String posixPath, {bool crawlUp: false}) {
+  YamlMap _getOptions(String posixPath, {bool crawlUp: false}) {
     Resource resource = pathTranslator.getResource(posixPath);
     return provider.getOptions(resource, crawlUp: crawlUp);
   }
diff --git a/pkg/analyzer/test/src/util/yaml_test.dart b/pkg/analyzer/test/src/util/yaml_test.dart
index 4e109ac..ca6054f 100644
--- a/pkg/analyzer/test/src/util/yaml_test.dart
+++ b/pkg/analyzer/test/src/util/yaml_test.dart
@@ -2,10 +2,10 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-library analyzer.src.test.util.yaml_test;
-
 import 'package:analyzer/src/util/yaml.dart';
 import 'package:test/test.dart';
+import 'package:yaml/src/event.dart';
+import 'package:yaml/yaml.dart';
 
 main() {
   group('yaml', () {
@@ -25,7 +25,7 @@
               },
               'seven': true
             }),
-            equals({
+            equals(wrap({
               'one': true,
               'two': false,
               'three': {
@@ -33,18 +33,20 @@
                 'five': true
               },
               'seven': true
-            }));
+            })));
       });
 
       test('list', () {
-        expect(merge([1, 2, 3], [2, 3, 4, 5]), equals([1, 2, 3, 4, 5]));
+        expect(merge([1, 2, 3], [2, 3, 4, 5]), equals(wrap([1, 2, 3, 4, 5])));
       });
 
       test('list w/ promotion', () {
-        expect(merge(['one', 'two', 'three'], {'three': false, 'four': true}),
-            equals({'one': true, 'two': true, 'three': false, 'four': true}));
+        expect(
+            merge(['one', 'two', 'three'], {'three': false, 'four': true}),
+            equals(wrap(
+                {'one': true, 'two': true, 'three': false, 'four': true})));
         expect(merge({'one': false, 'two': false}, ['one', 'three']),
-            equals({'one': true, 'two': false, 'three': true}));
+            equals(wrap({'one': true, 'two': false, 'three': true})));
       });
 
       test('map w/ list promotion', () {
@@ -57,7 +59,7 @@
         var map3 = {
           'one': {'a': true, 'b': false, 'c': true}
         };
-        expect(merge(map1, map2), map3);
+        expect(merge(map1, map2), wrap(map3));
       });
 
       test('map w/ no promotion', () {
@@ -70,7 +72,7 @@
         var map3 = {
           'one': {'a': 'foo', 'b': 'bar'}
         };
-        expect(merge(map1, map2), map3);
+        expect(merge(map1, map2), wrap(map3));
       });
 
       test('map w/ no promotion (2)', () {
@@ -83,7 +85,7 @@
         var map3 = {
           'one': ['a', 'b', 'c']
         };
-        expect(merge(map1, map2), map3);
+        expect(merge(map1, map2), wrap(map3));
       });
 
       test('object', () {
@@ -97,4 +99,77 @@
 
 final Merger merger = new Merger();
 
-Object merge(Object o1, Object o2) => merger.merge(o1, o2);
+bool containsKey(Map<dynamic, YamlNode> map, dynamic key) =>
+    _getValue(map, key) != null;
+
+void expectEquals(YamlNode actual, YamlNode expected) {
+  if (expected is YamlScalar) {
+    expect(actual, new isInstanceOf<YamlScalar>());
+    expect(expected.value, actual.value);
+  } else if (expected is YamlList) {
+    if (actual is YamlList) {
+      expect(actual.length, expected.length);
+      List<YamlNode> expectedNodes = expected.nodes;
+      List<YamlNode> actualNodes = actual.nodes;
+      for (int i = 0; i < expectedNodes.length; i++) {
+        expectEquals(actualNodes[i], expectedNodes[i]);
+      }
+    } else {
+      fail('Expected a YamlList, found ${actual.runtimeType}');
+    }
+  } else if (expected is YamlMap) {
+    if (actual is YamlMap) {
+      expect(actual.length, expected.length);
+      Map<dynamic, YamlNode> expectedNodes = expected.nodes;
+      Map<dynamic, YamlNode> actualNodes = actual.nodes;
+      for (var expectedKey in expectedNodes.keys) {
+        if (!containsKey(actualNodes, expectedKey)) {
+          fail('Missing key $expectedKey');
+        }
+      }
+      for (var actualKey in actualNodes.keys) {
+        if (!containsKey(expectedNodes, actualKey)) {
+          fail('Extra key $actualKey');
+        }
+      }
+      for (var expectedKey in expectedNodes.keys) {
+        expectEquals(_getValue(actualNodes, expectedKey),
+            _getValue(expectedNodes, expectedKey));
+      }
+    } else {
+      fail('Expected a YamlMap, found ${actual.runtimeType}');
+    }
+  } else {
+    fail('Unknown type of node: ${expected.runtimeType}');
+  }
+}
+
+Object merge(Object o1, Object o2) => merger.merge(wrap(o1), wrap(o2)).value;
+
+Object valueOf(Object object) => object is YamlNode ? object.value : object;
+
+YamlNode wrap(Object value) {
+  if (value is List) {
+    List wrappedElements = value.map((e) => wrap(e)).toList();
+    return new YamlList.internal(wrappedElements, null, CollectionStyle.BLOCK);
+  } else if (value is Map) {
+    Map<dynamic, YamlNode> wrappedEntries = <dynamic, YamlNode>{};
+    value.forEach((k, v) {
+      wrappedEntries[wrap(k)] = wrap(v);
+    });
+    return new YamlMap.internal(wrappedEntries, null, CollectionStyle.BLOCK);
+  } else {
+    return new YamlScalar.internal(
+        value, new ScalarEvent(null, '', ScalarStyle.PLAIN));
+  }
+}
+
+YamlNode _getValue(Map map, Object key) {
+  Object keyValue = valueOf(key);
+  for (var existingKey in map.keys) {
+    if (valueOf(existingKey) == keyValue) {
+      return map[existingKey];
+    }
+  }
+  return null;
+}
diff --git a/pkg/analyzer/tool/summary/mini_ast.dart b/pkg/analyzer/tool/summary/mini_ast.dart
index 6e3b75d..f2bbd10 100644
--- a/pkg/analyzer/tool/summary/mini_ast.dart
+++ b/pkg/analyzer/tool/summary/mini_ast.dart
@@ -379,7 +379,8 @@
   }
 
   @override
-  void endTopLevelFields(int count, Token beginToken, Token endToken) {
+  void endTopLevelFields(Token staticToken, Token covariantToken,
+      Token varFinalOrConst, int count, Token beginToken, Token endToken) {
     // We ignore top level variable declarations; they are present just to make
     // the IDL analyze without warnings.
     debugEvent("TopLevelFields");
diff --git a/pkg/analyzer_cli/lib/src/driver.dart b/pkg/analyzer_cli/lib/src/driver.dart
index 59ad0f0..c306703 100644
--- a/pkg/analyzer_cli/lib/src/driver.dart
+++ b/pkg/analyzer_cli/lib/src/driver.dart
@@ -34,6 +34,7 @@
 import 'package:analyzer/src/summary/package_bundle_reader.dart';
 import 'package:analyzer/src/summary/summary_sdk.dart' show SummaryBasedDartSdk;
 import 'package:analyzer/src/task/options.dart';
+import 'package:analyzer/src/util/yaml.dart';
 import 'package:analyzer_cli/src/analyzer_impl.dart';
 import 'package:analyzer_cli/src/batch_mode.dart';
 import 'package:analyzer_cli/src/build_mode.dart';
@@ -76,9 +77,9 @@
     telemetry.createAnalyticsInstance(_analyticsID, 'analyzer-cli'));
 
 /// Test this option map to see if it specifies lint rules.
-bool containsLintRuleEntry(Map<String, YamlNode> options) {
-  var linterNode = options['linter'];
-  return linterNode is YamlMap && linterNode.containsKey('rules');
+bool containsLintRuleEntry(YamlMap options) {
+  YamlNode linterNode = getValue(options, 'linter');
+  return linterNode is YamlMap && getValue(linterNode, 'rules') != null;
 }
 
 /// Make sure that we create an analytics instance that doesn't send for this
diff --git a/pkg/analyzer_cli/pubspec.yaml b/pkg/analyzer_cli/pubspec.yaml
index 0db8c4a..f0e587d 100644
--- a/pkg/analyzer_cli/pubspec.yaml
+++ b/pkg/analyzer_cli/pubspec.yaml
@@ -19,6 +19,5 @@
   yaml: ^2.1.2
 dev_dependencies:
   test_reflective_loader: ^0.1.0
-  mockito: ^2.0.2
   test: ^0.12.0
   usage: ^3.2.0+1
diff --git a/pkg/analyzer_cli/test/driver_test.dart b/pkg/analyzer_cli/test/driver_test.dart
index f638da8..3a51631 100644
--- a/pkg/analyzer_cli/test/driver_test.dart
+++ b/pkg/analyzer_cli/test/driver_test.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-library analyzer_cli.test.driver;
-
 import 'dart:async';
 import 'dart:io';
 
@@ -36,7 +34,8 @@
     // defineReflectiveTests(ExitCodesTest_UseCFE);
     defineReflectiveTests(LinterTest);
     defineReflectiveTests(LinterTest_PreviewDart2);
-    defineReflectiveTests(LinterTest_UseCFE);
+    // Disabled until integration with the CFE has been restarted.
+//    defineReflectiveTests(LinterTest_UseCFE);
     defineReflectiveTests(NonDartFilesTest);
     defineReflectiveTests(OptionsTest);
     defineReflectiveTests(OptionsTest_PreviewDart2);
@@ -699,8 +698,7 @@
   String get optionsFileName => AnalysisEngine.ANALYSIS_OPTIONS_YAML_FILE;
 
   test_containsLintRuleEntry() async {
-    Map<String, YamlNode> options;
-    options = _parseOptions('''
+    YamlMap options = _parseOptions('''
 linter:
   rules:
     - foo
@@ -772,7 +770,7 @@
     expect(getLints(driver.context), isEmpty);
   }
 
-  Map<String, YamlNode> _parseOptions(String src) =>
+  YamlMap _parseOptions(String src) =>
       new AnalysisOptionsProvider().getOptionsFromString(src);
 
   Future<Null> _runLinter_defaultLints() async {
diff --git a/pkg/analyzer_cli/test/mocks.dart b/pkg/analyzer_cli/test/mocks.dart
index 3cc6ebbd..4231d3c 100644
--- a/pkg/analyzer_cli/test/mocks.dart
+++ b/pkg/analyzer_cli/test/mocks.dart
@@ -2,26 +2,179 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-library analyzer_cli.test.mocks;
-
 import 'package:analyzer/analyzer.dart';
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer_cli/src/options.dart';
-import 'package:mockito/mockito.dart';
 
-class MockAnalysisError extends Mock implements AnalysisError {}
+class MockAnalysisError implements AnalysisError {
+  @override
+  MockSource source;
 
-class MockAnalysisErrorInfo extends Mock implements AnalysisErrorInfo {}
+  @override
+  MockErrorCode errorCode;
 
-class MockCommandLineOptions extends Mock implements CommandLineOptions {}
+  @override
+  int offset;
 
-class MockErrorCode extends Mock implements ErrorCode {}
+  @override
+  String message;
 
-class MockErrorType extends Mock implements ErrorType {}
+  @override
+  bool isStaticOnly;
 
-class MockLineInfo extends Mock implements LineInfo {}
+  @override
+  int length;
 
-class MockLineInfo_Location extends Mock implements LineInfo_Location {}
+  MockAnalysisError(this.source, this.errorCode, this.offset, this.message);
 
-class MockSource extends Mock implements Source {}
+  @override
+  String get correction => null;
+}
+
+class MockAnalysisErrorInfo implements AnalysisErrorInfo {
+  @override
+  LineInfo lineInfo;
+
+  @override
+  List<AnalysisError> errors;
+
+  MockAnalysisErrorInfo(this.lineInfo, this.errors);
+}
+
+class MockCommandLineOptions implements CommandLineOptions {
+  bool enableTypeChecks = false;
+  bool infosAreFatal = false;
+  bool machineFormat = false;
+  bool verbose = false;
+  bool color = false;
+
+  noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
+}
+
+class MockErrorCode implements ErrorCode {
+  @override
+  ErrorType type;
+
+  @override
+  ErrorSeverity errorSeverity;
+
+  @override
+  String name;
+
+  MockErrorCode(this.type, this.errorSeverity, this.name);
+
+  @override
+  String get correction {
+    throw new StateError('Unexpected invocation of correction');
+  }
+
+  @override
+  String get message {
+    throw new StateError('Unexpected invocation of message');
+  }
+
+  @override
+  String get uniqueName {
+    throw new StateError('Unexpected invocation of uniqueName');
+  }
+}
+
+class MockLineInfo implements LineInfo {
+  MockLineInfo_Location defaultLocation;
+
+  MockLineInfo({this.defaultLocation});
+
+  @override
+  int get lineCount {
+    throw new StateError('Unexpected invocation of lineCount');
+  }
+
+  @override
+  List<int> get lineStarts {
+    throw new StateError('Unexpected invocation of lineStarts');
+  }
+
+  @override
+  LineInfo_Location getLocation(int offset) {
+    if (defaultLocation != null) {
+      return defaultLocation;
+    }
+    throw new StateError('Unexpected invocation of getLocation');
+  }
+
+  @override
+  int getOffsetOfLine(int lineNumber) {
+    throw new StateError('Unexpected invocation of getOffsetOfLine');
+  }
+
+  @override
+  int getOffsetOfLineAfter(int offset) {
+    throw new StateError('Unexpected invocation of getOffsetOfLineAfter');
+  }
+}
+
+class MockLineInfo_Location implements LineInfo_Location {
+  @override
+  int lineNumber;
+
+  @override
+  int columnNumber;
+
+  MockLineInfo_Location(this.lineNumber, this.columnNumber);
+}
+
+class MockSource implements Source {
+  @override
+  String fullName;
+
+  MockSource(this.fullName);
+
+  @override
+  TimestampedData<String> get contents {
+    throw new StateError('Unexpected invocation of contents');
+  }
+
+  @override
+  String get encoding {
+    throw new StateError('Unexpected invocation of encoding');
+  }
+
+  @override
+  bool get isInSystemLibrary {
+    throw new StateError('Unexpected invocation of isInSystemLibrary');
+  }
+
+  @override
+  Source get librarySource {
+    throw new StateError('Unexpected invocation of librarySource');
+  }
+
+  @override
+  int get modificationStamp {
+    throw new StateError('Unexpected invocation of modificationStamp');
+  }
+
+  @override
+  String get shortName {
+    throw new StateError('Unexpected invocation of shortName');
+  }
+
+  @override
+  Source get source {
+    throw new StateError('Unexpected invocation of source');
+  }
+
+  @override
+  Uri get uri {
+    throw new StateError('Unexpected invocation of uri');
+  }
+
+  @override
+  UriKind get uriKind => null; //UriKind.FILE_URI;
+
+  @override
+  bool exists() {
+    throw new StateError('Unexpected invocation of exists');
+  }
+}
diff --git a/pkg/analyzer_cli/test/reporter_test.dart b/pkg/analyzer_cli/test/reporter_test.dart
index d5de24c..4f4bc85 100644
--- a/pkg/analyzer_cli/test/reporter_test.dart
+++ b/pkg/analyzer_cli/test/reporter_test.dart
@@ -2,14 +2,11 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-library analyzer_cli.test.formatter;
-
 import 'package:analyzer/analyzer.dart';
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer_cli/src/ansi.dart' as ansi;
 import 'package:analyzer_cli/src/error_formatter.dart';
 import 'package:test/test.dart' hide ErrorFormatter;
-import 'package:mockito/mockito.dart';
 
 import 'mocks.dart';
 
@@ -27,11 +24,11 @@
       stats = new AnalysisStats();
 
       options = new MockCommandLineOptions();
-      when(options.enableTypeChecks).thenReturn(false);
-      when(options.infosAreFatal).thenReturn(false);
-      when(options.machineFormat).thenReturn(false);
-      when(options.verbose).thenReturn(false);
-      when(options.color).thenReturn(false);
+      options.enableTypeChecks = false;
+      options.infosAreFatal = false;
+      options.machineFormat = false;
+      options.verbose = false;
+      options.color = false;
 
       reporter = new HumanErrorFormatter(out, options, stats);
     });
@@ -74,27 +71,13 @@
 
 MockAnalysisErrorInfo mockError(ErrorType type, ErrorSeverity severity) {
   // ErrorInfo
-  var info = new MockAnalysisErrorInfo();
-  var error = new MockAnalysisError();
-  var lineInfo = new MockLineInfo();
-  var location = new MockLineInfo_Location();
-  when(location.columnNumber).thenReturn(3);
-  when(location.lineNumber).thenReturn(3);
-  when(lineInfo.getLocation(any)).thenReturn(location);
-  when(info.lineInfo).thenReturn(lineInfo);
+  var location = new MockLineInfo_Location(3, 3);
+  var lineInfo = new MockLineInfo(defaultLocation: location);
 
   // Details
-  var code = new MockErrorCode();
-  when(code.type).thenReturn(type);
-  when(code.errorSeverity).thenReturn(severity);
-  when(code.name).thenReturn('mock_code');
-  when(error.errorCode).thenReturn(code);
-  when(error.message).thenReturn('MSG');
-  when(error.offset).thenReturn(20);
-  var source = new MockSource();
-  when(source.fullName).thenReturn('/foo/bar/baz.dart');
-  when(error.source).thenReturn(source);
-  when(info.errors).thenReturn([error]);
+  var code = new MockErrorCode(type, severity, 'mock_code');
+  var source = new MockSource('/foo/bar/baz.dart');
+  var error = new MockAnalysisError(source, code, 20, 'MSG');
 
-  return info;
+  return new MockAnalysisErrorInfo(lineInfo, [error]);
 }
diff --git a/pkg/analyzer_plugin/doc/api.html b/pkg/analyzer_plugin/doc/api.html
index a87463f..3fa21ce 100644
--- a/pkg/analyzer_plugin/doc/api.html
+++ b/pkg/analyzer_plugin/doc/api.html
@@ -1782,7 +1782,7 @@
       An enumeration of the kinds of refactorings that can be created.
     </p>
     
-  <dl><dt class="value">CONVERT_GETTER_TO_METHOD</dt><dt class="value">CONVERT_METHOD_TO_GETTER</dt><dt class="value">EXTRACT_LOCAL_VARIABLE</dt><dt class="value">EXTRACT_METHOD</dt><dt class="value">INLINE_LOCAL_VARIABLE</dt><dt class="value">INLINE_METHOD</dt><dt class="value">MOVE_FILE</dt><dt class="value">RENAME</dt><dt class="value">SORT_MEMBERS</dt></dl></dd><dt class="typeDefinition"><a name="type_RefactoringMethodParameter">RefactoringMethodParameter: object</a></dt><dd>
+  <dl><dt class="value">CONVERT_GETTER_TO_METHOD</dt><dt class="value">CONVERT_METHOD_TO_GETTER</dt><dt class="value">EXTRACT_LOCAL_VARIABLE</dt><dt class="value">EXTRACT_METHOD</dt><dt class="value">EXTRACT_WIDGET</dt><dt class="value">INLINE_LOCAL_VARIABLE</dt><dt class="value">INLINE_METHOD</dt><dt class="value">MOVE_FILE</dt><dt class="value">RENAME</dt><dt class="value">SORT_MEMBERS</dt></dl></dd><dt class="typeDefinition"><a name="type_RefactoringMethodParameter">RefactoringMethodParameter: object</a></dt><dd>
     
     <p>
       A description of a parameter in a method refactoring.
diff --git a/pkg/analyzer_plugin/lib/protocol/protocol_common.dart b/pkg/analyzer_plugin/lib/protocol/protocol_common.dart
index fa6e4fc..ca795ae 100644
--- a/pkg/analyzer_plugin/lib/protocol/protocol_common.dart
+++ b/pkg/analyzer_plugin/lib/protocol/protocol_common.dart
@@ -4667,6 +4667,7 @@
  *   CONVERT_METHOD_TO_GETTER
  *   EXTRACT_LOCAL_VARIABLE
  *   EXTRACT_METHOD
+ *   EXTRACT_WIDGET
  *   INLINE_LOCAL_VARIABLE
  *   INLINE_METHOD
  *   MOVE_FILE
@@ -4689,6 +4690,9 @@
   static const RefactoringKind EXTRACT_METHOD =
       const RefactoringKind._("EXTRACT_METHOD");
 
+  static const RefactoringKind EXTRACT_WIDGET =
+      const RefactoringKind._("EXTRACT_WIDGET");
+
   static const RefactoringKind INLINE_LOCAL_VARIABLE =
       const RefactoringKind._("INLINE_LOCAL_VARIABLE");
 
@@ -4710,6 +4714,7 @@
     CONVERT_METHOD_TO_GETTER,
     EXTRACT_LOCAL_VARIABLE,
     EXTRACT_METHOD,
+    EXTRACT_WIDGET,
     INLINE_LOCAL_VARIABLE,
     INLINE_METHOD,
     MOVE_FILE,
@@ -4732,6 +4737,8 @@
         return EXTRACT_LOCAL_VARIABLE;
       case "EXTRACT_METHOD":
         return EXTRACT_METHOD;
+      case "EXTRACT_WIDGET":
+        return EXTRACT_WIDGET;
       case "INLINE_LOCAL_VARIABLE":
         return INLINE_LOCAL_VARIABLE;
       case "INLINE_METHOD":
diff --git a/pkg/analyzer_plugin/lib/src/utilities/change_builder/change_builder_dart.dart b/pkg/analyzer_plugin/lib/src/utilities/change_builder/change_builder_dart.dart
index 1f1320c..e0728a5 100644
--- a/pkg/analyzer_plugin/lib/src/utilities/change_builder/change_builder_dart.dart
+++ b/pkg/analyzer_plugin/lib/src/utilities/change_builder/change_builder_dart.dart
@@ -44,7 +44,7 @@
   @override
   Future<Null> addFileEdit(
           String path, void buildFileEdit(DartFileEditBuilder builder)) =>
-      super.addFileEdit(path, buildFileEdit);
+      super.addFileEdit(path, (builder) => buildFileEdit(builder));
 
   @override
   Future<DartFileEditBuilderImpl> createFileEditBuilder(String path) async {
@@ -76,7 +76,7 @@
   @override
   void addLinkedEdit(String groupName,
           void buildLinkedEdit(DartLinkedEditBuilder builder)) =>
-      super.addLinkedEdit(groupName, buildLinkedEdit);
+      super.addLinkedEdit(groupName, (builder) => buildLinkedEdit(builder));
 
   @override
   LinkedEditBuilderImpl createLinkedEditBuilder() {
@@ -182,17 +182,20 @@
     bool typeRequired = true;
     if (isConst) {
       write(Keyword.CONST.lexeme);
+      write(' ');
       typeRequired = false;
     } else if (isFinal) {
       write(Keyword.FINAL.lexeme);
+      write(' ');
       typeRequired = false;
     }
     if (type != null) {
       writeType(type, groupName: typeGroupName, required: true);
+      write(' ');
     } else if (typeRequired) {
       write(Keyword.VAR.lexeme);
+      write(' ');
     }
-    write(' ');
     if (nameGroupName != null) {
       addSimpleLinkedEdit(nameGroupName, name);
     } else {
@@ -447,6 +450,24 @@
   }
 
   @override
+  void writeParameter(String name,
+      {StringBuffer displayTextBuffer,
+      ExecutableElement methodBeingCopied,
+      DartType type}) {
+    String parameterSource;
+    if (type != null) {
+      _EnclosingElementFinder finder = new _EnclosingElementFinder();
+      finder.find(dartFileEditBuilder.unit, offset);
+      parameterSource = _getTypeSource(
+          type, finder.enclosingClass, finder.enclosingExecutable,
+          parameterName: name, methodBeingCopied: methodBeingCopied);
+    } else {
+      parameterSource = name;
+    }
+    write(parameterSource, displayTextBuffer: displayTextBuffer);
+  }
+
+  @override
   void writeParameterMatchingArgument(
       Expression argument, int index, Set<String> usedNames) {
     // append type name
@@ -494,9 +515,10 @@
         }
       }
       // parameter
-      writeParameterSource(parameter.type, parameter.name,
+      writeParameter(parameter.name,
+          displayTextBuffer: displayTextBuffer,
           methodBeingCopied: methodBeingCopied,
-          displayTextBuffer: displayTextBuffer);
+          type: parameter.type);
       // default value
       String defaultCode = parameter.defaultValueCode;
       if (defaultCode != null) {
@@ -542,17 +564,6 @@
   }
 
   @override
-  void writeParameterSource(DartType type, String name,
-      {StringBuffer displayTextBuffer, ExecutableElement methodBeingCopied}) {
-    _EnclosingElementFinder finder = new _EnclosingElementFinder();
-    finder.find(dartFileEditBuilder.unit, offset);
-    String parameterSource = _getTypeSource(
-        type, finder.enclosingClass, finder.enclosingExecutable,
-        parameterName: name, methodBeingCopied: methodBeingCopied);
-    write(parameterSource, displayTextBuffer: displayTextBuffer);
-  }
-
-  @override
   bool writeType(DartType type,
       {bool addSupertypeProposals: false,
       String groupName,
@@ -1149,12 +1160,12 @@
 
   @override
   void addInsertion(int offset, void buildEdit(DartEditBuilder builder)) =>
-      super.addInsertion(offset, buildEdit);
+      super.addInsertion(offset, (builder) => buildEdit(builder));
 
   @override
   void addReplacement(
           SourceRange range, void buildEdit(DartEditBuilder builder)) =>
-      super.addReplacement(range, buildEdit);
+      super.addReplacement(range, (builder) => buildEdit(builder));
 
   @override
   void convertFunctionFromSyncToAsync(
diff --git a/pkg/analyzer_plugin/lib/utilities/change_builder/change_builder_dart.dart b/pkg/analyzer_plugin/lib/utilities/change_builder/change_builder_dart.dart
index a14dffc..c1165a1 100644
--- a/pkg/analyzer_plugin/lib/utilities/change_builder/change_builder_dart.dart
+++ b/pkg/analyzer_plugin/lib/utilities/change_builder/change_builder_dart.dart
@@ -176,6 +176,18 @@
       {StringBuffer displayTextBuffer});
 
   /**
+   * Write the code for a single parameter with the given [name].
+   *
+   * If a [methodBeingCopied] is provided, then type parameters defined by that
+   * method are assumed to be part of what is being written and hence valid
+   * types.
+   *
+   * If a [type] is provided, then it will be used as the type of the parameter.
+   */
+  void writeParameter(String name,
+      {ExecutableElement methodBeingCopied, DartType type});
+
+  /**
    * Write the code for a parameter that would match the given [argument]. The
    * name of the parameter will be generated based on the type of the argument,
    * but if the argument type is not known the [index] will be used to compose
@@ -203,17 +215,6 @@
   void writeParametersMatchingArguments(ArgumentList arguments);
 
   /**
-   * Write the code for a single parameter with the given [type] and [name].
-   * The [type] can be `null` if no type is to be specified for the parameter.
-   *
-   * If a [methodBeingCopied] is provided, then type parameters defined by that
-   * method are assumed to be part of what is being written and hence valid
-   * types.
-   */
-  void writeParameterSource(DartType type, String name,
-      {ExecutableElement methodBeingCopied});
-
-  /**
    * Write the code for a type annotation for the given [type]. If the [type] is
    * either `null` or represents the type 'dynamic', then the behavior depends
    * on whether a type is [required]. If [required] is `true`, then 'var' will
diff --git a/pkg/analyzer_plugin/test/integration/support/protocol_matchers.dart b/pkg/analyzer_plugin/test/integration/support/protocol_matchers.dart
index 960bce1..31c0e6793 100644
--- a/pkg/analyzer_plugin/test/integration/support/protocol_matchers.dart
+++ b/pkg/analyzer_plugin/test/integration/support/protocol_matchers.dart
@@ -726,6 +726,7 @@
  *   CONVERT_METHOD_TO_GETTER
  *   EXTRACT_LOCAL_VARIABLE
  *   EXTRACT_METHOD
+ *   EXTRACT_WIDGET
  *   INLINE_LOCAL_VARIABLE
  *   INLINE_METHOD
  *   MOVE_FILE
@@ -738,6 +739,7 @@
   "CONVERT_METHOD_TO_GETTER",
   "EXTRACT_LOCAL_VARIABLE",
   "EXTRACT_METHOD",
+  "EXTRACT_WIDGET",
   "INLINE_LOCAL_VARIABLE",
   "INLINE_METHOD",
   "MOVE_FILE",
diff --git a/pkg/analyzer_plugin/test/src/utilities/change_builder/change_builder_dart_test.dart b/pkg/analyzer_plugin/test/src/utilities/change_builder/change_builder_dart_test.dart
index e7ab4ef..4cc4c03 100644
--- a/pkg/analyzer_plugin/test/src/utilities/change_builder/change_builder_dart_test.dart
+++ b/pkg/analyzer_plugin/test/src/utilities/change_builder/change_builder_dart_test.dart
@@ -519,6 +519,23 @@
     expect(edit.replacement, equalsIgnoringWhitespace('const f;'));
   }
 
+  test_writeFieldDeclaration_isConst_type() async {
+    String path = provider.convertPath('/test.dart');
+    String content = 'class A {}';
+    addSource(path, content);
+    DartType typeA = await _getType(path, 'A');
+
+    DartChangeBuilderImpl builder = new DartChangeBuilder(session);
+    await builder.addFileEdit(path, (FileEditBuilder builder) {
+      builder.addInsertion(content.length - 1, (EditBuilder builder) {
+        (builder as DartEditBuilder)
+            .writeFieldDeclaration('f', isConst: true, type: typeA);
+      });
+    });
+    SourceEdit edit = getEdit(builder);
+    expect(edit.replacement, equalsIgnoringWhitespace('const A f;'));
+  }
+
   test_writeFieldDeclaration_isFinal() async {
     String path = provider.convertPath('/test.dart');
     String content = 'class A {}';
@@ -534,6 +551,23 @@
     expect(edit.replacement, equalsIgnoringWhitespace('final f;'));
   }
 
+  test_writeFieldDeclaration_isFinal_type() async {
+    String path = provider.convertPath('/test.dart');
+    String content = 'class A {}';
+    addSource(path, content);
+    DartType typeA = await _getType(path, 'A');
+
+    DartChangeBuilderImpl builder = new DartChangeBuilder(session);
+    await builder.addFileEdit(path, (FileEditBuilder builder) {
+      builder.addInsertion(content.length - 1, (EditBuilder builder) {
+        (builder as DartEditBuilder)
+            .writeFieldDeclaration('f', isFinal: true, type: typeA);
+      });
+    });
+    SourceEdit edit = getEdit(builder);
+    expect(edit.replacement, equalsIgnoringWhitespace('final A f;'));
+  }
+
   test_writeFieldDeclaration_isStatic() async {
     String path = provider.convertPath('/test.dart');
     String content = 'class A {}';
@@ -1308,6 +1342,37 @@
     }
   }
 
+  test_writeParameter() async {
+    String path = provider.convertPath('/test.dart');
+    String content = 'class A {}';
+    addSource(path, content);
+
+    DartChangeBuilderImpl builder = new DartChangeBuilder(session);
+    await builder.addFileEdit(path, (FileEditBuilder builder) {
+      builder.addInsertion(content.length - 1, (EditBuilder builder) {
+        (builder as DartEditBuilder).writeParameter('a');
+      });
+    });
+    SourceEdit edit = getEdit(builder);
+    expect(edit.replacement, equalsIgnoringWhitespace('a'));
+  }
+
+  test_writeParameter_type() async {
+    String path = provider.convertPath('/test.dart');
+    String content = 'class A {}';
+    addSource(path, content);
+    DartType typeA = await _getType(path, 'A');
+
+    DartChangeBuilderImpl builder = new DartChangeBuilder(session);
+    await builder.addFileEdit(path, (FileEditBuilder builder) {
+      builder.addInsertion(content.length - 1, (EditBuilder builder) {
+        (builder as DartEditBuilder).writeParameter('a', type: typeA);
+      });
+    });
+    SourceEdit edit = getEdit(builder);
+    expect(edit.replacement, equalsIgnoringWhitespace('A a'));
+  }
+
   test_writeParameterMatchingArgument() async {
     String path = provider.convertPath('/test.dart');
     String content = r'''
@@ -1445,22 +1510,6 @@
     expect(edit.replacement, equalsIgnoringWhitespace('String s, int i'));
   }
 
-  test_writeParameterSource() async {
-    String path = provider.convertPath('/test.dart');
-    String content = 'class A {}';
-    addSource(path, content);
-    DartType typeA = await _getType(path, 'A');
-
-    DartChangeBuilderImpl builder = new DartChangeBuilder(session);
-    await builder.addFileEdit(path, (FileEditBuilder builder) {
-      builder.addInsertion(content.length - 1, (EditBuilder builder) {
-        (builder as DartEditBuilder).writeParameterSource(typeA, 'a');
-      });
-    });
-    SourceEdit edit = getEdit(builder);
-    expect(edit.replacement, equalsIgnoringWhitespace('A a'));
-  }
-
   test_writeType_dynamic() async {
     String path = provider.convertPath('/test.dart');
     String content = 'class A {}';
diff --git a/pkg/analyzer_plugin/tool/spec/common_types_spec.html b/pkg/analyzer_plugin/tool/spec/common_types_spec.html
index 76f0995..3749755 100644
--- a/pkg/analyzer_plugin/tool/spec/common_types_spec.html
+++ b/pkg/analyzer_plugin/tool/spec/common_types_spec.html
@@ -1193,6 +1193,7 @@
       <value><code>CONVERT_METHOD_TO_GETTER</code></value>
       <value><code>EXTRACT_LOCAL_VARIABLE</code></value>
       <value><code>EXTRACT_METHOD</code></value>
+      <value><code>EXTRACT_WIDGET</code></value>
       <value><code>INLINE_LOCAL_VARIABLE</code></value>
       <value><code>INLINE_METHOD</code></value>
       <value><code>MOVE_FILE</code></value>
diff --git a/pkg/browser/LICENSE b/pkg/browser/LICENSE
deleted file mode 100644
index 5c60afe..0000000
--- a/pkg/browser/LICENSE
+++ /dev/null
@@ -1,26 +0,0 @@
-Copyright 2014, the Dart project authors. All rights reserved.
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are
-met:
-
-    * Redistributions of source code must retain the above copyright
-      notice, this list of conditions and the following disclaimer.
-    * Redistributions in binary form must reproduce the above
-      copyright notice, this list of conditions and the following
-      disclaimer in the documentation and/or other materials provided
-      with the distribution.
-    * Neither the name of Google Inc. nor the names of its
-      contributors may be used to endorse or promote products derived
-      from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/pkg/browser/README.md b/pkg/browser/README.md
deleted file mode 100644
index fa96851..0000000
--- a/pkg/browser/README.md
+++ /dev/null
@@ -1,39 +0,0 @@
-This package contains dart.js, and previously contained interop.js
-
-dart.js
-=======
-
-The dart.js file is used in Dart browser apps to check for native Dart support
-and either (a) bootstrap Dartium or (b) load compiled JS instead.  Previously,
-we've recommended that you add a script tag pointing the version of dart.js in
-our repository.  This doesn't work offline and also results in slower startup
-(see [dartbug.com/6723](http://dartbug.com/6723)).
-
-Instead, we now recommend that you install dart.js via the following steps:
-
-1. Add the following to your pubspec.yaml:
-  dependencies:
-    browser: any
-
-2. Run pub install.
-
-3. Use a relative script tag in your html to the installed version:
-
-    `<script src="packages/browser/dart.js"></script>`
-
-If you do not wish to use pub, you may host a copy of this file locally instead.
-In this case, you will need to update it yourself as necessary.  We reserve the
-right to move the old file in the repository, so we no longer recommend linking
-to it directly.
-
-interop.js
-==========
-
-This script was required for dart:js interop to work, but it is no longer
-needed. The functionality is now supported by dart:js directly.
-
-If you previously had a script such as this, please remove it:
-
-```html
-<script src="packages/browser/interop.js"></script>
-```
diff --git a/pkg/browser/lib/dart.js b/pkg/browser/lib/dart.js
deleted file mode 100644
index b1f97b1..0000000
--- a/pkg/browser/lib/dart.js
+++ /dev/null
@@ -1,49 +0,0 @@
-// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-(function() {
-// Bootstrap support for Dart scripts on the page as this script.
-// TODO(18463): Remove user agent check. We will remove 'Dart' from there.
-if (!navigator.dartEnabled && (navigator.userAgent.indexOf('(Dart)') === -1)) {
-  // TODO:
-  // - Support in-browser compilation.
-  // - Handle inline Dart scripts.
-
-  // Fall back to compiled JS. Run through all the scripts and
-  // replace them if they have a type that indicate that they source
-  // in Dart code (type="application/dart").
-  var scripts = document.getElementsByTagName("script");
-  var length = scripts.length;
-  for (var i = 0; i < length; ++i) {
-    if (scripts[i].type == "application/dart") {
-      // Remap foo.dart to foo.dart.js.
-      if (scripts[i].src && scripts[i].src != '') {
-        var script = document.createElement('script');
-        script.src = scripts[i].src.replace(/\.dart(?=\?|$)/, '.dart.js');
-        var parent = scripts[i].parentNode;
-        // TODO(vsm): Find a solution for issue 8455 that works with more
-        // than one script.
-        document.currentScript = script;
-        parent.replaceChild(script, scripts[i]);
-
-        // Support for incremental compilation.
-        script.onload = function (event) {
-          var script = event.target;
-          if (self.$dart_unsafe_incremental_support) {
-            new WebSocket(script.src.replace(/^http/, 'ws')).onmessage =
-              function (event) {
-                var patch = String(event.data);
-                self.$dart_unsafe_incremental_support.patch(patch);
-                script.dispatchEvent(
-                  new CustomEvent(
-                    "dart_program_updated",
-                    { bubbles: true, detail: { patch: patch } }));
-              };
-          }
-        };
-      }
-    }
-  }
-}
-})();
diff --git a/pkg/browser/lib/interop.js b/pkg/browser/lib/interop.js
deleted file mode 100644
index ec02e58..0000000
--- a/pkg/browser/lib/interop.js
+++ /dev/null
@@ -1,9 +0,0 @@
-// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-// TODO(jmesserly): remove this script after a deprecation period.
-if (typeof console == "object" && typeof console.warn == "function") {
-  console.warn('<script src="packages/browser/interop.js"> is no longer ' +
-      'needed for dart:js. See http://pub.dartlang.org/packages/browser.');
-}
diff --git a/pkg/browser/pubspec.yaml b/pkg/browser/pubspec.yaml
deleted file mode 100644
index af9396f..0000000
--- a/pkg/browser/pubspec.yaml
+++ /dev/null
@@ -1,8 +0,0 @@
-name: browser
-version: 0.10.1
-author: "Dart Team <misc@dartlang.org>"
-homepage: http://www.dartlang.org
-description: >
- The bootstrap dart.js script for Dart apps running in the browser.
-environment:
-  sdk: ">=1.3.0-dev.4.1 <2.0.0"
diff --git a/pkg/compiler/lib/src/diagnostics/messages.dart b/pkg/compiler/lib/src/diagnostics/messages.dart
index 99f7f7f..51ffa6b 100644
--- a/pkg/compiler/lib/src/diagnostics/messages.dart
+++ b/pkg/compiler/lib/src/diagnostics/messages.dart
@@ -3108,29 +3108,7 @@
           MessageKind.MALFORMED_STRING_LITERAL,
           r"A '$' has special meaning inside a string, and must be followed by "
           "an identifier or an expression in curly braces ({}).",
-          howToFix: r"Try adding a backslash (\) to escape the '$'.",
-          examples: const [
-            r"""
-main() {
-  return '$';
-}
-""",
-            r'''
-main() {
-  return "$";
-}
-''',
-            r"""
-main() {
-  return '''$''';
-}
-""",
-            r'''
-main() {
-  return """$""";
-}
-'''
-          ]),
+          howToFix: r"Try adding a backslash (\) to escape the '$'."),
 
       MessageKind.UNTERMINATED_COMMENT: const MessageTemplate(
           MessageKind.UNTERMINATED_COMMENT,
diff --git a/pkg/compiler/lib/src/io/source_information.dart b/pkg/compiler/lib/src/io/source_information.dart
index ae22161..0297bc2 100644
--- a/pkg/compiler/lib/src/io/source_information.dart
+++ b/pkg/compiler/lib/src/io/source_information.dart
@@ -279,6 +279,8 @@
 
 /// Compute the source map name for [element]. If [callStructure] is non-null
 /// it is used to name the parameter stub for [element].
+// TODO(johnniwinther): Merge this with `computeKernelElementNameForSourceMaps`
+// when the old frontend is removed.
 String computeElementNameForSourceMaps(Entity element,
     [CallStructure callStructure]) {
   if (element is AstElement) {
diff --git a/pkg/compiler/lib/src/js_backend/field_naming_mixin.dart b/pkg/compiler/lib/src/js_backend/field_naming_mixin.dart
index 6670249..e2d67ea 100644
--- a/pkg/compiler/lib/src/js_backend/field_naming_mixin.dart
+++ b/pkg/compiler/lib/src/js_backend/field_naming_mixin.dart
@@ -207,10 +207,10 @@
   @override
   Map<Entity, jsAst.Name> get names => registry.globalNames;
 
-  _MixinFieldNamingScope.mixin(ClassElement cls, _FieldNamingRegistry registry)
+  _MixinFieldNamingScope.mixin(ClassEntity cls, _FieldNamingRegistry registry)
       : super.rootScope(cls, registry);
 
-  _MixinFieldNamingScope.mixedIn(MixinApplicationElement container,
+  _MixinFieldNamingScope.mixedIn(ClassEntity container,
       _FieldNamingScope superScope, _FieldNamingRegistry registry)
       : super.inherit(container, superScope, registry);
 
diff --git a/pkg/compiler/lib/src/js_backend/minify_namer.dart b/pkg/compiler/lib/src/js_backend/minify_namer.dart
index 0554923..723bca7 100644
--- a/pkg/compiler/lib/src/js_backend/minify_namer.dart
+++ b/pkg/compiler/lib/src/js_backend/minify_namer.dart
@@ -316,37 +316,42 @@
 /// constructors declared along the inheritance chain.
 class _ConstructorBodyNamingScope {
   final int _startIndex;
-  final List _constructors;
-
+  final List<ConstructorEntity> _constructors;
   int get numberOfConstructors => _constructors.length;
 
-  _ConstructorBodyNamingScope.rootScope(ClassElement cls)
+  _ConstructorBodyNamingScope.rootScope(
+      ClassEntity cls, ElementEnvironment environment)
       : _startIndex = 0,
-        _constructors = cls.constructors.toList(growable: false);
+        _constructors = _getConstructorList(cls, environment);
 
-  _ConstructorBodyNamingScope.forClass(
-      ClassElement cls, _ConstructorBodyNamingScope superScope)
+  _ConstructorBodyNamingScope.forClass(ClassEntity cls,
+      _ConstructorBodyNamingScope superScope, ElementEnvironment environment)
       : _startIndex = superScope._startIndex + superScope.numberOfConstructors,
-        _constructors = cls.constructors.toList(growable: false);
+        _constructors = _getConstructorList(cls, environment);
 
   // Mixin Applications have constructors but we never generate code for them,
   // so they do not count in the inheritance chain.
   _ConstructorBodyNamingScope.forMixinApplication(
-      ClassElement cls, _ConstructorBodyNamingScope superScope)
+      ClassEntity cls, _ConstructorBodyNamingScope superScope)
       : _startIndex = superScope._startIndex + superScope.numberOfConstructors,
         _constructors = const [];
 
-  factory _ConstructorBodyNamingScope(ClassElement cls,
-      Map<ClassElement, _ConstructorBodyNamingScope> registry) {
+  factory _ConstructorBodyNamingScope(
+      ClassEntity cls,
+      Map<ClassEntity, _ConstructorBodyNamingScope> registry,
+      ElementEnvironment environment) {
     return registry.putIfAbsent(cls, () {
-      if (cls.superclass == null) {
-        return new _ConstructorBodyNamingScope.rootScope(cls);
-      } else if (cls.isMixinApplication) {
-        return new _ConstructorBodyNamingScope.forMixinApplication(
-            cls, new _ConstructorBodyNamingScope(cls.superclass, registry));
+      ClassEntity superclass = environment.getSuperClass(cls);
+      if (superclass == null) {
+        return new _ConstructorBodyNamingScope.rootScope(cls, environment);
+      } else if (environment.isMixinApplication(cls)) {
+        return new _ConstructorBodyNamingScope.forMixinApplication(cls,
+            new _ConstructorBodyNamingScope(superclass, registry, environment));
       } else {
         return new _ConstructorBodyNamingScope.forClass(
-            cls, new _ConstructorBodyNamingScope(cls.superclass, registry));
+            cls,
+            new _ConstructorBodyNamingScope(superclass, registry, environment),
+            environment);
       }
     });
   }
@@ -356,16 +361,23 @@
     assert(position >= 0, failedAt(body, "constructor body missing"));
     return "@constructorBody@${_startIndex + position}";
   }
+
+  static List<ConstructorEntity> _getConstructorList(
+      ClassEntity cls, ElementEnvironment environment) {
+    var result = <ConstructorEntity>[];
+    environment.forEachConstructor(cls, result.add);
+    return result;
+  }
 }
 
 abstract class _MinifyConstructorBodyNamer implements Namer {
-  Map<ClassElement, _ConstructorBodyNamingScope> _constructorBodyScopes =
-      new Map<ClassElement, _ConstructorBodyNamingScope>();
+  Map<ClassEntity, _ConstructorBodyNamingScope> _constructorBodyScopes =
+      new Map<ClassEntity, _ConstructorBodyNamingScope>();
 
   @override
   jsAst.Name constructorBodyName(ConstructorBodyEntity method) {
     _ConstructorBodyNamingScope scope = new _ConstructorBodyNamingScope(
-        method.enclosingClass, _constructorBodyScopes);
+        method.enclosingClass, _constructorBodyScopes, elementEnvironment);
     String key = scope.constructorBodyKeyFor(method);
     return _disambiguateMemberByKey(
         key, () => _proposeNameForConstructorBody(method));
diff --git a/pkg/compiler/lib/src/js_backend/namer.dart b/pkg/compiler/lib/src/js_backend/namer.dart
index 0dab60a..3a02f42 100644
--- a/pkg/compiler/lib/src/js_backend/namer.dart
+++ b/pkg/compiler/lib/src/js_backend/namer.dart
@@ -15,13 +15,7 @@
 import '../constants/values.dart';
 import '../common_elements.dart' show CommonElements, ElementEnvironment;
 import '../diagnostics/invariant.dart' show DEBUG_MODE;
-import '../elements/elements.dart'
-    show
-        ClassElement,
-        Element,
-        Elements,
-        MemberElement,
-        MixinApplicationElement;
+import '../elements/elements.dart' show Element, Elements, MemberElement;
 import '../elements/entities.dart';
 import '../elements/entity_utils.dart' as utils;
 import '../elements/jumps.dart';
@@ -578,7 +572,7 @@
     _literalLazyGetterPrefix = new StringBackedName(lazyGetterPrefix);
   }
 
-  ElementEnvironment get _elementEnvironment => _closedWorld.elementEnvironment;
+  ElementEnvironment get elementEnvironment => _closedWorld.elementEnvironment;
 
   CommonElements get _commonElements => _closedWorld.commonElements;
 
@@ -983,10 +977,10 @@
     bool isPrivate = Name.isPrivateName(fieldName);
     LibraryEntity memberLibrary = element.library;
     ClassEntity lookupClass =
-        _elementEnvironment.getSuperClass(element.enclosingClass);
+        elementEnvironment.getSuperClass(element.enclosingClass);
     while (lookupClass != null) {
       MemberEntity foundMember =
-          _elementEnvironment.lookupLocalClassMember(lookupClass, fieldName);
+          elementEnvironment.lookupLocalClassMember(lookupClass, fieldName);
       if (foundMember != null) {
         if (foundMember.isField) {
           if (!isPrivate || memberLibrary == foundMember.library) {
@@ -996,7 +990,7 @@
           }
         }
       }
-      lookupClass = _elementEnvironment.getSuperClass(lookupClass);
+      lookupClass = elementEnvironment.getSuperClass(lookupClass);
     }
     return false;
   }
diff --git a/pkg/compiler/lib/src/js_backend/runtime_types.dart b/pkg/compiler/lib/src/js_backend/runtime_types.dart
index 9b357d1..b655b94 100644
--- a/pkg/compiler/lib/src/js_backend/runtime_types.dart
+++ b/pkg/compiler/lib/src/js_backend/runtime_types.dart
@@ -1684,13 +1684,26 @@
 ClassFunctionType _computeFunctionType(
     ElementEnvironment _elementEnvironment, ClassEntity cls,
     {bool strongMode}) {
-  if (strongMode && !cls.isClosure) return null;
+  FunctionEntity signatureFunction;
+  if (cls.isClosure) {
+    // Use signature function if available.
+    signatureFunction =
+        _elementEnvironment.lookupLocalClassMember(cls, Identifiers.signature);
+    if (signatureFunction == null && strongMode) {
+      // In Dart 2, a closure only needs its function type if it has a
+      // signature function.
+      return null;
+    }
+  } else if (strongMode) {
+    // Only closures have function type in Dart 2.
+    return null;
+  }
   MemberEntity call =
       _elementEnvironment.lookupLocalClassMember(cls, Identifiers.call);
   if (call != null && call.isFunction) {
     FunctionEntity callFunction = call;
     FunctionType callType = _elementEnvironment.getFunctionType(callFunction);
-    return new ClassFunctionType(callFunction, callType);
+    return new ClassFunctionType(callFunction, callType, signatureFunction);
   }
   return null;
 }
@@ -2340,12 +2353,17 @@
 /// a class.
 class ClassFunctionType {
   /// The `call` function that defines the function type.
-  final MemberEntity callFunction;
+  final FunctionEntity callFunction;
 
   /// The type of the `call` function.
   final FunctionType callType;
 
-  ClassFunctionType(this.callFunction, this.callType);
+  /// The signature function for the function type.
+  ///
+  /// This is used for Dart 2.
+  final FunctionEntity signatureFunction;
+
+  ClassFunctionType(this.callFunction, this.callType, this.signatureFunction);
 }
 
 /// Runtime type usage for a class.
diff --git a/pkg/compiler/lib/src/js_emitter/program_builder/program_builder.dart b/pkg/compiler/lib/src/js_emitter/program_builder/program_builder.dart
index 7bc40d2..525d31b 100644
--- a/pkg/compiler/lib/src/js_emitter/program_builder/program_builder.dart
+++ b/pkg/compiler/lib/src/js_emitter/program_builder/program_builder.dart
@@ -678,7 +678,6 @@
         _task.emitter, _commonElements, _namer, _worldBuilder, _closedWorld,
         enableMinification: _options.enableMinification);
     RuntimeTypeGenerator runtimeTypeGenerator = new RuntimeTypeGenerator(
-        _elementEnvironment,
         _commonElements,
         _closureDataLookup,
         _outputUnitData,
@@ -688,8 +687,7 @@
         _rtiEncoder,
         _jsInteropAnalysis,
         _options.useKernel,
-        _options.strongMode,
-        _options.disableRtiOptimization);
+        _options.strongMode);
 
     void visitMember(MemberEntity member) {
       if (member.isInstanceMember && !member.isAbstract && !member.isField) {
diff --git a/pkg/compiler/lib/src/js_emitter/runtime_type_generator.dart b/pkg/compiler/lib/src/js_emitter/runtime_type_generator.dart
index e856ec6..a277091 100644
--- a/pkg/compiler/lib/src/js_emitter/runtime_type_generator.dart
+++ b/pkg/compiler/lib/src/js_emitter/runtime_type_generator.dart
@@ -11,8 +11,7 @@
         ClosureConversionTask,
         ScopeInfo;
 import '../common.dart';
-import '../common/names.dart' show Identifiers;
-import '../common_elements.dart' show CommonElements, ElementEnvironment;
+import '../common_elements.dart' show CommonElements;
 import '../deferred_load.dart' show OutputUnit, OutputUnitData;
 import '../elements/elements.dart' show ClassElement, MethodElement;
 import '../elements/entities.dart';
@@ -24,6 +23,7 @@
 import '../js_backend/runtime_types.dart'
     show
         ClassChecks,
+        ClassFunctionType,
         RuntimeTypesChecks,
         RuntimeTypesEncoder,
         Substitution,
@@ -35,8 +35,7 @@
 import 'code_emitter_task.dart' show CodeEmitterTask;
 
 // Function signatures used in the generation of runtime type information.
-typedef void FunctionTypeSignatureEmitter(
-    FunctionEntity method, FunctionType methodType);
+typedef void FunctionTypeSignatureEmitter(ClassFunctionType classFunctionType);
 
 class TypeTest {
   final jsAst.Name name;
@@ -99,7 +98,6 @@
 }
 
 class RuntimeTypeGenerator {
-  final ElementEnvironment _elementEnvironment;
   final CommonElements _commonElements;
   final ClosureConversionTask _closureDataLookup;
   final OutputUnitData _outputUnitData;
@@ -109,15 +107,9 @@
   final RuntimeTypesEncoder _rtiEncoder;
   final JsInteropAnalysis _jsInteropAnalysis;
   final bool _useKernel;
-
-  /// ignore: UNUSED_FIELD
   final bool _strongMode;
 
-  /// ignore: UNUSED_FIELD
-  final bool _disableRtiOptimization;
-
   RuntimeTypeGenerator(
-      this._elementEnvironment,
       this._commonElements,
       this._closureDataLookup,
       this._outputUnitData,
@@ -127,8 +119,15 @@
       this._rtiEncoder,
       this._jsInteropAnalysis,
       this._useKernel,
-      this._strongMode,
-      this._disableRtiOptimization);
+      this._strongMode);
+
+  /**
+   * Generate "is tests" for [cls] itself, and the "is tests" for the
+   * classes it implements and type argument substitution functions for these
+   * tests.   We don't need to add the "is tests" of the super class because
+   * they will be inherited at runtime, but we may need to generate the
+   * substitutions, because they may have changed.
+   */
 
   /// Generates all properties necessary for is-checks on the [classElement].
   ///
@@ -149,49 +148,54 @@
         failedAt(classElement));
 
     // TODO(johnniwinther): Include function signatures in [ClassChecks].
-    void generateFunctionTypeSignature(
-        FunctionEntity method, FunctionType type) {
+    void generateFunctionTypeSignature(ClassFunctionType classFunctionType) {
+      FunctionEntity method = classFunctionType.callFunction;
+      FunctionType type = classFunctionType.callType;
       assert(!(method is MethodElement && !method.isImplementation));
-      jsAst.Expression thisAccess = new jsAst.This();
-      if (method.enclosingClass.isClosure) {
-        ScopeInfo scopeInfo = _closureDataLookup.getScopeInfo(method);
-        if (scopeInfo is ClosureRepresentationInfo) {
-          FieldEntity thisLocal = scopeInfo.thisFieldEntity;
-          if (thisLocal != null) {
-            assert(
-                thisLocal is ClosureFieldElement || thisLocal is JClosureField);
-            jsAst.Name thisName = _namer.instanceFieldPropertyName(thisLocal);
-            thisAccess = js('this.#', thisName);
-          }
-        }
-      }
 
       // TODO(johnniwinther): Avoid unneeded function type indices or
       // signatures. We either need them for mirrors or because [type] is
       // potentially a subtype of a checked function. Currently we eagerly
       // generate a function type index or signature for all callable classes.
       if (storeFunctionTypeInMetadata && !type.containsTypeVariables) {
+        // TODO(johnniwinther,efortuna): Should we use the scheme for Dart 2?
         // TODO(sigmund): use output unit of `method` (Issue #31032)
         OutputUnit outputUnit = _outputUnitData.mainOutputUnit;
         result.functionTypeIndex =
             emitterTask.metadataCollector.reifyType(type, outputUnit);
       } else {
-        jsAst.Expression encoding;
-        MemberEntity signature = _elementEnvironment.lookupLocalClassMember(
-            method.enclosingClass, Identifiers.signature);
-        if (_useKernel &&
-            signature != null &&
-            generatedCode[signature] != null) {
-          // Use precomputed signature function.
-          encoding = generatedCode[signature];
+        jsAst.Expression encoding =
+            generatedCode[classFunctionType.signatureFunction];
+        if (classFunctionType.signatureFunction != null) {
+          // Use precomputed signature function if live.
         } else {
-          // TODO(efortuna): Reinsert assertion.
-          // Generate the signature on the fly.
+          assert(!_useKernel || !_strongMode);
+          // Generate the signature on the fly. This is only supported for
+          // Dart 1.
+
+          jsAst.Expression thisAccess = new jsAst.This();
+          if (method.enclosingClass.isClosure) {
+            ScopeInfo scopeInfo = _closureDataLookup.getScopeInfo(method);
+            if (scopeInfo is ClosureRepresentationInfo) {
+              FieldEntity thisLocal = scopeInfo.thisFieldEntity;
+              if (thisLocal != null) {
+                assert(thisLocal is ClosureFieldElement ||
+                    thisLocal is JClosureField);
+                jsAst.Name thisName =
+                    _namer.instanceFieldPropertyName(thisLocal);
+                thisAccess = js('this.#', thisName);
+              }
+            }
+          }
+
           encoding = _rtiEncoder.getSignatureEncoding(
               emitterTask.emitter, type, thisAccess);
         }
-        jsAst.Name operatorSignature = _namer.asName(_namer.operatorSignature);
-        result.addSignature(classElement, operatorSignature, encoding);
+        if (encoding != null) {
+          jsAst.Name operatorSignature =
+              _namer.asName(_namer.operatorSignature);
+          result.addSignature(classElement, operatorSignature, encoding);
+        }
       }
     }
 
@@ -226,13 +230,6 @@
     return result;
   }
 
-  /**
-   * Generate "is tests" for [cls] itself, and the "is tests" for the
-   * classes it implements and type argument substitution functions for these
-   * tests.   We don't need to add the "is tests" of the super class because
-   * they will be inherited at runtime, but we may need to generate the
-   * substitutions, because they may have changed.
-   */
   void _generateIsTestsOn(
       ClassEntity cls,
       FunctionTypeSignatureEmitter generateFunctionTypeSignature,
@@ -252,8 +249,7 @@
     }
 
     if (classChecks.functionType != null) {
-      generateFunctionTypeSignature(classChecks.functionType.callFunction,
-          classChecks.functionType.callType);
+      generateFunctionTypeSignature(classChecks.functionType);
     }
   }
 }
diff --git a/pkg/compiler/lib/src/kernel/dart2js_target.dart b/pkg/compiler/lib/src/kernel/dart2js_target.dart
index ba98796..f7ab997a 100644
--- a/pkg/compiler/lib/src/kernel/dart2js_target.dart
+++ b/pkg/compiler/lib/src/kernel/dart2js_target.dart
@@ -14,38 +14,13 @@
 /// A kernel [Target] to configure the Dart Front End for dart2js.
 class Dart2jsTarget extends Target {
   final TargetFlags flags;
+  final String name;
 
-  Dart2jsTarget(this.flags);
+  Dart2jsTarget(this.name, this.flags);
 
   bool get strongMode => flags.strongMode;
 
-  String get name => 'dart2js';
-
-  List<String> get extraRequiredLibraries => const <String>[
-        'dart:_chrome',
-        'dart:_foreign_helper',
-        'dart:_interceptors',
-        'dart:_internal',
-        'dart:_isolate_helper',
-        'dart:_js_embedded_names',
-        'dart:_js_helper',
-        'dart:_js_mirrors',
-        'dart:_js_names',
-        'dart:_native_typed_data',
-        'dart:async',
-        'dart:collection',
-        'dart:html',
-        'dart:html_common',
-        'dart:indexed_db',
-        'dart:io',
-        'dart:js',
-        'dart:js_util',
-        'dart:mirrors',
-        'dart:svg',
-        'dart:web_audio',
-        'dart:web_gl',
-        'dart:web_sql',
-      ];
+  List<String> get extraRequiredLibraries => _requiredLibraries[name];
 
   @override
   bool mayDefineRestrictedType(Uri uri) =>
@@ -96,3 +71,50 @@
     return new InvalidExpression(null);
   }
 }
+
+// TODO(sigmund): this "extraRequiredLibraries" needs to be removed...
+// compile-platform should just specify which libraries to compile instead.
+const _requiredLibraries = const <String, List<String>>{
+  'dart2js': const <String>[
+    'dart:_chrome',
+    'dart:_foreign_helper',
+    'dart:_interceptors',
+    'dart:_internal',
+    'dart:_isolate_helper',
+    'dart:_js_embedded_names',
+    'dart:_js_helper',
+    'dart:_js_mirrors',
+    'dart:_js_names',
+    'dart:_native_typed_data',
+    'dart:async',
+    'dart:collection',
+    'dart:html',
+    'dart:html_common',
+    'dart:indexed_db',
+    'dart:io',
+    'dart:js',
+    'dart:js_util',
+    'dart:mirrors',
+    'dart:svg',
+    'dart:web_audio',
+    'dart:web_gl',
+    'dart:web_sql',
+  ],
+  'dart2js_server': const <String>[
+    'dart:_foreign_helper',
+    'dart:_interceptors',
+    'dart:_internal',
+    'dart:_isolate_helper',
+    'dart:_js_embedded_names',
+    'dart:_js_helper',
+    'dart:_js_mirrors',
+    'dart:_js_names',
+    'dart:_native_typed_data',
+    'dart:async',
+    'dart:collection',
+    'dart:io',
+    'dart:js',
+    'dart:js_util',
+    'dart:mirrors',
+  ]
+};
diff --git a/pkg/compiler/lib/src/kernel/kernel_strategy.dart b/pkg/compiler/lib/src/kernel/kernel_strategy.dart
index f58417e..8106841 100644
--- a/pkg/compiler/lib/src/kernel/kernel_strategy.dart
+++ b/pkg/compiler/lib/src/kernel/kernel_strategy.dart
@@ -83,8 +83,14 @@
       env.Environment environment,
       DiagnosticReporter reporter,
       Measurer measurer) {
-    return new KernelLibraryLoaderTask(_options.platformBinaries,
-        _options.packageConfig, _elementMap, compilerInput, reporter, measurer,
+    return new KernelLibraryLoaderTask(
+        _options.librariesSpecificationUri,
+        _options.platformBinaries,
+        _options.packageConfig,
+        _elementMap,
+        compilerInput,
+        reporter,
+        measurer,
         verbose: _options.verbose,
         initializedCompilerState: initializedCompilerState);
   }
diff --git a/pkg/compiler/lib/src/library_loader.dart b/pkg/compiler/lib/src/library_loader.dart
index e6e2ea8..33ca393 100644
--- a/pkg/compiler/lib/src/library_loader.dart
+++ b/pkg/compiler/lib/src/library_loader.dart
@@ -202,7 +202,8 @@
     "math": "_internal/js_runtime/lib/math_patch.dart",
     "mirrors": "_internal/js_runtime/lib/mirrors_patch.dart",
     "typed_data": "_internal/js_runtime/lib/typed_data_patch.dart",
-    "_internal": "_internal/js_runtime/lib/internal_patch.dart"
+    "_internal": "_internal/js_runtime/lib/internal_patch.dart",
+    "_js": "js/_js_client.dart",
   };
 
   /// Returns the location of the patch-file associated with [libraryName]
@@ -823,6 +824,7 @@
 // TODO(sigmund): move this class to a new file under src/kernel/.
 class KernelLibraryLoaderTask extends CompilerTask
     implements LibraryLoaderTask {
+  final Uri librariesSpecification;
   final Uri platformBinaries;
   final Uri _packageConfig;
 
@@ -840,9 +842,16 @@
 
   fe.InitializedCompilerState initializedCompilerState;
 
-  KernelLibraryLoaderTask(this.platformBinaries, this._packageConfig,
-      this._elementMap, this.compilerInput, this.reporter, Measurer measurer,
-      {this.verbose: false, this.initializedCompilerState})
+  KernelLibraryLoaderTask(
+      this.librariesSpecification,
+      this.platformBinaries,
+      this._packageConfig,
+      this._elementMap,
+      this.compilerInput,
+      this.reporter,
+      Measurer measurer,
+      {this.verbose: false,
+      this.initializedCompilerState})
       : _allLoadedLibraries = new List<LibraryEntity>(),
         super(measurer);
 
@@ -862,12 +871,16 @@
         new BinaryBuilder(input.data).readComponent(component);
       } else {
         bool strongMode = _elementMap.options.strongMode;
+        String targetName =
+            _elementMap.options.compileForServer ? "dart2js_server" : "dart2js";
         String platform = strongMode
-            ? 'dart2js_platform_strong.dill'
-            : 'dart2js_platform.dill';
+            ? '${targetName}_platform_strong.dill'
+            : '${targetName}_platform.dill';
         initializedCompilerState = fe.initializeCompiler(
             initializedCompilerState,
-            new Dart2jsTarget(new TargetFlags(strongMode: strongMode)),
+            new Dart2jsTarget(
+                targetName, new TargetFlags(strongMode: strongMode)),
+            librariesSpecification,
             platformBinaries.resolve(platform),
             _packageConfig);
         component = await fe.compile(
diff --git a/pkg/compiler/lib/src/options.dart b/pkg/compiler/lib/src/options.dart
index ec4b54c..c42e066 100644
--- a/pkg/compiler/lib/src/options.dart
+++ b/pkg/compiler/lib/src/options.dart
@@ -100,6 +100,10 @@
   /// and in the emitted output of the compiler.
   bool get hasBuildId => buildId != _UNDETERMINED_BUILD_ID;
 
+  /// Whether to compile for the server category. This is used to compile to JS
+  /// that is intended to be run on server-side VMs like nodejs.
+  final bool compileForServer;
+
   /// Location where to generate a map containing details of how deferred
   /// libraries are subdivided.
   final Uri deferredMapUri;
@@ -177,8 +181,12 @@
   final Uri outputUri;
 
   /// Location of the platform configuration file.
+  // TODO(sigmund): deprecate and remove, use only [librariesSpecificationUri]
   final Uri platformConfigUri;
 
+  /// Location of the libraries specification file.
+  final Uri librariesSpecificationUri;
+
   /// Location of the kernel platform `.dill` files.
   final Uri platformBinaries;
 
@@ -305,6 +313,7 @@
         analyzeSignaturesOnly: _hasOption(options, Flags.analyzeSignaturesOnly),
         buildId: _extractStringOption(
             options, '--build-id=', _UNDETERMINED_BUILD_ID),
+        compileForServer: _resolveCompileForServerFromOptions(options),
         deferredMapUri: _extractUriOption(options, '--deferred-map='),
         fatalWarnings: _hasOption(options, Flags.fatalWarnings),
         terseDiagnostics: _hasOption(options, Flags.terse),
@@ -336,6 +345,7 @@
         outputUri: _extractUriOption(options, '--out='),
         platformConfigUri:
             _resolvePlatformConfigFromOptions(libraryRoot, options),
+        librariesSpecificationUri: _resolveLibrariesSpecification(libraryRoot),
         platformBinaries: platformBinaries ??
             _extractUriOption(options, '--platform-binaries='),
         preserveComments: _hasOption(options, Flags.preserveComments),
@@ -382,6 +392,7 @@
       bool analyzeOnly: false,
       bool analyzeSignaturesOnly: false,
       String buildId: _UNDETERMINED_BUILD_ID,
+      bool compileForServer: false,
       Uri deferredMapUri: null,
       bool fatalWarnings: false,
       bool terseDiagnostics: false,
@@ -406,6 +417,7 @@
       bool kernelGlobalInference: false,
       Uri outputUri: null,
       Uri platformConfigUri: null,
+      Uri librariesSpecificationUri: null,
       Uri platformBinaries: null,
       bool preserveComments: false,
       bool preserveUris: false,
@@ -463,6 +475,7 @@
             analyzeOnly || analyzeSignaturesOnly || analyzeAll || resolveOnly,
         analyzeSignaturesOnly: analyzeSignaturesOnly,
         buildId: buildId,
+        compileForServer: compileForServer,
         deferredMapUri: deferredMapUri,
         fatalWarnings: fatalWarnings,
         terseDiagnostics: terseDiagnostics,
@@ -488,6 +501,7 @@
         outputUri: outputUri,
         platformConfigUri: platformConfigUri ??
             _resolvePlatformConfig(libraryRoot, null, const []),
+        librariesSpecificationUri: _resolveLibrariesSpecification(libraryRoot),
         platformBinaries: platformBinaries,
         preserveComments: preserveComments,
         preserveUris: preserveUris,
@@ -520,6 +534,7 @@
       this.analyzeOnly: false,
       this.analyzeSignaturesOnly: false,
       this.buildId: _UNDETERMINED_BUILD_ID,
+      this.compileForServer: false,
       this.deferredMapUri: null,
       this.fatalWarnings: false,
       this.terseDiagnostics: false,
@@ -543,6 +558,7 @@
       this.generateSourceMap: true,
       this.outputUri: null,
       this.platformConfigUri: null,
+      this.librariesSpecificationUri: null,
       this.platformBinaries: null,
       this.preserveComments: false,
       this.preserveUris: false,
@@ -583,6 +599,7 @@
       analyzeOnly,
       analyzeSignaturesOnly,
       buildId,
+      compileForServer,
       deferredMapUri,
       fatalWarnings,
       terseDiagnostics,
@@ -607,6 +624,7 @@
       kernelGlobalInference,
       outputUri,
       platformConfigUri,
+      librariesSpecificationUri,
       platformBinaries,
       preserveComments,
       preserveUris,
@@ -645,6 +663,7 @@
         analyzeSignaturesOnly:
             analyzeSignaturesOnly ?? options.analyzeSignaturesOnly,
         buildId: buildId ?? options.buildId,
+        compileForServer: compileForServer ?? options.compileForServer,
         deferredMapUri: deferredMapUri ?? options.deferredMapUri,
         fatalWarnings: fatalWarnings ?? options.fatalWarnings,
         terseDiagnostics: terseDiagnostics ?? options.terseDiagnostics,
@@ -678,6 +697,8 @@
         generateSourceMap: generateSourceMap ?? options.generateSourceMap,
         outputUri: outputUri ?? options.outputUri,
         platformConfigUri: platformConfigUri ?? options.platformConfigUri,
+        librariesSpecificationUri:
+            librariesSpecificationUri ?? options.librariesSpecificationUri,
         platformBinaries: platformBinaries ?? options.platformBinaries,
         preserveComments: preserveComments ?? options.preserveComments,
         preserveUris: preserveUris ?? options.preserveUris,
@@ -790,6 +811,11 @@
   }
 }
 
+bool _resolveCompileForServerFromOptions(List<String> options) {
+  var categories = _extractCsvOption(options, '--categories=');
+  return categories.length == 1 && categories.single == 'Server';
+}
+
 Uri _resolvePlatformConfigFromOptions(Uri libraryRoot, List<String> options) {
   return _resolvePlatformConfig(
       libraryRoot,
@@ -797,6 +823,9 @@
       _extractCsvOption(options, '--categories='));
 }
 
+Uri _resolveLibrariesSpecification(Uri libraryRoot) =>
+    libraryRoot.resolve('lib/libraries.json');
+
 /// Locations of the platform descriptor files relative to the library root.
 const String _clientPlatform = "lib/dart_client.platform";
 const String _serverPlatform = "lib/dart_server.platform";
diff --git a/pkg/compiler/lib/src/parser/element_listener.dart b/pkg/compiler/lib/src/parser/element_listener.dart
index 0658333..3f77774 100644
--- a/pkg/compiler/lib/src/parser/element_listener.dart
+++ b/pkg/compiler/lib/src/parser/element_listener.dart
@@ -350,13 +350,26 @@
   }
 
   @override
+  void beginNamedMixinApplication(
+      Token begin, Token abstractToken, Token name) {
+    if (abstractToken == null) {
+      pushNode(Modifiers.EMPTY);
+    } else {
+      Link<Node> poppedNodes = const Link<Node>();
+      poppedNodes = poppedNodes.prepend(new Identifier(abstractToken));
+      NodeList modifierNodes = new NodeList(null, poppedNodes, null, ' ');
+      pushNode(new Modifiers(modifierNodes));
+    }
+  }
+
+  @override
   void endNamedMixinApplication(Token beginToken, Token classKeyword,
       Token equals, Token implementsKeyword, Token endToken) {
     NodeList interfaces = (implementsKeyword != null) ? popNode() : null;
     MixinApplication mixinApplication = popNode();
+    Modifiers modifiers = popNode();
     NodeList typeParameters = popNode();
     Identifier name = popNode();
-    Modifiers modifiers = popNode();
     NamedMixinApplication namedMixinApplication = new NamedMixinApplication(
         name,
         typeParameters,
@@ -412,7 +425,8 @@
   }
 
   @override
-  void endTopLevelFields(int count, Token beginToken, Token endToken) {
+  void endTopLevelFields(Token staticToken, Token covariantToken,
+      Token varFinalOrConst, int count, Token beginToken, Token endToken) {
     bool hasParseError = currentMemberHasParseError;
     memberErrors = memberErrors.tail;
     void buildFieldElement(Identifier name, VariableList fields) {
@@ -421,11 +435,30 @@
 
     NodeList variables = makeNodeList(count, null, null, ",");
     popNode(); // type
-    Modifiers modifiers = popNode();
+    Modifiers modifiers =
+        newFieldModifiers(staticToken, covariantToken, varFinalOrConst);
     buildFieldElements(modifiers, variables, compilationUnitElement,
         buildFieldElement, beginToken, endToken, hasParseError);
   }
 
+  Modifiers newFieldModifiers(
+      Token staticToken, Token covariantToken, Token varFinalOrConst) {
+    Link<Node> modifierNodes = const Link<Node>();
+    if (varFinalOrConst != null) {
+      modifierNodes = modifierNodes.prepend(new Identifier(varFinalOrConst));
+    }
+    if (covariantToken != null) {
+      modifierNodes = modifierNodes.prepend(new Identifier(covariantToken));
+    }
+    if (staticToken != null) {
+      modifierNodes = modifierNodes.prepend(new Identifier(staticToken));
+    }
+    if (!modifierNodes.isNotEmpty) {
+      return Modifiers.EMPTY;
+    }
+    return new Modifiers(new NodeList(null, modifierNodes, null, ' '));
+  }
+
   @override
   void handleInvalidTopLevelDeclaration(Token endToken) {
     memberErrors = memberErrors.tail;
diff --git a/pkg/compiler/lib/src/parser/member_listener.dart b/pkg/compiler/lib/src/parser/member_listener.dart
index 7846f70..3d1ed39 100644
--- a/pkg/compiler/lib/src/parser/member_listener.dart
+++ b/pkg/compiler/lib/src/parser/member_listener.dart
@@ -117,9 +117,11 @@
   }
 
   @override
-  void endFields(int count, Token beginToken, Token endToken) {
+  void endFields(Token staticToken, Token covariantToken, Token varFinalOrConst,
+      int count, Token beginToken, Token endToken) {
     bool hasParseError = memberErrors.head;
-    super.endFields(count, beginToken, endToken);
+    super.endFields(staticToken, covariantToken, varFinalOrConst, count,
+        beginToken, endToken);
     VariableDefinitions variableDefinitions = popNode();
     Modifiers modifiers = variableDefinitions.modifiers;
     pushNode(null);
diff --git a/pkg/compiler/lib/src/parser/node_listener.dart b/pkg/compiler/lib/src/parser/node_listener.dart
index 54d308e..bb0925d 100644
--- a/pkg/compiler/lib/src/parser/node_listener.dart
+++ b/pkg/compiler/lib/src/parser/node_listener.dart
@@ -122,14 +122,26 @@
   }
 
   @override
+  void beginClassDeclaration(Token begin, Token abstractToken, Token name) {
+    if (abstractToken == null) {
+      pushNode(Modifiers.EMPTY);
+    } else {
+      Link<Node> poppedNodes = const Link<Node>();
+      poppedNodes = poppedNodes.prepend(new Identifier(abstractToken));
+      NodeList modifierNodes = new NodeList(null, poppedNodes, null, ' ');
+      pushNode(new Modifiers(modifierNodes));
+    }
+  }
+
+  @override
   void endClassDeclaration(Token beginToken, Token endToken) {
     NodeList body = popNode();
     NodeList interfaces = popNode();
     TokenNode extendsNode = popNode();
     Node supertype = popNode();
+    Modifiers modifiers = popNode();
     NodeList typeParameters = popNode();
     Identifier name = popNode();
-    Modifiers modifiers = popNode();
     // TODO(danrubel): can we remove the extends keyword from ClassNode ?
     pushNode(new ClassNode(modifiers, name, typeParameters, supertype,
         interfaces, beginToken, extendsNode.token, body, endToken));
@@ -216,9 +228,9 @@
       Token equals, Token implementsKeyword, Token endToken) {
     NodeList interfaces = (implementsKeyword != null) ? popNode() : null;
     Node mixinApplication = popNode();
+    Modifiers modifiers = popNode();
     NodeList typeParameters = popNode();
     Identifier name = popNode();
-    Modifiers modifiers = popNode();
     pushNode(new NamedMixinApplication(name, typeParameters, modifiers,
         mixinApplication, interfaces, beginToken, endToken));
   }
@@ -238,10 +250,12 @@
   }
 
   @override
-  void endTopLevelFields(int count, Token beginToken, Token endToken) {
+  void endTopLevelFields(Token staticToken, Token covariantToken,
+      Token varFinalOrConst, int count, Token beginToken, Token endToken) {
     NodeList variables = makeNodeList(count, null, endToken, ",");
     TypeAnnotation type = popNode();
-    Modifiers modifiers = popNode();
+    Modifiers modifiers =
+        newFieldModifiers(staticToken, covariantToken, varFinalOrConst);
     pushNode(new VariableDefinitions(type, modifiers, variables));
   }
 
@@ -567,6 +581,7 @@
     TypeAnnotation type = popNode();
     Modifiers modifiers = new Modifiers(new NodeList.empty());
     NodeList typeVariables = popNode();
+    popNode(); // Metadata.
     pushNode(new FunctionDeclaration(new FunctionExpression(name, typeVariables,
         formals, body, type, modifiers, initializers, null, asyncModifier)));
   }
@@ -751,10 +766,12 @@
   }
 
   @override
-  void endFields(int count, Token beginToken, Token endToken) {
+  void endFields(Token staticToken, Token covariantToken, Token varFinalOrConst,
+      int count, Token beginToken, Token endToken) {
     NodeList variables = makeNodeList(count, null, endToken, ",");
     TypeAnnotation type = popNode();
-    Modifiers modifiers = popNode();
+    Modifiers modifiers =
+        newFieldModifiers(staticToken, covariantToken, varFinalOrConst);
     pushNode(new VariableDefinitions(type, modifiers, variables));
   }
 
diff --git a/pkg/compiler/tool/generate_kernel.dart b/pkg/compiler/tool/generate_kernel.dart
index a649997..1ccdd8b 100644
--- a/pkg/compiler/tool/generate_kernel.dart
+++ b/pkg/compiler/tool/generate_kernel.dart
@@ -23,7 +23,7 @@
 main(List<String> args) async {
   ArgResults flags = _argParser.parse(args);
   var options = new CompilerOptions()
-    ..target = new Dart2jsTarget(new TargetFlags())
+    ..target = new Dart2jsTarget("dart2js", new TargetFlags())
     ..packagesFileUri = Uri.base.resolve('.packages')
     ..setExitCodeOnProblem = true
     ..linkedDependencies = [
diff --git a/pkg/dev_compiler/tool/input_sdk/patch/core_patch.dart b/pkg/dev_compiler/tool/input_sdk/patch/core_patch.dart
index 3e7dd29..048f13f 100644
--- a/pkg/dev_compiler/tool/input_sdk/patch/core_patch.dart
+++ b/pkg/dev_compiler/tool/input_sdk/patch/core_patch.dart
@@ -1219,6 +1219,7 @@
   /// Does *not* clear digits below ds.
   static void _lsh(
       Uint16List xDigits, int xUsed, int n, Uint16List resultDigits) {
+    assert(xUsed > 0);
     final digitShift = n ~/ _digitBits;
     final bitShift = n % _digitBits;
     final carryBitShift = _digitBits - bitShift;
@@ -1248,6 +1249,7 @@
     if (shiftAmount < 0) {
       throw new ArgumentError("shift-amount must be posititve $shiftAmount");
     }
+    if (_isZero) return this;
     final digitShift = shiftAmount ~/ _digitBits;
     final bitShift = shiftAmount % _digitBits;
     if (bitShift == 0) {
@@ -1283,6 +1285,7 @@
   // resultDigits[0..resultUsed-1] = xDigits[0..xUsed-1] >> n.
   static void _rsh(
       Uint16List xDigits, int xUsed, int n, Uint16List resultDigits) {
+    assert(xUsed > 0);
     final digitsShift = n ~/ _digitBits;
     final bitShift = n % _digitBits;
     final carryBitShift = _digitBits - bitShift;
@@ -1310,6 +1313,7 @@
     if (shiftAmount < 0) {
       throw new ArgumentError("shift-amount must be posititve $shiftAmount");
     }
+    if (_isZero) return this;
     final digitShift = shiftAmount ~/ _digitBits;
     final bitShift = shiftAmount % _digitBits;
     if (bitShift == 0) {
@@ -1552,6 +1556,7 @@
    */
   _BigIntImpl operator &(BigInt bigInt) {
     _BigIntImpl other = bigInt;
+    if (_isZero || other._isZero) return zero;
     if (_isNegative == other._isNegative) {
       if (_isNegative) {
         // (-this) & (-other) == ~(this-1) & ~(other-1)
@@ -1591,6 +1596,8 @@
    */
   _BigIntImpl operator |(BigInt bigInt) {
     _BigIntImpl other = bigInt;
+    if (_isZero) return other;
+    if (other._isZero) return this;
     if (_isNegative == other._isNegative) {
       if (_isNegative) {
         // (-this) | (-other) == ~(this-1) | ~(other-1)
@@ -1631,6 +1638,8 @@
    */
   _BigIntImpl operator ^(BigInt bigInt) {
     _BigIntImpl other = bigInt;
+    if (_isZero) return other;
+    if (other._isZero) return this;
     if (_isNegative == other._isNegative) {
       if (_isNegative) {
         // (-this) ^ (-other) == ~(this-1) ^ ~(other-1) == (this-1) ^ (other-1)
@@ -1665,6 +1674,7 @@
    * This maps any integer `x` to `-x - 1`.
    */
   _BigIntImpl operator ~() {
+    if (_isZero) return _minusOne;
     if (_isNegative) {
       // ~(-this) == ~(~(this-1)) == this-1
       return _absSubSetSign(one, false);
@@ -1677,6 +1687,8 @@
   /// Addition operator.
   _BigIntImpl operator +(BigInt bigInt) {
     _BigIntImpl other = bigInt;
+    if (_isZero) return other;
+    if (other._isZero) return this;
     var isNegative = _isNegative;
     if (isNegative == other._isNegative) {
       // this + other == this + other
@@ -1694,6 +1706,8 @@
   /// Subtraction operator.
   _BigIntImpl operator -(BigInt bigInt) {
     _BigIntImpl other = bigInt;
+    if (_isZero) return -other;
+    if (other._isZero) return this;
     var isNegative = _isNegative;
     if (isNegative != other._isNegative) {
       // this - (-other) == this + other
diff --git a/pkg/front_end/lib/src/api_prototype/incremental_kernel_generator.dart b/pkg/front_end/lib/src/api_prototype/incremental_kernel_generator.dart
index 460e203..c60a782 100644
--- a/pkg/front_end/lib/src/api_prototype/incremental_kernel_generator.dart
+++ b/pkg/front_end/lib/src/api_prototype/incremental_kernel_generator.dart
@@ -22,8 +22,9 @@
         bootstrapDill);
   }
 
-  /// Returns a component whose libraries are the recompiled libraries.
-  Future<Component> computeDelta({Uri entryPoint});
+  /// Returns a component whose libraries are the recompiled libraries,
+  /// or - in the case of [fullComponent] - a full Component.
+  Future<Component> computeDelta({Uri entryPoint, bool fullComponent});
 
   /// Remove the file associated with the given file [uri] from the set of
   /// valid files.  This guarantees that those files will be re-read on the
diff --git a/pkg/front_end/lib/src/api_unstable/dart2js.dart b/pkg/front_end/lib/src/api_unstable/dart2js.dart
index c8151c0..666f32d 100644
--- a/pkg/front_end/lib/src/api_unstable/dart2js.dart
+++ b/pkg/front_end/lib/src/api_unstable/dart2js.dart
@@ -27,18 +27,24 @@
 
 export 'compiler_state.dart' show InitializedCompilerState;
 
-InitializedCompilerState initializeCompiler(InitializedCompilerState oldState,
-    Target target, Uri sdkUri, Uri packagesFileUri) {
+InitializedCompilerState initializeCompiler(
+    InitializedCompilerState oldState,
+    Target target,
+    Uri librariesSpecificationUri,
+    Uri sdkPlatformUri,
+    Uri packagesFileUri) {
   if (oldState != null &&
       oldState.options.packagesFileUri == packagesFileUri &&
-      oldState.options.linkedDependencies[0] == sdkUri) {
+      oldState.options.librariesSpecificationUri == librariesSpecificationUri &&
+      oldState.options.linkedDependencies[0] == sdkPlatformUri) {
     return oldState;
   }
 
   CompilerOptions options = new CompilerOptions()
     ..target = target
     ..strongMode = target.strongMode
-    ..linkedDependencies = [sdkUri]
+    ..linkedDependencies = [sdkPlatformUri]
+    ..librariesSpecificationUri = librariesSpecificationUri
     ..packagesFileUri = packagesFileUri;
 
   ProcessedOptions processedOpts = new ProcessedOptions(options, false, []);
diff --git a/pkg/front_end/lib/src/base/libraries_specification.dart b/pkg/front_end/lib/src/base/libraries_specification.dart
index 3c1dcfb..28c95fe 100644
--- a/pkg/front_end/lib/src/base/libraries_specification.dart
+++ b/pkg/front_end/lib/src/base/libraries_specification.dart
@@ -30,6 +30,12 @@
 ///             "convert": {
 ///                "uri": "convert/convert.dart",
 ///             }
+///             "mirrors": {
+///                "uri": "mirrors/mirrors.dart",
+///             }
+///         }
+///         "environment_overrides": {
+///             "mirrors": false
 ///         }
 ///       }
 ///     }
@@ -38,9 +44,8 @@
 ///   - a top level entry for each target. Keys are target names (e.g. "vm"
 ///     above), and values contain the entire specification of a target.
 ///
-///   - each target specification is a map. Today only one key ("libraries") is
-///     supported, but this may be extended in the future to add more
-///     information on each target.
+///   - each target specification is a map. Today two keys are supported:
+///     "libraries" and "environment_overrides".
 ///
 ///   - The "libraries" entry contains details for how each platform library is
 ///     implemented. The entry is a map, where keys are the name of the platform
@@ -58,6 +63,20 @@
 ///     which will be resolved relative to the location of the library
 ///     specification file.
 ///
+///   - The "environment_overrides" entry contains rules to override the value
+///     of environment variables that are derived from the platform libraries.
+///
+///     By default every platform library that is available in the "libraries"
+///     section implicitly defines an environment variable `dart.library.name`
+///     as `"true"`, to indicate that the library is supported.  Some backends
+///     override this to allow imports to a platform library, but still report
+///     that the library is not supported in conditional imports and const
+///     `fromEnvironment` expressions.
+///
+///     A name key listed in the "environment_overrides" section must match the
+///     name of a library in the "libraries" section. The value is a bool,
+///     however, since the libraries are assumed to be supported by default, we
+///     only expect users to use `false`.
 ///
 /// Note: we currently have several different files that need to be updated
 /// when changing libraries, sources, and patch files:
@@ -69,6 +88,9 @@
 /// https://github.com/dart-lang/sdk/issues/28836), but for now we need to pay
 /// close attention to change them consistently.
 
+// TODO(sigmund): consider moving the overrides directly into the libraries
+// section (e.g. add a "supported: false" entry).
+
 // TODO(sigmund): move this file to a shared package.
 import 'dart:convert' show JSON;
 
@@ -84,10 +106,16 @@
   const LibrariesSpecification(
       [this._targets = const <String, TargetLibrariesSpecification>{}]);
 
-  /// The library specification for a given [target], or null if none is
+  /// The library specification for a given [target], or throws if none is
   /// available.
-  TargetLibrariesSpecification specificationFor(String target) =>
-      _targets[target];
+  TargetLibrariesSpecification specificationFor(String target) {
+    var targetSpec = _targets[target];
+    if (targetSpec == null) {
+      throw new LibrariesSpecificationException(
+        'No library specification for target "$target"');
+    }
+    return targetSpec;
+  }
 
   /// Parse the given [json] as a library specification, resolving any relative
   /// paths from [baseUri].
@@ -153,8 +181,28 @@
         }
         libraries[name] = new LibraryInfo(name, uri, patches);
       });
-      targets[targetName] =
-          new TargetLibrariesSpecification(targetName, libraries);
+      Map<String, bool> environmentOverrides = <String, bool>{};
+      if (targetData.containsKey("environment_overrides")) {
+        var overridesData = targetData["environment_overrides"];
+        if (overridesData is! Map) {
+          return _reportError(
+              "environment_overrides entry for '$targetName' is not a map");
+        }
+        overridesData.forEach((String name, value) {
+          if (!libraries.containsKey(name)) {
+            return _reportError(
+                "entry '$name' does not correspond to an existing library "
+                "in '$targetName'");
+          }
+          if (value is bool) {
+            environmentOverrides[name] = value;
+          } else {
+            return _reportError("entry '$name' is not a bool");
+          }
+        });
+      }
+      targets[targetName] = new TargetLibrariesSpecification(
+          targetName, libraries, environmentOverrides);
     });
     return new LibrariesSpecification(targets);
   }
@@ -180,6 +228,10 @@
         };
       });
       result[targetName] = {'libraries': libraries};
+      if (target._environmentOverrides.isNotEmpty) {
+        result[targetName]['environment_overrides'] =
+            target._environmentOverrides;
+      }
     });
     return result;
   }
@@ -192,11 +244,21 @@
 
   final Map<String, LibraryInfo> _libraries;
 
+  final Map<String, bool> _environmentOverrides;
+
   const TargetLibrariesSpecification(this.targetName,
-      [this._libraries = const <String, LibraryInfo>{}]);
+      [this._libraries = const <String, LibraryInfo>{},
+      this._environmentOverrides = const <String, bool>{}]);
 
   /// Details about a library whose import is `dart:$name`.
   LibraryInfo libraryInfoFor(String name) => _libraries[name];
+
+  /// Environment override for a library whose import is `dart:$name`. The value
+  /// can be "true", "false", or null if no override was given.
+  String environmentOverrideFor(String name) {
+    var override = _environmentOverrides[name];
+    return override == null ? null : "$override";
+  }
 }
 
 /// Information about a `dart:` library in a specific target platform.
diff --git a/pkg/front_end/lib/src/fasta/builder_graph.dart b/pkg/front_end/lib/src/fasta/builder_graph.dart
index b78d5f9..b4350b1 100644
--- a/pkg/front_end/lib/src/fasta/builder_graph.dart
+++ b/pkg/front_end/lib/src/fasta/builder_graph.dart
@@ -4,6 +4,8 @@
 
 library fasta.builder_graph;
 
+import 'package:kernel/kernel.dart' show LibraryDependency, LibraryPart;
+
 import 'package:kernel/util/graph.dart' show Graph;
 
 import 'builder/builder.dart' show LibraryBuilder;
@@ -49,22 +51,15 @@
       }
     } else if (library is DillLibraryBuilder) {
       // Imports and exports
-      for (var dependency in library.library.dependencies) {
-        var uriString;
-        if (dependency.importedLibraryReference.node != null) {
-          uriString = '${dependency.targetLibrary.importUri}';
-        } else {
-          uriString =
-              '${dependency.importedLibraryReference.canonicalName.name}';
-        }
-        Uri uri = Uri.parse(uriString);
+      for (LibraryDependency dependency in library.library.dependencies) {
+        Uri uri = dependency.targetLibrary.importUri;
         if (builders.containsKey(uri)) {
           yield uri;
         }
       }
 
       // Parts
-      for (var part in library.library.parts) {
+      for (LibraryPart part in library.library.parts) {
         Uri uri = part.fileUri;
         if (builders.containsKey(uri)) {
           yield uri;
diff --git a/pkg/front_end/lib/src/fasta/compiler_context.dart b/pkg/front_end/lib/src/fasta/compiler_context.dart
index 77ab869..54d8af3 100644
--- a/pkg/front_end/lib/src/fasta/compiler_context.dart
+++ b/pkg/front_end/lib/src/fasta/compiler_context.dart
@@ -125,7 +125,8 @@
     return current.enableColorsCached ??= computeEnableColors(current);
   }
 
-  static void clear() {
+  void clear() {
     StringToken.canonicalizer.clear();
+    errors.clear();
   }
 }
diff --git a/pkg/front_end/lib/src/fasta/incremental_compiler.dart b/pkg/front_end/lib/src/fasta/incremental_compiler.dart
index b3039b5..3d7d04b 100644
--- a/pkg/front_end/lib/src/fasta/incremental_compiler.dart
+++ b/pkg/front_end/lib/src/fasta/incremental_compiler.dart
@@ -8,13 +8,14 @@
 
 import 'package:kernel/binary/ast_from_binary.dart' show BinaryBuilder;
 
-import 'package:kernel/kernel.dart' show Library, Procedure, Component, Source;
+import 'package:kernel/kernel.dart'
+    show Component, Library, LibraryPart, Procedure, Source;
+
+import '../api_prototype/file_system.dart' show FileSystemEntity;
 
 import '../api_prototype/incremental_kernel_generator.dart'
     show IncrementalKernelGenerator;
 
-import '../api_prototype/file_system.dart' show FileSystemEntity;
-
 import 'builder/builder.dart' show LibraryBuilder;
 
 import 'builder_graph.dart' show BuilderGraph;
@@ -25,7 +26,10 @@
 
 import 'dill/dill_target.dart' show DillTarget;
 
-import 'kernel/kernel_target.dart' show KernelTarget;
+import 'kernel/kernel_incremental_target.dart'
+    show KernelIncrementalTarget, KernelIncrementalTargetErroneousComponent;
+
+import 'library_graph.dart' show LibraryGraph;
 
 import 'source/source_library_builder.dart' show SourceLibraryBuilder;
 
@@ -46,13 +50,14 @@
   final Uri initializeFromDillUri;
   bool initializedFromDill = false;
 
-  KernelTarget userCode;
+  KernelIncrementalTarget userCode;
 
   IncrementalCompiler(this.context, [this.initializeFromDillUri])
       : ticker = context.options.ticker;
 
   @override
-  Future<Component> computeDelta({Uri entryPoint}) async {
+  Future<Component> computeDelta(
+      {Uri entryPoint, bool fullComponent: false}) async {
     ticker.reset();
     entryPoint ??= context.options.inputs.single;
     return context.runInContext<Future<Component>>((CompilerContext c) async {
@@ -72,7 +77,7 @@
             bytesLength = prepareSummary(summaryBytes, uriTranslator, c, data);
           }
         }
-        appendLibraries(data, bytesLength);
+        appendLibraries(data, bytesLength, uriTranslator);
 
         try {
           await dillLoadedData.buildOutlines();
@@ -83,7 +88,7 @@
           initializedFromDill = false;
           data.reset();
           bytesLength = prepareSummary(summaryBytes, uriTranslator, c, data);
-          appendLibraries(data, bytesLength);
+          appendLibraries(data, bytesLength, uriTranslator);
           await dillLoadedData.buildOutlines();
         }
         summaryBytes = null;
@@ -115,11 +120,13 @@
         ticker.logMs("Decided to reuse ${reusedLibraries.length}"
             " of ${userCode.loader.builders.length} libraries");
       }
-
       reusedLibraries.addAll(platformBuilders);
-      userCode = new KernelTarget(
+
+      KernelIncrementalTarget userCodeOld = userCode;
+      userCode = new KernelIncrementalTarget(
           c.fileSystem, false, dillLoadedData, dillLoadedData.uriTranslator,
           uriToSource: c.uriToSource);
+
       for (LibraryBuilder library in reusedLibraries) {
         userCode.loader.builders[library.uri] = library;
         if (library.uri.scheme == "dart" && library.uri.path == "core") {
@@ -127,47 +134,97 @@
         }
       }
 
-      userCode.read(entryPoint);
+      Component componentWithDill;
+      try {
+        userCode.read(entryPoint);
+        await userCode.buildOutlines();
 
-      await userCode.buildOutlines();
-
-      // This is not the full program. It is the component including all
-      // libraries loaded from .dill files.
-      Component componentWithDill =
-          await userCode.buildComponent(verify: c.options.verify);
+        // This is not the full component. It is the component including all
+        // libraries loaded from .dill files.
+        componentWithDill =
+            await userCode.buildComponent(verify: c.options.verify);
+      } on KernelIncrementalTargetErroneousComponent {
+        List<Library> librariesWithSdk = userCode.component.libraries;
+        List<Library> libraries = <Library>[];
+        for (Library lib in librariesWithSdk) {
+          if (lib.fileUri.scheme == "dart") continue;
+          libraries.add(lib);
+          break;
+        }
+        userCode.loader.builders.clear();
+        userCode = userCodeOld;
+        return new Component(
+            libraries: libraries, uriToSource: data.uriToSource);
+      }
+      userCodeOld?.loader?.builders?.clear();
+      userCodeOld = null;
 
       List<Library> libraries =
           new List<Library>.from(userCode.loader.libraries);
       data.uriToSource.addAll(userCode.uriToSource);
-      if (data.includeUserLoadedLibraries) {
-        for (LibraryBuilder library in reusedLibraries) {
-          if (library.fileUri.scheme == "dart") continue;
-          assert(library is DillLibraryBuilder);
-          libraries.add((library as DillLibraryBuilder).library);
-        }
-
-        // For now ensure original order of libraries to produce bit-perfect
-        // output.
-        libraries.sort((a, b) {
-          int aOrder = data.importUriToOrder[a.importUri];
-          int bOrder = data.importUriToOrder[b.importUri];
-          if (aOrder != null && bOrder != null) return aOrder - bOrder;
-          if (aOrder != null) return -1;
-          if (bOrder != null) return 1;
-          return 0;
-        });
-      }
-
-      // This component represents the parts of the program that were
-      // recompiled.
       Procedure mainMethod = componentWithDill == null
           ? data.userLoadedUriMain
           : componentWithDill.mainMethod;
+      if (data.includeUserLoadedLibraries || fullComponent) {
+        addReusedLibraries(libraries, mainMethod, reusedLibraries, data);
+      }
+
+      // Clean up.
+      userCode.loader.releaseAncillaryResources();
+
+      // This is the incremental component.
       return new Component(libraries: libraries, uriToSource: data.uriToSource)
         ..mainMethod = mainMethod;
     });
   }
 
+  void addReusedLibraries(List<Library> libraries, Procedure mainMethod,
+      List<LibraryBuilder> reusedLibraries, IncrementalCompilerData data) {
+    Map<Uri, Library> libraryMap = <Uri, Library>{};
+    for (Library library in libraries) {
+      libraryMap[library.fileUri] = library;
+    }
+    List<Uri> worklist = new List<Uri>.from(libraryMap.keys);
+    worklist.add(mainMethod?.enclosingLibrary?.fileUri);
+
+    Map<Uri, Library> potentiallyReferencedLibraries = <Uri, Library>{};
+    for (LibraryBuilder library in reusedLibraries) {
+      if (library.fileUri.scheme == "dart") continue;
+      Library lib = library.target;
+      potentiallyReferencedLibraries[library.fileUri] = lib;
+      libraryMap[library.fileUri] = lib;
+    }
+
+    LibraryGraph graph = new LibraryGraph(libraryMap);
+    while (worklist.isNotEmpty && potentiallyReferencedLibraries.isNotEmpty) {
+      Uri uri = worklist.removeLast();
+      if (libraryMap.containsKey(uri)) {
+        for (Uri neighbor in graph.neighborsOf(uri)) {
+          worklist.add(neighbor);
+        }
+        libraryMap.remove(uri);
+        Library library = potentiallyReferencedLibraries.remove(uri);
+        if (library != null) {
+          libraries.add(library);
+        }
+      }
+    }
+    for (Uri uri in potentiallyReferencedLibraries.keys) {
+      userCode.loader.builders.remove(uri);
+    }
+
+    // For now ensure original order of libraries to produce bit-perfect
+    // output.
+    libraries.sort((a, b) {
+      int aOrder = data.importUriToOrder[a.importUri];
+      int bOrder = data.importUriToOrder[b.importUri];
+      if (aOrder != null && bOrder != null) return aOrder - bOrder;
+      if (aOrder != null) return -1;
+      if (bOrder != null) return 1;
+      return 0;
+    });
+  }
+
   int prepareSummary(List<int> summaryBytes, UriTranslator uriTranslator,
       CompilerContext c, IncrementalCompilerData data) {
     dillLoadedData = new DillTarget(ticker, uriTranslator, c.options.target);
@@ -198,6 +255,8 @@
             data.component.libraries.map((Library lib) => lib.importUri));
         ticker.logMs("Read $initializeFromDillUri");
 
+        Set<Uri> sdkUris = data.component.uriToSource.keys.toSet();
+
         // We're going to output all we read here so lazy loading it
         // doesn't make sense.
         new BinaryBuilder(initializationBytes, disableLazyReading: true)
@@ -211,14 +270,29 @@
         }
         data.userLoadedUriMain = data.component.mainMethod;
         data.includeUserLoadedLibraries = true;
-        data.uriToSource.addAll(data.component.uriToSource);
+        for (Uri uri in data.component.uriToSource.keys) {
+          if (sdkUris.contains(uri)) continue;
+          data.uriToSource[uri] = data.component.uriToSource[uri];
+        }
       }
     }
     return bytesLength;
   }
 
-  void appendLibraries(IncrementalCompilerData data, int bytesLength) {
+  void appendLibraries(IncrementalCompilerData data, int bytesLength,
+      UriTranslator uriTranslator) {
     if (data.component != null) {
+      List<Library> keepLibraries = <Library>[];
+      for (Library lib in data.component.libraries) {
+        if (lib.importUri.scheme != "package" ||
+            uriTranslator.translate(lib.importUri, false) != null) {
+          keepLibraries.add(lib);
+        }
+      }
+      data.component.libraries
+        ..clear()
+        ..addAll(keepLibraries);
+
       dillLoadedData.loader
           .appendLibraries(data.component, byteCount: bytesLength);
     }
@@ -254,11 +328,11 @@
       }
       if (!recursive) return;
       if (library is SourceLibraryBuilder) {
-        for (var part in library.parts) {
+        for (LibraryBuilder part in library.parts) {
           addBuilderAndInvalidateUris(part.uri, part, false);
         }
       } else if (library is DillLibraryBuilder) {
-        for (var part in library.library.parts) {
+        for (LibraryPart part in library.library.parts) {
           addBuilderAndInvalidateUris(part.fileUri, library, false);
         }
       }
@@ -269,6 +343,8 @@
       userCode.loader.builders.forEach(addBuilderAndInvalidateUris);
     }
 
+    recordInvalidatedImportUrisForTesting(invalidatedImportUris);
+
     BuilderGraph graph = new BuilderGraph(builders);
 
     // Compute direct dependencies for each import URI (the reverse of the
@@ -309,7 +385,7 @@
     // builder can exist multiple times in the values list.
     Set<Uri> seenUris = new Set<Uri>();
     List<LibraryBuilder> result = <LibraryBuilder>[];
-    for (var builder in builders.values) {
+    for (LibraryBuilder builder in builders.values) {
       if (builder.isPart) continue;
       if (!seenUris.add(builder.fileUri)) continue;
       result.add(builder);
@@ -321,6 +397,8 @@
   void invalidate(Uri uri) {
     invalidatedUris.add(uri);
   }
+
+  void recordInvalidatedImportUrisForTesting(List<Uri> uris) {}
 }
 
 class IncrementalCompilerData {
diff --git a/pkg/front_end/lib/src/fasta/kernel/body_builder.dart b/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
index bdf106f..542a791 100644
--- a/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
@@ -429,13 +429,15 @@
   }
 
   @override
-  void endTopLevelFields(int count, Token beginToken, Token endToken) {
+  void endTopLevelFields(Token staticToken, Token covariantToken,
+      Token varFinalOrConst, int count, Token beginToken, Token endToken) {
     debugEvent("TopLevelFields");
     push(count);
   }
 
   @override
-  void endFields(int count, Token beginToken, Token endToken) {
+  void endFields(Token staticToken, Token covariantToken, Token varFinalOrConst,
+      int count, Token beginToken, Token endToken) {
     debugEvent("Fields");
     push(count);
   }
@@ -471,7 +473,6 @@
       }
     }
     pop(); // Type.
-    pop(); // Modifiers.
     List annotations = pop();
     if (annotations != null) {
       _typeInferrer.inferMetadata(this, annotations);
@@ -2861,6 +2862,9 @@
     returnType ??= const DynamicType();
     exitFunction();
     List<TypeParameter> typeParameters = typeVariableBuildersToKernel(pop());
+    if (!isFunctionExpression) {
+      pop(); // Metadata.
+    }
     FunctionNode function = formals.addToFunction(new FunctionNode(body,
         typeParameters: typeParameters,
         asyncMarker: asyncModifier,
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_class_builder.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_class_builder.dart
index b4e425e..5ead269 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_class_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_class_builder.dart
@@ -27,7 +27,9 @@
 
 import 'package:kernel/class_hierarchy.dart' show ClassHierarchy;
 
-import 'package:kernel/type_algebra.dart' show Substitution;
+import 'package:kernel/clone.dart' show CloneWithoutBody;
+
+import 'package:kernel/type_algebra.dart' show Substitution, getSubstitutionMap;
 
 import 'package:kernel/type_environment.dart' show TypeEnvironment;
 
@@ -51,6 +53,8 @@
         templateOverrideTypeVariablesMismatch,
         templateRedirectionTargetNotFound;
 
+import '../names.dart' show noSuchMethodName;
+
 import '../problems.dart' show unexpected, unhandled, unimplemented;
 
 import '../type_inference/type_schema.dart' show UnknownType;
@@ -284,6 +288,73 @@
     });
   }
 
+  // TODO(dmitryas): Find a better place for this routine.
+  static bool hasUserDefinedNoSuchMethod(
+      Class klass, ClassHierarchy hierarchy) {
+    Member noSuchMethod = hierarchy.getDispatchTarget(klass, noSuchMethodName);
+    // `Object` doesn't have a superclass reference.
+    return noSuchMethod != null &&
+        noSuchMethod.enclosingClass.superclass != null;
+  }
+
+  void addNoSuchMethodForwarderForProcedure(
+      Procedure procedure, ClassHierarchy hierarchy) {
+    CloneWithoutBody cloner = new CloneWithoutBody(
+        typeSubstitution: getSubstitutionMap(
+            hierarchy.getClassAsInstanceOf(cls, procedure.enclosingClass)));
+    Procedure cloned = cloner.clone(procedure);
+    cloned.isAbstract = true;
+    cloned.isNoSuchMethodForwarder = true;
+
+    String name = cloned.name.name;
+    cls.procedures.add(cloned);
+    cloned.parent = cls;
+    DillMemberBuilder memberBuilder = new DillMemberBuilder(cloned, this);
+    memberBuilder.next = scopeBuilder[name];
+    scopeBuilder.addMember(name, memberBuilder);
+  }
+
+  void addNoSuchMethodForwarders(ClassHierarchy hierarchy) {
+    if (!hasUserDefinedNoSuchMethod(cls, hierarchy)) {
+      return;
+    }
+
+    Set<Name> existingForwardersNames = new Set<Name>();
+    if (cls.superclass != null &&
+        hasUserDefinedNoSuchMethod(cls.superclass, hierarchy)) {
+      List<Member> concrete = hierarchy.getDispatchTargets(cls.superclass);
+      for (Member member in hierarchy.getInterfaceMembers(cls.superclass)) {
+        if (ClassHierarchy.findMemberByName(concrete, member.name) == null) {
+          existingForwardersNames.add(member.name);
+        }
+      }
+    }
+    if (cls.mixedInClass != null &&
+        hasUserDefinedNoSuchMethod(cls.mixedInClass, hierarchy)) {
+      List<Member> concrete = hierarchy.getDispatchTargets(cls.mixedInClass);
+      for (Member member in hierarchy.getInterfaceMembers(cls.mixedInClass)) {
+        if (ClassHierarchy.findMemberByName(concrete, member.name) == null) {
+          existingForwardersNames.add(member.name);
+        }
+      }
+    }
+
+    List<Member> concrete = hierarchy.getDispatchTargets(cls);
+    List<Member> declared = hierarchy.getDeclaredMembers(cls);
+    for (Member member in hierarchy.getInterfaceMembers(cls)) {
+      if ((member is Procedure) &&
+          ClassHierarchy.findMemberByName(concrete, member.name) == null &&
+          !existingForwardersNames.contains(member.name)) {
+        if (ClassHierarchy.findMemberByName(declared, member.name) != null) {
+          member.isNoSuchMethodForwarder = true;
+        } else {
+          addNoSuchMethodForwarderForProcedure(member, hierarchy);
+        }
+        existingForwardersNames.add(member.name);
+      }
+    }
+  }
+
   Uri _getMemberUri(Member member) {
     if (member is Field) return member.fileUri;
     if (member is Procedure) return member.fileUri;
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_incremental_target.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_incremental_target.dart
new file mode 100644
index 0000000..d83c9ae
--- /dev/null
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_incremental_target.dart
@@ -0,0 +1,35 @@
+// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library fasta.kernel_incremental_target;
+
+import 'package:kernel/ast.dart' show Component, Source;
+
+import '../../api_prototype/file_system.dart' show FileSystem;
+
+import '../dill/dill_target.dart' show DillTarget;
+
+import '../uri_translator.dart' show UriTranslator;
+
+import 'kernel_target.dart' show KernelTarget;
+
+class KernelIncrementalTarget extends KernelTarget {
+  Component component;
+
+  KernelIncrementalTarget(FileSystem fileSystem, bool includeComments,
+      DillTarget dillTarget, UriTranslator uriTranslator,
+      {Map<Uri, Source> uriToSource})
+      : super(fileSystem, includeComments, dillTarget, uriTranslator,
+            uriToSource: uriToSource);
+
+  @override
+  Component erroneousComponent(bool isFullComponent) {
+    component = super.erroneousComponent(isFullComponent);
+    throw const KernelIncrementalTargetErroneousComponent();
+  }
+}
+
+class KernelIncrementalTargetErroneousComponent {
+  const KernelIncrementalTargetErroneousComponent();
+}
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart
index 9550057..778e898 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart
@@ -264,6 +264,9 @@
         loader.performTopLevelInference(myClasses);
       }
       loader.checkOverrides(myClasses);
+      if (backendTarget.enableNoSuchMethodForwarders) {
+        loader.addNoSuchMethodForwarders(myClasses);
+      }
     } on deprecated_InputError catch (e) {
       ticker.logMs("Got deprecated_InputError");
       handleInputError(e, isFullComponent: false);
@@ -355,6 +358,13 @@
           (LocatedMessage message) => new ExpressionStatement(new Throw(
               new StringLiteral(context.format(message, Severity.error)))))));
     }
+
+    // Clear libraries to avoid having 'the same' library added in both outline
+    // and body building. As loader.libraries is used in the incremental
+    // compiler that will causes problems (i.e. it cannot serialize because 2
+    // libraries has the same URI).
+    loader.libraries.clear();
+
     loader.libraries.add(library.library);
     library.build(loader.coreLibrary);
     return link(<Library>[library.library]);
diff --git a/pkg/front_end/lib/src/fasta/library_graph.dart b/pkg/front_end/lib/src/fasta/library_graph.dart
new file mode 100644
index 0000000..0d7ab6f
--- /dev/null
+++ b/pkg/front_end/lib/src/fasta/library_graph.dart
@@ -0,0 +1,37 @@
+// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library fasta.library_graph;
+
+import 'package:kernel/kernel.dart' show Library, LibraryDependency;
+
+import 'package:kernel/util/graph.dart' show Graph;
+
+class LibraryGraph implements Graph<Uri> {
+  final Map<Uri, Library> libraries;
+
+  LibraryGraph(this.libraries);
+
+  Iterable<Uri> get vertices => libraries.keys;
+
+  Iterable<Uri> neighborsOf(Uri vertex) sync* {
+    Library library = libraries[vertex];
+    if (library == null) {
+      throw "Library not found: $vertex";
+    }
+
+    // Imports and exports
+    for (LibraryDependency dependency in library.dependencies) {
+      Uri uri1 = dependency.targetLibrary.importUri;
+      Uri uri2 = dependency.targetLibrary.fileUri;
+      if (libraries.containsKey(uri1)) {
+        yield uri1;
+      } else if (uri2 != null) {
+        if (libraries.containsKey(uri2)) {
+          yield uri2;
+        }
+      }
+    }
+  }
+}
diff --git a/pkg/front_end/lib/src/fasta/parser/forwarding_listener.dart b/pkg/front_end/lib/src/fasta/parser/forwarding_listener.dart
index c5c0802..17fb305 100644
--- a/pkg/front_end/lib/src/fasta/parser/forwarding_listener.dart
+++ b/pkg/front_end/lib/src/fasta/parser/forwarding_listener.dart
@@ -66,8 +66,8 @@
   }
 
   @override
-  void beginClassDeclaration(Token beginToken, Token name) {
-    listener?.beginClassDeclaration(beginToken, name);
+  void beginClassDeclaration(Token begin, Token abstractToken, Token name) {
+    listener?.beginClassDeclaration(begin, abstractToken, name);
   }
 
   @override
@@ -299,8 +299,9 @@
   }
 
   @override
-  void beginNamedMixinApplication(Token beginToken, Token name) {
-    listener?.beginNamedMixinApplication(beginToken, name);
+  void beginNamedMixinApplication(
+      Token begin, Token abstractToken, Token name) {
+    listener?.beginNamedMixinApplication(begin, abstractToken, name);
   }
 
   @override
@@ -564,8 +565,10 @@
   }
 
   @override
-  void endFields(int count, Token beginToken, Token endToken) {
-    listener?.endFields(count, beginToken, endToken);
+  void endFields(Token staticToken, Token covariantToken, Token varFinalOrConst,
+      int count, Token beginToken, Token endToken) {
+    listener?.endFields(staticToken, covariantToken, varFinalOrConst, count,
+        beginToken, endToken);
   }
 
   @override
@@ -810,8 +813,10 @@
   }
 
   @override
-  void endTopLevelFields(int count, Token beginToken, Token endToken) {
-    listener?.endTopLevelFields(count, beginToken, endToken);
+  void endTopLevelFields(Token staticToken, Token covariantToken,
+      Token varFinalOrConst, int count, Token beginToken, Token endToken) {
+    listener?.endTopLevelFields(staticToken, covariantToken, varFinalOrConst,
+        count, beginToken, endToken);
   }
 
   @override
diff --git a/pkg/front_end/lib/src/fasta/parser/identifier_context.dart b/pkg/front_end/lib/src/fasta/parser/identifier_context.dart
index af0a4e2..d53576c 100644
--- a/pkg/front_end/lib/src/fasta/parser/identifier_context.dart
+++ b/pkg/front_end/lib/src/fasta/parser/identifier_context.dart
@@ -2,8 +2,16 @@
 // 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:front_end/src/fasta/fasta_codes.dart';
-import 'package:front_end/src/scanner/token.dart';
+import '../../scanner/token.dart' show Token;
+
+import '../fasta_codes.dart'
+    show Message, Template, templateExpectedIdentifier, templateExpectedType;
+
+import '../scanner/token_constants.dart' show IDENTIFIER_TOKEN;
+
+import 'identifier_context_impl.dart';
+
+import 'parser.dart' show Parser;
 
 /// Information about the parser state that is passed to the listener at the
 /// time an identifier is encountered. It is also used by the parser for error
@@ -15,42 +23,42 @@
 class IdentifierContext {
   /// Identifier is being declared as the name of an import prefix (i.e. `Foo`
   /// in `import "..." as Foo;`)
-  static const importPrefixDeclaration = const IdentifierContext._(
+  static const importPrefixDeclaration = const IdentifierContext(
       'importPrefixDeclaration',
       inDeclaration: true,
       isBuiltInIdentifierAllowed: false);
 
   /// Identifier is the start of a dotted name in a conditional import or
   /// export.
-  static const dottedName = const IdentifierContext._('dottedName');
+  static const dottedName = const IdentifierContext('dottedName');
 
   /// Identifier is part of a dotted name in a conditional import or export, but
   /// it's not the first identifier of the dotted name.
   static const dottedNameContinuation =
-      const IdentifierContext._('dottedNameContinuation', isContinuation: true);
+      const IdentifierContext('dottedNameContinuation', isContinuation: true);
 
   /// Identifier is one of the shown/hidden names in an import/export
   /// combinator.
-  static const combinator = const IdentifierContext._('combinator');
+  static const combinator = const IdentifierContext('combinator');
 
   /// Identifier is the start of a name in an annotation that precedes a
   /// declaration (i.e. it appears directly after an `@`).
   static const metadataReference =
-      const IdentifierContext._('metadataReference', isScopeReference: true);
+      const IdentifierContext('metadataReference', isScopeReference: true);
 
   /// Identifier is part of a name in an annotation that precedes a declaration,
   /// but it's not the first identifier in the name.
   static const metadataContinuation =
-      const IdentifierContext._('metadataContinuation', isContinuation: true);
+      const IdentifierContext('metadataContinuation', isContinuation: true);
 
   /// Identifier is part of a name in an annotation that precedes a declaration,
   /// but it appears after type parameters (e.g. `foo` in `@X<Y>.foo()`).
-  static const metadataContinuationAfterTypeArguments =
-      const IdentifierContext._('metadataContinuationAfterTypeArguments',
-          isContinuation: true);
+  static const metadataContinuationAfterTypeArguments = const IdentifierContext(
+      'metadataContinuationAfterTypeArguments',
+      isContinuation: true);
 
   /// Identifier is the name being declared by a typedef declaration.
-  static const typedefDeclaration = const IdentifierContext._(
+  static const typedefDeclaration = const IdentifierContext(
       'typedefDeclaration',
       inDeclaration: true,
       isBuiltInIdentifierAllowed: false);
@@ -58,99 +66,96 @@
   /// Identifier is a field initializer in a formal parameter list (i.e. it
   /// appears directly after `this.`).
   static const fieldInitializer =
-      const IdentifierContext._('fieldInitializer', isContinuation: true);
+      const IdentifierContext('fieldInitializer', isContinuation: true);
 
   /// Identifier is a formal parameter being declared as part of a function,
   /// method, or typedef declaration.
-  static const formalParameterDeclaration = const IdentifierContext._(
+  static const formalParameterDeclaration = const IdentifierContext(
       'formalParameterDeclaration',
       inDeclaration: true);
 
   /// Identifier is the start of a library name (e.g. `foo` in the directive
   /// 'library foo;`).
-  static const libraryName = const IdentifierContext._('libraryName',
-      inLibraryOrPartOfDeclaration: true);
+  static const libraryName = const LibraryIdentifierContext();
 
   /// Identifier is part of a library name, but it's not the first identifier in
   /// the name.
-  static const libraryNameContinuation = const IdentifierContext._(
-      'libraryNameContinuation',
-      inLibraryOrPartOfDeclaration: true,
-      isContinuation: true);
+  static const libraryNameContinuation =
+      const LibraryIdentifierContext.continuation();
 
   /// Identifier is the start of a library name referenced by a `part of`
   /// directive (e.g. `foo` in the directive `part of foo;`).
   static const partName =
-      const IdentifierContext._('partName', inLibraryOrPartOfDeclaration: true);
+      const IdentifierContext('partName', inLibraryOrPartOfDeclaration: true);
 
   /// Identifier is part of a library name referenced by a `part of` directive,
   /// but it's not the first identifier in the name.
-  static const partNameContinuation = const IdentifierContext._(
+  static const partNameContinuation = const IdentifierContext(
       'partNameContinuation',
       inLibraryOrPartOfDeclaration: true,
       isContinuation: true);
 
   /// Identifier is the type name being declared by an enum declaration.
-  static const enumDeclaration = const IdentifierContext._('enumDeclaration',
+  static const enumDeclaration = const IdentifierContext('enumDeclaration',
       inDeclaration: true, isBuiltInIdentifierAllowed: false);
 
   /// Identifier is an enumerated value name being declared by an enum
   /// declaration.
   static const enumValueDeclaration =
-      const IdentifierContext._('enumValueDeclaration', inDeclaration: true);
+      const IdentifierContext('enumValueDeclaration', inDeclaration: true);
 
   /// Identifier is the name being declared by a class declaration or a named
   /// mixin application, for example, `Foo` in `class Foo = X with Y;`.
-  static const classOrNamedMixinDeclaration = const IdentifierContext._(
+  static const classOrNamedMixinDeclaration = const IdentifierContext(
       'classOrNamedMixinDeclaration',
       inDeclaration: true,
       isBuiltInIdentifierAllowed: false);
 
   /// Identifier is the name of a type variable being declared (e.g. `Foo` in
   /// `class C<Foo extends num> {}`).
-  static const typeVariableDeclaration = const IdentifierContext._(
+  static const typeVariableDeclaration = const IdentifierContext(
       'typeVariableDeclaration',
       inDeclaration: true,
       isBuiltInIdentifierAllowed: false);
 
   /// Identifier is the start of a reference to a type that starts with prefix.
-  static const prefixedTypeReference = const IdentifierContext._(
+  static const prefixedTypeReference = const IdentifierContext(
       'prefixedTypeReference',
       isScopeReference: true,
       isBuiltInIdentifierAllowed: true,
       recoveryTemplate: templateExpectedType);
 
   /// Identifier is the start of a reference to a type declared elsewhere.
-  static const typeReference = const IdentifierContext._('typeReference',
+  static const typeReference = const IdentifierContext('typeReference',
       isScopeReference: true,
       isBuiltInIdentifierAllowed: false,
       recoveryTemplate: templateExpectedType);
 
   /// Identifier is part of a reference to a type declared elsewhere, but it's
   /// not the first identifier of the reference.
-  static const typeReferenceContinuation = const IdentifierContext._(
+  static const typeReferenceContinuation = const IdentifierContext(
       'typeReferenceContinuation',
       isContinuation: true,
       isBuiltInIdentifierAllowed: false);
 
   /// Identifier is a name being declared by a top level variable declaration.
-  static const topLevelVariableDeclaration = const IdentifierContext._(
+  static const topLevelVariableDeclaration = const IdentifierContext(
       'topLevelVariableDeclaration',
       inDeclaration: true);
 
   /// Identifier is a name being declared by a field declaration.
   static const fieldDeclaration =
-      const IdentifierContext._('fieldDeclaration', inDeclaration: true);
+      const IdentifierContext('fieldDeclaration', inDeclaration: true);
 
   /// Identifier is the name being declared by a top level function declaration.
-  static const topLevelFunctionDeclaration = const IdentifierContext._(
+  static const topLevelFunctionDeclaration = const IdentifierContext(
       'topLevelFunctionDeclaration',
       inDeclaration: true);
 
   /// Identifier is the start of the name being declared by a method
   /// declaration.
   static const methodDeclaration =
-      const IdentifierContext._('methodDeclaration', inDeclaration: true);
+      const IdentifierContext('methodDeclaration', inDeclaration: true);
 
   /// Identifier is part of the name being declared by a method declaration,
   /// but it's not the first identifier of the name.
@@ -158,7 +163,7 @@
   /// In valid Dart, this can only happen if the identifier is the name of a
   /// named constructor which is being declared, e.g. `foo` in
   /// `class C { C.foo(); }`.
-  static const methodDeclarationContinuation = const IdentifierContext._(
+  static const methodDeclarationContinuation = const IdentifierContext(
       'methodDeclarationContinuation',
       inDeclaration: true,
       isContinuation: true);
@@ -168,7 +173,7 @@
   /// TODO(paulberry,ahe): Does this ever occur in valid Dart, or does it only
   /// occur as part of error recovery?  If it's only as part of error recovery,
   /// perhaps we should just re-use methodDeclaration.
-  static const operatorName = const IdentifierContext._('operatorName');
+  static const operatorName = const IdentifierContext('operatorName');
 
   /// Identifier is the name being declared by a local function declaration that
   /// uses a "get" or "set" keyword.
@@ -176,22 +181,20 @@
   /// TODO(paulberry,ahe): Does this ever occur in valid Dart, or does it only
   /// occur as part of error recovery?  If it's only as part of error recovery,
   /// perhaps we should just re-use localFunctionDeclaration.
-  static const localAccessorDeclaration = const IdentifierContext._(
-      'localAccessorDeclaration',
-      inDeclaration: true);
+  static const localAccessorDeclaration =
+      const IdentifierContext('localAccessorDeclaration', inDeclaration: true);
 
   /// Identifier is the start of the name being declared by a local function
   /// declaration.
-  static const localFunctionDeclaration = const IdentifierContext._(
-      'localFunctionDeclaration',
-      inDeclaration: true);
+  static const localFunctionDeclaration =
+      const IdentifierContext('localFunctionDeclaration', inDeclaration: true);
 
   /// Identifier is part of the name being declared by a local function
   /// declaration, but it's not the first identifier of the name.
   ///
   /// TODO(paulberry,ahe): Does this ever occur in valid Dart, or does it only
   /// occur as part of error recovery?
-  static const localFunctionDeclarationContinuation = const IdentifierContext._(
+  static const localFunctionDeclarationContinuation = const IdentifierContext(
       'localFunctionDeclarationContinuation',
       inDeclaration: true,
       isContinuation: true);
@@ -201,39 +204,39 @@
   /// TODO(paulberry,ahe): What is an example of valid Dart code where this
   /// would occur?
   static const functionExpressionName =
-      const IdentifierContext._('functionExpressionName');
+      const IdentifierContext('functionExpressionName');
 
   /// Identifier is the start of a reference to a constructor declared
   /// elsewhere.
   static const constructorReference =
-      const IdentifierContext._('constructorReference', isScopeReference: true);
+      const IdentifierContext('constructorReference', isScopeReference: true);
 
   /// Identifier is part of a reference to a constructor declared elsewhere, but
   /// it's not the first identifier of the reference.
-  static const constructorReferenceContinuation = const IdentifierContext._(
+  static const constructorReferenceContinuation = const IdentifierContext(
       'constructorReferenceContinuation',
       isContinuation: true);
 
   /// Identifier is part of a reference to a constructor declared elsewhere, but
   /// it appears after type parameters (e.g. `foo` in `X<Y>.foo`).
   static const constructorReferenceContinuationAfterTypeArguments =
-      const IdentifierContext._(
+      const IdentifierContext(
           'constructorReferenceContinuationAfterTypeArguments',
           isContinuation: true);
 
   /// Identifier is the declaration of a label (i.e. it is followed by `:` and
   /// then a statement).
   static const labelDeclaration =
-      const IdentifierContext._('labelDeclaration', inDeclaration: true);
+      const IdentifierContext('labelDeclaration', inDeclaration: true);
 
   /// Identifier is the start of a reference occurring in a literal symbol (e.g.
   /// `foo` in `#foo`).
   static const literalSymbol =
-      const IdentifierContext._('literalSymbol', inSymbol: true);
+      const IdentifierContext('literalSymbol', inSymbol: true);
 
   /// Identifier is part of a reference occurring in a literal symbol, but it's
   /// not the first identifier of the reference (e.g. `foo` in `#prefix.foo`).
-  static const literalSymbolContinuation = const IdentifierContext._(
+  static const literalSymbolContinuation = const IdentifierContext(
       'literalSymbolContinuation',
       inSymbol: true,
       isContinuation: true);
@@ -241,26 +244,25 @@
   /// Identifier appears in an expression, and it does not immediately follow a
   /// `.`.
   static const expression =
-      const IdentifierContext._('expression', isScopeReference: true);
+      const IdentifierContext('expression', isScopeReference: true);
 
   /// Identifier appears in an expression, and it immediately follows a `.`.
   static const expressionContinuation =
-      const IdentifierContext._('expressionContinuation', isContinuation: true);
+      const IdentifierContext('expressionContinuation', isContinuation: true);
 
   /// Identifier is a reference to a named argument of a function or method
   /// invocation (e.g. `foo` in `f(foo: 0);`.
-  static const namedArgumentReference = const IdentifierContext._(
+  static const namedArgumentReference = const IdentifierContext(
       'namedArgumentReference',
       allowedInConstantExpression: true);
 
   /// Identifier is a name being declared by a local variable declaration.
-  static const localVariableDeclaration = const IdentifierContext._(
-      'localVariableDeclaration',
-      inDeclaration: true);
+  static const localVariableDeclaration =
+      const IdentifierContext('localVariableDeclaration', inDeclaration: true);
 
   /// Identifier is a reference to a label (e.g. `foo` in `break foo;`).
   /// Labels have their own scope.
-  static const labelReference = const IdentifierContext._('labelReference');
+  static const labelReference = const IdentifierContext('labelReference');
 
   final String _name;
 
@@ -290,7 +292,7 @@
 
   final Template<_MessageWithArgument<Token>> recoveryTemplate;
 
-  const IdentifierContext._(this._name,
+  const IdentifierContext(this._name,
       {this.inDeclaration: false,
       this.inLibraryOrPartOfDeclaration: false,
       this.inSymbol: false,
@@ -307,6 +309,16 @@
                 (inDeclaration || isContinuation || inSymbol);
 
   String toString() => _name;
+
+  /// Ensure that the next token is an identifier (or keyword which should be
+  /// treated as an identifier) and return that identifier.
+  /// Report errors as necessary via [parser].
+  Token ensureIdentifier(Token token, Parser parser) {
+    assert(token.next.kind != IDENTIFIER_TOKEN);
+    // TODO(danrubel): Implement this method for each identifier context
+    // such that they return a non-null value.
+    return null;
+  }
 }
 
 // TODO(ahe): Remove when analyzer supports generalized function syntax.
diff --git a/pkg/front_end/lib/src/fasta/parser/identifier_context_impl.dart b/pkg/front_end/lib/src/fasta/parser/identifier_context_impl.dart
new file mode 100644
index 0000000..54aeabe
--- /dev/null
+++ b/pkg/front_end/lib/src/fasta/parser/identifier_context_impl.dart
@@ -0,0 +1,73 @@
+// Copyright (c) 2018, 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 '../../scanner/token.dart' show SyntheticStringToken, Token, TokenType;
+
+import '../fasta_codes.dart' as fasta;
+
+import '../scanner/token_constants.dart' show IDENTIFIER_TOKEN;
+
+import 'identifier_context.dart';
+
+import 'parser.dart' show Parser;
+
+import 'util.dart' show optional;
+
+/// See [IdentifierContext].libraryName
+class LibraryIdentifierContext extends IdentifierContext {
+  const LibraryIdentifierContext()
+      : super('libraryName', inLibraryOrPartOfDeclaration: true);
+
+  const LibraryIdentifierContext.continuation()
+      : super('libraryNameContinuation',
+            inLibraryOrPartOfDeclaration: true, isContinuation: true);
+
+  @override
+  Token ensureIdentifier(Token token, Parser parser) {
+    Token identifier = token.next;
+    assert(identifier.kind != IDENTIFIER_TOKEN);
+    if (identifier.isIdentifier) {
+      Token next = identifier.next;
+      if (optional('.', next) ||
+          optional(';', next) ||
+          !looksLikeStartOfNextDeclaration(identifier)) {
+        return identifier;
+      }
+      // Although this is a valid library name, the library declaration
+      // is invalid and this looks like the start of the next declaration.
+      // In this situation, fall through to insert a synthetic library name.
+    }
+    if (optional('.', identifier) ||
+        optional(';', identifier) ||
+        looksLikeStartOfNextDeclaration(identifier)) {
+      identifier = parser.insertSyntheticIdentifier(token, this,
+          message: fasta.templateExpectedIdentifier.withArguments(identifier));
+    } else {
+      parser.reportRecoverableErrorWithToken(
+          identifier, fasta.templateExpectedIdentifier);
+      if (!identifier.isKeywordOrIdentifier) {
+        // When in doubt, consume the token to ensure we make progress
+        // but insert a synthetic identifier to satisfy listeners.
+        identifier = insertSyntheticIdentifierAfter(identifier, parser);
+      }
+    }
+    return identifier;
+  }
+
+  bool looksLikeStartOfNextDeclaration(Token token) =>
+      token.isTopLevelKeyword ||
+      optional('const', token) ||
+      optional('get', token) ||
+      optional('final', token) ||
+      optional('set', token) ||
+      optional('var', token) ||
+      optional('void', token);
+}
+
+Token insertSyntheticIdentifierAfter(Token token, Parser parser) {
+  Token identifier =
+      new SyntheticStringToken(TokenType.IDENTIFIER, '', token.charOffset, 0);
+  parser.rewriter.insertTokenAfter(token, identifier);
+  return identifier;
+}
diff --git a/pkg/front_end/lib/src/fasta/parser/listener.dart b/pkg/front_end/lib/src/fasta/parser/listener.dart
index 167775d..2b4d876 100644
--- a/pkg/front_end/lib/src/fasta/parser/listener.dart
+++ b/pkg/front_end/lib/src/fasta/parser/listener.dart
@@ -93,7 +93,7 @@
   /// Handle the beginning of a class declaration.
   /// [beginToken] may be the same as [name], or may point to modifiers
   /// (or extraneous modifiers in the case of recovery) preceding [name].
-  void beginClassDeclaration(Token beginToken, Token name) {}
+  void beginClassDeclaration(Token begin, Token abstractToken, Token name) {}
 
   /// Handle an extends clause in a class declaration. Substructures:
   /// - supertype (may be a mixin application)
@@ -257,7 +257,8 @@
   /// - Variable declarations (count times)
   ///
   /// Doesn't have a corresponding begin event, use [beginMember] instead.
-  void endFields(int count, Token beginToken, Token endToken) {
+  void endFields(Token staticToken, Token covariantToken, Token varFinalOrConst,
+      int count, Token beginToken, Token endToken) {
     logEvent("Fields");
   }
 
@@ -322,12 +323,15 @@
   }
 
   /// Handle the beginning of a local function declaration.  Substructures:
+  /// - Metadata
   /// - Type variables
   void beginLocalFunctionDeclaration(Token token) {}
 
   /// A function declaration.
   ///
   /// Substructures:
+  /// - Metadata
+  /// - Type variables
   /// - Return type
   /// - Name
   /// - Type variables
@@ -405,7 +409,8 @@
   /// Handle the beginning of a named mixin application.
   /// [beginToken] may be the same as [name], or may point to modifiers
   /// (or extraneous modifiers in the case of recovery) preceding [name].
-  void beginNamedMixinApplication(Token beginToken, Token name) {}
+  void beginNamedMixinApplication(
+      Token begin, Token abstractToken, Token name) {}
 
   /// Handle the end of a named mixin declaration.  Substructures:
   /// - metadata
@@ -806,14 +811,14 @@
 
   /// Handle the end of a top level variable declaration.  Substructures:
   /// - Metadata
-  /// - Modifiers
   /// - Type
   /// - Repeated [count] times:
   ///   - Variable name (identifier)
   ///   - Field initializer
   /// Doesn't have a corresponding begin event.
   /// Use [beginTopLevelMember] instead.
-  void endTopLevelFields(int count, Token beginToken, Token endToken) {
+  void endTopLevelFields(Token staticToken, Token covariantToken,
+      Token varFinalOrConst, int count, Token beginToken, Token endToken) {
     logEvent("TopLevelFields");
   }
 
@@ -915,6 +920,9 @@
     logEvent("FunctionExpression");
   }
 
+  /// Handle the start of a variables declaration.  Substructures:
+  /// - Metadata
+  /// - Type
   void beginVariablesDeclaration(Token token, Token varFinalOrConst) {}
 
   void endVariablesDeclaration(int count, Token endToken) {
diff --git a/pkg/front_end/lib/src/fasta/parser/parser.dart b/pkg/front_end/lib/src/fasta/parser/parser.dart
index d48c0a3..8ede4a9 100644
--- a/pkg/front_end/lib/src/fasta/parser/parser.dart
+++ b/pkg/front_end/lib/src/fasta/parser/parser.dart
@@ -29,7 +29,6 @@
 
 import '../scanner/token_constants.dart'
     show
-        CLOSE_CURLY_BRACKET_TOKEN,
         COMMA_TOKEN,
         DOUBLE_TOKEN,
         EOF_TOKEN,
@@ -1645,23 +1644,18 @@
       Token token, Token beforeAbstractToken) {
     token = token.next;
     listener.beginClassOrNamedMixinApplication(token);
-    Token begin = beforeAbstractToken?.next ?? token;
-    if (beforeAbstractToken != null) {
-      token = parseModifier(beforeAbstractToken).next;
-      listener.handleModifiers(1);
-    } else {
-      listener.handleModifiers(0);
-    }
+    Token abstractToken = beforeAbstractToken?.next;
+    Token begin = abstractToken ?? token;
     Token classKeyword = token;
     expect("class", token);
     Token name =
         ensureIdentifier(token, IdentifierContext.classOrNamedMixinDeclaration);
     token = parseTypeVariablesOpt(name);
     if (optional('=', token.next)) {
-      listener.beginNamedMixinApplication(begin, name);
+      listener.beginNamedMixinApplication(begin, abstractToken, name);
       return parseNamedMixinApplication(token, begin, classKeyword);
     } else {
-      listener.beginClassDeclaration(begin, name);
+      listener.beginClassDeclaration(begin, abstractToken, name);
       return parseClass(token, begin, classKeyword);
     }
   }
@@ -1857,10 +1851,14 @@
 
   Token parseStringPart(Token token) {
     token = token.next;
-    if (token.kind != STRING_TOKEN) {
-      token =
-          reportUnrecoverableErrorWithToken(token, fasta.templateExpectedString)
-              .next;
+    while (token.kind != STRING_TOKEN) {
+      if (token is ErrorToken) {
+        reportErrorToken(token, true);
+      } else {
+        token = reportUnrecoverableErrorWithToken(
+            token, fasta.templateExpectedString);
+      }
+      token = token.next;
     }
     listener.handleStringPart(token);
     return token;
@@ -1894,7 +1892,24 @@
   /// identifier in the given [context], create a synthetic identifier, report
   /// an error, and return the synthetic identifier.
   Token ensureIdentifier(Token token, IdentifierContext context) {
+    assert(context != null);
     Token next = token.next;
+    if (next.kind == IDENTIFIER_TOKEN) {
+      listener.handleIdentifier(next, context);
+      return next;
+    }
+    Token identifier = context.ensureIdentifier(token, this);
+    // TODO(danrubel): Once refactoring is complete,
+    // context.ensureIdentifier should never return null.
+    if (identifier != null) {
+      assert(identifier.isKeywordOrIdentifier);
+      listener.handleIdentifier(identifier, context);
+      return identifier;
+    }
+
+    // TODO(danrubel): Roll everything beyond this point into the
+    // ensureIdentifier methods in the various IdentifierContext subclasses.
+
     if (!next.isIdentifier) {
       if (optional("void", next)) {
         reportRecoverableError(next, fasta.messageInvalidVoid);
@@ -2050,9 +2065,6 @@
       followingValues = [';', 'hide', 'show', 'deferred', 'as'];
     } else if (context == IdentifierContext.labelDeclaration) {
       followingValues = [':'];
-    } else if (context == IdentifierContext.libraryName ||
-        context == IdentifierContext.libraryNameContinuation) {
-      followingValues = ['.', ';'];
     } else if (context == IdentifierContext.literalSymbol ||
         context == IdentifierContext.literalSymbolContinuation) {
       followingValues = ['.', ';'];
@@ -2285,18 +2297,8 @@
     {
       // Analyse the next tokens to see if they could be a type.
 
-      if (continuation ==
-          TypeContinuation.ExpressionStatementOrConstDeclaration) {
-        // This is a special case. The first token is `const` and we need to
-        // analyze the tokens following the const keyword.
-        assert(optional("const", token.next));
-        beforeBegin = token;
-        begin = beforeToken = token.next;
-        token = beforeToken.next;
-      } else {
-        beforeToken = beforeBegin = token;
-        token = begin = token.next;
-      }
+      beforeToken = beforeBegin = token;
+      token = begin = token.next;
 
       if (optional("void", token)) {
         // `void` is a type.
@@ -2412,17 +2414,6 @@
       return token;
     }
 
-    /// Returns true if [kind] could be the end of a variable declaration.
-    bool looksLikeVariableDeclarationEnd(int kind) {
-      return EQ_TOKEN == kind ||
-          SEMICOLON_TOKEN == kind ||
-          COMMA_TOKEN == kind ||
-          // Recovery: Return true for these additional invalid situations
-          // in which we assume a missing semicolon.
-          OPEN_CURLY_BRACKET_TOKEN == kind ||
-          CLOSE_CURLY_BRACKET_TOKEN == kind;
-    }
-
     /// Returns true if [token] could be the start of a function body.
     bool looksLikeFunctionBody(Token token) {
       return optional('{', token) ||
@@ -2494,119 +2485,6 @@
         }
         continue optional;
 
-      case TypeContinuation.ExpressionStatementOrDeclaration:
-        assert(begin.isIdentifier || identical(begin.stringValue, 'void'));
-        if (!inPlainSync && optional("await", begin)) {
-          return parseExpressionStatement(beforeBegin);
-        }
-
-        if (looksLikeType && token.isIdentifier) {
-          Token afterId = token.next;
-
-          int afterIdKind = afterId.kind;
-          if (looksLikeVariableDeclarationEnd(afterIdKind)) {
-            // We are looking at `type identifier` followed by
-            // `(',' | '=' | ';')`.
-
-            // TODO(ahe): Generate type events and call
-            // parseVariablesDeclarationRest instead.
-            return parseVariablesDeclaration(beforeBegin);
-          } else if (OPEN_PAREN_TOKEN == afterIdKind) {
-            // We are looking at `type identifier '('`.
-            if (looksLikeFunctionBody(afterId.endGroup.next)) {
-              // We are looking at `type identifier '(' ... ')'` followed
-              // `( '{' | '=>' | 'async' | 'sync' )`.
-
-              // Although it looks like there are no type variables here, they
-              // may get injected from a comment.
-              Token beforeFormals = parseTypeVariablesOpt(token);
-
-              listener.beginLocalFunctionDeclaration(begin);
-              if (voidToken != null) {
-                listener.handleVoidKeyword(voidToken);
-              } else {
-                commitType();
-              }
-              return parseNamedFunctionRest(
-                  beforeToken, begin, beforeFormals, false);
-            }
-          } else if (identical(afterIdKind, LT_TOKEN)) {
-            // We are looking at `type identifier '<'`.
-            Token beforeFormals = afterId.endGroup;
-            if (beforeFormals?.next != null &&
-                optional("(", beforeFormals.next)) {
-              if (looksLikeFunctionBody(beforeFormals.next.endGroup.next)) {
-                // We are looking at "type identifier '<' ... '>' '(' ... ')'"
-                // followed by '{', '=>', 'async', or 'sync'.
-                parseTypeVariablesOpt(token);
-                listener.beginLocalFunctionDeclaration(begin);
-                if (voidToken != null) {
-                  listener.handleVoidKeyword(voidToken);
-                } else {
-                  commitType();
-                }
-                return parseNamedFunctionRest(
-                    beforeToken, begin, beforeFormals, false);
-              }
-            }
-          }
-          // Fall-through to expression statement.
-        } else {
-          beforeToken = beforeBegin;
-          token = begin;
-          if (optional(':', token.next)) {
-            return parseLabeledStatement(beforeToken);
-          } else if (optional('(', token.next)) {
-            if (looksLikeFunctionBody(token.next.endGroup.next)) {
-              // We are looking at `identifier '(' ... ')'` followed by `'{'`,
-              // `'=>'`, `'async'`, or `'sync'`.
-
-              // Although it looks like there are no type variables here, they
-              // may get injected from a comment.
-              Token formals = parseTypeVariablesOpt(token);
-
-              listener.beginLocalFunctionDeclaration(token);
-              listener.handleNoType(token);
-              return parseNamedFunctionRest(beforeToken, begin, formals, false);
-            }
-          } else if (optional('<', token.next)) {
-            Token gt = token.next.endGroup;
-            if (gt?.next != null && optional("(", gt.next)) {
-              if (looksLikeFunctionBody(gt.next.endGroup.next)) {
-                // We are looking at `identifier '<' ... '>' '(' ... ')'`
-                // followed by `'{'`, `'=>'`, `'async'`, or `'sync'`.
-                parseTypeVariablesOpt(token);
-                listener.beginLocalFunctionDeclaration(token);
-                listener.handleNoType(token);
-                return parseNamedFunctionRest(beforeToken, begin, gt, false);
-              }
-            }
-            // Fall through to expression statement.
-          }
-        }
-        return parseExpressionStatement(beforeBegin);
-
-      case TypeContinuation.ExpressionStatementOrConstDeclaration:
-        Token identifier;
-        if (looksLikeType && token.isIdentifier) {
-          identifier = token;
-        } else if (begin.next.isIdentifier) {
-          identifier = begin.next;
-        }
-        if (identifier != null) {
-          if (looksLikeVariableDeclarationEnd(identifier.next.kind)) {
-            // We are looking at "const type identifier" followed by '=', ';',
-            // or ','.
-
-            // TODO(ahe): Generate type events and call
-            // parseVariablesDeclarationRest instead.
-            return parseVariablesDeclaration(beforeBegin);
-          }
-          // Fall-through to expression statement.
-        }
-
-        return parseExpressionStatement(beforeBegin);
-
       case TypeContinuation.SendOrFunctionLiteral:
         Token beforeName;
         Token name;
@@ -3068,29 +2946,15 @@
       Token beforeName,
       MemberKind memberKind,
       TypeContinuation typeContinuation) {
-    // TODO(danrubel): Consider passing modifiers via endTopLevelField
-    // rather than using handleModifier and handleModifiers.
-    int modifierCount = 0;
     if (externalToken != null) {
       reportRecoverableError(externalToken, fasta.messageExternalField);
     }
-    if (staticToken != null) {
-      listener.handleModifier(staticToken);
-      ++modifierCount;
-    } else if (covariantToken != null) {
+    if (covariantToken != null) {
       if (varFinalOrConst != null && optional('final', varFinalOrConst)) {
         reportRecoverableError(covariantToken, fasta.messageFinalAndCovariant);
         covariantToken = null;
-      } else {
-        listener.handleModifier(covariantToken);
-        ++modifierCount;
       }
     }
-    if (varFinalOrConst != null) {
-      listener.handleModifier(varFinalOrConst);
-      ++modifierCount;
-    }
-    listener.handleModifiers(modifierCount);
 
     bool isTopLevel = memberKind == MemberKind.TopLevelField;
 
@@ -3120,9 +2984,11 @@
     }
     token = ensureSemicolon(token);
     if (isTopLevel) {
-      listener.endTopLevelFields(fieldCount, beforeStart.next, token);
+      listener.endTopLevelFields(staticToken, covariantToken, varFinalOrConst,
+          fieldCount, beforeStart.next, token);
     } else {
-      listener.endFields(fieldCount, beforeStart.next, token);
+      listener.endFields(staticToken, covariantToken, varFinalOrConst,
+          fieldCount, beforeStart.next, token);
     }
     return token;
   }
@@ -3346,6 +3212,11 @@
         ? fasta.templateExpectedButGot.withArguments('{')
         : template.withArguments(token);
     reportRecoverableError(next, message);
+    return insertBlock(token);
+  }
+
+  Token insertBlock(Token token) {
+    Token next = token.next;
     Token replacement = link(
         new SyntheticBeginToken(TokenType.OPEN_CURLY_BRACKET, next.offset),
         new SyntheticToken(TokenType.CLOSE_CURLY_BRACKET, next.offset));
@@ -3990,7 +3861,7 @@
           beforeName.next, fasta.messageNamedFunctionExpression);
     }
     listener.endFunctionName(begin, token);
-    token = parseFormalParametersOpt(formals, MemberKind.Local);
+    token = parseFormalParametersRequiredOpt(formals, MemberKind.Local);
     token = parseInitializersOpt(token);
     token = parseAsyncOptBody(token, isFunctionExpression, false);
     if (isFunctionExpression) {
@@ -4278,15 +4149,25 @@
   }
 
   Token parseStatementX(Token token) {
-    final value = token.next.stringValue;
     if (identical(token.next.kind, IDENTIFIER_TOKEN)) {
-      return parseExpressionStatementOrDeclaration(token);
-    } else if (identical(value, '{')) {
+      if (optional(':', token.next.next)) {
+        return parseLabeledStatement(token);
+      }
+      return parseExpressionStatementOrDeclarationAfterModifiers(token, token);
+    }
+    final value = token.next.stringValue;
+    if (identical(value, '{')) {
       return parseBlock(token);
     } else if (identical(value, 'return')) {
       return parseReturnStatement(token);
     } else if (identical(value, 'var') || identical(value, 'final')) {
-      return parseVariablesDeclaration(token);
+      Token varOrFinal = token.next;
+      if (isModifier(varOrFinal.next)) {
+        return parseExpressionStatementOrDeclaration(token);
+      } else {
+        return parseExpressionStatementOrDeclarationAfterModifiers(
+            varOrFinal, token, varOrFinal);
+      }
     } else if (identical(value, 'if')) {
       return parseIfStatement(token);
     } else if (identical(value, 'await') && optional('for', token.next.next)) {
@@ -4298,8 +4179,6 @@
     } else if (identical(value, 'throw') && optional(';', token.next.next)) {
       // TODO(kasperl): Stop dealing with throw here.
       return parseRethrowStatement(token);
-    } else if (identical(value, 'void')) {
-      return parseExpressionStatementOrDeclaration(token);
     } else if (identical(value, 'while')) {
       return parseWhileStatement(token);
     } else if (identical(value, 'do')) {
@@ -4332,14 +4211,15 @@
       throw "Internal error: Unknown asyncState: '$asyncState'.";
     } else if (identical(value, 'const')) {
       return parseExpressionStatementOrConstDeclaration(token);
-    } else if (isModifier(token.next)) {
-      return parseVariablesDeclaration(token);
-    } else if (token.next.isIdentifier) {
-      return parseExpressionStatementOrDeclaration(token);
-    } else if (identical(value, '@')) {
-      return parseVariablesDeclaration(token);
-    } else {
+    } else if (!inPlainSync && identical(value, 'await')) {
       return parseExpressionStatement(token);
+    } else if (token.next.isIdentifier) {
+      if (optional(':', token.next.next)) {
+        return parseLabeledStatement(token);
+      }
+      return parseExpressionStatementOrDeclaration(token);
+    } else {
+      return parseExpressionStatementOrDeclaration(token);
     }
   }
 
@@ -4386,21 +4266,6 @@
     return token;
   }
 
-  Token parseExpressionStatementOrDeclaration(Token token) {
-    return parseType(token, TypeContinuation.ExpressionStatementOrDeclaration);
-  }
-
-  Token parseExpressionStatementOrConstDeclaration(Token token) {
-    Token next = token.next;
-    assert(optional('const', next));
-    if (next.next.isModifier) {
-      return parseVariablesDeclaration(token);
-    } else {
-      return parseType(
-          token, TypeContinuation.ExpressionStatementOrConstDeclaration);
-    }
-  }
-
   /// ```
   /// label:
   ///   identifier ':'
@@ -4424,9 +4289,7 @@
   /// ```
   Token parseLabeledStatement(Token token) {
     Token next = token.next;
-    // TODO(brianwilkerson): Enable this assert.
-    // `parseType` is allowing `void` to be a label.
-//    assert(next.isIdentifier);
+    assert(next.isIdentifier);
     assert(optional(':', next.next));
     int labelCount = 0;
     do {
@@ -5487,10 +5350,72 @@
     return token;
   }
 
-  /// Parse the metadata, modifiers, and type of a local declaration and return
-  /// the last token consumed. If a local variable declaration or local
-  /// function declaration is not found, then return the starting token.
-  Token parseLocalDeclarationStartOpt(final Token start) {
+  /// Returns true if [token] could be the start of a function declaration
+  /// without a return type.
+  bool looksLikeLocalFunction(Token token) {
+    if (token.isIdentifier) {
+      token = token.next;
+      if (optional('<', token)) {
+        Token closeBrace = token.endGroup;
+        if (closeBrace == null) {
+          return false;
+        }
+        token = closeBrace.next;
+      }
+      if (optional('(', token)) {
+        token = token.endGroup.next;
+        return optional('{', token) ||
+            optional('=>', token) ||
+            optional('async', token) ||
+            optional('sync', token);
+      } else if (optional('=>', token)) {
+        // Recovery: Looks like a local function that is missing parenthesis.
+        return true;
+      }
+    }
+    return false;
+  }
+
+  Token parseExpressionStatementOrConstDeclaration(final Token start) {
+    Token constToken = start.next;
+    assert(optional('const', constToken));
+    if (!isModifier(constToken.next)) {
+      TypeInfo typeInfo = computeType(constToken, false);
+      if (typeInfo == noTypeInfo) {
+        Token next = constToken.next;
+        if (!next.isIdentifier) {
+          return parseExpressionStatement(start);
+        }
+        next = next.next;
+        if (!(optional('=', next) ||
+            // Recovery
+            next.isKeywordOrIdentifier ||
+            optional(';', next) ||
+            optional(',', next) ||
+            optional('{', next))) {
+          return parseExpressionStatement(start);
+        }
+      }
+      return parseExpressionStatementOrDeclarationAfterModifiers(
+          constToken, start, constToken, typeInfo);
+    }
+    return parseExpressionStatementOrDeclaration(start);
+  }
+
+  /// This method has two modes based upon [onlyParseVariableDeclarationStart].
+  ///
+  /// If [onlyParseVariableDeclarationStart] is `false` (the default) then this
+  /// method will parse a local variable declaration, a local function,
+  /// or an expression statement, and then return the last consumed token.
+  ///
+  /// If [onlyParseVariableDeclarationStart] is `true` then this method
+  /// will only parse the metadata, modifiers, and type of a local variable
+  /// declaration if it exists. It is the responsibility of the caller to
+  /// call [parseVariablesDeclarationRest] to finish parsing the local variable
+  /// declaration. If a local variable declaration is not found then this
+  /// method will return [start].
+  Token parseExpressionStatementOrDeclaration(final Token start,
+      [bool onlyParseVariableDeclarationStart = false]) {
     Token token = start;
     Token next = token.next;
     if (optional('@', next)) {
@@ -5521,36 +5446,67 @@
       }
     }
 
-    Token beforeType = token;
-    TypeInfo typeInfo = computeType(beforeType, false);
-    token = typeInfo.skipType(beforeType);
-    next = token.next;
+    return parseExpressionStatementOrDeclarationAfterModifiers(
+        token, start, varFinalOrConst, null, onlyParseVariableDeclarationStart);
+  }
 
-    if (next.isIdentifier) {
-      if (optional('<', next.next) || optional('(', next.next)) {
-        // Found an expression or local function declaration.
-        // TODO(danrubel): Process local function declarations.
-        return start;
+  /// See [parseExpressionStatementOrDeclaration]
+  Token parseExpressionStatementOrDeclarationAfterModifiers(
+      final Token beforeType, final Token start,
+      [Token varFinalOrConst = null,
+      TypeInfo typeInfo,
+      bool onlyParseVariableDeclarationStart = false]) {
+    typeInfo ??= computeType(beforeType, false);
+    Token token = typeInfo.skipType(beforeType);
+    Token next = token.next;
+
+    if (!onlyParseVariableDeclarationStart && looksLikeLocalFunction(next)) {
+      // Parse a local function declaration.
+      if (varFinalOrConst != null) {
+        reportRecoverableErrorWithToken(
+            varFinalOrConst, fasta.templateExtraneousModifier);
       }
+      if (!optional('@', start.next)) {
+        listener.beginMetadataStar(start.next);
+        listener.endMetadataStar(0);
+      }
+      Token beforeFormals = parseTypeVariablesOpt(next);
+      listener.beginLocalFunctionDeclaration(start.next);
+      token = typeInfo.parseType(beforeType, this);
+      next = token.next;
+      return parseNamedFunctionRest(token, start.next, beforeFormals, false);
     }
 
     if (token == start) {
       // If no annotation, modifier, or type, and this is not a local function
-      // then return without consuming any tokens because this is not
-      // a local declaration.
-      return start;
+      // then this must be an expression statement.
+      if (onlyParseVariableDeclarationStart) {
+        return start;
+      } else {
+        return parseExpressionStatement(start);
+      }
+    }
+    if (next.type.isBuiltIn &&
+        beforeType == start &&
+        typeInfo.couldBeExpression) {
+      // Detect expressions such as identifier `as` identifier
+      // and treat those as expressions.
+      int kind = next.next.kind;
+      if (EQ_TOKEN != kind && SEMICOLON_TOKEN != kind && COMMA_TOKEN != kind) {
+        if (onlyParseVariableDeclarationStart) {
+          if (!optional('in', next.next)) {
+            return start;
+          }
+        } else {
+          return parseExpressionStatement(start);
+        }
+      }
     }
 
-    if (!optional('@', start.next)) {
-      listener.beginMetadataStar(start.next);
-      listener.endMetadataStar(0);
-    }
-    token = typeInfo.parseType(beforeType, this);
-    next = token.next;
-
-    // If there is not an identifier, then allow ensureIdentifier to report an
-    // error and don't report errors here.
     if (next.isIdentifier) {
+      // Only report these errors if there is an identifier. If there is not an
+      // identifier, then allow ensureIdentifier to report an error
+      // and don't report errors here.
       if (varFinalOrConst == null) {
         if (typeInfo == noTypeInfo) {
           reportRecoverableError(next, fasta.messageMissingConstFinalVarOrType);
@@ -5562,58 +5518,19 @@
       }
     }
 
+    if (!optional('@', start.next)) {
+      listener.beginMetadataStar(start.next);
+      listener.endMetadataStar(0);
+    }
+    token = typeInfo.parseType(beforeType, this);
+    next = token.next;
     listener.beginVariablesDeclaration(next, varFinalOrConst);
+    if (!onlyParseVariableDeclarationStart) {
+      token = parseVariablesDeclarationRest(token, true);
+    }
     return token;
   }
 
-  Token parseVariablesDeclaration(Token token) {
-    token = parseMetadataStar(token);
-    Token next = token.next;
-
-    Token varFinalOrConst;
-    if (isModifier(next)) {
-      if (optional('var', next)) {
-        varFinalOrConst = token = token.next;
-        next = token.next;
-      } else if (optional('final', next) || optional('const', next)) {
-        varFinalOrConst = token = token.next;
-        next = token.next;
-      }
-
-      if (isModifier(next)) {
-        // Recovery
-        ModifierRecoveryContext2 modifierContext =
-            new ModifierRecoveryContext2(this);
-        token = modifierContext.parseVariableDeclarationModifiers(token,
-            varFinalOrConst: varFinalOrConst);
-
-        varFinalOrConst = modifierContext.varFinalOrConst;
-        modifierContext = null;
-      }
-    }
-
-    TypeInfo typeInfo = computeType(token, false);
-    if (varFinalOrConst == null) {
-      if (typeInfo == noTypeInfo) {
-        // If there is no modifer, no type, and no identifier
-        // then let parseVariablesDeclarationMaybeSemicolonRest
-        // report a missing identifier rather than reporting two errors.
-        if (token.next.isIdentifier) {
-          reportRecoverableError(
-              token.next, fasta.messageMissingConstFinalVarOrType);
-        }
-      }
-    } else if (optional('var', varFinalOrConst)) {
-      if (typeInfo != noTypeInfo) {
-        reportRecoverableError(token.next, fasta.messageTypeAfterVar);
-      }
-    }
-    token = typeInfo.parseType(token, this);
-
-    listener.beginVariablesDeclaration(token.next, varFinalOrConst);
-    return parseVariablesDeclarationRest(token, true);
-  }
-
   Token parseVariablesDeclarationRest(Token token, bool endWithSemicolon) {
     int count = 1;
     token = parseOptionallyInitializedIdentifier(token);
@@ -5702,14 +5619,22 @@
       Token closeParen =
           semicolon.setNext(new SyntheticToken(TokenType.CLOSE_PAREN, offset));
       openParen.endGroup = closeParen;
-
       closeParen.setNext(leftParenthesis);
+      insertBlock(closeParen);
+
       leftParenthesis = openParen;
     }
     token = leftParenthesis;
 
-    token = parseLocalDeclarationStartOpt(token);
+    // Pass `true` so that the [parseExpressionStatementOrDeclaration] only
+    // parses the metadata, modifiers, and type of a local variable
+    // declaration if it exists. This enables capturing [beforeIdentifier]
+    // for later error reporting.
+    token = parseExpressionStatementOrDeclaration(token, true);
     Token beforeIdentifier = token;
+
+    // Parse the remainder of the local variable declaration
+    // or an expression if no local variable declaration was found.
     if (token != leftParenthesis) {
       token = parseVariablesDeclarationRest(token, false);
     } else if (optional(';', token.next)) {
@@ -5721,6 +5646,7 @@
     Token next = token.next;
     if (!optional('in', next)) {
       if (optional(':', next)) {
+        // Recovery
         reportRecoverableError(next, fasta.messageColonInPlaceOfIn);
         // Fall through to process `for ( ... in ... )`
       } else {
@@ -5858,12 +5784,19 @@
     listener.beginDoWhileStatementBody(doToken.next);
     LoopState savedLoopState = loopState;
     loopState = LoopState.InsideLoop;
-    token = parseStatement(doToken).next;
+    token = parseStatement(doToken);
     loopState = savedLoopState;
     listener.endDoWhileStatementBody(token);
-    Token whileToken = token;
-    expect('while', token);
-    token = parseParenthesizedExpression(token);
+    Token whileToken = token.next;
+    if (!optional('while', whileToken)) {
+      reportRecoverableError(
+          whileToken, fasta.templateExpectedButGot.withArguments('while'));
+      whileToken = rewriter
+          .insertTokenAfter(token,
+              new SyntheticKeywordToken(Keyword.WHILE, whileToken.charOffset))
+          .next;
+    }
+    token = parseParenthesizedExpression(whileToken);
     token = ensureSemicolon(token);
     listener.endDoWhileStatement(doToken, whileToken, token);
     return token;
diff --git a/pkg/front_end/lib/src/fasta/parser/type_continuation.dart b/pkg/front_end/lib/src/fasta/parser/type_continuation.dart
index 165353e..a825ae5 100644
--- a/pkg/front_end/lib/src/fasta/parser/type_continuation.dart
+++ b/pkg/front_end/lib/src/fasta/parser/type_continuation.dart
@@ -31,14 +31,6 @@
   /// should parse the following as a type unless it is followed by `=`.
   Typedef,
 
-  /// Indicates that what follows is either a local declaration or an
-  /// expression.
-  ExpressionStatementOrDeclaration,
-
-  /// Indicates that the keyword `const` has just been seen, and what follows
-  /// may be a local variable declaration or an expression.
-  ExpressionStatementOrConstDeclaration,
-
   /// Indicates that the parser is parsing an expression and has just seen an
   /// identifier.
   SendOrFunctionLiteral,
diff --git a/pkg/front_end/lib/src/fasta/parser/type_info.dart b/pkg/front_end/lib/src/fasta/parser/type_info.dart
index d282fcb..704ca9b9 100644
--- a/pkg/front_end/lib/src/fasta/parser/type_info.dart
+++ b/pkg/front_end/lib/src/fasta/parser/type_info.dart
@@ -33,6 +33,12 @@
 /// [TypeInfo] provides information that has collected by [computeType]
 /// about a particular type reference.
 abstract class TypeInfo {
+  /// Return `true` if the tokens comprising the type represented by the
+  /// receiver could be interpreted as a valid standalone expression.
+  /// For example, `A` or `A.b` could be interpreted as a type references
+  /// or as expressions, while `A<T>` only looks like a type reference.
+  bool get couldBeExpression;
+
   /// Call this function when it's known that the token after [token] is a type.
   /// This function will call the appropriate event methods on the [Parser]'s
   /// listener to handle the type. This may modify the token stream
@@ -197,6 +203,9 @@
   ComplexTypeInfo(Token beforeStart) : this.start = beforeStart.next;
 
   @override
+  bool get couldBeExpression => false;
+
+  @override
   Token parseType(Token token, Parser parser) {
     assert(identical(token.next, start));
     Listener listener = parser.listener;
diff --git a/pkg/front_end/lib/src/fasta/parser/type_info_impl.dart b/pkg/front_end/lib/src/fasta/parser/type_info_impl.dart
index 58b67bc..811672b 100644
--- a/pkg/front_end/lib/src/fasta/parser/type_info_impl.dart
+++ b/pkg/front_end/lib/src/fasta/parser/type_info_impl.dart
@@ -21,6 +21,9 @@
   const NoTypeInfo();
 
   @override
+  bool get couldBeExpression => false;
+
+  @override
   Token parseType(Token token, Parser parser) {
     parser.listener.handleNoType(token);
     return token;
@@ -37,6 +40,9 @@
   const PrefixedTypeInfo();
 
   @override
+  bool get couldBeExpression => true;
+
+  @override
   Token parseType(Token token, Parser parser) {
     Token start = token = token.next;
     assert(token.isKeywordOrIdentifier);
@@ -68,6 +74,9 @@
   const SimpleTypeArgumentsInfo();
 
   @override
+  bool get couldBeExpression => false;
+
+  @override
   Token parseType(Token token, Parser parser) {
     Token start = token = token.next;
     assert(token.isKeywordOrIdentifier);
@@ -100,6 +109,9 @@
   const SimpleTypeInfo();
 
   @override
+  bool get couldBeExpression => true;
+
+  @override
   Token parseType(Token token, Parser parser) {
     token = token.next;
     assert(token.isKeywordOrIdentifier);
@@ -121,6 +133,9 @@
   const VoidTypeInfo();
 
   @override
+  bool get couldBeExpression => false;
+
+  @override
   Token parseType(Token token, Parser parser) {
     token = token.next;
     parser.listener.handleVoidKeyword(token);
diff --git a/pkg/front_end/lib/src/fasta/source/diet_listener.dart b/pkg/front_end/lib/src/fasta/source/diet_listener.dart
index 3b901fb..445b4a5 100644
--- a/pkg/front_end/lib/src/fasta/source/diet_listener.dart
+++ b/pkg/front_end/lib/src/fasta/source/diet_listener.dart
@@ -219,7 +219,8 @@
   }
 
   @override
-  void endFields(int count, Token beginToken, Token endToken) {
+  void endFields(Token staticToken, Token covariantToken, Token varFinalOrConst,
+      int count, Token beginToken, Token endToken) {
     debugEvent("Fields");
     buildFields(count, beginToken, false);
   }
@@ -246,7 +247,8 @@
   }
 
   @override
-  void endTopLevelFields(int count, Token beginToken, Token endToken) {
+  void endTopLevelFields(Token staticToken, Token covariantToken,
+      Token varFinalOrConst, int count, Token beginToken, Token endToken) {
     debugEvent("TopLevelFields");
     buildFields(count, beginToken, true);
   }
diff --git a/pkg/front_end/lib/src/fasta/source/outline_builder.dart b/pkg/front_end/lib/src/fasta/source/outline_builder.dart
index 95f7e87..1637a9f 100644
--- a/pkg/front_end/lib/src/fasta/source/outline_builder.dart
+++ b/pkg/front_end/lib/src/fasta/source/outline_builder.dart
@@ -42,7 +42,9 @@
         Var,
         abstractMask,
         constMask,
-        externalMask;
+        covariantMask,
+        externalMask,
+        staticMask;
 
 import '../operator.dart'
     show
@@ -362,23 +364,26 @@
   }
 
   @override
-  void beginClassDeclaration(Token begin, Token name) {
+  void beginClassDeclaration(Token begin, Token abstractToken, Token name) {
     debugEvent("beginNamedMixinApplication");
     List<TypeVariableBuilder> typeVariables = pop();
     push(typeVariables ?? NullValue.TypeVariables);
     library.currentDeclaration
       ..name = name.lexeme
       ..typeVariables = typeVariables;
+    push(abstractToken != null ? abstractMask : 0);
   }
 
   @override
-  void beginNamedMixinApplication(Token beginToken, Token name) {
+  void beginNamedMixinApplication(
+      Token begin, Token abstractToken, Token name) {
     debugEvent("beginNamedMixinApplication");
     List<TypeVariableBuilder> typeVariables = pop();
     push(typeVariables ?? NullValue.TypeVariables);
     library.currentDeclaration
       ..name = name.lexeme
       ..typeVariables = typeVariables;
+    push(abstractToken != null ? abstractMask : 0);
   }
 
   @override
@@ -408,13 +413,13 @@
     List<TypeBuilder> interfaces = pop(NullValue.TypeBuilderList);
     int supertypeOffset = pop();
     TypeBuilder supertype = pop();
+    int modifiers = pop();
     List<TypeVariableBuilder> typeVariables = pop();
     int charOffset = pop();
     String name = pop();
     if (typeVariables != null && supertype is MixinApplicationBuilder) {
       supertype.typeVariables = typeVariables;
     }
-    int modifiers = Modifier.validate(pop());
     List<MetadataBuilder> metadata = pop();
 
     library.addClass(
@@ -713,10 +718,10 @@
     String documentationComment = getDocumentationComment(beginToken);
     List<TypeBuilder> interfaces = popIfNotNull(implementsKeyword);
     TypeBuilder mixinApplication = pop();
+    int modifiers = pop();
     List<TypeVariableBuilder> typeVariables = pop();
     int charOffset = pop();
     String name = pop();
-    int modifiers = Modifier.validate(pop());
     List<MetadataBuilder> metadata = pop();
     library.addNamedMixinApplication(documentationComment, metadata, name,
         typeVariables, modifiers, mixinApplication, interfaces, charOffset);
@@ -971,11 +976,14 @@
   }
 
   @override
-  void endTopLevelFields(int count, Token beginToken, Token endToken) {
+  void endTopLevelFields(Token staticToken, Token covariantToken,
+      Token varFinalOrConst, int count, Token beginToken, Token endToken) {
     debugEvent("endTopLevelFields");
     List fieldsInfo = popList(count * 4);
     TypeBuilder type = pop();
-    int modifiers = Modifier.validate(pop());
+    int modifiers = (staticToken != null ? staticMask : 0) |
+        (covariantToken != null ? covariantMask : 0) |
+        Modifier.validateVarFinalOrConst(varFinalOrConst?.lexeme);
     List<MetadataBuilder> metadata = pop();
     String documentationComment = getDocumentationComment(beginToken);
     library.addFields(
@@ -984,11 +992,14 @@
   }
 
   @override
-  void endFields(int count, Token beginToken, Token endToken) {
+  void endFields(Token staticToken, Token covariantToken, Token varFinalOrConst,
+      int count, Token beginToken, Token endToken) {
     debugEvent("Fields");
     List fieldsInfo = popList(count * 4);
     TypeBuilder type = pop();
-    int modifiers = Modifier.validate(pop());
+    int modifiers = (staticToken != null ? staticMask : 0) |
+        (covariantToken != null ? covariantMask : 0) |
+        Modifier.validateVarFinalOrConst(varFinalOrConst?.lexeme);
     List<MetadataBuilder> metadata = pop();
     String documentationComment = getDocumentationComment(beginToken);
     library.addFields(
diff --git a/pkg/front_end/lib/src/fasta/source/source_library_builder.dart b/pkg/front_end/lib/src/fasta/source/source_library_builder.dart
index 2980d2f..79e0664 100644
--- a/pkg/front_end/lib/src/fasta/source/source_library_builder.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_library_builder.dart
@@ -244,6 +244,9 @@
     const String prefix = "dart.library.";
     if (!dottedName.startsWith(prefix)) return "";
     dottedName = dottedName.substring(prefix.length);
+    String override =
+        loader.target.uriTranslator.environmentOverrideFor(dottedName);
+    if (override != null) return override;
 
     LibraryBuilder imported =
         loader.builders[new Uri(scheme: "dart", path: dottedName)];
diff --git a/pkg/front_end/lib/src/fasta/source/source_loader.dart b/pkg/front_end/lib/src/fasta/source/source_loader.dart
index 79c88ae..e15d994 100644
--- a/pkg/front_end/lib/src/fasta/source/source_loader.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_loader.dart
@@ -561,7 +561,9 @@
     Set<Library> libraries = new Set<Library>();
     List<Library> workList = <Library>[];
     builders.forEach((Uri uri, LibraryBuilder library) {
-      if (!library.isPart && !library.isPatch) {
+      if (!library.isPart &&
+          !library.isPatch &&
+          (library.loader == this || library.fileUri.scheme == "dart")) {
         if (libraries.add(library.target)) {
           workList.add(library.target);
         }
@@ -630,6 +632,15 @@
     ticker.logMs("Checked overrides");
   }
 
+  void addNoSuchMethodForwarders(List<SourceClassBuilder> sourceClasses) {
+    for (SourceClassBuilder builder in sourceClasses) {
+      if (builder.library.loader == this) {
+        builder.addNoSuchMethodForwarders(hierarchy);
+      }
+    }
+    ticker.logMs("Added noSuchMethod forwarders");
+  }
+
   void createTypeInferenceEngine() {
     typeInferenceEngine =
         new ShadowTypeInferenceEngine(instrumentation, target.strongMode);
@@ -800,4 +811,9 @@
           new InstrumentationValueLiteral(context.code.name));
     }
   }
+
+  void releaseAncillaryResources() {
+    hierarchy = null;
+    typeInferenceEngine = null;
+  }
 }
diff --git a/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart b/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart
index b43d976..b2e71fc 100644
--- a/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart
+++ b/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart
@@ -497,7 +497,7 @@
           actualType = getCalleeType(callMember, actualType);
           var conditional = new ConditionalExpression(nullCheck,
               new NullLiteral()..fileOffset = fileOffset, tearOff, actualType);
-          var let = new Let(t, conditional);
+          var let = new Let(t, conditional)..fileOffset = fileOffset;
           parent?.replaceChild(expression, let);
           expression = let;
         }
diff --git a/pkg/front_end/lib/src/fasta/uri_translator.dart b/pkg/front_end/lib/src/fasta/uri_translator.dart
index d2f32ff..135ad73 100644
--- a/pkg/front_end/lib/src/fasta/uri_translator.dart
+++ b/pkg/front_end/lib/src/fasta/uri_translator.dart
@@ -24,5 +24,12 @@
   ///
   /// Note: this only translates the URI, there is no guarantee that the
   /// corresponding file exists in the file system.
-  Uri translate(Uri uri);
+  ///
+  /// If [reportMessage] is true a message will be reported via
+  /// [CompilerContext.current].
+  Uri translate(Uri uri, [bool reportMessage = true]);
+
+  /// Return the value of `dart.library.name`, if it was overriden in the
+  /// library specification file, otherwise return null.
+  String environmentOverrideFor(String libraryName);
 }
diff --git a/pkg/front_end/lib/src/fasta/uri_translator_impl.dart b/pkg/front_end/lib/src/fasta/uri_translator_impl.dart
index 9d31710..5c52e50 100644
--- a/pkg/front_end/lib/src/fasta/uri_translator_impl.dart
+++ b/pkg/front_end/lib/src/fasta/uri_translator_impl.dart
@@ -37,12 +37,18 @@
   // TODO(sigmund, ahe): consider expanding this API to include an error
   // callback, so we can provide an error location when one is available. For
   // example, if the error occurs in an `import`.
-  Uri translate(Uri uri) {
+  Uri translate(Uri uri, [bool reportMessage = true]) {
     if (uri.scheme == "dart") return _translateDartUri(uri);
-    if (uri.scheme == "package") return _translatePackageUri(uri);
+    if (uri.scheme == "package") {
+      return _translatePackageUri(uri, reportMessage);
+    }
     return null;
   }
 
+  @override
+  String environmentOverrideFor(String libraryName) =>
+      dartLibraries.environmentOverrideFor(libraryName);
+
   /// Return the file URI that corresponds to the given `dart` URI, or `null`
   /// if there is no corresponding Dart library registered.
   Uri _translateDartUri(Uri uri) {
@@ -53,16 +59,21 @@
   /// Return the file URI that corresponds to the given `package` URI, or
   /// `null` if the `package` [uri] format is invalid, or there is no
   /// corresponding package registered.
-  Uri _translatePackageUri(Uri uri) {
+  Uri _translatePackageUri(Uri uri, bool reportMessage) {
     try {
       // TODO(sigmund): once we remove the `parse` API, we can ensure that
       // packages will never be null and get rid of `?` below.
-      return packages?.resolve(uri, notFound: _packageUriNotFound);
+      return packages?.resolve(uri,
+          notFound: reportMessage
+              ? _packageUriNotFound
+              : _packageUriNotFoundNoReport);
     } on ArgumentError catch (e) {
       // TODO(sigmund): catch a more precise error when
       // https://github.com/dart-lang/package_config/issues/40 is fixed.
-      CompilerContext.current.reportWithoutLocation(
-          templateInvalidPackageUri.withArguments(uri, '$e'), Severity.error);
+      if (reportMessage) {
+        CompilerContext.current.reportWithoutLocation(
+            templateInvalidPackageUri.withArguments(uri, '$e'), Severity.error);
+      }
       return null;
     }
   }
@@ -76,4 +87,8 @@
     // compiler.
     return null;
   }
+
+  static Uri _packageUriNotFoundNoReport(Uri uri) {
+    return null;
+  }
 }
diff --git a/pkg/front_end/pubspec.yaml b/pkg/front_end/pubspec.yaml
index c5970959..e4a0be5 100644
--- a/pkg/front_end/pubspec.yaml
+++ b/pkg/front_end/pubspec.yaml
@@ -9,7 +9,7 @@
   charcode: '^1.1.1'
   convert: '^2.0.1'
   crypto: '^2.0.2'
-  kernel: 0.3.0-alpha.10
+  kernel: 0.3.0-alpha.11
   meta: '^1.1.1'
   package_config: '^1.0.1'
   path: '^1.3.9'
diff --git a/pkg/front_end/test/fasta/parser/type_info_test.dart b/pkg/front_end/test/fasta/parser/type_info_test.dart
index 9486a3f..4bbac1c 100644
--- a/pkg/front_end/test/fasta/parser/type_info_test.dart
+++ b/pkg/front_end/test/fasta/parser/type_info_test.dart
@@ -22,6 +22,7 @@
     TypeInfo typeInfo = noTypeInfo;
     Token start = scanString('before ;').tokens;
     Token expectedEnd = start;
+    expect(typeInfo.couldBeExpression, isFalse);
     expect(typeInfo.skipType(start), expectedEnd);
 
     TypeInfoListener listener = new TypeInfoListener();
@@ -34,6 +35,7 @@
     Token start = scanString('before void ;').tokens;
     Token expectedEnd = start.next;
     expect(typeInfo.skipType(start), expectedEnd);
+    expect(typeInfo.couldBeExpression, isFalse);
 
     TypeInfoListener listener = new TypeInfoListener();
     expect(typeInfo.parseType(start, new Parser(listener)), expectedEnd);
@@ -45,6 +47,7 @@
     Token start = scanString('before C.a ;').tokens;
     Token expectedEnd = start.next.next.next;
     expect(typeInfo.skipType(start), expectedEnd);
+    expect(typeInfo.couldBeExpression, isTrue);
 
     TypeInfoListener listener = new TypeInfoListener();
     expect(typeInfo.parseType(start, new Parser(listener)), expectedEnd);
@@ -62,6 +65,7 @@
     Token start = scanString('before C ;').tokens;
     Token expectedEnd = start.next;
     expect(typeInfo.skipType(start), expectedEnd);
+    expect(typeInfo.couldBeExpression, isTrue);
 
     TypeInfoListener listener = new TypeInfoListener();
     expect(typeInfo.parseType(start, new Parser(listener)), expectedEnd);
@@ -77,6 +81,7 @@
     Token start = scanString('before C<T> ;').tokens;
     Token expectedEnd = start.next.next.next.next;
     expect(typeInfo.skipType(start), expectedEnd);
+    expect(typeInfo.couldBeExpression, isFalse);
 
     TypeInfoListener listener = new TypeInfoListener();
     expect(typeInfo.parseType(start, new Parser(listener)), expectedEnd);
@@ -590,6 +595,7 @@
     TypeInfoListener listener = new TypeInfoListener();
     Parser parser = new Parser(listener);
     expect(typeInfo.start, start.next, reason: source);
+    expect(typeInfo.couldBeExpression, isFalse);
     expectEnd(expectedAfter, typeInfo.skipType(start));
     expectEnd(expectedAfter, typeInfo.parseType(start, parser));
     if (expectedCalls != null) {
diff --git a/pkg/front_end/test/incremental_bulk_compiler_full.dart b/pkg/front_end/test/incremental_bulk_compiler_full.dart
new file mode 100644
index 0000000..6f4e489
--- /dev/null
+++ b/pkg/front_end/test/incremental_bulk_compiler_full.dart
@@ -0,0 +1,155 @@
+// Copyright (c) 2018, 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' show Future;
+
+import 'package:expect/expect.dart' show Expect;
+
+import 'package:front_end/src/api_prototype/compiler_options.dart'
+    show CompilerOptions;
+
+import 'package:front_end/src/api_prototype/incremental_kernel_generator.dart'
+    show IncrementalKernelGenerator;
+
+import 'package:front_end/src/compute_platform_binaries_location.dart'
+    show computePlatformBinariesLocation;
+
+import 'package:front_end/src/fasta/fasta_codes.dart' show LocatedMessage;
+
+import 'package:front_end/src/fasta/incremental_compiler.dart'
+    show IncrementalCompiler;
+
+import 'package:front_end/src/fasta/kernel/utils.dart' show serializeComponent;
+
+import 'package:front_end/src/fasta/severity.dart' show Severity;
+
+import 'package:kernel/kernel.dart' show Component, Library, Reference;
+
+import 'package:kernel/text/ast_to_text.dart'
+    show globalDebuggingNames, NameSystem;
+
+import 'package:testing/testing.dart'
+    show Chain, ChainContext, Result, Step, TestDescription, runMe;
+
+main([List<String> arguments = const []]) =>
+    runMe(arguments, createContext, "../testing.json");
+
+Future<Context> createContext(
+    Chain suite, Map<String, String> environment) async {
+  return new Context();
+}
+
+class Context extends ChainContext {
+  final List<Step> steps = const <Step>[
+    const RunTest(),
+  ];
+
+  // Override special handling of negative tests.
+  @override
+  Result processTestResult(
+      TestDescription description, Result result, bool last) {
+    return result;
+  }
+
+  IncrementalCompiler compiler;
+}
+
+CompilerOptions getOptions(bool strong) {
+  final Uri sdkRoot = computePlatformBinariesLocation();
+  var options = new CompilerOptions()
+    ..sdkRoot = sdkRoot
+    ..librariesSpecificationUri = Uri.base.resolve("sdk/lib/libraries.json")
+    ..onProblem = (LocatedMessage message, Severity severity, String formatted,
+        int line, int column) {
+      // ignore
+    }
+    ..strongMode = strong;
+  if (strong) {
+    options.sdkSummary =
+        computePlatformBinariesLocation().resolve("vm_platform_strong.dill");
+  } else {
+    options.sdkSummary =
+        computePlatformBinariesLocation().resolve("vm_platform.dill");
+  }
+  return options;
+}
+
+class RunTest extends Step<TestDescription, TestDescription, Context> {
+  const RunTest();
+
+  String get name => "run test";
+
+  Future<Result<TestDescription>> run(
+      TestDescription description, Context context) async {
+    Uri uri = description.uri;
+
+    // "One shot compile"
+    bool oneShotFailed = false;
+    List<int> oneShotSerialized;
+    try {
+      IncrementalCompiler compiler =
+          new IncrementalKernelGenerator(getOptions(true), uri);
+      oneShotSerialized = postProcess(await compiler.computeDelta());
+    } catch (e) {
+      oneShotFailed = true;
+    }
+
+    // Bulk
+    bool bulkFailed = false;
+    List<int> bulkSerialized;
+    try {
+      globalDebuggingNames = new NameSystem();
+      if (context.compiler == null) {
+        context.compiler =
+            new IncrementalKernelGenerator(getOptions(true), uri);
+      }
+      Component bulkCompiledComponent = await context.compiler
+          .computeDelta(entryPoint: uri, fullComponent: true);
+      bulkSerialized = postProcess(bulkCompiledComponent);
+    } catch (e) {
+      bulkFailed = true;
+    }
+
+    if (bulkFailed || oneShotFailed) {
+      if (bulkFailed != oneShotFailed) {
+        throw "Bulk-compiler failed: $bulkFailed; "
+            "one-shot failed: $oneShotFailed";
+      }
+    } else {
+      checkIsEqual(oneShotSerialized, bulkSerialized);
+    }
+
+    return pass(description);
+  }
+
+  List<int> postProcess(Component c) {
+    c.libraries.sort((l1, l2) {
+      return l1.fileUri.toString().compareTo(l2.fileUri.toString());
+    });
+
+    c.computeCanonicalNames();
+    for (Library library in c.libraries) {
+      library.additionalExports.sort((Reference r1, Reference r2) {
+        return r1.canonicalName
+            .toString()
+            .compareTo(r2.canonicalName.toString());
+      });
+    }
+
+    return serializeComponent(c);
+  }
+
+  void checkIsEqual(List<int> a, List<int> b) {
+    int length = a.length;
+    if (b.length < length) {
+      length = b.length;
+    }
+    for (int i = 0; i < length; ++i) {
+      if (a[i] != b[i]) {
+        Expect.fail("Data differs at byte ${i+1}.");
+      }
+    }
+    Expect.equals(a.length, b.length);
+  }
+}
diff --git a/pkg/front_end/test/incremental_bulk_compiler_smoke_test.dart b/pkg/front_end/test/incremental_bulk_compiler_smoke_test.dart
new file mode 100644
index 0000000..5399635
--- /dev/null
+++ b/pkg/front_end/test/incremental_bulk_compiler_smoke_test.dart
@@ -0,0 +1,17 @@
+// Copyright (c) 2018, 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' show Future;
+
+import 'package:testing/testing.dart' show Chain, runMe;
+
+import 'incremental_bulk_compiler_full.dart' show Context;
+
+main([List<String> arguments = const []]) =>
+    runMe(arguments, createContext, "../testing.json");
+
+Future<Context> createContext(
+    Chain suite, Map<String, String> environment) async {
+  return new Context();
+}
diff --git a/pkg/front_end/test/incremental_dart2js_load_from_dill_test.dart b/pkg/front_end/test/incremental_dart2js_load_from_dill_test.dart
new file mode 100644
index 0000000..50cedd6
--- /dev/null
+++ b/pkg/front_end/test/incremental_dart2js_load_from_dill_test.dart
@@ -0,0 +1,70 @@
+// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:io' show Directory, File;
+
+import 'package:expect/expect.dart' show Expect;
+
+import 'incremental_load_from_dill_test.dart'
+    show normalCompile, initializedCompile, checkIsEqual;
+
+Directory outDir;
+
+main() async {
+  outDir =
+      Directory.systemTemp.createTempSync("incremental_load_from_dill_test");
+  try {
+    await testDart2jsCompile();
+    print("----");
+  } finally {
+    outDir.deleteSync(recursive: true);
+  }
+}
+
+void testDart2jsCompile() async {
+  final Uri dart2jsUrl = Uri.base.resolve("pkg/compiler/bin/dart2js.dart");
+  final Uri invalidateUri = Uri.parse("package:compiler/src/filenames.dart");
+  Uri normalDill = outDir.uri.resolve("dart2js.full.dill");
+  Uri fullDillFromInitialized =
+      outDir.uri.resolve("dart2js.full_from_initialized.dill");
+  Uri nonexisting = outDir.uri.resolve("dart2js.nonexisting.dill");
+  Uri nonLoadable = outDir.uri.resolve("dart2js.nonloadable.dill");
+
+  // Compile dart2js without initializing from dill.
+  Stopwatch stopwatch = new Stopwatch()..start();
+  await normalCompile(dart2jsUrl, normalDill);
+  print("Normal compile took ${stopwatch.elapsedMilliseconds} ms");
+
+  // Create a file that cannot be (fully) loaded as a dill file.
+  List<int> corruptData = new File.fromUri(normalDill).readAsBytesSync();
+  for (int i = 10 * (corruptData.length ~/ 16);
+      i < 15 * (corruptData.length ~/ 16);
+      ++i) {
+    corruptData[i] = 42;
+  }
+  new File.fromUri(nonLoadable).writeAsBytesSync(corruptData);
+
+  // Compile dart2js, initializing from the just-compiled dill,
+  // a nonexisting file and a dill file that isn't valid.
+  for (List<Object> initializationData in [
+    [normalDill, true],
+    [nonexisting, false],
+    //  [nonLoadable, false] // disabled for now
+  ]) {
+    Uri initializeWith = initializationData[0];
+    bool initializeExpect = initializationData[1];
+    stopwatch.reset();
+    bool initializeResult = await initializedCompile(
+        dart2jsUrl, fullDillFromInitialized, initializeWith, [invalidateUri]);
+    Expect.equals(initializeExpect, initializeResult);
+    print("Initialized compile(s) from ${initializeWith.pathSegments.last} "
+        "took ${stopwatch.elapsedMilliseconds} ms");
+
+    // Compare the two files.
+    List<int> normalDillData = new File.fromUri(normalDill).readAsBytesSync();
+    List<int> initializedDillData =
+        new File.fromUri(fullDillFromInitialized).readAsBytesSync();
+    checkIsEqual(normalDillData, initializedDillData);
+  }
+}
diff --git a/pkg/front_end/test/incremental_load_from_dill_test.dart b/pkg/front_end/test/incremental_load_from_dill_test.dart
index 5ba4f3b..93bd46b 100644
--- a/pkg/front_end/test/incremental_load_from_dill_test.dart
+++ b/pkg/front_end/test/incremental_load_from_dill_test.dart
@@ -3,411 +3,294 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'dart:async' show Future;
+
 import 'dart:io' show Directory, File;
 
 import 'package:expect/expect.dart' show Expect;
+
+import 'package:front_end/src/base/processed_options.dart'
+    show ProcessedOptions;
+
+import 'package:front_end/src/fasta/compiler_context.dart' show CompilerContext;
+
 import 'package:front_end/src/api_prototype/compiler_options.dart'
     show CompilerOptions;
-import 'package:front_end/src/api_prototype/incremental_kernel_generator.dart'
-    show IncrementalKernelGenerator;
-import 'package:front_end/src/compute_platform_binaries_location.dart'
-    show computePlatformBinariesLocation;
-import 'package:front_end/src/fasta/incremental_compiler.dart'
-    show IncrementalCompiler;
-import 'package:front_end/src/fasta/kernel/utils.dart'
-    show writeComponentToFile, serializeComponent;
+
 import "package:front_end/src/api_prototype/memory_file_system.dart"
     show MemoryFileSystem;
-import 'package:kernel/kernel.dart'
-    show Class, EmptyStatement, Library, Procedure, Component;
+
+import 'package:front_end/src/compute_platform_binaries_location.dart'
+    show computePlatformBinariesLocation;
 
 import 'package:front_end/src/fasta/fasta_codes.dart' show LocatedMessage;
 
+import 'package:front_end/src/fasta/incremental_compiler.dart'
+    show IncrementalCompiler;
+
+import 'package:front_end/src/fasta/kernel/utils.dart'
+    show writeComponentToFile, serializeComponent;
+
 import 'package:front_end/src/fasta/severity.dart' show Severity;
 
-Directory outDir;
+import 'package:kernel/kernel.dart'
+    show Class, EmptyStatement, Library, Procedure, Component;
 
-main() async {
-  await runPassingTest(testDart2jsCompile);
-  await runPassingTest(testDisappearingLibrary);
-  await runPassingTest(testDeferredLibrary);
-  await runPassingTest(testStrongModeMixins);
-  await runFailingTest(
-      testStrongModeMixins2,
-      "testStrongModeMixins2_a.dart: Error: "
-      "The parameter 'value' of the method 'A::child' has type");
-  await runPassingTest(testInvalidateExportOfMain);
-  await runPassingTest(testInvalidatePart);
+import "package:testing/testing.dart"
+    show Chain, ChainContext, Result, Step, TestDescription, runMe;
+
+import "package:yaml/yaml.dart" show YamlMap, loadYamlNode;
+
+main([List<String> arguments = const []]) =>
+    runMe(arguments, createContext, "../testing.json");
+
+Future<Context> createContext(
+    Chain suite, Map<String, String> environment) async {
+  return new Context();
 }
 
-void runFailingTest(dynamic test, String expectContains) async {
-  try {
-    await runPassingTest(test);
-    throw "Expected this to fail.";
-  } catch (e) {
-    if (e.toString().contains(expectContains)) {
-      print("got expected error as this test is currently failing");
-    } else {
-      rethrow;
+class Context extends ChainContext {
+  final List<Step> steps = const <Step>[
+    const ReadTest(),
+    const RunCompilations(),
+  ];
+
+  @override
+  void cleanUp(TestDescription description, Result result) {
+    cleanupHelper?.outDir?.deleteSync(recursive: true);
+  }
+
+  TestData cleanupHelper;
+}
+
+class TestData {
+  YamlMap map;
+  Directory outDir;
+}
+
+class ReadTest extends Step<TestDescription, TestData, Context> {
+  const ReadTest();
+
+  String get name => "read test";
+
+  Future<Result<TestData>> run(
+      TestDescription description, Context context) async {
+    Uri uri = description.uri;
+    String contents = await new File.fromUri(uri).readAsString();
+    TestData data = new TestData();
+    data.map = loadYamlNode(contents, sourceUrl: uri);
+    data.outDir =
+        Directory.systemTemp.createTempSync("incremental_load_from_dill_test");
+    context.cleanupHelper = data;
+    return pass(data);
+  }
+}
+
+class RunCompilations extends Step<TestData, TestData, Context> {
+  const RunCompilations();
+
+  String get name => "run compilations";
+
+  Future<Result<TestData>> run(TestData data, Context context) async {
+    YamlMap map = data.map;
+    switch (map["type"]) {
+      case "simple":
+        await simpleTest(
+          map["sources"],
+          map["name"],
+          map["entry"],
+          map["strong"],
+          map["invalidate"],
+          data.outDir,
+        );
+        break;
+      case "newworld":
+        await newWorldTest(
+          map["strong"],
+          map["worlds"],
+        );
+        break;
+      default:
+        throw "Unexpected type: ${map['type']}";
     }
+    return pass(data);
   }
 }
 
-void runPassingTest(dynamic test) async {
-  outDir =
-      Directory.systemTemp.createTempSync("incremental_load_from_dill_test");
-  try {
-    await test();
-    print("----");
-  } finally {
-    outDir.deleteSync(recursive: true);
-  }
-}
-
-/// Invalidate a part file.
-void testInvalidatePart() async {
-  final Uri a = outDir.uri.resolve("testInvalidatePart_a.dart");
-  final Uri b = outDir.uri.resolve("testInvalidatePart_b.dart");
-  final Uri c = outDir.uri.resolve("testInvalidatePart_c.dart");
-  final Uri d = outDir.uri.resolve("testInvalidatePart_d.dart");
-
-  Uri output = outDir.uri.resolve("testInvalidatePart_full.dill");
-  Uri bootstrappedOutput =
-      outDir.uri.resolve("testInvalidatePart_full_from_bootstrap.dill");
-
-  new File.fromUri(a).writeAsStringSync("""
-    library a;
-    import 'testInvalidatePart_c.dart';
-    part 'testInvalidatePart_b.dart';
-    """);
-  new File.fromUri(b).writeAsStringSync("""
-    part of a;
-    b() { print("b"); }
-    """);
-  new File.fromUri(c).writeAsStringSync("""
-    library c;
-    part 'testInvalidatePart_d.dart';
-    """);
-  new File.fromUri(d).writeAsStringSync("""
-    part of c;
-    d() { print("d"); }
-    """);
-
-  Stopwatch stopwatch = new Stopwatch()..start();
-  await normalCompile(a, output, options: getOptions(true));
-  print("Normal compile took ${stopwatch.elapsedMilliseconds} ms");
-
-  stopwatch.reset();
-  bool bootstrapResult = await bootstrapCompile(
-      a, bootstrappedOutput, output, [b],
-      performSizeTests: true, options: getOptions(true));
-  print("Bootstrapped compile(s) from ${output.pathSegments.last} "
-      "took ${stopwatch.elapsedMilliseconds} ms");
-  Expect.isTrue(bootstrapResult);
-
-  // Compare the two files.
-  List<int> normalDillData = new File.fromUri(output).readAsBytesSync();
-  List<int> bootstrappedDillData =
-      new File.fromUri(bootstrappedOutput).readAsBytesSync();
-  checkBootstrappedIsEqual(normalDillData, bootstrappedDillData);
-}
-
-/// Invalidate the entrypoint which just exports another file (which has main).
-void testInvalidateExportOfMain() async {
-  final Uri a = outDir.uri.resolve("testInvalidateExportOfMain_a.dart");
-  final Uri b = outDir.uri.resolve("testInvalidateExportOfMain_b.dart");
-
-  Uri output = outDir.uri.resolve("testInvalidateExportOfMain_full.dill");
-  Uri bootstrappedOutput =
-      outDir.uri.resolve("testInvalidateExportOfMain_full_from_bootstrap.dill");
-
-  new File.fromUri(a).writeAsStringSync("""
-    export 'testInvalidateExportOfMain_b.dart';
-    """);
-  new File.fromUri(b).writeAsStringSync("""
-    main() { print("hello"); }
-    """);
-
-  Stopwatch stopwatch = new Stopwatch()..start();
-  await normalCompile(a, output, options: getOptions(true));
-  print("Normal compile took ${stopwatch.elapsedMilliseconds} ms");
-
-  stopwatch.reset();
-  bool bootstrapResult = await bootstrapCompile(
-      a, bootstrappedOutput, output, [a],
-      performSizeTests: true, options: getOptions(true));
-  print("Bootstrapped compile(s) from ${output.pathSegments.last} "
-      "took ${stopwatch.elapsedMilliseconds} ms");
-  Expect.isTrue(bootstrapResult);
-
-  // Compare the two files.
-  List<int> normalDillData = new File.fromUri(output).readAsBytesSync();
-  List<int> bootstrappedDillData =
-      new File.fromUri(bootstrappedOutput).readAsBytesSync();
-  checkBootstrappedIsEqual(normalDillData, bootstrappedDillData);
-}
-
-/// Compile in strong mode. Use mixins.
-void testStrongModeMixins2() async {
-  final Uri a = outDir.uri.resolve("testStrongModeMixins2_a.dart");
-  final Uri b = outDir.uri.resolve("testStrongModeMixins2_b.dart");
-
-  Uri output = outDir.uri.resolve("testStrongModeMixins2_full.dill");
-  Uri bootstrappedOutput =
-      outDir.uri.resolve("testStrongModeMixins2_full_from_bootstrap.dill");
-
-  new File.fromUri(a).writeAsStringSync("""
-    import 'testStrongModeMixins2_b.dart';
-    class A extends Object with B<C>, D<Object> {}
-    """);
-  new File.fromUri(b).writeAsStringSync("""
-    abstract class B<ChildType extends Object> extends Object {
-      ChildType get child => null;
-      set child(ChildType value) {}
+void simpleTest(
+    Map<String, String> sourceFiles,
+    String testName,
+    String entryPoint,
+    bool strong,
+    List<String> invalidate,
+    Directory outDir) async {
+  Uri entryPointUri;
+  Set<String> invalidateFilenames = invalidate?.toSet() ?? new Set<String>();
+  List<Uri> invalidateUris = <Uri>[];
+  Uri packagesUri;
+  for (String filename in sourceFiles.keys) {
+    Uri uri = outDir.uri.resolve(filename);
+    if (filename == entryPoint) entryPointUri = uri;
+    if (invalidateFilenames.contains(filename)) invalidateUris.add(uri);
+    String source = sourceFiles[filename];
+    if (filename == ".packages") {
+      source = substituteVariables(source, outDir.uri);
+      packagesUri = uri;
     }
+    new File.fromUri(uri).writeAsStringSync(source);
+  }
 
-    class C extends Object {}
-
-    abstract class D<T extends Object> extends Object with B<T> {}
-    """);
+  Uri output = outDir.uri.resolve("${testName}_full.dill");
+  Uri initializedOutput =
+      outDir.uri.resolve("${testName}_full_from_initialized.dill");
 
   Stopwatch stopwatch = new Stopwatch()..start();
-  await normalCompile(a, output, options: getOptions(true));
+  CompilerOptions options = getOptions(strong);
+  if (packagesUri != null) {
+    options.packagesFileUri = packagesUri;
+  }
+  await normalCompile(entryPointUri, output, options: options);
   print("Normal compile took ${stopwatch.elapsedMilliseconds} ms");
 
   stopwatch.reset();
-  bool bootstrapResult = await bootstrapCompile(
-      a, bootstrappedOutput, output, [a],
-      performSizeTests: true, options: getOptions(true));
-  print("Bootstrapped compile(s) from ${output.pathSegments.last} "
+  bool initializedResult = await initializedCompile(
+      entryPointUri, initializedOutput, output, invalidateUris,
+      options: getOptions(strong));
+  print("Initialized compile(s) from ${output.pathSegments.last} "
       "took ${stopwatch.elapsedMilliseconds} ms");
-  Expect.isTrue(bootstrapResult);
+  Expect.isTrue(initializedResult);
 
   // Compare the two files.
   List<int> normalDillData = new File.fromUri(output).readAsBytesSync();
-  List<int> bootstrappedDillData =
-      new File.fromUri(bootstrappedOutput).readAsBytesSync();
-  checkBootstrappedIsEqual(normalDillData, bootstrappedDillData);
+  List<int> initializedDillData =
+      new File.fromUri(initializedOutput).readAsBytesSync();
+  checkIsEqual(normalDillData, initializedDillData);
 }
 
-/// Compile in strong mode. Invalidate a file so type inferrer starts
-/// on something compiled from source and (potentially) goes into
-/// something loaded from dill.
-void testStrongModeMixins() async {
-  final Uri a = outDir.uri.resolve("testStrongModeMixins_a.dart");
-  final Uri b = outDir.uri.resolve("testStrongModeMixins_b.dart");
-
-  Uri output = outDir.uri.resolve("testStrongModeMixins_full.dill");
-  Uri bootstrappedOutput =
-      outDir.uri.resolve("testStrongModeMixins_full_from_bootstrap.dill");
-
-  new File.fromUri(a).writeAsStringSync("""
-    import 'testStrongModeMixins_b.dart';
-    class A extends Object with B<Object>, C {}
-    """);
-  new File.fromUri(b).writeAsStringSync("""
-    abstract class C<T extends Object> extends Object with B<T> {}
-    abstract class B<ChildType extends Object> extends Object {}
-    """);
-
-  Stopwatch stopwatch = new Stopwatch()..start();
-  await normalCompile(a, output, options: getOptions(true));
-  print("Normal compile took ${stopwatch.elapsedMilliseconds} ms");
-
-  stopwatch.reset();
-  bool bootstrapResult = await bootstrapCompile(
-      a, bootstrappedOutput, output, [a],
-      performSizeTests: true, options: getOptions(true));
-  print("Bootstrapped compile(s) from ${output.pathSegments.last} "
-      "took ${stopwatch.elapsedMilliseconds} ms");
-  Expect.isTrue(bootstrapResult);
-
-  // Compare the two files.
-  List<int> normalDillData = new File.fromUri(output).readAsBytesSync();
-  List<int> bootstrappedDillData =
-      new File.fromUri(bootstrappedOutput).readAsBytesSync();
-  checkBootstrappedIsEqual(normalDillData, bootstrappedDillData);
-}
-
-/// Test loading from a dill file with a deferred library.
-/// This is done by bootstrapping with no changes.
-void testDeferredLibrary() async {
-  final Uri input = outDir.uri.resolve("testDeferredLibrary_main.dart");
-  final Uri b = outDir.uri.resolve("testDeferredLibrary_b.dart");
-  Uri output = outDir.uri.resolve("testDeferredLibrary_full.dill");
-  Uri bootstrappedOutput =
-      outDir.uri.resolve("testDeferredLibrary_full_from_bootstrap.dill");
-  new File.fromUri(input).writeAsStringSync("""
-      import 'testDeferredLibrary_b.dart' deferred as b;
-
-      void main() {
-        print(b.foo());
-      }
-      """);
-  new File.fromUri(b).writeAsStringSync("""
-      String foo() => "hello from foo in b";
-      """);
-
-  Stopwatch stopwatch = new Stopwatch()..start();
-  await normalCompile(input, output);
-  print("Normal compile took ${stopwatch.elapsedMilliseconds} ms");
-
-  stopwatch.reset();
-  bool bootstrapResult = await bootstrapCompile(
-      input, bootstrappedOutput, output, [],
-      performSizeTests: false);
-  print("Bootstrapped compile(s) from ${output.pathSegments.last} "
-      "took ${stopwatch.elapsedMilliseconds} ms");
-  Expect.isTrue(bootstrapResult);
-
-  // Compare the two files.
-  List<int> normalDillData = new File.fromUri(output).readAsBytesSync();
-  List<int> bootstrappedDillData =
-      new File.fromUri(bootstrappedOutput).readAsBytesSync();
-  checkBootstrappedIsEqual(normalDillData, bootstrappedDillData);
-}
-
-void testDart2jsCompile() async {
-  final Uri dart2jsUrl = Uri.base.resolve("pkg/compiler/bin/dart2js.dart");
-  final Uri invalidateUri = Uri.parse("package:compiler/src/filenames.dart");
-  Uri normalDill = outDir.uri.resolve("dart2js.full.dill");
-  Uri bootstrappedDill = outDir.uri.resolve("dart2js.bootstrap.dill");
-  Uri nonexisting = outDir.uri.resolve("dart2js.nonexisting.dill");
-  Uri nonLoadable = outDir.uri.resolve("dart2js.nonloadable.dill");
-
-  // Compile dart2js without bootstrapping.
-  Stopwatch stopwatch = new Stopwatch()..start();
-  await normalCompile(dart2jsUrl, normalDill);
-  print("Normal compile took ${stopwatch.elapsedMilliseconds} ms");
-
-  // Create a file that cannot be (fully) loaded as a dill file.
-  List<int> corruptData = new File.fromUri(normalDill).readAsBytesSync();
-  for (int i = 10 * (corruptData.length ~/ 16);
-      i < 15 * (corruptData.length ~/ 16);
-      ++i) {
-    corruptData[i] = 42;
-  }
-  new File.fromUri(nonLoadable).writeAsBytesSync(corruptData);
-
-  // Compile dart2js, bootstrapping from the just-compiled dill,
-  // a nonexisting file and a dill file that isn't valid.
-  for (List<Object> bootstrapData in [
-    [normalDill, true],
-    [nonexisting, false],
-    //  [nonLoadable, false] // disabled for now
-  ]) {
-    Uri bootstrapWith = bootstrapData[0];
-    bool bootstrapExpect = bootstrapData[1];
-    stopwatch.reset();
-    bool bootstrapResult = await bootstrapCompile(
-        dart2jsUrl, bootstrappedDill, bootstrapWith, [invalidateUri]);
-    Expect.equals(bootstrapExpect, bootstrapResult);
-    print("Bootstrapped compile(s) from ${bootstrapWith.pathSegments.last} "
-        "took ${stopwatch.elapsedMilliseconds} ms");
-
-    // Compare the two files.
-    List<int> normalDillData = new File.fromUri(normalDill).readAsBytesSync();
-    List<int> bootstrappedDillData =
-        new File.fromUri(bootstrappedDill).readAsBytesSync();
-    checkBootstrappedIsEqual(normalDillData, bootstrappedDillData);
-  }
-}
-
-void checkBootstrappedIsEqual(
-    List<int> normalDillData, List<int> bootstrappedDillData) {
-  Expect.equals(normalDillData.length, bootstrappedDillData.length);
-  for (int i = 0; i < normalDillData.length; ++i) {
-    if (normalDillData[i] != bootstrappedDillData[i]) {
-      Expect.fail("Normally compiled and bootstrapped compile differs.");
-    }
-  }
-}
-
-/// Compile an application with n libraries, then
-/// compile "the same" application, but with m < n libraries,
-/// where (at least one) of the missing libraries are "in the middle"
-/// of the library list ---  bootstrapping from the dill with n libarries.
-void testDisappearingLibrary() async {
+void newWorldTest(bool strong, List worlds) async {
+  final Uri sdkRoot = computePlatformBinariesLocation();
   final Uri base = Uri.parse("org-dartlang-test:///");
   final Uri sdkSummary = base.resolve("vm_platform.dill");
-  final Uri main = base.resolve("main.dart");
-  final Uri b = base.resolve("b.dart");
-  final Uri bootstrap = base.resolve("bootstrapFrom.dill");
-  final List<int> sdkSummaryData = await new File.fromUri(
-          computePlatformBinariesLocation().resolve("vm_platform.dill"))
-      .readAsBytes();
+  final Uri initializeFrom = base.resolve("initializeFrom.dill");
+  Uri platformUri;
+  if (strong) {
+    platformUri = sdkRoot.resolve("vm_platform_strong.dill");
+  } else {
+    platformUri = sdkRoot.resolve("vm_platform.dill");
+  }
+  final List<int> sdkSummaryData =
+      await new File.fromUri(platformUri).readAsBytes();
 
-  List<int> libCount2;
-  {
+  List<int> newestWholeComponent;
+  for (var world in worlds) {
     MemoryFileSystem fs = new MemoryFileSystem(base);
     fs.entityForUri(sdkSummary).writeAsBytesSync(sdkSummaryData);
-
-    fs.entityForUri(main).writeAsStringSync("""
-      library mainLibrary;
-      import "b.dart" as b;
-
-      main() {
-        b.foo();
+    bool expectInitializeFromDill = false;
+    if (newestWholeComponent != null && newestWholeComponent.isNotEmpty) {
+      fs.entityForUri(initializeFrom).writeAsBytesSync(newestWholeComponent);
+      expectInitializeFromDill = true;
+    }
+    Map<String, String> sourceFiles = world["sources"];
+    Uri packagesUri;
+    for (String filename in sourceFiles.keys) {
+      String data = sourceFiles[filename] ?? "";
+      Uri uri = base.resolve(filename);
+      if (filename == ".packages") {
+        data = substituteVariables(data, base);
+        packagesUri = uri;
       }
-      """);
+      fs.entityForUri(uri).writeAsStringSync(data);
+    }
 
-    fs.entityForUri(b).writeAsStringSync("""
-      library bLibrary;
-
-      foo() {
-        print("hello from b.dart foo!");
-      }
-      """);
-
-    CompilerOptions options = getOptions(false);
+    CompilerOptions options = getOptions(strong);
     options.fileSystem = fs;
     options.sdkRoot = null;
     options.sdkSummary = sdkSummary;
-    IncrementalCompiler compiler =
-        new IncrementalKernelGenerator(options, main);
-    Stopwatch stopwatch = new Stopwatch()..start();
-    var component = await compiler.computeDelta();
-    throwOnEmptyMixinBodies(component);
-    print("Normal compile took ${stopwatch.elapsedMilliseconds} ms");
-    libCount2 = serializeComponent(component);
-    if (component.libraries.length != 2) {
-      throw "Expected 2 libraries, got ${component.libraries.length}";
+    if (packagesUri != null) {
+      options.packagesFileUri = packagesUri;
     }
-    if (component.libraries[0].fileUri != main) {
-      throw "Expected the first library to have uri $main but was "
-          "${component.libraries[0].fileUri}";
-    }
-  }
+    bool gotError = false;
+    List<String> formattedErrors = <String>[];
+    bool gotWarning = false;
+    List<String> formattedWarnings = <String>[];
 
-  {
-    MemoryFileSystem fs = new MemoryFileSystem(base);
-    fs.entityForUri(sdkSummary).writeAsBytesSync(sdkSummaryData);
-    fs.entityForUri(bootstrap).writeAsBytesSync(libCount2);
-    fs.entityForUri(b).writeAsStringSync("""
-      library bLibrary;
-
-      main() {
-        print("hello from b!");
+    options.onProblem = (LocatedMessage message, Severity severity,
+        String formatted, int line, int column) {
+      if (severity == Severity.error) {
+        gotError = true;
+        formattedErrors.add(formatted);
+      } else if (severity == Severity.warning) {
+        gotWarning = true;
+        formattedWarnings.add(formatted);
       }
-      """);
-    CompilerOptions options = getOptions(false);
-    options.fileSystem = fs;
-    options.sdkRoot = null;
-    options.sdkSummary = sdkSummary;
-    IncrementalCompiler compiler =
-        new IncrementalKernelGenerator(options, b, bootstrap);
-    compiler.invalidate(main);
-    compiler.invalidate(b);
+    };
+
+    Uri entry = base.resolve(world["entry"]);
+    TestIncrementalCompiler compiler =
+        new TestIncrementalCompiler(options, entry, initializeFrom);
+
+    if (world["invalidate"] != null) {
+      for (var filename in world["invalidate"]) {
+        compiler.invalidate(base.resolve(filename));
+      }
+    }
+
     Stopwatch stopwatch = new Stopwatch()..start();
-    var component = await compiler.computeDelta();
+    Component component = await compiler.computeDelta();
+    if (world["errors"] == true && !gotError) {
+      throw "Expected error, but didn't get any.";
+    } else if (world["errors"] != true && gotError) {
+      throw "Got unexpected error(s): $formattedErrors.";
+    }
+    if (world["warnings"] == true && !gotWarning) {
+      throw "Expected warning, but didn't get any.";
+    } else if (world["warnings"] != true && gotWarning) {
+      throw "Got unexpected warnings(s): $formattedWarnings.";
+    }
     throwOnEmptyMixinBodies(component);
-    print("Bootstrapped compile took ${stopwatch.elapsedMilliseconds} ms");
-    if (component.libraries.length != 1) {
-      throw "Expected 1 library, got ${component.libraries.length}";
+    print("Compile took ${stopwatch.elapsedMilliseconds} ms");
+    newestWholeComponent = serializeComponent(component);
+    if (component.libraries.length != world["expectedLibraryCount"]) {
+      throw "Expected ${world["expectedLibraryCount"]} libraries, "
+          "got ${component.libraries.length}";
+    }
+    if (component.libraries[0].importUri != entry) {
+      throw "Expected the first library to have uri $entry but was "
+          "${component.libraries[0].importUri}";
+    }
+    if (compiler.initializedFromDill != expectInitializeFromDill) {
+      throw "Expected that initializedFromDill would be "
+          "$expectInitializeFromDill but was ${compiler.initializedFromDill}";
+    }
+    if (world["invalidate"] != null) {
+      Expect.equals(world["invalidate"].length,
+          compiler.invalidatedImportUrisForTesting.length);
+      List expectedInvalidatedUri = world["expectedInvalidatedUri"];
+      if (expectedInvalidatedUri != null) {
+        Expect.setEquals(
+            expectedInvalidatedUri
+                .map((s) => Uri.parse(substituteVariables(s, base))),
+            compiler.invalidatedImportUrisForTesting);
+      }
+    } else {
+      Expect.isNull(compiler.invalidatedImportUrisForTesting);
+      Expect.isNull(world["expectedInvalidatedUri"]);
     }
   }
 }
 
+void checkIsEqual(List<int> a, List<int> b) {
+  int length = a.length;
+  if (b.length < length) {
+    length = b.length;
+  }
+  for (int i = 0; i < length; ++i) {
+    if (a[i] != b[i]) {
+      Expect.fail("Data differs at byte ${i+1}.");
+    }
+  }
+  Expect.equals(a.length, b.length);
+}
+
 CompilerOptions getOptions(bool strong) {
   final Uri sdkRoot = computePlatformBinariesLocation();
   var options = new CompilerOptions()
@@ -421,11 +304,9 @@
     }
     ..strongMode = strong;
   if (strong) {
-    options.sdkSummary =
-        computePlatformBinariesLocation().resolve("vm_platform_strong.dill");
+    options.sdkSummary = sdkRoot.resolve("vm_platform_strong.dill");
   } else {
-    options.sdkSummary =
-        computePlatformBinariesLocation().resolve("vm_platform.dill");
+    options.sdkSummary = sdkRoot.resolve("vm_platform.dill");
   }
   return options;
 }
@@ -433,13 +314,51 @@
 Future<bool> normalCompile(Uri input, Uri output,
     {CompilerOptions options}) async {
   options ??= getOptions(false);
-  IncrementalCompiler compiler = new IncrementalKernelGenerator(options, input);
-  var component = await compiler.computeDelta();
+  TestIncrementalCompiler compiler =
+      new TestIncrementalCompiler(options, input);
+  Component component = await compiler.computeDelta();
   throwOnEmptyMixinBodies(component);
   await writeComponentToFile(component, output);
   return compiler.initializedFromDill;
 }
 
+Future<bool> initializedCompile(
+    Uri input, Uri output, Uri initializeWith, List<Uri> invalidateUris,
+    {CompilerOptions options}) async {
+  options ??= getOptions(false);
+  TestIncrementalCompiler compiler =
+      new TestIncrementalCompiler(options, input, initializeWith);
+  for (Uri invalidateUri in invalidateUris) {
+    compiler.invalidate(invalidateUri);
+  }
+  var initializedComponent = await compiler.computeDelta();
+  throwOnEmptyMixinBodies(initializedComponent);
+  bool result = compiler.initializedFromDill;
+  await writeComponentToFile(initializedComponent, output);
+  for (Uri invalidateUri in invalidateUris) {
+    compiler.invalidate(invalidateUri);
+  }
+
+  var partialComponent = await compiler.computeDelta();
+  throwOnEmptyMixinBodies(partialComponent);
+  var emptyComponent = await compiler.computeDelta();
+  throwOnEmptyMixinBodies(emptyComponent);
+
+  var fullLibUris =
+      initializedComponent.libraries.map((lib) => lib.importUri).toList();
+  var partialLibUris =
+      partialComponent.libraries.map((lib) => lib.importUri).toList();
+  var emptyLibUris =
+      emptyComponent.libraries.map((lib) => lib.importUri).toList();
+
+  Expect.isTrue(fullLibUris.length > partialLibUris.length ||
+      partialLibUris.length == invalidateUris.length);
+  Expect.isTrue(partialLibUris.isNotEmpty || invalidateUris.isEmpty);
+  Expect.isTrue(emptyLibUris.isEmpty);
+
+  return result;
+}
+
 void throwOnEmptyMixinBodies(Component component) {
   int empty = countEmptyMixinBodies(component);
   if (empty != 0) {
@@ -452,7 +371,6 @@
   for (Library lib in component.libraries) {
     for (Class c in lib.classes) {
       if (c.isSyntheticMixinImplementation) {
-        // Assume mixin
         for (Procedure p in c.procedures) {
           if (p.function.body is EmptyStatement) {
             empty++;
@@ -464,40 +382,22 @@
   return empty;
 }
 
-Future<bool> bootstrapCompile(
-    Uri input, Uri output, Uri bootstrapWith, List<Uri> invalidateUris,
-    {bool performSizeTests: true, CompilerOptions options}) async {
-  options ??= getOptions(false);
-  IncrementalCompiler compiler =
-      new IncrementalKernelGenerator(options, input, bootstrapWith);
-  for (Uri invalidateUri in invalidateUris) {
-    compiler.invalidate(invalidateUri);
+String substituteVariables(String source, Uri base) {
+  return source.replaceAll(r"${outDirUri}", "${base}");
+}
+
+class TestIncrementalCompiler extends IncrementalCompiler {
+  List<Uri> invalidatedImportUrisForTesting;
+
+  TestIncrementalCompiler(CompilerOptions options, Uri entryPoint,
+      [Uri initializeFrom])
+      : super(
+            new CompilerContext(
+                new ProcessedOptions(options, false, [entryPoint])),
+            initializeFrom);
+
+  @override
+  void recordInvalidatedImportUrisForTesting(List<Uri> uris) {
+    invalidatedImportUrisForTesting = uris.isEmpty ? null : uris.toList();
   }
-  var bootstrappedComponent = await compiler.computeDelta();
-  throwOnEmptyMixinBodies(bootstrappedComponent);
-  bool result = compiler.initializedFromDill;
-  await writeComponentToFile(bootstrappedComponent, output);
-  for (Uri invalidateUri in invalidateUris) {
-    compiler.invalidate(invalidateUri);
-  }
-
-  var partialComponent = await compiler.computeDelta();
-  throwOnEmptyMixinBodies(partialComponent);
-  var emptyComponent = await compiler.computeDelta();
-  throwOnEmptyMixinBodies(emptyComponent);
-
-  var fullLibUris =
-      bootstrappedComponent.libraries.map((lib) => lib.importUri).toList();
-  var partialLibUris =
-      partialComponent.libraries.map((lib) => lib.importUri).toList();
-  var emptyLibUris =
-      emptyComponent.libraries.map((lib) => lib.importUri).toList();
-
-  if (performSizeTests) {
-    Expect.isTrue(fullLibUris.length > partialLibUris.length);
-    Expect.isTrue(partialLibUris.isNotEmpty);
-    Expect.isTrue(emptyLibUris.isEmpty);
-  }
-
-  return result;
 }
diff --git a/pkg/front_end/test/src/base/libraries_specification_test.dart b/pkg/front_end/test/src/base/libraries_specification_test.dart
index 4f9c8ed..60315e2 100644
--- a/pkg/front_end/test/src/base/libraries_specification_test.dart
+++ b/pkg/front_end/test/src/base/libraries_specification_test.dart
@@ -197,6 +197,43 @@
       expect(spec.specificationFor('none').libraryInfoFor('c').uri,
           Uri.parse('org-dartlang-test:///one/two/c/main.dart'));
     });
+
+    test('environment_overrides entry must be a map', () async {
+      var jsonString = '{"vm" : {"libraries": {"core": {"uri": "main.dart"}},'
+          '"environment_overrides": []}}';
+      expect(
+          () => LibrariesSpecification.parse(
+              Uri.parse('org-dartlang-test:///f.json'), jsonString),
+          throwsA((e) => e is LibrariesSpecificationException));
+    });
+
+    test('environment_overrides values must be bool', () async {
+      var jsonString = '{"vm" : {"libraries": {"core": {"uri": "main.dart"}},'
+          '"environment_overrides": {"core": 3}}}';
+      expect(
+          () => LibrariesSpecification.parse(
+              Uri.parse('org-dartlang-test:///f.json'), jsonString),
+          throwsA((e) => e is LibrariesSpecificationException));
+    });
+
+    test('environment_overrides correspond to existing libraries', () async {
+      var jsonString = '{"vm" : {"libraries": {"core": {"uri": "main.dart"}},'
+          '"environment_overrides": {"ui": false}}}';
+      expect(
+          () => LibrariesSpecification.parse(
+              Uri.parse('org-dartlang-test:///f.json'), jsonString),
+          throwsA((e) => e is LibrariesSpecificationException));
+    });
+
+    test('environment_overrides can be read from the public API', () async {
+      var jsonString = '{"vm" : {"libraries": {"core": {"uri": "main.dart"}},'
+          '"environment_overrides": {"core": false}}}';
+      var spec = LibrariesSpecification.parse(
+          Uri.parse('org-dartlang-test:///one/two/f.json'), jsonString);
+      expect(
+          spec.specificationFor('vm').environmentOverrideFor('core'), "false");
+      expect(spec.specificationFor('vm').environmentOverrideFor('ui'), null);
+    });
   });
 
   group('toJson', () {
@@ -226,6 +263,9 @@
                 "uri": "c/main.dart",
                 "patches": []
               }
+          },
+          "environment_overrides": {
+              "c" : false
           }
         }
       }
diff --git a/pkg/front_end/testcases/ast_builder.status b/pkg/front_end/testcases/ast_builder.status
index dc8b1a2..71b880f 100644
--- a/pkg/front_end/testcases/ast_builder.status
+++ b/pkg/front_end/testcases/ast_builder.status
@@ -6,6 +6,7 @@
 # generating analyzer ASTs and connecting up type inference information.
 annotation_top: Crash
 argument_mismatch: Fail
+bug32629: Fail
 dynamic_and_void: Fail
 illegal_named_function_expression: Crash
 illegal_named_function_expression_scope: Crash
diff --git a/pkg/front_end/testcases/bug32629.dart b/pkg/front_end/testcases/bug32629.dart
new file mode 100644
index 0000000..88610e0
--- /dev/null
+++ b/pkg/front_end/testcases/bug32629.dart
@@ -0,0 +1,19 @@
+// Copyright (c) 2018, 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.
+
+/*@testedFeatures=error*/
+
+class A {
+  dynamic call(dynamic a, dynamic b) {
+    return a;
+  }
+}
+
+typedef S Reducer<S>(S a, dynamic b);
+
+void foo<S>(Reducer<S> v) {}
+
+void main() {
+  foo<String>(new /*@error=InvalidAssignment*/ A());
+}
diff --git a/pkg/front_end/testcases/bug32629.dart.direct.expect b/pkg/front_end/testcases/bug32629.dart.direct.expect
new file mode 100644
index 0000000..1f4307c
--- /dev/null
+++ b/pkg/front_end/testcases/bug32629.dart.direct.expect
@@ -0,0 +1,17 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+typedef Reducer<S extends core::Object> = (S, dynamic) → S;
+class A extends core::Object {
+  synthetic constructor •() → void
+    : super core::Object::•()
+    ;
+  method call(dynamic a, dynamic b) → dynamic {
+    return a;
+  }
+}
+static method foo<S extends core::Object>((self::foo::S, dynamic) → self::foo::S v) → void {}
+static method main() → void {
+  self::foo<core::String>(new self::A::•());
+}
diff --git a/pkg/front_end/testcases/bug32629.dart.direct.transformed.expect b/pkg/front_end/testcases/bug32629.dart.direct.transformed.expect
new file mode 100644
index 0000000..1f4307c
--- /dev/null
+++ b/pkg/front_end/testcases/bug32629.dart.direct.transformed.expect
@@ -0,0 +1,17 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+typedef Reducer<S extends core::Object> = (S, dynamic) → S;
+class A extends core::Object {
+  synthetic constructor •() → void
+    : super core::Object::•()
+    ;
+  method call(dynamic a, dynamic b) → dynamic {
+    return a;
+  }
+}
+static method foo<S extends core::Object>((self::foo::S, dynamic) → self::foo::S v) → void {}
+static method main() → void {
+  self::foo<core::String>(new self::A::•());
+}
diff --git a/pkg/front_end/testcases/bug32629.dart.outline.expect b/pkg/front_end/testcases/bug32629.dart.outline.expect
new file mode 100644
index 0000000..d37f8be
--- /dev/null
+++ b/pkg/front_end/testcases/bug32629.dart.outline.expect
@@ -0,0 +1,15 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+typedef Reducer<S extends core::Object> = (S, dynamic) → S;
+class A extends core::Object {
+  synthetic constructor •() → void
+    ;
+  method call(dynamic a, dynamic b) → dynamic
+    ;
+}
+static method foo<S extends core::Object>((self::foo::S, dynamic) → self::foo::S v) → void
+  ;
+static method main() → void
+  ;
diff --git a/pkg/front_end/testcases/bug32629.dart.strong.expect b/pkg/front_end/testcases/bug32629.dart.strong.expect
new file mode 100644
index 0000000..0258b41
--- /dev/null
+++ b/pkg/front_end/testcases/bug32629.dart.strong.expect
@@ -0,0 +1,20 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+typedef Reducer<S extends core::Object> = (S, dynamic) → S;
+class A extends core::Object {
+  synthetic constructor •() → void
+    : super core::Object::•()
+    ;
+  method call(dynamic a, dynamic b) → dynamic {
+    return a;
+  }
+}
+static method foo<S extends core::Object>((self::foo::S, dynamic) → self::foo::S v) → void {}
+static method main() → void {
+  self::foo<core::String>(let final dynamic #t1 = let final self::A #t2 = new self::A::•() in #t2.==(null) ?{(dynamic, dynamic) → dynamic} null : #t2.{self::A::call} in let dynamic _ = null in invalid-expression "pkg/front_end/testcases/bug32629.dart:18:47: Error: A value of type '(dynamic, dynamic) \u8594 dynamic' can't be assigned to a variable of type '(dart.core::String, dynamic) \u8594 dart.core::String'.
+Try changing the type of the left hand side, or casting the right hand side to '(dart.core::String, dynamic) \u8594 dart.core::String'.
+  foo<String>(new /*@error=InvalidAssignment*/A());
+                                              ^");
+}
diff --git a/pkg/front_end/testcases/bug32629.dart.strong.transformed.expect b/pkg/front_end/testcases/bug32629.dart.strong.transformed.expect
new file mode 100644
index 0000000..b6f7b796
--- /dev/null
+++ b/pkg/front_end/testcases/bug32629.dart.strong.transformed.expect
@@ -0,0 +1,20 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+typedef Reducer<S extends core::Object> = (S, dynamic) → S;
+class A extends core::Object {
+  synthetic constructor •() → void
+    : super core::Object::•()
+    ;
+  method call(dynamic a, dynamic b) → dynamic {
+    return a;
+  }
+}
+static method foo<S extends core::Object>((self::foo::S, dynamic) → self::foo::S v) → void {}
+static method main() → void {
+  self::foo<core::String>(let final (dynamic, dynamic) → dynamic #t1 = let final self::A #t2 = new self::A::•() in #t2.==(null) ?{(dynamic, dynamic) → dynamic} null : #t2.{self::A::call} in let<BottomType> _ = null in invalid-expression "pkg/front_end/testcases/bug32629.dart:18:47: Error: A value of type '(dynamic, dynamic) \u8594 dynamic' can't be assigned to a variable of type '(dart.core::String, dynamic) \u8594 dart.core::String'.
+Try changing the type of the left hand side, or casting the right hand side to '(dart.core::String, dynamic) \u8594 dart.core::String'.
+  foo<String>(new /*@error=InvalidAssignment*/A());
+                                              ^");
+}
diff --git a/pkg/front_end/testcases/incremental_bulk_compiler_full.status b/pkg/front_end/testcases/incremental_bulk_compiler_full.status
new file mode 100644
index 0000000..acb1629
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_bulk_compiler_full.status
@@ -0,0 +1,3 @@
+# Copyright (c) 2018, 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.md file.
diff --git a/pkg/front_end/testcases/incremental_bulk_compiler_smoke.status b/pkg/front_end/testcases/incremental_bulk_compiler_smoke.status
new file mode 100644
index 0000000..acb1629
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_bulk_compiler_smoke.status
@@ -0,0 +1,3 @@
+# Copyright (c) 2018, 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.md file.
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/calculated_bounds_no_strongmode.yaml b/pkg/front_end/testcases/incremental_initialize_from_dill/calculated_bounds_no_strongmode.yaml
new file mode 100644
index 0000000..c6eb17a
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/calculated_bounds_no_strongmode.yaml
@@ -0,0 +1,22 @@
+# Copyright (c) 2018, 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.md file.
+
+# Test compiling in non-strong-mode from source and initializing from dill.
+# Make sure that any inference if done in the same way.
+
+type: simple
+name: testCalculatedBounds
+entry: testCalculatedBounds_a.dart
+strong: false
+invalidate:
+  - testCalculatedBounds_a.dart
+sources:
+  testCalculatedBounds_a.dart: |
+    import 'testCalculatedBounds_b.dart';
+
+    class A {
+      void foo(B cls) {}
+    }
+  testCalculatedBounds_b.dart: |
+    abstract class B<T extends String> {}
\ No newline at end of file
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/deferred_library.yaml b/pkg/front_end/testcases/incremental_initialize_from_dill/deferred_library.yaml
new file mode 100644
index 0000000..7ffc3f1
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/deferred_library.yaml
@@ -0,0 +1,21 @@
+# Copyright (c) 2018, 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.md file.
+
+# Test loading from a dill file with a deferred library.
+# This is done by initializing from dill and making no changes/invalidations.
+
+type: simple
+name: testDeferredLibrary
+entry: testDeferredLibrary_main.dart
+strong: false
+invalidate:
+sources:
+  testDeferredLibrary_main.dart: |
+    import 'testDeferredLibrary_b.dart' deferred as b;
+
+    void main() {
+      print(b.foo());
+    }
+  testDeferredLibrary_b.dart: |
+    String foo() => "hello from foo in b";
\ No newline at end of file
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/disappearing_library.yaml b/pkg/front_end/testcases/incremental_initialize_from_dill/disappearing_library.yaml
new file mode 100644
index 0000000..a00341b
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/disappearing_library.yaml
@@ -0,0 +1,40 @@
+# Copyright (c) 2018, 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.md file.
+
+# Compile an application with n libraries, then
+# compile "the same" application, but with m < n libraries,
+# where (at least one) of the missing libraries are "in the middle"
+# of the library list --- initializing from the dill with n libraries.
+
+type: newworld
+strong: false
+worlds:
+  - entry: main.dart
+    sources:
+      main.dart: |
+        library mainLibrary;
+        import "b.dart" as b;
+
+        main() {
+          b.foo();
+        }
+      b.dart: |
+        library bLibrary;
+
+        foo() {
+          print("hello from b.dart foo!");
+        }
+    expectedLibraryCount: 2
+  - entry: b.dart
+    invalidate:
+      - main.dart
+      - b.dart
+    sources:
+      b.dart: |
+        library bLibrary;
+
+        main() {
+          print("hello from b!");
+        }
+    expectedLibraryCount: 1
\ No newline at end of file
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/disappearing_package.yaml b/pkg/front_end/testcases/incremental_initialize_from_dill/disappearing_package.yaml
new file mode 100644
index 0000000..78c978d
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/disappearing_package.yaml
@@ -0,0 +1,36 @@
+# Copyright (c) 2018, 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.md file.
+
+# Compile an application with a package and use it.
+# Then remove the package from .packages and remove any use of it.
+# The package is still included in the dill file we initialize from,
+# but shouldn't cause trouble, nor be included in the output.
+
+type: newworld
+strong: false
+worlds:
+  - entry: main.dart
+    sources:
+      main.dart: |
+        import "package:dummy/b.dart";
+        main() {
+          print("hello");
+          b();
+        }
+      b.dart: |
+        b() {
+          print("b");
+        }
+      .packages: dummy:${outDirUri}
+    expectedLibraryCount: 2
+  - entry: main.dart
+    invalidate:
+      - main.dart
+    sources:
+      main.dart: |
+        main() {
+          print("hello");
+        }
+      .packages:
+    expectedLibraryCount: 1
\ No newline at end of file
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/invalidate_export_of_main.yaml b/pkg/front_end/testcases/incremental_initialize_from_dill/invalidate_export_of_main.yaml
new file mode 100644
index 0000000..5a11db2
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/invalidate_export_of_main.yaml
@@ -0,0 +1,17 @@
+# Copyright (c) 2018, 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.md file.
+
+# Invalidate the entrypoint which just exports another file (which has main).
+
+type: simple
+name: testInvalidateExportOfMain
+entry: testInvalidateExportOfMain_a.dart
+strong: true
+invalidate:
+  - testInvalidateExportOfMain_a.dart
+sources:
+  testInvalidateExportOfMain_a.dart: |
+    export 'testInvalidateExportOfMain_b.dart';
+  testInvalidateExportOfMain_b.dart: |
+    main() { print("hello"); }
\ No newline at end of file
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/invalidate_package_part.yaml b/pkg/front_end/testcases/incremental_initialize_from_dill/invalidate_package_part.yaml
new file mode 100644
index 0000000..e7811bd
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/invalidate_package_part.yaml
@@ -0,0 +1,63 @@
+# Copyright (c) 2018, 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.md file.
+
+# Test that invalidating a part of a package works with both file and package
+# URI.
+
+type: newworld
+strong: false
+worlds:
+  - entry: "package:dummy/main.dart"
+    sources:
+      main.dart: |
+        part "b.dart";
+        main() {
+          print("hello");
+          b();
+        }
+      b.dart: |
+        part of "main.dart";
+        b() {
+          print("b1");
+        }
+      .packages: dummy:${outDirUri}
+    expectedLibraryCount: 1
+  - entry: "package:dummy/main.dart"
+    invalidate:
+      - b.dart
+    expectedInvalidatedUri:
+      - "package:dummy/b.dart"
+    sources:
+      main.dart: |
+        part "b.dart";
+        main() {
+          print("hello");
+          b();
+        }
+      b.dart: |
+        part of "main.dart";
+        b() {
+          print("b2");
+        }
+      .packages: dummy:${outDirUri}
+    expectedLibraryCount: 1
+  - entry: "package:dummy/main.dart"
+    invalidate:
+      - "package:dummy/b.dart"
+    expectedInvalidatedUri:
+      - "package:dummy/b.dart"
+    sources:
+      main.dart: |
+        part "b.dart";
+        main() {
+          print("hello");
+          b();
+        }
+      b.dart: |
+        part of "main.dart";
+        b() {
+          print("b3");
+        }
+      .packages: dummy:${outDirUri}
+    expectedLibraryCount: 1
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/invalidate_package_part_as_file.yaml b/pkg/front_end/testcases/incremental_initialize_from_dill/invalidate_package_part_as_file.yaml
new file mode 100644
index 0000000..759ae72
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/invalidate_package_part_as_file.yaml
@@ -0,0 +1,24 @@
+# Copyright (c) 2018, 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.md file.
+
+# Test that invalidating a part of a package works with file URI.
+
+type: simple
+name: testDeferredLibrary
+entry: "package:dummy/main.dart"
+strong: false
+invalidate:
+sources:
+  main.dart: |
+    part "b.dart";
+    main() {
+      print("hello");
+      b();
+    }
+  b.dart: |
+    part of "main.dart";
+    b() {
+      print("b1");
+    }
+  .packages: dummy:${outDirUri}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/invalidate_package_part_as_package.yaml b/pkg/front_end/testcases/incremental_initialize_from_dill/invalidate_package_part_as_package.yaml
new file mode 100644
index 0000000..759ae72
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/invalidate_package_part_as_package.yaml
@@ -0,0 +1,24 @@
+# Copyright (c) 2018, 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.md file.
+
+# Test that invalidating a part of a package works with file URI.
+
+type: simple
+name: testDeferredLibrary
+entry: "package:dummy/main.dart"
+strong: false
+invalidate:
+sources:
+  main.dart: |
+    part "b.dart";
+    main() {
+      print("hello");
+      b();
+    }
+  b.dart: |
+    part of "main.dart";
+    b() {
+      print("b1");
+    }
+  .packages: dummy:${outDirUri}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/invalidate_part.yaml b/pkg/front_end/testcases/incremental_initialize_from_dill/invalidate_part.yaml
new file mode 100644
index 0000000..e3828ea
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/invalidate_part.yaml
@@ -0,0 +1,26 @@
+# Copyright (c) 2018, 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.md file.
+
+# Invalidate a part file.
+
+type: simple
+name: testInvalidatePart
+entry: testInvalidatePart_a.dart
+strong: true
+invalidate:
+  - testInvalidatePart_b.dart
+sources:
+  testInvalidatePart_a.dart: |
+    library a;
+    import 'testInvalidatePart_c.dart';
+    part 'testInvalidatePart_b.dart';
+  testInvalidatePart_b.dart: |
+    part of a;
+    b() { print("b"); }
+  testInvalidatePart_c.dart: |
+    library c;
+    part 'testInvalidatePart_d.dart';
+  testInvalidatePart_d.dart: |
+    part of c;
+    d() { print("d"); }
\ No newline at end of file
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/mixin_from_sdk.yaml b/pkg/front_end/testcases/incremental_initialize_from_dill/mixin_from_sdk.yaml
new file mode 100644
index 0000000..b86dbc7
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/mixin_from_sdk.yaml
@@ -0,0 +1,26 @@
+# Copyright (c) 2018, 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.md file.
+
+# Test using a mixin from the sdk and invalidationg it.
+# Make sure compiling from source and compiling where we initialize from dill
+# ends up including the same source code.
+
+type: simple
+name: testMixinFromSdk
+entry: testMixinFromSdk_a.dart
+strong: true
+invalidate:
+  - testMixinFromSdk_a.dart
+sources:
+  testMixinFromSdk_a.dart: |
+    import 'dart:collection';
+
+    class Foo extends Object with ListMixin<int> {
+      int length = 0;
+      int operator [](int index) {
+        return 42;
+      }
+
+      void operator []=(int index, int value) {}
+    }
\ No newline at end of file
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/remove_import_with_error.yaml b/pkg/front_end/testcases/incremental_initialize_from_dill/remove_import_with_error.yaml
new file mode 100644
index 0000000..fb8b511
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/remove_import_with_error.yaml
@@ -0,0 +1,67 @@
+# Copyright (c) 2018, 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.md file.
+
+# First compile a file (a) that imports a file (b) with errors in it.
+# Then change a to not import b, but leave b as-is, thus rightfully only
+# invalidating a. Compiling this should not result in any errors.
+
+type: newworld
+strong: false
+worlds:
+  - entry: main.dart
+    errors: true
+    warnings: false
+    sources:
+      main.dart: |
+        library mainLibrary;
+        import "b.dart" as b;
+
+        main() {
+          b.foo();
+        }
+      b.dart: |
+        library bLibrary;
+
+        foo() {
+          print("hello from b.dart foo!");
+          print(new C());
+        }
+
+        class I<T> {}
+
+        class A implements I<int> {}
+
+        class B implements I<String> {}
+
+        class C extends A implements B {}
+
+    expectedLibraryCount: 2
+  - entry: main.dart
+    invalidate:
+      - main.dart
+    errors: false
+    warnings: false
+    sources:
+      main.dart: |
+        library mainLibrary;
+
+        main() {
+          print("hello");
+        }
+      b.dart: |
+        library bLibrary;
+
+        foo() {
+          print("hello from b.dart foo!");
+          print(new C());
+        }
+
+        class I<T> {}
+
+        class A implements I<int> {}
+
+        class B implements I<String> {}
+
+        class C extends A implements B {}
+    expectedLibraryCount: 1
\ No newline at end of file
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/status.status b/pkg/front_end/testcases/incremental_initialize_from_dill/status.status
new file mode 100644
index 0000000..2dcebd2
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/status.status
@@ -0,0 +1,11 @@
+# Copyright (c) 2018, 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.md file.
+
+# Status file for the test suite ../test/incremental_load_from_dill_yaml_test.dart.
+
+calculated_bounds_no_strongmode: Crash
+invalidate_package_part: Crash
+invalidate_package_part_as_file: Crash
+invalidate_package_part_as_package: Crash
+strongmode_mixins_2: Crash
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/strongmode_mixins.yaml b/pkg/front_end/testcases/incremental_initialize_from_dill/strongmode_mixins.yaml
new file mode 100644
index 0000000..dbabbd3
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/strongmode_mixins.yaml
@@ -0,0 +1,21 @@
+# Copyright (c) 2018, 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.md file.
+
+# Compile in strong mode. Invalidate a file so type inferrer starts
+# on something compiled from source and (potentially) goes into
+# something loaded from dill.
+
+type: simple
+name: testStrongModeMixins
+entry: testStrongModeMixins_a.dart
+strong: true
+invalidate:
+  - testStrongModeMixins_a.dart
+sources:
+  testStrongModeMixins_a.dart: |
+    import 'testStrongModeMixins_b.dart';
+    class A extends Object with B<Object>, C {}
+  testStrongModeMixins_b.dart: |
+    abstract class C<T extends Object> extends Object with B<T> {}
+    abstract class B<ChildType extends Object> extends Object {}
\ No newline at end of file
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/strongmode_mixins_2.yaml b/pkg/front_end/testcases/incremental_initialize_from_dill/strongmode_mixins_2.yaml
new file mode 100644
index 0000000..4907a06
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/strongmode_mixins_2.yaml
@@ -0,0 +1,25 @@
+# Copyright (c) 2018, 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.md file.
+
+# Compile in strong mode. Use mixins.
+
+type: simple
+name: testStrongModeMixins2
+entry: testStrongModeMixins2_a.dart
+strong: true
+invalidate:
+  - testStrongModeMixins2_a.dart
+sources:
+  testStrongModeMixins2_a.dart: |
+    import 'testStrongModeMixins2_b.dart';
+    class A extends Object with B<C>, D<Object> {}
+  testStrongModeMixins2_b.dart: |
+    abstract class B<ChildType extends Object> extends Object {
+      ChildType get child => null;
+      set child(ChildType value) {}
+    }
+
+    class C extends Object {}
+
+    abstract class D<T extends Object> extends Object with B<T> {}
\ No newline at end of file
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/unused_file.yaml b/pkg/front_end/testcases/incremental_initialize_from_dill/unused_file.yaml
new file mode 100644
index 0000000..a2c5739
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/unused_file.yaml
@@ -0,0 +1,38 @@
+# Copyright (c) 2018, 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.md file.
+
+# Compile an application where we use an import, then recomile without changing
+# the import but where we no longer use it.
+# The imported file is still included in the dill file we initialize from,
+# but shouldn't cause trouble, nor be included in the output.
+
+type: newworld
+strong: false
+worlds:
+  - entry: main.dart
+    sources:
+      main.dart: |
+        import "b.dart";
+        main() {
+          print("hello");
+          b();
+        }
+      b.dart: |
+        b() {
+          print("b");
+        }
+    expectedLibraryCount: 2
+  - entry: main.dart
+    invalidate:
+      - main.dart
+    sources:
+      main.dart: |
+        main() {
+          print("hello");
+        }
+      b.dart: |
+        b() {
+          print("b");
+        }
+    expectedLibraryCount: 1
\ No newline at end of file
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/abstract_interface_nsm_inherited.dart b/pkg/front_end/testcases/no_such_method_forwarders/abstract_interface_nsm_inherited.dart
new file mode 100644
index 0000000..e5d16a8
--- /dev/null
+++ b/pkg/front_end/testcases/no_such_method_forwarders/abstract_interface_nsm_inherited.dart
@@ -0,0 +1,21 @@
+// Copyright (c) 2018, 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.
+
+// This test checks that a noSuchMethod forwarder is generated in classes that
+// inherit a user-defined noSuchMethod from their superclass and have not
+// implemented abstract methods from their interfaces.
+
+class A {
+  dynamic noSuchMethod(Invocation i) {
+    return null;
+  }
+}
+
+abstract class I {
+  void foo();
+}
+
+class B extends A implements I {}
+
+main() {}
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/abstract_interface_nsm_inherited.dart.direct.expect b/pkg/front_end/testcases/no_such_method_forwarders/abstract_interface_nsm_inherited.dart.direct.expect
new file mode 100644
index 0000000..77108c2
--- /dev/null
+++ b/pkg/front_end/testcases/no_such_method_forwarders/abstract_interface_nsm_inherited.dart.direct.expect
@@ -0,0 +1,25 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  synthetic constructor •() → void
+    : super core::Object::•()
+    ;
+  method noSuchMethod(core::Invocation i) → dynamic {
+    return null;
+  }
+}
+abstract class I extends core::Object {
+  synthetic constructor •() → void
+    : super core::Object::•()
+    ;
+  abstract method foo() → void;
+}
+class B extends self::A implements self::I {
+  synthetic constructor •() → void
+    : super self::A::•()
+    ;
+  abstract no-such-method-forwarder method foo() → void;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/abstract_interface_nsm_inherited.dart.direct.transformed.expect b/pkg/front_end/testcases/no_such_method_forwarders/abstract_interface_nsm_inherited.dart.direct.transformed.expect
new file mode 100644
index 0000000..77108c2
--- /dev/null
+++ b/pkg/front_end/testcases/no_such_method_forwarders/abstract_interface_nsm_inherited.dart.direct.transformed.expect
@@ -0,0 +1,25 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  synthetic constructor •() → void
+    : super core::Object::•()
+    ;
+  method noSuchMethod(core::Invocation i) → dynamic {
+    return null;
+  }
+}
+abstract class I extends core::Object {
+  synthetic constructor •() → void
+    : super core::Object::•()
+    ;
+  abstract method foo() → void;
+}
+class B extends self::A implements self::I {
+  synthetic constructor •() → void
+    : super self::A::•()
+    ;
+  abstract no-such-method-forwarder method foo() → void;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/abstract_interface_nsm_inherited.dart.outline.expect b/pkg/front_end/testcases/no_such_method_forwarders/abstract_interface_nsm_inherited.dart.outline.expect
new file mode 100644
index 0000000..f5898c4
--- /dev/null
+++ b/pkg/front_end/testcases/no_such_method_forwarders/abstract_interface_nsm_inherited.dart.outline.expect
@@ -0,0 +1,22 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  synthetic constructor •() → void
+    ;
+  method noSuchMethod(core::Invocation i) → dynamic
+    ;
+}
+abstract class I extends core::Object {
+  synthetic constructor •() → void
+    ;
+  abstract method foo() → void;
+}
+class B extends self::A implements self::I {
+  synthetic constructor •() → void
+    ;
+  abstract no-such-method-forwarder method foo() → void;
+}
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/abstract_interface_nsm_inherited.dart.strong.expect b/pkg/front_end/testcases/no_such_method_forwarders/abstract_interface_nsm_inherited.dart.strong.expect
new file mode 100644
index 0000000..77108c2
--- /dev/null
+++ b/pkg/front_end/testcases/no_such_method_forwarders/abstract_interface_nsm_inherited.dart.strong.expect
@@ -0,0 +1,25 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  synthetic constructor •() → void
+    : super core::Object::•()
+    ;
+  method noSuchMethod(core::Invocation i) → dynamic {
+    return null;
+  }
+}
+abstract class I extends core::Object {
+  synthetic constructor •() → void
+    : super core::Object::•()
+    ;
+  abstract method foo() → void;
+}
+class B extends self::A implements self::I {
+  synthetic constructor •() → void
+    : super self::A::•()
+    ;
+  abstract no-such-method-forwarder method foo() → void;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/abstract_interface_nsm_inherited.dart.strong.transformed.expect b/pkg/front_end/testcases/no_such_method_forwarders/abstract_interface_nsm_inherited.dart.strong.transformed.expect
new file mode 100644
index 0000000..77108c2
--- /dev/null
+++ b/pkg/front_end/testcases/no_such_method_forwarders/abstract_interface_nsm_inherited.dart.strong.transformed.expect
@@ -0,0 +1,25 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  synthetic constructor •() → void
+    : super core::Object::•()
+    ;
+  method noSuchMethod(core::Invocation i) → dynamic {
+    return null;
+  }
+}
+abstract class I extends core::Object {
+  synthetic constructor •() → void
+    : super core::Object::•()
+    ;
+  abstract method foo() → void;
+}
+class B extends self::A implements self::I {
+  synthetic constructor •() → void
+    : super self::A::•()
+    ;
+  abstract no-such-method-forwarder method foo() → void;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/interface_with_concrete.dart b/pkg/front_end/testcases/no_such_method_forwarders/interface_with_concrete.dart
new file mode 100644
index 0000000..a23c474
--- /dev/null
+++ b/pkg/front_end/testcases/no_such_method_forwarders/interface_with_concrete.dart
@@ -0,0 +1,21 @@
+// Copyright (c) 2018, 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.
+
+// This method checks that the noSuchMethod forwarder is generated in cases when
+// the class of the implemented interface has concrete methods.
+
+class A {
+  dynamic noSuchMethod(Invocation i) {
+    return null;
+  }
+}
+
+class I {
+  // This method is concrete.
+  void foo() {}
+}
+
+class B extends A implements I {}
+
+main() {}
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/interface_with_concrete.dart.direct.expect b/pkg/front_end/testcases/no_such_method_forwarders/interface_with_concrete.dart.direct.expect
new file mode 100644
index 0000000..6de0ac2
--- /dev/null
+++ b/pkg/front_end/testcases/no_such_method_forwarders/interface_with_concrete.dart.direct.expect
@@ -0,0 +1,25 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  synthetic constructor •() → void
+    : super core::Object::•()
+    ;
+  method noSuchMethod(core::Invocation i) → dynamic {
+    return null;
+  }
+}
+class I extends core::Object {
+  synthetic constructor •() → void
+    : super core::Object::•()
+    ;
+  method foo() → void {}
+}
+class B extends self::A implements self::I {
+  synthetic constructor •() → void
+    : super self::A::•()
+    ;
+  abstract no-such-method-forwarder method foo() → void;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/interface_with_concrete.dart.direct.transformed.expect b/pkg/front_end/testcases/no_such_method_forwarders/interface_with_concrete.dart.direct.transformed.expect
new file mode 100644
index 0000000..6de0ac2
--- /dev/null
+++ b/pkg/front_end/testcases/no_such_method_forwarders/interface_with_concrete.dart.direct.transformed.expect
@@ -0,0 +1,25 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  synthetic constructor •() → void
+    : super core::Object::•()
+    ;
+  method noSuchMethod(core::Invocation i) → dynamic {
+    return null;
+  }
+}
+class I extends core::Object {
+  synthetic constructor •() → void
+    : super core::Object::•()
+    ;
+  method foo() → void {}
+}
+class B extends self::A implements self::I {
+  synthetic constructor •() → void
+    : super self::A::•()
+    ;
+  abstract no-such-method-forwarder method foo() → void;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/interface_with_concrete.dart.outline.expect b/pkg/front_end/testcases/no_such_method_forwarders/interface_with_concrete.dart.outline.expect
new file mode 100644
index 0000000..a299436
--- /dev/null
+++ b/pkg/front_end/testcases/no_such_method_forwarders/interface_with_concrete.dart.outline.expect
@@ -0,0 +1,23 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  synthetic constructor •() → void
+    ;
+  method noSuchMethod(core::Invocation i) → dynamic
+    ;
+}
+class I extends core::Object {
+  synthetic constructor •() → void
+    ;
+  method foo() → void
+    ;
+}
+class B extends self::A implements self::I {
+  synthetic constructor •() → void
+    ;
+  abstract no-such-method-forwarder method foo() → void;
+}
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/interface_with_concrete.dart.strong.expect b/pkg/front_end/testcases/no_such_method_forwarders/interface_with_concrete.dart.strong.expect
new file mode 100644
index 0000000..6de0ac2
--- /dev/null
+++ b/pkg/front_end/testcases/no_such_method_forwarders/interface_with_concrete.dart.strong.expect
@@ -0,0 +1,25 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  synthetic constructor •() → void
+    : super core::Object::•()
+    ;
+  method noSuchMethod(core::Invocation i) → dynamic {
+    return null;
+  }
+}
+class I extends core::Object {
+  synthetic constructor •() → void
+    : super core::Object::•()
+    ;
+  method foo() → void {}
+}
+class B extends self::A implements self::I {
+  synthetic constructor •() → void
+    : super self::A::•()
+    ;
+  abstract no-such-method-forwarder method foo() → void;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/interface_with_concrete.dart.strong.transformed.expect b/pkg/front_end/testcases/no_such_method_forwarders/interface_with_concrete.dart.strong.transformed.expect
new file mode 100644
index 0000000..6de0ac2
--- /dev/null
+++ b/pkg/front_end/testcases/no_such_method_forwarders/interface_with_concrete.dart.strong.transformed.expect
@@ -0,0 +1,25 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  synthetic constructor •() → void
+    : super core::Object::•()
+    ;
+  method noSuchMethod(core::Invocation i) → dynamic {
+    return null;
+  }
+}
+class I extends core::Object {
+  synthetic constructor •() → void
+    : super core::Object::•()
+    ;
+  method foo() → void {}
+}
+class B extends self::A implements self::I {
+  synthetic constructor •() → void
+    : super self::A::•()
+    ;
+  abstract no-such-method-forwarder method foo() → void;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/interface_with_nsm.dart b/pkg/front_end/testcases/no_such_method_forwarders/interface_with_nsm.dart
new file mode 100644
index 0000000..af56a39
--- /dev/null
+++ b/pkg/front_end/testcases/no_such_method_forwarders/interface_with_nsm.dart
@@ -0,0 +1,26 @@
+// Copyright (c) 2018, 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.
+
+// This test checks that if an interface have a user-defined noSuchMethod, its
+// implementations that have their own user-defined noSuchMethods still receive
+// the noSuchMethod forwarders for each not implemented method from the
+// interface.
+
+class I {
+  dynamic noSuchMethod(Invocation i) => null;
+
+  // This should be a noSuchMethod forwarder, because [I] has a user-defined
+  // [noSuchMethod].
+  void foo();
+}
+
+class M {
+  dynamic noSuchMethod(Invocation i) => null;
+}
+
+class A extends Object with M implements I {}
+
+class B extends Object with M implements I {}
+
+main() {}
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/interface_with_nsm.dart.direct.expect b/pkg/front_end/testcases/no_such_method_forwarders/interface_with_nsm.dart.direct.expect
new file mode 100644
index 0000000..7463788
--- /dev/null
+++ b/pkg/front_end/testcases/no_such_method_forwarders/interface_with_nsm.dart.direct.expect
@@ -0,0 +1,36 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class I extends core::Object {
+  synthetic constructor •() → void
+    : super core::Object::•()
+    ;
+  method noSuchMethod(core::Invocation i) → dynamic
+    return null;
+  abstract no-such-method-forwarder method foo() → void;
+}
+class M extends core::Object {
+  synthetic constructor •() → void
+    : super core::Object::•()
+    ;
+  method noSuchMethod(core::Invocation i) → dynamic
+    return null;
+}
+abstract class _A&Object&M = core::Object with self::M {
+}
+class A extends self::_A&Object&M implements self::I {
+  synthetic constructor •() → void
+    : super core::Object::•()
+    ;
+  abstract no-such-method-forwarder method foo() → void;
+}
+abstract class _B&Object&M = core::Object with self::M {
+}
+class B extends self::_B&Object&M implements self::I {
+  synthetic constructor •() → void
+    : super core::Object::•()
+    ;
+  abstract no-such-method-forwarder method foo() → void;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/interface_with_nsm.dart.direct.transformed.expect b/pkg/front_end/testcases/no_such_method_forwarders/interface_with_nsm.dart.direct.transformed.expect
new file mode 100644
index 0000000..49caf94
--- /dev/null
+++ b/pkg/front_end/testcases/no_such_method_forwarders/interface_with_nsm.dart.direct.transformed.expect
@@ -0,0 +1,46 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class I extends core::Object {
+  synthetic constructor •() → void
+    : super core::Object::•()
+    ;
+  method noSuchMethod(core::Invocation i) → dynamic
+    return null;
+  abstract no-such-method-forwarder method foo() → void;
+}
+class M extends core::Object {
+  synthetic constructor •() → void
+    : super core::Object::•()
+    ;
+  method noSuchMethod(core::Invocation i) → dynamic
+    return null;
+}
+abstract class _A&Object&M extends core::Object implements self::M {
+  synthetic constructor •() → void
+    : super core::Object::•()
+    ;
+  method noSuchMethod(core::Invocation i) → dynamic
+    return null;
+}
+class A extends self::_A&Object&M implements self::I {
+  synthetic constructor •() → void
+    : super core::Object::•()
+    ;
+  abstract no-such-method-forwarder method foo() → void;
+}
+abstract class _B&Object&M extends core::Object implements self::M {
+  synthetic constructor •() → void
+    : super core::Object::•()
+    ;
+  method noSuchMethod(core::Invocation i) → dynamic
+    return null;
+}
+class B extends self::_B&Object&M implements self::I {
+  synthetic constructor •() → void
+    : super core::Object::•()
+    ;
+  abstract no-such-method-forwarder method foo() → void;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/interface_with_nsm.dart.outline.expect b/pkg/front_end/testcases/no_such_method_forwarders/interface_with_nsm.dart.outline.expect
new file mode 100644
index 0000000..f61d498
--- /dev/null
+++ b/pkg/front_end/testcases/no_such_method_forwarders/interface_with_nsm.dart.outline.expect
@@ -0,0 +1,33 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class I extends core::Object {
+  synthetic constructor •() → void
+    ;
+  method noSuchMethod(core::Invocation i) → dynamic
+    ;
+  abstract no-such-method-forwarder method foo() → void;
+}
+class M extends core::Object {
+  synthetic constructor •() → void
+    ;
+  method noSuchMethod(core::Invocation i) → dynamic
+    ;
+}
+abstract class _A&Object&M = core::Object with self::M {
+}
+class A extends self::_A&Object&M implements self::I {
+  synthetic constructor •() → void
+    ;
+  abstract no-such-method-forwarder method foo() → void;
+}
+abstract class _B&Object&M = core::Object with self::M {
+}
+class B extends self::_B&Object&M implements self::I {
+  synthetic constructor •() → void
+    ;
+  abstract no-such-method-forwarder method foo() → void;
+}
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/interface_with_nsm.dart.strong.expect b/pkg/front_end/testcases/no_such_method_forwarders/interface_with_nsm.dart.strong.expect
new file mode 100644
index 0000000..7463788
--- /dev/null
+++ b/pkg/front_end/testcases/no_such_method_forwarders/interface_with_nsm.dart.strong.expect
@@ -0,0 +1,36 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class I extends core::Object {
+  synthetic constructor •() → void
+    : super core::Object::•()
+    ;
+  method noSuchMethod(core::Invocation i) → dynamic
+    return null;
+  abstract no-such-method-forwarder method foo() → void;
+}
+class M extends core::Object {
+  synthetic constructor •() → void
+    : super core::Object::•()
+    ;
+  method noSuchMethod(core::Invocation i) → dynamic
+    return null;
+}
+abstract class _A&Object&M = core::Object with self::M {
+}
+class A extends self::_A&Object&M implements self::I {
+  synthetic constructor •() → void
+    : super core::Object::•()
+    ;
+  abstract no-such-method-forwarder method foo() → void;
+}
+abstract class _B&Object&M = core::Object with self::M {
+}
+class B extends self::_B&Object&M implements self::I {
+  synthetic constructor •() → void
+    : super core::Object::•()
+    ;
+  abstract no-such-method-forwarder method foo() → void;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/interface_with_nsm.dart.strong.transformed.expect b/pkg/front_end/testcases/no_such_method_forwarders/interface_with_nsm.dart.strong.transformed.expect
new file mode 100644
index 0000000..49caf94
--- /dev/null
+++ b/pkg/front_end/testcases/no_such_method_forwarders/interface_with_nsm.dart.strong.transformed.expect
@@ -0,0 +1,46 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class I extends core::Object {
+  synthetic constructor •() → void
+    : super core::Object::•()
+    ;
+  method noSuchMethod(core::Invocation i) → dynamic
+    return null;
+  abstract no-such-method-forwarder method foo() → void;
+}
+class M extends core::Object {
+  synthetic constructor •() → void
+    : super core::Object::•()
+    ;
+  method noSuchMethod(core::Invocation i) → dynamic
+    return null;
+}
+abstract class _A&Object&M extends core::Object implements self::M {
+  synthetic constructor •() → void
+    : super core::Object::•()
+    ;
+  method noSuchMethod(core::Invocation i) → dynamic
+    return null;
+}
+class A extends self::_A&Object&M implements self::I {
+  synthetic constructor •() → void
+    : super core::Object::•()
+    ;
+  abstract no-such-method-forwarder method foo() → void;
+}
+abstract class _B&Object&M extends core::Object implements self::M {
+  synthetic constructor •() → void
+    : super core::Object::•()
+    ;
+  method noSuchMethod(core::Invocation i) → dynamic
+    return null;
+}
+class B extends self::_B&Object&M implements self::I {
+  synthetic constructor •() → void
+    : super core::Object::•()
+    ;
+  abstract no-such-method-forwarder method foo() → void;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/no_dup_from_mixin.dart b/pkg/front_end/testcases/no_such_method_forwarders/no_dup_from_mixin.dart
new file mode 100644
index 0000000..fcbc2e3
--- /dev/null
+++ b/pkg/front_end/testcases/no_such_method_forwarders/no_dup_from_mixin.dart
@@ -0,0 +1,18 @@
+// Copyright (c) 2018, 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.
+
+// This test checks that the noSuchMethod forwarder is not duplicated in classes
+// that mix in the classes that already have the forwarder.
+
+abstract class I {
+  void foo();
+}
+
+class A implements I {
+  dynamic noSuchMethod(Invocation i) => null;
+}
+
+class B extends Object with A {}
+
+main() {}
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/no_dup_from_mixin.dart.direct.expect b/pkg/front_end/testcases/no_such_method_forwarders/no_dup_from_mixin.dart.direct.expect
new file mode 100644
index 0000000..aeadca5
--- /dev/null
+++ b/pkg/front_end/testcases/no_such_method_forwarders/no_dup_from_mixin.dart.direct.expect
@@ -0,0 +1,26 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+abstract class I extends core::Object {
+  synthetic constructor •() → void
+    : super core::Object::•()
+    ;
+  abstract method foo() → void;
+}
+class A extends core::Object implements self::I {
+  synthetic constructor •() → void
+    : super core::Object::•()
+    ;
+  method noSuchMethod(core::Invocation i) → dynamic
+    return null;
+  abstract no-such-method-forwarder method foo() → void;
+}
+abstract class _B&Object&A = core::Object with self::A {
+}
+class B extends self::_B&Object&A {
+  synthetic constructor •() → void
+    : super core::Object::•()
+    ;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/no_dup_from_mixin.dart.direct.transformed.expect b/pkg/front_end/testcases/no_such_method_forwarders/no_dup_from_mixin.dart.direct.transformed.expect
new file mode 100644
index 0000000..f43923a
--- /dev/null
+++ b/pkg/front_end/testcases/no_such_method_forwarders/no_dup_from_mixin.dart.direct.transformed.expect
@@ -0,0 +1,32 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+abstract class I extends core::Object {
+  synthetic constructor •() → void
+    : super core::Object::•()
+    ;
+  abstract method foo() → void;
+}
+class A extends core::Object implements self::I {
+  synthetic constructor •() → void
+    : super core::Object::•()
+    ;
+  method noSuchMethod(core::Invocation i) → dynamic
+    return null;
+  abstract no-such-method-forwarder method foo() → void;
+}
+abstract class _B&Object&A extends core::Object implements self::A {
+  synthetic constructor •() → void
+    : super core::Object::•()
+    ;
+  method noSuchMethod(core::Invocation i) → dynamic
+    return null;
+  abstract no-such-method-forwarder method foo() → void;
+}
+class B extends self::_B&Object&A {
+  synthetic constructor •() → void
+    : super core::Object::•()
+    ;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/no_dup_from_mixin.dart.outline.expect b/pkg/front_end/testcases/no_such_method_forwarders/no_dup_from_mixin.dart.outline.expect
new file mode 100644
index 0000000..71c513d
--- /dev/null
+++ b/pkg/front_end/testcases/no_such_method_forwarders/no_dup_from_mixin.dart.outline.expect
@@ -0,0 +1,24 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+abstract class I extends core::Object {
+  synthetic constructor •() → void
+    ;
+  abstract method foo() → void;
+}
+class A extends core::Object implements self::I {
+  synthetic constructor •() → void
+    ;
+  method noSuchMethod(core::Invocation i) → dynamic
+    ;
+  abstract no-such-method-forwarder method foo() → void;
+}
+abstract class _B&Object&A = core::Object with self::A {
+}
+class B extends self::_B&Object&A {
+  synthetic constructor •() → void
+    ;
+}
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/no_dup_from_mixin.dart.strong.expect b/pkg/front_end/testcases/no_such_method_forwarders/no_dup_from_mixin.dart.strong.expect
new file mode 100644
index 0000000..aeadca5
--- /dev/null
+++ b/pkg/front_end/testcases/no_such_method_forwarders/no_dup_from_mixin.dart.strong.expect
@@ -0,0 +1,26 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+abstract class I extends core::Object {
+  synthetic constructor •() → void
+    : super core::Object::•()
+    ;
+  abstract method foo() → void;
+}
+class A extends core::Object implements self::I {
+  synthetic constructor •() → void
+    : super core::Object::•()
+    ;
+  method noSuchMethod(core::Invocation i) → dynamic
+    return null;
+  abstract no-such-method-forwarder method foo() → void;
+}
+abstract class _B&Object&A = core::Object with self::A {
+}
+class B extends self::_B&Object&A {
+  synthetic constructor •() → void
+    : super core::Object::•()
+    ;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/no_dup_from_mixin.dart.strong.transformed.expect b/pkg/front_end/testcases/no_such_method_forwarders/no_dup_from_mixin.dart.strong.transformed.expect
new file mode 100644
index 0000000..f43923a
--- /dev/null
+++ b/pkg/front_end/testcases/no_such_method_forwarders/no_dup_from_mixin.dart.strong.transformed.expect
@@ -0,0 +1,32 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+abstract class I extends core::Object {
+  synthetic constructor •() → void
+    : super core::Object::•()
+    ;
+  abstract method foo() → void;
+}
+class A extends core::Object implements self::I {
+  synthetic constructor •() → void
+    : super core::Object::•()
+    ;
+  method noSuchMethod(core::Invocation i) → dynamic
+    return null;
+  abstract no-such-method-forwarder method foo() → void;
+}
+abstract class _B&Object&A extends core::Object implements self::A {
+  synthetic constructor •() → void
+    : super core::Object::•()
+    ;
+  method noSuchMethod(core::Invocation i) → dynamic
+    return null;
+  abstract no-such-method-forwarder method foo() → void;
+}
+class B extends self::_B&Object&A {
+  synthetic constructor •() → void
+    : super core::Object::•()
+    ;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/nsm_inherited.dart b/pkg/front_end/testcases/no_such_method_forwarders/nsm_inherited.dart
new file mode 100644
index 0000000..ecd60f1
--- /dev/null
+++ b/pkg/front_end/testcases/no_such_method_forwarders/nsm_inherited.dart
@@ -0,0 +1,16 @@
+// Copyright (c) 2018, 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.
+
+// This test checks that the noSuchMethod forwarder is generated in cases when
+// the user-defined noSuchMethod is inherited by classes with abstract methods.
+
+class M {
+  dynamic noSuchMethod(Invocation invocation) => null;
+}
+
+class A extends M {
+  void call(String s);
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/nsm_inherited.dart.direct.expect b/pkg/front_end/testcases/no_such_method_forwarders/nsm_inherited.dart.direct.expect
new file mode 100644
index 0000000..5b3dcdd
--- /dev/null
+++ b/pkg/front_end/testcases/no_such_method_forwarders/nsm_inherited.dart.direct.expect
@@ -0,0 +1,18 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class M extends core::Object {
+  synthetic constructor •() → void
+    : super core::Object::•()
+    ;
+  method noSuchMethod(core::Invocation invocation) → dynamic
+    return null;
+}
+class A extends self::M {
+  synthetic constructor •() → void
+    : super self::M::•()
+    ;
+  abstract no-such-method-forwarder method call(core::String s) → void;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/nsm_inherited.dart.direct.transformed.expect b/pkg/front_end/testcases/no_such_method_forwarders/nsm_inherited.dart.direct.transformed.expect
new file mode 100644
index 0000000..5b3dcdd
--- /dev/null
+++ b/pkg/front_end/testcases/no_such_method_forwarders/nsm_inherited.dart.direct.transformed.expect
@@ -0,0 +1,18 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class M extends core::Object {
+  synthetic constructor •() → void
+    : super core::Object::•()
+    ;
+  method noSuchMethod(core::Invocation invocation) → dynamic
+    return null;
+}
+class A extends self::M {
+  synthetic constructor •() → void
+    : super self::M::•()
+    ;
+  abstract no-such-method-forwarder method call(core::String s) → void;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/nsm_inherited.dart.outline.expect b/pkg/front_end/testcases/no_such_method_forwarders/nsm_inherited.dart.outline.expect
new file mode 100644
index 0000000..6fdc38e
--- /dev/null
+++ b/pkg/front_end/testcases/no_such_method_forwarders/nsm_inherited.dart.outline.expect
@@ -0,0 +1,17 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class M extends core::Object {
+  synthetic constructor •() → void
+    ;
+  method noSuchMethod(core::Invocation invocation) → dynamic
+    ;
+}
+class A extends self::M {
+  synthetic constructor •() → void
+    ;
+  abstract no-such-method-forwarder method call(core::String s) → void;
+}
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/nsm_inherited.dart.strong.expect b/pkg/front_end/testcases/no_such_method_forwarders/nsm_inherited.dart.strong.expect
new file mode 100644
index 0000000..5b3dcdd
--- /dev/null
+++ b/pkg/front_end/testcases/no_such_method_forwarders/nsm_inherited.dart.strong.expect
@@ -0,0 +1,18 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class M extends core::Object {
+  synthetic constructor •() → void
+    : super core::Object::•()
+    ;
+  method noSuchMethod(core::Invocation invocation) → dynamic
+    return null;
+}
+class A extends self::M {
+  synthetic constructor •() → void
+    : super self::M::•()
+    ;
+  abstract no-such-method-forwarder method call(core::String s) → void;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/nsm_inherited.dart.strong.transformed.expect b/pkg/front_end/testcases/no_such_method_forwarders/nsm_inherited.dart.strong.transformed.expect
new file mode 100644
index 0000000..5b3dcdd
--- /dev/null
+++ b/pkg/front_end/testcases/no_such_method_forwarders/nsm_inherited.dart.strong.transformed.expect
@@ -0,0 +1,18 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class M extends core::Object {
+  synthetic constructor •() → void
+    : super core::Object::•()
+    ;
+  method noSuchMethod(core::Invocation invocation) → dynamic
+    return null;
+}
+class A extends self::M {
+  synthetic constructor •() → void
+    : super self::M::•()
+    ;
+  abstract no-such-method-forwarder method call(core::String s) → void;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/nsm_mixed_in.dart b/pkg/front_end/testcases/no_such_method_forwarders/nsm_mixed_in.dart
new file mode 100644
index 0000000..284d817
--- /dev/null
+++ b/pkg/front_end/testcases/no_such_method_forwarders/nsm_mixed_in.dart
@@ -0,0 +1,18 @@
+// Copyright (c) 2018, 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.
+
+// This test checks that the noSuchMethod forwarder is generated in cases when
+// the user-defined noSuchMethod is mixed in to a class with abstract methods.
+
+class A {
+  dynamic noSuchMethod(Invocation i) {
+    return null;
+  }
+}
+
+class B extends Object with A {
+  void foo();
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/nsm_mixed_in.dart.direct.expect b/pkg/front_end/testcases/no_such_method_forwarders/nsm_mixed_in.dart.direct.expect
new file mode 100644
index 0000000..82b4b89
--- /dev/null
+++ b/pkg/front_end/testcases/no_such_method_forwarders/nsm_mixed_in.dart.direct.expect
@@ -0,0 +1,21 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  synthetic constructor •() → void
+    : super core::Object::•()
+    ;
+  method noSuchMethod(core::Invocation i) → dynamic {
+    return null;
+  }
+}
+abstract class _B&Object&A = core::Object with self::A {
+}
+class B extends self::_B&Object&A {
+  synthetic constructor •() → void
+    : super core::Object::•()
+    ;
+  abstract no-such-method-forwarder method foo() → void;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/nsm_mixed_in.dart.direct.transformed.expect b/pkg/front_end/testcases/no_such_method_forwarders/nsm_mixed_in.dart.direct.transformed.expect
new file mode 100644
index 0000000..224585c
--- /dev/null
+++ b/pkg/front_end/testcases/no_such_method_forwarders/nsm_mixed_in.dart.direct.transformed.expect
@@ -0,0 +1,27 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  synthetic constructor •() → void
+    : super core::Object::•()
+    ;
+  method noSuchMethod(core::Invocation i) → dynamic {
+    return null;
+  }
+}
+abstract class _B&Object&A extends core::Object implements self::A {
+  synthetic constructor •() → void
+    : super core::Object::•()
+    ;
+  method noSuchMethod(core::Invocation i) → dynamic {
+    return null;
+  }
+}
+class B extends self::_B&Object&A {
+  synthetic constructor •() → void
+    : super core::Object::•()
+    ;
+  abstract no-such-method-forwarder method foo() → void;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/nsm_mixed_in.dart.outline.expect b/pkg/front_end/testcases/no_such_method_forwarders/nsm_mixed_in.dart.outline.expect
new file mode 100644
index 0000000..6e0c11e
--- /dev/null
+++ b/pkg/front_end/testcases/no_such_method_forwarders/nsm_mixed_in.dart.outline.expect
@@ -0,0 +1,19 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  synthetic constructor •() → void
+    ;
+  method noSuchMethod(core::Invocation i) → dynamic
+    ;
+}
+abstract class _B&Object&A = core::Object with self::A {
+}
+class B extends self::_B&Object&A {
+  synthetic constructor •() → void
+    ;
+  abstract no-such-method-forwarder method foo() → void;
+}
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/nsm_mixed_in.dart.strong.expect b/pkg/front_end/testcases/no_such_method_forwarders/nsm_mixed_in.dart.strong.expect
new file mode 100644
index 0000000..82b4b89
--- /dev/null
+++ b/pkg/front_end/testcases/no_such_method_forwarders/nsm_mixed_in.dart.strong.expect
@@ -0,0 +1,21 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  synthetic constructor •() → void
+    : super core::Object::•()
+    ;
+  method noSuchMethod(core::Invocation i) → dynamic {
+    return null;
+  }
+}
+abstract class _B&Object&A = core::Object with self::A {
+}
+class B extends self::_B&Object&A {
+  synthetic constructor •() → void
+    : super core::Object::•()
+    ;
+  abstract no-such-method-forwarder method foo() → void;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/nsm_mixed_in.dart.strong.transformed.expect b/pkg/front_end/testcases/no_such_method_forwarders/nsm_mixed_in.dart.strong.transformed.expect
new file mode 100644
index 0000000..224585c
--- /dev/null
+++ b/pkg/front_end/testcases/no_such_method_forwarders/nsm_mixed_in.dart.strong.transformed.expect
@@ -0,0 +1,27 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  synthetic constructor •() → void
+    : super core::Object::•()
+    ;
+  method noSuchMethod(core::Invocation i) → dynamic {
+    return null;
+  }
+}
+abstract class _B&Object&A extends core::Object implements self::A {
+  synthetic constructor •() → void
+    : super core::Object::•()
+    ;
+  method noSuchMethod(core::Invocation i) → dynamic {
+    return null;
+  }
+}
+class B extends self::_B&Object&A {
+  synthetic constructor •() → void
+    : super core::Object::•()
+    ;
+  abstract no-such-method-forwarder method foo() → void;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/same.dart b/pkg/front_end/testcases/no_such_method_forwarders/same.dart
new file mode 100644
index 0000000..40d7c26
--- /dev/null
+++ b/pkg/front_end/testcases/no_such_method_forwarders/same.dart
@@ -0,0 +1,17 @@
+// Copyright (c) 2018, 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.
+
+// This test checks that a noSuchMethod forwarder is generated in the case when
+// the user-defined noSuchMethod and the abstract method are both defined in the
+// same class.
+
+class A {
+  dynamic noSuchMethod(Invocation i) {
+    return null;
+  }
+
+  void foo();
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/same.dart.direct.expect b/pkg/front_end/testcases/no_such_method_forwarders/same.dart.direct.expect
new file mode 100644
index 0000000..a8c2894
--- /dev/null
+++ b/pkg/front_end/testcases/no_such_method_forwarders/same.dart.direct.expect
@@ -0,0 +1,14 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  synthetic constructor •() → void
+    : super core::Object::•()
+    ;
+  method noSuchMethod(core::Invocation i) → dynamic {
+    return null;
+  }
+  abstract no-such-method-forwarder method foo() → void;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/same.dart.direct.transformed.expect b/pkg/front_end/testcases/no_such_method_forwarders/same.dart.direct.transformed.expect
new file mode 100644
index 0000000..a8c2894
--- /dev/null
+++ b/pkg/front_end/testcases/no_such_method_forwarders/same.dart.direct.transformed.expect
@@ -0,0 +1,14 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  synthetic constructor •() → void
+    : super core::Object::•()
+    ;
+  method noSuchMethod(core::Invocation i) → dynamic {
+    return null;
+  }
+  abstract no-such-method-forwarder method foo() → void;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/same.dart.outline.expect b/pkg/front_end/testcases/no_such_method_forwarders/same.dart.outline.expect
new file mode 100644
index 0000000..ef9c2e6
--- /dev/null
+++ b/pkg/front_end/testcases/no_such_method_forwarders/same.dart.outline.expect
@@ -0,0 +1,13 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  synthetic constructor •() → void
+    ;
+  method noSuchMethod(core::Invocation i) → dynamic
+    ;
+  abstract no-such-method-forwarder method foo() → void;
+}
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/same.dart.strong.expect b/pkg/front_end/testcases/no_such_method_forwarders/same.dart.strong.expect
new file mode 100644
index 0000000..a8c2894
--- /dev/null
+++ b/pkg/front_end/testcases/no_such_method_forwarders/same.dart.strong.expect
@@ -0,0 +1,14 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  synthetic constructor •() → void
+    : super core::Object::•()
+    ;
+  method noSuchMethod(core::Invocation i) → dynamic {
+    return null;
+  }
+  abstract no-such-method-forwarder method foo() → void;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/same.dart.strong.transformed.expect b/pkg/front_end/testcases/no_such_method_forwarders/same.dart.strong.transformed.expect
new file mode 100644
index 0000000..a8c2894
--- /dev/null
+++ b/pkg/front_end/testcases/no_such_method_forwarders/same.dart.strong.transformed.expect
@@ -0,0 +1,14 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  synthetic constructor •() → void
+    : super core::Object::•()
+    ;
+  method noSuchMethod(core::Invocation i) → dynamic {
+    return null;
+  }
+  abstract no-such-method-forwarder method foo() → void;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/subst_on_forwarder.dart b/pkg/front_end/testcases/no_such_method_forwarders/subst_on_forwarder.dart
new file mode 100644
index 0000000..f461405
--- /dev/null
+++ b/pkg/front_end/testcases/no_such_method_forwarders/subst_on_forwarder.dart
@@ -0,0 +1,21 @@
+// Copyright (c) 2018, 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.
+
+// This test checks that the generated noSuchMethod forwarder for a
+// non-implemented abstract method has all the references to the type variables
+// in its signature replaced with the appropriate types.
+
+class I<T> {
+  T foo();
+}
+
+class M {
+  dynamic noSuchMethod(Invocation i) {
+    return null;
+  }
+}
+
+class A extends Object with M implements I<int> {}
+
+main() {}
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/subst_on_forwarder.dart.direct.expect b/pkg/front_end/testcases/no_such_method_forwarders/subst_on_forwarder.dart.direct.expect
new file mode 100644
index 0000000..ffa2406
--- /dev/null
+++ b/pkg/front_end/testcases/no_such_method_forwarders/subst_on_forwarder.dart.direct.expect
@@ -0,0 +1,27 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class I<T extends core::Object> extends core::Object {
+  synthetic constructor •() → void
+    : super core::Object::•()
+    ;
+  abstract method foo() → self::I::T;
+}
+class M extends core::Object {
+  synthetic constructor •() → void
+    : super core::Object::•()
+    ;
+  method noSuchMethod(core::Invocation i) → dynamic {
+    return null;
+  }
+}
+abstract class _A&Object&M = core::Object with self::M {
+}
+class A extends self::_A&Object&M implements self::I<core::int> {
+  synthetic constructor •() → void
+    : super core::Object::•()
+    ;
+  abstract no-such-method-forwarder method foo() → core::int;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/subst_on_forwarder.dart.direct.transformed.expect b/pkg/front_end/testcases/no_such_method_forwarders/subst_on_forwarder.dart.direct.transformed.expect
new file mode 100644
index 0000000..41aef5e
--- /dev/null
+++ b/pkg/front_end/testcases/no_such_method_forwarders/subst_on_forwarder.dart.direct.transformed.expect
@@ -0,0 +1,33 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class I<T extends core::Object> extends core::Object {
+  synthetic constructor •() → void
+    : super core::Object::•()
+    ;
+  abstract method foo() → self::I::T;
+}
+class M extends core::Object {
+  synthetic constructor •() → void
+    : super core::Object::•()
+    ;
+  method noSuchMethod(core::Invocation i) → dynamic {
+    return null;
+  }
+}
+abstract class _A&Object&M extends core::Object implements self::M {
+  synthetic constructor •() → void
+    : super core::Object::•()
+    ;
+  method noSuchMethod(core::Invocation i) → dynamic {
+    return null;
+  }
+}
+class A extends self::_A&Object&M implements self::I<core::int> {
+  synthetic constructor •() → void
+    : super core::Object::•()
+    ;
+  abstract no-such-method-forwarder method foo() → core::int;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/subst_on_forwarder.dart.outline.expect b/pkg/front_end/testcases/no_such_method_forwarders/subst_on_forwarder.dart.outline.expect
new file mode 100644
index 0000000..6a7ca94
--- /dev/null
+++ b/pkg/front_end/testcases/no_such_method_forwarders/subst_on_forwarder.dart.outline.expect
@@ -0,0 +1,24 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class I<T extends core::Object> extends core::Object {
+  synthetic constructor •() → void
+    ;
+  abstract method foo() → self::I::T;
+}
+class M extends core::Object {
+  synthetic constructor •() → void
+    ;
+  method noSuchMethod(core::Invocation i) → dynamic
+    ;
+}
+abstract class _A&Object&M = core::Object with self::M {
+}
+class A extends self::_A&Object&M implements self::I<core::int> {
+  synthetic constructor •() → void
+    ;
+  abstract no-such-method-forwarder method foo() → core::int;
+}
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/subst_on_forwarder.dart.strong.expect b/pkg/front_end/testcases/no_such_method_forwarders/subst_on_forwarder.dart.strong.expect
new file mode 100644
index 0000000..ffa2406
--- /dev/null
+++ b/pkg/front_end/testcases/no_such_method_forwarders/subst_on_forwarder.dart.strong.expect
@@ -0,0 +1,27 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class I<T extends core::Object> extends core::Object {
+  synthetic constructor •() → void
+    : super core::Object::•()
+    ;
+  abstract method foo() → self::I::T;
+}
+class M extends core::Object {
+  synthetic constructor •() → void
+    : super core::Object::•()
+    ;
+  method noSuchMethod(core::Invocation i) → dynamic {
+    return null;
+  }
+}
+abstract class _A&Object&M = core::Object with self::M {
+}
+class A extends self::_A&Object&M implements self::I<core::int> {
+  synthetic constructor •() → void
+    : super core::Object::•()
+    ;
+  abstract no-such-method-forwarder method foo() → core::int;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/subst_on_forwarder.dart.strong.transformed.expect b/pkg/front_end/testcases/no_such_method_forwarders/subst_on_forwarder.dart.strong.transformed.expect
new file mode 100644
index 0000000..41aef5e
--- /dev/null
+++ b/pkg/front_end/testcases/no_such_method_forwarders/subst_on_forwarder.dart.strong.transformed.expect
@@ -0,0 +1,33 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class I<T extends core::Object> extends core::Object {
+  synthetic constructor •() → void
+    : super core::Object::•()
+    ;
+  abstract method foo() → self::I::T;
+}
+class M extends core::Object {
+  synthetic constructor •() → void
+    : super core::Object::•()
+    ;
+  method noSuchMethod(core::Invocation i) → dynamic {
+    return null;
+  }
+}
+abstract class _A&Object&M extends core::Object implements self::M {
+  synthetic constructor •() → void
+    : super core::Object::•()
+    ;
+  method noSuchMethod(core::Invocation i) → dynamic {
+    return null;
+  }
+}
+class A extends self::_A&Object&M implements self::I<core::int> {
+  synthetic constructor •() → void
+    : super core::Object::•()
+    ;
+  abstract no-such-method-forwarder method foo() → core::int;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/strong.status b/pkg/front_end/testcases/strong.status
index 91b818e..bdc3645 100644
--- a/pkg/front_end/testcases/strong.status
+++ b/pkg/front_end/testcases/strong.status
@@ -14,6 +14,7 @@
 bug21938: TypeCheckError
 bug30695: TypeCheckError
 bug31124: RuntimeError # Test has an intentional error
+bug32629: Fail # Test has an intentional error
 call: Fail
 cascade: Fail
 casts: Fail
diff --git a/pkg/front_end/testing.json b/pkg/front_end/testing.json
index b1fadda..af4b8b4 100644
--- a/pkg/front_end/testing.json
+++ b/pkg/front_end/testing.json
@@ -148,6 +148,48 @@
     },
 
     {
+      "name": "incremental_load_from_dill",
+      "kind": "Chain",
+      "source": "test/incremental_load_from_dill_test.dart",
+      "path": "testcases/incremental_initialize_from_dill/",
+      "status": "testcases/incremental_initialize_from_dill/status.status",
+      "pattern": [
+        "\\.yaml$"
+      ],
+      "exclude": [
+      ]
+    },
+
+    {
+      "name": "incremental_bulk_compiler_smoke",
+      "kind": "Chain",
+      "source": "test/incremental_bulk_compiler_smoke_test.dart",
+      "path": "../../tests/",
+      "status": "testcases/incremental_bulk_compiler_smoke.status",
+      "pattern": [
+        "/language_2/accessor_conflict_export2_test\\.dart$",
+        "/language_2/accessor_conflict_export_test\\.dart$",
+        "/language_2/regress_14348_test\\.dart$",
+        "/language_2/regress_18535_test\\.dart$"
+      ],
+      "exclude": [
+      ]
+    },
+
+    {
+      "name": "incremental_bulk_compiler_full",
+      "kind": "Chain",
+      "source": "test/incremental_bulk_compiler_full.dart",
+      "path": "../../tests/",
+      "status": "testcases/incremental_bulk_compiler_full.status",
+      "pattern": [
+        "language_2/.*_test\\.dart$"
+      ],
+      "exclude": [
+      ]
+    },
+
+    {
       "name": "sdk",
       "kind": "Chain",
       "source": "test/fasta/sdk_test.dart",
diff --git a/pkg/front_end/tool/_fasta/compile_platform.dart b/pkg/front_end/tool/_fasta/compile_platform.dart
index 5629776..b2bf572 100644
--- a/pkg/front_end/tool/_fasta/compile_platform.dart
+++ b/pkg/front_end/tool/_fasta/compile_platform.dart
@@ -9,7 +9,10 @@
 import 'dart:io' show File, Platform, exitCode;
 
 import 'package:compiler/src/kernel/dart2js_target.dart' show Dart2jsTarget;
-import 'package:vm/target/runner.dart' show RunnerTarget;
+
+import 'package:vm/target/dart_runner.dart' show DartRunnerTarget;
+
+import 'package:vm/target/flutter_runner.dart' show FlutterRunnerTarget;
 
 import 'package:kernel/target/targets.dart' show TargetFlags, targets;
 
@@ -35,8 +38,13 @@
 const int iterations = const int.fromEnvironment("iterations", defaultValue: 1);
 
 Future main(List<String> arguments) async {
-  targets["dart2js"] = (TargetFlags flags) => new Dart2jsTarget(flags);
-  targets["runner"] = (TargetFlags flags) => new RunnerTarget(flags);
+  targets["dart2js"] =
+      (TargetFlags flags) => new Dart2jsTarget("dart2js", flags);
+  targets["dart2js_server"] =
+      (TargetFlags flags) => new Dart2jsTarget("dart2js_server", flags);
+  targets["dart_runner"] = (TargetFlags flags) => new DartRunnerTarget(flags);
+  targets["flutter_runner"] =
+      (TargetFlags flags) => new FlutterRunnerTarget(flags);
   for (int i = 0; i < iterations; i++) {
     if (i > 0) {
       print("\n");
diff --git a/pkg/front_end/tool/_fasta/entry_points.dart b/pkg/front_end/tool/_fasta/entry_points.dart
index 67cbe59..c69bb9b 100644
--- a/pkg/front_end/tool/_fasta/entry_points.dart
+++ b/pkg/front_end/tool/_fasta/entry_points.dart
@@ -49,7 +49,10 @@
 const int iterations = const int.fromEnvironment("iterations", defaultValue: 1);
 
 compileEntryPoint(List<String> arguments) async {
-  targets["dart2js"] = (TargetFlags flags) => new Dart2jsTarget(flags);
+  targets["dart2js"] =
+      (TargetFlags flags) => new Dart2jsTarget("dart2js", flags);
+  targets["dart2js_server"] =
+      (TargetFlags flags) => new Dart2jsTarget("dart2js_server", flags);
 
   // Timing results for each iteration
   List<double> elapsedTimes = <double>[];
diff --git a/pkg/kernel/binary.md b/pkg/kernel/binary.md
index 9305d16..6179db3 100644
--- a/pkg/kernel/binary.md
+++ b/pkg/kernel/binary.md
@@ -353,6 +353,7 @@
   Byte flags (isStatic, isAbstract, isExternal, isConst, isForwardingStub,
               isGenericContravariant, isForwardingSemiStub,
               isRedirectingFactoryConstructor);
+  Byte flags2 (isNoSuchMethodForwarder);
   Name name;
   List<Expression> annotations;
   // Only present if the 'isForwardingStub' flag is set.
diff --git a/pkg/kernel/lib/ast.dart b/pkg/kernel/lib/ast.dart
index 2152cd9..099307e 100644
--- a/pkg/kernel/lib/ast.dart
+++ b/pkg/kernel/lib/ast.dart
@@ -1451,6 +1451,7 @@
 class Procedure extends Member {
   ProcedureKind kind;
   int flags = 0;
+  int flags2 = 0;
   // function is null if and only if abstract, external.
   FunctionNode function;
 
@@ -1539,6 +1540,7 @@
   static const int FlagForwardingSemiStub = 1 << 6;
   // TODO(29841): Remove this flag after the issue is resolved.
   static const int FlagRedirectingFactoryConstructor = 1 << 7;
+  static const int Flag2NoSuchMethodForwarder = 1 << 0;
 
   bool get isStatic => flags & FlagStatic != 0;
   bool get isAbstract => flags & FlagAbstract != 0;
@@ -1581,6 +1583,8 @@
   /// and forwarding to [forwardingStubSuperTarget].
   bool get isSyntheticForwarder => isForwardingStub && !isForwardingSemiStub;
 
+  bool get isNoSuchMethodForwarder => flags2 & Flag2NoSuchMethodForwarder != 0;
+
   void set isStatic(bool value) {
     flags = value ? (flags | FlagStatic) : (flags & ~FlagStatic);
   }
@@ -1620,6 +1624,13 @@
         : (flags & ~FlagRedirectingFactoryConstructor);
   }
 
+  void set isNoSuchMethodForwarder(bool value) {
+    assert(isAbstract);
+    flags2 = value
+        ? (flags2 | Flag2NoSuchMethodForwarder)
+        : (flags2 & ~Flag2NoSuchMethodForwarder);
+  }
+
   bool get isInstanceMember => !isStatic;
   bool get isGetter => kind == ProcedureKind.Getter;
   bool get isSetter => kind == ProcedureKind.Setter;
diff --git a/pkg/kernel/lib/binary/ast_from_binary.dart b/pkg/kernel/lib/binary/ast_from_binary.dart
index ce35260..4869901 100644
--- a/pkg/kernel/lib/binary/ast_from_binary.dart
+++ b/pkg/kernel/lib/binary/ast_from_binary.dart
@@ -933,6 +933,7 @@
     int kindIndex = readByte();
     var kind = ProcedureKind.values[kindIndex];
     var flags = readByte();
+    var flags2 = readByte();
     var name = readName();
     var annotations = readAnnotationList(node);
     assert(() {
@@ -956,6 +957,7 @@
       node.fileEndOffset = fileEndOffset;
       node.kind = kind;
       node.flags = flags;
+      node.flags2 = flags2;
       node.name = name;
       node.fileUri = fileUri;
       node.annotations = annotations;
diff --git a/pkg/kernel/lib/binary/ast_to_binary.dart b/pkg/kernel/lib/binary/ast_to_binary.dart
index 7bec298..a71ec32 100644
--- a/pkg/kernel/lib/binary/ast_to_binary.dart
+++ b/pkg/kernel/lib/binary/ast_to_binary.dart
@@ -808,6 +808,7 @@
     writeOffset(node.fileEndOffset);
     writeByte(node.kind.index);
     writeByte(node.flags);
+    writeByte(node.flags2);
     writeName(node.name ?? '');
     writeAnnotationList(node.annotations);
     writeOptionalReference(node.forwardingStubSuperTargetReference);
diff --git a/pkg/kernel/lib/class_hierarchy.dart b/pkg/kernel/lib/class_hierarchy.dart
index 20eadbe..be0c79a 100644
--- a/pkg/kernel/lib/class_hierarchy.dart
+++ b/pkg/kernel/lib/class_hierarchy.dart
@@ -724,7 +724,9 @@
 
     // Run a downward traversal from the root, compute preorder numbers for
     // each class, and build their subtype sets as interval lists.
-    _topDownSortVisit(_infoFor[classes[0]]);
+    if (classes.isNotEmpty) {
+      _topDownSortVisit(_infoFor[classes[0]]);
+    }
 
     // Now that the intervals for subclass, mixer, and implementer queries are
     // built, we may infer and record supertypes for the classes.
diff --git a/pkg/kernel/lib/clone.dart b/pkg/kernel/lib/clone.dart
index 3eb51ac..3901902 100644
--- a/pkg/kernel/lib/clone.dart
+++ b/pkg/kernel/lib/clone.dart
@@ -423,19 +423,15 @@
 
   visitProcedure(Procedure node) {
     return new Procedure(node.name, node.kind, clone(node.function),
-        isAbstract: node.isAbstract,
-        isStatic: node.isStatic,
-        isExternal: node.isExternal,
-        isConst: node.isConst,
-        isForwardingStub: node.isForwardingStub,
-        isForwardingSemiStub: node.isForwardingSemiStub,
         transformerFlags: node.transformerFlags,
         fileUri: _activeFileUri,
         forwardingStubSuperTarget: node.forwardingStubSuperTarget,
         forwardingStubInterfaceTarget: node.forwardingStubInterfaceTarget)
       ..fileOffset = _cloneFileOffset(node.fileOffset)
       ..fileEndOffset = _cloneFileOffset(node.fileEndOffset)
-      ..isGenericContravariant = node.isGenericContravariant;
+      ..isGenericContravariant = node.isGenericContravariant
+      ..flags = node.flags
+      ..flags2 = node.flags2;
   }
 
   visitField(Field node) {
@@ -590,3 +586,11 @@
     return defaultTreeNode(node);
   }
 }
+
+class CloneWithoutBody extends CloneVisitor {
+  CloneWithoutBody({Map<TypeParameter, DartType> typeSubstitution})
+      : super(typeSubstitution: typeSubstitution);
+
+  @override
+  TreeNode cloneFunctionNodeBody(FunctionNode node) => null;
+}
diff --git a/pkg/kernel/lib/target/targets.dart b/pkg/kernel/lib/target/targets.dart
index 22672fd..ec9a8aa 100644
--- a/pkg/kernel/lib/target/targets.dart
+++ b/pkg/kernel/lib/target/targets.dart
@@ -76,6 +76,15 @@
   /// promotion do not slow down compilation too much.
   bool get disableTypeInference => false;
 
+  /// A derived class may change this to `true` to enable forwarders to
+  /// user-defined `noSuchMethod` that are generated for each abstract member
+  /// if such `noSuchMethod` is present.
+  ///
+  /// The forwarders are abstract [Procedure]s with [isNoSuchMethodForwarder]
+  /// bit set.  The implementation of the behavior of such forwarders is up
+  /// for the target backend.
+  bool get enableNoSuchMethodForwarders => false;
+
   /// A derived class may change this to `true` to enable Flutter specific
   /// "super-mixins" semantics.
   ///
diff --git a/pkg/kernel/lib/target/vm.dart b/pkg/kernel/lib/target/vm.dart
index 5fd891e..322d2c5 100644
--- a/pkg/kernel/lib/target/vm.dart
+++ b/pkg/kernel/lib/target/vm.dart
@@ -26,6 +26,9 @@
   bool get strongMode => flags.strongMode;
 
   @override
+  bool get enableNoSuchMethodForwarders => true;
+
+  @override
   String get name => 'vm';
 
   // This is the order that bootstrap libraries are loaded according to
diff --git a/pkg/kernel/lib/text/ast_to_text.dart b/pkg/kernel/lib/text/ast_to_text.dart
index fcf52cf..ade2e8e 100644
--- a/pkg/kernel/lib/text/ast_to_text.dart
+++ b/pkg/kernel/lib/text/ast_to_text.dart
@@ -929,6 +929,7 @@
     writeModifier(node.isForwardingStub, 'forwarding-stub');
     writeModifier(node.isForwardingSemiStub, 'forwarding-semi-stub');
     writeModifier(node.isGenericContravariant, 'generic-contravariant');
+    writeModifier(node.isNoSuchMethodForwarder, 'no-such-method-forwarder');
     writeWord(procedureKindToString(node.kind));
     if ((node.enclosingClass == null &&
             node.enclosingLibrary.fileUri != node.fileUri) ||
diff --git a/pkg/kernel/lib/transformations/closure/clone_without_body.dart b/pkg/kernel/lib/transformations/closure/clone_without_body.dart
index 1f13b54..1e4b344 100644
--- a/pkg/kernel/lib/transformations/closure/clone_without_body.dart
+++ b/pkg/kernel/lib/transformations/closure/clone_without_body.dart
@@ -4,14 +4,4 @@
 
 library kernel.transformations.closure.converter;
 
-import '../../ast.dart' show DartType, FunctionNode, TreeNode, TypeParameter;
-
-import '../../clone.dart' show CloneVisitor;
-
-class CloneWithoutBody extends CloneVisitor {
-  CloneWithoutBody({Map<TypeParameter, DartType> typeSubstitution})
-      : super(typeSubstitution: typeSubstitution);
-
-  @override
-  TreeNode cloneFunctionNodeBody(FunctionNode node) => null;
-}
+export '../../clone.dart' show CloneWithoutBody;
diff --git a/pkg/kernel/pubspec.yaml b/pkg/kernel/pubspec.yaml
index 6e17f7d..a08802c 100644
--- a/pkg/kernel/pubspec.yaml
+++ b/pkg/kernel/pubspec.yaml
@@ -12,7 +12,7 @@
   package_config: ^1.0.0
 dev_dependencies:
   analyzer: '>=0.30.0 <0.32.0'
-  front_end: 0.1.0-alpha.10
+  front_end: 0.1.0-alpha.11
   test: ^0.12.15+6
   stack_trace: ^1.6.6
   ansicolor: ^0.0.9
diff --git a/pkg/kernel/test/frontend_bench.dart b/pkg/kernel/test/frontend_bench.dart
deleted file mode 100644
index 78d01c2..0000000
--- a/pkg/kernel/test/frontend_bench.dart
+++ /dev/null
@@ -1,67 +0,0 @@
-// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'dart:io';
-import 'package:analyzer/src/context/cache.dart';
-import 'package:analyzer/task/model.dart';
-import 'package:args/args.dart';
-import 'package:analyzer/src/kernel/loader.dart';
-import 'package:kernel/kernel.dart';
-import 'package:package_config/discovery.dart';
-
-ArgParser parser = new ArgParser()
-  ..addOption('sdk',
-      help: 'Path to Dart SDK', valueHelp: 'path', defaultsTo: '/usr/lib/dart')
-  ..addOption('packages',
-      abbr: 'p',
-      help: 'Path to the packages folder or .packages file',
-      valueHelp: 'path')
-  ..addFlag('strong', help: 'Use strong mode');
-
-String get usage => '''
-Usage: frontend_bench [options] FILE.dart
-
-Benchmark the analyzer-based frontend.
-
-Options:
-${parser.options}
-''';
-
-main(List<String> args) {
-  if (args.length == 0) {
-    print(usage);
-    exit(1);
-  }
-  ArgResults options = parser.parse(args);
-
-  if (options.rest.length != 1) {
-    print('Exactly one file must be given');
-    exit(1);
-  }
-
-  String sdk = options['sdk'];
-  String packagePath = options['packages'];
-  bool strongMode = options['strong'];
-
-  String path = options.rest.single;
-  var uri = new Uri(scheme: 'file', path: new File(path).absolute.path);
-  var packages =
-      getPackagesDirectory(new Uri(scheme: 'file', path: packagePath));
-  Component repository = new Component();
-
-  new DartLoader(
-          repository,
-          new DartOptions(
-              strongMode: strongMode, sdk: sdk, packagePath: packagePath),
-          packages)
-      .loadComponent(uri);
-
-  CacheEntry.recomputedCounts.forEach((key, value) {
-    print('Recomputed $key $value times');
-  });
-
-  AnalysisTask.stopwatchMap.forEach((key, Stopwatch watch) {
-    print('$key took ${watch.elapsedMilliseconds} ms');
-  });
-}
diff --git a/pkg/pkg.status b/pkg/pkg.status
index a742edc..a03128c 100644
--- a/pkg/pkg.status
+++ b/pkg/pkg.status
@@ -116,7 +116,7 @@
 front_end/test/fasta/ast_builder_test: Pass, Slow, Timeout
 front_end/test/fasta/bootstrap_test: Skip # Issue 31902
 front_end/test/fasta/strong_test: Pass, Slow, Timeout
-front_end/test/incremental_load_from_dill_test: Pass, Slow
+front_end/test/incremental_dart2js_load_from_dill_test: Pass, Slow
 front_end/test/src/incremental/hot_reload_e2e_test: Skip # Issue 31901
 front_end/test/whole_program_test: Skip # Issue 31902
 
diff --git a/pkg/vm/lib/frontend_server.dart b/pkg/vm/lib/frontend_server.dart
index 15ee47f..341207f 100644
--- a/pkg/vm/lib/frontend_server.dart
+++ b/pkg/vm/lib/frontend_server.dart
@@ -256,7 +256,6 @@
       printer.writeComponentFile(component);
       await sink.close();
       _outputStream.writeln('$boundaryKey $_kernelBinaryFilename');
-
       final String depfile = options['depfile'];
       if (depfile != null) {
         await _writeDepfile(component, _kernelBinaryFilename, depfile);
@@ -270,6 +269,10 @@
 
   Future<Null> invalidateIfBootstrapping() async {
     if (_kernelBinaryFilename != _kernelBinaryFilenameFull) return null;
+    // If the generator is initialized bootstrapping is not in effect anyway,
+    // so there's no reason to spend time invalidating what should be
+    // invalidated by the normal approach anyway.
+    if (_generator.initialized) return null;
 
     try {
       final File f = new File(_kernelBinaryFilenameFull);
@@ -342,7 +345,7 @@
 
   @override
   void resetIncrementalCompiler() {
-    _generator = _createGenerator(new Uri.file(_kernelBinaryFilenameFull));
+    _generator.resetDeltaState();
     _kernelBinaryFilename = _kernelBinaryFilenameFull;
   }
 
diff --git a/pkg/vm/lib/incremental_compiler.dart b/pkg/vm/lib/incremental_compiler.dart
index bfe5919..91d9426 100644
--- a/pkg/vm/lib/incremental_compiler.dart
+++ b/pkg/vm/lib/incremental_compiler.dart
@@ -17,6 +17,8 @@
   IncrementalKernelGenerator _generator;
   List<Component> _pendingDeltas;
   CompilerOptions _compilerOptions;
+  bool initialized = false;
+  bool fullComponent = false;
 
   IncrementalCompiler(this._compilerOptions, Uri entryPoint,
       {Uri bootstrapDill}) {
@@ -30,7 +32,10 @@
   /// If [entryPoint] is specified, that points to new entry point for the
   /// compilation. Otherwise, previously set entryPoint is used.
   Future<Component> compile({Uri entryPoint}) async {
-    Component component = await _generator.computeDelta(entryPoint: entryPoint);
+    Component component = await _generator.computeDelta(
+        entryPoint: entryPoint, fullComponent: fullComponent);
+    initialized = true;
+    fullComponent = false;
     final bool firstDelta = _pendingDeltas.isEmpty;
     _pendingDeltas.add(component);
     if (firstDelta) {
@@ -64,4 +69,9 @@
   invalidate(Uri uri) {
     _generator.invalidate(uri);
   }
+
+  resetDeltaState() {
+    _pendingDeltas.clear();
+    fullComponent = true;
+  }
 }
diff --git a/pkg/vm/lib/target/runner.dart b/pkg/vm/lib/target/dart_runner.dart
similarity index 83%
rename from pkg/vm/lib/target/runner.dart
rename to pkg/vm/lib/target/dart_runner.dart
index 3b7ce0c..fe75c94 100644
--- a/pkg/vm/lib/target/runner.dart
+++ b/pkg/vm/lib/target/dart_runner.dart
@@ -1,16 +1,19 @@
 // Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
-library kernel.target.runner;
+library kernel.target.dart_runner;
 
 import 'package:kernel/target/targets.dart';
 import 'package:kernel/target/vm.dart' show VmTarget;
 
-class RunnerTarget extends VmTarget {
-  RunnerTarget(TargetFlags flags) : super(flags);
+class DartRunnerTarget extends VmTarget {
+  DartRunnerTarget(TargetFlags flags) : super(flags);
 
   @override
-  String get name => 'runner';
+  String get name => 'dart_runner';
+
+  @override
+  bool get enableSuperMixins => true;
 
   // This is the order that bootstrap libraries are loaded according to
   // `runtime/vm/object_store.h`.
diff --git a/pkg/vm/lib/target/runner.dart b/pkg/vm/lib/target/flutter_runner.dart
similarity index 76%
copy from pkg/vm/lib/target/runner.dart
copy to pkg/vm/lib/target/flutter_runner.dart
index 3b7ce0c..8878c01 100644
--- a/pkg/vm/lib/target/runner.dart
+++ b/pkg/vm/lib/target/flutter_runner.dart
@@ -1,16 +1,19 @@
 // Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
-library kernel.target.runner;
+library kernel.target.flutter_runner;
 
 import 'package:kernel/target/targets.dart';
 import 'package:kernel/target/vm.dart' show VmTarget;
 
-class RunnerTarget extends VmTarget {
-  RunnerTarget(TargetFlags flags) : super(flags);
+class FlutterRunnerTarget extends VmTarget {
+  FlutterRunnerTarget(TargetFlags flags) : super(flags);
 
   @override
-  String get name => 'runner';
+  String get name => 'flutter_runner';
+
+  @override
+  bool get enableSuperMixins => true;
 
   // This is the order that bootstrap libraries are loaded according to
   // `runtime/vm/object_store.h`.
@@ -33,10 +36,12 @@
         'dart:nativewrappers',
         'dart:io',
 
-        // Required for dart_runner.
+        // Required for flutter_runner.
         'dart:fuchsia.builtin',
         'dart:zircon',
         'dart:fuchsia',
         'dart:vmservice_io',
+        'dart:ui',
+        'dart:mozart.internal',
       ];
 }
diff --git a/pkg/vm/test/frontend_server_test.dart b/pkg/vm/test/frontend_server_test.dart
index 3279881..bc18e95 100644
--- a/pkg/vm/test/frontend_server_test.dart
+++ b/pkg/vm/test/frontend_server_test.dart
@@ -377,6 +377,7 @@
 
       final _MockedIncrementalCompiler generator =
           new _MockedIncrementalCompiler();
+      when(generator.initialized).thenAnswer((_) => false);
       when(generator.compile())
           .thenAnswer((_) => new Future<Component>.value(new Component()));
       final _MockedBinaryPrinterFactory printerFactory =
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/no_such_method.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/no_such_method.dart.expect
index f15ef86..9971701 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/no_such_method.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/no_such_method.dart.expect
@@ -52,6 +52,9 @@
   method noSuchMethod(core::Invocation invocation) → dynamic {
     return new self::T1::•();
   }
+  abstract no-such-method-forwarder get bar() → dynamic;
+  abstract no-such-method-forwarder method foo() → dynamic;
+  abstract no-such-method-forwarder method bazz(dynamic a1, dynamic a2, dynamic a3, [dynamic a4, dynamic a5]) → dynamic;
 }
 class C extends core::Object {
   synthetic constructor •() → void
@@ -65,6 +68,9 @@
   synthetic constructor •() → void
     : super self::C::•()
     ;
+  abstract no-such-method-forwarder get bar() → dynamic;
+  abstract no-such-method-forwarder method foo() → dynamic;
+  abstract no-such-method-forwarder method bazz(dynamic a1, dynamic a2, dynamic a3, [dynamic a4, dynamic a5]) → dynamic;
 }
 class E extends core::Object implements self::A {
   synthetic constructor •() → void
@@ -75,6 +81,8 @@
   method noSuchMethod(core::Invocation invocation) → dynamic {
     return new self::T4::•();
   }
+  abstract no-such-method-forwarder get bar() → dynamic;
+  abstract no-such-method-forwarder method bazz(dynamic a1, dynamic a2, dynamic a3, [dynamic a4, dynamic a5]) → dynamic;
 }
 class F extends core::Object {
   synthetic constructor •() → void
diff --git a/runtime/bin/dartutils.cc b/runtime/bin/dartutils.cc
index e23ba23..8043ec0 100644
--- a/runtime/bin/dartutils.cc
+++ b/runtime/bin/dartutils.cc
@@ -368,6 +368,7 @@
   if (File::GetType(NULL, filename, true) == File::kIsFile) {
     File* file = File::Open(NULL, filename, File::kRead);
     if (file != NULL) {
+      RefCntReleaseScope<File> rs(file);
       intptr_t max_magic_length = 0;
       max_magic_length =
           Utils::Maximum(max_magic_length, snapshot_magic_number.length);
@@ -382,7 +383,6 @@
       if (file->ReadFully(&header, max_magic_length)) {
         magic_number = DartUtils::SniffForMagicNumber(header, sizeof(header));
       }
-      file->Close();
     }
   }
   return magic_number;
diff --git a/runtime/bin/extensions_fuchsia.cc b/runtime/bin/extensions_fuchsia.cc
index 540963f..34aa8d0 100644
--- a/runtime/bin/extensions_fuchsia.cc
+++ b/runtime/bin/extensions_fuchsia.cc
@@ -30,7 +30,7 @@
     return NULL;
   }
   zx_handle_t vmo;
-  zx_status_t status = fdio_get_vmo(fd, &vmo);
+  zx_status_t status = fdio_get_vmo_clone(fd, &vmo);
   close(fd);
   if (status != ZX_OK) {
     return NULL;
diff --git a/runtime/bin/run_vm_tests.cc b/runtime/bin/run_vm_tests.cc
index 31ecf76..d5d6ff0 100644
--- a/runtime/bin/run_vm_tests.cc
+++ b/runtime/bin/run_vm_tests.cc
@@ -165,7 +165,6 @@
       DART_KERNEL_ISOLATE_NAME, main, isolate_snapshot_data,
       isolate_snapshot_instructions, flags, isolate_data, error);
   if (isolate == NULL) {
-    *error = strdup("Failed to create isolate");
     delete isolate_data;
     return NULL;
   }
diff --git a/runtime/lib/bigint_patch.dart b/runtime/lib/bigint_patch.dart
index 08bcf47..331dd25 100644
--- a/runtime/lib/bigint_patch.dart
+++ b/runtime/lib/bigint_patch.dart
@@ -540,6 +540,7 @@
   /// Note: This function may be intrinsified.
   static void _lsh(
       Uint32List xDigits, int xUsed, int n, Uint32List resultDigits) {
+    assert(xUsed > 0);
     final digitShift = n ~/ _digitBits;
     final bitShift = n % _digitBits;
     final carryBitShift = _digitBits - bitShift;
@@ -569,6 +570,7 @@
     if (shiftAmount < 0) {
       throw new ArgumentError("shift-amount must be positive $shiftAmount");
     }
+    if (_isZero) return this;
     final digitShift = shiftAmount ~/ _digitBits;
     final bitShift = shiftAmount % _digitBits;
     if (bitShift == 0) {
@@ -611,6 +613,7 @@
   /// Note: This function may be intrinsified.
   static void _rsh(
       Uint32List xDigits, int xUsed, int n, Uint32List resultDigits) {
+    assert(xUsed > 0);
     final digitsShift = n ~/ _digitBits;
     final bitShift = n % _digitBits;
     final carryBitShift = _digitBits - bitShift;
@@ -638,6 +641,7 @@
     if (shiftAmount < 0) {
       throw new ArgumentError("shift-amount must be positive $shiftAmount");
     }
+    if (_isZero) return this;
     final digitShift = shiftAmount ~/ _digitBits;
     final bitShift = shiftAmount % _digitBits;
     if (bitShift == 0) {
@@ -902,6 +906,7 @@
    */
   _BigIntImpl operator &(BigInt bigInt) {
     _BigIntImpl other = bigInt;
+    if (_isZero || other._isZero) return zero;
     if (_isNegative == other._isNegative) {
       if (_isNegative) {
         // (-this) & (-other) == ~(this-1) & ~(other-1)
@@ -941,6 +946,8 @@
    */
   _BigIntImpl operator |(BigInt bigInt) {
     _BigIntImpl other = bigInt;
+    if (_isZero) return other;
+    if (other._isZero) return this;
     if (_isNegative == other._isNegative) {
       if (_isNegative) {
         // (-this) | (-other) == ~(this-1) | ~(other-1)
@@ -981,6 +988,8 @@
    */
   _BigIntImpl operator ^(BigInt bigInt) {
     _BigIntImpl other = bigInt;
+    if (_isZero) return other;
+    if (other._isZero) return this;
     if (_isNegative == other._isNegative) {
       if (_isNegative) {
         // (-this) ^ (-other) == ~(this-1) ^ ~(other-1) == (this-1) ^ (other-1)
@@ -1015,6 +1024,7 @@
    * This maps any integer `x` to `-x - 1`.
    */
   _BigIntImpl operator ~() {
+    if (_isZero) return _minusOne;
     if (_isNegative) {
       // ~(-this) == ~(~(this-1)) == this-1
       return _absSubSetSign(one, false);
@@ -1027,6 +1037,8 @@
   /// Addition operator.
   _BigIntImpl operator +(BigInt bigInt) {
     _BigIntImpl other = bigInt;
+    if (_isZero) return other;
+    if (other._isZero) return this;
     var isNegative = _isNegative;
     if (isNegative == other._isNegative) {
       // this + other == this + other
@@ -1044,6 +1056,8 @@
   /// Subtraction operator.
   _BigIntImpl operator -(BigInt bigInt) {
     _BigIntImpl other = bigInt;
+    if (_isZero) return -other;
+    if (other._isZero) return this;
     var isNegative = _isNegative;
     if (isNegative != other._isNegative) {
       // this - (-other) == this + other
diff --git a/runtime/platform/utils.h b/runtime/platform/utils.h
index bd8e1ab..2917008 100644
--- a/runtime/platform/utils.h
+++ b/runtime/platform/utils.h
@@ -286,6 +286,12 @@
   static uint32_t HostToLittleEndian32(uint32_t host_value);
   static uint64_t HostToLittleEndian64(uint64_t host_value);
 
+  static uint32_t BigEndianToHost32(uint32_t be_value) {
+    // Going between Host <-> BE is the same operation for all practical
+    // purposes.
+    return HostToBigEndian32(be_value);
+  }
+
   static bool DoublesBitEqual(const double a, const double b) {
     return bit_cast<int64_t, double>(a) == bit_cast<int64_t, double>(b);
   }
diff --git a/runtime/tests/vm/dart/regress32597_test.dart b/runtime/tests/vm/dart/regress32597_test.dart
new file mode 100644
index 0000000..969af09
--- /dev/null
+++ b/runtime/tests/vm/dart/regress32597_test.dart
@@ -0,0 +1,40 @@
+// Copyright (c) 2018, 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.
+
+// Regression test for dartbug.com/32597: incorrect type was assigned to phi
+// in strong mode.
+
+// VMOptions=--optimization_counter_threshold=10 --no-background-compilation
+
+class Token {
+  Token next;
+}
+
+class StringToken extends Token {}
+
+class ErrorToken extends Token {}
+
+void foo(Token tokens) {
+  Token current = tokens;
+  for (int i = 0; i < 1; i++) {
+    while (current is ErrorToken) {
+      ErrorToken first = current;
+      // Loading phi (created for local variable 'current') from another local
+      // variable ('first') with more specific type should not change the type
+      // assigned to phi.
+      print(first);
+    }
+    current = current.next;
+  }
+}
+
+void main() {
+  Token token = new StringToken();
+  token.next = token;
+
+  for (int i = 0; i < 100; i++) {
+    foo(token);
+  }
+  print('ok');
+}
diff --git a/runtime/tests/vm/vm.status b/runtime/tests/vm/vm.status
index 983023c..0d9f1cd 100644
--- a/runtime/tests/vm/vm.status
+++ b/runtime/tests/vm/vm.status
@@ -64,9 +64,9 @@
 dart/redirection_type_shuffling_test/none: RuntimeError
 
 [ $compiler != dartk ]
-cc/IsolateReload_KernelIncrementalCompile: Skip
-cc/IsolateReload_KernelIncrementalCompileAppAndLib: Skip
-cc/IsolateReload_KernelIncrementalCompileGenerics: Skip
+cc/IsolateReload_KernelIncrementalCompile: SkipByDesign
+cc/IsolateReload_KernelIncrementalCompileAppAndLib: SkipByDesign
+cc/IsolateReload_KernelIncrementalCompileGenerics: SkipByDesign
 cc/Mixin_PrivateSuperResolution: Skip
 cc/Mixin_PrivateSuperResolutionCrossLibraryShouldFail: Skip
 
@@ -77,7 +77,7 @@
 dart/byte_array_test: Skip # Incompatible flag --disable_alloc_stubs_after_gc
 
 [ $mode == debug ]
-cc/CorelibIsolateStartup: Skip # This is a benchmark that is not informative in debug mode.
+cc/CorelibIsolateStartup: SkipByDesign # This is a benchmark that is not informative in debug mode.
 cc/VerifyExplicit_Crash: Crash # Negative tests of VerifiedMemory should crash iff in DEBUG mode. TODO(koda): Improve support for negative tests.
 cc/VerifyImplicit_Crash: Crash # Negative tests of VerifiedMemory should crash iff in DEBUG mode. TODO(koda): Improve support for negative tests.
 dart/spawn_shutdown_test: Pass, Slow # VM Shutdown test, It can take some time for all the isolates to shutdown in a Debug build.
@@ -88,8 +88,8 @@
 [ $runtime != vm ]
 dart/hello_fuchsia_test: SkipByDesign # This is a test for fuchsia OS
 dart/snapshot_version_test: SkipByDesign # Spawns processes
-dart/spawn_infinite_loop_test: Skip # VM shutdown test
-dart/spawn_shutdown_test: Skip # VM Shutdown test
+dart/spawn_infinite_loop_test: SkipByDesign # VM shutdown test
+dart/spawn_shutdown_test: SkipByDesign # VM Shutdown test
 
 [ $system == fuchsia ]
 cc/CorelibIsolateStartup: Skip # OOM crash can bring down the OS.
@@ -142,7 +142,6 @@
 *: Skip # Issue 28649
 
 [ $compiler == dartk && $mode == debug && $runtime == vm ]
-cc/InjectNativeFields1: Crash
 cc/PrintJSON: Crash
 cc/Service_TokenStream: Crash
 
@@ -154,16 +153,12 @@
 
 [ $compiler == dartk && $mode == release && $runtime == vm ]
 cc/CorelibIsolateStartup: Timeout, Pass
-cc/InjectNativeFields1: Fail
 cc/Service_TokenStream: Fail
 
 [ $compiler == dartk && $runtime == vm ]
 cc/CanonicalizationInScriptSnapshots: Fail
 cc/Class_ComputeEndTokenPos: Crash
-cc/DartAPI_CurrentStackTraceInfo: Fail
-cc/DartAPI_InjectNativeFields1: Skip
 cc/DartAPI_InvokeNoSuchMethod: Fail
-cc/DartAPI_Invoke_CrossLibrary: Crash
 cc/DartAPI_IsolateSetCheckedMode: Skip # Checked mode is not relevant for dart 2?
 cc/DartAPI_IsolateShutdownRunDartCode: Skip # Flaky
 cc/DartAPI_LazyLoadDeoptimizes: Fail
@@ -175,10 +170,7 @@
 cc/DartAPI_LoadPatchSignatureMismatch: Crash
 cc/DartAPI_LoadSource: Crash
 cc/DartAPI_LoadSource_LateLoad: Crash
-cc/DartAPI_LookupLibrary: Crash
-cc/DartAPI_NativeFieldAccess: Fail
 cc/DartAPI_ParsePatchLibrary: Crash
-cc/DartAPI_PropagateError: Fail
 cc/DartAPI_StackOverflowStackTraceInfoArrowFunction: Fail
 cc/DartAPI_StackOverflowStackTraceInfoBraceFunction1: Fail
 cc/DartAPI_StackOverflowStackTraceInfoBraceFunction2: Fail
@@ -195,12 +187,6 @@
 cc/GenerateSource: Skip # Cannot generate source from a kernel binary.
 cc/IsolateReload_NotTypedefToTypedef: Fail
 cc/IsolateReload_TypedefToNotTypedef: Fail
-cc/Parser_AllocateVariables_CaptureLoopVar: Fail
-cc/Parser_AllocateVariables_CapturedVar: Fail
-cc/Parser_AllocateVariables_Issue7681: Fail
-cc/Parser_AllocateVariables_MiddleChain: Fail
-cc/Parser_AllocateVariables_NestedCapturedVar: Fail
-cc/Parser_AllocateVariables_TwoChains: Fail
 cc/Profiler_BasicSourcePositionOptimized: Skip
 cc/Profiler_BinaryOperatorSourcePositionOptimized: Skip
 cc/Profiler_GetSourceReport: Fail
@@ -245,11 +231,6 @@
 cc/IsolateReload_TearOff_AddArguments: Fail
 cc/IsolateReload_TearOff_Instance_Equality: Fail
 cc/IsolateReload_TearOff_List_Set: Fail
-cc/Parser_AllocateVariables_CaptureLoopVar: Crash
-cc/Parser_AllocateVariables_Issue7681: Crash
-cc/Parser_AllocateVariables_MiddleChain: Crash
-cc/Parser_AllocateVariables_NestedCapturedVar: Crash
-cc/Parser_AllocateVariables_TwoChains: Crash
 
 [ $compiler == dartk && $runtime == vm && $strong ]
 cc/IsolateReload_LibraryHide: Crash
@@ -279,14 +260,13 @@
 cc/DartAPI_NativePortPostInteger: Crash # Issue 32190
 cc/DartAPI_NativePortReceiveInteger: Timeout # Issue 32190
 cc/DartAPI_NativePortReceiveNull: Timeout # Issue 32190
-cc/DartAPI_NewNativePort: Crash,Timeout # Issue 32190
+cc/DartAPI_NewNativePort: Crash, Timeout # Issue 32190
 cc/DartGeneratedArrayLiteralMessages: Crash # Issue 32190
 cc/FullSnapshot1: Crash # Issue 32190
 cc/IsolateReload_LibraryImportAdded: Crash # Issue 32190
 cc/IsolateReload_LibraryImportRemoved: Fail # Issue 32190
 cc/IsolateReload_LibraryLookup: Fail, Crash # Issue 32190
 cc/Mixin_PrivateSuperResolutionCrossLibraryShouldFail: Fail, Crash # Issue 32190
-cc/StackMapGC: Crash # Issue 32190
 
 # Enabling of dartk for sim{arm,arm64,dbc64} revelaed these test failures, which
 # are to be triaged.  Isolate tests are skipped on purpose due to the usage of
@@ -363,6 +343,15 @@
 [ $compiler == dart2analyzer || $compiler == dart2js ]
 dart/data_uri*test: Skip # Data uri's not supported by dart2js or the analyzer.
 
+# Tests for VM parser aren't valid for Dart 2.
+[ $compiler == dartk || $compiler == dartkp ]
+cc/Parser_AllocateVariables_CaptureLoopVar: SkipByDesign
+cc/Parser_AllocateVariables_CapturedVar: SkipByDesign
+cc/Parser_AllocateVariables_Issue7681: SkipByDesign
+cc/Parser_AllocateVariables_MiddleChain: SkipByDesign
+cc/Parser_AllocateVariables_NestedCapturedVar: SkipByDesign
+cc/Parser_AllocateVariables_TwoChains: SkipByDesign
+
 [ $compiler == precompiler || $mode == product ]
 cc/CoreSnapshotSize: SkipByDesign # Imports dart:mirrors
 cc/CreateMirrorSystem: SkipByDesign # Imports dart:mirrors
diff --git a/runtime/vm/allocation.cc b/runtime/vm/allocation.cc
index 93ee9d0..b1a7e93 100644
--- a/runtime/vm/allocation.cc
+++ b/runtime/vm/allocation.cc
@@ -69,7 +69,9 @@
 }
 
 #if defined(DEBUG)
-NoSafepointScope::NoSafepointScope() : StackResource(Thread::Current()) {
+NoSafepointScope::NoSafepointScope(Thread* current_thread)
+    : StackResource(current_thread != nullptr ? current_thread
+                                              : Thread::Current()) {
   thread()->IncrementNoSafepointScopeDepth();
 }
 
diff --git a/runtime/vm/allocation.h b/runtime/vm/allocation.h
index 3442acf..b9af2f9 100644
--- a/runtime/vm/allocation.h
+++ b/runtime/vm/allocation.h
@@ -82,7 +82,7 @@
 #if defined(DEBUG)
 class NoSafepointScope : public StackResource {
  public:
-  NoSafepointScope();
+  explicit NoSafepointScope(Thread* thread = nullptr);
   ~NoSafepointScope();
 
  private:
@@ -91,7 +91,7 @@
 #else   // defined(DEBUG)
 class NoSafepointScope : public ValueObject {
  public:
-  NoSafepointScope() {}
+  explicit NoSafepointScope(Thread* thread = nullptr) {}
 
  private:
   DISALLOW_COPY_AND_ASSIGN(NoSafepointScope);
diff --git a/runtime/vm/code_descriptors_test.cc b/runtime/vm/code_descriptors_test.cc
index aaa7fc1..b67e93d 100644
--- a/runtime/vm/code_descriptors_test.cc
+++ b/runtime/vm/code_descriptors_test.cc
@@ -202,7 +202,7 @@
       "    return i + k; }"
       "  static int moo() {"
       "    var i = A.foo();"
-      "    Expect.equals(30, i);"
+      "    if (i != 30) throw '$i != 30';"
       "  }\n"
       "}\n";
   // First setup the script and compile the script.
diff --git a/runtime/vm/compiler/backend/flow_graph.cc b/runtime/vm/compiler/backend/flow_graph.cc
index febb84c..77ca3cb 100644
--- a/runtime/vm/compiler/backend/flow_graph.cc
+++ b/runtime/vm/compiler/backend/flow_graph.cc
@@ -1191,8 +1191,12 @@
 
           if ((phi != NULL) && isolate()->strong() &&
               FLAG_use_strong_mode_types) {
-            phi->UpdateType(
-                CompileType::FromAbstractType(load->local().type()));
+            // Assign type to phi only if phi was not copied from another local.
+            const auto* phis = phi->block()->phis();
+            if ((index < phis->length()) && ((*phis)[index] == phi)) {
+              phi->UpdateType(
+                  CompileType::FromAbstractType(load->local().type()));
+            }
           }
         } else if (drop != NULL) {
           // Drop temps from the environment.
diff --git a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
index 22f92eb..3a7ad08 100644
--- a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
+++ b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
@@ -8,6 +8,8 @@
 #include "vm/compiler/jit/compiler.h"
 #include "vm/longjump.h"
 #include "vm/object_store.h"
+#include "vm/resolver.h"
+#include "vm/stack_frame.h"
 
 #if !defined(DART_PRECOMPILED_RUNTIME)
 
@@ -18,6 +20,7 @@
 #define H (translation_helper_)
 #define T (type_translator_)
 #define I Isolate::Current()
+#define B (flow_graph_builder_)
 
 static bool IsFieldInitializer(const Function& function, Zone* zone) {
   return (function.kind() == RawFunction::kImplicitStaticFinalGetter) &&
@@ -217,6 +220,7 @@
       if (++next_read_ == field) return;
     case kFlags:
       flags_ = builder_->ReadFlags();
+      flags2_ = builder_->ReadFlags();
       if (++next_read_ == field) return;
     case kName:
       builder_->SkipName();  // read name.
@@ -1084,7 +1088,7 @@
     case RawFunction::kIrregexpFunction:
       UNREACHABLE();
   }
-  if (needs_expr_temp_) {
+  if (needs_expr_temp_ || parsed_function_->is_no_such_method_forwarder()) {
     scope_->AddVariable(parsed_function_->EnsureExpressionTemp());
   }
   parsed_function_->AllocateVariables();
@@ -3747,8 +3751,8 @@
   }
 }
 
-void StreamingFlowGraphBuilder::ReadUntilFunctionNode(
-    ParsedFunction* set_forwarding_stub) {
+bool StreamingFlowGraphBuilder::ReadUntilFunctionNode(
+    ParsedFunction* parsed_function) {
   const Tag tag = PeekTag();
   if (tag == kProcedure) {
     ProcedureHelper procedure_helper(this);
@@ -3757,17 +3761,22 @@
       // Running a procedure without a function node doesn't make sense.
       UNREACHABLE();
     }
-    if (set_forwarding_stub != NULL && flow_graph_builder_ &&
+    if (parsed_function != NULL && flow_graph_builder_ != nullptr &&
         procedure_helper.IsForwardingStub() && !procedure_helper.IsAbstract()) {
       ASSERT(procedure_helper.forwarding_stub_super_target_ != -1);
-      set_forwarding_stub->MarkForwardingStub(
+      parsed_function->MarkForwardingStub(
           procedure_helper.forwarding_stub_super_target_);
     }
+    if (parsed_function != NULL && flow_graph_builder_ != nullptr &&
+        procedure_helper.IsNoSuchMethodForwarder()) {
+      parsed_function->set_is_no_such_method_forwarder(true);
+    }
+    return procedure_helper.IsNoSuchMethodForwarder();
     // Now at start of FunctionNode.
   } else if (tag == kConstructor) {
     ConstructorHelper constructor_helper(this);
     constructor_helper.ReadUntilExcluding(ConstructorHelper::kFunction);
-    return;
+    return false;
     // Now at start of FunctionNode.
     // Notice that we also have a list of initializers after that!
   } else if (tag == kFunctionNode) {
@@ -3776,6 +3785,7 @@
     ReportUnexpectedTag("a procedure, a constructor or a function node", tag);
     UNREACHABLE();
   }
+  return false;
 }
 
 StringIndex StreamingFlowGraphBuilder::GetNameFromVariableDeclaration(
@@ -4322,6 +4332,219 @@
                 flow_graph_builder_->last_used_block_id_, prologue_info);
 }
 
+FlowGraph* StreamingFlowGraphBuilder::BuildGraphOfNoSuchMethodForwarder(
+    const Function& function,
+    bool is_implicit_closure_function) {
+  // The prologue builder needs the default parameter values.
+  SetupDefaultParameterValues();
+
+  TargetEntryInstr* normal_entry = B->BuildTargetEntry();
+  PrologueInfo prologue_info(-1, -1);
+  BlockEntryInstr* instruction_cursor =
+      B->BuildPrologue(normal_entry, &prologue_info);
+
+  B->graph_entry_ = new (Z) GraphEntryInstr(*parsed_function(), normal_entry,
+                                            Compiler::kNoOSRDeoptId);
+
+  Fragment body(instruction_cursor);
+  body += B->CheckStackOverflowInPrologue();
+
+  // If we are inside the tearoff wrapper function (implicit closure), we need
+  // to extract the receiver from the context. We just replace it directly on
+  // the stack to simplify the rest of the code.
+  if (is_implicit_closure_function) {
+    if (parsed_function()->has_arg_desc_var()) {
+      body += B->LoadArgDescriptor();
+      body += LoadField(ArgumentsDescriptor::count_offset());
+      body += LoadLocal(parsed_function()->current_context_var());
+      body += B->LoadField(Context::variable_offset(0));
+      body += B->StoreFpRelativeSlot(kWordSize * kParamEndSlotFromFp);
+      body += Drop();
+    } else {
+      body += LoadLocal(parsed_function()->current_context_var());
+      body += B->LoadField(Context::variable_offset(0));
+      body += B->StoreFpRelativeSlot(
+          kWordSize * (kParamEndSlotFromFp + function.NumParameters()));
+      body += Drop();
+    }
+  }
+
+  FunctionNodeHelper function_node_helper(this);
+  function_node_helper.ReadUntilExcluding(FunctionNodeHelper::kTypeParameters);
+
+  if (function.NeedsArgumentTypeChecks(I)) {
+    AlternativeReadingScope _(reader_);
+    body += BuildArgumentTypeChecks();
+  }
+
+  function_node_helper.ReadUntilExcluding(
+      FunctionNodeHelper::kPositionalParameters);
+
+  body += NullConstant();
+  LocalVariable* result = MakeTemporary();
+
+  // Do "++argument_count" if any type arguments were passed.
+  LocalVariable* argument_count_var = parsed_function()->expression_temp_var();
+  body += IntConstant(0);
+  body += StoreLocal(TokenPosition::kNoSource, argument_count_var);
+  body += Drop();
+  if (function.IsGeneric() && Isolate::Current()->reify_generic_functions()) {
+    Fragment test_generic;
+    JoinEntryInstr* join = BuildJoinEntry();
+
+    TargetEntryInstr *passed_type_args, *not_passed_type_args;
+    test_generic += B->LoadArgDescriptor();
+    test_generic += LoadField(ArgumentsDescriptor::type_args_len_offset());
+    test_generic += IntConstant(0);
+    test_generic += BranchIfEqual(&not_passed_type_args, &passed_type_args,
+                                  /*negate=*/false);
+
+    Fragment passed_type_args_frag(passed_type_args);
+    passed_type_args_frag += IntConstant(1);
+    passed_type_args_frag +=
+        StoreLocal(TokenPosition::kNoSource, argument_count_var);
+    passed_type_args_frag += Drop();
+    passed_type_args_frag += Goto(join);
+
+    Fragment not_passed_type_args_frag(not_passed_type_args);
+    not_passed_type_args_frag += Goto(join);
+
+    body += Fragment(test_generic.entry, join);
+  }
+
+  if (function.HasOptionalParameters()) {
+    body += B->LoadArgDescriptor();
+    body += LoadField(ArgumentsDescriptor::count_offset());
+  } else {
+    body += IntConstant(function.NumParameters());
+  }
+  body += LoadLocal(argument_count_var);
+  body += B->SmiBinaryOp(Token::kADD, /* truncate= */ true);
+  LocalVariable* argument_count = MakeTemporary();
+
+  // We are generating code like the following:
+  //
+  // var arguments = new Array<dynamic>(argument_count);
+  //
+  // for (int i = 0; i < argument_count; ++i) {
+  //   arguments[i] = LoadFpRelativeSlot(
+  //       kWordSize * (kParamEndSlotFromFp + argument_count - i));
+  // }
+  body += Constant(TypeArguments::ZoneHandle(Z, TypeArguments::null()));
+  body += LoadLocal(argument_count);
+  body += CreateArray();
+  LocalVariable* arguments = MakeTemporary();
+
+  {
+    // int i = 0
+    LocalVariable* index = parsed_function()->expression_temp_var();
+    body += IntConstant(0);
+    body += StoreLocal(TokenPosition::kNoSource, index);
+    body += Drop();
+
+    TargetEntryInstr* body_entry;
+    TargetEntryInstr* loop_exit;
+
+    Fragment condition;
+    // i < argument_count
+    condition += LoadLocal(index);
+    condition += LoadLocal(argument_count);
+    condition += B->SmiRelationalOp(Token::kLT);
+    condition += BranchIfTrue(&body_entry, &loop_exit, /*negate=*/false);
+
+    Fragment loop_body(body_entry);
+
+    // arguments[i] = LoadFpRelativeSlot(
+    //     kWordSize * (kParamEndSlotFromFp + argument_count - i));
+    loop_body += LoadLocal(arguments);
+    loop_body += LoadLocal(index);
+    loop_body += LoadLocal(argument_count);
+    loop_body += LoadLocal(index);
+    loop_body += B->SmiBinaryOp(Token::kSUB, /*truncate=*/true);
+    loop_body += B->LoadFpRelativeSlot(kWordSize * kParamEndSlotFromFp);
+    loop_body += StoreIndexed(kArrayCid);
+    loop_body += Drop();
+
+    // ++i
+    loop_body += LoadLocal(index);
+    loop_body += IntConstant(1);
+    loop_body += B->SmiBinaryOp(Token::kADD, /*truncate=*/true);
+    loop_body += StoreLocal(TokenPosition::kNoSource, index);
+    loop_body += Drop();
+
+    JoinEntryInstr* join = BuildJoinEntry();
+    loop_body += Goto(join);
+
+    Fragment loop(join);
+    loop += condition;
+
+    Instruction* entry =
+        new (Z) GotoInstr(join, Thread::Current()->GetNextDeoptId());
+    body += Fragment(entry, loop_exit);
+  }
+
+  // Load receiver.
+  if (is_implicit_closure_function) {
+    body += LoadLocal(parsed_function()->current_context_var());
+    body += B->LoadField(Context::variable_offset(0));
+  } else {
+    LocalScope* scope = parsed_function()->node_sequence()->scope();
+    body += LoadLocal(scope->VariableAt(0));
+  }
+  body += PushArgument();
+
+  body += Constant(String::ZoneHandle(Z, function.name()));
+  body += PushArgument();
+
+  if (!parsed_function()->has_arg_desc_var()) {
+    // If there is no variable for the arguments descriptor (this function's
+    // signature doesn't require it), then we need to create one.
+    Array& args_desc = Array::ZoneHandle(
+        Z, ArgumentsDescriptor::New(0, function.NumParameters()));
+    body += Constant(args_desc);
+  } else {
+    body += B->LoadArgDescriptor();
+  }
+  body += PushArgument();
+
+  body += LoadLocal(arguments);
+  body += PushArgument();
+
+  // false -> this is not super NSM
+  body += Constant(Bool::False());
+  body += PushArgument();
+
+  const Class& mirror_class =
+      Class::Handle(Z, Library::LookupCoreClass(Symbols::InvocationMirror()));
+  ASSERT(!mirror_class.IsNull());
+  const Function& allocation_function = Function::ZoneHandle(
+      Z, mirror_class.LookupStaticFunction(
+             Library::PrivateCoreLibName(Symbols::AllocateInvocationMirror())));
+  ASSERT(!allocation_function.IsNull());
+  body += StaticCall(TokenPosition::kMinSource, allocation_function,
+                     /* argument_count = */ 4, ICData::kStatic);
+  body += PushArgument();  // For the call to noSuchMethod.
+
+  body += InstanceCall(TokenPosition::kNoSource, Symbols::NoSuchMethod(),
+                       Token::kILLEGAL, 2, 1);
+  body += StoreLocal(TokenPosition::kNoSource, result);
+  body += Drop();
+
+  body += Drop();  // arguments
+  body += Drop();  // argument count
+
+  AbstractType& return_type = AbstractType::Handle(function.result_type());
+  if (!return_type.IsDynamicType() && !return_type.IsVoidType() &&
+      !return_type.IsObjectType()) {
+    body += flow_graph_builder_->AssertAssignable(
+        TokenPosition::kNoSource, return_type, Symbols::Empty());
+  }
+  body += Return(TokenPosition::kNoSource);
+
+  return new (Z) FlowGraph(*parsed_function(), B->graph_entry_,
+                           B->last_used_block_id_, prologue_info);
+}
+
 Fragment StreamingFlowGraphBuilder::BuildArgumentTypeChecks(
     TypeChecksToBuild mode /*= kDefaultTypeChecks*/) {
   FunctionNodeHelper function_node_helper(this);
@@ -4783,6 +5006,18 @@
   ActiveMemberScope active_member(active_class(), &outermost_function);
   ActiveTypeParametersScope active_type_params(active_class(), function, Z);
 
+  SetOffset(kernel_offset);
+
+  // We need to read out the NSM-forwarder bit before we can build scopes.
+  switch (function.kind()) {
+    case RawFunction::kImplicitClosureFunction:
+    case RawFunction::kRegularFunction: {
+      AlternativeReadingScope alt(reader_);
+      ReadUntilFunctionNode(parsed_function());  // read until function node.
+    }
+    default: {}
+  }
+
   // The IR builder will create its own local variables and scopes, and it
   // will not need an AST.  The code generator will assume that there is a
   // local variable stack slot allocated for the current context and (I
@@ -4790,19 +5025,21 @@
   // requires allocating an unused expression temporary variable.
   set_scopes(parsed_function()->EnsureKernelScopes());
 
-  SetOffset(kernel_offset);
-
   switch (function.kind()) {
-    case RawFunction::kClosureFunction:
-    case RawFunction::kImplicitClosureFunction:
-    case RawFunction::kConvertedClosureFunction:
     case RawFunction::kRegularFunction:
+    case RawFunction::kImplicitClosureFunction:
+      if (ReadUntilFunctionNode(parsed_function())) {
+        return BuildGraphOfNoSuchMethodForwarder(
+            function, function.IsImplicitClosureFunction());
+      } else if (function.IsImplicitClosureFunction()) {
+        return BuildGraphOfImplicitClosureFunction(function);
+      }
+    // fallthrough intended
+    case RawFunction::kClosureFunction:
+    case RawFunction::kConvertedClosureFunction:
     case RawFunction::kGetterFunction:
     case RawFunction::kSetterFunction: {
       ReadUntilFunctionNode(parsed_function());  // read until function node.
-      if (function.IsImplicitClosureFunction()) {
-        return BuildGraphOfImplicitClosureFunction(function);
-      }
       return BuildGraphOfFunction(false);
     }
     case RawFunction::kConstructor: {
diff --git a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h
index 40d1d89..7db1719 100644
--- a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h
+++ b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h
@@ -276,6 +276,10 @@
     kRedirectingFactoryConstructor = 1 << 7,
   };
 
+  enum Flag2 {
+    kNoSuchMethodForwarder = 1 << 0,
+  };
+
   explicit ProcedureHelper(StreamingFlowGraphBuilder* builder) {
     builder_ = builder;
     next_read_ = kStart;
@@ -298,12 +302,16 @@
   bool IsRedirectingFactoryConstructor() {
     return (flags_ & kRedirectingFactoryConstructor) != 0;
   }
+  bool IsNoSuchMethodForwarder() {
+    return (flags2_ & kNoSuchMethodForwarder) != 0;
+  }
 
   NameIndex canonical_name_;
   TokenPosition position_;
   TokenPosition end_position_;
   Kind kind_;
   uint8_t flags_;
+  uint8_t flags2_;
   intptr_t source_uri_index_;
   intptr_t annotation_count_;
 
@@ -1042,7 +1050,9 @@
   // If a 'ParsedFunction' is provided for 'set_forwarding_stub', this method
   // will attach the forwarding stub target reference to the parsed function if
   // it crosses a procedure node for a concrete forwarding stub.
-  void ReadUntilFunctionNode(ParsedFunction* set_forwarding_stub = NULL);
+  //
+  // Returns 'true' if discovered a no-such-method forwarder.
+  bool ReadUntilFunctionNode(ParsedFunction* set_forwarding_stub = NULL);
   intptr_t ReadListLength();
 
   enum DispatchCategory { Interface, ViaThis, Closure, DynamicDispatch };
@@ -1071,7 +1081,9 @@
   Fragment BuildInitializers(const Class& parent_class);
   FlowGraph* BuildGraphOfImplicitClosureFunction(const Function& function);
   FlowGraph* BuildGraphOfFunction(bool constructor);
-  FlowGraph* BuildGraphOfForwardingStub(const Function& function);
+  FlowGraph* BuildGraphOfNoSuchMethodForwarder(
+      const Function& function,
+      bool is_implicit_closure_function);
 
   intptr_t GetOffsetForSourceInfo(intptr_t index);
 
@@ -1156,8 +1168,10 @@
   const TypeArguments& PeekArgumentsInstantiatedType(const Class& klass);
   intptr_t PeekArgumentsCount();
 
-  LocalVariable* LookupVariable(intptr_t kernel_offset);
+  // See BaseFlowGraphBuilder::MakeTemporary.
   LocalVariable* MakeTemporary();
+
+  LocalVariable* LookupVariable(intptr_t kernel_offset);
   RawFunction* LookupMethodByMember(NameIndex target,
                                     const String& method_name);
   Function& FindMatchingFunctionAnyArgs(const Class& klass, const String& name);
diff --git a/runtime/vm/compiler/frontend/kernel_to_il.cc b/runtime/vm/compiler/frontend/kernel_to_il.cc
index 2e5356c..a354661 100644
--- a/runtime/vm/compiler/frontend/kernel_to_il.cc
+++ b/runtime/vm/compiler/frontend/kernel_to_il.cc
@@ -1457,7 +1457,7 @@
   ArgumentArray arguments = GetArguments(num_args);
   NativeCallInstr* call =
       new (Z) NativeCallInstr(name, function, FLAG_link_natives_lazily,
-                              TokenPosition::kNoSource, arguments);
+                              function->end_token_pos(), arguments);
   Push(call);
   return Fragment(call);
 }
@@ -2724,7 +2724,7 @@
 }
 
 static void ProcessTokenPositionsEntry(
-    const TypedData& data,
+    const TypedData& kernel_data,
     const Script& script,
     const Script& entry_script,
     intptr_t kernel_offset,
@@ -2733,24 +2733,22 @@
     TranslationHelper* helper,
     GrowableArray<intptr_t>* token_positions,
     GrowableArray<intptr_t>* yield_positions) {
-  if (data.IsNull() ||
-      script.kernel_string_offsets() != entry_script.kernel_string_offsets()) {
+  if (kernel_data.IsNull()) {
     return;
   }
 
   StreamingFlowGraphBuilder streaming_flow_graph_builder(
-      helper, script, zone_, data, data_kernel_offset);
+      helper, script, zone_, kernel_data, data_kernel_offset);
   streaming_flow_graph_builder.CollectTokenPositionsFor(
       script.kernel_script_index(), entry_script.kernel_script_index(),
       kernel_offset, token_positions, yield_positions);
 }
 
-void CollectTokenPositionsFor(const Script& const_script) {
+void CollectTokenPositionsFor(const Script& interesting_script) {
   Thread* thread = Thread::Current();
   Zone* zone_ = thread->zone();
-  Script& script = Script::Handle(Z, const_script.raw());
   TranslationHelper helper(thread);
-  helper.InitFromScript(script);
+  helper.InitFromScript(interesting_script);
 
   GrowableArray<intptr_t> token_positions(10);
   GrowableArray<intptr_t> yield_positions(1);
@@ -2759,9 +2757,13 @@
   const GrowableObjectArray& libs =
       GrowableObjectArray::Handle(Z, isolate->object_store()->libraries());
   Library& lib = Library::Handle(Z);
-  Object& entry = Object::Handle();
+  Object& entry = Object::Handle(Z);
   Script& entry_script = Script::Handle(Z);
   TypedData& data = TypedData::Handle(Z);
+
+  auto& temp_array = Array::Handle(Z);
+  auto& temp_field = Field::Handle(Z);
+  auto& temp_function = Function::Handle(Z);
   for (intptr_t i = 0; i < libs.Length(); i++) {
     lib ^= libs.At(i);
     DictionaryIterator it(lib);
@@ -2770,40 +2772,41 @@
       data = TypedData::null();
       if (entry.IsClass()) {
         const Class& klass = Class::Cast(entry);
-        entry_script = klass.script();
-        if (!entry_script.IsNull() &&
-            (script.kernel_script_index() ==
-             entry_script.kernel_script_index()) &&
-            (script.kernel_string_offsets() ==
-             entry_script.kernel_string_offsets())) {
+        if (klass.script() == interesting_script.raw()) {
           token_positions.Add(klass.token_pos().value());
         }
         if (klass.is_finalized()) {
-          Array& array = Array::Handle(Z, klass.fields());
-          Field& field = Field::Handle(Z);
-          for (intptr_t i = 0; i < array.Length(); ++i) {
-            field ^= array.At(i);
-            if (field.kernel_offset() <= 0) {
+          temp_array = klass.fields();
+          for (intptr_t i = 0; i < temp_array.Length(); ++i) {
+            temp_field ^= temp_array.At(i);
+            if (temp_field.kernel_offset() <= 0) {
               // Skip artificially injected fields.
               continue;
             }
-            data = field.KernelData();
-            entry_script = field.Script();
-            ProcessTokenPositionsEntry(
-                data, script, entry_script, field.kernel_offset(),
-                field.KernelDataProgramOffset(), Z, &helper, &token_positions,
-                &yield_positions);
+            entry_script = temp_field.Script();
+            if (entry_script.raw() != interesting_script.raw()) {
+              continue;
+            }
+            data = temp_field.KernelData();
+            ProcessTokenPositionsEntry(data, interesting_script, entry_script,
+                                       temp_field.kernel_offset(),
+                                       temp_field.KernelDataProgramOffset(), Z,
+                                       &helper, &token_positions,
+                                       &yield_positions);
           }
-          array = klass.functions();
-          Function& function = Function::Handle(Z);
-          for (intptr_t i = 0; i < array.Length(); ++i) {
-            function ^= array.At(i);
-            data = function.KernelData();
-            entry_script = function.script();
-            ProcessTokenPositionsEntry(
-                data, script, entry_script, function.kernel_offset(),
-                function.KernelDataProgramOffset(), Z, &helper,
-                &token_positions, &yield_positions);
+          temp_array = klass.functions();
+          for (intptr_t i = 0; i < temp_array.Length(); ++i) {
+            temp_function ^= temp_array.At(i);
+            entry_script = temp_function.script();
+            if (entry_script.raw() != interesting_script.raw()) {
+              continue;
+            }
+            data = temp_function.KernelData();
+            ProcessTokenPositionsEntry(data, interesting_script, entry_script,
+                                       temp_function.kernel_offset(),
+                                       temp_function.KernelDataProgramOffset(),
+                                       Z, &helper, &token_positions,
+                                       &yield_positions);
           }
         } else {
           // Class isn't finalized yet: read the data attached to it.
@@ -2815,17 +2818,24 @@
           const intptr_t class_offset = klass.kernel_offset();
 
           entry_script = klass.script();
-          ProcessTokenPositionsEntry(data, script, entry_script, class_offset,
-                                     library_kernel_offset, Z, &helper,
-                                     &token_positions, &yield_positions);
+          if (entry_script.raw() != interesting_script.raw()) {
+            continue;
+          }
+          ProcessTokenPositionsEntry(data, interesting_script, entry_script,
+                                     class_offset, library_kernel_offset, Z,
+                                     &helper, &token_positions,
+                                     &yield_positions);
         }
       } else if (entry.IsFunction()) {
-        const Function& function = Function::Cast(entry);
-        data = function.KernelData();
-        entry_script = function.script();
-        ProcessTokenPositionsEntry(data, script, entry_script,
-                                   function.kernel_offset(),
-                                   function.KernelDataProgramOffset(), Z,
+        temp_function ^= entry.raw();
+        entry_script = temp_function.script();
+        if (entry_script.raw() != interesting_script.raw()) {
+          continue;
+        }
+        data = temp_function.KernelData();
+        ProcessTokenPositionsEntry(data, interesting_script, entry_script,
+                                   temp_function.kernel_offset(),
+                                   temp_function.KernelDataProgramOffset(), Z,
                                    &helper, &token_positions, &yield_positions);
       } else if (entry.IsField()) {
         const Field& field = Field::Cast(entry);
@@ -2833,9 +2843,12 @@
           // Skip artificially injected fields.
           continue;
         }
-        data = field.KernelData();
         entry_script = field.Script();
-        ProcessTokenPositionsEntry(data, script, entry_script,
+        if (entry_script.raw() != interesting_script.raw()) {
+          continue;
+        }
+        data = field.KernelData();
+        ProcessTokenPositionsEntry(data, interesting_script, entry_script,
                                    field.kernel_offset(),
                                    field.KernelDataProgramOffset(), Z, &helper,
                                    &token_positions, &yield_positions);
@@ -2843,6 +2856,7 @@
     }
   }
 
+  Script& script = Script::Handle(Z, interesting_script.raw());
   Array& array_object = Array::Handle(Z);
   array_object = AsSortedDuplicateFreeArray(&token_positions);
   script.set_debug_positions(array_object);
diff --git a/runtime/vm/compiler/frontend/kernel_to_il.h b/runtime/vm/compiler/frontend/kernel_to_il.h
index cd5ffd4..50c607c 100644
--- a/runtime/vm/compiler/frontend/kernel_to_il.h
+++ b/runtime/vm/compiler/frontend/kernel_to_il.h
@@ -562,6 +562,25 @@
   // Drop given number of temps from the stack but preserve top of the stack.
   Fragment DropTempsPreserveTop(intptr_t num_temps_to_drop);
 
+  // Create a pseudo-local variable for a location on the expression stack.
+  // Note: SSA construction currently does not support inserting Phi functions
+  // for expression stack locations - only real local variables are supported.
+  // This means that you can't use MakeTemporary in a way that would require
+  // a Phi in SSA form. For example example below will be miscompiled or
+  // will crash debug VM with assertion when building SSA for optimizing 
+  // compiler:
+  //
+  //     t = MakeTemporary()
+  //     Branch B1 or B2
+  //     B1:
+  //       StoreLocal(t, v0)
+  //       goto B3
+  //     B2:
+  //       StoreLocal(t, v1)
+  //       goto B3
+  //     B3:
+  //       LoadLocal(t)
+  //
   LocalVariable* MakeTemporary();
 
   Fragment PushArgument();
diff --git a/runtime/vm/compiler/method_recognizer.h b/runtime/vm/compiler/method_recognizer.h
index 67ae5b3..1203498 100644
--- a/runtime/vm/compiler/method_recognizer.h
+++ b/runtime/vm/compiler/method_recognizer.h
@@ -146,14 +146,15 @@
   V(_Smi, ~, Smi_bitNegate, Smi, 0x67299f4f)                                   \
   V(_Smi, get:bitLength, Smi_bitLength, Smi, 0x25b3cb0a)                       \
   V(_Smi, _bitAndFromSmi, Smi_bitAndFromSmi, Smi, 0x562d5047)                  \
-  V(_Bigint, _lsh, Bigint_lsh, Dynamic, 0x7b99f80e)                            \
-  V(_Bigint, _rsh, Bigint_rsh, Dynamic, 0x5262b3a1)                            \
-  V(_Bigint, _absAdd, Bigint_absAdd, Dynamic, 0x07cad968)                      \
-  V(_Bigint, _absSub, Bigint_absSub, Dynamic, 0x1bf1bb4c)                      \
-  V(_Bigint, _mulAdd, Bigint_mulAdd, Dynamic, 0x229759b7)                      \
-  V(_Bigint, _sqrAdd, Bigint_sqrAdd, Dynamic, 0x5212b81f)                      \
-  V(_Bigint, _estQuotientDigit, Bigint_estQuotientDigit, Dynamic, 0x4dd342fe)  \
-  V(_Montgomery, _mulMod, Montgomery_mulMod, Dynamic, 0x17a515ac)              \
+  V(_BigIntImpl, _lsh, Bigint_lsh, Dynamic, 0x5b6cfc8b)                        \
+  V(_BigIntImpl, _rsh, Bigint_rsh, Dynamic, 0x6ff14a49)                        \
+  V(_BigIntImpl, _absAdd, Bigint_absAdd, Dynamic, 0x5bf14238)                  \
+  V(_BigIntImpl, _absSub, Bigint_absSub, Dynamic, 0x1de5bd32)                  \
+  V(_BigIntImpl, _mulAdd, Bigint_mulAdd, Smi, 0x6f277966)                      \
+  V(_BigIntImpl, _sqrAdd, Bigint_sqrAdd, Smi, 0x68e4c8ea)                      \
+  V(_BigIntImpl, _estimateQuotientDigit, Bigint_estQuotientDigit, Smi,         \
+    0x35456d91)                                                                \
+  V(_BigIntMontgomeryReduction, _mulMod, Montgomery_mulMod, Smi, 0x0f7b0375)   \
   V(_Double, >, Double_greaterThan, Bool, 0x4f1375a3)                          \
   V(_Double, >=, Double_greaterEqualThan, Bool, 0x4260c184)                    \
   V(_Double, <, Double_lessThan, Bool, 0x365d1eba)                             \
@@ -460,14 +461,14 @@
   V(::, sin, MathSin, 0x6b7bd98c)                                              \
   V(::, sqrt, MathSqrt, 0x70482cf3)                                            \
   V(::, tan, MathTan, 0x3bcd772a)                                              \
-  V(_Bigint, _lsh, Bigint_lsh, 0x7b99f80e)                                     \
-  V(_Bigint, _rsh, Bigint_rsh, 0x5262b3a1)                                     \
-  V(_Bigint, _absAdd, Bigint_absAdd, 0x07cad968)                               \
-  V(_Bigint, _absSub, Bigint_absSub, 0x1bf1bb4c)                               \
-  V(_Bigint, _mulAdd, Bigint_mulAdd, 0x229759b7)                               \
-  V(_Bigint, _sqrAdd, Bigint_sqrAdd, 0x5212b81f)                               \
-  V(_Bigint, _estQuotientDigit, Bigint_estQuotientDigit, 0x4dd342fe)           \
-  V(_Montgomery, _mulMod, Montgomery_mulMod, 0x17a515ac)                       \
+  V(_BigIntImpl, _lsh, Bigint_lsh, 0x5b6cfc8b)                                 \
+  V(_BigIntImpl, _rsh, Bigint_rsh, 0x6ff14a49)                                 \
+  V(_BigIntImpl, _absAdd, Bigint_absAdd, 0x5bf14238)                           \
+  V(_BigIntImpl, _absSub, Bigint_absSub, 0x1de5bd32)                           \
+  V(_BigIntImpl, _mulAdd, Bigint_mulAdd, 0x6f277966)                           \
+  V(_BigIntImpl, _sqrAdd, Bigint_sqrAdd, 0x68e4c8ea)                           \
+  V(_BigIntImpl, _estimateQuotientDigit, Bigint_estQuotientDigit, 0x35456d91)  \
+  V(_BigIntMontgomeryReduction, _mulMod, Montgomery_mulMod, 0x0f7b0375)        \
   V(_Double, >, Double_greaterThan, 0x4f1375a3)                                \
   V(_Double, >=, Double_greaterEqualThan, 0x4260c184)                          \
   V(_Double, <, Double_lessThan, 0x365d1eba)                                   \
diff --git a/runtime/vm/dart_api_impl_test.cc b/runtime/vm/dart_api_impl_test.cc
index 2c6f781..728a7db 100644
--- a/runtime/vm/dart_api_impl_test.cc
+++ b/runtime/vm/dart_api_impl_test.cc
@@ -324,6 +324,8 @@
   intptr_t line_number = 0;
   intptr_t column_number = 0;
   const char* cstr = "";
+  const char* test_lib =
+      FLAG_use_dart_frontend ? "file:///test-lib" : "test-lib";
 
   // Top frame is inspectStack().
   Dart_ActivationFrame frame;
@@ -335,7 +337,7 @@
   Dart_StringToCString(function_name, &cstr);
   EXPECT_STREQ("inspectStack", cstr);
   Dart_StringToCString(script_url, &cstr);
-  EXPECT_STREQ("test-lib", cstr);
+  EXPECT_STREQ(test_lib, cstr);
   EXPECT_EQ(1, line_number);
   EXPECT_EQ(47, column_number);
 
@@ -348,7 +350,7 @@
   Dart_StringToCString(function_name, &cstr);
   EXPECT_STREQ("foo", cstr);
   Dart_StringToCString(script_url, &cstr);
-  EXPECT_STREQ("test-lib", cstr);
+  EXPECT_STREQ(test_lib, cstr);
   EXPECT_EQ(2, line_number);
   EXPECT_EQ(20, column_number);
 
@@ -363,7 +365,7 @@
     Dart_StringToCString(function_name, &cstr);
     EXPECT_STREQ("foo", cstr);
     Dart_StringToCString(script_url, &cstr);
-    EXPECT_STREQ("test-lib", cstr);
+    EXPECT_STREQ(test_lib, cstr);
     EXPECT_EQ(2, line_number);
     EXPECT_EQ(37, column_number);
   }
@@ -377,7 +379,7 @@
   Dart_StringToCString(function_name, &cstr);
   EXPECT_STREQ("testMain", cstr);
   Dart_StringToCString(script_url, &cstr);
-  EXPECT_STREQ("test-lib", cstr);
+  EXPECT_STREQ(test_lib, cstr);
   EXPECT_EQ(3, line_number);
   EXPECT_EQ(15, column_number);
 
@@ -551,22 +553,67 @@
   return reinterpret_cast<Dart_NativeFunction>(&PropagateErrorNative);
 }
 
-TEST_CASE(DartAPI_PropagateError) {
+TEST_CASE(DartAPI_PropagateCompileTimeError) {
   const char* kScriptChars =
       "raiseCompileError() {\n"
       "  return missing_semicolon\n"
       "}\n"
       "\n"
-      "void throwException() {\n"
-      "  throw new Exception('myException');\n"
-      "}\n"
-      "\n"
       "void nativeFunc(closure) native 'Test_nativeFunc';\n"
       "\n"
       "void Func1() {\n"
       "  nativeFunc(() => raiseCompileError());\n"
+      "}\n";
+  Dart_Handle lib =
+      TestCase::LoadTestScript(kScriptChars, &PropagateError_native_lookup);
+  Dart_Handle result;
+
+  // Use Dart_PropagateError to propagate the error.
+  use_throw_exception = false;
+  use_set_return = false;
+
+  result = Dart_Invoke(lib, NewString("Func1"), 0, NULL);
+  EXPECT(Dart_IsError(result));
+
+  if (FLAG_use_dart_frontend) {
+    EXPECT_SUBSTRING("Expected ';' before this.", Dart_GetError(result));
+  } else {
+    EXPECT_SUBSTRING("semicolon expected", Dart_GetError(result));
+  }
+
+  // Use Dart_SetReturnValue to propagate the error.
+  use_throw_exception = false;
+  use_set_return = true;
+
+  result = Dart_Invoke(lib, NewString("Func1"), 0, NULL);
+  EXPECT(Dart_IsError(result));
+  if (FLAG_use_dart_frontend) {
+    EXPECT_SUBSTRING("Expected ';' before this.", Dart_GetError(result));
+  } else {
+    EXPECT_SUBSTRING("semicolon expected", Dart_GetError(result));
+  }
+
+  // Use Dart_ThrowException to propagate the error.
+  use_throw_exception = true;
+  use_set_return = false;
+
+  result = Dart_Invoke(lib, NewString("Func1"), 0, NULL);
+  EXPECT(Dart_IsError(result));
+  if (FLAG_use_dart_frontend) {
+    EXPECT_SUBSTRING("Expected ';' before this.", Dart_GetError(result));
+  } else {
+    EXPECT_SUBSTRING("semicolon expected", Dart_GetError(result));
+  }
+}
+
+TEST_CASE(DartAPI_PropagateError) {
+  const char* kScriptChars =
+      "void throwException() {\n"
+      "  throw new Exception('myException');\n"
       "}\n"
       "\n"
+      "void nativeFunc(closure) native 'Test_nativeFunc';\n"
+      "\n"
       "void Func2() {\n"
       "  nativeFunc(() => throwException());\n"
       "}\n";
@@ -578,10 +625,6 @@
   use_throw_exception = false;
   use_set_return = false;
 
-  result = Dart_Invoke(lib, NewString("Func1"), 0, NULL);
-  EXPECT(Dart_IsError(result));
-  EXPECT_SUBSTRING("semicolon expected", Dart_GetError(result));
-
   result = Dart_Invoke(lib, NewString("Func2"), 0, NULL);
   EXPECT(Dart_IsError(result));
   EXPECT(Dart_ErrorHasException(result));
@@ -591,10 +634,6 @@
   use_throw_exception = false;
   use_set_return = true;
 
-  result = Dart_Invoke(lib, NewString("Func1"), 0, NULL);
-  EXPECT(Dart_IsError(result));
-  EXPECT_SUBSTRING("semicolon expected", Dart_GetError(result));
-
   result = Dart_Invoke(lib, NewString("Func2"), 0, NULL);
   EXPECT(Dart_IsError(result));
   EXPECT(Dart_ErrorHasException(result));
@@ -604,10 +643,6 @@
   use_throw_exception = true;
   use_set_return = false;
 
-  result = Dart_Invoke(lib, NewString("Func1"), 0, NULL);
-  EXPECT(Dart_IsError(result));
-  EXPECT_SUBSTRING("semicolon expected", Dart_GetError(result));
-
   result = Dart_Invoke(lib, NewString("Func2"), 0, NULL);
   EXPECT(Dart_IsError(result));
   EXPECT(Dart_ErrorHasException(result));
@@ -3931,57 +3966,6 @@
   return reinterpret_cast<Dart_NativeFunction>(&NativeFieldLookup);
 }
 
-TEST_CASE(DartAPI_InjectNativeFields1) {
-  const char* kScriptChars =
-      "class NativeFields extends NativeFieldsWrapper {\n"
-      "  NativeFields(int i, int j) : fld1 = i, fld2 = j {}\n"
-      "  int fld1;\n"
-      "  final int fld2;\n"
-      "  static int fld3;\n"
-      "  static const int fld4 = 10;\n"
-      "}\n"
-      "NativeFields testMain() {\n"
-      "  NativeFields obj = new NativeFields(10, 20);\n"
-      "  return obj;\n"
-      "}\n";
-  Dart_Handle result;
-
-  const int kNumNativeFields = 4;
-
-  // Create a test library.
-  Dart_Handle lib =
-      TestCase::LoadTestScript(kScriptChars, NULL, USER_TEST_URI, false);
-
-  // Create a native wrapper class with native fields.
-  result = Dart_CreateNativeWrapperClass(lib, NewString("NativeFieldsWrapper"),
-                                         kNumNativeFields);
-  EXPECT_VALID(result);
-  result = Dart_FinalizeLoading(false);
-  EXPECT_VALID(result);
-
-  // Load up a test script in the test library.
-
-  // Invoke a function which returns an object of type NativeFields.
-  result = Dart_Invoke(lib, NewString("testMain"), 0, NULL);
-  EXPECT_VALID(result);
-  CHECK_API_SCOPE(thread);
-  HANDLESCOPE(thread);
-  Instance& obj = Instance::Handle();
-  obj ^= Api::UnwrapHandle(result);
-  const Class& cls = Class::Handle(obj.clazz());
-  // We expect the newly created "NativeFields" object to have
-  // 2 dart instance fields (fld1, fld2) and a reference to the native fields.
-  // Hence the size of an instance of "NativeFields" should be
-  // (1 + 2) * kWordSize + size of object header.
-  // We check to make sure the instance size computed by the VM matches
-  // our expectations.
-  intptr_t header_size = sizeof(RawObject);
-  EXPECT_EQ(
-      Utils::RoundUp(((1 + 2) * kWordSize) + header_size, kObjectAlignment),
-      cls.instance_size());
-  EXPECT_EQ(kNumNativeFields, cls.num_native_fields());
-}
-
 TEST_CASE(DartAPI_InjectNativeFields2) {
   const char* kScriptChars =
       "class NativeFields extends NativeFieldsWrapper {\n"
@@ -4262,55 +4246,6 @@
   EXPECT_EQ(20, value);
 }
 
-TEST_CASE(DartAPI_NativeFieldAccess) {
-  const char* kScriptChars =
-      "class NativeFields extends NativeFieldsWrapper {\n"
-      "  NativeFields(int i, int j) : fld1 = i, fld2 = j {}\n"
-      "  int fld0;\n"
-      "  int fld1;\n"
-      "  final int fld2;\n"
-      "  static int fld3;\n"
-      "  static const int fld4 = 10;\n"
-      "}\n"
-      "NativeFields testMain() {\n"
-      "  NativeFields obj = new NativeFields(10, 20);\n"
-      "  return obj;\n"
-      "}\n";
-  const int kNumNativeFields = 4;
-
-  // Create a test library.
-  Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, native_field_lookup,
-                                             USER_TEST_URI, false);
-
-  // Create a native wrapper class with native fields.
-  Dart_Handle result = Dart_CreateNativeWrapperClass(
-      lib, NewString("NativeFieldsWrapper"), kNumNativeFields);
-  EXPECT_VALID(result);
-  result = Dart_FinalizeLoading(false);
-  EXPECT_VALID(result);
-
-  // Load up a test script in it.
-
-  // Invoke a function which returns an object of type NativeFields.
-  Dart_Handle retobj = Dart_Invoke(lib, NewString("testMain"), 0, NULL);
-  EXPECT_VALID(retobj);
-
-  // Now access and set various instance fields of the returned object.
-  TestNativeFields(retobj);
-
-  // Test that accessing an error handle propagates the error.
-  Dart_Handle error = Api::NewError("myerror");
-  intptr_t field_value = 0;
-
-  result = Dart_GetNativeInstanceField(error, 0, &field_value);
-  EXPECT(Dart_IsError(result));
-  EXPECT_STREQ("myerror", Dart_GetError(result));
-
-  result = Dart_SetNativeInstanceField(error, 0, 1);
-  EXPECT(Dart_IsError(result));
-  EXPECT_STREQ("myerror", Dart_GetError(result));
-}
-
 TEST_CASE(DartAPI_ImplicitNativeFieldAccess) {
   const char* kScriptChars =
       "import 'dart:nativewrappers';"
@@ -5127,15 +5062,11 @@
       "void _imported() {}\n";
 
   // Load lib1
-  Dart_Handle url = NewString("library1_url");
-  Dart_Handle source = NewString(kLibrary1Chars);
-  Dart_Handle lib1 = Dart_LoadLibrary(url, Dart_Null(), source, 0, 0);
+  Dart_Handle lib1 = TestCase::LoadTestLibrary("library1_url", kLibrary1Chars);
   EXPECT_VALID(lib1);
 
   // Load lib2
-  url = NewString("library2_url");
-  source = NewString(kLibrary2Chars);
-  Dart_Handle lib2 = Dart_LoadLibrary(url, Dart_Null(), source, 0, 0);
+  Dart_Handle lib2 = TestCase::LoadTestLibrary("library2_url", kLibrary2Chars);
   EXPECT_VALID(lib2);
 
   // Import lib2 from lib1
@@ -5785,23 +5716,38 @@
   const char* kScriptChars =
       "import 'library1_dart';"
       "main() {}";
+  const char* kLibrary1 = "file:///library1_dart";
   const char* kLibrary1Chars =
-      "library library1_dart;"
-      "import 'library2_dart';";
+      "library library1;"
+      "final x = 0;";
 
-  // Create a test library and Load up a test script in it.
-  Dart_Handle url = NewString(TestCase::url());
-  Dart_Handle source = NewString(kScriptChars);
-  Dart_Handle result = Dart_SetLibraryTagHandler(library_handler);
-  EXPECT_VALID(result);
-  result = Dart_LoadScript(url, Dart_Null(), source, 0, 0);
-  EXPECT_VALID(result);
+  Dart_Handle url;
+  Dart_Handle result;
 
-  url = NewString("library1_dart");
-  source = NewString(kLibrary1Chars);
-  result = Dart_LoadLibrary(url, Dart_Null(), source, 0, 0);
-  EXPECT_VALID(result);
+  // Create a test library and load up a test script in it.
+  if (FLAG_use_dart_frontend) {
+    TestCase::AddTestLib("file:///library1_dart", kLibrary1Chars);
+    // LoadTestScript resets the LibraryTagHandler, which we don't want when
+    // using the VM compiler, so we only use it with the Dart frontend for this
+    // test.
+    result = TestCase::LoadTestScript(kScriptChars, NULL, TestCase::url());
+    EXPECT_VALID(result);
+  } else {
+    Dart_Handle source = NewString(kScriptChars);
+    url = NewString(TestCase::url());
 
+    result = Dart_SetLibraryTagHandler(library_handler);
+    EXPECT_VALID(result);
+
+    result = Dart_LoadScript(url, Dart_Null(), source, 0, 0);
+    EXPECT_VALID(result);
+
+    url = NewString(kLibrary1);
+    source = NewString(kLibrary1Chars);
+    result = Dart_LoadLibrary(url, Dart_Null(), source, 0, 0);
+  }
+
+  url = NewString(kLibrary1);
   result = Dart_LookupLibrary(url);
   EXPECT_VALID(result);
 
diff --git a/runtime/vm/kernel_binary.h b/runtime/vm/kernel_binary.h
index 8f67d03..559d178 100644
--- a/runtime/vm/kernel_binary.h
+++ b/runtime/vm/kernel_binary.h
@@ -163,10 +163,15 @@
 class Reader {
  public:
   Reader(const uint8_t* buffer, intptr_t size)
-      : raw_buffer_(buffer), typed_data_(NULL), size_(size), offset_(0) {}
+      : thread_(NULL),
+        raw_buffer_(buffer),
+        typed_data_(NULL),
+        size_(size),
+        offset_(0) {}
 
   explicit Reader(const TypedData& typed_data)
-      : raw_buffer_(NULL),
+      : thread_(Thread::Current()),
+        raw_buffer_(NULL),
         typed_data_(&typed_data),
         size_(typed_data.IsNull() ? 0 : typed_data.Length()),
         offset_(0) {}
@@ -184,11 +189,13 @@
 
   uint32_t ReadUInt32At(intptr_t offset) const {
     ASSERT((size_ >= 4) && (offset >= 0) && (offset <= size_ - 4));
-
-    const uint8_t* buffer = this->buffer();
-    uint32_t value = (buffer[offset + 0] << 24) | (buffer[offset + 1] << 16) |
-                     (buffer[offset + 2] << 8) | (buffer[offset + 3] << 0);
-    return value;
+    uint32_t value;
+    if (raw_buffer_ != NULL) {
+      value = *reinterpret_cast<const uint32_t*>(raw_buffer_ + offset);
+    } else {
+      value = typed_data_->GetUint32(offset);
+    }
+    return Utils::BigEndianToHost32(value);
   }
 
   uint32_t ReadFromIndexNoReset(intptr_t end_offset,
@@ -323,14 +330,14 @@
   void CopyDataToVMHeap(const TypedData& typed_data,
                         intptr_t offset,
                         intptr_t size) {
-    NoSafepointScope no_safepoint;
+    NoSafepointScope no_safepoint(thread_);
     memmove(typed_data.DataAddr(0), buffer() + offset, size);
   }
 
   uint8_t* CopyDataIntoZone(Zone* zone, intptr_t offset, intptr_t length) {
     uint8_t* buffer_ = zone->Alloc<uint8_t>(length);
     {
-      NoSafepointScope no_safepoint;
+      NoSafepointScope no_safepoint(thread_);
       memmove(buffer_, buffer() + offset, length);
     }
     return buffer_;
@@ -341,10 +348,11 @@
     if (raw_buffer_ != NULL) {
       return raw_buffer_;
     }
-    NoSafepointScope no_safepoint;
+    NoSafepointScope no_safepoint(thread_);
     return reinterpret_cast<uint8_t*>(typed_data_->DataAddr(0));
   }
 
+  Thread* thread_;
   const uint8_t* raw_buffer_;
   const TypedData* typed_data_;
   intptr_t size_;
diff --git a/runtime/vm/kernel_isolate.cc b/runtime/vm/kernel_isolate.cc
index 829c764..5d2a12c 100644
--- a/runtime/vm/kernel_isolate.cc
+++ b/runtime/vm/kernel_isolate.cc
@@ -101,6 +101,8 @@
         OS::PrintErr(DART_KERNEL_ISOLATE_NAME ": Isolate creation error: %s\n",
                      error);
       }
+      free(error);
+      error = NULL;
       KernelIsolate::SetKernelIsolate(NULL);
       KernelIsolate::FinishedInitializing();
       return;
diff --git a/runtime/vm/kernel_loader.cc b/runtime/vm/kernel_loader.cc
index b2b6b26..490d3cd 100644
--- a/runtime/vm/kernel_loader.cc
+++ b/runtime/vm/kernel_loader.cc
@@ -1304,6 +1304,8 @@
   const String& name = H.DartProcedureName(procedure_helper.canonical_name_);
   bool is_method = in_class && !procedure_helper.IsStatic();
   bool is_abstract = procedure_helper.IsAbstract();
+  bool is_no_such_method_forwarder = procedure_helper.IsNoSuchMethodForwarder();
+
   bool is_external = procedure_helper.IsExternal();
   String* native_name = NULL;
   intptr_t annotation_count;
@@ -1377,13 +1379,20 @@
   }
   const Object& script_class =
       ClassForScriptAt(owner, procedure_helper.source_uri_index_);
+  RawFunction::Kind kind = GetFunctionType(procedure_helper.kind_);
+  is_no_such_method_forwarder &= kind == RawFunction::kRegularFunction;
   Function& function = Function::ZoneHandle(
-      Z, Function::New(name, GetFunctionType(procedure_helper.kind_),
+      Z, Function::New(name, kind,
                        !is_method,  // is_static
                        false,       // is_const
-                       is_abstract, is_external,
+                       is_abstract && !is_no_such_method_forwarder, is_external,
                        native_name != NULL,  // is_native
                        script_class, procedure_helper.position_));
+  if (is_no_such_method_forwarder) {
+    // Not inlinable yet because its implementation is generic against the call
+    // site in a way that makes assumptions about the stack frame layout.
+    function.set_is_inlinable(false);
+  }
   function.set_end_token_pos(procedure_helper.end_position_);
   functions_.Add(&function);
   function.set_kernel_offset(procedure_offset);
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index ad7d534..ea5328d 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -7191,7 +7191,9 @@
   // In strong mode, change covariant parameter types to Object in the implicit
   // closure of a method compiled by kernel.
   // The VM's parser erases covariant types immediately in strong mode.
-  if (thread->isolate()->strong() && !is_static() && (kernel_offset() > 0)) {
+  do {
+    if (is_static() || kernel_offset() == 0) break;
+
     const Script& function_script = Script::Handle(zone, script());
     kernel::TranslationHelper translation_helper(thread);
     kernel::StreamingFlowGraphBuilder builder(
@@ -7200,7 +7202,10 @@
     translation_helper.InitFromScript(function_script);
     builder.SetOffset(kernel_offset());
 
-    builder.ReadUntilFunctionNode();
+    closure_function.set_is_inlinable(!builder.ReadUntilFunctionNode(NULL));
+
+    if (!thread->isolate()->strong()) break;
+
     kernel::FunctionNodeHelper fn_helper(&builder);
 
     // Check the positional parameters, including the optional positional ones.
@@ -7231,7 +7236,7 @@
                                             object_type);
       }
     }
-  }
+  } while (false);
   const Type& signature_type =
       Type::Handle(zone, closure_function.SignatureType());
   if (!signature_type.IsFinalized()) {
diff --git a/runtime/vm/object.h b/runtime/vm/object.h
index 8946317..3581349 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -8168,8 +8168,10 @@
 
 #define TYPED_GETTER_SETTER(name, type)                                        \
   type Get##name(intptr_t byte_offset) const {                                 \
-    NoSafepointScope no_safepoint;                                             \
-    return ReadUnaligned(reinterpret_cast<type*>(DataAddr(byte_offset)));      \
+    ASSERT((byte_offset >= 0) &&                                               \
+           (byte_offset + static_cast<intptr_t>(sizeof(type)) - 1) <           \
+               LengthInBytes());                                               \
+    return ReadUnaligned(ReadOnlyDataAddr<type>(byte_offset));                 \
   }                                                                            \
   void Set##name(intptr_t byte_offset, type value) const {                     \
     NoSafepointScope no_safepoint;                                             \
@@ -8295,6 +8297,18 @@
   }
 
  private:
+  // Provides const access to non-pointer, non-aligned data within the object.
+  // Such access does not need a write barrier, but it is *not* GC-safe, since
+  // the object might move.
+  //
+  // Therefore this method is private and the call-sites in this class need to
+  // ensure the returned pointer does not escape.
+  template <typename FieldType>
+  const FieldType* ReadOnlyDataAddr(intptr_t byte_offset) const {
+    return reinterpret_cast<const FieldType*>((raw_ptr()->data()) +
+                                              byte_offset);
+  }
+
   static intptr_t element_size(intptr_t index) {
     ASSERT(0 <= index && index < kNumElementSizes);
     intptr_t size = element_size_table[index];
diff --git a/runtime/vm/parser.cc b/runtime/vm/parser.cc
index 7568b96..576a194 100644
--- a/runtime/vm/parser.cc
+++ b/runtime/vm/parser.cc
@@ -168,7 +168,8 @@
 }
 
 ParsedFunction::ParsedFunction(Thread* thread, const Function& function)
-    : thread_(thread),
+    : is_no_such_method_forwarder_(false),
+      thread_(thread),
       function_(function),
       code_(Code::Handle(zone(), function.unoptimized_code())),
       node_sequence_(NULL),
diff --git a/runtime/vm/parser.h b/runtime/vm/parser.h
index 12d0557..75baa8d 100644
--- a/runtime/vm/parser.h
+++ b/runtime/vm/parser.h
@@ -220,7 +220,17 @@
     return raw_parameters_[i];
   }
 
+  bool is_no_such_method_forwarder() const {
+    return is_no_such_method_forwarder_;
+  }
+
+  void set_is_no_such_method_forwarder(bool value) {
+    is_no_such_method_forwarder_ = value;
+  }
+
  private:
+  bool is_no_such_method_forwarder_;
+
   Thread* thread_;
   const Function& function_;
   Code& code_;
diff --git a/sdk/BUILD.gn b/sdk/BUILD.gn
index ed685d8..b3e25e2 100644
--- a/sdk/BUILD.gn
+++ b/sdk/BUILD.gn
@@ -57,6 +57,7 @@
 # ......dart_native_api.h
 # ......dart_tools_api.h
 # ....lib/
+# ......libraries.json
 # ......dart_client.platform
 # ......dart_server.platform
 # ......dart_shared.platform
@@ -64,7 +65,9 @@
 #.........spec.sum
 #.........strong.sum
 #.........dart2js_platform.dill
+#.........dart2js_server_platform.dill
 #.........dart2js_platform_strong.dill
+#.........dart2js_server_platform_strong.dill
 #.........vm_outline.dill
 #.........vm_outline_strong.dill
 #.........vm_platform.dill
@@ -548,11 +551,15 @@
   deps = [
     ":copy_libraries",
     "../utils/compiler:compile_dart2js_platform",
+    "../utils/compiler:compile_dart2js_server_platform",
     "../utils/compiler:compile_dart2js_platform_strong",
+    "../utils/compiler:compile_dart2js_server_platform_strong",
   ]
   sources = [
     "$root_out_dir/dart2js_platform.dill",
+    "$root_out_dir/dart2js_server_platform.dill",
     "$root_out_dir/dart2js_platform_strong.dill",
+    "$root_out_dir/dart2js_server_platform_strong.dill",
   ]
   outputs = [
     "$root_out_dir/dart-sdk/lib/_internal/{{source_file_part}}",
@@ -779,6 +786,20 @@
   ]
 }
 
+# This rule copies libraries.json files to lib/
+copy("copy_libraries_specification") {
+  visibility = [ ":create_common_sdk" ]
+  sources = [
+    "lib/libraries.json",
+  ]
+  deps = [
+    ":copy_libraries",
+  ]
+  outputs = [
+    "$root_out_dir/dart-sdk/lib/{{source_file_part}}",
+  ]
+}
+
 # This rule copies .platform files to lib/
 copy("copy_platform_files") {
   visibility = [ ":create_common_sdk" ]
@@ -924,6 +945,7 @@
     ":copy_headers",
     ":copy_libraries_dart",
     ":copy_license",
+    ":copy_libraries_specification",
     ":copy_platform_files",
     ":copy_pub_assets",
     ":copy_readme",
diff --git a/sdk/lib/_internal/js_runtime/lib/core_patch.dart b/sdk/lib/_internal/js_runtime/lib/core_patch.dart
index df3bf16..d0f53c3 100644
--- a/sdk/lib/_internal/js_runtime/lib/core_patch.dart
+++ b/sdk/lib/_internal/js_runtime/lib/core_patch.dart
@@ -1299,6 +1299,7 @@
   /// Does *not* clear digits below ds.
   static void _lsh(
       Uint16List xDigits, int xUsed, int n, Uint16List resultDigits) {
+    assert(xUsed > 0);
     final digitShift = n ~/ _digitBits;
     final bitShift = n % _digitBits;
     final carryBitShift = _digitBits - bitShift;
@@ -1328,6 +1329,7 @@
     if (shiftAmount < 0) {
       throw new ArgumentError("shift-amount must be posititve $shiftAmount");
     }
+    if (_isZero) return this;
     final digitShift = shiftAmount ~/ _digitBits;
     final bitShift = shiftAmount % _digitBits;
     if (bitShift == 0) {
@@ -1363,6 +1365,7 @@
   // resultDigits[0..resultUsed-1] = xDigits[0..xUsed-1] >> n.
   static void _rsh(
       Uint16List xDigits, int xUsed, int n, Uint16List resultDigits) {
+    assert(xUsed > 0);
     final digitsShift = n ~/ _digitBits;
     final bitShift = n % _digitBits;
     final carryBitShift = _digitBits - bitShift;
@@ -1390,6 +1393,7 @@
     if (shiftAmount < 0) {
       throw new ArgumentError("shift-amount must be posititve $shiftAmount");
     }
+    if (_isZero) return this;
     final digitShift = shiftAmount ~/ _digitBits;
     final bitShift = shiftAmount % _digitBits;
     if (bitShift == 0) {
@@ -1632,6 +1636,7 @@
    */
   _BigIntImpl operator &(BigInt bigInt) {
     _BigIntImpl other = bigInt;
+    if (_isZero || other._isZero) return zero;
     if (_isNegative == other._isNegative) {
       if (_isNegative) {
         // (-this) & (-other) == ~(this-1) & ~(other-1)
@@ -1671,6 +1676,8 @@
    */
   _BigIntImpl operator |(BigInt bigInt) {
     _BigIntImpl other = bigInt;
+    if (_isZero) return other;
+    if (other._isZero) return this;
     if (_isNegative == other._isNegative) {
       if (_isNegative) {
         // (-this) | (-other) == ~(this-1) | ~(other-1)
@@ -1711,6 +1718,8 @@
    */
   _BigIntImpl operator ^(BigInt bigInt) {
     _BigIntImpl other = bigInt;
+    if (_isZero) return other;
+    if (other._isZero) return this;
     if (_isNegative == other._isNegative) {
       if (_isNegative) {
         // (-this) ^ (-other) == ~(this-1) ^ ~(other-1) == (this-1) ^ (other-1)
@@ -1745,6 +1754,7 @@
    * This maps any integer `x` to `-x - 1`.
    */
   _BigIntImpl operator ~() {
+    if (_isZero) return _minusOne;
     if (_isNegative) {
       // ~(-this) == ~(~(this-1)) == this-1
       return _absSubSetSign(one, false);
@@ -1757,6 +1767,8 @@
   /// Addition operator.
   _BigIntImpl operator +(BigInt bigInt) {
     _BigIntImpl other = bigInt;
+    if (_isZero) return other;
+    if (other._isZero) return this;
     var isNegative = _isNegative;
     if (isNegative == other._isNegative) {
       // this + other == this + other
@@ -1774,6 +1786,8 @@
   /// Subtraction operator.
   _BigIntImpl operator -(BigInt bigInt) {
     _BigIntImpl other = bigInt;
+    if (_isZero) return -other;
+    if (other._isZero) return this;
     var isNegative = _isNegative;
     if (isNegative != other._isNegative) {
       // this - (-other) == this + other
diff --git a/sdk/lib/_internal/sdk_library_metadata/lib/libraries.dart b/sdk/lib/_internal/sdk_library_metadata/lib/libraries.dart
index 5f3a40c..c2ba34e 100644
--- a/sdk/lib/_internal/sdk_library_metadata/lib/libraries.dart
+++ b/sdk/lib/_internal/sdk_library_metadata/lib/libraries.dart
@@ -90,6 +90,11 @@
       categories: "Client",
       maturity: Maturity.STABLE,
       platforms: DART2JS_PLATFORM),
+  "_js": const LibraryInfo("js/_js.dart",
+      categories: "Client",
+      dart2jsPatchPath: "js/_js_client.dart",
+      documented: false,
+      platforms: DART2JS_PLATFORM),
   "js_util": const LibraryInfo("js_util/dart2js/js_util_dart2js.dart",
       categories: "Client",
       maturity: Maturity.STABLE,
diff --git a/sdk/lib/dart_client.platform b/sdk/lib/dart_client.platform
index 3813dc0..0228d99 100644
--- a/sdk/lib/dart_client.platform
+++ b/sdk/lib/dart_client.platform
@@ -32,6 +32,7 @@
 cli: unsupported:cli/cli.dart
 isolate: isolate/isolate.dart
 js: js/dart2js/js_dart2js.dart
+_js: js/_js.dart
 js_util: js_util/dart2js/js_util_dart2js.dart
 math: math/math.dart
 mirrors: mirrors/mirrors.dart
diff --git a/sdk/lib/dart_server.platform b/sdk/lib/dart_server.platform
index de57d4c..414a30c 100644
--- a/sdk/lib/dart_server.platform
+++ b/sdk/lib/dart_server.platform
@@ -37,6 +37,7 @@
 web_sql: unsupported:
 _chrome: unsupported:
 js: unsupported:
+_js: unsupported:
 js_util: unsupported:
 _mirror_helper: unsupported:
 _internal: internal/internal.dart
diff --git a/sdk/lib/dart_shared.platform b/sdk/lib/dart_shared.platform
index be8ed61..922fb98 100644
--- a/sdk/lib/dart_shared.platform
+++ b/sdk/lib/dart_shared.platform
@@ -26,6 +26,7 @@
 cli: cli/cli.dart
 isolate: isolate/isolate.dart
 js: js/dart2js/js_dart2js.dart
+_js: js/_js.dart
 js_util: js_util/dart2js/js_util_dart2js.dart
 math: math/math.dart
 mirrors: mirrors/mirrors.dart
diff --git a/sdk/lib/js/_js.dart b/sdk/lib/js/_js.dart
new file mode 100644
index 0000000..aef7ef9
--- /dev/null
+++ b/sdk/lib/js/_js.dart
@@ -0,0 +1,21 @@
+// Copyright (c) 2018, 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.
+
+/// Helper library used by `dart:js`.
+///
+/// This library hides any logic that is specific to the web, and allows us to
+/// support `dart:js` for compiling to javascript on the server (e.g. to target
+/// nodejs).
+library dart._js;
+
+/// Whether `o` is a browser object such as `Blob`, `Event`, `KeyRange`,
+/// `ImageData`, `Node`, and `Window`.
+///
+/// On non-web targets, this function always returns false.
+external bool isBrowserObject(dynamic o);
+
+/// Convert a browser object to it's Dart counterpart. None of these types are
+/// wrapped, but this function is needed to inform dart2js about the possible
+/// types that are used and that therefore cannot be tree-shaken.
+external Object convertFromBrowserObject(dynamic o);
diff --git a/sdk/lib/js/_js_client.dart b/sdk/lib/js/_js_client.dart
new file mode 100644
index 0000000..74df24d
--- /dev/null
+++ b/sdk/lib/js/_js_client.dart
@@ -0,0 +1,21 @@
+// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:html' show Blob, Event, ImageData, Node, Window;
+import 'dart:indexed_db' show KeyRange;
+import 'dart:_js_helper' show patch;
+import 'dart:_foreign_helper' show JS;
+
+@patch
+bool isBrowserObject(dynamic o) =>
+    o is Blob ||
+    o is Event ||
+    o is KeyRange ||
+    o is ImageData ||
+    o is Node ||
+    o is Window;
+
+@patch
+Object convertFromBrowserObject(dynamic o) =>
+    JS('Blob|Event|KeyRange|ImageData|Node|Window', '#', o);
diff --git a/sdk/lib/js/_js_server.dart b/sdk/lib/js/_js_server.dart
new file mode 100644
index 0000000..b941d77
--- /dev/null
+++ b/sdk/lib/js/_js_server.dart
@@ -0,0 +1,11 @@
+// Copyright (c) 2018, 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:_js_helper' show patch;
+
+@patch
+bool isBrowserObject(dynamic o) => false;
+
+@patch
+Object convertFromBrowserObject(dynamic o) => o;
diff --git a/sdk/lib/js/dart2js/js_dart2js.dart b/sdk/lib/js/dart2js/js_dart2js.dart
index 5d1e2d3..74c55b8 100644
--- a/sdk/lib/js/dart2js/js_dart2js.dart
+++ b/sdk/lib/js/dart2js/js_dart2js.dart
@@ -58,17 +58,11 @@
  *
  * The following types are transferred directly and not proxied:
  *
- * * "Basic" types: `null`, `bool`, `num`, `String`, `DateTime`
- * * `Blob`
- * * `Event`
- * * `HtmlCollection`
- * * `ImageData`
- * * `KeyRange`
- * * `Node`
- * * `NodeList`
- * * `TypedData`, including its subclasses like `Int32List`, but _not_
- *   `ByteBuffer`
- * * `Window`
+ *   * Basic types: `null`, `bool`, `num`, `String`, `DateTime`
+ *   * `TypedData`, including its subclasses like `Int32List`, but _not_
+ *     `ByteBuffer`
+ *   * When compiling for the web, also: `Blob`, `Event`, `ImageData`,
+ *     `KeyRange`, `Node`, and `Window`.
  *
  * ## Converting collections with JsObject.jsify()
  *
@@ -87,9 +81,7 @@
  */
 library dart.js;
 
-import 'dart:html' show Blob, Event, ImageData, Node, Window;
 import 'dart:collection' show HashMap, ListMixin;
-import 'dart:indexed_db' show KeyRange;
 import 'dart:typed_data' show TypedData;
 
 import 'dart:_foreign_helper' show JS, JS_CONST, DART_CLOSURE_TO_JS;
@@ -97,6 +89,7 @@
     show JavaScriptObject, UnknownJavaScriptObject, DART_CLOSURE_PROPERTY_NAME;
 import 'dart:_js_helper'
     show Primitives, convertDartClosureToJS, getIsolateAffinityTag;
+import 'dart:_js' show isBrowserObject, convertFromBrowserObject;
 
 export 'dart:_interceptors' show JavaScriptObject;
 
@@ -568,13 +561,10 @@
   if (o is JsObject) {
     return o._jsObject;
   }
-  if (o is Blob ||
-      o is Event ||
-      o is KeyRange ||
-      o is ImageData ||
-      o is Node ||
-      o is TypedData ||
-      o is Window) {
+  if (isBrowserObject(o)) {
+    return o;
+  }
+  if (o is TypedData) {
     return o;
   }
   if (o is DateTime) {
@@ -610,16 +600,10 @@
       JS('bool', 'typeof # == "number"', o) ||
       JS('bool', 'typeof # == "boolean"', o)) {
     return o;
-  } else if (_isLocalObject(o) &&
-      (o is Blob ||
-          o is Event ||
-          o is KeyRange ||
-          o is ImageData ||
-          o is Node ||
-          o is TypedData ||
-          o is Window)) {
-    // long line: dart2js doesn't allow string concatenation in the JS() form
-    return JS('Blob|Event|KeyRange|ImageData|Node|TypedData|Window', '#', o);
+  } else if (_isLocalObject(o) && isBrowserObject(o)) {
+    return convertFromBrowserObject(o);
+  } else if (_isLocalObject(o) && o is TypedData) {
+    return JS('TypedData', '#', o);
   } else if (JS('bool', '# instanceof Date', o)) {
     var ms = JS('num', '#.getTime()', o);
     return new DateTime.fromMillisecondsSinceEpoch(ms);
diff --git a/sdk/lib/libraries.json b/sdk/lib/libraries.json
index c2b21b0..633ae36 100644
--- a/sdk/lib/libraries.json
+++ b/sdk/lib/libraries.json
@@ -146,18 +146,22 @@
     }
   },
   "dart2js": {
+    "environment_overrides": {
+      "mirrors": false,
+      "io": false
+    },
     "libraries": {
       "async": {
         "patches": "_internal/js_runtime/lib/async_patch.dart",
         "uri": "async/async.dart"
       },
+      "_interceptors": {
+        "uri": "_internal/js_runtime/lib/interceptors.dart"
+      },
       "mirrors": {
         "patches": "_internal/js_runtime/lib/mirrors_patch_cfe.dart",
         "uri": "mirrors/mirrors.dart"
       },
-      "_interceptors": {
-        "uri": "_internal/js_runtime/lib/interceptors.dart"
-      },
       "_js_embedded_names": {
         "uri": "_internal/js_runtime/lib/shared/embedded_names.dart"
       },
@@ -237,6 +241,10 @@
       "indexed_db": {
         "uri": "indexed_db/dart2js/indexed_db_dart2js.dart"
       },
+      "_js": {
+        "patches": "js/_js_client.dart",
+        "uri": "js/_js.dart"
+      },
       "convert": {
         "patches": "_internal/js_runtime/lib/convert_patch.dart",
         "uri": "convert/convert.dart"
@@ -258,5 +266,100 @@
         "uri": "svg/dart2js/svg_dart2js.dart"
       }
     }
+  },
+  "dart2js_server": {
+    "environment_overrides": {
+      "mirrors": false,
+      "io": false
+    },
+    "libraries": {
+      "async": {
+        "patches": "_internal/js_runtime/lib/async_patch.dart",
+        "uri": "async/async.dart"
+      },
+      "mirrors": {
+        "patches": "_internal/js_runtime/lib/mirrors_patch_cfe.dart",
+        "uri": "mirrors/mirrors.dart"
+      },
+      "_interceptors": {
+        "uri": "_internal/js_runtime/lib/interceptors.dart"
+      },
+      "_js_embedded_names": {
+        "uri": "_internal/js_runtime/lib/shared/embedded_names.dart"
+      },
+      "io": {
+        "patches": "_internal/js_runtime/lib/io_patch.dart",
+        "uri": "io/io.dart"
+      },
+      "_internal": {
+        "patches": "_internal/js_runtime/lib/internal_patch.dart",
+        "uri": "internal/internal.dart"
+      },
+      "_async_await_error_codes": {
+        "uri": "_internal/js_runtime/lib/shared/async_await_error_codes.dart"
+      },
+      "_http": {
+        "uri": "_http/http.dart"
+      },
+      "_js_helper": {
+        "uri": "_internal/js_runtime/lib/js_helper.dart"
+      },
+      "_js_primitives": {
+        "uri": "_internal/js_runtime/lib/js_primitives.dart"
+      },
+      "js": {
+        "uri": "js/dart2js/js_dart2js.dart"
+      },
+      "_js_mirrors": {
+        "uri": "_internal/js_runtime/lib/js_mirrors.dart"
+      },
+      "_native_typed_data": {
+        "uri": "_internal/js_runtime/lib/native_typed_data.dart"
+      },
+      "core": {
+        "patches": "_internal/js_runtime/lib/core_patch.dart",
+        "uri": "core/core.dart"
+      },
+      "_js_names": {
+        "uri": "_internal/js_runtime/lib/js_names.dart"
+      },
+      "js_util": {
+        "uri": "js_util/dart2js/js_util_dart2js.dart"
+      },
+      "collection": {
+        "patches": "_internal/js_runtime/lib/collection_patch.dart",
+        "uri": "collection/collection.dart"
+      },
+      "typed_data": {
+        "patches": "_internal/js_runtime/lib/typed_data_patch.dart",
+        "uri": "typed_data/typed_data.dart"
+      },
+      "isolate": {
+        "patches": "_internal/js_runtime/lib/isolate_patch.dart",
+        "uri": "isolate/isolate.dart"
+      },
+      "developer": {
+        "patches": "_internal/js_runtime/lib/developer_patch.dart",
+        "uri": "developer/developer.dart"
+      },
+      "_js": {
+        "patches": "js/_js_server.dart",
+        "uri": "js/_js.dart"
+      },
+      "convert": {
+        "patches": "_internal/js_runtime/lib/convert_patch.dart",
+        "uri": "convert/convert.dart"
+      },
+      "_isolate_helper": {
+        "uri": "_internal/js_runtime/lib/isolate_helper.dart"
+      },
+      "math": {
+        "patches": "_internal/js_runtime/lib/math_patch.dart",
+        "uri": "math/math.dart"
+      },
+      "_foreign_helper": {
+        "uri": "_internal/js_runtime/lib/foreign_helper.dart"
+      }
+    }
   }
-}
+}
\ No newline at end of file
diff --git a/sdk/lib/libraries.yaml b/sdk/lib/libraries.yaml
index c959674..2bb6e8c 100644
--- a/sdk/lib/libraries.yaml
+++ b/sdk/lib/libraries.yaml
@@ -192,6 +192,10 @@
     js:
       uri: "js/dart2js/js_dart2js.dart"
 
+    _js:
+      uri: "js/_js.dart"
+      patches: "js/_js_client.dart"
+
     js_util:
       uri: "js_util/dart2js/js_util_dart2js.dart"
 
@@ -201,7 +205,7 @@
 
     mirrors:
       uri: "mirrors/mirrors.dart"
-      patches: "_internal/js_runtime/lib/mirrors_patch.dart"
+      patches: "_internal/js_runtime/lib/mirrors_patch_cfe.dart"
 
     typed_data:
       uri: "typed_data/typed_data.dart"
@@ -255,3 +259,100 @@
 
     _metadata:
       uri: "html/html_common/metadata.dart"
+
+  environment_overrides:
+    io: false
+    mirrors: false
+
+dart2js_server:
+  libraries:
+    async:
+      uri: "async/async.dart"
+      patches: "_internal/js_runtime/lib/async_patch.dart"
+
+    collection:
+      uri: "collection/collection.dart"
+      patches: "_internal/js_runtime/lib/collection_patch.dart"
+
+    convert:
+      uri: "convert/convert.dart"
+      patches: "_internal/js_runtime/lib/convert_patch.dart"
+
+    core:
+      uri: "core/core.dart"
+      patches: "_internal/js_runtime/lib/core_patch.dart"
+
+    developer:
+      uri: "developer/developer.dart"
+      patches: "_internal/js_runtime/lib/developer_patch.dart"
+
+    _http:
+      uri: "_http/http.dart"
+
+    io:
+      uri: "io/io.dart"
+      patches: "_internal/js_runtime/lib/io_patch.dart"
+
+    isolate:
+      uri: "isolate/isolate.dart"
+      patches: "_internal/js_runtime/lib/isolate_patch.dart"
+
+    js:
+      uri: "js/dart2js/js_dart2js.dart"
+
+    _js:
+      uri: "js/_js.dart"
+      patches: "js/_js_server.dart"
+
+    js_util:
+      uri: "js_util/dart2js/js_util_dart2js.dart"
+
+    math:
+      uri: "math/math.dart"
+      patches: "_internal/js_runtime/lib/math_patch.dart"
+
+    mirrors:
+      uri: "mirrors/mirrors.dart"
+      patches: "_internal/js_runtime/lib/mirrors_patch_cfe.dart"
+
+    typed_data:
+      uri: "typed_data/typed_data.dart"
+      patches: "_internal/js_runtime/lib/typed_data_patch.dart"
+
+    _native_typed_data:
+      uri: "_internal/js_runtime/lib/native_typed_data.dart"
+
+    _internal:
+      uri: "internal/internal.dart"
+      patches: "_internal/js_runtime/lib/internal_patch.dart"
+
+    _js_helper:
+      uri: "_internal/js_runtime/lib/js_helper.dart"
+
+    _interceptors:
+      uri: "_internal/js_runtime/lib/interceptors.dart"
+
+    _foreign_helper:
+      uri: "_internal/js_runtime/lib/foreign_helper.dart"
+
+    _isolate_helper:
+      uri: "_internal/js_runtime/lib/isolate_helper.dart"
+
+    _js_mirrors:
+      uri: "_internal/js_runtime/lib/js_mirrors.dart"
+
+    _js_names:
+      uri: "_internal/js_runtime/lib/js_names.dart"
+
+    _js_primitives:
+      uri: "_internal/js_runtime/lib/js_primitives.dart"
+
+    _js_embedded_names:
+      uri: "_internal/js_runtime/lib/shared/embedded_names.dart"
+
+    _async_await_error_codes:
+      uri: "_internal/js_runtime/lib/shared/async_await_error_codes.dart"
+
+  environment_overrides:
+    io: false
+    mirrors: false
diff --git a/sdk/lib/web_audio/dart2js/web_audio_dart2js.dart b/sdk/lib/web_audio/dart2js/web_audio_dart2js.dart
index deb724c..707b1e7 100644
--- a/sdk/lib/web_audio/dart2js/web_audio_dart2js.dart
+++ b/sdk/lib/web_audio/dart2js/web_audio_dart2js.dart
@@ -206,10 +206,9 @@
   @DocsEditable()
   final AudioParam playbackRate;
 
-  @JSName('start')
   @DomName('AudioBufferSourceNode.start')
   @DocsEditable()
-  void start2([num when, num grainOffset, num grainDuration]) native;
+  void start([num when, num grainOffset, num grainDuration]) native;
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
@@ -599,10 +598,11 @@
   static const EventStreamProvider<Event> endedEvent =
       const EventStreamProvider<Event>('ended');
 
+  @JSName('start')
   @DomName('AudioScheduledSourceNode.start')
   @DocsEditable()
   @Experimental() // untriaged
-  void start([num when]) native;
+  void start2([num when]) native;
 
   @DomName('AudioScheduledSourceNode.stop')
   @DocsEditable()
diff --git a/tests/co19/co19-dart2js.status b/tests/co19/co19-dart2js.status
index 9ef5fea..c05773a 100644
--- a/tests/co19/co19-dart2js.status
+++ b/tests/co19/co19-dart2js.status
@@ -468,6 +468,7 @@
 LayoutTests/fast/css/max-device-aspect-ratio_t01: RuntimeError, Pass # Issue 28998
 LayoutTests/fast/css/media-query-recovery_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css/modify-ua-rules-from-javascript_t01: RuntimeError
+LayoutTests/fast/css/padding-no-renderer_t01: Pass, RuntimeError
 LayoutTests/fast/css/parsing-at-rule-recovery_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css/parsing-css-allowed-string-characters_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css/parsing-page-rule_t01: RuntimeError # Please triage this failure
diff --git a/tests/compiler/dart2js/closure/show.dart b/tests/compiler/dart2js/closure/show.dart
new file mode 100644
index 0000000..ae6eb5e
--- /dev/null
+++ b/tests/compiler/dart2js/closure/show.dart
@@ -0,0 +1,22 @@
+// Copyright (c) 2018, 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.
+
+/// Helper program that shows the closure data on a dart program.
+
+import 'package:args/args.dart';
+import '../equivalence/id_equivalence_helper.dart';
+import '../equivalence/show_helper.dart';
+import 'closure_test.dart';
+
+main(List<String> args) async {
+  ArgParser argParser = createArgParser();
+  argParser.addFlag('inference', defaultsTo: true);
+  argParser.addFlag('side-effects', defaultsTo: false);
+  argParser.addFlag('callers', defaultsTo: false);
+  ArgResults results = argParser.parse(args);
+
+  ComputeMemberDataFunction astFunction = computeClosureData;
+  ComputeMemberDataFunction kernelFunction = computeKernelClosureData;
+  await show(results, astFunction, kernelFunction);
+}
diff --git a/tests/compiler/dart2js/dart2js.status b/tests/compiler/dart2js/dart2js.status
index 31320ad..f4b558f 100644
--- a/tests/compiler/dart2js/dart2js.status
+++ b/tests/compiler/dart2js/dart2js.status
@@ -10,7 +10,8 @@
 codegen/logical_expression_test: Fail # Issue 17027
 codegen/simple_function_subtype_test: Fail # simple_function_subtype_test is temporarily(?) disabled due to new method for building function type tests.
 deferred_loading/deferred_loading_test: Slow, Pass
-equivalence/id_equivalence_test: Pass, Slow
+equivalence/id_equivalence1_test: Pass, Slow
+equivalence/id_equivalence2_test: Pass, Slow
 generate_code_with_compile_time_errors_test: RuntimeError # not supported yet with the new FE.
 in_user_code_test: RuntimeError # analyze-only with CFE is not complete (Issues 32512, 32513)
 inference/inference0_test: Slow, Pass
@@ -78,8 +79,6 @@
 mirrors/import_mirrors_test: Pass, Slow
 mirrors/mirror_final_field_inferrer2_test: Crash, Pass, Slow # Issue 15581
 old_frontend/analyze_api_test: Pass, Slow # DON'T CHANGE THIS LINE -- Don't mark these tests as failing. Instead, fix the errors/warnings that they report or update the whitelist in the test-files to temporarily allow digression.
-old_frontend/analyze_dart2js_test: Pass, Slow # DON'T CHANGE THIS LINE -- Don't mark these tests as failing. Instead, fix the errors/warnings that they report or update the whitelist in the test-files to temporarily allow digression.
-old_frontend/analyze_unused_dart2js_test: Pass, Slow
 old_frontend/check_elements_invariants_test: Skip # Slow and only needs to be run in one configuration
 old_frontend/check_members_test: Pass, Slow
 old_frontend/duplicate_library_test: Pass, Slow
@@ -103,8 +102,6 @@
 mirrors/mirror_final_field_inferrer2_test: Pass, Slow
 mirrors/preserve_uris_test: Pass, Slow
 old_frontend/analyze_dart2js_helpers_test: Pass, Slow
-old_frontend/analyze_dart2js_test: Pass, Slow
-old_frontend/analyze_unused_dart2js_test: Pass, Slow
 old_frontend/duplicate_library_test: Pass, Slow
 output_type_test: Pass, Slow
 serialization*: Slow, Pass
diff --git a/tests/compiler/dart2js/dill_loader_test.dart b/tests/compiler/dart2js/dill_loader_test.dart
index 1963d3b..4192756 100644
--- a/tests/compiler/dart2js/dill_loader_test.dart
+++ b/tests/compiler/dart2js/dill_loader_test.dart
@@ -43,7 +43,7 @@
     Uri entryPoint = Uri.parse('memory:main.dill');
 
     var options = new CompilerOptions()
-      ..target = new Dart2jsTarget(new TargetFlags())
+      ..target = new Dart2jsTarget("dart2js", new TargetFlags())
       ..packagesFileUri = Uri.base.resolve('.packages')
       ..linkedDependencies = <Uri>[
         computePlatformBinariesLocation().resolve("dart2js_platform.dill"),
diff --git a/tests/compiler/dart2js/end_to_end/async_compiler_input_provider_test.dart b/tests/compiler/dart2js/end_to_end/async_compiler_input_provider_test.dart
index 8349c81..9cfb6cb 100644
--- a/tests/compiler/dart2js/end_to_end/async_compiler_input_provider_test.dart
+++ b/tests/compiler/dart2js/end_to_end/async_compiler_input_provider_test.dart
@@ -2,8 +2,6 @@
 // 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.
 
-// TODO(johnniwinther): Port this test to use '--use-kernel'.
-
 import "dart:async";
 import "dart:io";
 
@@ -11,6 +9,7 @@
 import "package:async_helper/async_helper.dart";
 
 import 'package:compiler/compiler.dart' as compiler;
+import 'package:compiler/src/filenames.dart';
 
 const SOURCES = const {
   "/main.dart": """
@@ -49,7 +48,8 @@
   // Find the path to sdk/ in the repo relative to this script.
   Uri libraryRoot = Uri.base.resolve('sdk/');
   Uri packageRoot = Uri.base.resolve('packages/');
-  var platformDir = Uri.parse(Platform.resolvedExecutable).resolve('.');
+  var platformDir =
+      Uri.parse(nativeToUriPath(Platform.resolvedExecutable)).resolve('.');
   asyncTest(() => compiler.compile(
           entrypoint,
           libraryRoot,
diff --git a/tests/compiler/dart2js/equivalence/check_functions.dart b/tests/compiler/dart2js/equivalence/check_functions.dart
index 01e83cc..945803a 100644
--- a/tests/compiler/dart2js/equivalence/check_functions.dart
+++ b/tests/compiler/dart2js/equivalence/check_functions.dart
@@ -520,6 +520,7 @@
       Uri.parse('dart:mirrors'),
       Uri.parse('dart:_js_mirrors'),
       Uri.parse('dart:js'),
+      Uri.parse('dart:_js'),
       Uri.parse('dart:js_util'),
       Uri.parse('dart:_chrome'),
       Uri.parse('dart:io'),
diff --git a/tests/compiler/dart2js/equivalence/id_equivalence.dart b/tests/compiler/dart2js/equivalence/id_equivalence.dart
index 0794c05..93500b0 100644
--- a/tests/compiler/dart2js/equivalence/id_equivalence.dart
+++ b/tests/compiler/dart2js/equivalence/id_equivalence.dart
@@ -28,6 +28,9 @@
 abstract class Id {
   IdKind get kind;
   bool get isGlobal;
+
+  /// Display name for this id.
+  String get descriptor;
 }
 
 class IdValue {
@@ -155,6 +158,8 @@
 
   String get name => className != null ? '$className.$memberName' : memberName;
 
+  String get descriptor => 'member $name';
+
   String toString() => 'element:$name';
 }
 
@@ -177,6 +182,8 @@
 
   String get name => className;
 
+  String get descriptor => 'class $name';
+
   String toString() => 'class:$name';
 }
 
@@ -198,6 +205,8 @@
     return value == other.value && kind == other.kind;
   }
 
+  String get descriptor => 'offset $value ($kind)';
+
   String toString() => '$kind:$value';
 }
 
@@ -217,8 +226,12 @@
     }
   }
 
+  String get objectText {
+    return 'object `${'$object'.replaceAll('\n', '')}` (${object.runtimeType})';
+  }
+
   String toString() =>
-      'ActualData(value=$value,sourceSpan=$sourceSpan,object=$object)';
+      'ActualData(value=$value,sourceSpan=$sourceSpan,object=$objectText)';
 }
 
 abstract class DataRegistry {
@@ -432,14 +445,16 @@
         case SendStructureKind.INCOMPATIBLE_INVOKE:
           switch (sendStructure.semantics.kind) {
             case AccessKind.EXPRESSION:
-              computeForNode(node, createInvokeId(node.argumentsNode));
+              computeForNode(node,
+                  createInvokeId(node.typeArgumentsNode ?? node.argumentsNode));
               break;
             case AccessKind.LOCAL_VARIABLE:
             case AccessKind.FINAL_LOCAL_VARIABLE:
             case AccessKind.PARAMETER:
             case AccessKind.FINAL_PARAMETER:
               computeForNode(node, createAccessId(node));
-              computeForNode(node, createInvokeId(node.argumentsNode));
+              computeForNode(node,
+                  createInvokeId(node.typeArgumentsNode ?? node.argumentsNode));
               break;
             case AccessKind.STATIC_FIELD:
             case AccessKind.FINAL_STATIC_FIELD:
@@ -449,13 +464,17 @@
             case AccessKind.SUPER_FIELD:
             case AccessKind.SUPER_FINAL_FIELD:
             case AccessKind.SUPER_GETTER:
-              computeForNode(node, createInvokeId(node.argumentsNode));
+              computeForNode(node,
+                  createInvokeId(node.typeArgumentsNode ?? node.argumentsNode));
               break;
             case AccessKind.TOPLEVEL_GETTER:
               if (elements[node].isDeferredLoaderGetter) {
                 computeForNode(node, createInvokeId(node.selector));
               } else {
-                computeForNode(node, createInvokeId(node.argumentsNode));
+                computeForNode(
+                    node,
+                    createInvokeId(
+                        node.typeArgumentsNode ?? node.argumentsNode));
               }
               break;
             default:
diff --git a/tests/compiler/dart2js/equivalence/id_equivalence1_test.dart b/tests/compiler/dart2js/equivalence/id_equivalence1_test.dart
new file mode 100644
index 0000000..553ae8f
--- /dev/null
+++ b/tests/compiler/dart2js/equivalence/id_equivalence1_test.dart
@@ -0,0 +1,9 @@
+// Copyright (c) 2018, 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 'id_equivalence_tester.dart';
+
+main(List<String> args) {
+  mainInternal(args, dataDirectories1);
+}
diff --git a/tests/compiler/dart2js/equivalence/id_equivalence2_test.dart b/tests/compiler/dart2js/equivalence/id_equivalence2_test.dart
new file mode 100644
index 0000000..c7c81cf
--- /dev/null
+++ b/tests/compiler/dart2js/equivalence/id_equivalence2_test.dart
@@ -0,0 +1,9 @@
+// Copyright (c) 2018, 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 'id_equivalence_tester.dart';
+
+main(List<String> args) {
+  mainInternal(args, dataDirectories2);
+}
diff --git a/tests/compiler/dart2js/equivalence/id_equivalence_helper.dart b/tests/compiler/dart2js/equivalence/id_equivalence_helper.dart
index 09b47fa..80ec57a 100644
--- a/tests/compiler/dart2js/equivalence/id_equivalence_helper.dart
+++ b/tests/compiler/dart2js/equivalence/id_equivalence_helper.dart
@@ -82,6 +82,19 @@
 
 const String stopAfterTypeInference = 'stopAfterTypeInference';
 
+/// Reports [message] as an error using [spannable] as error location.
+void reportError(
+    DiagnosticReporter reporter, Spannable spannable, String message) {
+  reporter
+      .reportErrorMessage(spannable, MessageKind.GENERIC, {'text': message});
+}
+
+/// Display name used for compilation using the old dart2js frontend.
+const String astName = 'dart2js old frontend';
+
+/// Display name used for compilation using the new common frontend.
+const String kernelName = 'kernel';
+
 /// Compute actual data for all members defined in the program with the
 /// [entryPoint] and [memorySourceFiles].
 ///
@@ -468,7 +481,7 @@
     }
 
     print('----------------------------------------------------------------');
-    print('Test: $name');
+    print('Test file: ${entity.uri}');
     // Pretend this is a dart2js_native test to allow use of 'native' keyword
     // and import of private libraries.
     String commonTestPath = 'sdk/tests/compiler';
@@ -523,7 +536,7 @@
           verbose: verbose,
           forUserLibrariesOnly: forUserLibrariesOnly,
           globalIds: annotations.globalData.keys);
-      if (await checkCode(code, annotations, compiledData1,
+      if (await checkCode(astName, entity.uri, code, annotations, compiledData1,
           fatalErrors: !testAfterFailures)) {
         hasFailures = true;
       }
@@ -540,7 +553,8 @@
           verbose: verbose,
           forUserLibrariesOnly: forUserLibrariesOnly,
           globalIds: annotations.globalData.keys);
-      if (await checkCode(code, annotations, compiledData2,
+      if (await checkCode(
+          kernelName, entity.uri, code, annotations, compiledData2,
           filterActualData: filterActualData,
           fatalErrors: !testAfterFailures)) {
         hasFailures = true;
@@ -554,12 +568,17 @@
 
 /// Checks [compiledData] against the expected data in [expectedMap] derived
 /// from [code].
-Future<bool> checkCode(Map<Uri, AnnotatedCode> code,
-    MemberAnnotations<IdValue> expectedMaps, CompiledData compiledData,
+Future<bool> checkCode(
+    String mode,
+    Uri mainFileUri,
+    Map<Uri, AnnotatedCode> code,
+    MemberAnnotations<IdValue> expectedMaps,
+    CompiledData compiledData,
     {bool filterActualData(IdValue expected, ActualData actualData),
     bool fatalErrors: true}) async {
   IdData data = new IdData(code, expectedMaps, compiledData);
   bool hasFailure = false;
+  Set<Uri> neededDiffs = new Set<Uri>();
 
   void checkActualMap(
       Map<Id, ActualData> actualMap, Map<Id, IdValue> expectedMap,
@@ -567,14 +586,15 @@
     bool hasLocalFailure = false;
     actualMap.forEach((Id id, ActualData actualData) {
       IdValue actual = actualData.value;
+
       if (!expectedMap.containsKey(id)) {
         if (actual.value != '') {
-          reportHere(
+          reportError(
               data.compiler.reporter,
               actualData.sourceSpan,
-              'Id $id = ${colors.red('$actual')} for ${actualData.object} '
-              '(${actualData.object.runtimeType}) '
-              'not expected in ${expectedMap.keys}');
+              'EXTRA $mode DATA for ${id.descriptor} = '
+              '${colors.red('$actual')} for ${actualData.objectText}. '
+              'Data was expected for these ids: ${expectedMap.keys}');
           if (filterActualData == null || filterActualData(null, actualData)) {
             hasLocalFailure = true;
           }
@@ -582,11 +602,11 @@
       } else {
         IdValue expected = expectedMap[id];
         if (actual != expected) {
-          reportHere(
+          reportError(
               data.compiler.reporter,
               actualData.sourceSpan,
-              'Object: ${actualData.object} '
-              '(${actualData.object.runtimeType})\n '
+              'UNEXPECTED $mode DATA for ${id.descriptor}: '
+              'Object: ${actualData.objectText}\n '
               'expected: ${colors.green('$expected')}\n '
               'actual: ${colors.red('$actual')}');
           if (filterActualData == null ||
@@ -599,9 +619,7 @@
     if (hasLocalFailure) {
       hasFailure = true;
       if (uri != null) {
-        print('--annotations diff [${uri.pathSegments.last}]-------------');
-        print(data.diffCode(uri));
-        print('----------------------------------------------------------');
+        neededDiffs.add(uri);
       }
     }
   }
@@ -612,29 +630,23 @@
   checkActualMap(data.actualMaps.globalData, data.expectedMaps.globalData);
 
   Set<Id> missingIds = new Set<Id>();
-  StringBuffer combinedAnnotationsDiff = new StringBuffer();
   void checkMissing(Map<Id, IdValue> expectedMap, Map<Id, ActualData> actualMap,
       [Uri uri]) {
     expectedMap.forEach((Id id, IdValue expected) {
       if (!actualMap.containsKey(id)) {
         missingIds.add(id);
-        StringBuffer sb = new StringBuffer();
-        for (Id id in actualMap.keys.where((d) => d.kind == id.kind)) {
-          sb.write('\n  $id');
-        }
+        String message = 'MISSING $mode DATA for ${id.descriptor}: '
+            'Expected ${colors.green('$expected')}';
         if (uri != null) {
-          reportHere(
-              data.compiler.reporter,
-              computeSpannable(data.elementEnvironment, uri, id),
-              'Expected $expected for id $id missing in${sb}');
+          reportError(data.compiler.reporter,
+              computeSpannable(data.elementEnvironment, uri, id), message);
         } else {
-          print('Expected $expected for id $id missing in${sb}');
+          print(message);
         }
       }
     });
     if (missingIds.isNotEmpty && uri != null) {
-      combinedAnnotationsDiff.write('Missing in $uri:\n');
-      combinedAnnotationsDiff.write('${data.diffCode(uri)}\n');
+      neededDiffs.add(uri);
     }
   }
 
@@ -642,13 +654,13 @@
     checkMissing(expectedMap, data.actualMaps[uri], uri);
   });
   checkMissing(data.expectedMaps.globalData, data.actualMaps.globalData);
-  if (combinedAnnotationsDiff.isNotEmpty) {
-    print('--annotations diff--------------------------------------------');
-    print(combinedAnnotationsDiff.toString());
-    print('--------------------------------------------------------------');
+  for (Uri uri in neededDiffs) {
+    print('--annotations diff [${uri.pathSegments.last}]-------------');
+    print(data.diffCode(uri));
+    print('----------------------------------------------------------');
   }
   if (missingIds.isNotEmpty) {
-    print("Ids not found: ${missingIds}.");
+    print("MISSING ids: ${missingIds}.");
     hasFailure = true;
   }
   if (hasFailure && fatalErrors) {
@@ -749,6 +761,7 @@
 }
 
 Future<bool> compareData(
+    Uri mainFileUri,
     Uri entryPoint,
     Map<String, String> memorySourceFiles,
     ComputeMemberDataFunction computeAstData,
@@ -775,14 +788,15 @@
       skipUnprocessedMembers: skipUnprocessedMembers,
       skipFailedCompilations: skipFailedCompilations);
   if (data2 == null) return false;
-  await compareCompiledData(data1, data2,
+  await compareCompiledData(mainFileUri, data1, data2,
       whiteList: whiteList,
       skipMissingUris: !forUserLibrariesOnly,
       verbose: verbose);
   return true;
 }
 
-Future compareCompiledData(CompiledData data1, CompiledData data2,
+Future compareCompiledData(
+    Uri mainFileUri, CompiledData data1, CompiledData data2,
     {bool skipMissingUris: false,
     bool verbose: false,
     bool whiteList(Uri uri, Id id)}) async {
@@ -831,9 +845,20 @@
     actualMap1.forEach((Id id, ActualData actualData1) {
       IdValue value1 = actualData1.value;
       IdValue value2 = actualMap2[id]?.value;
+
       if (value1 != value2) {
-        reportHere(data1.compiler.reporter, actualData1.sourceSpan,
-            '$id: from source:${value1},from dill:${value2}');
+        String message;
+        if (value2 != null) {
+          String prefix = 'DATA MISMATCH for ${id.descriptor}';
+          message = '$prefix: Data from $astName: ${value1}, '
+              'data from $kernelName: ${value2}';
+        } else {
+          String prefix = 'MISSING $kernelName DATA for ${id.descriptor}, '
+              'object = ${actualData1.objectText}';
+          message = '$prefix: Data from $astName: ${value1}, '
+              'no data from $kernelName';
+        }
+        reportError(data1.compiler.reporter, actualData1.sourceSpan, message);
         if (!whiteList(uri1, id)) {
           hasErrors = hasErrorsInUri = true;
         }
@@ -843,15 +868,24 @@
       IdValue value2 = actualData2.value;
       IdValue value1 = actualMap1[id]?.value;
       if (value1 != value2) {
-        reportHere(data2.compiler.reporter, actualData2.sourceSpan,
-            '$id: from source:${value1},from dill:${value2}');
+        String prefix = 'EXTRA $kernelName DATA for ${id.descriptor}, '
+            'object = ${actualData2.objectText}';
+        String message =
+            '$prefix: Data from $kernelName: ${value2}, no data from $astName';
+        reportError(data1.compiler.reporter, actualData2.sourceSpan, message);
         if (!whiteList(uri1, id)) {
           hasErrors = hasErrorsInUri = true;
         }
       }
     });
     if (hasErrorsInUri) {
-      print('--annotations diff $uri1---------------------------------------');
+      Uri fileUri;
+      if (data1.compiler.mainLibraryUri == uri1) {
+        fileUri = mainFileUri;
+      } else {
+        fileUri = uri1;
+      }
+      print('--annotations diff for: $fileUri -------------------------------');
       print(withAnnotations(
           sourceCode1,
           data1.computeDiffAnnotationsAgainst(actualMap1, actualMap2, uri1,
diff --git a/tests/compiler/dart2js/equivalence/id_equivalence_test.dart b/tests/compiler/dart2js/equivalence/id_equivalence_tester.dart
similarity index 91%
rename from tests/compiler/dart2js/equivalence/id_equivalence_test.dart
rename to tests/compiler/dart2js/equivalence/id_equivalence_tester.dart
index b4441ed..3592578 100644
--- a/tests/compiler/dart2js/equivalence/id_equivalence_test.dart
+++ b/tests/compiler/dart2js/equivalence/id_equivalence_tester.dart
@@ -15,24 +15,27 @@
 import 'package:compiler/src/resolution/access_semantics.dart';
 import 'package:compiler/src/resolution/send_structure.dart';
 import 'package:compiler/src/tree/nodes.dart' as ast;
+import 'package:expect/expect.dart';
 import 'package:kernel/ast.dart' as ir;
 import 'package:sourcemap_testing/src/annotated_code_helper.dart';
-import '../equivalence/id_equivalence.dart';
-import '../equivalence/id_equivalence_helper.dart';
+import 'id_equivalence.dart';
+import 'id_equivalence_helper.dart';
 
-const List<String> dataDirectories = const <String>[
+const List<String> dataDirectories1 = const <String>[
   '../closure/data',
   '../inference/data',
+  '../inlining/data',
+];
+
+const List<String> dataDirectories2 = const <String>[
   '../jumps/data',
+  '../rti/data',
+  '../rti/emission',
 ];
 
 const List<String> skipList = const <String>[
-  // TODO(johnniwinther): Fix these when kernel provides a unique offset for
-  // `()` in `foo[0]()`.
-  'closure_tracer.dart',
-  'closure_tracer_28919.dart',
-  'index_call.dart',
-  'map_tracer_const.dart',
+  // Unpatched external functions are not supported in the legacy frontend.
+  'external.dart',
   // Id equivalence doesn't support libraries.
   'mixin_constructor_default_parameter_values.dart',
   // Id equivalence doesn't support unused constructors.
@@ -42,14 +45,22 @@
 ];
 
 main(List<String> args) {
+  mainInternal(args, []..addAll(dataDirectories1)..addAll(dataDirectories2));
+}
+
+mainInternal(List<String> args, Iterable<String> dataDirectories) {
+  args = args.toList();
+  bool shouldContinue = args.remove('-c');
+  bool continued = false;
   asyncTest(() async {
+    bool hasFailures = false;
     for (String path in dataDirectories) {
       Directory dataDir = new Directory.fromUri(Platform.script.resolve(path));
       await for (FileSystemEntity entity in dataDir.list()) {
-        if (args.isNotEmpty && !args.contains(entity.uri.pathSegments.last)) {
-          continue;
-        }
-        if (skipList.contains(entity.uri.pathSegments.last)) {
+        String name = entity.uri.pathSegments.last;
+        if (args.isNotEmpty && !args.contains(name) && !continued) continue;
+        if (shouldContinue) continued = true;
+        if (skipList.contains(name)) {
           print('Skipping ${entity.uri}');
           continue;
         }
@@ -65,11 +76,14 @@
         Map<String, String> memorySourceFiles = {
           entryPoint.path: code.sourceCode
         };
-        await compareData(entryPoint, memorySourceFiles, computeAstMemberData,
-            computeIrMemberData,
-            options: [Flags.disableTypeInference, stopAfterTypeInference]);
+        if (!await compareData(entity.uri, entryPoint, memorySourceFiles,
+            computeAstMemberData, computeIrMemberData,
+            options: [Flags.disableTypeInference, stopAfterTypeInference])) {
+          hasFailures = true;
+        }
       }
     }
+    Expect.isFalse(hasFailures, 'Errors found.');
   });
 }
 
diff --git a/tests/compiler/dart2js/inference/inference_equivalence.dart b/tests/compiler/dart2js/inference/inference_equivalence.dart
index cdd9a9e..638eab5 100644
--- a/tests/compiler/dart2js/inference/inference_equivalence.dart
+++ b/tests/compiler/dart2js/inference/inference_equivalence.dart
@@ -72,7 +72,7 @@
 Future<bool> testUri(Uri uri,
     {bool verbose: false, bool whiteList(Uri uri, Id id)}) {
   return compareData(
-      uri, const {}, computeMemberAstTypeMasks, computeMemberIrTypeMasks,
+      uri, uri, const {}, computeMemberAstTypeMasks, computeMemberIrTypeMasks,
       options: [stopAfterTypeInference],
       forUserLibrariesOnly: false,
       skipUnprocessedMembers: true,
diff --git a/tests/compiler/dart2js/kernel/compiler_helper.dart b/tests/compiler/dart2js/kernel/compiler_helper.dart
index e32bb06..d59c303 100644
--- a/tests/compiler/dart2js/kernel/compiler_helper.dart
+++ b/tests/compiler/dart2js/kernel/compiler_helper.dart
@@ -65,7 +65,7 @@
 
   MemoryKernelLibraryLoaderTask(KernelToElementMapForImpact elementMap,
       DiagnosticReporter reporter, Measurer measurer, this.component)
-      : super(null, null, elementMap, null, reporter, measurer);
+      : super(null, null, null, elementMap, null, reporter, measurer);
 
   Future<LoadedLibraries> loadLibrary(Uri resolvedUri,
       {bool skipFileWithPartOfTag: false}) async {
diff --git a/tests/compiler/dart2js/old_frontend/analyze_dart2js_test.dart b/tests/compiler/dart2js/old_frontend/analyze_dart2js_test.dart
deleted file mode 100644
index e10862d..0000000
--- a/tests/compiler/dart2js/old_frontend/analyze_dart2js_test.dart
+++ /dev/null
@@ -1,67 +0,0 @@
-// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-library analyze_dart2js;
-
-import 'package:async_helper/async_helper.dart';
-import 'package:compiler/src/filenames.dart';
-import 'package:compiler/src/compiler.dart';
-import 'analyze_helper.dart';
-import 'related_types.dart';
-
-/**
- * Map of whitelisted warnings and errors.
- *
- * Only add a whitelisting together with a bug report to dartbug.com and add
- * the bug issue number as a comment on the whitelisting.
- *
- * Use an identifiable suffix of the file uri as key. Use a fixed substring of
- * the error/warning message in the list of whitelistings for each file.
- */
-// TODO(johnniwinther): Support canonical URIs as keys and message kinds as
-// values.
-const Map<String, List<String>> WHITE_LIST = const {
-  "pkg/front_end/lib/src/fasta/kernel/kernel_library_builder.dart": const [
-    "The getter 'iterator' is not defined for the class 'Object'.",
-  ],
-  "pkg/front_end/lib/src/fasta/type_inference/type_schema.dart": const [
-    "The class 'UnknownType' overrides 'operator==', but not 'get hashCode'."
-  ],
-  "pkg/kernel/lib/transformations/closure/": const [
-    "Duplicated library name 'kernel.transformations.closure.converter'",
-  ],
-  "pkg/kernel/lib/transformations/closure/info.dart": const [
-    "Types 'FunctionNode' and 'FunctionDeclaration' have no common subtypes."
-  ],
-  "third_party/pkg/collection/lib/src/functions.dart": const [
-    "Method type variables are treated as `dynamic` in `as` expressions."
-  ],
-  "sdk/lib/_internal/js_runtime/lib/js_array.dart": const [
-    "Method type variables do not have a runtime value.",
-  ],
-  "sdk/lib/collection/iterable.dart": const [
-    "Method type variables do not have a runtime value.",
-  ],
-  "sdk/lib/collection/list.dart": const [
-    "Method type variables do not have a runtime value.",
-    "Method type variables are treated as `dynamic` in `as` expressions.",
-  ],
-  "sdk/lib/collection/set.dart": const [
-    "Method type variables do not have a runtime value.",
-  ],
-  "sdk/lib/core/iterable.dart": const [
-    "Method type variables do not have a runtime value.",
-    "Method type variables are treated as `dynamic` in `as` expressions.",
-  ],
-};
-
-void main() {
-  var uri = currentDirectory.resolve('pkg/compiler/lib/src/dart2js.dart');
-  asyncTest(() => analyze([uri], WHITE_LIST, checkResults: checkResults));
-}
-
-bool checkResults(Compiler compiler, CollectingDiagnosticHandler handler) {
-  checkRelatedTypes(compiler);
-  return !handler.hasHint;
-}
diff --git a/tests/compiler/dart2js/old_frontend/analyze_unused_dart2js_test.dart b/tests/compiler/dart2js/old_frontend/analyze_unused_dart2js_test.dart
deleted file mode 100644
index dd803ab..0000000
--- a/tests/compiler/dart2js/old_frontend/analyze_unused_dart2js_test.dart
+++ /dev/null
@@ -1,109 +0,0 @@
-// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-library analyze_unused_dart2js;
-
-import 'package:async_helper/async_helper.dart';
-
-import 'package:compiler/src/compiler.dart';
-import 'package:compiler/src/diagnostics/messages.dart';
-import 'package:compiler/src/elements/elements.dart' show LibraryElement;
-import 'package:compiler/src/filenames.dart';
-
-import 'analyze_helper.dart';
-
-// Do not remove WHITE_LIST even if it's empty.  The error message for
-// unused members refers to WHITE_LIST by name.
-const Map<String, List<String>> WHITE_LIST = const {
-  // TODO(johnniwinther): uncomment when [Compiler.reportUnusedCode] is
-  // reenabled.
-  // // Helper methods for debugging should never be called from production code:
-  // "lib/src/helpers/": const [" is never "],
-
-  // // Node.asAssert, Node.asLiteralBool is never used.
-  // "lib/src/tree/nodes.dart": const [
-  //   "The method 'asAssert' is never called.",
-  //   "The method 'asLiteralBool' is never called."
-  // ],
-
-  // // Uncalled methods in SemanticSendVisitor and subclasses.
-  // "lib/src/resolution/semantic_visitor.dart": const ["The method 'error"],
-  // "lib/src/resolution/semantic_visitor_mixins.dart": const [
-  //   "The class 'SuperBulkMixin'",
-  //   "The class 'Base",
-  //   "The method 'error",
-  //   "The method 'visit"
-  // ],
-
-  // // Uncalled type predicate.  Keep while related predicates are used.
-  // "lib/src/ssa/nodes.dart": const ["The method 'isArray' is never called"],
-
-  // // Serialization code is only used in test.
-  // "lib/src/serialization/": const ["is never"],
-
-  // "lib/src/universe/world_builder.dart": const [
-  //   "The method 'getterInvocationsByName' is never called.",
-  //   "The method 'setterInvocationsByName' is never called."
-  // ],
-
-  "pkg/front_end/lib/src/fasta/type_inference/type_schema.dart": const [
-    "The class 'UnknownType' overrides 'operator==', but not 'get hashCode'."
-  ],
-
-  "pkg/kernel/lib/transformations/closure/": const [
-    "Duplicated library name 'kernel.transformations.closure.converter'",
-  ],
-
-  "pkg/kernel/lib/binary/ast_to_binary.dart": const [
-    "'void' is not a subtype of bound 'Object' for type variable",
-  ],
-
-  "pkg/compiler/lib/src/js_backend/runtime_types.dart": const [
-    "'void' is not a subtype of bound 'Object' for type variable",
-  ],
-
-  "sdk/lib/io/file.dart": const [
-    "'void' is not a subtype of bound 'Object' for type variable",
-  ],
-
-  "sdk/lib/io/file_impl.dart": const [
-    "'void' is not a subtype of bound 'Object' for type variable",
-  ],
-};
-
-void main() {
-  var uri =
-      currentDirectory.resolve('pkg/compiler/lib/src/use_unused_api.dart');
-  asyncTest(() => analyze([uri], WHITE_LIST,
-      mode: AnalysisMode.TREE_SHAKING, checkResults: checkResults));
-}
-
-bool checkResults(Compiler compiler, CollectingDiagnosticHandler handler) {
-  var helperUri =
-      currentDirectory.resolve('pkg/compiler/lib/src/helpers/helpers.dart');
-  void checkLive(member) {
-    if (member.isFunction) {
-      if (compiler.resolutionWorldBuilder.isMemberUsed(member)) {
-        compiler.reporter.reportHintMessage(member, MessageKind.GENERIC,
-            {'text': "Helper function in production code '$member'."});
-      }
-    } else if (member.isClass) {
-      if (member.isResolved) {
-        compiler.reporter.reportHintMessage(member, MessageKind.GENERIC,
-            {'text': "Helper class in production code '$member'."});
-      } else {
-        member.forEachLocalMember(checkLive);
-      }
-    } else if (member.isTypedef) {
-      if (member.isResolved) {
-        compiler.reporter.reportHintMessage(member, MessageKind.GENERIC,
-            {'text': "Helper typedef in production code '$member'."});
-      }
-    }
-  }
-
-  (compiler.libraryLoader.lookupLibrary(helperUri) as LibraryElement)
-      .forEachLocalMember(checkLive);
-  return handler.checkResults();
-}
diff --git a/tests/compiler/dart2js/sourcemaps/name_test.dart b/tests/compiler/dart2js/sourcemaps/name_test.dart
index 4855843..f540c8b 100644
--- a/tests/compiler/dart2js/sourcemaps/name_test.dart
+++ b/tests/compiler/dart2js/sourcemaps/name_test.dart
@@ -6,9 +6,11 @@
 
 import 'package:async_helper/async_helper.dart';
 import 'package:expect/expect.dart';
+import 'package:compiler/src/commandline_options.dart';
 import 'package:compiler/src/compiler.dart';
 import 'package:compiler/src/elements/entities.dart';
-import 'package:compiler/src/io/source_information.dart';
+import 'package:compiler/src/io/kernel_source_information.dart';
+import 'package:compiler/src/kernel/kernel_backend_strategy.dart';
 import '../memory_compiler.dart';
 
 const String SOURCE = '''
@@ -71,22 +73,25 @@
 }
 ''';
 
-check(Entity element, String expectedName) {
-  String name = computeElementNameForSourceMaps(element);
-  Expect.equals(expectedName, name,
-      "Unexpected name '$name' for $element, expected '$expectedName'.");
-}
-
 main() {
   asyncTest(() async {
-    CompilationResult result =
-        await runCompiler(memorySourceFiles: {'main.dart': SOURCE});
+    CompilationResult result = await runCompiler(
+        memorySourceFiles: {'main.dart': SOURCE},
+        options: [Flags.disableInlining]);
     Compiler compiler = result.compiler;
+    KernelBackendStrategy backendStrategy = compiler.backendStrategy;
     var env = compiler.backendClosedWorldForTesting.elementEnvironment;
     LibraryEntity mainApp = env.mainLibrary;
 
-    Entity lookup(String name) {
-      Entity element;
+    check(MemberEntity element, String expectedName) {
+      String name = computeKernelElementNameForSourceMaps(
+          backendStrategy.elementMap, element);
+      Expect.equals(expectedName, name,
+          "Unexpected name '$name' for $element, expected '$expectedName'.");
+    }
+
+    MemberEntity lookup(String name) {
+      MemberEntity element;
       int dotPosition = name.indexOf('.');
       if (dotPosition != -1) {
         String clsName = name.substring(0, dotPosition);
@@ -95,8 +100,6 @@
         var subname = name.substring(dotPosition + 1);
         element = env.lookupLocalClassMember(cls, subname) ??
             env.lookupConstructor(cls, subname);
-      } else if (name.substring(0, 1) == name.substring(0, 1).toUpperCase()) {
-        element = env.lookupClass(mainApp, name);
       } else {
         element = env.lookupLibraryMember(mainApp, name);
       }
@@ -125,7 +128,6 @@
         env.forEachNestedClosure(element, (closure) {
           String expectedName = expectedClosureNames[index];
           check(closure, expectedName);
-          check(closure.enclosingClass, expectedName);
           index++;
         });
       }
@@ -133,28 +135,28 @@
 
     checkName('toplevelField');
     checkName('toplevelMethod');
-    // TODO(johnniwinther): improve closure names.
-    checkName('toplevelAnonymous', ['toplevelAnonymous_closure']);
-    checkName('toplevelLocal', ['toplevelLocal_localMethod']);
-    checkName('Class');
+    checkName('toplevelAnonymous', ['toplevelAnonymous.<anonymous function>']);
+    checkName('toplevelLocal', ['toplevelLocal.localMethod']);
     checkName('main');
 
     checkName('Class.staticField');
     checkName('Class.staticMethod');
-    checkName('Class.staticAnonymous', ['Class_staticAnonymous_closure']);
-    checkName('Class.staticLocal', ['Class_staticLocal_localMethod']);
+    checkName('Class.staticAnonymous',
+        ['Class.staticAnonymous.<anonymous function>']);
+    checkName('Class.staticLocal', ['Class.staticLocal.localMethod']);
 
-    checkName('Class', ['Class_closure'], 'Class.');
-    checkName('Class.named', ['Class\$named_localMethod']);
+    checkName('Class', ['Class.<anonymous function>'], 'Class.');
+    checkName('Class.named', ['Class.named.localMethod']);
 
     checkName('Class.instanceField');
     checkName('Class.instanceMethod');
-    checkName('Class.instanceAnonymous', ['Class_instanceAnonymous_closure']);
-    checkName('Class.instanceLocal', ['Class_instanceLocal_localMethod']);
+    checkName('Class.instanceAnonymous',
+        ['Class.instanceAnonymous.<anonymous function>']);
+    checkName('Class.instanceLocal', ['Class.instanceLocal.localMethod']);
     checkName('Class.instanceNestedLocal', [
-      'Class_instanceNestedLocal_localMethod',
-      'Class_instanceNestedLocal_localMethod_closure',
-      'Class_instanceNestedLocal_localMethod_nestedLocalMethod'
+      'Class.instanceNestedLocal.localMethod',
+      'Class.instanceNestedLocal.localMethod.<anonymous function>',
+      'Class.instanceNestedLocal.localMethod.nestedLocalMethod'
     ]);
   });
 }
diff --git a/tests/corelib_2/bigint_test.dart b/tests/corelib_2/bigint_test.dart
index 0401e12..ed526b4 100644
--- a/tests/corelib_2/bigint_test.dart
+++ b/tests/corelib_2/bigint_test.dart
@@ -280,6 +280,33 @@
   Expect.equals(-BigInt.parse("1000000001000000000"), a * b);
 }
 
+testBigintAnd() {
+  var a = BigInt.parse("0x55555555555555555555");
+  var b = BigInt.parse("0x33333333333333333333");
+  var c = BigInt.parse("0x11111111111111111111");
+  Expect.equals(BigInt.zero, BigInt.zero & a);
+  Expect.equals(BigInt.zero, a & BigInt.zero);
+  Expect.equals(c, a & b);
+}
+
+testBigintOr() {
+  var a = BigInt.parse("0x33333333333333333333");
+  var b = BigInt.parse("0x55555555555555555555");
+  var c = BigInt.parse("0x77777777777777777777");
+  Expect.equals(a, BigInt.zero | a);
+  Expect.equals(a, a | BigInt.zero);
+  Expect.equals(c, a | b);
+}
+
+testBigintXor() {
+  var a = BigInt.parse("0x33333333333333333333");
+  var b = BigInt.parse("0x55555555555555555555");
+  var c = BigInt.parse("0x66666666666666666666");
+  Expect.equals(a, BigInt.zero ^ a);
+  Expect.equals(a, a ^ BigInt.zero);
+  Expect.equals(c, a ^ b);
+}
+
 testBigintAdd() {
   // Bigint and Smi.
   var a = BigInt.parse("12345678901234567890");
@@ -289,6 +316,8 @@
   // Bigint and Bigint.
   a = BigInt.parse("10000000000000000001");
   Expect.equals(BigInt.parse("20000000000000000002"), a + a);
+  Expect.equals(a, BigInt.zero + a);
+  Expect.equals(a, a + BigInt.zero);
 }
 
 testBigintSub() {
@@ -300,6 +329,8 @@
   // Bigint and Bigint.
   a = BigInt.parse("10000000000000000001");
   Expect.equals(BigInt.parse("20000000000000000002"), a + a);
+  Expect.equals(-a, BigInt.zero - a);
+  Expect.equals(a, a - BigInt.zero);
 }
 
 testBigintMul() {
@@ -634,6 +665,12 @@
 }
 
 testShiftAmount() {
+  Expect.equals(BigInt.zero, BigInt.zero << 0);
+  Expect.equals(BigInt.zero, BigInt.zero >> 0);
+  Expect.equals(BigInt.zero, BigInt.zero << 1234567890);
+  Expect.equals(BigInt.zero, BigInt.zero >> 1234567890);
+  Expect.equals(BigInt.two.pow(999), BigInt.one << 999);
+  Expect.equals(BigInt.one, BigInt.two.pow(999) >> 999);
   Expect.equals(BigInt.zero, new BigInt.from(12) >> 0x7FFFFFFFFFFFFFFF);
   Expect.equals(-BigInt.one, -new BigInt.from(12) >> 0x7FFFFFFFFFFFFFFF);
   bool exceptionCaught = false;
@@ -910,6 +947,9 @@
     testModInverse();
     testGcd();
     testSmiOverflow();
+    testBigintAnd();
+    testBigintOr();
+    testBigintXor();
     testBigintAdd();
     testBigintSub();
     testBigintMul();
diff --git a/tests/corelib_2/corelib_2.status b/tests/corelib_2/corelib_2.status
index 4083750a..2890a4f 100644
--- a/tests/corelib_2/corelib_2.status
+++ b/tests/corelib_2/corelib_2.status
@@ -87,6 +87,9 @@
 [ !$strong ]
 cast_test: SkipByDesign # Uses generic method parameters.
 
+[ $arch == ia32 && $builder_tag == optimization_counter_threshold ]
+bigint_from_test: RuntimeError # Issue 32619
+
 [ $arch == simarmv5te && ($runtime == dart_precompiled || $runtime == vm) ]
 int_parse_radix_test/*: Pass, Slow
 integer_parsed_mul_div_vm_test: Pass, Slow
@@ -213,10 +216,8 @@
 
 [ $compiler == dart2js && $fasta && $host_checked && $strong ]
 apply3_test: RuntimeError
-apply_test: Crash # 'file:*/pkg/compiler/lib/src/js_emitter/runtime_type_generator.dart': Failed assertion: line 208 pos 18: '!(_useKernel && _strongMode && !_disableRtiOptimization) ||
 bigint_test: RuntimeError
 cast_test: RuntimeError
-date_time11_test: Crash # 'file:*/pkg/compiler/lib/src/js_emitter/runtime_type_generator.dart': Failed assertion: line 208 pos 18: '!(_useKernel && _strongMode && !_disableRtiOptimization) ||
 dynamic_nosuchmethod_test: RuntimeError
 error_stack_trace1_test: RuntimeError # Issue 12399
 growable_list_test: RuntimeError # Concurrent modifications test always runs
@@ -232,7 +233,6 @@
 iterable_return_type_test/01: RuntimeError # Issue 20085
 iterable_return_type_test/02: RuntimeError # Dart2js does not support Uint64*.
 iterable_to_list_test/01: RuntimeError # Issue 26501
-iterable_where_type_test: Crash # 'file:*/pkg/compiler/lib/src/js_emitter/runtime_type_generator.dart': Failed assertion: line 208 pos 18: '!(_useKernel && _strongMode && !_disableRtiOptimization) ||
 list_concurrent_modify_test: RuntimeError # dart2js does not fully implement these
 list_test/01: RuntimeError
 list_test/none: RuntimeError
diff --git a/tests/html/audiobuffersourcenode_test.dart b/tests/html/audiobuffersourcenode_test.dart
index 34dc221..7da731f 100644
--- a/tests/html/audiobuffersourcenode_test.dart
+++ b/tests/html/audiobuffersourcenode_test.dart
@@ -19,7 +19,7 @@
         var ctx = new AudioContext();
         AudioBufferSourceNode node = ctx.createBufferSource();
         expect(node is AudioBufferSourceNode, isTrue);
-        node.start2(ctx.currentTime, 0, 2);
+        node.start(ctx.currentTime, 0, 2);
         expect(node is AudioBufferSourceNode, isTrue);
       }
     });
diff --git a/tests/html/html.status b/tests/html/html.status
index bd4fae9..2b26a61 100644
--- a/tests/html/html.status
+++ b/tests/html/html.status
@@ -125,6 +125,7 @@
 audiobuffersourcenode_test/functional: RuntimeError
 canvasrenderingcontext2d_test/drawImage_video_element: Fail # Safari does not support drawImage w/ video element
 canvasrenderingcontext2d_test/drawImage_video_element_dataUrl: Fail # Safari does not support drawImage w/ video element
+css_test/functional: RuntimeError # Issue 32576
 element_animate_test: Fail # Element.animate not supported on these browsers.
 element_test: Pass, Fail # Issue 21434
 element_types_test/supported_content: Fail # Safari Feature support statuses - All changes should be accompanied by platform support annotation changes.
@@ -150,6 +151,7 @@
 rtc_test/supported: Fail # Safari Feature support statuses - All changes should be accompanied by platform support annotation changes.
 shadow_dom_test/supported: Fail # Safari Feature support statuses - All changes should be accompanied by platform support annotation changes.
 speechrecognition_test/supported: Fail # Safari Feature support statuses - All changes should be accompanied by platform support annotation changes.
+svgelement_test/getBoundingClientRect: RuntimeError # Issue 32572
 touchevent_test/supported: Fail # Safari does not support TouchEvents
 webgl_1_test: Pass, Fail # Issue 8219
 worker_api_test: Skip # Issue 13221
diff --git a/tests/language/language_dart2js.status b/tests/language/language_dart2js.status
index 5161156..9cc7e0e 100644
--- a/tests/language/language_dart2js.status
+++ b/tests/language/language_dart2js.status
@@ -10,6 +10,7 @@
 full_stacktrace1_test: Pass, RuntimeError # Issue 12698
 full_stacktrace2_test: Pass, RuntimeError # Issue 12698
 full_stacktrace3_test: Pass, RuntimeError # Issue 12698
+library_env_test/has_no_html_support: RuntimeError, OK
 local_function_test: RuntimeError # Issue 31879
 vm/*: Skip # Issue 12699
 
@@ -29,7 +30,6 @@
 override_field_test/02: Pass, Slow # TODO(kasperl): Please triage.
 
 [ $compiler == dart2js && $runtime == d8 && $fasta ]
-library_env_test/has_no_io_support: RuntimeError
 regress_23408_test: RuntimeError
 
 [ $compiler == dart2js && $runtime != drt ]
@@ -66,20 +66,19 @@
 [ $compiler == dart2js && $system == windows && !$fasta && ($runtime == chrome || $runtime == ff) ]
 string_literals_test: RuntimeError # Issue 27533
 
+[ $compiler == dart2js && $browser ]
+config_import_test: RuntimeError # Test flag is not passed to the compiler.
+library_env_test/has_io_support: RuntimeError, OK # dart2js doesn't support io when using '--categories=Client'.
+
 [ $compiler == dart2js && $browser && $csp && !$fast_startup ]
 conditional_import_string_test: Fail # Issue 30615
 conditional_import_test: Fail # Issue 30615
 
-[ $compiler == dart2js && $browser && $fasta ]
-conditional_import_string_test: RuntimeError
-conditional_import_test: RuntimeError
-config_import_corelib_test: RuntimeError
-library_env_test/has_io_support: RuntimeError
+[ $compiler == dart2js && !$browser ]
+library_env_test/has_no_io_support: RuntimeError, OK # dart2js supports io when using '--categories=all'.
 
-[ $compiler == dart2js && $browser && !$fasta ]
-config_import_test: Fail # Test flag is not passed to the compiler.
-library_env_test/has_io_support: RuntimeError # Issue 27398
-library_env_test/has_no_io_support: Pass # Issue 27398
+[ $compiler == dart2js && !$browser && $fasta ]
+config_import_corelib_test: RuntimeError, OK # all dart:* are supported when using '--categories=all'.
 
 [ $compiler == dart2js && $checked && $fasta ]
 assertion_initializer_const_function_test/01: RuntimeError
@@ -332,7 +331,7 @@
 class_literal_test/01: RuntimeError
 class_literal_test/03: RuntimeError
 class_literal_test/07: RuntimeError
-config_import_test: RuntimeError
+config_import_test: RuntimeError # not supported by fasta
 const_error_multiply_initialized_test/02: MissingCompileTimeError
 const_error_multiply_initialized_test/04: MissingCompileTimeError
 const_evaluation_test/01: RuntimeError
@@ -408,8 +407,7 @@
 invocation_mirror_test: RuntimeError # mirrors not supported
 issue21079_test: RuntimeError
 left_shift_test: RuntimeError
-library_env_test/has_mirror_support: RuntimeError
-library_env_test/has_no_html_support: RuntimeError
+library_env_test/has_mirror_support: RuntimeError, OK
 list_literal4_test: RuntimeError
 main_not_a_function_test/01: CompileTimeError
 many_overridden_no_such_method_test: RuntimeError
@@ -688,9 +686,7 @@
 invocation_mirror2_test: RuntimeError # Issue 6490 (wrong retval).
 invocation_mirror_empty_arguments_test: Fail # Issue 24331
 left_shift_test: RuntimeError # Issue 1533
-library_env_test/has_no_html_support: RuntimeError, OK # The following tests are supposed to fail. In testing-mode, dart2js supports all dart:X libraries (because it uses '--categories=all').
-library_env_test/has_no_io_support: RuntimeError, OK # The following tests are supposed to fail. In testing-mode, dart2js supports all dart:X libraries (because it uses '--categories=all').
-library_env_test/has_no_mirror_support: RuntimeError, OK # The following tests are supposed to fail. In testing-mode, dart2js supports all dart:X libraries (because it uses '--categories=all').
+library_env_test/has_no_mirror_support: RuntimeError, OK
 list_literal4_test: RuntimeError # Issue 12890
 malformed_test/none: Fail # Expect failure in lib/_internal/js_runtime/lib/preambles/d8.js
 method_override5_test: RuntimeError # Issue 12809
diff --git a/tests/language_2/language_2_dart2js.status b/tests/language_2/language_2_dart2js.status
index f42f191..acf2b12 100644
--- a/tests/language_2/language_2_dart2js.status
+++ b/tests/language_2/language_2_dart2js.status
@@ -6,9 +6,12 @@
 [ $compiler == dart2js ]
 async_star_cancel_while_paused_test: RuntimeError # Issue 22853
 bit_operations_test: RuntimeError, OK # non JS number semantics
+config_import_corelib_test: CompileTimeError # we need a special platform.dill file for categories=all. Once we fix that, all dart:* are supported when using '--categories=all' so this will become a RuntimeError, OK.
 config_import_test: RuntimeError # Test flag is not passed to the compiler.
 double_identical_test: RuntimeError # Negative and positive zero are distinct, but not in dart2js; bug #11551.
 issue23244_test: RuntimeError # Isolates - enum canonicalization - Issue 23244
+library_env_test/has_mirror_support: RuntimeError, OK
+library_env_test/has_no_html_support: RuntimeError, OK
 null_test/mirrors: SkipByDesign # Uses mirrors.
 vm/*: SkipByDesign # Tests for the VM.
 
@@ -176,13 +179,15 @@
 string_literals_test: Pass, RuntimeError # Failures on dart2js-win7-chrome-4-4-be and dart2js-win7-ie11ff-4-4-be
 
 [ $compiler == dart2js && $browser ]
-library_env_test/has_io_support: RuntimeError # Issue 27398
-library_env_test/has_no_io_support: Pass # Issue 27398
+library_env_test/has_io_support: RuntimeError, OK # dart2js doesn't support io when compiling on --categories=Client
 
 [ $compiler == dart2js && $browser && $csp && !$fast_startup ]
 conditional_import_string_test: Fail # Issue 30615
 conditional_import_test: Fail # Issue 30615
 
+[ $compiler == dart2js && !$browser ]
+library_env_test/has_no_io_support: RuntimeError, OK # dart2js supports io when using '--categories=all'.
+
 [ $compiler == dart2js && $checked ]
 covariant_subtyping_test: CompileTimeError
 
@@ -584,24 +589,23 @@
 assertion_test: RuntimeError, OK
 
 [ $compiler == dart2js && !$checked && $fasta ]
+cascaded_forwarding_stubs_generic_test: RuntimeError
+cascaded_forwarding_stubs_test: RuntimeError
+checked_setter3_test: RuntimeError # Issue 31128
 constructor_call_as_function_test: CompileTimeError # Issue 32517
-implicit_creation/implicit_const_context_prefix_constructor_test: CompileTimeError # Issue 32517
-implicit_creation/implicit_new_constructor_named_test: CompileTimeError # Issue 32517
+forwarding_semi_stub_test: RuntimeError
+forwarding_stub_tearoff_generic_test: RuntimeError
+forwarding_stub_tearoff_test: RuntimeError
 implicit_creation/implicit_const_context_constructor_generic_test: CompileTimeError # Issue 32517
-implicit_creation/implicit_const_context_prefix_constructor_named_test: CompileTimeError # Issue 32517
 implicit_creation/implicit_const_context_constructor_named_test: CompileTimeError # Issue 32517
 implicit_creation/implicit_const_context_constructor_test: CompileTimeError # Issue 32517
+implicit_creation/implicit_const_context_prefix_constructor_named_test: CompileTimeError # Issue 32517
+implicit_creation/implicit_const_context_prefix_constructor_test: CompileTimeError # Issue 32517
+implicit_creation/implicit_new_constructor_named_test: CompileTimeError # Issue 32517
 implicit_creation/implicit_new_constructor_test: CompileTimeError # Issue 32517
 implicit_creation/implicit_new_or_const_composite_test: CompileTimeError # Issue 32517
 implicit_creation/implicit_new_or_const_test: CompileTimeError # Issue 32517
 implicit_creation/implicit_new_prefix_constructor_named_test: CompileTimeError # Issue 32517
-
-cascaded_forwarding_stubs_generic_test: RuntimeError
-cascaded_forwarding_stubs_test: RuntimeError
-checked_setter3_test: RuntimeError # Issue 31128
-forwarding_semi_stub_test: RuntimeError
-forwarding_stub_tearoff_generic_test: RuntimeError
-forwarding_stub_tearoff_test: RuntimeError
 implicit_downcast_during_assignment_test: RuntimeError
 implicit_downcast_during_combiner_test: RuntimeError
 implicit_downcast_during_compound_assignment_test: RuntimeError
@@ -1231,8 +1235,6 @@
 compile_time_constant_static5_test/16: CompileTimeError
 compile_time_constant_static5_test/21: CompileTimeError
 compile_time_constant_static5_test/23: CompileTimeError
-conditional_import_string_test: CompileTimeError
-conditional_import_test: CompileTimeError
 conditional_rewrite_test: RuntimeError
 config_import_corelib_test: CompileTimeError
 config_import_test: RuntimeError
@@ -1418,7 +1420,6 @@
 generic_no_such_method_dispatcher_simple_test: CompileTimeError
 generic_no_such_method_dispatcher_test: CompileTimeError
 generic_tearoff_test: CompileTimeError
-generic_test: RuntimeError
 getter_override2_test/02: MissingCompileTimeError
 getter_override_test/00: MissingCompileTimeError
 getter_override_test/01: MissingCompileTimeError
@@ -1626,6 +1627,7 @@
 no_such_method_test: RuntimeError
 nosuchmethod_forwarding/nosuchmethod_forwarding_test/05: RuntimeError
 nosuchmethod_forwarding/nosuchmethod_forwarding_test/06: RuntimeError
+nosuchmethod_forwarding/nosuchmethod_forwarding_arguments_test: RuntimeError
 null_no_such_method_test: CompileTimeError
 null_test/mirrors: RuntimeError
 null_test/none: RuntimeError
@@ -1854,8 +1856,8 @@
 void_type_usage_test/conditional2_dynamic_init: Crash # 'package:front_end/src/fasta/type_inference/type_schema_environment.dart': Failed assertion: line 214 pos 12: 'false': is not true.
 void_type_usage_test/conditional2_for: Crash # 'package:front_end/src/fasta/type_inference/type_schema_environment.dart': Failed assertion: line 214 pos 12: 'false': is not true.
 void_type_usage_test/conditional2_literal_list_init: Crash # 'package:front_end/src/fasta/type_inference/type_schema_environment.dart': Failed assertion: line 214 pos 12: 'false': is not true.
-void_type_usage_test/conditional2_literal_map_value_init2: Crash # 'package:front_end/src/fasta/type_inference/type_schema_environment.dart': Failed assertion: line 214 pos 12: 'false': is not true.
 void_type_usage_test/conditional2_literal_map_value_init: Crash # 'package:front_end/src/fasta/type_inference/type_schema_environment.dart': Failed assertion: line 214 pos 12: 'false': is not true.
+void_type_usage_test/conditional2_literal_map_value_init2: Crash # 'package:front_end/src/fasta/type_inference/type_schema_environment.dart': Failed assertion: line 214 pos 12: 'false': is not true.
 void_type_usage_test/conditional2_null_equals2: Crash # 'package:front_end/src/fasta/type_inference/type_schema_environment.dart': Failed assertion: line 214 pos 12: 'false': is not true.
 void_type_usage_test/conditional2_parens: Crash # 'package:front_end/src/fasta/type_inference/type_schema_environment.dart': Failed assertion: line 214 pos 12: 'false': is not true.
 void_type_usage_test/conditional2_return: Crash # 'package:front_end/src/fasta/type_inference/type_schema_environment.dart': Failed assertion: line 214 pos 12: 'false': is not true.
@@ -1871,8 +1873,8 @@
 void_type_usage_test/conditional3_dynamic_init: Crash # 'package:front_end/src/fasta/type_inference/type_schema_environment.dart': Failed assertion: line 214 pos 12: 'false': is not true.
 void_type_usage_test/conditional3_for: Crash # 'package:front_end/src/fasta/type_inference/type_schema_environment.dart': Failed assertion: line 214 pos 12: 'false': is not true.
 void_type_usage_test/conditional3_literal_list_init: Crash # 'package:front_end/src/fasta/type_inference/type_schema_environment.dart': Failed assertion: line 214 pos 12: 'false': is not true.
-void_type_usage_test/conditional3_literal_map_value_init2: Crash # 'package:front_end/src/fasta/type_inference/type_schema_environment.dart': Failed assertion: line 214 pos 12: 'false': is not true.
 void_type_usage_test/conditional3_literal_map_value_init: Crash # 'package:front_end/src/fasta/type_inference/type_schema_environment.dart': Failed assertion: line 214 pos 12: 'false': is not true.
+void_type_usage_test/conditional3_literal_map_value_init2: Crash # 'package:front_end/src/fasta/type_inference/type_schema_environment.dart': Failed assertion: line 214 pos 12: 'false': is not true.
 void_type_usage_test/conditional3_null_equals2: Crash # 'package:front_end/src/fasta/type_inference/type_schema_environment.dart': Failed assertion: line 214 pos 12: 'false': is not true.
 void_type_usage_test/conditional3_parens: Crash # 'package:front_end/src/fasta/type_inference/type_schema_environment.dart': Failed assertion: line 214 pos 12: 'false': is not true.
 void_type_usage_test/conditional3_return: Crash # 'package:front_end/src/fasta/type_inference/type_schema_environment.dart': Failed assertion: line 214 pos 12: 'false': is not true.
@@ -1990,8 +1992,6 @@
 compile_time_constant_static5_test/16: CompileTimeError
 compile_time_constant_static5_test/21: CompileTimeError
 compile_time_constant_static5_test/23: CompileTimeError
-conditional_import_string_test: CompileTimeError
-conditional_import_test: CompileTimeError
 conditional_rewrite_test: RuntimeError
 config_import_corelib_test: CompileTimeError
 config_import_test: RuntimeError
@@ -2387,6 +2387,7 @@
 no_such_method_test: RuntimeError
 nosuchmethod_forwarding/nosuchmethod_forwarding_test/05: RuntimeError
 nosuchmethod_forwarding/nosuchmethod_forwarding_test/06: RuntimeError
+nosuchmethod_forwarding/nosuchmethod_forwarding_arguments_test: RuntimeError
 null_no_such_method_test: CompileTimeError
 null_test/mirrors: RuntimeError
 null_test/none: RuntimeError
@@ -2610,4 +2611,3 @@
 mixin_mixin_bound2_test: RuntimeError # Issue 31054
 mixin_mixin_bound_test: RuntimeError # Issue 31054
 mixin_mixin_type_arguments_test: RuntimeError # Issue 31054
-
diff --git a/tests/language_2/language_2_dartdevc.status b/tests/language_2/language_2_dartdevc.status
index e94da20..2dfeef7 100644
--- a/tests/language_2/language_2_dartdevc.status
+++ b/tests/language_2/language_2_dartdevc.status
@@ -167,6 +167,7 @@
 multiline_newline_test/none: RuntimeError
 multiple_interface_inheritance_test: CompileTimeError # Issue 30552
 nested_generic_closure_test: CompileTimeError
+nosuchmethod_forwarding/nosuchmethod_forwarding_arguments_test: RuntimeError # Issue 31425
 override_inheritance_field_test/04: CompileTimeError
 override_inheritance_field_test/06: CompileTimeError
 override_inheritance_field_test/26: CompileTimeError
@@ -612,6 +613,7 @@
 named_parameters_default_eq_test/02: MissingCompileTimeError
 no_such_method_mock_test: RuntimeError # Issue 31425
 nosuchmethod_forwarding/nosuchmethod_forwarding_test/06: RuntimeError # Issue 31425
+nosuchmethod_forwarding/nosuchmethod_forwarding_arguments_test: RuntimeError # Issue 31425
 nsm5_test: MissingCompileTimeError
 null2_test: RuntimeError # Issue 32194
 null_method_test: RuntimeError # Issue 32194
@@ -885,4 +887,3 @@
 switch_try_catch_test: RuntimeError # Issue 29920; Expect.throws: Unexpected 'UnimplementedError: node <ShadowContinueSwitchStatement> see https://github.com/dart-lang/sdk/issues/29352 `continue #L1;
 truncdiv_test: RuntimeError # Issue 29920; Expect.throws fails: Did not throw
 vm/*: SkipByDesign # VM only tests.; VM only tests.
-
diff --git a/tests/language_2/language_2_kernel.status b/tests/language_2/language_2_kernel.status
index cea3c5c..776be24 100644
--- a/tests/language_2/language_2_kernel.status
+++ b/tests/language_2/language_2_kernel.status
@@ -717,8 +717,6 @@
 no_main_test/01: Skip
 no_main_test/01: DartkCrash
 no_such_method_mock_test: RuntimeError # Issue 31426
-nosuchmethod_forwarding/nosuchmethod_forwarding_test/05: RuntimeError # Issue 31426
-nosuchmethod_forwarding/nosuchmethod_forwarding_test/06: RuntimeError # Issue 31426
 null_no_such_method_test: CompileTimeError # Issue 31533
 override_inheritance_field_test/04: CompileTimeError # Issue 31616
 override_inheritance_field_test/06: CompileTimeError # Issue 31616
@@ -1075,8 +1073,6 @@
 no_main_test/01: Skip
 no_such_method_mock_test: RuntimeError
 no_such_method_test: SkipByDesign
-nosuchmethod_forwarding/nosuchmethod_forwarding_test/05: RuntimeError # Issue 31426
-nosuchmethod_forwarding/nosuchmethod_forwarding_test/06: RuntimeError # Issue 31426
 null_no_such_method_test: CompileTimeError # Issue 31533
 null_test/mirrors: Skip # Uses mirrors.
 null_test/none: SkipByDesign
@@ -2209,4 +2205,3 @@
 [ $compiler == dartk || $compiler == dartkp ]
 generic_function_bounds_test: RuntimeError # Issue 32076
 generic_test/01: MissingCompileTimeError
-
diff --git a/tests/language_2/language_2_vm.status b/tests/language_2/language_2_vm.status
index a6dedf1..dfc7a3b 100644
--- a/tests/language_2/language_2_vm.status
+++ b/tests/language_2/language_2_vm.status
@@ -1328,6 +1328,7 @@
 generic_methods_test: Pass # Issue 25869
 nosuchmethod_forwarding/nosuchmethod_forwarding_test/05: RuntimeError
 nosuchmethod_forwarding/nosuchmethod_forwarding_test/06: RuntimeError
+nosuchmethod_forwarding/nosuchmethod_forwarding_arguments_test: RuntimeError
 nsm5_test: MissingCompileTimeError
 override_inheritance_no_such_method_test/05: MissingCompileTimeError
 
@@ -1346,4 +1347,3 @@
 invalid_type_argument_count_test/03: MissingCompileTimeError # Error only in strong mode
 invalid_type_argument_count_test/04: MissingCompileTimeError # Error only in strong mode
 partial_tearoff_instantiation_test/none: CompileTimeError
-
diff --git a/tests/language_2/nosuchmethod_forwarding/nosuchmethod_forwarding_arguments_test.dart b/tests/language_2/nosuchmethod_forwarding/nosuchmethod_forwarding_arguments_test.dart
new file mode 100644
index 0000000..cf5b1be
--- /dev/null
+++ b/tests/language_2/nosuchmethod_forwarding/nosuchmethod_forwarding_arguments_test.dart
@@ -0,0 +1,84 @@
+// Copyright (c) 2018, 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.
+
+// Testing that `noSuchMethod` forwarding properly handles optional, named and
+// type parameters, and result type checking.
+
+import 'package:expect/expect.dart';
+
+class A {
+  dynamic noSuchMethod(Invocation invoke) {
+    if (invoke.memberName == #test0) {
+      Expect.equals(invoke.positionalArguments[0], 1);
+      Expect.equals(invoke.positionalArguments[1], 2);
+      return null;
+    } else if (invoke.memberName == #test1) {
+      Expect.isTrue(invoke.namedArguments.isEmpty);
+      return null;
+    } else if (invoke.memberName == #test2) {
+      Expect.isTrue(invoke.namedArguments.isEmpty);
+      return null;
+    } else if (invoke.memberName == #test3) {
+      Expect.equals(invoke.namedArguments[#x], "ok");
+      return null;
+    } else if (invoke.memberName == #test4) {
+      Expect.equals(invoke.positionalArguments[0], "ok");
+      return null;
+    } else if (invoke.memberName == #test5) {
+      Expect.equals(invoke.typeArguments[0].toString(), "int");
+      return null;
+    } else if (invoke.memberName == #test6) {
+      return 1;
+    } else if (invoke.memberName == #allTogetherNow) {
+      Expect.equals(invoke.typeArguments.length, 2);
+      Expect.equals(invoke.typeArguments[0].toString(), "num");
+      Expect.equals(invoke.typeArguments[1].toString(), "double");
+
+      Expect.equals(invoke.positionalArguments.length, 1);
+      Expect.equals(invoke.positionalArguments[0], 2.0);
+
+      Expect.equals(invoke.namedArguments.length, 1);
+      Expect.equals(invoke.namedArguments[#foo], const <num>[3, 4]);
+    }
+  }
+
+  void test0(int x, int y);
+  void test1({String x});
+  void test2({String x: "w/e"});
+  void test3({String x: "w/e"});
+  void test4([String x]);
+  void test5<T extends num>(T x);
+  String test6();
+
+  T allTogetherNow<T, S extends T>(S x1, {List<T> foo: const <Null>[]});
+}
+
+main() {
+  var a = new A();
+
+  a.test0(1, 2);
+  (a.test0 as dynamic)(1, 2);
+
+  a.test1();
+  (a.test1 as dynamic)();
+
+  a.test2();
+  (a.test2 as dynamic)();
+
+  a.test3(x: "ok");
+  (a.test3 as dynamic)(x: "ok");
+
+  a.test4("ok");
+  (a.test4 as dynamic)("ok");
+
+  a.test5<int>(1);
+  (a.test5 as dynamic)<int>(1);
+  Expect.throwsTypeError(() => (a.test5 as dynamic)<String>("foo"));
+  Expect.throwsTypeError(() => (a.test5 as dynamic)<int>(3.0));
+
+  Expect.throwsTypeError(() => a.test6());
+  Expect.throwsTypeError(() => (a.test6 as dynamic)());
+
+  a.allTogetherNow<num, double>(2.0, foo: const <num>[3, 4]);
+}
diff --git a/tests/lib_2/async/future_or_type_test.dart b/tests/lib_2/async/future_or_type_test.dart
new file mode 100644
index 0000000..df5a014
--- /dev/null
+++ b/tests/lib_2/async/future_or_type_test.dart
@@ -0,0 +1,254 @@
+// Copyright (c) 2018, 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.
+
+// In strong mode, `FutureOr` should be a valid type in most locations.
+
+import 'dart:async';
+import 'package:expect/expect.dart';
+
+typedef void FunTakes<T>(T x);
+typedef T FunReturns<T>();
+
+main() {
+  // Some useful values.
+  dynamic n = null;
+  dynamic i = 0;
+  dynamic d = 1.5;
+  dynamic fni = new Future<num>.value(i);
+  dynamic fnd = new Future<num>.value(d);
+  dynamic fi = new Future<int>.value(i);
+  dynamic fd = new Future<double>.value(d);
+  dynamic fn = new Future<Null>.value(null);
+
+  dynamic o = new Object();
+  dynamic fo = new Future<Object>.value(o);
+  dynamic foi = new Future<Object>.value(i);
+
+  if (typeAssertionsEnabled) {
+    // Type annotation allows correct values.
+    FutureOr<num> v;
+    v = n;
+    v = i;
+    v = d;
+    v = fni;
+    v = fnd;
+    v = fi;
+    v = fd;
+    v = fn;
+    // Disallows invalid values.
+    // These are all valid down-casts that fail at runtime.
+    Expect.throws(() => v = o);
+    Expect.throws(() => v = fo);
+    Expect.throws(() => v = foi);
+
+    void fun(FutureOr<num> v) {}
+    fun(n);
+    fun(i);
+    fun(d);
+    fun(fni);
+    fun(fnd);
+    fun(fi);
+    fun(fd);
+    fun(fn);
+    // Disallows invalid values.
+    // These are all valid down-casts that fail at runtime.
+    Expect.throws(() => fun(o));
+    Expect.throws(() => fun(fo));
+    Expect.throws(() => fun(foi));
+
+    FutureOr<num> fun2(Object o) => o; // implicit down-cast to return type.
+    fun2(n);
+    fun2(i);
+    fun2(d);
+    fun2(fni);
+    fun2(fnd);
+    fun2(fi);
+    fun2(fd);
+    fun2(fn);
+    // Disallows invalid values.
+    Expect.throws(() => fun2(o));
+    Expect.throws(() => fun2(fo));
+    Expect.throws(() => fun2(foi));
+
+    List<Object> list = new List<FutureOr<num>>();
+    list.add(n);
+    list.add(i);
+    list.add(d);
+    list.add(fni);
+    list.add(fnd);
+    list.add(fi);
+    list.add(fd);
+    list.add(fn);
+    Expect.throws(() => list.add(o));
+    Expect.throws(() => list.add(fo));
+    Expect.throws(() => list.add(foi));
+  }
+
+  {
+    // Casts.
+    FutureOr<num> v;
+    v = n as FutureOr<num>;
+    v = i as FutureOr<num>;
+    v = d as FutureOr<num>;
+    v = fni as FutureOr<num>;
+    v = fnd as FutureOr<num>;
+    v = fi as FutureOr<num>;
+    v = fd as FutureOr<num>;
+    v = fn as FutureOr<num>;
+    // Disallows invalid values.
+    // These are all valid down-casts that fail at runtime.
+    Expect.throws(() => v = o as FutureOr<num>);
+    Expect.throws(() => v = fo as FutureOr<num>);
+    Expect.throws(() => v = foi as FutureOr<num>);
+  }
+
+  {
+    // on-catch
+    String check(Object o) {
+      try {
+        throw o;
+      } on FutureOr<num> {
+        return "caught";
+      } on Object {
+        return "uncaught";
+      }
+    }
+
+    // Can't throw null, so no `n` case here.
+    Expect.equals("caught", check(i));
+    Expect.equals("caught", check(d));
+    Expect.equals("caught", check(fni));
+    Expect.equals("caught", check(fnd));
+    Expect.equals("caught", check(fi));
+    Expect.equals("caught", check(fd));
+    Expect.equals("caught", check(fn));
+
+    Expect.equals("uncaught", check(o));
+    Expect.equals("uncaught", check(fo));
+    Expect.equals("uncaught", check(foi));
+  }
+
+  {
+    // Type variable bound.
+    var valids = <C<FutureOr<num>>>[
+      new C<Null>(),
+      new C<int>(),
+      new C<double>(),
+      new C<num>(),
+      new C<Future<Null>>(),
+      new C<Future<int>>(),
+      new C<Future<double>>(),
+      new C<Future<num>>(),
+      new C<FutureOr<Null>>(),
+      new C<FutureOr<int>>(),
+      new C<FutureOr<double>>(),
+      new C<FutureOr<num>>(),
+    ];
+    Expect.equals(12, valids.length);
+  }
+
+  {
+    // Dynamic checks.
+    Expect.isFalse(new C<FutureOr<num>>().isCheck(n));
+    Expect.isTrue(new C<FutureOr<num>>().isCheck(i));
+    Expect.isTrue(new C<FutureOr<num>>().isCheck(d));
+    Expect.isTrue(new C<FutureOr<num>>().isCheck(fni));
+    Expect.isTrue(new C<FutureOr<num>>().isCheck(fnd));
+    Expect.isTrue(new C<FutureOr<num>>().isCheck(fi));
+    Expect.isTrue(new C<FutureOr<num>>().isCheck(fd));
+    Expect.isTrue(new C<FutureOr<num>>().isCheck(fn));
+    Expect.isFalse(new C<FutureOr<num>>().isCheck(o));
+    Expect.isFalse(new C<FutureOr<num>>().isCheck(fo));
+    Expect.isFalse(new C<FutureOr<num>>().isCheck(foi));
+
+    Expect.isFalse(new C<FutureOr<int>>().isCheck(n));
+    Expect.isTrue(new C<FutureOr<int>>().isCheck(i));
+    Expect.isFalse(new C<FutureOr<int>>().isCheck(d));
+    Expect.isFalse(new C<FutureOr<int>>().isCheck(fni));
+    Expect.isFalse(new C<FutureOr<int>>().isCheck(fnd));
+    Expect.isTrue(new C<FutureOr<int>>().isCheck(fi));
+    Expect.isFalse(new C<FutureOr<int>>().isCheck(fd));
+    Expect.isTrue(new C<FutureOr<int>>().isCheck(fn));
+    Expect.isFalse(new C<FutureOr<int>>().isCheck(o));
+    Expect.isFalse(new C<FutureOr<int>>().isCheck(fo));
+    Expect.isFalse(new C<FutureOr<int>>().isCheck(foi));
+
+    Expect.isTrue(new C<FutureOr<Null>>().isCheck(n));
+    Expect.isFalse(new C<FutureOr<Null>>().isCheck(i));
+    Expect.isFalse(new C<FutureOr<Null>>().isCheck(d));
+    Expect.isFalse(new C<FutureOr<Null>>().isCheck(fni));
+    Expect.isFalse(new C<FutureOr<Null>>().isCheck(fnd));
+    Expect.isFalse(new C<FutureOr<Null>>().isCheck(fi));
+    Expect.isFalse(new C<FutureOr<Null>>().isCheck(fd));
+    Expect.isTrue(new C<FutureOr<Null>>().isCheck(fn));
+    Expect.isFalse(new C<FutureOr<Null>>().isCheck(o));
+    Expect.isFalse(new C<FutureOr<Null>>().isCheck(fo));
+    Expect.isFalse(new C<FutureOr<Null>>().isCheck(foi));
+
+    Expect.isFalse(new C<Future<num>>().isCheck(n));
+    Expect.isFalse(new C<Future<num>>().isCheck(i));
+    Expect.isFalse(new C<Future<num>>().isCheck(d));
+    Expect.isTrue(new C<Future<num>>().isCheck(fni));
+    Expect.isTrue(new C<Future<num>>().isCheck(fnd));
+    Expect.isTrue(new C<Future<num>>().isCheck(fi));
+    Expect.isTrue(new C<Future<num>>().isCheck(fd));
+    Expect.isTrue(new C<Future<num>>().isCheck(fn));
+    Expect.isFalse(new C<Future<num>>().isCheck(o));
+    Expect.isFalse(new C<Future<num>>().isCheck(fo));
+    Expect.isFalse(new C<Future<num>>().isCheck(foi));
+
+    Expect.isFalse(new C<Future<int>>().isCheck(n));
+    Expect.isFalse(new C<Future<int>>().isCheck(i));
+    Expect.isFalse(new C<Future<int>>().isCheck(d));
+    Expect.isFalse(new C<Future<int>>().isCheck(fni));
+    Expect.isFalse(new C<Future<int>>().isCheck(fnd));
+    Expect.isTrue(new C<Future<int>>().isCheck(fi));
+    Expect.isFalse(new C<Future<int>>().isCheck(fd));
+    Expect.isTrue(new C<Future<int>>().isCheck(fn));
+    Expect.isFalse(new C<Future<int>>().isCheck(o));
+    Expect.isFalse(new C<Future<int>>().isCheck(fo));
+    Expect.isFalse(new C<Future<int>>().isCheck(foi));
+
+    Expect.isFalse(new C<num>().isCheck(n));
+    Expect.isTrue(new C<num>().isCheck(i));
+    Expect.isTrue(new C<num>().isCheck(d));
+    Expect.isFalse(new C<num>().isCheck(fni));
+    Expect.isFalse(new C<num>().isCheck(fnd));
+    Expect.isFalse(new C<num>().isCheck(fi));
+    Expect.isFalse(new C<num>().isCheck(fd));
+    Expect.isFalse(new C<num>().isCheck(fn));
+    Expect.isFalse(new C<num>().isCheck(o));
+    Expect.isFalse(new C<num>().isCheck(fo));
+    Expect.isFalse(new C<num>().isCheck(foi));
+
+    Expect.isFalse(new C<int>().isCheck(n));
+    Expect.isTrue(new C<int>().isCheck(i));
+    Expect.isFalse(new C<int>().isCheck(d));
+    Expect.isFalse(new C<int>().isCheck(fni));
+    Expect.isFalse(new C<int>().isCheck(fnd));
+    Expect.isFalse(new C<int>().isCheck(fi));
+    Expect.isFalse(new C<int>().isCheck(fd));
+    Expect.isFalse(new C<int>().isCheck(fn));
+    Expect.isFalse(new C<int>().isCheck(o));
+    Expect.isFalse(new C<int>().isCheck(fo));
+    Expect.isFalse(new C<int>().isCheck(foi));
+
+    Expect.isTrue(new C<Null>().isCheck(n));
+    Expect.isFalse(new C<Null>().isCheck(i));
+    Expect.isFalse(new C<Null>().isCheck(d));
+    Expect.isFalse(new C<Null>().isCheck(fni));
+    Expect.isFalse(new C<Null>().isCheck(fnd));
+    Expect.isFalse(new C<Null>().isCheck(fi));
+    Expect.isFalse(new C<Null>().isCheck(fd));
+    Expect.isFalse(new C<Null>().isCheck(fn));
+    Expect.isFalse(new C<Null>().isCheck(o));
+    Expect.isFalse(new C<Null>().isCheck(fo));
+    Expect.isFalse(new C<Null>().isCheck(foi));
+  }
+}
+
+// FutureOr used as type parameter bound.
+class C<T extends FutureOr<num>> {
+  bool isCheck(Object o) => o is T;
+}
diff --git a/tests/lib_2/html/audiobuffersourcenode_test.dart b/tests/lib_2/html/audiobuffersourcenode_test.dart
index ddfb55c..9c98cf0 100644
--- a/tests/lib_2/html/audiobuffersourcenode_test.dart
+++ b/tests/lib_2/html/audiobuffersourcenode_test.dart
@@ -15,7 +15,7 @@
         var ctx = new AudioContext();
         AudioBufferSourceNode node = ctx.createBufferSource();
         expect(node is AudioBufferSourceNode, isTrue);
-        node.start2(ctx.currentTime, 0, 2);
+        node.start(ctx.currentTime, 0, 2);
         expect(node is AudioBufferSourceNode, isTrue);
       }
     });
diff --git a/tests/lib_2/html/websql_test.dart b/tests/lib_2/html/websql_test.dart
index 728b0fd..1d52d5d 100644
--- a/tests/lib_2/html/websql_test.dart
+++ b/tests/lib_2/html/websql_test.dart
@@ -57,12 +57,6 @@
   await setup();
 
   group('Database', () {
-    test('supported', () {
-      expect(SqlDatabase.supported, true);
-    });
-  });
-
-  group('Database', () {
     test('Open/Transaction', () async {
       if (!SqlDatabase.supported) return;
 
diff --git a/tests/lib_2/lib_2.status b/tests/lib_2/lib_2.status
index 322ea0f..a5c29d5 100644
--- a/tests/lib_2/lib_2.status
+++ b/tests/lib_2/lib_2.status
@@ -124,6 +124,9 @@
 async/stream_last_where_test/badType: MissingCompileTimeError
 mirrors/redirecting_factory_different_type_test/02: MissingCompileTimeError
 
+[ !$strong && $compiler != fasta && $compiler != dart2analyzer ]
+async/future_or_type_test: Fail # Strong mode implements FutureOr, non-strong treats it as dynamic.
+
 [ $builder_tag == mac10_7 && $runtime == safari ]
 typed_data/setRange_2_test: Fail # Safari doesn't fully implement spec for TypedArray.set
 typed_data/setRange_3_test: Fail # Safari doesn't fully implement spec for TypedArray.set
diff --git a/tests/lib_2/lib_2_dart2js.status b/tests/lib_2/lib_2_dart2js.status
index 85c39cc..a7913ac 100644
--- a/tests/lib_2/lib_2_dart2js.status
+++ b/tests/lib_2/lib_2_dart2js.status
@@ -407,7 +407,6 @@
 html/speechrecognition_test: RuntimeError # Please triage.
 html/text_event_test: Fail # Issue 17893
 html/webgl_1_test: Pass, Fail # Issue 8219
-html/websql_test: Fail
 isolate/kill_self_synchronously_test: RuntimeError
 
 [ $compiler == dart2js && $runtime == ie11 ]
diff --git a/tools/VERSION b/tools/VERSION
index bdaeec8..2e2e188 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 0
 PATCH 0
-PRERELEASE 40
+PRERELEASE 41
 PRERELEASE_PATCH 0
diff --git a/tools/apps/update_homebrew/lib/update_homebrew.dart b/tools/apps/update_homebrew/lib/update_homebrew.dart
index 350c779..5628c41 100644
--- a/tools/apps/update_homebrew/lib/update_homebrew.dart
+++ b/tools/apps/update_homebrew/lib/update_homebrew.dart
@@ -157,12 +157,18 @@
     bin.write_exec_script Dir["#{libexec}/bin/{pub,dart?*}"]
 
     if build.with? "dartium"
+      if build.devel?
+        odie "dartium is no longer supported with --devel builds. Remove --with-dartium and try again."
+      end
       dartium_binary = "Chromium.app/Contents/MacOS/Chromium"
       prefix.install resource("dartium")
       (bin+"dartium").write shim_script dartium_binary
     end
 
     if build.with? "content-shell"
+      if build.devel?
+        odie "content-shell is no longer supported with --devel builds. Remove --with-content-shell and try again."
+      end
       content_shell_binary = "Content Shell.app/Contents/MacOS/Content Shell"
       prefix.install resource("content_shell")
       (bin+"content_shell").write shim_script content_shell_binary
diff --git a/tools/bots/test_matrix.json b/tools/bots/test_matrix.json
index 21094fc..9b22618 100644
--- a/tools/bots/test_matrix.json
+++ b/tools/bots/test_matrix.json
@@ -11,12 +11,21 @@
       ".packages"
     ],
     "dart2js": [
-      "out/ReleaseX64/",
-      "xcodebuild/ReleaseX64/",
-      "tools/",
-      "tests/",
+      ".packages",
+      "out/ReleaseIA32/dart-sdk/",
+      "out/ReleaseX64/dart-sdk/",
       "pkg/",
-      ".packages"
+      "runtime/tests/",
+      "samples-dev/",
+      "samples/",
+      "tests/",
+      "third_party/d8/",
+      "third_party/observatory_pub_packages/packages/web_components/",
+      "third_party/pkg/",
+      "third_party/pkg_tested/",
+      "tools/",
+      "xcodebuild/ReleaseIA32/dart-sdk/",
+      "xcodebuild/ReleaseX64/dart-sdk/"
     ],
     "vm_debug": [
       "out/DebugIA32/",
@@ -615,13 +624,17 @@
         },
         {
           "name": "vm tests",
-          "arguments": ["--vm-options=--optimization-counter-threshold=5"]
+          "arguments": [
+            "--vm-options=--optimization-counter-threshold=5",
+            "--builder-tag=optimization_counter_threshold"
+          ]
         },
         {
           "name": "checked vm tests",
           "arguments": [
             "--checked",
-            "--vm-options=--optimization-counter-threshold=5"
+            "--vm-options=--optimization-counter-threshold=5",
+            "--builder-tag=optimization_counter_threshold"
           ]
         }
       ]
@@ -880,32 +893,6 @@
           "fileset": "dart2js"
         },
         {
-          "name": "dart2js fast-startup tests",
-          "arguments": [
-            "--use-sdk",
-            "--compiler=dart2js",
-            "--dart2js-batch",
-            "--reset-browser-configuration",
-            "--fast-startup"
-          ],
-          "exclude_tests": ["observatory_ui", "co19"],
-          "shards": 4,
-          "fileset": "dart2js"
-        },
-        {
-          "name": "dart2js fast-startup co19 tests",
-          "arguments": [
-            "--use-sdk",
-            "--compiler=dart2js",
-            "--dart2js-batch",
-            "--reset-browser-configuration",
-            "--fast-startup"
-          ],
-          "tests": ["co19"],
-          "shards": 4,
-          "fileset": "dart2js"
-        },
-        {
           "name": "dart2js package tests",
           "arguments": [
             "--use-sdk",
@@ -934,9 +921,51 @@
             "--reset-browser-configuration"
           ],
           "tests": ["dart2js_extra","dart2js_native"]
+        }
+      ]
+    },
+    {
+      "builders": [
+        "dart2js-faststartup-linux-x64-chrome"
+      ],
+      "meta": {
+        "description":
+          "These builders run dart2js tests with the --fast-startup option."
+      },
+      "steps": [
+        {
+          "name": "build dart",
+          "script": "tools/build.py",
+          "arguments": ["create_sdk"]
         },
         {
-          "name": "dart2js fast-startup pkg tests",
+          "name": "dart2js fast-startup tests",
+          "arguments": [
+            "--use-sdk",
+            "--compiler=dart2js",
+            "--dart2js-batch",
+            "--reset-browser-configuration",
+            "--fast-startup"
+          ],
+          "exclude_tests": ["observatory_ui", "co19"],
+          "shards": 4,
+          "fileset": "dart2js"
+        },
+        {
+          "name": "dart2js fast-startup co19 tests",
+          "arguments": [
+            "--use-sdk",
+            "--compiler=dart2js",
+            "--dart2js-batch",
+            "--reset-browser-configuration",
+            "--fast-startup"
+          ],
+          "tests": ["co19"],
+          "shards": 4,
+          "fileset": "dart2js"
+        },
+        {
+          "name": "dart2js fast-startup package tests",
           "arguments": [
             "--use-sdk",
             "--compiler=dart2js",
diff --git a/tools/copy_tree.py b/tools/copy_tree.py
index a9925b4..5d72750 100755
--- a/tools/copy_tree.py
+++ b/tools/copy_tree.py
@@ -82,7 +82,7 @@
       errors.append((srcname, dstname, str(why)))
     # catch the Error from the recursive CopyTree so that we can
     # continue with other files
-    except Error as err:
+    except Exception as err:
       errors.extend(err.args[0])
   try:
     shutil.copystat(src, dst)
diff --git a/tools/dart2js/sourceMapViewer/web/display.dart b/tools/dart2js/sourceMapViewer/web/display.dart
index fa21a25..824f6aa 100644
--- a/tools/dart2js/sourceMapViewer/web/display.dart
+++ b/tools/dart2js/sourceMapViewer/web/display.dart
@@ -51,8 +51,6 @@
 displaySource(String filename, List<String> source, TargetEntry entry) {
   int line = entry.sourceLine;
   int column = entry.sourceColumn;
-  int nameId = entry.sourceNameId;
-  String id = nameId == null ? null : sourceMap.names[nameId];
   selectedSource.children.clear();
   SpanElement marker = new SpanElement()
     ..className = "marker"
@@ -308,7 +306,7 @@
 
   getMap().then((mapFileName) {
     load(mapFileName).then((mapFileContent) {
-      sourceMap = new SingleMapping.fromJson(JSON.decode(mapFileContent));
+      sourceMap = new SingleMapping.fromJson(jsonDecode(mapFileContent));
       displayMap(mapFileContent);
       targetFileName.text = sourceMap.targetUrl;
       load(targetFileName.text).then((targetFileContent) {
diff --git a/tools/dart2js/sourceMapViewer/web/display.html b/tools/dart2js/sourceMapViewer/web/display.html
index 834cf64..54bfefc 100644
--- a/tools/dart2js/sourceMapViewer/web/display.html
+++ b/tools/dart2js/sourceMapViewer/web/display.html
@@ -57,7 +57,6 @@
      </td>
     </tr>
     </table></div>
-    <script type="application/dart" src="display.dart"></script>
-    <script src="packages/browser/dart.js"></script>
+    <script defer src="display.dart.js"></script>
   </body>
 </html>
\ No newline at end of file
diff --git a/tools/dom/idl/dart/dart.idl b/tools/dom/idl/dart/dart.idl
index 570ccc5..b9acad3 100644
--- a/tools/dom/idl/dart/dart.idl
+++ b/tools/dom/idl/dart/dart.idl
@@ -493,8 +493,8 @@
 };
 
 [DartSupplemental]
-interface AudioBufferSourceNode {
-    [DartName=start2] void start(optional double when = 0, optional double grainOffset, optional double grainDuration);
+interface AudioScheduledSourceNode {
+    [DartName=start2] void start(optional double when);
 };
 
 // Remove operations webkitRequestFullscreen replaced w/ requestFullscreen.
diff --git a/tools/patch_sdk.dart b/tools/patch_sdk.dart
index 9dac1deb..f8dd6fc 100644
--- a/tools/patch_sdk.dart
+++ b/tools/patch_sdk.dart
@@ -29,7 +29,6 @@
 import 'package:kernel/target/targets.dart';
 import 'package:kernel/target/vm.dart' show VmTarget;
 import 'package:kernel/target/flutter.dart' show FlutterTarget;
-import 'package:vm/target/runner.dart' show RunnerTarget;
 import 'package:compiler/src/kernel/dart2js_target.dart' show Dart2jsTarget;
 
 /// Set of input files that were read by this script to generate patched SDK.
@@ -134,17 +133,13 @@
       target = new VmTarget(flags);
       break;
 
-    case 'runner':
-      target = new RunnerTarget(flags);
-      break;
-
     case 'flutter':
     case 'flutter_release':
       target = new FlutterTarget(flags);
       break;
 
     case 'dart2js':
-      target = new Dart2jsTarget(flags);
+      target = new Dart2jsTarget("dart2js", flags);
       break;
 
     default:
diff --git a/utils/compiler/BUILD.gn b/utils/compiler/BUILD.gn
index bcea398..a279e9e 100644
--- a/utils/compiler/BUILD.gn
+++ b/utils/compiler/BUILD.gn
@@ -110,3 +110,36 @@
     "dart:core",
   ]
 }
+
+compile_platform("compile_dart2js_server_platform") {
+  sources = [
+    "../../sdk/lib/libraries.json",
+  ]
+
+  outputs = [
+    "$root_out_dir/dart2js_server_platform.dill",
+    "$root_out_dir/dart2js_server_outline.dill",
+  ]
+
+  args = [
+    "--target=dart2js_server",
+    "dart:core",
+  ]
+}
+
+compile_platform("compile_dart2js_server_platform_strong") {
+  sources = [
+    "../../sdk/lib/libraries.json",
+  ]
+
+  outputs = [
+    "$root_out_dir/dart2js_server_platform_strong.dill",
+    "$root_out_dir/dart2js_server_outline_strong.dill",
+  ]
+
+  args = [
+    "--target=dart2js_server",
+    "--strong",
+    "dart:core",
+  ]
+}