Version 1.23.0-dev.5.0

Merge commit '5812e69c3af88c97767e7ad9510f6f2dca3ce398' into dev
diff --git a/.travis.yml b/.travis.yml
index 24d69ac..448e847 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -66,7 +66,7 @@
   # Empty to suppress default pub get behavior
 before_script:
   # Node modules used by DDC
-  - nvm install 5.5.0
+  - nvm install 6.9.1
   - npm install
 script:
   # Run DDC tests
@@ -86,6 +86,7 @@
   - TEST=package
 matrix:
   allow_failures:
+    - env: ANALYZER=master DDC_BROWSERS=Firefox
     - env: ANALYZER=master DDC_BROWSERS=ChromeCanaryTravis
     - env: ANALYZER=master CXX=clang++
 notifications:
diff --git a/DEPS b/DEPS
index b20d8b9..3d7627e 100644
--- a/DEPS
+++ b/DEPS
@@ -104,9 +104,9 @@
   "smoke_tag" : "@v0.3.6+2",
   "source_map_stack_trace_tag": "@1.1.4",
   "source_maps-0.9.4_rev": "@38524",
-  "source_maps_tag": "@0.10.2",
+  "source_maps_tag": "@0.10.3",
   "source_span_tag": "@1.3.1",
-  "stack_trace_tag": "@1.7.1",
+  "stack_trace_tag": "@1.7.2",
   "stream_channel_tag": "@1.6.1",
   "string_scanner_tag": "@1.0.1",
   "sunflower_rev": "@879b704933413414679396b129f5dfa96f7a0b1e",
diff --git a/pkg/analyzer/lib/dart/ast/ast_factory.dart b/pkg/analyzer/lib/dart/ast/ast_factory.dart
index 40a5830..ab890ce 100644
--- a/pkg/analyzer/lib/dart/ast/ast_factory.dart
+++ b/pkg/analyzer/lib/dart/ast/ast_factory.dart
@@ -626,7 +626,7 @@
       TypeAnnotation returnType,
       Token functionKeyword,
       TypeParameterList typeParameters,
-      FormalParameterList _parameters);
+      FormalParameterList parameters);
 
   /**
    * Returns a newly created generic type alias. Either or both of the
diff --git a/pkg/analyzer/lib/dart/element/element.dart b/pkg/analyzer/lib/dart/element/element.dart
index 7cb2939..c02e88a 100644
--- a/pkg/analyzer/lib/dart/element/element.dart
+++ b/pkg/analyzer/lib/dart/element/element.dart
@@ -1283,14 +1283,11 @@
   static List<FunctionTypeAliasElement> EMPTY_LIST =
       new List<FunctionTypeAliasElement>(0);
 
-  /**
-   * Return the compilation unit in which this type alias is defined.
-   */
   @override
   CompilationUnitElement get enclosingElement;
 
   @override
-  FunctionTypeAlias computeNode();
+  TypeAlias computeNode();
 }
 
 /**
@@ -1314,9 +1311,7 @@
    */
   DartType get returnType;
 
-  /**
-   * The type of this element, which will be a function type.
-   */
+  @override
   FunctionType get type;
 }
 
diff --git a/pkg/analyzer/lib/error/error.dart b/pkg/analyzer/lib/error/error.dart
index 0e9ad7b..3b4ccac 100644
--- a/pkg/analyzer/lib/error/error.dart
+++ b/pkg/analyzer/lib/error/error.dart
@@ -59,6 +59,7 @@
   CompileTimeErrorCode.ARGUMENT_DEFINITION_TEST_NON_PARAMETER,
   CompileTimeErrorCode.ASYNC_FOR_IN_WRONG_CONTEXT,
   CompileTimeErrorCode.AWAIT_IN_WRONG_CONTEXT,
+  CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_PREFIX_NAME,
   CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE,
   CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPEDEF_NAME,
   CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE_NAME,
diff --git a/pkg/analyzer/lib/file_system/file_system.dart b/pkg/analyzer/lib/file_system/file_system.dart
index 139330b..11223c9 100644
--- a/pkg/analyzer/lib/file_system/file_system.dart
+++ b/pkg/analyzer/lib/file_system/file_system.dart
@@ -32,6 +32,9 @@
    */
   int get modificationStamp;
 
+  @override
+  File copyTo(Folder parentFolder);
+
   /**
    * Create a new [Source] instance that serves this file.
    */
@@ -114,6 +117,14 @@
    */
   bool contains(String path);
 
+  @override
+  Folder copyTo(Folder parentFolder);
+
+  /**
+   * If this folder does not already exist, create it.
+   */
+  void create();
+
   /**
    * Return an existing child [Resource] with the given [relPath].
    * Return a not existing [File] if no such child exist.
@@ -170,6 +181,19 @@
   String get shortName;
 
   /**
+   * Copy this resource to a child of the [parentFolder] with the same kind and
+   * [shortName] as this resource. If this resource is a folder, then all of the
+   * contents of the folder will be recursively copied.
+   *
+   * The parent folder is created if it does not already exist.
+   *
+   * Existing files and folders will be overwritten.
+   *
+   * Return the resource corresponding to this resource in the parent folder.
+   */
+  Resource copyTo(Folder parentFolder);
+
+  /**
    * Synchronously deletes this resource and its children.
    *
    * Throws an exception if the resource cannot be deleted.
diff --git a/pkg/analyzer/lib/file_system/memory_file_system.dart b/pkg/analyzer/lib/file_system/memory_file_system.dart
index 3cab6ee..6e7ab64 100644
--- a/pkg/analyzer/lib/file_system/memory_file_system.dart
+++ b/pkg/analyzer/lib/file_system/memory_file_system.dart
@@ -326,6 +326,11 @@
   }
 
   @override
+  File copyTo(Folder parentFolder) {
+    throw new FileSystemException(path, 'File could not be copied');
+  }
+
+  @override
   Source createSource([Uri uri]) {
     throw new FileSystemException(path, 'File could not be read');
   }
@@ -396,6 +401,14 @@
   }
 
   @override
+  File copyTo(Folder parentFolder) {
+    parentFolder.create();
+    File destination = parentFolder.getChildAssumingFile(shortName);
+    destination.writeAsBytesSync(readAsBytesSync());
+    return destination;
+  }
+
+  @override
   Source createSource([Uri uri]) {
     uri ??= _provider.pathContext.toUri(path);
     return new FileSource(this, uri);
@@ -472,6 +485,21 @@
   }
 
   @override
+  Folder copyTo(Folder parentFolder) {
+    Folder destination = parentFolder.getChildAssumingFolder(shortName);
+    destination.create();
+    for (Resource child in getChildren()) {
+      child.copyTo(destination);
+    }
+    return destination;
+  }
+
+  @override
+  void create() {
+    _provider.newFolder(path);
+  }
+
+  @override
   void delete() {
     _provider.deleteFolder(path);
   }
diff --git a/pkg/analyzer/lib/file_system/physical_file_system.dart b/pkg/analyzer/lib/file_system/physical_file_system.dart
index b190c1b..f3906be 100644
--- a/pkg/analyzer/lib/file_system/physical_file_system.dart
+++ b/pkg/analyzer/lib/file_system/physical_file_system.dart
@@ -150,6 +150,14 @@
   io.File get _file => _entry as io.File;
 
   @override
+  File copyTo(Folder parentFolder) {
+    parentFolder.create();
+    File destination = parentFolder.getChildAssumingFile(shortName);
+    destination.writeAsBytesSync(readAsBytesSync());
+    return destination;
+  }
+
+  @override
   Source createSource([Uri uri]) {
     return new FileSource(this, uri ?? pathContext.toUri(path));
   }
@@ -246,6 +254,21 @@
   }
 
   @override
+  Folder copyTo(Folder parentFolder) {
+    Folder destination = parentFolder.getChildAssumingFolder(shortName);
+    destination.create();
+    for (Resource child in getChildren()) {
+      child.copyTo(destination);
+    }
+    return destination;
+  }
+
+  @override
+  void create() {
+    _directory.createSync(recursive: true);
+  }
+
+  @override
   Resource getChild(String relPath) {
     String canonicalPath = canonicalizePath(relPath);
     return PhysicalResourceProvider.INSTANCE.getResource(canonicalPath);
diff --git a/pkg/analyzer/lib/src/dart/ast/ast_factory.dart b/pkg/analyzer/lib/src/dart/ast/ast_factory.dart
index a3a09ee9..ebe811a 100644
--- a/pkg/analyzer/lib/src/dart/ast/ast_factory.dart
+++ b/pkg/analyzer/lib/src/dart/ast/ast_factory.dart
@@ -548,9 +548,9 @@
           TypeAnnotation returnType,
           Token functionKeyword,
           TypeParameterList typeParameters,
-          FormalParameterList _parameters) =>
+          FormalParameterList parameters) =>
       new GenericFunctionTypeImpl(
-          returnType, functionKeyword, typeParameters, _parameters);
+          returnType, functionKeyword, typeParameters, parameters);
 
   @override
   GenericTypeAlias genericTypeAlias(
diff --git a/pkg/analyzer/lib/src/dart/element/builder.dart b/pkg/analyzer/lib/src/dart/element/builder.dart
index cea4664..ee136eb 100644
--- a/pkg/analyzer/lib/src/dart/element/builder.dart
+++ b/pkg/analyzer/lib/src/dart/element/builder.dart
@@ -427,6 +427,47 @@
   }
 
   @override
+  Object visitGenericFunctionType(GenericFunctionType node) {
+    ElementHolder holder = new ElementHolder();
+    _visitChildren(holder, node);
+    FunctionElementImpl element =
+        new FunctionElementImpl.forOffset(node.beginToken.offset);
+    _setCodeRange(element, node);
+    element.parameters = holder.parameters;
+    element.typeParameters = holder.typeParameters;
+    FunctionType type = new FunctionTypeImpl(element);
+    element.type = type;
+    if (node.returnType == null) {
+      element.hasImplicitReturnType = true;
+    }
+    _currentHolder.addFunction(element);
+    (node as GenericFunctionTypeImpl).type = type;
+    holder.validate();
+    return null;
+  }
+
+  @override
+  Object visitGenericTypeAlias(GenericTypeAlias node) {
+    ElementHolder holder = new ElementHolder();
+    _visitChildren(holder, node);
+    SimpleIdentifier aliasName = node.name;
+    List<TypeParameterElement> typeParameters = holder.typeParameters;
+    GenericTypeAliasElementImpl element =
+        new GenericTypeAliasElementImpl.forNode(aliasName);
+    _setCodeRange(element, node);
+    element.metadata = _createElementAnnotations(node.metadata);
+    setElementDocumentationComment(element, node);
+    element.typeParameters = typeParameters;
+    _createTypeParameterTypes(typeParameters);
+    element.type = new FunctionTypeImpl.forTypedef(element);
+    element.function = holder.functions[0];
+    _currentHolder.addTypeAlias(element);
+    aliasName.staticElement = element;
+    holder.validate();
+    return null;
+  }
+
+  @override
   Object visitImportDirective(ImportDirective node) {
     List<ElementAnnotation> annotations =
         _createElementAnnotations(node.metadata);
diff --git a/pkg/analyzer/lib/src/dart/element/element.dart b/pkg/analyzer/lib/src/dart/element/element.dart
index af93dd3..aa31f7d 100644
--- a/pkg/analyzer/lib/src/dart/element/element.dart
+++ b/pkg/analyzer/lib/src/dart/element/element.dart
@@ -4875,6 +4875,237 @@
 }
 
 /**
+ * A function type alias of the form
+ *     `typedef` identifier typeParameters = genericFunctionType;
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+class GenericTypeAliasElementImpl extends ElementImpl
+    with TypeParameterizedElementMixin
+    implements FunctionTypeAliasElement {
+  /**
+   * The unlinked representation of the type in the summary.
+   */
+  final UnlinkedTypedef _unlinkedTypedef;
+
+  /**
+   * The element representing the generic function type if this is a generic
+   * function type alias, or `null` if it isn't.
+   */
+  FunctionElement _function;
+
+  /**
+   * The type of function defined by this type alias.
+   */
+  FunctionType _type;
+
+  /**
+   * A list containing all of the type parameters defined for this type.
+   */
+  List<TypeParameterElement> _typeParameters = TypeParameterElement.EMPTY_LIST;
+
+  /**
+   * Initialize a newly created type alias element to have the given [name].
+   */
+  GenericTypeAliasElementImpl.forNode(Identifier name)
+      : _unlinkedTypedef = null,
+        super.forNode(name);
+
+  /**
+   * Initialize using the given serialized information.
+   */
+  GenericTypeAliasElementImpl.forSerialized(
+      this._unlinkedTypedef, CompilationUnitElementImpl enclosingUnit)
+      : super.forSerialized(enclosingUnit);
+
+  @override
+  int get codeLength {
+    if (_unlinkedTypedef != null) {
+      return _unlinkedTypedef.codeRange?.length;
+    }
+    return super.codeLength;
+  }
+
+  @override
+  int get codeOffset {
+    if (_unlinkedTypedef != null) {
+      return _unlinkedTypedef.codeRange?.offset;
+    }
+    return super.codeOffset;
+  }
+
+  @override
+  String get displayName => name;
+
+  @override
+  String get documentationComment {
+    if (_unlinkedTypedef != null) {
+      return _unlinkedTypedef?.documentationComment?.text;
+    }
+    return super.documentationComment;
+  }
+
+  @override
+  CompilationUnitElement get enclosingElement =>
+      super.enclosingElement as CompilationUnitElement;
+
+  @override
+  TypeParameterizedElementMixin get enclosingTypeParameterContext => null;
+
+  @override
+  CompilationUnitElementImpl get enclosingUnit =>
+      _enclosingElement as CompilationUnitElementImpl;
+
+  /**
+   * Return the function element representing the generic function type on the
+   * right side of the equals.
+   */
+  FunctionElement get function {
+    if (_function == null && _unlinkedTypedef != null) {
+      DartType type = enclosingUnit.resynthesizerContext.resolveTypeRef(
+          _unlinkedTypedef.returnType, this,
+          declaredType: true);
+      if (type is FunctionType) {
+        _function = type.element;
+      }
+    }
+    return _function;
+  }
+
+  /**
+   * Set the function element representing the generic function type on the
+   * right side of the equals to the given [function].
+   */
+  void set function(FunctionElement function) {
+    _assertNotResynthesized(_unlinkedTypedef);
+    if (function != null) {
+      (function as FunctionElementImpl).enclosingElement = this;
+    }
+    _function = function;
+  }
+
+  @override
+  ElementKind get kind => ElementKind.FUNCTION_TYPE_ALIAS;
+
+  @override
+  List<ElementAnnotation> get metadata {
+    if (_unlinkedTypedef != null) {
+      return _metadata ??=
+          _buildAnnotations(enclosingUnit, _unlinkedTypedef.annotations);
+    }
+    return super.metadata;
+  }
+
+  @override
+  String get name {
+    if (_unlinkedTypedef != null) {
+      return _unlinkedTypedef.name;
+    }
+    return super.name;
+  }
+
+  @override
+  int get nameOffset {
+    int offset = super.nameOffset;
+    if (offset == 0 && _unlinkedTypedef != null) {
+      return _unlinkedTypedef.nameOffset;
+    }
+    return offset;
+  }
+
+  @override
+  List<ParameterElement> get parameters => function.parameters;
+
+  @override
+  DartType get returnType => function.returnType;
+
+  @override
+  FunctionType get type {
+    if (_unlinkedTypedef != null && _type == null) {
+      _type = new FunctionTypeImpl.forTypedef(this);
+    }
+    return _type;
+  }
+
+  void set type(FunctionType type) {
+    _assertNotResynthesized(_unlinkedTypedef);
+    _type = type;
+  }
+
+  @override
+  TypeParameterizedElementMixin get typeParameterContext => this;
+
+  @override
+  List<TypeParameterElement> get typeParameters {
+    if (_unlinkedTypedef != null) {
+      return super.typeParameters;
+    }
+    return _typeParameters;
+  }
+
+  /**
+   * Set the type parameters defined for this type to the given
+   * [typeParameters].
+   */
+  void set typeParameters(List<TypeParameterElement> typeParameters) {
+    _assertNotResynthesized(_unlinkedTypedef);
+    for (TypeParameterElement typeParameter in typeParameters) {
+      (typeParameter as TypeParameterElementImpl).enclosingElement = this;
+    }
+    this._typeParameters = typeParameters;
+  }
+
+  @override
+  List<UnlinkedTypeParam> get unlinkedTypeParams =>
+      _unlinkedTypedef.typeParameters;
+
+  @override
+  /*=T*/ accept/*<T>*/(ElementVisitor<dynamic/*=T*/ > visitor) =>
+      visitor.visitFunctionTypeAliasElement(this);
+
+  @override
+  void appendTo(StringBuffer buffer) {
+    buffer.write("typedef ");
+    buffer.write(displayName);
+    int typeParameterCount = _typeParameters.length;
+    if (typeParameterCount > 0) {
+      buffer.write("<");
+      for (int i = 0; i < typeParameterCount; i++) {
+        if (i > 0) {
+          buffer.write(", ");
+        }
+        (_typeParameters[i] as TypeParameterElementImpl).appendTo(buffer);
+      }
+      buffer.write(">");
+    }
+    buffer.write(" = ");
+    (function as FunctionElementImpl).appendTo(buffer);
+  }
+
+  @override
+  FunctionTypeAlias computeNode() =>
+      getNodeMatching((node) => node is GenericTypeAlias);
+
+  @override
+  ElementImpl getChild(String identifier) {
+    for (TypeParameterElement typeParameter in _typeParameters) {
+      TypeParameterElementImpl typeParameterImpl = typeParameter;
+      if (typeParameterImpl.identifier == identifier) {
+        return typeParameterImpl;
+      }
+    }
+    return null;
+  }
+
+  @override
+  void visitChildren(ElementVisitor visitor) {
+    super.visitChildren(visitor);
+    safelyVisitChildren(typeParameters, visitor);
+    function?.accept(visitor);
+  }
+}
+
+/**
  * A concrete implementation of a [HideElementCombinator].
  */
 class HideElementCombinatorImpl implements HideElementCombinator {
diff --git a/pkg/analyzer/lib/src/dart/error/hint_codes.dart b/pkg/analyzer/lib/src/dart/error/hint_codes.dart
index 72eb3ce..fb77ae7 100644
--- a/pkg/analyzer/lib/src/dart/error/hint_codes.dart
+++ b/pkg/analyzer/lib/src/dart/error/hint_codes.dart
@@ -355,7 +355,7 @@
   static const HintCode MUST_CALL_SUPER = const HintCode(
       'MUST_CALL_SUPER',
       "This method overrides a method annotated as @mustCallSuper in '{0}', "
-      "but does invoke the overridden method.");
+      "but does not invoke the overridden method.");
 
   /**
    * A condition in a control flow statement could evaluate to `null` because it
diff --git a/pkg/analyzer/lib/src/error/codes.dart b/pkg/analyzer/lib/src/error/codes.dart
index 8171fa6..c315950 100644
--- a/pkg/analyzer/lib/src/error/codes.dart
+++ b/pkg/analyzer/lib/src/error/codes.dart
@@ -249,6 +249,20 @@
           "Try marking the function body with either 'async' or 'async*'.");
 
   /**
+   * 16.33 Identifier Reference: It is a compile-time error if a built-in
+   * identifier is used as the declared name of a prefix, class, type parameter
+   * or type alias.
+   *
+   * Parameters:
+   * 0: the built-in identifier that is being used
+   */
+  static const CompileTimeErrorCode BUILT_IN_IDENTIFIER_AS_PREFIX_NAME =
+      const CompileTimeErrorCode(
+          'BUILT_IN_IDENTIFIER_AS_PREFIX_NAME',
+          "The built-in identifier '{0}' can't be used as a prefix name.",
+          "Try choosing a different name for the prefix.");
+
+  /**
    * 12.30 Identifier Reference: It is a compile-time error to use a built-in
    * identifier other than dynamic as a type annotation.
    *
@@ -262,9 +276,9 @@
           "Try correcting the name to match an existing type.");
 
   /**
-   * 12.30 Identifier Reference: It is a compile-time error if a built-in
-   * identifier is used as the declared name of a class, type parameter or type
-   * alias.
+   * 16.33 Identifier Reference: It is a compile-time error if a built-in
+   * identifier is used as the declared name of a prefix, class, type parameter
+   * or type alias.
    *
    * Parameters:
    * 0: the built-in identifier that is being used
@@ -276,9 +290,9 @@
           "Try choosing a different name for the type.");
 
   /**
-   * 12.30 Identifier Reference: It is a compile-time error if a built-in
-   * identifier is used as the declared name of a class, type parameter or type
-   * alias.
+   * 16.33 Identifier Reference: It is a compile-time error if a built-in
+   * identifier is used as the declared name of a prefix, class, type parameter
+   * or type alias.
    *
    * Parameters:
    * 0: the built-in identifier that is being used
@@ -290,9 +304,9 @@
           "Try choosing a different name for the typedef.");
 
   /**
-   * 12.30 Identifier Reference: It is a compile-time error if a built-in
-   * identifier is used as the declared name of a class, type parameter or type
-   * alias.
+   * 16.33 Identifier Reference: It is a compile-time error if a built-in
+   * identifier is used as the declared name of a prefix, class, type parameter
+   * or type alias.
    *
    * Parameters:
    * 0: the built-in identifier that is being used
diff --git a/pkg/analyzer/lib/src/generated/error_verifier.dart b/pkg/analyzer/lib/src/generated/error_verifier.dart
index adc6f11..1fa5eae 100644
--- a/pkg/analyzer/lib/src/generated/error_verifier.dart
+++ b/pkg/analyzer/lib/src/generated/error_verifier.dart
@@ -900,6 +900,10 @@
   @override
   Object visitImportDirective(ImportDirective node) {
     ImportElement importElement = node.element;
+    if (node.prefix != null) {
+      _checkForBuiltInIdentifierAsName(
+          node.prefix, CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_PREFIX_NAME);
+    }
     if (importElement != null) {
       _checkForImportDuplicateLibraryName(node, importElement);
       _checkForImportInternalLibrary(node, importElement);
@@ -1403,7 +1407,12 @@
   void _checkDuplicateDefinitionInParameterList(FormalParameterList node) {
     Map<String, Element> definedNames = new HashMap<String, Element>();
     for (FormalParameter parameter in node.parameters) {
-      _checkDuplicateIdentifier(definedNames, parameter.identifier);
+      SimpleIdentifier identifier = parameter.identifier;
+      if (identifier != null) {
+        // The identifier can be null if this is a parameter list for a generic
+        // function type.
+        _checkDuplicateIdentifier(definedNames, identifier);
+      }
     }
   }
 
diff --git a/pkg/analyzer/lib/src/summary/format.dart b/pkg/analyzer/lib/src/summary/format.dart
index c86b37c..8771170 100644
--- a/pkg/analyzer/lib/src/summary/format.dart
+++ b/pkg/analyzer/lib/src/summary/format.dart
@@ -64,6 +64,19 @@
   }
 }
 
+class _TypedefStyleReader extends fb.Reader<idl.TypedefStyle> {
+  const _TypedefStyleReader() : super();
+
+  @override
+  int get size => 1;
+
+  @override
+  idl.TypedefStyle read(fb.BufferContext bc, int offset) {
+    int index = const fb.Uint8Reader().read(bc, offset);
+    return index < idl.TypedefStyle.values.length ? idl.TypedefStyle.values[index] : idl.TypedefStyle.functionType;
+  }
+}
+
 class _UnlinkedConstructorInitializerKindReader extends fb.Reader<idl.UnlinkedConstructorInitializerKind> {
   const _UnlinkedConstructorInitializerKindReader() : super();
 
@@ -1795,6 +1808,7 @@
   List<UnlinkedParamBuilder> _syntheticParams;
   EntityRefBuilder _syntheticReturnType;
   List<EntityRefBuilder> _typeArguments;
+  List<UnlinkedTypeParamBuilder> _typeParameters;
 
   @override
   List<int> get implicitFunctionTypeIndices => _implicitFunctionTypeIndices ??= <int>[];
@@ -1917,14 +1931,26 @@
     this._typeArguments = value;
   }
 
-  EntityRefBuilder({List<int> implicitFunctionTypeIndices, int paramReference, int reference, int slot, List<UnlinkedParamBuilder> syntheticParams, EntityRefBuilder syntheticReturnType, List<EntityRefBuilder> typeArguments})
+  @override
+  List<UnlinkedTypeParamBuilder> get typeParameters => _typeParameters ??= <UnlinkedTypeParamBuilder>[];
+
+  /**
+   * If this is a function type, the type parameters defined for the function
+   * type (if any).
+   */
+  void set typeParameters(List<UnlinkedTypeParamBuilder> value) {
+    this._typeParameters = value;
+  }
+
+  EntityRefBuilder({List<int> implicitFunctionTypeIndices, int paramReference, int reference, int slot, List<UnlinkedParamBuilder> syntheticParams, EntityRefBuilder syntheticReturnType, List<EntityRefBuilder> typeArguments, List<UnlinkedTypeParamBuilder> typeParameters})
     : _implicitFunctionTypeIndices = implicitFunctionTypeIndices,
       _paramReference = paramReference,
       _reference = reference,
       _slot = slot,
       _syntheticParams = syntheticParams,
       _syntheticReturnType = syntheticReturnType,
-      _typeArguments = typeArguments;
+      _typeArguments = typeArguments,
+      _typeParameters = typeParameters;
 
   /**
    * Flush [informative] data recursively.
@@ -1933,6 +1959,7 @@
     _syntheticParams?.forEach((b) => b.flushInformative());
     _syntheticReturnType?.flushInformative();
     _typeArguments?.forEach((b) => b.flushInformative());
+    _typeParameters?.forEach((b) => b.flushInformative());
   }
 
   /**
@@ -1968,6 +1995,14 @@
         x?.collectApiSignature(signature);
       }
     }
+    if (this._typeParameters == null) {
+      signature.addInt(0);
+    } else {
+      signature.addInt(this._typeParameters.length);
+      for (var x in this._typeParameters) {
+        x?.collectApiSignature(signature);
+      }
+    }
   }
 
   fb.Offset finish(fb.Builder fbBuilder) {
@@ -1975,6 +2010,7 @@
     fb.Offset offset_syntheticParams;
     fb.Offset offset_syntheticReturnType;
     fb.Offset offset_typeArguments;
+    fb.Offset offset_typeParameters;
     if (!(_implicitFunctionTypeIndices == null || _implicitFunctionTypeIndices.isEmpty)) {
       offset_implicitFunctionTypeIndices = fbBuilder.writeListUint32(_implicitFunctionTypeIndices);
     }
@@ -1987,6 +2023,9 @@
     if (!(_typeArguments == null || _typeArguments.isEmpty)) {
       offset_typeArguments = fbBuilder.writeList(_typeArguments.map((b) => b.finish(fbBuilder)).toList());
     }
+    if (!(_typeParameters == null || _typeParameters.isEmpty)) {
+      offset_typeParameters = fbBuilder.writeList(_typeParameters.map((b) => b.finish(fbBuilder)).toList());
+    }
     fbBuilder.startTable();
     if (offset_implicitFunctionTypeIndices != null) {
       fbBuilder.addOffset(4, offset_implicitFunctionTypeIndices);
@@ -2009,6 +2048,9 @@
     if (offset_typeArguments != null) {
       fbBuilder.addOffset(1, offset_typeArguments);
     }
+    if (offset_typeParameters != null) {
+      fbBuilder.addOffset(7, offset_typeParameters);
+    }
     return fbBuilder.endTable();
   }
 }
@@ -2033,6 +2075,7 @@
   List<idl.UnlinkedParam> _syntheticParams;
   idl.EntityRef _syntheticReturnType;
   List<idl.EntityRef> _typeArguments;
+  List<idl.UnlinkedTypeParam> _typeParameters;
 
   @override
   List<int> get implicitFunctionTypeIndices {
@@ -2075,6 +2118,12 @@
     _typeArguments ??= const fb.ListReader<idl.EntityRef>(const _EntityRefReader()).vTableGet(_bc, _bcOffset, 1, const <idl.EntityRef>[]);
     return _typeArguments;
   }
+
+  @override
+  List<idl.UnlinkedTypeParam> get typeParameters {
+    _typeParameters ??= const fb.ListReader<idl.UnlinkedTypeParam>(const _UnlinkedTypeParamReader()).vTableGet(_bc, _bcOffset, 7, const <idl.UnlinkedTypeParam>[]);
+    return _typeParameters;
+  }
 }
 
 abstract class _EntityRefMixin implements idl.EntityRef {
@@ -2088,6 +2137,7 @@
     if (syntheticParams.isNotEmpty) _result["syntheticParams"] = syntheticParams.map((_value) => _value.toJson()).toList();
     if (syntheticReturnType != null) _result["syntheticReturnType"] = syntheticReturnType.toJson();
     if (typeArguments.isNotEmpty) _result["typeArguments"] = typeArguments.map((_value) => _value.toJson()).toList();
+    if (typeParameters.isNotEmpty) _result["typeParameters"] = typeParameters.map((_value) => _value.toJson()).toList();
     return _result;
   }
 
@@ -2100,6 +2150,7 @@
     "syntheticParams": syntheticParams,
     "syntheticReturnType": syntheticReturnType,
     "typeArguments": typeArguments,
+    "typeParameters": typeParameters,
   };
 
   @override
@@ -3748,8 +3799,8 @@
 
   /**
    * Each item of this list corresponds to a unique referenced element.  It is
-   * the identifier of the class member element name, or `null` if the element is
-   * a top-level element.  The list is sorted in ascending order, so that the
+   * the identifier of the class member element name, or `null` if the element
+   * is a top-level element.  The list is sorted in ascending order, so that the
    * client can quickly check whether an element is referenced in this
    * [PackageIndex].
    */
@@ -8371,8 +8422,8 @@
   UnlinkedExecutableBuilder get initializer => _initializer;
 
   /**
-   * The synthetic initializer function of the parameter.  Absent if the variable
-   * does not have an initializer.
+   * The synthetic initializer function of the parameter.  Absent if the
+   * variable does not have an initializer.
    */
   void set initializer(UnlinkedExecutableBuilder value) {
     this._initializer = value;
@@ -8402,7 +8453,14 @@
   bool get isFunctionTyped => _isFunctionTyped ??= false;
 
   /**
-   * Indicates whether this is a function-typed parameter.
+   * Indicates whether this is a function-typed parameter. A parameter is
+   * function-typed if the declaration of the parameter has explicit formal
+   * parameters
+   * ```
+   * int functionTyped(int p)
+   * ```
+   * but is not function-typed if it does not, even if the type of the parameter
+   * is a function type.
    */
   void set isFunctionTyped(bool value) {
     this._isFunctionTyped = value;
@@ -9445,6 +9503,7 @@
   int _nameOffset;
   List<UnlinkedParamBuilder> _parameters;
   EntityRefBuilder _returnType;
+  idl.TypedefStyle _style;
   List<UnlinkedTypeParamBuilder> _typeParameters;
 
   @override
@@ -9513,13 +9572,25 @@
   EntityRefBuilder get returnType => _returnType;
 
   /**
-   * Return type of the typedef.
+   * If [style] is [TypedefStyle.functionType], the return type of the typedef.
+   * If [style] is [TypedefStyle.genericFunctionType], the function type being
+   * defined.
    */
   void set returnType(EntityRefBuilder value) {
     this._returnType = value;
   }
 
   @override
+  idl.TypedefStyle get style => _style ??= idl.TypedefStyle.functionType;
+
+  /**
+   * The style of the typedef.
+   */
+  void set style(idl.TypedefStyle value) {
+    this._style = value;
+  }
+
+  @override
   List<UnlinkedTypeParamBuilder> get typeParameters => _typeParameters ??= <UnlinkedTypeParamBuilder>[];
 
   /**
@@ -9529,7 +9600,7 @@
     this._typeParameters = value;
   }
 
-  UnlinkedTypedefBuilder({List<UnlinkedExprBuilder> annotations, CodeRangeBuilder codeRange, UnlinkedDocumentationCommentBuilder documentationComment, String name, int nameOffset, List<UnlinkedParamBuilder> parameters, EntityRefBuilder returnType, List<UnlinkedTypeParamBuilder> typeParameters})
+  UnlinkedTypedefBuilder({List<UnlinkedExprBuilder> annotations, CodeRangeBuilder codeRange, UnlinkedDocumentationCommentBuilder documentationComment, String name, int nameOffset, List<UnlinkedParamBuilder> parameters, EntityRefBuilder returnType, idl.TypedefStyle style, List<UnlinkedTypeParamBuilder> typeParameters})
     : _annotations = annotations,
       _codeRange = codeRange,
       _documentationComment = documentationComment,
@@ -9537,6 +9608,7 @@
       _nameOffset = nameOffset,
       _parameters = parameters,
       _returnType = returnType,
+      _style = style,
       _typeParameters = typeParameters;
 
   /**
@@ -9583,6 +9655,7 @@
         x?.collectApiSignature(signature);
       }
     }
+    signature.addInt(this._style == null ? 0 : this._style.index);
   }
 
   fb.Offset finish(fb.Builder fbBuilder) {
@@ -9636,6 +9709,9 @@
     if (offset_returnType != null) {
       fbBuilder.addOffset(2, offset_returnType);
     }
+    if (_style != null && _style != idl.TypedefStyle.functionType) {
+      fbBuilder.addUint8(8, _style.index);
+    }
     if (offset_typeParameters != null) {
       fbBuilder.addOffset(5, offset_typeParameters);
     }
@@ -9663,6 +9739,7 @@
   int _nameOffset;
   List<idl.UnlinkedParam> _parameters;
   idl.EntityRef _returnType;
+  idl.TypedefStyle _style;
   List<idl.UnlinkedTypeParam> _typeParameters;
 
   @override
@@ -9708,6 +9785,12 @@
   }
 
   @override
+  idl.TypedefStyle get style {
+    _style ??= const _TypedefStyleReader().vTableGet(_bc, _bcOffset, 8, idl.TypedefStyle.functionType);
+    return _style;
+  }
+
+  @override
   List<idl.UnlinkedTypeParam> get typeParameters {
     _typeParameters ??= const fb.ListReader<idl.UnlinkedTypeParam>(const _UnlinkedTypeParamReader()).vTableGet(_bc, _bcOffset, 5, const <idl.UnlinkedTypeParam>[]);
     return _typeParameters;
@@ -9725,6 +9808,7 @@
     if (nameOffset != 0) _result["nameOffset"] = nameOffset;
     if (parameters.isNotEmpty) _result["parameters"] = parameters.map((_value) => _value.toJson()).toList();
     if (returnType != null) _result["returnType"] = returnType.toJson();
+    if (style != idl.TypedefStyle.functionType) _result["style"] = style.toString().split('.')[1];
     if (typeParameters.isNotEmpty) _result["typeParameters"] = typeParameters.map((_value) => _value.toJson()).toList();
     return _result;
   }
@@ -9738,6 +9822,7 @@
     "nameOffset": nameOffset,
     "parameters": parameters,
     "returnType": returnType,
+    "style": style,
     "typeParameters": typeParameters,
   };
 
diff --git a/pkg/analyzer/lib/src/summary/format.fbs b/pkg/analyzer/lib/src/summary/format.fbs
index c0d461a..4f37949 100644
--- a/pkg/analyzer/lib/src/summary/format.fbs
+++ b/pkg/analyzer/lib/src/summary/format.fbs
@@ -210,6 +210,34 @@
 }
 
 /**
+ * Enum used to indicate the style of a typedef.
+ */
+enum TypedefStyle : byte {
+  /**
+   * A typedef that defines a non-generic function type. The syntax is
+   * ```
+   * 'typedef' returnType? identifier typeParameters? formalParameterList ';'
+   * ```
+   * The typedef can have type parameters associated with it, but the function
+   * type that results from applying type arguments does not.
+   */
+  functionType,
+
+  /**
+   * A typedef expressed using generic function type syntax. The syntax is
+   * ```
+   * typeAlias ::=
+   *     'typedef' identifier typeParameters? '=' genericFunctionType ';'
+   * genericFunctionType ::=
+   *     returnType? 'Function' typeParameters? parameterTypeList
+   * ```
+   * Both the typedef itself and the function type that results from applying
+   * type arguments can have type parameters.
+   */
+  genericFunctionType
+}
+
+/**
  * Enum used to indicate the kind of an constructor initializer.
  */
 enum UnlinkedConstructorInitializerKind : byte {
@@ -494,8 +522,8 @@
   /**
    * Pop the top 2*n values from the stack (where n is obtained from
    * [UnlinkedExpr.ints]), interpret them as key/value pairs, place them in a
-   * [Map], and push the result back onto the stack.  The two type parameters for
-   * the [Map] are obtained from [UnlinkedExpr.references].
+   * [Map], and push the result back onto the stack.  The two type parameters
+   * for the [Map] are obtained from [UnlinkedExpr.references].
    */
   makeTypedMap,
 
@@ -1086,8 +1114,8 @@
 }
 
 /**
- * Summary information about a reference to a an entity such as a type, top
- * level executable, or executable within a class.
+ * Summary information about a reference to an entity such as a type, top level
+ * executable, or executable within a class.
  */
 table EntityRef {
   /**
@@ -1171,6 +1199,12 @@
    * type arguments used to instantiate it (if any).
    */
   typeArguments:[EntityRef] (id: 1);
+
+  /**
+   * If this is a function type, the type parameters defined for the function
+   * type (if any).
+   */
+  typeParameters:[UnlinkedTypeParam] (id: 7);
 }
 
 /**
@@ -1495,8 +1529,8 @@
 
   /**
    * Each item of this list corresponds to a unique referenced element.  It is
-   * the identifier of the class member element name, or `null` if the element is
-   * a top-level element.  The list is sorted in ascending order, so that the
+   * the identifier of the class member element name, or `null` if the element
+   * is a top-level element.  The list is sorted in ascending order, so that the
    * client can quickly check whether an element is referenced in this
    * [PackageIndex].
    */
@@ -2317,8 +2351,8 @@
   inheritsCovariantSlot:uint (id: 14);
 
   /**
-   * The synthetic initializer function of the parameter.  Absent if the variable
-   * does not have an initializer.
+   * The synthetic initializer function of the parameter.  Absent if the
+   * variable does not have an initializer.
    */
   initializer:UnlinkedExecutable (id: 12);
 
@@ -2333,7 +2367,14 @@
   isFinal:bool (id: 16);
 
   /**
-   * Indicates whether this is a function-typed parameter.
+   * Indicates whether this is a function-typed parameter. A parameter is
+   * function-typed if the declaration of the parameter has explicit formal
+   * parameters
+   * ```
+   * int functionTyped(int p)
+   * ```
+   * but is not function-typed if it does not, even if the type of the parameter
+   * is a function type.
    */
   isFunctionTyped:bool (id: 5);
 
@@ -2523,11 +2564,18 @@
   parameters:[UnlinkedParam] (id: 3);
 
   /**
-   * Return type of the typedef.
+   * If [style] is [TypedefStyle.functionType], the return type of the typedef.
+   * If [style] is [TypedefStyle.genericFunctionType], the function type being
+   * defined.
    */
   returnType:EntityRef (id: 2);
 
   /**
+   * The style of the typedef.
+   */
+  style:TypedefStyle (id: 8);
+
+  /**
    * Type parameters of the typedef, if any.
    */
   typeParameters:[UnlinkedTypeParam] (id: 5);
diff --git a/pkg/analyzer/lib/src/summary/idl.dart b/pkg/analyzer/lib/src/summary/idl.dart
index 3389fee..14e506f 100644
--- a/pkg/analyzer/lib/src/summary/idl.dart
+++ b/pkg/analyzer/lib/src/summary/idl.dart
@@ -356,8 +356,8 @@
 }
 
 /**
- * Summary information about a reference to a an entity such as a type, top
- * level executable, or executable within a class.
+ * Summary information about a reference to an entity such as a type, top level
+ * executable, or executable within a class.
  */
 abstract class EntityRef extends base.SummaryClass {
   /**
@@ -448,6 +448,13 @@
    */
   @Id(1)
   List<EntityRef> get typeArguments;
+
+  /**
+   * If this is a function type, the type parameters defined for the function
+   * type (if any).
+   */
+  @Id(7)
+  List<UnlinkedTypeParam> get typeParameters;
 }
 
 /**
@@ -966,8 +973,8 @@
 
   /**
    * Each item of this list corresponds to a unique referenced element.  It is
-   * the identifier of the class member element name, or `null` if the element is
-   * a top-level element.  The list is sorted in ascending order, so that the
+   * the identifier of the class member element name, or `null` if the element
+   * is a top-level element.  The list is sorted in ascending order, so that the
    * client can quickly check whether an element is referenced in this
    * [PackageIndex].
    */
@@ -1096,6 +1103,34 @@
 }
 
 /**
+ * Enum used to indicate the style of a typedef.
+ */
+enum TypedefStyle {
+  /**
+   * A typedef that defines a non-generic function type. The syntax is
+   * ```
+   * 'typedef' returnType? identifier typeParameters? formalParameterList ';'
+   * ```
+   * The typedef can have type parameters associated with it, but the function
+   * type that results from applying type arguments does not.
+   */
+  functionType,
+
+  /**
+   * A typedef expressed using generic function type syntax. The syntax is
+   * ```
+   * typeAlias ::=
+   *     'typedef' identifier typeParameters? '=' genericFunctionType ';'
+   * genericFunctionType ::=
+   *     returnType? 'Function' typeParameters? parameterTypeList
+   * ```
+   * Both the typedef itself and the function type that results from applying
+   * type arguments can have type parameters.
+   */
+  genericFunctionType
+}
+
+/**
  * Index information about a unit in a [PackageIndex].
  */
 abstract class UnitIndex extends base.SummaryClass {
@@ -2127,8 +2162,8 @@
   /**
    * Pop the top 2*n values from the stack (where n is obtained from
    * [UnlinkedExpr.ints]), interpret them as key/value pairs, place them in a
-   * [Map], and push the result back onto the stack.  The two type parameters for
-   * the [Map] are obtained from [UnlinkedExpr.references].
+   * [Map], and push the result back onto the stack.  The two type parameters
+   * for the [Map] are obtained from [UnlinkedExpr.references].
    */
   makeTypedMap,
 
@@ -2618,8 +2653,8 @@
   int get inheritsCovariantSlot;
 
   /**
-   * The synthetic initializer function of the parameter.  Absent if the variable
-   * does not have an initializer.
+   * The synthetic initializer function of the parameter.  Absent if the
+   * variable does not have an initializer.
    */
   @Id(12)
   UnlinkedExecutable get initializer;
@@ -2637,7 +2672,14 @@
   bool get isFinal;
 
   /**
-   * Indicates whether this is a function-typed parameter.
+   * Indicates whether this is a function-typed parameter. A parameter is
+   * function-typed if the declaration of the parameter has explicit formal
+   * parameters
+   * ```
+   * int functionTyped(int p)
+   * ```
+   * but is not function-typed if it does not, even if the type of the parameter
+   * is a function type.
    */
   @Id(5)
   bool get isFunctionTyped;
@@ -2886,12 +2928,20 @@
   List<UnlinkedParam> get parameters;
 
   /**
-   * Return type of the typedef.
+   * If [style] is [TypedefStyle.functionType], the return type of the typedef.
+   * If [style] is [TypedefStyle.genericFunctionType], the function type being
+   * defined.
    */
   @Id(2)
   EntityRef get returnType;
 
   /**
+   * The style of the typedef.
+   */
+  @Id(8)
+  TypedefStyle get style;
+
+  /**
    * Type parameters of the typedef, if any.
    */
   @Id(5)
diff --git a/pkg/analyzer/lib/src/summary/link.dart b/pkg/analyzer/lib/src/summary/link.dart
index d67a8e5..a43bc65 100644
--- a/pkg/analyzer/lib/src/summary/link.dart
+++ b/pkg/analyzer/lib/src/summary/link.dart
@@ -2381,7 +2381,14 @@
     } else {
       ClassElementForLink classElement =
           unit.resolveConstructorClassRef(ref.reference).asClass;
-      stack.add(classElement?.type ?? DynamicTypeImpl.instance);
+      DartType inferredType;
+      if (classElement != null) {
+        InterfaceType rawType = classElement.type;
+        inferredType = linker.typeSystem.instantiateToBounds(rawType);
+      } else {
+        inferredType = DynamicTypeImpl.instance;
+      }
+      stack.add(inferredType);
     }
   }
 
diff --git a/pkg/analyzer/test/file_system/memory_file_system_test.dart b/pkg/analyzer/test/file_system/memory_file_system_test.dart
index cb39b49..3c3ac72 100644
--- a/pkg/analyzer/test/file_system/memory_file_system_test.dart
+++ b/pkg/analyzer/test/file_system/memory_file_system_test.dart
@@ -47,6 +47,19 @@
 class FileTest {
   MemoryResourceProvider provider = new MemoryResourceProvider();
 
+  void test_copy() {
+    String contents = 'contents';
+    File file =
+        provider.newFile(provider.convertPath('/foo/file.txt'), contents);
+    Folder destination =
+        provider.getFolder(provider.convertPath('/destination'));
+
+    File copy = file.copyTo(destination);
+    expect(copy.parent, destination);
+    expect(copy.shortName, file.shortName);
+    expect(copy.readAsStringSync(), contents);
+  }
+
   void test_delete() {
     File file =
         provider.newFile(provider.convertPath('/foo/file.txt'), 'content');
@@ -311,6 +324,22 @@
     expect(folder.contains(provider.convertPath('/foo/bar')), isFalse);
   }
 
+  void test_copy() {
+    String sourcePath = provider.convertPath('/source');
+    String subdirPath = provider.convertPath('/source/subdir');
+    provider.newFolder(sourcePath);
+    provider.newFolder(subdirPath);
+    provider.newFile(provider.convertPath('/source/file1.txt'), 'file1');
+    provider.newFile(provider.convertPath('/source/subdir/file2.txt'), 'file2');
+    Folder source = provider.getFolder(sourcePath);
+    Folder destination =
+        provider.getFolder(provider.convertPath('/destination'));
+
+    Folder copy = source.copyTo(destination);
+    expect(copy.parent, destination);
+    _verifyStructure(copy, source);
+  }
+
   void test_delete() {
     Folder folder = provider.newFolder(provider.convertPath('/foo'));
     Folder barFolder = provider.newFolder(provider.convertPath('/foo/bar'));
@@ -457,6 +486,52 @@
     Folder folder = provider.newFolder(path);
     expect(folder.toUri(), provider.pathContext.toUri(path));
   }
+
+  /**
+   * Verify that the [copy] has the same name and content as the [source].
+   */
+  void _verifyStructure(Folder copy, Folder source) {
+    expect(copy.shortName, source.shortName);
+    Map<String, File> sourceFiles = <String, File>{};
+    Map<String, Folder> sourceFolders = <String, Folder>{};
+    for (Resource child in source.getChildren()) {
+      if (child is File) {
+        sourceFiles[child.shortName] = child;
+      } else if (child is Folder) {
+        sourceFolders[child.shortName] = child;
+      } else {
+        fail('Unknown class of resource: ${child.runtimeType}');
+      }
+    }
+    Map<String, File> copyFiles = <String, File>{};
+    Map<String, Folder> copyFolders = <String, Folder>{};
+    for (Resource child in source.getChildren()) {
+      if (child is File) {
+        copyFiles[child.shortName] = child;
+      } else if (child is Folder) {
+        copyFolders[child.shortName] = child;
+      } else {
+        fail('Unknown class of resource: ${child.runtimeType}');
+      }
+    }
+    for (String fileName in sourceFiles.keys) {
+      File sourceChild = sourceFiles[fileName];
+      File copiedChild = copyFiles[fileName];
+      if (copiedChild == null) {
+        fail('Failed to copy file ${sourceChild.path}');
+      }
+      expect(copiedChild.readAsStringSync(), sourceChild.readAsStringSync(),
+          reason: 'Incorrectly copied file ${sourceChild.path}');
+    }
+    for (String fileName in sourceFolders.keys) {
+      Folder sourceChild = sourceFolders[fileName];
+      Folder copiedChild = copyFolders[fileName];
+      if (copiedChild == null) {
+        fail('Failed to copy folder ${sourceChild.path}');
+      }
+      _verifyStructure(copiedChild, sourceChild);
+    }
+  }
 }
 
 @reflectiveTest
diff --git a/pkg/analyzer/test/file_system/physical_resource_provider_test.dart b/pkg/analyzer/test/file_system/physical_resource_provider_test.dart
index 62b4bba..71c30b9 100644
--- a/pkg/analyzer/test/file_system/physical_resource_provider_test.dart
+++ b/pkg/analyzer/test/file_system/physical_resource_provider_test.dart
@@ -44,6 +44,18 @@
     file = PhysicalResourceProvider.INSTANCE.getResource(path);
   }
 
+  void test_copy() {
+    PhysicalResourceProvider provider = PhysicalResourceProvider.INSTANCE;
+    String contents = 'contents';
+    new io.File(path).writeAsStringSync(contents);
+    Folder destination = provider.getFolder(join(tempPath, 'destination'));
+
+    File copy = file.copyTo(destination);
+    expect(copy.parent, destination);
+    expect(copy.shortName, file.shortName);
+    expect(copy.readAsStringSync(), contents);
+  }
+
   void test_createSource() {
     new io.File(path).writeAsStringSync('contents');
     Source source = file.createSource();
@@ -300,6 +312,22 @@
     expect(folder.contains(path), isFalse);
   }
 
+  void test_copy() {
+    PhysicalResourceProvider provider = PhysicalResourceProvider.INSTANCE;
+    String sourcePath = join(tempPath, 'source');
+    String subdirPath = join(sourcePath, 'subdir');
+    new io.Directory(sourcePath).createSync();
+    new io.Directory(subdirPath).createSync();
+    new io.File(join(sourcePath, 'file1.txt')).writeAsStringSync('file1');
+    new io.File(join(subdirPath, 'file2.txt')).writeAsStringSync('file2');
+    Folder source = provider.getFolder(sourcePath);
+    Folder destination = provider.getFolder(join(tempPath, 'destination'));
+
+    Folder copy = source.copyTo(destination);
+    expect(copy.parent, destination);
+    _verifyStructure(copy, source);
+  }
+
   void test_delete() {
     new io.File(join(path, 'myFile')).createSync();
     var child = folder.getChild('myFile');
@@ -449,6 +477,52 @@
     Folder folder = PhysicalResourceProvider.INSTANCE.getFolder(path);
     expect(folder.toUri(), new Uri.directory(path));
   }
+
+  /**
+   * Verify that the [copy] has the same name and content as the [source].
+   */
+  void _verifyStructure(Folder copy, Folder source) {
+    expect(copy.shortName, source.shortName);
+    Map<String, File> sourceFiles = <String, File>{};
+    Map<String, Folder> sourceFolders = <String, Folder>{};
+    for (Resource child in source.getChildren()) {
+      if (child is File) {
+        sourceFiles[child.shortName] = child;
+      } else if (child is Folder) {
+        sourceFolders[child.shortName] = child;
+      } else {
+        fail('Unknown class of resource: ${child.runtimeType}');
+      }
+    }
+    Map<String, File> copyFiles = <String, File>{};
+    Map<String, Folder> copyFolders = <String, Folder>{};
+    for (Resource child in source.getChildren()) {
+      if (child is File) {
+        copyFiles[child.shortName] = child;
+      } else if (child is Folder) {
+        copyFolders[child.shortName] = child;
+      } else {
+        fail('Unknown class of resource: ${child.runtimeType}');
+      }
+    }
+    for (String fileName in sourceFiles.keys) {
+      File sourceChild = sourceFiles[fileName];
+      File copiedChild = copyFiles[fileName];
+      if (copiedChild == null) {
+        fail('Failed to copy file ${sourceChild.path}');
+      }
+      expect(copiedChild.readAsStringSync(), sourceChild.readAsStringSync(),
+          reason: 'Incorrectly copied file ${sourceChild.path}');
+    }
+    for (String fileName in sourceFolders.keys) {
+      Folder sourceChild = sourceFolders[fileName];
+      Folder copiedChild = copyFolders[fileName];
+      if (copiedChild == null) {
+        fail('Failed to copy folder ${sourceChild.path}');
+      }
+      _verifyStructure(copiedChild, sourceChild);
+    }
+  }
 }
 
 @reflectiveTest
diff --git a/pkg/analyzer/test/generated/compile_time_error_code_test.dart b/pkg/analyzer/test/generated/compile_time_error_code_test.dart
index 3c95c9d..a8b21c9 100644
--- a/pkg/analyzer/test/generated/compile_time_error_code_test.dart
+++ b/pkg/analyzer/test/generated/compile_time_error_code_test.dart
@@ -624,6 +624,16 @@
     verify([source]);
   }
 
+  test_builtInIdentifierAsPrefixName() async {
+    Source source = addSource("import 'dart:async' as abstract;");
+    await computeAnalysisResult(source);
+    assertErrors(source, [
+      CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_PREFIX_NAME,
+      HintCode.UNUSED_IMPORT
+    ]);
+    verify([source]);
+  }
+
   test_builtInIdentifierAsType_formalParameter_field() async {
     Source source = addSource(r'''
 class A {
diff --git a/pkg/analyzer/test/generated/non_error_resolver_test.dart b/pkg/analyzer/test/generated/non_error_resolver_test.dart
index 21568cc..f9c5a45 100644
--- a/pkg/analyzer/test/generated/non_error_resolver_test.dart
+++ b/pkg/analyzer/test/generated/non_error_resolver_test.dart
@@ -2195,17 +2195,6 @@
     verify([source]);
   }
 
-  test_implicitThisReferenceInInitializer_importPrefix() async {
-    Source source = addSource(r'''
-import 'dart:async' as abstract;
-class A {
-  var v = new abstract.Completer();
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
-  }
-
   test_implicitThisReferenceInInitializer_prefixedIdentifier() async {
     Source source = addSource(r'''
 class A {
diff --git a/pkg/analyzer/test/generated/parser_fasta_test.dart b/pkg/analyzer/test/generated/parser_fasta_test.dart
index eb8b5f9..c272a1a 100644
--- a/pkg/analyzer/test/generated/parser_fasta_test.dart
+++ b/pkg/analyzer/test/generated/parser_fasta_test.dart
@@ -66,13 +66,6 @@
 
   @override
   @failingTest
-  void test_parseClassMember_getter_functionType() {
-    // TODO(paulberry): InputError: ErrorKind.ExpectedFunctionBody {actual: get}
-    super.test_parseClassMember_getter_functionType();
-  }
-
-  @override
-  @failingTest
   void test_parseClassMember_method_generic_comment_noReturnType() {
     // TODO(paulberry): Fasta doesn't support generic comment syntax
     super.test_parseClassMember_method_generic_comment_noReturnType();
@@ -101,20 +94,6 @@
 
   @override
   @failingTest
-  void test_parseClassMember_method_returnType_functionType() {
-    // TODO(paulberry): InputError: ErrorKind.ExpectedFunctionBody {actual: m}
-    super.test_parseClassMember_method_returnType_functionType();
-  }
-
-  @override
-  @failingTest
-  void test_parseClassMember_operator_functionType() {
-    // TODO(paulberry): InputError: ErrorKind.ExpectedFunctionBody {actual: operator}
-    super.test_parseClassMember_operator_functionType();
-  }
-
-  @override
-  @failingTest
   void test_parseClassMember_redirectingFactory_const() {
     // TODO(paulberry): Unhandled event: ConstructorReference
     super.test_parseClassMember_redirectingFactory_const();
@@ -154,55 +133,6 @@
     // TODO(paulberry): Expected: an object with length of <1>
     super.test_parseConstructorFieldInitializer_unqualified();
   }
-
-  @override
-  @failingTest
-  void test_parseGetter_nonStatic() {
-    // TODO(paulberry): handle doc comments
-    super.test_parseGetter_nonStatic();
-  }
-
-  @override
-  @failingTest
-  void test_parseGetter_static() {
-    // TODO(paulberry): Invalid modifier (static). Report an error.
-    super.test_parseGetter_static();
-  }
-
-  @override
-  @failingTest
-  void test_parseInitializedIdentifierList_type() {
-    // TODO(paulberry): handle doc comments
-    super.test_parseInitializedIdentifierList_type();
-  }
-
-  @override
-  @failingTest
-  void test_parseInitializedIdentifierList_var() {
-    // TODO(paulberry): handle doc comments
-    super.test_parseInitializedIdentifierList_var();
-  }
-
-  @override
-  @failingTest
-  void test_parseOperator() {
-    // TODO(paulberry): handle doc comments
-    super.test_parseOperator();
-  }
-
-  @override
-  @failingTest
-  void test_parseSetter_nonStatic() {
-    // TODO(paulberry): handle doc comments
-    super.test_parseSetter_nonStatic();
-  }
-
-  @override
-  @failingTest
-  void test_parseSetter_static() {
-    // TODO(paulberry): Invalid modifier (static). Report an error.
-    super.test_parseSetter_static();
-  }
 }
 
 /**
@@ -331,29 +261,23 @@
   @override
   @failingTest
   void
-      test_parseAssignableExpression_expression_args_dot_typeParameterComments() {
+      test_parseAssignableExpression_expression_args_dot_typeArgumentComments() {
     super
-        .test_parseAssignableExpression_expression_args_dot_typeParameterComments();
+        .test_parseAssignableExpression_expression_args_dot_typeArgumentComments();
   }
 
   @override
   @failingTest
-  void test_parseAssignableExpression_expression_args_dot_typeParameters() {
-    super.test_parseAssignableExpression_expression_args_dot_typeParameters();
+  void test_parseAssignableExpression_expression_args_dot_typeArguments() {
+    super.test_parseAssignableExpression_expression_args_dot_typeArguments();
   }
 
   @override
   @failingTest
   void
-      test_parseAssignableExpression_identifier_args_dot_typeParameterComments() {
+      test_parseAssignableExpression_identifier_args_dot_typeArgumentComments() {
     super
-        .test_parseAssignableExpression_identifier_args_dot_typeParameterComments();
-  }
-
-  @override
-  @failingTest
-  void test_parseAwaitExpression() {
-    super.test_parseAwaitExpression();
+        .test_parseAssignableExpression_identifier_args_dot_typeArgumentComments();
   }
 
   @override
@@ -376,24 +300,12 @@
 
   @override
   @failingTest
-  void test_parseCascadeSection_p_assign_withCascade() {
-    super.test_parseCascadeSection_p_assign_withCascade();
-  }
-
-  @override
-  @failingTest
   void test_parseCascadeSection_p_assign_withCascade_typeArgumentComments() {
     super.test_parseCascadeSection_p_assign_withCascade_typeArgumentComments();
   }
 
   @override
   @failingTest
-  void test_parseCascadeSection_p_assign_withCascade_typeArguments() {
-    super.test_parseCascadeSection_p_assign_withCascade_typeArguments();
-  }
-
-  @override
-  @failingTest
   void test_parseCascadeSection_pa_typeArgumentComments() {
     super.test_parseCascadeSection_pa_typeArgumentComments();
   }
@@ -430,12 +342,6 @@
 
   @override
   @failingTest
-  void test_parseConstExpression_instanceCreation() {
-    super.test_parseConstExpression_instanceCreation();
-  }
-
-  @override
-  @failingTest
   void test_parseConstExpression_listLiteral_typed_genericComment() {
     super.test_parseConstExpression_listLiteral_typed_genericComment();
   }
@@ -475,42 +381,36 @@
   @override
   @failingTest
   void
-      test_parseInstanceCreationExpression_qualifiedType_named_typeParameterComment() {
+      test_parseInstanceCreationExpression_qualifiedType_named_typeArgumentComments() {
     super
-        .test_parseInstanceCreationExpression_qualifiedType_named_typeParameterComment();
+        .test_parseInstanceCreationExpression_qualifiedType_named_typeArgumentComments();
   }
 
   @override
   @failingTest
   void
-      test_parseInstanceCreationExpression_qualifiedType_typeParameterComment() {
+      test_parseInstanceCreationExpression_qualifiedType_typeArgumentComments() {
     super
-        .test_parseInstanceCreationExpression_qualifiedType_typeParameterComment();
+        .test_parseInstanceCreationExpression_qualifiedType_typeArgumentComments();
   }
 
   @override
   @failingTest
-  void test_parseInstanceCreationExpression_type_named_typeParameterComment() {
+  void test_parseInstanceCreationExpression_type_named_typeArgumentComments() {
     super
-        .test_parseInstanceCreationExpression_type_named_typeParameterComment();
+        .test_parseInstanceCreationExpression_type_named_typeArgumentComments();
   }
 
   @override
   @failingTest
-  void test_parseInstanceCreationExpression_type_typeParameterComment() {
-    super.test_parseInstanceCreationExpression_type_typeParameterComment();
+  void test_parseInstanceCreationExpression_type_typeArgumentComments() {
+    super.test_parseInstanceCreationExpression_type_typeArgumentComments();
   }
 
   @override
   @failingTest
-  void test_parseInstanceCreationExpression_type_typeParameters_nullable() {
-    super.test_parseInstanceCreationExpression_type_typeParameters_nullable();
-  }
-
-  @override
-  @failingTest
-  void test_parseListLiteral_empty_oneToken() {
-    super.test_parseListLiteral_empty_oneToken();
+  void test_parseInstanceCreationExpression_type_typeArguments_nullable() {
+    super.test_parseInstanceCreationExpression_type_typeArguments_nullable();
   }
 
   @override
@@ -521,72 +421,6 @@
 
   @override
   @failingTest
-  void test_parseListLiteral_empty_twoTokens() {
-    super.test_parseListLiteral_empty_twoTokens();
-  }
-
-  @override
-  @failingTest
-  void test_parseListOrMapLiteral_list_noType() {
-    super.test_parseListOrMapLiteral_list_noType();
-  }
-
-  @override
-  @failingTest
-  void test_parseListOrMapLiteral_list_type() {
-    super.test_parseListOrMapLiteral_list_type();
-  }
-
-  @override
-  @failingTest
-  void test_parseListOrMapLiteral_map_noType() {
-    super.test_parseListOrMapLiteral_map_noType();
-  }
-
-  @override
-  @failingTest
-  void test_parseListOrMapLiteral_map_type() {
-    super.test_parseListOrMapLiteral_map_type();
-  }
-
-  @override
-  @failingTest
-  void test_parseMapLiteral_empty() {
-    super.test_parseMapLiteral_empty();
-  }
-
-  @override
-  @failingTest
-  void test_parseMapLiteral_multiple() {
-    super.test_parseMapLiteral_multiple();
-  }
-
-  @override
-  @failingTest
-  void test_parseMapLiteral_single() {
-    super.test_parseMapLiteral_single();
-  }
-
-  @override
-  @failingTest
-  void test_parseMapLiteralEntry_complex() {
-    super.test_parseMapLiteralEntry_complex();
-  }
-
-  @override
-  @failingTest
-  void test_parseMapLiteralEntry_int() {
-    super.test_parseMapLiteralEntry_int();
-  }
-
-  @override
-  @failingTest
-  void test_parseMapLiteralEntry_string() {
-    super.test_parseMapLiteralEntry_string();
-  }
-
-  @override
-  @failingTest
   void
       test_parsePostfixExpression_none_methodInvocation_question_dot_typeArgumentComments() {
     super
@@ -603,38 +437,20 @@
 
   @override
   @failingTest
-  void test_parsePrimaryExpression_const() {
-    super.test_parsePrimaryExpression_const();
-  }
-
-  @override
-  @failingTest
   void test_parsePrimaryExpression_listLiteral_typed_genericComment() {
     super.test_parsePrimaryExpression_listLiteral_typed_genericComment();
   }
 
   @override
   @failingTest
-  void test_parsePrimaryExpression_mapLiteral() {
-    super.test_parsePrimaryExpression_mapLiteral();
-  }
-
-  @override
-  @failingTest
   void test_parsePrimaryExpression_mapLiteral_typed_genericComment() {
     super.test_parsePrimaryExpression_mapLiteral_typed_genericComment();
   }
 
   @override
   @failingTest
-  void test_parseRelationalExpression_as_functionType_noReturnType() {
-    super.test_parseRelationalExpression_as_functionType_noReturnType();
-  }
-
-  @override
-  @failingTest
-  void test_parseRelationalExpression_as_functionType_returnType() {
-    super.test_parseRelationalExpression_as_functionType_returnType();
+  void test_parsePrimaryExpression_super() {
+    super.test_parsePrimaryExpression_super();
   }
 
   @override
@@ -651,12 +467,6 @@
 
   @override
   @failingTest
-  void test_parseRethrowExpression() {
-    super.test_parseRethrowExpression();
-  }
-
-  @override
-  @failingTest
   void test_parseSuperConstructorInvocation_named() {
     super.test_parseSuperConstructorInvocation_named();
   }
@@ -669,18 +479,6 @@
 
   @override
   @failingTest
-  void test_parseSymbolLiteral_operator() {
-    super.test_parseSymbolLiteral_operator();
-  }
-
-  @override
-  @failingTest
-  void test_parseSymbolLiteral_void() {
-    super.test_parseSymbolLiteral_void();
-  }
-
-  @override
-  @failingTest
   void test_parseUnaryExpression_decrement_super() {
     super.test_parseUnaryExpression_decrement_super();
   }
@@ -761,7 +559,7 @@
 
   @override
   void createParser(String content) {
-    var scanner = new StringScanner(content);
+    var scanner = new StringScanner(content, includeComments: true);
     _parserProxy = new ParserProxy(scanner.tokenize());
   }
 
@@ -789,7 +587,8 @@
 
   @override
   AwaitExpression parseAwaitExpression(String code) {
-    return _parseExpression(code);
+    var function = _parseExpression('() async => $code') as FunctionExpression;
+    return (function.body as ExpressionFunctionBody).expression;
   }
 
   @override
@@ -810,7 +609,7 @@
   @override
   Expression parseCascadeSection(String code) {
     var cascadeExpression = _parseExpression('null$code') as CascadeExpression;
-    return cascadeExpression.cascadeSections.single;
+    return cascadeExpression.cascadeSections.first;
   }
 
   @override
@@ -888,8 +687,12 @@
       {bool inFunctionType: false,
       List<ErrorCode> errorCodes: const <ErrorCode>[]}) {
     return _runParser(
-            code, (parser) => parser.parseFormalParameters, errorCodes)
-        as FormalParameterList;
+        code,
+        (parser) => (fasta.Token token) {
+              return parser.parseFormalParameters(token,
+                  inFunctionType: inFunctionType);
+            },
+        errorCodes) as FormalParameterList;
   }
 
   @override
@@ -931,7 +734,8 @@
 
   @override
   TypedLiteral parseListOrMapLiteral(analyzer.Token modifier, String code) {
-    return _parseExpression('$modifier $code');
+    String literalCode = modifier != null ? '$modifier $code' : code;
+    return parsePrimaryExpression(literalCode) as TypedLiteral;
   }
 
   @override
@@ -955,12 +759,13 @@
       sc += typeArgumentsCode;
     }
     sc += code;
-    return _parseExpression(sc);
+    return parsePrimaryExpression(sc) as MapLiteral;
   }
 
   @override
   MapLiteralEntry parseMapLiteralEntry(String code) {
-    return (_parseExpression('{$code}') as MapLiteral).entries.single;
+    var mapLiteral = parseMapLiteral(null, null, '{ $code }');
+    return mapLiteral.entries.single;
   }
 
   @override
@@ -994,7 +799,9 @@
 
   @override
   Expression parsePrimaryExpression(String code) {
-    return _parseExpression(code);
+    return _runParser(
+            code, (parser) => parser.parsePrimary, const <ErrorCode>[])
+        as Expression;
   }
 
   @override
@@ -1081,27 +888,6 @@
     with FormalParameterParserTestMixin {
   @override
   @failingTest
-  void test_parseFormalParameter_covariant_type_function() {
-    // TODO(scheglov): Unhandled event: FunctionTypedFormalParameter
-    super.test_parseFormalParameter_covariant_type_function();
-  }
-
-  @override
-  @failingTest
-  void test_parseFormalParameter_type_function() {
-    // TODO(scheglov): Unhandled event: FunctionTypedFormalParameter
-    super.test_parseFormalParameter_type_function();
-  }
-
-  @override
-  @failingTest
-  void test_parseFormalParameterList_normal_named_inFunctionType() {
-    // TODO(scheglov): Unhandled event: OptionalFormalParameters
-    super.test_parseFormalParameterList_normal_named_inFunctionType();
-  }
-
-  @override
-  @failingTest
   void test_parseFormalParameterList_prefixedType_partial() {
     // TODO(scheglov): Unimplemented: errors
     super.test_parseFormalParameterList_prefixedType_partial();
@@ -1181,13 +967,6 @@
     super
         .test_parseNormalFormalParameter_function_void_typeParameters_nullable();
   }
-
-  @override
-  @failingTest
-  void test_parseNormalFormalParameter_simple_noName() {
-    // TODO(scheglov): in function type, type instead of parameter name
-    super.test_parseNormalFormalParameter_simple_noName();
-  }
 }
 
 /**
@@ -1332,13 +1111,6 @@
 
   @override
   @failingTest
-  void test_parseClassDeclaration_typeAlias_withB() {
-    // TODO(paulberry,ahe): capture `with` token.
-    super.test_parseClassDeclaration_typeAlias_withB();
-  }
-
-  @override
-  @failingTest
   void test_parseCompilationUnit_builtIn_asFunctionName() {
     // TODO(paulberry,ahe): Fasta's parser is confused when one of the built-in
     // identifiers `export`, `import`, `library`, `part`, or `typedef` appears
@@ -1348,13 +1120,6 @@
 
   @override
   @failingTest
-  void test_parseCompilationUnit_empty() {
-    // TODO(paulberry): No objects placed on stack
-    super.test_parseCompilationUnit_empty();
-  }
-
-  @override
-  @failingTest
   void test_parseCompilationUnit_exportAsPrefix() {
     // TODO(paulberry): As of commit 5de9108 this syntax is invalid.
     super.test_parseCompilationUnit_exportAsPrefix();
@@ -1369,13 +1134,6 @@
 
   @override
   @failingTest
-  void test_parseCompilationUnit_script() {
-    // TODO(paulberry): No objects placed on stack
-    super.test_parseCompilationUnit_script();
-  }
-
-  @override
-  @failingTest
   void test_parseCompilationUnit_typedefAsPrefix() {
     // TODO(paulberry): As of commit 5de9108 this syntax is invalid.
     super.test_parseCompilationUnit_typedefAsPrefix();
@@ -1391,25 +1149,6 @@
         .test_parseCompilationUnitMember_function_generic_noReturnType_annotated();
   }
 
-  void test_parseCompilationUnitMember_typedef() {
-    // TODO(paulberry): Unhandled event: FunctionTypeAlias
-    super.test_parseCompilationUnitMember_typedef();
-  }
-
-  @override
-  @failingTest
-  void test_parseDirectives_complete() {
-    // TODO(paulberry,ahe): Fasta doesn't support script tags yet.
-    super.test_parseDirectives_complete();
-  }
-
-  @override
-  @failingTest
-  void test_parseDirectives_empty() {
-    // TODO(paulberry): No objects placed on stack
-    super.test_parseDirectives_empty();
-  }
-
   @override
   @failingTest
   void test_parseDirectives_mixed() {
@@ -1422,27 +1161,6 @@
 
   @override
   @failingTest
-  void test_parseDirectives_script() {
-    // TODO(paulberry): No objects placed on stack
-    super.test_parseDirectives_script();
-  }
-
-  @override
-  @failingTest
-  void test_parseFunctionDeclaration_function() {
-    // TODO(paulberry): handle doc comments
-    super.test_parseFunctionDeclaration_function();
-  }
-
-  @override
-  @failingTest
-  void test_parseFunctionDeclaration_functionWithTypeParameters() {
-    // TODO(paulberry): handle doc comments
-    super.test_parseFunctionDeclaration_functionWithTypeParameters();
-  }
-
-  @override
-  @failingTest
   void test_parseFunctionDeclaration_functionWithTypeParameters_comment() {
     // TODO(paulberry,ahe): generic method comment syntax is not supported by
     // Fasta.
@@ -1451,20 +1169,6 @@
 
   @override
   @failingTest
-  void test_parseFunctionDeclaration_getter() {
-    // TODO(paulberry): handle doc comments
-    super.test_parseFunctionDeclaration_getter();
-  }
-
-  @override
-  @failingTest
-  void test_parseFunctionDeclaration_setter() {
-    // TODO(paulberry): handle doc comments
-    super.test_parseFunctionDeclaration_setter();
-  }
-
-  @override
-  @failingTest
   void test_parsePartOfDirective_name() {
     // TODO(paulberry,ahe): Thes test verifies that even if URIs in "part of"
     // declarations are enabled, a construct of the form "part of identifier;"
@@ -1480,78 +1184,4 @@
     // Fasta.
     super.test_parsePartOfDirective_uri();
   }
-
-  @override
-  @failingTest
-  void test_parseTypeAlias_genericFunction_noParameters() {
-    super.test_parseTypeAlias_genericFunction_noParameters();
-  }
-
-  @override
-  @failingTest
-  void test_parseTypeAlias_genericFunction_noReturnType() {
-    super.test_parseTypeAlias_genericFunction_noReturnType();
-  }
-
-  @override
-  @failingTest
-  void test_parseTypeAlias_genericFunction_parameterizedReturnType() {
-    super.test_parseTypeAlias_genericFunction_parameterizedReturnType();
-  }
-
-  @override
-  @failingTest
-  void test_parseTypeAlias_genericFunction_parameters() {
-    super.test_parseTypeAlias_genericFunction_parameters();
-  }
-
-  @override
-  @failingTest
-  void test_parseTypeAlias_genericFunction_typeParameters() {
-    super.test_parseTypeAlias_genericFunction_typeParameters();
-  }
-
-  @override
-  @failingTest
-  void test_parseTypeAlias_genericFunction_typeParameters_noParameters() {
-    super.test_parseTypeAlias_genericFunction_typeParameters_noParameters();
-  }
-
-  @override
-  @failingTest
-  void test_parseTypeAlias_genericFunction_typeParameters_noReturnType() {
-    super.test_parseTypeAlias_genericFunction_typeParameters_noReturnType();
-  }
-
-  @override
-  @failingTest
-  void
-      test_parseTypeAlias_genericFunction_typeParameters_parameterizedReturnType() {
-    super
-        .test_parseTypeAlias_genericFunction_typeParameters_parameterizedReturnType();
-  }
-
-  @override
-  @failingTest
-  void test_parseTypeAlias_genericFunction_typeParameters_parameters() {
-    super.test_parseTypeAlias_genericFunction_typeParameters_parameters();
-  }
-
-  @override
-  @failingTest
-  void test_parseTypeAlias_genericFunction_typeParameters_typeParameters() {
-    super.test_parseTypeAlias_genericFunction_typeParameters_typeParameters();
-  }
-
-  @override
-  @failingTest
-  void test_parseTypeAlias_genericFunction_typeParameters_voidReturnType() {
-    super.test_parseTypeAlias_genericFunction_typeParameters_voidReturnType();
-  }
-
-  @override
-  @failingTest
-  void test_parseTypeAlias_genericFunction_voidReturnType() {
-    super.test_parseTypeAlias_genericFunction_voidReturnType();
-  }
 }
diff --git a/pkg/analyzer/test/generated/parser_test.dart b/pkg/analyzer/test/generated/parser_test.dart
index dc25481..52faa8f 100644
--- a/pkg/analyzer/test/generated/parser_test.dart
+++ b/pkg/analyzer/test/generated/parser_test.dart
@@ -82,8 +82,7 @@
 
   Expression parseAssignableExpression(String code, bool primaryAllowed);
 
-  Expression parseAssignableSelector(
-      String code, bool optional,
+  Expression parseAssignableSelector(String code, bool optional,
       {bool allowConditional: true});
 
   AwaitExpression parseAwaitExpression(String code);
@@ -355,6 +354,12 @@
         AwaitExpression, (expression as BinaryExpression).rightOperand);
   }
 
+  void test_parseClassMember_constructor_withDocComment() {
+    createParser('/// Doc\nC();');
+    var constructor = parser.parseClassMember('C') as ConstructorDeclaration;
+    expectCommentText(constructor.documentationComment, '/// Doc');
+  }
+
   void test_parseClassMember_constructor_withInitializers() {
     // TODO(brianwilkerson) Test other kinds of class members: fields, getters
     // and setters.
@@ -1233,6 +1238,18 @@
     expect(method.propertyKeyword, isNotNull);
     expect((method.returnType as TypeName).name.name, 'T');
   }
+
+  void test_simpleFormalParameter_withDocComment() {
+    createParser('''
+int f(
+    /// Doc
+    int x) {}
+''');
+    var function = parseFullCompilationUnitMember() as FunctionDeclaration;
+    var parameter = function.functionExpression.parameters.parameters[0]
+        as NormalFormalParameter;
+    expectCommentText(parameter.documentationComment, '/// Doc');
+  }
 }
 
 /**
@@ -4057,7 +4074,7 @@
   }
 
   void
-      test_parseAssignableExpression_expression_args_dot_typeParameterComments() {
+      test_parseAssignableExpression_expression_args_dot_typeArgumentComments() {
     enableGenericMethodComments = true;
     Expression expression = parseAssignableExpression('(x)/*<F>*/(y).z', false);
     expect(expression, isNotNull);
@@ -4074,7 +4091,7 @@
     expect(propertyAccess.propertyName, isNotNull);
   }
 
-  void test_parseAssignableExpression_expression_args_dot_typeParameters() {
+  void test_parseAssignableExpression_expression_args_dot_typeArguments() {
     Expression expression = parseAssignableExpression('(x)<F>(y).z', false);
     expect(expression, isNotNull);
     assertNoErrors();
@@ -4145,7 +4162,7 @@
   }
 
   void
-      test_parseAssignableExpression_identifier_args_dot_typeParameterComments() {
+      test_parseAssignableExpression_identifier_args_dot_typeArgumentComments() {
     enableGenericMethodComments = true;
     Expression expression = parseAssignableExpression('x/*<E>*/(y).z', false);
     expect(expression, isNotNull);
@@ -4161,7 +4178,7 @@
     expect(propertyAccess.propertyName, isNotNull);
   }
 
-  void test_parseAssignableExpression_identifier_args_dot_typeParameters() {
+  void test_parseAssignableExpression_identifier_args_dot_typeArguments() {
     Expression expression = parseAssignableExpression('x<E>(y).z', false);
     expect(expression, isNotNull);
     assertNoErrors();
@@ -4267,7 +4284,7 @@
   }
 
   void test_parseAwaitExpression() {
-    AwaitExpression expression = parseAwaitExpression('await x;');
+    AwaitExpression expression = parseAwaitExpression('await x');
     expect(expression, isNotNull);
     assertNoErrors();
     expect(expression.awaitKeyword, isNotNull);
@@ -5005,7 +5022,7 @@
   }
 
   void
-      test_parseInstanceCreationExpression_qualifiedType_named_typeParameterComment() {
+      test_parseInstanceCreationExpression_qualifiedType_named_typeArgumentComments() {
     enableGenericMethodComments = true;
     Token token = TokenFactory.tokenFromKeyword(Keyword.NEW);
     InstanceCreationExpression expression =
@@ -5024,7 +5041,7 @@
   }
 
   void
-      test_parseInstanceCreationExpression_qualifiedType_named_typeParameters() {
+      test_parseInstanceCreationExpression_qualifiedType_named_typeArguments() {
     Token token = TokenFactory.tokenFromKeyword(Keyword.NEW);
     InstanceCreationExpression expression =
         parseInstanceCreationExpression('A.B<E>.c()', token);
@@ -5042,7 +5059,7 @@
   }
 
   void
-      test_parseInstanceCreationExpression_qualifiedType_typeParameterComment() {
+      test_parseInstanceCreationExpression_qualifiedType_typeArgumentComments() {
     enableGenericMethodComments = true;
     Token token = TokenFactory.tokenFromKeyword(Keyword.NEW);
     InstanceCreationExpression expression =
@@ -5060,7 +5077,7 @@
     expect(expression.argumentList, isNotNull);
   }
 
-  void test_parseInstanceCreationExpression_qualifiedType_typeParameters() {
+  void test_parseInstanceCreationExpression_qualifiedType_typeArguments() {
     Token token = TokenFactory.tokenFromKeyword(Keyword.NEW);
     InstanceCreationExpression expression =
         parseInstanceCreationExpression('A.B<E>()', token);
@@ -5111,7 +5128,7 @@
     expect(expression.argumentList, isNotNull);
   }
 
-  void test_parseInstanceCreationExpression_type_named_typeParameterComment() {
+  void test_parseInstanceCreationExpression_type_named_typeArgumentComments() {
     enableGenericMethodComments = true;
     Token token = TokenFactory.tokenFromKeyword(Keyword.NEW);
     InstanceCreationExpression expression =
@@ -5129,7 +5146,7 @@
     expect(expression.argumentList, isNotNull);
   }
 
-  void test_parseInstanceCreationExpression_type_named_typeParameters() {
+  void test_parseInstanceCreationExpression_type_named_typeArguments() {
     Token token = TokenFactory.tokenFromKeyword(Keyword.NEW);
     InstanceCreationExpression expression =
         parseInstanceCreationExpression('A<B>.c()', token);
@@ -5146,7 +5163,7 @@
     expect(expression.argumentList, isNotNull);
   }
 
-  void test_parseInstanceCreationExpression_type_typeParameterComment() {
+  void test_parseInstanceCreationExpression_type_typeArgumentComments() {
     enableGenericMethodComments = true;
     Token token = TokenFactory.tokenFromKeyword(Keyword.NEW);
     InstanceCreationExpression expression =
@@ -5164,7 +5181,7 @@
     expect(expression.argumentList, isNotNull);
   }
 
-  void test_parseInstanceCreationExpression_type_typeParameters() {
+  void test_parseInstanceCreationExpression_type_typeArguments() {
     Token token = TokenFactory.tokenFromKeyword(Keyword.NEW);
     InstanceCreationExpression expression =
         parseInstanceCreationExpression('A<B>()', token);
@@ -5181,7 +5198,7 @@
     expect(expression.argumentList, isNotNull);
   }
 
-  void test_parseInstanceCreationExpression_type_typeParameters_nullable() {
+  void test_parseInstanceCreationExpression_type_typeArguments_nullable() {
     enableNnbd = true;
     Token token = TokenFactory.tokenFromKeyword(Keyword.NEW);
     InstanceCreationExpression expression =
@@ -5206,7 +5223,7 @@
     ListLiteral literal = parseListLiteral(token, null, '[]');
     expect(literal, isNotNull);
     assertNoErrors();
-    expect(literal.constKeyword, token);
+    expect(literal.constKeyword.keyword, Keyword.CONST);
     expect(literal.typeArguments, isNull);
     expect(literal.leftBracket, isNotNull);
     expect(literal.elements, hasLength(0));
@@ -5231,7 +5248,7 @@
     ListLiteral literal = parseListLiteral(token, null, '[ ]');
     expect(literal, isNotNull);
     assertNoErrors();
-    expect(literal.constKeyword, token);
+    expect(literal.constKeyword.keyword, Keyword.CONST);
     expect(literal.typeArguments, isNull);
     expect(literal.leftBracket, isNotNull);
     expect(literal.elements, hasLength(0));
@@ -5347,7 +5364,7 @@
     MapLiteral literal = parseMapLiteral(token, '<String, int>', '{}');
     expect(literal, isNotNull);
     assertNoErrors();
-    expect(literal.constKeyword, token);
+    expect(literal.constKeyword.keyword, Keyword.CONST);
     expect(literal.typeArguments, isNotNull);
     expect(literal.leftBracket, isNotNull);
     expect(literal.entries, hasLength(0));
@@ -6835,6 +6852,25 @@
     expect(defaultParameter.kind, kind);
   }
 
+  void test_parseFormalParameter_type_named_noDefault() {
+    ParameterKind kind = ParameterKind.NAMED;
+    FormalParameter parameter = parseFormalParameter('A a', kind);
+    expect(parameter, isNotNull);
+    assertNoErrors();
+    expect(parameter, new isInstanceOf<DefaultFormalParameter>());
+    DefaultFormalParameter defaultParameter = parameter;
+    SimpleFormalParameter simpleParameter =
+        defaultParameter.parameter as SimpleFormalParameter;
+    expect(simpleParameter.covariantKeyword, isNull);
+    expect(simpleParameter.identifier, isNotNull);
+    expect(simpleParameter.keyword, isNull);
+    expect(simpleParameter.type, isNotNull);
+    expect(simpleParameter.kind, kind);
+    expect(defaultParameter.separator, isNull);
+    expect(defaultParameter.defaultValue, isNull);
+    expect(defaultParameter.kind, kind);
+  }
+
   void test_parseFormalParameter_type_normal() {
     ParameterKind kind = ParameterKind.REQUIRED;
     FormalParameter parameter = parseFormalParameter('A a', kind);
@@ -6868,6 +6904,25 @@
     expect(defaultParameter.kind, kind);
   }
 
+  void test_parseFormalParameter_type_positional_noDefault() {
+    ParameterKind kind = ParameterKind.POSITIONAL;
+    FormalParameter parameter = parseFormalParameter('A a', kind);
+    expect(parameter, isNotNull);
+    assertNoErrors();
+    expect(parameter, new isInstanceOf<DefaultFormalParameter>());
+    DefaultFormalParameter defaultParameter = parameter;
+    SimpleFormalParameter simpleParameter =
+        defaultParameter.parameter as SimpleFormalParameter;
+    expect(simpleParameter.covariantKeyword, isNull);
+    expect(simpleParameter.identifier, isNotNull);
+    expect(simpleParameter.keyword, isNull);
+    expect(simpleParameter.type, isNotNull);
+    expect(simpleParameter.kind, kind);
+    expect(defaultParameter.separator, isNull);
+    expect(defaultParameter.defaultValue, isNull);
+    expect(defaultParameter.kind, kind);
+  }
+
   void test_parseFormalParameter_var_named() {
     ParameterKind kind = ParameterKind.NAMED;
     FormalParameter parameter = parseFormalParameter('var a : null', kind);
@@ -7213,6 +7268,11 @@
     expect(parameterList.parameters, hasLength(0));
   }
 
+  void test_parseNormalFormalParameter_field_function_withDocComment() {
+    var parameter = parseNormalFormalParameter('/// Doc\nthis.f()');
+    expectCommentText(parameter.documentationComment, '/// Doc');
+  }
+
   void test_parseNormalFormalParameter_field_noType() {
     NormalFormalParameter parameter = parseNormalFormalParameter('this.a');
     expect(parameter, isNotNull);
@@ -7249,6 +7309,11 @@
     expect(fieldParameter.parameters, isNull);
   }
 
+  void test_parseNormalFormalParameter_field_withDocComment() {
+    var parameter = parseNormalFormalParameter('/// Doc\nthis.a');
+    expectCommentText(parameter.documentationComment, '/// Doc');
+  }
+
   void test_parseNormalFormalParameter_function_named() {
     ParameterKind kind = ParameterKind.NAMED;
     var defaultParameter =
@@ -7487,6 +7552,12 @@
     expect(functionParameter.question, isNotNull);
   }
 
+  void test_parseNormalFormalParameter_function_withDocComment() {
+    var parameter = parseFormalParameter('/// Doc\nf()', ParameterKind.REQUIRED)
+        as FunctionTypedFormalParameter;
+    expectCommentText(parameter.documentationComment, '/// Doc');
+  }
+
   void test_parseNormalFormalParameter_simple_const_noType() {
     NormalFormalParameter parameter = parseNormalFormalParameter('const a');
     expect(parameter, isNotNull);
@@ -7717,11 +7788,10 @@
   }
 
   @override
-  Expression parseAssignableSelector(
-      String code, bool optional,
+  Expression parseAssignableSelector(String code, bool optional,
       {bool allowConditional: true}) {
-    Expression prefix =
-        astFactory.simpleIdentifier(new StringToken(TokenType.STRING, 'foo', 0));
+    Expression prefix = astFactory
+        .simpleIdentifier(new StringToken(TokenType.STRING, 'foo', 0));
     createParser(code);
     return parser.parseAssignableSelector(prefix, optional,
         allowConditional: allowConditional);
@@ -13012,6 +13082,12 @@
         "import 'import1_lib.dart' show hide, show hide ugly;");
   }
 
+  void test_import_withDocComment() {
+    var compilationUnit = parseCompilationUnit('/// Doc\nimport "foo.dart";');
+    var importDirective = compilationUnit.directives[0];
+    expectCommentText(importDirective.documentationComment, '/// Doc');
+  }
+
   void test_parseClassDeclaration_abstract() {
     createParser('abstract class A {}');
     CompilationUnitMember member = parseFullCompilationUnitMember();
@@ -13235,6 +13311,18 @@
     expect(declaration.typeParameters.typeParameters, hasLength(1));
   }
 
+  void test_parseClassDeclaration_withDocumentationComment() {
+    createParser('/// Doc\nclass C {}');
+    var classDeclaration = parseFullCompilationUnitMember() as ClassDeclaration;
+    expectCommentText(classDeclaration.documentationComment, '/// Doc');
+  }
+
+  void test_parseClassTypeAlias_withDocumentationComment() {
+    createParser('/// Doc\nclass C = D with E;');
+    var classTypeAlias = parseFullCompilationUnitMember() as ClassTypeAlias;
+    expectCommentText(classTypeAlias.documentationComment, '/// Doc');
+  }
+
   void test_parseCompilationUnit_abstractAsPrefix_parameterized() {
     createParser('abstract<dynamic> _abstract = new abstract.A();');
     CompilationUnit unit = parser.parseCompilationUnit2();
@@ -13705,6 +13793,12 @@
     expect(typeAlias.parameters.parameters, hasLength(0));
   }
 
+  void test_parseCompilationUnitMember_typedef_withDocComment() {
+    createParser('/// Doc\ntypedef F();');
+    var typeAlias = parseFullCompilationUnitMember() as FunctionTypeAlias;
+    expectCommentText(typeAlias.documentationComment, '/// Doc');
+  }
+
   void test_parseCompilationUnitMember_typedVariable() {
     createParser('int x = 0;');
     CompilationUnitMember member = parseFullCompilationUnitMember();
@@ -13730,6 +13824,13 @@
     expect(declaration.variables.keyword.lexeme, 'var');
   }
 
+  void test_parseCompilationUnitMember_variable_withDocumentationComment() {
+    createParser('/// Doc\nvar x = 0;');
+    var declaration =
+        parseFullCompilationUnitMember() as TopLevelVariableDeclaration;
+    expectCommentText(declaration.documentationComment, '/// Doc');
+  }
+
   void test_parseCompilationUnitMember_variableGet() {
     createParser('String get = null;');
     CompilationUnitMember member = parseFullCompilationUnitMember();
@@ -13765,6 +13866,12 @@
     expect(exportDirective.semicolon, isNotNull);
   }
 
+  void test_parseDirective_export_withDocComment() {
+    createParser("/// Doc\nexport 'foo.dart';");
+    var directive = parseFullDirective() as ExportDirective;
+    expectCommentText(directive.documentationComment, '/// Doc');
+  }
+
   void test_parseDirective_import() {
     createParser("import 'lib/lib.dart';");
     Directive directive = parseFullDirective();
@@ -13816,6 +13923,12 @@
     expect(lib.name.components[2].name, 'c');
   }
 
+  void test_parseDirective_library_withDocumentationComment() {
+    createParser('/// Doc\nlibrary l;');
+    var directive = parseFullDirective() as LibraryDirective;
+    expectCommentText(directive.documentationComment, '/// Doc');
+  }
+
   void test_parseDirective_part() {
     createParser("part 'lib/lib.dart';");
     Directive directive = parseFullDirective();
@@ -13852,6 +13965,18 @@
     expect(partOf.libraryName.components[2].name, 'c');
   }
 
+  void test_parseDirective_part_of_withDocumentationComment() {
+    createParser('/// Doc\npart of a;');
+    var partOf = parseFullDirective() as PartOfDirective;
+    expectCommentText(partOf.documentationComment, '/// Doc');
+  }
+
+  void test_parseDirective_part_withDocumentationComment() {
+    createParser("/// Doc\npart 'lib.dart';");
+    var directive = parseFullDirective() as PartDirective;
+    expectCommentText(directive.documentationComment, '/// Doc');
+  }
+
   void test_parseDirective_partOf() {
     createParser("part of l;");
     Directive directive = parseFullDirective();
@@ -13948,6 +14073,23 @@
     expect(declaration.rightBracket, isNotNull);
   }
 
+  void test_parseEnumDeclaration_withDocComment_onEnum() {
+    createParser('/// Doc\nenum E {ONE}');
+    var declaration = parseFullCompilationUnitMember() as EnumDeclaration;
+    expectCommentText(declaration.documentationComment, '/// Doc');
+  }
+
+  void test_parseEnumDeclaration_withDocComment_onValue() {
+    createParser('''
+enum E {
+  /// Doc
+  ONE
+}''');
+    var declaration = parseFullCompilationUnitMember() as EnumDeclaration;
+    var value = declaration.constants[0];
+    expectCommentText(value.documentationComment, '/// Doc');
+  }
+
   void test_parseExportDirective_configuration_multiple() {
     createParser("export 'lib/lib.dart' if (a) 'b.dart' if (c) 'd.dart';");
     ExportDirective directive = parseFullDirective();
@@ -14582,4 +14724,10 @@
     expect(functionType.returnType, isNotNull);
     expect(functionType.typeParameters, isNull);
   }
+
+  void test_parseTypeAlias_genericFunction_withDocComment() {
+    createParser('/// Doc\ntypedef F = bool Function();');
+    var typeAlias = parseFullCompilationUnitMember() as GenericTypeAlias;
+    expectCommentText(typeAlias.documentationComment, '/// Doc');
+  }
 }
diff --git a/pkg/analyzer/test/src/summary/resynthesize_common.dart b/pkg/analyzer/test/src/summary/resynthesize_common.dart
index c1d72d5..a69a771 100644
--- a/pkg/analyzer/test/src/summary/resynthesize_common.dart
+++ b/pkg/analyzer/test/src/summary/resynthesize_common.dart
@@ -3669,6 +3669,32 @@
     }
   }
 
+  test_const_invokeConstructor_named_unresolved6() {
+    var library = checkLibrary(
+        r'''
+class C<T> {}
+const V = const C.named();
+''',
+        allowErrors: true);
+    if (isStrongMode) {
+      checkElementText(
+          library,
+          r'''
+class C<T> {
+}
+const C<dynamic> V = const C.named();
+''');
+    } else {
+      checkElementText(
+          library,
+          r'''
+class C<T> {
+}
+const dynamic V = const C.named();
+''');
+    }
+  }
+
   test_const_invokeConstructor_unnamed() {
     var library = checkLibrary(r'''
 class C {
diff --git a/pkg/analyzer_cli/lib/src/options.dart b/pkg/analyzer_cli/lib/src/options.dart
index aab9ddf..0dfbde4 100644
--- a/pkg/analyzer_cli/lib/src/options.dart
+++ b/pkg/analyzer_cli/lib/src/options.dart
@@ -456,17 +456,11 @@
 
       // Persistent worker.
       if (args.contains('--persistent_worker')) {
-        bool validArgs;
-        if (!args.contains('--build-mode')) {
-          validArgs = false;
-        } else if (args.length == 2) {
-          validArgs = true;
-        } else if (args.length == 4 && args.contains('--dart-sdk')) {
-          validArgs = true;
-        } else {
-          validArgs = false;
-        }
-        if (!validArgs) {
+        bool hasBuildMode = args.contains('--build-mode');
+        bool onlyDartSdkArg = args.length == 2 ||
+            (args.length == 3 && args.any((a) => a.startsWith('--dart-sdk'))) ||
+            (args.length == 4 && args.contains('--dart-sdk'));
+        if (!(hasBuildMode && onlyDartSdkArg)) {
           printAndFail('The --persistent_worker flag should be used with and '
               'only with the --build-mode flag, and possibly the --dart-sdk '
               'option. Got: $args');
diff --git a/pkg/analyzer_plugin/doc/api.html b/pkg/analyzer_plugin/doc/api.html
index 3ddbd12..808a6f0 100644
--- a/pkg/analyzer_plugin/doc/api.html
+++ b/pkg/analyzer_plugin/doc/api.html
@@ -1195,6 +1195,23 @@
           The class that declares the element being suggested. This field is
           omitted if the suggested element is not a member of a class.
         </p>
+      </dd><dt class="field"><b>defaultArgumentListString (<span style="color:#999999">optional</span> String)</b></dt><dd>
+        
+        <p>
+          A default String for use in generating argument list source contents
+          on the client side.
+        </p>
+      </dd><dt class="field"><b>defaultArgumentListTextRanges (<span style="color:#999999">optional</span> List&lt;int&gt;)</b></dt><dd>
+        
+        <p>
+          Pairs of offsets and lengths describing 'defaultArgumentListString'
+          text ranges suitable for use by clients to set up linked edits of
+          default argument source contents. For example, given an argument list
+          string 'x, y', the corresponding text range [0, 1, 3, 1], indicates
+          two text ranges of length 1, starting at offsets 0 and 3. Clients can
+          use these ranges to treat the 'x' and 'y' values specially for linked
+          edits.
+        </p>
       </dd><dt class="field"><b>element (<span style="color:#999999">optional</span> <a href="#type_Element">Element</a>)</b></dt><dd>
         
         <p>
diff --git a/pkg/analyzer_plugin/lib/protocol/protocol_generated.dart b/pkg/analyzer_plugin/lib/protocol/protocol_generated.dart
index 0e063ca..fe74a87 100644
--- a/pkg/analyzer_plugin/lib/protocol/protocol_generated.dart
+++ b/pkg/analyzer_plugin/lib/protocol/protocol_generated.dart
@@ -2473,6 +2473,8 @@
  *   "docSummary": optional String
  *   "docComplete": optional String
  *   "declaringType": optional String
+ *   "defaultArgumentListString": optional String
+ *   "defaultArgumentListTextRanges": optional List<int>
  *   "element": optional Element
  *   "returnType": optional String
  *   "parameterNames": optional List<String>
@@ -2507,6 +2509,10 @@
 
   String _declaringType;
 
+  String _defaultArgumentListString;
+
+  List<int> _defaultArgumentListTextRanges;
+
   Element _element;
 
   String _returnType;
@@ -2673,6 +2679,42 @@
   }
 
   /**
+   * A default String for use in generating argument list source contents on
+   * the client side.
+   */
+  String get defaultArgumentListString => _defaultArgumentListString;
+
+  /**
+   * A default String for use in generating argument list source contents on
+   * the client side.
+   */
+  void set defaultArgumentListString(String value) {
+    this._defaultArgumentListString = value;
+  }
+
+  /**
+   * Pairs of offsets and lengths describing 'defaultArgumentListString' text
+   * ranges suitable for use by clients to set up linked edits of default
+   * argument source contents. For example, given an argument list string 'x,
+   * y', the corresponding text range [0, 1, 3, 1], indicates two text ranges
+   * of length 1, starting at offsets 0 and 3. Clients can use these ranges to
+   * treat the 'x' and 'y' values specially for linked edits.
+   */
+  List<int> get defaultArgumentListTextRanges => _defaultArgumentListTextRanges;
+
+  /**
+   * Pairs of offsets and lengths describing 'defaultArgumentListString' text
+   * ranges suitable for use by clients to set up linked edits of default
+   * argument source contents. For example, given an argument list string 'x,
+   * y', the corresponding text range [0, 1, 3, 1], indicates two text ranges
+   * of length 1, starting at offsets 0 and 3. Clients can use these ranges to
+   * treat the 'x' and 'y' values specially for linked edits.
+   */
+  void set defaultArgumentListTextRanges(List<int> value) {
+    this._defaultArgumentListTextRanges = value;
+  }
+
+  /**
    * Information about the element reference being suggested.
    */
   Element get element => _element;
@@ -2802,7 +2844,7 @@
     this._importUri = value;
   }
 
-  CompletionSuggestion(CompletionSuggestionKind kind, int relevance, String completion, int selectionOffset, int selectionLength, bool isDeprecated, bool isPotential, {String docSummary, String docComplete, String declaringType, Element element, String returnType, List<String> parameterNames, List<String> parameterTypes, int requiredParameterCount, bool hasNamedParameters, String parameterName, String parameterType, String importUri}) {
+  CompletionSuggestion(CompletionSuggestionKind kind, int relevance, String completion, int selectionOffset, int selectionLength, bool isDeprecated, bool isPotential, {String docSummary, String docComplete, String declaringType, String defaultArgumentListString, List<int> defaultArgumentListTextRanges, Element element, String returnType, List<String> parameterNames, List<String> parameterTypes, int requiredParameterCount, bool hasNamedParameters, String parameterName, String parameterType, String importUri}) {
     this.kind = kind;
     this.relevance = relevance;
     this.completion = completion;
@@ -2813,6 +2855,8 @@
     this.docSummary = docSummary;
     this.docComplete = docComplete;
     this.declaringType = declaringType;
+    this.defaultArgumentListString = defaultArgumentListString;
+    this.defaultArgumentListTextRanges = defaultArgumentListTextRanges;
     this.element = element;
     this.returnType = returnType;
     this.parameterNames = parameterNames;
@@ -2883,6 +2927,14 @@
       if (json.containsKey("declaringType")) {
         declaringType = jsonDecoder.decodeString(jsonPath + ".declaringType", json["declaringType"]);
       }
+      String defaultArgumentListString;
+      if (json.containsKey("defaultArgumentListString")) {
+        defaultArgumentListString = jsonDecoder.decodeString(jsonPath + ".defaultArgumentListString", json["defaultArgumentListString"]);
+      }
+      List<int> defaultArgumentListTextRanges;
+      if (json.containsKey("defaultArgumentListTextRanges")) {
+        defaultArgumentListTextRanges = jsonDecoder.decodeList(jsonPath + ".defaultArgumentListTextRanges", json["defaultArgumentListTextRanges"], jsonDecoder.decodeInt);
+      }
       Element element;
       if (json.containsKey("element")) {
         element = new Element.fromJson(jsonDecoder, jsonPath + ".element", json["element"]);
@@ -2919,7 +2971,7 @@
       if (json.containsKey("importUri")) {
         importUri = jsonDecoder.decodeString(jsonPath + ".importUri", json["importUri"]);
       }
-      return new CompletionSuggestion(kind, relevance, completion, selectionOffset, selectionLength, isDeprecated, isPotential, docSummary: docSummary, docComplete: docComplete, declaringType: declaringType, element: element, returnType: returnType, parameterNames: parameterNames, parameterTypes: parameterTypes, requiredParameterCount: requiredParameterCount, hasNamedParameters: hasNamedParameters, parameterName: parameterName, parameterType: parameterType, importUri: importUri);
+      return new CompletionSuggestion(kind, relevance, completion, selectionOffset, selectionLength, isDeprecated, isPotential, docSummary: docSummary, docComplete: docComplete, declaringType: declaringType, defaultArgumentListString: defaultArgumentListString, defaultArgumentListTextRanges: defaultArgumentListTextRanges, element: element, returnType: returnType, parameterNames: parameterNames, parameterTypes: parameterTypes, requiredParameterCount: requiredParameterCount, hasNamedParameters: hasNamedParameters, parameterName: parameterName, parameterType: parameterType, importUri: importUri);
     } else {
       throw jsonDecoder.mismatch(jsonPath, "CompletionSuggestion", json);
     }
@@ -2944,6 +2996,12 @@
     if (declaringType != null) {
       result["declaringType"] = declaringType;
     }
+    if (defaultArgumentListString != null) {
+      result["defaultArgumentListString"] = defaultArgumentListString;
+    }
+    if (defaultArgumentListTextRanges != null) {
+      result["defaultArgumentListTextRanges"] = defaultArgumentListTextRanges;
+    }
     if (element != null) {
       result["element"] = element.toJson();
     }
@@ -2990,6 +3048,8 @@
           docSummary == other.docSummary &&
           docComplete == other.docComplete &&
           declaringType == other.declaringType &&
+          defaultArgumentListString == other.defaultArgumentListString &&
+          listEqual(defaultArgumentListTextRanges, other.defaultArgumentListTextRanges, (int a, int b) => a == b) &&
           element == other.element &&
           returnType == other.returnType &&
           listEqual(parameterNames, other.parameterNames, (String a, String b) => a == b) &&
@@ -3016,6 +3076,8 @@
     hash = JenkinsSmiHash.combine(hash, docSummary.hashCode);
     hash = JenkinsSmiHash.combine(hash, docComplete.hashCode);
     hash = JenkinsSmiHash.combine(hash, declaringType.hashCode);
+    hash = JenkinsSmiHash.combine(hash, defaultArgumentListString.hashCode);
+    hash = JenkinsSmiHash.combine(hash, defaultArgumentListTextRanges.hashCode);
     hash = JenkinsSmiHash.combine(hash, element.hashCode);
     hash = JenkinsSmiHash.combine(hash, returnType.hashCode);
     hash = JenkinsSmiHash.combine(hash, parameterNames.hashCode);
diff --git a/pkg/analyzer_plugin/test/integration/support/protocol_matchers.dart b/pkg/analyzer_plugin/test/integration/support/protocol_matchers.dart
index 6f0b2c4..0d6e5e2 100644
--- a/pkg/analyzer_plugin/test/integration/support/protocol_matchers.dart
+++ b/pkg/analyzer_plugin/test/integration/support/protocol_matchers.dart
@@ -579,6 +579,8 @@
  *   "docSummary": optional String
  *   "docComplete": optional String
  *   "declaringType": optional String
+ *   "defaultArgumentListString": optional String
+ *   "defaultArgumentListTextRanges": optional List<int>
  *   "element": optional Element
  *   "returnType": optional String
  *   "parameterNames": optional List<String>
@@ -603,6 +605,8 @@
     "docSummary": isString,
     "docComplete": isString,
     "declaringType": isString,
+    "defaultArgumentListString": isString,
+    "defaultArgumentListTextRanges": isListOf(isInt),
     "element": isElement,
     "returnType": isString,
     "parameterNames": isListOf(isString),
diff --git a/pkg/analyzer_plugin/tool/spec/plugin_spec.html b/pkg/analyzer_plugin/tool/spec/plugin_spec.html
index 119e41d..6f48ae8 100644
--- a/pkg/analyzer_plugin/tool/spec/plugin_spec.html
+++ b/pkg/analyzer_plugin/tool/spec/plugin_spec.html
@@ -1038,6 +1038,25 @@
           omitted if the suggested element is not a member of a class.
         </p>
       </field>
+      <field name="defaultArgumentListString" optional="true">
+        <ref>String</ref>
+        <p>
+          A default String for use in generating argument list source contents
+          on the client side.
+        </p>
+      </field>
+      <field name="defaultArgumentListTextRanges" optional="true">
+        <list><ref>int</ref></list>
+        <p>
+          Pairs of offsets and lengths describing 'defaultArgumentListString'
+          text ranges suitable for use by clients to set up linked edits of
+          default argument source contents. For example, given an argument list
+          string 'x, y', the corresponding text range [0, 1, 3, 1], indicates
+          two text ranges of length 1, starting at offsets 0 and 3. Clients can
+          use these ranges to treat the 'x' and 'y' values specially for linked
+          edits.
+        </p>
+      </field>
       <field name="element" optional="true">
         <ref>Element</ref>
         <p>
diff --git a/pkg/compiler/lib/src/diagnostics/messages.dart b/pkg/compiler/lib/src/diagnostics/messages.dart
index 751ffe7..b92e556 100644
--- a/pkg/compiler/lib/src/diagnostics/messages.dart
+++ b/pkg/compiler/lib/src/diagnostics/messages.dart
@@ -2,64 +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.
 
-/**
- * The messages in this file should meet the following guide lines:
- *
- * 1. The message should be a complete sentence starting with an uppercase
- * letter, and ending with a period.
- *
- * 2. Reserved words and embedded identifiers should be in single quotes, so
- * prefer double quotes for the complete message. For example, "The
- * class '#{className}' can't use 'super'." Notice that the word 'class' in the
- * preceding message is not quoted as it refers to the concept 'class', not the
- * reserved word. On the other hand, 'super' refers to the reserved word. Do
- * not quote 'null' and numeric literals.
- *
- * 3. Do not try to compose messages, as it can make translating them hard.
- *
- * 4. Try to keep the error messages short, but informative.
- *
- * 5. Use simple words and terminology, assume the reader of the message
- * doesn't have an advanced degree in math, and that English is not the
- * reader's native language. Do not assume any formal computer science
- * training. For example, do not use Latin abbreviations (prefer "that is" over
- * "i.e.", and "for example" over "e.g."). Also avoid phrases such as "if and
- * only if" and "iff", that level of precision is unnecessary.
- *
- * 6. Prefer contractions when they are in common use, for example, prefer
- * "can't" over "cannot". Using "cannot", "must not", "shall not", etc. is
- * off-putting to people new to programming.
- *
- * 7. Use common terminology, preferably from the Dart Language
- * Specification. This increases the user's chance of finding a good
- * explanation on the web.
- *
- * 8. Do not try to be cute or funny. It is extremely frustrating to work on a
- * product that crashes with a "tongue-in-cheek" message, especially if you did
- * not want to use this product to begin with.
- *
- * 9. Do not lie, that is, do not write error messages containing phrases like
- * "can't happen".  If the user ever saw this message, it would be a
- * lie. Prefer messages like: "Internal error: This function should not be
- * called when 'x' is null.".
- *
- * 10. Prefer to not use imperative tone. That is, the message should not sound
- * accusing or like it is ordering the user around. The computer should
- * describe the problem, not criticize for violating the specification.
- *
- * Other things to keep in mind:
- *
- * An INFO message should always be preceded by a non-INFO message, and the
- * INFO messages are additional details about the preceding non-INFO
- * message. For example, consider duplicated elements. First report a WARNING
- * or ERROR about the duplicated element, and then report an INFO about the
- * location of the existing element.
- *
- * Generally, we want to provide messages that consists of three sentences:
- * 1. what is wrong, 2. why is it wrong, 3. how do I fix it. However, we
- * combine the first two in [template] and the last in [howToFix].
- */
-
+/// The messages in this file should follow the [Guide for Writing
+/// Diagnostics](../../../../front_end/lib/src/fasta/diagnostics.md).
+///
+/// Other things to keep in mind:
+///
+/// An INFO message should always be preceded by a non-INFO message, and the
+/// INFO messages are additional details about the preceding non-INFO
+/// message. For example, consider duplicated elements. First report a WARNING
+/// or ERROR about the duplicated element, and then report an INFO about the
+/// location of the existing element.
 library dart2js.messages;
 
 import 'package:front_end/src/fasta/scanner.dart' show ErrorToken, Token;
diff --git a/pkg/compiler/lib/src/parser/element_listener.dart b/pkg/compiler/lib/src/parser/element_listener.dart
index 1c50d01..f7d9b41 100644
--- a/pkg/compiler/lib/src/parser/element_listener.dart
+++ b/pkg/compiler/lib/src/parser/element_listener.dart
@@ -335,7 +335,7 @@
   }
 
   @override
-  void endMixinApplication() {
+  void endMixinApplication(Token withKeyword) {
     NodeList mixins = popNode();
     NominalTypeAnnotation superclass = popNode();
     pushNode(new MixinApplication(superclass, mixins));
diff --git a/pkg/compiler/lib/src/parser/node_listener.dart b/pkg/compiler/lib/src/parser/node_listener.dart
index 09483b2..f808776 100644
--- a/pkg/compiler/lib/src/parser/node_listener.dart
+++ b/pkg/compiler/lib/src/parser/node_listener.dart
@@ -736,6 +736,11 @@
   }
 
   @override
+  void handleSymbolVoid(Token token) {
+    logEvent('SymbolVoid');
+  }
+
+  @override
   void handleOperatorName(Token operatorKeyword, Token token) {
     Operator op = new Operator(token);
     pushNode(new Send(new Identifier(operatorKeyword), op, null));
diff --git a/pkg/compiler/lib/src/ssa/builder.dart b/pkg/compiler/lib/src/ssa/builder.dart
index e6ae55e..ac5c660 100644
--- a/pkg/compiler/lib/src/ssa/builder.dart
+++ b/pkg/compiler/lib/src/ssa/builder.dart
@@ -473,7 +473,7 @@
 
     bool doesNotContainCode() {
       // A function with size 1 does not contain any code.
-      return InlineWeeder.canBeInlined(functionResolvedAst, 1, true,
+      return InlineWeeder.canBeInlined(functionResolvedAst, 1,
           enableUserAssertions: compiler.options.enableUserAssertions);
     }
 
@@ -481,7 +481,7 @@
       // The call is on a path which is executed rarely, so inline only if it
       // does not make the program larger.
       if (isCalledOnce(function)) {
-        return InlineWeeder.canBeInlined(functionResolvedAst, -1, false,
+        return InlineWeeder.canBeInlined(functionResolvedAst, null,
             enableUserAssertions: compiler.options.enableUserAssertions);
       }
       // TODO(sra): Measure if inlining would 'reduce' the size.  One desirable
@@ -519,7 +519,7 @@
       if (cachedCanBeInlined == true) {
         // We may have forced the inlining of some methods. Therefore check
         // if we can inline this method regardless of size.
-        assert(InlineWeeder.canBeInlined(functionResolvedAst, -1, false,
+        assert(InlineWeeder.canBeInlined(functionResolvedAst, null,
             allowLoops: true,
             enableUserAssertions: compiler.options.enableUserAssertions));
         return true;
@@ -527,7 +527,6 @@
 
       int numParameters = function.functionSignature.parameterCount;
       int maxInliningNodes;
-      bool useMaxInliningNodes = true;
       if (insideLoop) {
         maxInliningNodes = InlineWeeder.INLINING_NODES_INSIDE_LOOP +
             InlineWeeder.INLINING_NODES_INSIDE_LOOP_ARG_FACTOR * numParameters;
@@ -540,11 +539,10 @@
       // inlining stack are called only once as well, we know we will
       // save on output size by inlining this method.
       if (isCalledOnce(function)) {
-        useMaxInliningNodes = false;
+        maxInliningNodes = null;
       }
-      bool canInline;
-      canInline = InlineWeeder.canBeInlined(
-          functionResolvedAst, maxInliningNodes, useMaxInliningNodes,
+      bool canInline = InlineWeeder.canBeInlined(
+          functionResolvedAst, maxInliningNodes,
           enableUserAssertions: compiler.options.enableUserAssertions);
       if (canInline) {
         backend.inlineCache.markAsInlinable(function, insideLoop: insideLoop);
@@ -6587,23 +6585,23 @@
   bool seenReturn = false;
   bool tooDifficult = false;
   int nodeCount = 0;
-  final int maxInliningNodes;
-  final bool useMaxInliningNodes;
+  final int maxInliningNodes; // `null` for unbounded.
   final bool allowLoops;
   final bool enableUserAssertions;
+  final TreeElements elements;
 
-  InlineWeeder(this.maxInliningNodes, this.useMaxInliningNodes, this.allowLoops,
+  InlineWeeder._(this.elements, this.maxInliningNodes, this.allowLoops,
       this.enableUserAssertions);
 
-  static bool canBeInlined(
-      ResolvedAst resolvedAst, int maxInliningNodes, bool useMaxInliningNodes,
+  static bool canBeInlined(ResolvedAst resolvedAst, int maxInliningNodes,
       {bool allowLoops: false, bool enableUserAssertions: null}) {
     assert(enableUserAssertions is bool); // Ensure we passed it.
     if (resolvedAst.elements.containsTryStatement) return false;
 
-    InlineWeeder weeder = new InlineWeeder(maxInliningNodes,
-        useMaxInliningNodes, allowLoops, enableUserAssertions);
+    InlineWeeder weeder = new InlineWeeder._(resolvedAst.elements,
+        maxInliningNodes, allowLoops, enableUserAssertions);
     ast.FunctionExpression functionExpression = resolvedAst.node;
+
     weeder.visit(functionExpression.initializers);
     weeder.visit(functionExpression.body);
     weeder.visit(functionExpression.asyncModifier);
@@ -6611,7 +6609,7 @@
   }
 
   bool registerNode() {
-    if (!useMaxInliningNodes) return true;
+    if (maxInliningNodes == null) return true;
     if (nodeCount++ > maxInliningNodes) {
       tooDifficult = true;
       return false;
@@ -6658,6 +6656,15 @@
   }
 
   void visitSend(ast.Send node) {
+    // TODO(sra): Investigate following, and possibly count occurrences, since
+    // repeated references might cause a temporary to be assigned.
+    //
+    //     Element element = elements[node];
+    //     if (element != null && element.isParameter) {
+    //       // Don't count as additional node, since it's likely that passing
+    //       // the argument would cost us as much space as we inline.
+    //       return;
+    //     }
     if (!registerNode()) return;
     node.visitChildren(this);
   }
@@ -6674,6 +6681,34 @@
     tooDifficult = true;
   }
 
+  void visitConditional(ast.Conditional node) {
+    // Heuristic: In "parameter ? A : B" there is a high probability that
+    // parameter is a constant. Assuming the parameter is constant, we can
+    // compute a count that is bounded by the largest arm rather than the sum of
+    // both arms.
+    visit(node.condition);
+    if (tooDifficult) return;
+    int commonPrefixCount = nodeCount;
+
+    visit(node.thenExpression);
+    if (tooDifficult) return;
+    int thenCount = nodeCount - commonPrefixCount;
+
+    nodeCount = commonPrefixCount;
+    visit(node.elseExpression);
+    if (tooDifficult) return;
+    int elseCount = nodeCount - commonPrefixCount;
+
+    nodeCount = commonPrefixCount + thenCount + elseCount;
+    if (node.condition.asSend() != null &&
+        elements[node.condition]?.isParameter == true) {
+      nodeCount =
+          commonPrefixCount + (thenCount > elseCount ? thenCount : elseCount);
+    }
+    // This is last so that [tooDifficult] is always updated.
+    if (!registerNode()) return;
+  }
+
   void visitRethrow(ast.Rethrow node) {
     if (!registerNode()) return;
     tooDifficult = true;
diff --git a/pkg/dart_messages/lib/shared_messages.dart b/pkg/dart_messages/lib/shared_messages.dart
index ae91711..aeba72e 100644
--- a/pkg/dart_messages/lib/shared_messages.dart
+++ b/pkg/dart_messages/lib/shared_messages.dart
@@ -2,62 +2,14 @@
 // 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.
 
-// An update to this file must be followed by regenerating the corresponding
-// json, dart2js and analyzer file. Use `publish.dart` in the bin directory.
-//
-// Every message in this file must have an id. Use `message_id.dart` in the
-// bin directory to generate a fresh one.
-
-// The messages in this file should meet the following guide lines:
-//
-// 1. The message should be a complete sentence starting with an uppercase
-// letter, and ending with a period.
-//
-// 2. Reserved words and embedded identifiers should be in single quotes, so
-// prefer double quotes for the complete message. For example, "The
-// class '#{className}' can't use 'super'." Notice that the word 'class' in the
-// preceding message is not quoted as it refers to the concept 'class', not the
-// reserved word. On the other hand, 'super' refers to the reserved word. Do
-// not quote 'null' and numeric literals.
-//
-// 3. Do not try to compose messages, as it can make translating them hard.
-//
-// 4. Try to keep the error messages short, but informative.
-//
-// 5. Use simple words and terminology, assume the reader of the message
-// doesn't have an advanced degree in math, and that English is not the
-// reader's native language. Do not assume any formal computer science
-// training. For example, do not use Latin abbreviations (prefer "that is" over
-// "i.e.", and "for example" over "e.g."). Also avoid phrases such as "if and
-// only if" and "iff", that level of precision is unnecessary.
-//
-// 6. Prefer contractions when they are in common use, for example, prefer
-// "can't" over "cannot". Using "cannot", "must not", "shall not", etc. is
-// off-putting to people new to programming.
-//
-// 7. Use common terminology, preferably from the Dart Language
-// Specification. This increases the user's chance of finding a good
-// explanation on the web.
-//
-// 8. Do not try to be cute or funny. It is extremely frustrating to work on a
-// product that crashes with a "tongue-in-cheek" message, especially if you did
-// not want to use this product to begin with.
-//
-// 9. Do not lie, that is, do not write error messages containing phrases like
-// "can't happen".  If the user ever saw this message, it would be a
-// lie. Prefer messages like: "Internal error: This function should not be
-// called when 'x' is null.".
-//
-// 10. Prefer to not use imperative tone. That is, the message should not sound
-// accusing or like it is ordering the user around. The computer should
-// describe the problem, not criticize for violating the specification.
-//
-// Other things to keep in mind:
-//
-// Generally, we want to provide messages that consists of three sentences:
-// 1. what is wrong, 2. why is it wrong, 3. how do I fix it. However, we
-// combine the first two in [template] and the last in [howToFix].
-
+/// An update to this file must be followed by regenerating the corresponding
+/// json, dart2js and analyzer file. Use `publish.dart` in the bin directory.
+///
+/// Every message in this file must have an id. Use `message_id.dart` in the
+/// bin directory to generate a fresh one.
+///
+/// The messages in this file should follow the [Guide for Writing
+/// Diagnostics](../../front_end/lib/src/fasta/diagnostics.md).
 import 'dart:convert';
 
 /// Encodes the category of the message.
diff --git a/pkg/dev_compiler/lib/js/amd/dart_sdk.js b/pkg/dev_compiler/lib/js/amd/dart_sdk.js
index 89fc660..4c79816 100644
--- a/pkg/dev_compiler/lib/js/amd/dart_sdk.js
+++ b/pkg/dev_compiler/lib/js/amd/dart_sdk.js
@@ -32,6 +32,7 @@
   const web_audio = Object.create(null);
   const web_gl = Object.create(null);
   const web_sql = Object.create(null);
+  const nativewrappers = Object.create(null);
   let ListOfObject = () => (ListOfObject = dart.constFn(core.List$(core.Object)))();
   let JSArrayOfListOfObject = () => (JSArrayOfListOfObject = dart.constFn(_interceptors.JSArray$(ListOfObject())))();
   let JSArrayOfObject = () => (JSArrayOfObject = dart.constFn(_interceptors.JSArray$(core.Object)))();
@@ -111,6 +112,7 @@
   let ListOf_IsolateEvent = () => (ListOf_IsolateEvent = dart.constFn(core.List$(_isolate_helper._IsolateEvent)))();
   let QueueOf_IsolateEvent = () => (QueueOf_IsolateEvent = dart.constFn(collection.Queue$(_isolate_helper._IsolateEvent)))();
   let CompleterOfList = () => (CompleterOfList = dart.constFn(async.Completer$(core.List)))();
+  let FutureOrOfList = () => (FutureOrOfList = dart.constFn(async.FutureOr$(core.List)))();
   let dynamicTovoid = () => (dynamicTovoid = dart.constFn(dart.functionType(dart.void, [dart.dynamic])))();
   let StringTovoid = () => (StringTovoid = dart.constFn(dart.functionType(dart.void, [core.String])))();
   let ExpandoOfint = () => (ExpandoOfint = dart.constFn(core.Expando$(core.int)))();
@@ -707,6 +709,7 @@
   let dynamicAndStringAnddynamicTovoid = () => (dynamicAndStringAnddynamicTovoid = dart.constFn(dart.definiteFunctionType(dart.void, [dart.dynamic, core.String, dart.dynamic])))();
   let FAndintToF = () => (FAndintToF = dart.constFn(dart.definiteFunctionType(F => [F, [F, core.int]])))();
   let JSSyntaxRegExpTodynamic = () => (JSSyntaxRegExpTodynamic = dart.constFn(dart.definiteFunctionType(dart.dynamic, [_js_helper.JSSyntaxRegExp])))();
+  let ListToListOfString = () => (ListToListOfString = dart.constFn(dart.definiteFunctionType(ListOfString(), [core.List])))();
   let JSSyntaxRegExpToint = () => (JSSyntaxRegExpToint = dart.constFn(dart.definiteFunctionType(core.int, [_js_helper.JSSyntaxRegExp])))();
   let JSSyntaxRegExpAndStringAndintToMatch = () => (JSSyntaxRegExpAndStringAndintToMatch = dart.constFn(dart.definiteFunctionType(core.Match, [_js_helper.JSSyntaxRegExp, core.String, core.int])))();
   let dynamicAnddynamicAnddynamicToint = () => (dynamicAnddynamicAnddynamicToint = dart.constFn(dart.definiteFunctionType(core.int, [dart.dynamic, dart.dynamic, dart.dynamic])))();
@@ -1884,6 +1887,9 @@
   dart.trapRuntimeErrors = function(flag) {
     dart._trapRuntimeErrors = flag;
   };
+  dart.ignoreWhitelistedErrors = function(flag) {
+    dart._ignoreWhitelistedErrors = flag;
+  };
   dart.throwCastError = function(object, actual, type) {
     var found = dart.typeName(actual);
     var expected = dart.typeName(type);
@@ -2247,7 +2253,7 @@
     let result = dart.isSubtype(actual, type);
     if (result || actual == dart.jsobject || actual == core.int && type == core.double) return true;
     if (result === false) return false;
-    if (ignoreFromWhiteList == void 0) return result;
+    if (!dart._ignoreWhitelistedErrors || ignoreFromWhiteList == void 0) return result;
     if (dart._ignoreTypeFailure(actual, type)) return true;
     return result;
   };
@@ -2991,6 +2997,7 @@
   dart._typeFormalCount = Symbol("_typeFormalCount");
   dart.isSubtype = dart._subtypeMemo((t1, t2) => t1 === t2 || dart._isSubtype(t1, t2, true));
   dart._trapRuntimeErrors = true;
+  dart._ignoreWhitelistedErrors = true;
   dart._jsIterator = Symbol("_jsIterator");
   dart._current = Symbol("_current");
   dart._AsyncStarStreamController = class _AsyncStarStreamController {
@@ -4069,6 +4076,13 @@
       children: dart.definiteFunctionType(core.List$(_debugger.NameValuePair), [dart.dynamic])
     })
   });
+  _debugger.StackTraceMapper = dart.typedef('StackTraceMapper', () => dart.functionType(core.String, [core.String]));
+  dart.copyProperties(_debugger, {
+    get stackTraceMapper() {
+      let _util = dart.global.$dartStackTraceUtility;
+      return _debugger.StackTraceMapper._check(_util != null ? _util.mapper : null);
+    }
+  });
   _debugger.registerDevtoolsFormatter = function() {
     let formatters = JSArrayOfJsonMLFormatter().of([_debugger._devtoolsFormatter]);
     dart.global.devtoolsFormatters = formatters;
@@ -9839,7 +9853,7 @@
       let completer = CompleterOfList().new();
       port.first.then(dart.dynamic)(dart.fn(msg => {
         if (dart.equals(dart.dindex(msg, 0), _isolate_helper._SPAWNED_SIGNAL)) {
-          completer.complete(msg);
+          completer.complete(FutureOrOfList()._check(msg));
         } else {
           dart.assert(dart.equals(dart.dindex(msg, 0), _isolate_helper._SPAWN_FAILED_SIGNAL));
           completer.completeError(dart.dindex(msg, 1));
@@ -11938,6 +11952,9 @@
       let trace = null;
       if (this[_exception] !== null && typeof this[_exception] === "object") {
         trace = this[_exception].stack;
+        if (trace != null && _debugger.stackTraceMapper != null) {
+          trace = _debugger.stackTraceMapper(trace);
+        }
       }
       return this[_trace] = trace == null ? '' : trace;
     }
@@ -12831,6 +12848,10 @@
     return regexp[_nativeRegExp];
   };
   dart.lazyFn(_js_helper.regExpGetNative, () => JSSyntaxRegExpTodynamic());
+  _js_helper._stringList = function(l) {
+    return ListOfString()._check(l == null ? l : dart.list(l, core.String));
+  };
+  dart.lazyFn(_js_helper._stringList, () => ListToListOfString());
   const _nativeGlobalVersion = Symbol('_nativeGlobalVersion');
   _js_helper.regExpGetGlobalNative = function(regexp) {
     let nativeRegexp = regexp[_nativeGlobalVersion];
@@ -12897,7 +12918,7 @@
     firstMatch(string) {
       let m = this[_nativeRegExp].exec(_js_helper.checkString(string));
       if (m == null) return null;
-      return new _js_helper._MatchImplementation(this, m);
+      return new _js_helper._MatchImplementation(this, _js_helper._stringList(m));
     }
     hasMatch(string) {
       return this[_nativeRegExp].test(_js_helper.checkString(string));
@@ -12921,7 +12942,7 @@
       regexp.lastIndex = start;
       let match = regexp.exec(string);
       if (match == null) return null;
-      return new _js_helper._MatchImplementation(this, ListOfString()._check(match));
+      return new _js_helper._MatchImplementation(this, _js_helper._stringList(match));
     }
     [_execAnchored](string, start) {
       let regexp = this[_nativeAnchoredVersion];
@@ -12930,7 +12951,7 @@
       if (match == null) return null;
       if (match[dartx._get](dart.notNull(match[dartx.length]) - 1) != null) return null;
       match[dartx.length] = dart.notNull(match[dartx.length]) - 1;
-      return new _js_helper._MatchImplementation(this, ListOfString()._check(match));
+      return new _js_helper._MatchImplementation(this, _js_helper._stringList(match));
     }
     matchAsPrefix(string, start) {
       if (start === void 0) start = 0;
@@ -18310,12 +18331,14 @@
   async._Completer = _Completer();
   const _asyncCompleteError = Symbol('_asyncCompleteError');
   async._AsyncCompleter$ = dart.generic(T => {
+    let FutureOrOfT = () => (FutureOrOfT = dart.constFn(async.FutureOr$(T)))();
     class _AsyncCompleter extends async._Completer$(T) {
       new() {
         super.new();
       }
       complete(value) {
         if (value === void 0) value = null;
+        FutureOrOfT()._check(value);
         if (!dart.test(this.future[_mayComplete])) dart.throw(new core.StateError("Future already completed"));
         this.future[_asyncComplete](value);
       }
@@ -18325,7 +18348,7 @@
     }
     dart.setSignature(_AsyncCompleter, {
       methods: () => ({
-        complete: dart.definiteFunctionType(dart.void, [], [dart.dynamic]),
+        complete: dart.definiteFunctionType(dart.void, [], [FutureOrOfT()]),
         [_completeError]: dart.definiteFunctionType(dart.void, [core.Object, core.StackTrace])
       })
     });
@@ -18333,12 +18356,14 @@
   });
   async._AsyncCompleter = _AsyncCompleter();
   async._SyncCompleter$ = dart.generic(T => {
+    let FutureOrOfT = () => (FutureOrOfT = dart.constFn(async.FutureOr$(T)))();
     class _SyncCompleter extends async._Completer$(T) {
       new() {
         super.new();
       }
       complete(value) {
         if (value === void 0) value = null;
+        FutureOrOfT()._check(value);
         if (!dart.test(this.future[_mayComplete])) dart.throw(new core.StateError("Future already completed"));
         this.future[_complete](value);
       }
@@ -18348,7 +18373,7 @@
     }
     dart.setSignature(_SyncCompleter, {
       methods: () => ({
-        complete: dart.definiteFunctionType(dart.void, [], [dart.dynamic]),
+        complete: dart.definiteFunctionType(dart.void, [], [FutureOrOfT()]),
         [_completeError]: dart.definiteFunctionType(dart.void, [core.Object, core.StackTrace])
       })
     });
@@ -32094,7 +32119,7 @@
       return new core.Duration._microseconds(this[_duration][dartx.abs]());
     }
     _negate() {
-      return new core.Duration._microseconds(-dart.notNull(this[_duration]));
+      return new core.Duration._microseconds(0 - dart.notNull(this[_duration]));
     }
   };
   dart.defineNamedConstructor(core.Duration, '_microseconds');
@@ -72294,6 +72319,7 @@
       timestamp: dart.definiteFunctionType(core.int, [])
     })
   });
+  dart.defineExtensionMembers(html$._GeopositionWrapper, ['coords', 'timestamp']);
   dart.defineExtensionNames([
     'coords',
     'timestamp'
@@ -89774,6 +89800,21 @@
       stopPropagation: dart.definiteFunctionType(dart.void, [])
     })
   });
+  dart.defineExtensionMembers(html$._WrappedEvent, [
+    'preventDefault',
+    'stopImmediatePropagation',
+    'stopPropagation',
+    'bubbles',
+    'cancelable',
+    'currentTarget',
+    'defaultPrevented',
+    'eventPhase',
+    'target',
+    'timeStamp',
+    'type',
+    'matchingTarget',
+    'path'
+  ]);
   html$._BeforeUnloadEvent = class _BeforeUnloadEvent extends html$._WrappedEvent {
     new(base) {
       this[_returnValue] = null;
@@ -89795,6 +89836,7 @@
     getters: () => ({returnValue: dart.definiteFunctionType(core.String, [])}),
     setters: () => ({returnValue: dart.definiteFunctionType(dart.void, [core.String])})
   });
+  dart.defineExtensionMembers(html$._BeforeUnloadEvent, ['returnValue', 'returnValue']);
   const _eventType = Symbol('_eventType');
   html$._BeforeUnloadEventStreamProvider = class _BeforeUnloadEventStreamProvider extends core.Object {
     new(eventType) {
@@ -93097,6 +93139,25 @@
     }),
     names: ['_makeRecord', '_convertToHexString']
   });
+  dart.defineExtensionMembers(html$.KeyEvent, [
+    'getModifierState',
+    'keyCode',
+    'charCode',
+    'altKey',
+    'which',
+    'currentTarget',
+    'code',
+    'ctrlKey',
+    'detail',
+    'key',
+    'keyLocation',
+    'metaKey',
+    'shiftKey',
+    'sourceDevice',
+    'view',
+    'location',
+    'repeat'
+  ]);
   dart.defineLazy(html$.KeyEvent, {
     get _keyboardEventDispatchRecord() {
       return html$.KeyEvent._makeRecord();
@@ -94802,12 +94863,16 @@
   dart.defineExtensionMembers(html$._DOMWindowCrossFrame, [
     'close',
     'postMessage',
+    'addEventListener',
+    'dispatchEvent',
+    'removeEventListener',
     'history',
     'location',
     'closed',
     'opener',
     'parent',
-    'top'
+    'top',
+    'on'
   ]);
   html$._LocationCrossFrame = class _LocationCrossFrame extends core.Object {
     set href(val) {
@@ -95324,12 +95389,33 @@
   };
   dart.fn(html_common.convertNativeToDart_ContextAttributes, dynamicTodynamic$());
   html_common._TypedImageData = class _TypedImageData extends core.Object {
+    get data() {
+      return this[data$];
+    }
+    set data(value) {
+      super.data = value;
+    }
+    get height() {
+      return this[height$];
+    }
+    set height(value) {
+      super.height = value;
+    }
+    get width() {
+      return this[width$];
+    }
+    set width(value) {
+      super.width = value;
+    }
     new(data, height, width) {
-      this.data = data;
-      this.height = height;
-      this.width = width;
+      this[data$] = data;
+      this[height$] = height;
+      this[width$] = width;
     }
   };
+  const data$ = Symbol("_TypedImageData.data");
+  const height$ = Symbol("_TypedImageData.height");
+  const width$ = Symbol("_TypedImageData.width");
   html_common._TypedImageData[dart.implements] = () => [html$.ImageData];
   dart.setSignature(html_common._TypedImageData, {
     fields: () => ({
@@ -95338,6 +95424,7 @@
       width: core.int
     })
   });
+  dart.defineExtensionMembers(html_common._TypedImageData, ['data', 'height', 'width']);
   html_common.convertNativeToDart_ImageData = function(nativeImageData) {
     0;
     if (html$.ImageData.is(nativeImageData)) {
@@ -98618,7 +98705,7 @@
       dart.throw(new core.UnsupportedError("Not supported"));
     }
     get height() {
-      return this[height$];
+      return this[height$0];
     }
     set height(value) {
       super.height = value;
@@ -98630,7 +98717,7 @@
       super.result = value;
     }
     get width() {
-      return this[width$];
+      return this[width$0];
     }
     set width(value) {
       super.width = value;
@@ -98648,9 +98735,9 @@
       super.y = value;
     }
   };
-  const height$ = Symbol("FilterPrimitiveStandardAttributes.height");
+  const height$0 = Symbol("FilterPrimitiveStandardAttributes.height");
   const result = Symbol("FilterPrimitiveStandardAttributes.result");
-  const width$ = Symbol("FilterPrimitiveStandardAttributes.width");
+  const width$0 = Symbol("FilterPrimitiveStandardAttributes.width");
   const x = Symbol("FilterPrimitiveStandardAttributes.x");
   const y = Symbol("FilterPrimitiveStandardAttributes.y");
   dart.setSignature(svg$.FilterPrimitiveStandardAttributes, {
@@ -105445,7 +105532,7 @@
     methods: () => ({[dartx.executeSql]: dart.definiteFunctionType(dart.void, [core.String, ListOfObject()], [web_sql.SqlStatementCallback, web_sql.SqlStatementErrorCallback])})
   });
   dart.registerExtension(dart.global.SQLTransaction, web_sql.SqlTransaction);
-  dart.trackLibraries("dart_sdk", {"dart:_runtime": dart, "dart:_debugger": _debugger, "dart:_foreign_helper": _foreign_helper, "dart:_interceptors": _interceptors, "dart:_internal": _internal, "dart:_isolate_helper": _isolate_helper, "dart:_js_embedded_names": _js_embedded_names, "dart:_js_helper": _js_helper, "dart:_js_mirrors": _js_mirrors, "dart:_js_primitives": _js_primitives, "dart:_metadata": _metadata, "dart:_native_typed_data": _native_typed_data, "dart:async": async, "dart:collection": collection, "dart:convert": convert, "dart:core": core, "dart:developer": developer, "dart:io": io, "dart:isolate": isolate$, "dart:js": js, "dart:js_util": js_util, "dart:math": math, "dart:mirrors": mirrors, "dart:typed_data": typed_data, "dart:indexed_db": indexed_db, "dart:html": html$, "dart:html_common": html_common, "dart:svg": svg$, "dart:web_audio": web_audio, "dart:web_gl": web_gl, "dart:web_sql": web_sql});
+  dart.trackLibraries("dart_sdk", {"dart:_runtime": dart, "dart:_debugger": _debugger, "dart:_foreign_helper": _foreign_helper, "dart:_interceptors": _interceptors, "dart:_internal": _internal, "dart:_isolate_helper": _isolate_helper, "dart:_js_embedded_names": _js_embedded_names, "dart:_js_helper": _js_helper, "dart:_js_mirrors": _js_mirrors, "dart:_js_primitives": _js_primitives, "dart:_metadata": _metadata, "dart:_native_typed_data": _native_typed_data, "dart:async": async, "dart:collection": collection, "dart:convert": convert, "dart:core": core, "dart:developer": developer, "dart:io": io, "dart:isolate": isolate$, "dart:js": js, "dart:js_util": js_util, "dart:math": math, "dart:mirrors": mirrors, "dart:typed_data": typed_data, "dart:indexed_db": indexed_db, "dart:html": html$, "dart:html_common": html_common, "dart:svg": svg$, "dart:web_audio": web_audio, "dart:web_gl": web_gl, "dart:web_sql": web_sql, "dart:nativewrappers": nativewrappers});
   // Exports:
   return {
     dart: dart,
@@ -105479,6 +105566,7 @@
     svg: svg$,
     web_audio: web_audio,
     web_gl: web_gl,
-    web_sql: web_sql
+    web_sql: web_sql,
+    nativewrappers: nativewrappers
   };
 });
diff --git a/pkg/dev_compiler/lib/js/common/dart_sdk.js b/pkg/dev_compiler/lib/js/common/dart_sdk.js
index 0237cf3..a6f9749 100644
--- a/pkg/dev_compiler/lib/js/common/dart_sdk.js
+++ b/pkg/dev_compiler/lib/js/common/dart_sdk.js
@@ -31,6 +31,7 @@
 const web_audio = Object.create(null);
 const web_gl = Object.create(null);
 const web_sql = Object.create(null);
+const nativewrappers = Object.create(null);
 let ListOfObject = () => (ListOfObject = dart.constFn(core.List$(core.Object)))();
 let JSArrayOfListOfObject = () => (JSArrayOfListOfObject = dart.constFn(_interceptors.JSArray$(ListOfObject())))();
 let JSArrayOfObject = () => (JSArrayOfObject = dart.constFn(_interceptors.JSArray$(core.Object)))();
@@ -110,6 +111,7 @@
 let ListOf_IsolateEvent = () => (ListOf_IsolateEvent = dart.constFn(core.List$(_isolate_helper._IsolateEvent)))();
 let QueueOf_IsolateEvent = () => (QueueOf_IsolateEvent = dart.constFn(collection.Queue$(_isolate_helper._IsolateEvent)))();
 let CompleterOfList = () => (CompleterOfList = dart.constFn(async.Completer$(core.List)))();
+let FutureOrOfList = () => (FutureOrOfList = dart.constFn(async.FutureOr$(core.List)))();
 let dynamicTovoid = () => (dynamicTovoid = dart.constFn(dart.functionType(dart.void, [dart.dynamic])))();
 let StringTovoid = () => (StringTovoid = dart.constFn(dart.functionType(dart.void, [core.String])))();
 let ExpandoOfint = () => (ExpandoOfint = dart.constFn(core.Expando$(core.int)))();
@@ -706,6 +708,7 @@
 let dynamicAndStringAnddynamicTovoid = () => (dynamicAndStringAnddynamicTovoid = dart.constFn(dart.definiteFunctionType(dart.void, [dart.dynamic, core.String, dart.dynamic])))();
 let FAndintToF = () => (FAndintToF = dart.constFn(dart.definiteFunctionType(F => [F, [F, core.int]])))();
 let JSSyntaxRegExpTodynamic = () => (JSSyntaxRegExpTodynamic = dart.constFn(dart.definiteFunctionType(dart.dynamic, [_js_helper.JSSyntaxRegExp])))();
+let ListToListOfString = () => (ListToListOfString = dart.constFn(dart.definiteFunctionType(ListOfString(), [core.List])))();
 let JSSyntaxRegExpToint = () => (JSSyntaxRegExpToint = dart.constFn(dart.definiteFunctionType(core.int, [_js_helper.JSSyntaxRegExp])))();
 let JSSyntaxRegExpAndStringAndintToMatch = () => (JSSyntaxRegExpAndStringAndintToMatch = dart.constFn(dart.definiteFunctionType(core.Match, [_js_helper.JSSyntaxRegExp, core.String, core.int])))();
 let dynamicAnddynamicAnddynamicToint = () => (dynamicAnddynamicAnddynamicToint = dart.constFn(dart.definiteFunctionType(core.int, [dart.dynamic, dart.dynamic, dart.dynamic])))();
@@ -1883,6 +1886,9 @@
 dart.trapRuntimeErrors = function(flag) {
   dart._trapRuntimeErrors = flag;
 };
+dart.ignoreWhitelistedErrors = function(flag) {
+  dart._ignoreWhitelistedErrors = flag;
+};
 dart.throwCastError = function(object, actual, type) {
   var found = dart.typeName(actual);
   var expected = dart.typeName(type);
@@ -2246,7 +2252,7 @@
   let result = dart.isSubtype(actual, type);
   if (result || actual == dart.jsobject || actual == core.int && type == core.double) return true;
   if (result === false) return false;
-  if (ignoreFromWhiteList == void 0) return result;
+  if (!dart._ignoreWhitelistedErrors || ignoreFromWhiteList == void 0) return result;
   if (dart._ignoreTypeFailure(actual, type)) return true;
   return result;
 };
@@ -2990,6 +2996,7 @@
 dart._typeFormalCount = Symbol("_typeFormalCount");
 dart.isSubtype = dart._subtypeMemo((t1, t2) => t1 === t2 || dart._isSubtype(t1, t2, true));
 dart._trapRuntimeErrors = true;
+dart._ignoreWhitelistedErrors = true;
 dart._jsIterator = Symbol("_jsIterator");
 dart._current = Symbol("_current");
 dart._AsyncStarStreamController = class _AsyncStarStreamController {
@@ -4068,6 +4075,13 @@
     children: dart.definiteFunctionType(core.List$(_debugger.NameValuePair), [dart.dynamic])
   })
 });
+_debugger.StackTraceMapper = dart.typedef('StackTraceMapper', () => dart.functionType(core.String, [core.String]));
+dart.copyProperties(_debugger, {
+  get stackTraceMapper() {
+    let _util = dart.global.$dartStackTraceUtility;
+    return _debugger.StackTraceMapper._check(_util != null ? _util.mapper : null);
+  }
+});
 _debugger.registerDevtoolsFormatter = function() {
   let formatters = JSArrayOfJsonMLFormatter().of([_debugger._devtoolsFormatter]);
   dart.global.devtoolsFormatters = formatters;
@@ -9838,7 +9852,7 @@
     let completer = CompleterOfList().new();
     port.first.then(dart.dynamic)(dart.fn(msg => {
       if (dart.equals(dart.dindex(msg, 0), _isolate_helper._SPAWNED_SIGNAL)) {
-        completer.complete(msg);
+        completer.complete(FutureOrOfList()._check(msg));
       } else {
         dart.assert(dart.equals(dart.dindex(msg, 0), _isolate_helper._SPAWN_FAILED_SIGNAL));
         completer.completeError(dart.dindex(msg, 1));
@@ -11937,6 +11951,9 @@
     let trace = null;
     if (this[_exception] !== null && typeof this[_exception] === "object") {
       trace = this[_exception].stack;
+      if (trace != null && _debugger.stackTraceMapper != null) {
+        trace = _debugger.stackTraceMapper(trace);
+      }
     }
     return this[_trace] = trace == null ? '' : trace;
   }
@@ -12830,6 +12847,10 @@
   return regexp[_nativeRegExp];
 };
 dart.lazyFn(_js_helper.regExpGetNative, () => JSSyntaxRegExpTodynamic());
+_js_helper._stringList = function(l) {
+  return ListOfString()._check(l == null ? l : dart.list(l, core.String));
+};
+dart.lazyFn(_js_helper._stringList, () => ListToListOfString());
 const _nativeGlobalVersion = Symbol('_nativeGlobalVersion');
 _js_helper.regExpGetGlobalNative = function(regexp) {
   let nativeRegexp = regexp[_nativeGlobalVersion];
@@ -12896,7 +12917,7 @@
   firstMatch(string) {
     let m = this[_nativeRegExp].exec(_js_helper.checkString(string));
     if (m == null) return null;
-    return new _js_helper._MatchImplementation(this, m);
+    return new _js_helper._MatchImplementation(this, _js_helper._stringList(m));
   }
   hasMatch(string) {
     return this[_nativeRegExp].test(_js_helper.checkString(string));
@@ -12920,7 +12941,7 @@
     regexp.lastIndex = start;
     let match = regexp.exec(string);
     if (match == null) return null;
-    return new _js_helper._MatchImplementation(this, ListOfString()._check(match));
+    return new _js_helper._MatchImplementation(this, _js_helper._stringList(match));
   }
   [_execAnchored](string, start) {
     let regexp = this[_nativeAnchoredVersion];
@@ -12929,7 +12950,7 @@
     if (match == null) return null;
     if (match[dartx._get](dart.notNull(match[dartx.length]) - 1) != null) return null;
     match[dartx.length] = dart.notNull(match[dartx.length]) - 1;
-    return new _js_helper._MatchImplementation(this, ListOfString()._check(match));
+    return new _js_helper._MatchImplementation(this, _js_helper._stringList(match));
   }
   matchAsPrefix(string, start) {
     if (start === void 0) start = 0;
@@ -18309,12 +18330,14 @@
 async._Completer = _Completer();
 const _asyncCompleteError = Symbol('_asyncCompleteError');
 async._AsyncCompleter$ = dart.generic(T => {
+  let FutureOrOfT = () => (FutureOrOfT = dart.constFn(async.FutureOr$(T)))();
   class _AsyncCompleter extends async._Completer$(T) {
     new() {
       super.new();
     }
     complete(value) {
       if (value === void 0) value = null;
+      FutureOrOfT()._check(value);
       if (!dart.test(this.future[_mayComplete])) dart.throw(new core.StateError("Future already completed"));
       this.future[_asyncComplete](value);
     }
@@ -18324,7 +18347,7 @@
   }
   dart.setSignature(_AsyncCompleter, {
     methods: () => ({
-      complete: dart.definiteFunctionType(dart.void, [], [dart.dynamic]),
+      complete: dart.definiteFunctionType(dart.void, [], [FutureOrOfT()]),
       [_completeError]: dart.definiteFunctionType(dart.void, [core.Object, core.StackTrace])
     })
   });
@@ -18332,12 +18355,14 @@
 });
 async._AsyncCompleter = _AsyncCompleter();
 async._SyncCompleter$ = dart.generic(T => {
+  let FutureOrOfT = () => (FutureOrOfT = dart.constFn(async.FutureOr$(T)))();
   class _SyncCompleter extends async._Completer$(T) {
     new() {
       super.new();
     }
     complete(value) {
       if (value === void 0) value = null;
+      FutureOrOfT()._check(value);
       if (!dart.test(this.future[_mayComplete])) dart.throw(new core.StateError("Future already completed"));
       this.future[_complete](value);
     }
@@ -18347,7 +18372,7 @@
   }
   dart.setSignature(_SyncCompleter, {
     methods: () => ({
-      complete: dart.definiteFunctionType(dart.void, [], [dart.dynamic]),
+      complete: dart.definiteFunctionType(dart.void, [], [FutureOrOfT()]),
       [_completeError]: dart.definiteFunctionType(dart.void, [core.Object, core.StackTrace])
     })
   });
@@ -32093,7 +32118,7 @@
     return new core.Duration._microseconds(this[_duration][dartx.abs]());
   }
   _negate() {
-    return new core.Duration._microseconds(-dart.notNull(this[_duration]));
+    return new core.Duration._microseconds(0 - dart.notNull(this[_duration]));
   }
 };
 dart.defineNamedConstructor(core.Duration, '_microseconds');
@@ -72293,6 +72318,7 @@
     timestamp: dart.definiteFunctionType(core.int, [])
   })
 });
+dart.defineExtensionMembers(html$._GeopositionWrapper, ['coords', 'timestamp']);
 dart.defineExtensionNames([
   'coords',
   'timestamp'
@@ -89773,6 +89799,21 @@
     stopPropagation: dart.definiteFunctionType(dart.void, [])
   })
 });
+dart.defineExtensionMembers(html$._WrappedEvent, [
+  'preventDefault',
+  'stopImmediatePropagation',
+  'stopPropagation',
+  'bubbles',
+  'cancelable',
+  'currentTarget',
+  'defaultPrevented',
+  'eventPhase',
+  'target',
+  'timeStamp',
+  'type',
+  'matchingTarget',
+  'path'
+]);
 html$._BeforeUnloadEvent = class _BeforeUnloadEvent extends html$._WrappedEvent {
   new(base) {
     this[_returnValue] = null;
@@ -89794,6 +89835,7 @@
   getters: () => ({returnValue: dart.definiteFunctionType(core.String, [])}),
   setters: () => ({returnValue: dart.definiteFunctionType(dart.void, [core.String])})
 });
+dart.defineExtensionMembers(html$._BeforeUnloadEvent, ['returnValue', 'returnValue']);
 const _eventType = Symbol('_eventType');
 html$._BeforeUnloadEventStreamProvider = class _BeforeUnloadEventStreamProvider extends core.Object {
   new(eventType) {
@@ -93096,6 +93138,25 @@
   }),
   names: ['_makeRecord', '_convertToHexString']
 });
+dart.defineExtensionMembers(html$.KeyEvent, [
+  'getModifierState',
+  'keyCode',
+  'charCode',
+  'altKey',
+  'which',
+  'currentTarget',
+  'code',
+  'ctrlKey',
+  'detail',
+  'key',
+  'keyLocation',
+  'metaKey',
+  'shiftKey',
+  'sourceDevice',
+  'view',
+  'location',
+  'repeat'
+]);
 dart.defineLazy(html$.KeyEvent, {
   get _keyboardEventDispatchRecord() {
     return html$.KeyEvent._makeRecord();
@@ -94801,12 +94862,16 @@
 dart.defineExtensionMembers(html$._DOMWindowCrossFrame, [
   'close',
   'postMessage',
+  'addEventListener',
+  'dispatchEvent',
+  'removeEventListener',
   'history',
   'location',
   'closed',
   'opener',
   'parent',
-  'top'
+  'top',
+  'on'
 ]);
 html$._LocationCrossFrame = class _LocationCrossFrame extends core.Object {
   set href(val) {
@@ -95323,12 +95388,33 @@
 };
 dart.fn(html_common.convertNativeToDart_ContextAttributes, dynamicTodynamic$());
 html_common._TypedImageData = class _TypedImageData extends core.Object {
+  get data() {
+    return this[data$];
+  }
+  set data(value) {
+    super.data = value;
+  }
+  get height() {
+    return this[height$];
+  }
+  set height(value) {
+    super.height = value;
+  }
+  get width() {
+    return this[width$];
+  }
+  set width(value) {
+    super.width = value;
+  }
   new(data, height, width) {
-    this.data = data;
-    this.height = height;
-    this.width = width;
+    this[data$] = data;
+    this[height$] = height;
+    this[width$] = width;
   }
 };
+const data$ = Symbol("_TypedImageData.data");
+const height$ = Symbol("_TypedImageData.height");
+const width$ = Symbol("_TypedImageData.width");
 html_common._TypedImageData[dart.implements] = () => [html$.ImageData];
 dart.setSignature(html_common._TypedImageData, {
   fields: () => ({
@@ -95337,6 +95423,7 @@
     width: core.int
   })
 });
+dart.defineExtensionMembers(html_common._TypedImageData, ['data', 'height', 'width']);
 html_common.convertNativeToDart_ImageData = function(nativeImageData) {
   0;
   if (html$.ImageData.is(nativeImageData)) {
@@ -98617,7 +98704,7 @@
     dart.throw(new core.UnsupportedError("Not supported"));
   }
   get height() {
-    return this[height$];
+    return this[height$0];
   }
   set height(value) {
     super.height = value;
@@ -98629,7 +98716,7 @@
     super.result = value;
   }
   get width() {
-    return this[width$];
+    return this[width$0];
   }
   set width(value) {
     super.width = value;
@@ -98647,9 +98734,9 @@
     super.y = value;
   }
 };
-const height$ = Symbol("FilterPrimitiveStandardAttributes.height");
+const height$0 = Symbol("FilterPrimitiveStandardAttributes.height");
 const result = Symbol("FilterPrimitiveStandardAttributes.result");
-const width$ = Symbol("FilterPrimitiveStandardAttributes.width");
+const width$0 = Symbol("FilterPrimitiveStandardAttributes.width");
 const x = Symbol("FilterPrimitiveStandardAttributes.x");
 const y = Symbol("FilterPrimitiveStandardAttributes.y");
 dart.setSignature(svg$.FilterPrimitiveStandardAttributes, {
@@ -105444,7 +105531,7 @@
   methods: () => ({[dartx.executeSql]: dart.definiteFunctionType(dart.void, [core.String, ListOfObject()], [web_sql.SqlStatementCallback, web_sql.SqlStatementErrorCallback])})
 });
 dart.registerExtension(dart.global.SQLTransaction, web_sql.SqlTransaction);
-dart.trackLibraries("dart_sdk", {"dart:_runtime": dart, "dart:_debugger": _debugger, "dart:_foreign_helper": _foreign_helper, "dart:_interceptors": _interceptors, "dart:_internal": _internal, "dart:_isolate_helper": _isolate_helper, "dart:_js_embedded_names": _js_embedded_names, "dart:_js_helper": _js_helper, "dart:_js_mirrors": _js_mirrors, "dart:_js_primitives": _js_primitives, "dart:_metadata": _metadata, "dart:_native_typed_data": _native_typed_data, "dart:async": async, "dart:collection": collection, "dart:convert": convert, "dart:core": core, "dart:developer": developer, "dart:io": io, "dart:isolate": isolate$, "dart:js": js, "dart:js_util": js_util, "dart:math": math, "dart:mirrors": mirrors, "dart:typed_data": typed_data, "dart:indexed_db": indexed_db, "dart:html": html$, "dart:html_common": html_common, "dart:svg": svg$, "dart:web_audio": web_audio, "dart:web_gl": web_gl, "dart:web_sql": web_sql});
+dart.trackLibraries("dart_sdk", {"dart:_runtime": dart, "dart:_debugger": _debugger, "dart:_foreign_helper": _foreign_helper, "dart:_interceptors": _interceptors, "dart:_internal": _internal, "dart:_isolate_helper": _isolate_helper, "dart:_js_embedded_names": _js_embedded_names, "dart:_js_helper": _js_helper, "dart:_js_mirrors": _js_mirrors, "dart:_js_primitives": _js_primitives, "dart:_metadata": _metadata, "dart:_native_typed_data": _native_typed_data, "dart:async": async, "dart:collection": collection, "dart:convert": convert, "dart:core": core, "dart:developer": developer, "dart:io": io, "dart:isolate": isolate$, "dart:js": js, "dart:js_util": js_util, "dart:math": math, "dart:mirrors": mirrors, "dart:typed_data": typed_data, "dart:indexed_db": indexed_db, "dart:html": html$, "dart:html_common": html_common, "dart:svg": svg$, "dart:web_audio": web_audio, "dart:web_gl": web_gl, "dart:web_sql": web_sql, "dart:nativewrappers": nativewrappers});
 // Exports:
 exports.dart = dart;
 exports.dartx = dartx;
@@ -105478,3 +105565,4 @@
 exports.web_audio = web_audio;
 exports.web_gl = web_gl;
 exports.web_sql = web_sql;
+exports.nativewrappers = nativewrappers;
diff --git a/pkg/dev_compiler/lib/js/es6/dart_sdk.js b/pkg/dev_compiler/lib/js/es6/dart_sdk.js
index 3b8dcbc..93fa7b2 100644
--- a/pkg/dev_compiler/lib/js/es6/dart_sdk.js
+++ b/pkg/dev_compiler/lib/js/es6/dart_sdk.js
@@ -30,6 +30,7 @@
 export const web_audio = Object.create(null);
 export const web_gl = Object.create(null);
 export const web_sql = Object.create(null);
+export const nativewrappers = Object.create(null);
 let ListOfObject = () => (ListOfObject = dart.constFn(core.List$(core.Object)))();
 let JSArrayOfListOfObject = () => (JSArrayOfListOfObject = dart.constFn(_interceptors.JSArray$(ListOfObject())))();
 let JSArrayOfObject = () => (JSArrayOfObject = dart.constFn(_interceptors.JSArray$(core.Object)))();
@@ -109,6 +110,7 @@
 let ListOf_IsolateEvent = () => (ListOf_IsolateEvent = dart.constFn(core.List$(_isolate_helper._IsolateEvent)))();
 let QueueOf_IsolateEvent = () => (QueueOf_IsolateEvent = dart.constFn(collection.Queue$(_isolate_helper._IsolateEvent)))();
 let CompleterOfList = () => (CompleterOfList = dart.constFn(async.Completer$(core.List)))();
+let FutureOrOfList = () => (FutureOrOfList = dart.constFn(async.FutureOr$(core.List)))();
 let dynamicTovoid = () => (dynamicTovoid = dart.constFn(dart.functionType(dart.void, [dart.dynamic])))();
 let StringTovoid = () => (StringTovoid = dart.constFn(dart.functionType(dart.void, [core.String])))();
 let ExpandoOfint = () => (ExpandoOfint = dart.constFn(core.Expando$(core.int)))();
@@ -705,6 +707,7 @@
 let dynamicAndStringAnddynamicTovoid = () => (dynamicAndStringAnddynamicTovoid = dart.constFn(dart.definiteFunctionType(dart.void, [dart.dynamic, core.String, dart.dynamic])))();
 let FAndintToF = () => (FAndintToF = dart.constFn(dart.definiteFunctionType(F => [F, [F, core.int]])))();
 let JSSyntaxRegExpTodynamic = () => (JSSyntaxRegExpTodynamic = dart.constFn(dart.definiteFunctionType(dart.dynamic, [_js_helper.JSSyntaxRegExp])))();
+let ListToListOfString = () => (ListToListOfString = dart.constFn(dart.definiteFunctionType(ListOfString(), [core.List])))();
 let JSSyntaxRegExpToint = () => (JSSyntaxRegExpToint = dart.constFn(dart.definiteFunctionType(core.int, [_js_helper.JSSyntaxRegExp])))();
 let JSSyntaxRegExpAndStringAndintToMatch = () => (JSSyntaxRegExpAndStringAndintToMatch = dart.constFn(dart.definiteFunctionType(core.Match, [_js_helper.JSSyntaxRegExp, core.String, core.int])))();
 let dynamicAnddynamicAnddynamicToint = () => (dynamicAnddynamicAnddynamicToint = dart.constFn(dart.definiteFunctionType(core.int, [dart.dynamic, dart.dynamic, dart.dynamic])))();
@@ -1882,6 +1885,9 @@
 dart.trapRuntimeErrors = function(flag) {
   dart._trapRuntimeErrors = flag;
 };
+dart.ignoreWhitelistedErrors = function(flag) {
+  dart._ignoreWhitelistedErrors = flag;
+};
 dart.throwCastError = function(object, actual, type) {
   var found = dart.typeName(actual);
   var expected = dart.typeName(type);
@@ -2245,7 +2251,7 @@
   let result = dart.isSubtype(actual, type);
   if (result || actual == dart.jsobject || actual == core.int && type == core.double) return true;
   if (result === false) return false;
-  if (ignoreFromWhiteList == void 0) return result;
+  if (!dart._ignoreWhitelistedErrors || ignoreFromWhiteList == void 0) return result;
   if (dart._ignoreTypeFailure(actual, type)) return true;
   return result;
 };
@@ -2989,6 +2995,7 @@
 dart._typeFormalCount = Symbol("_typeFormalCount");
 dart.isSubtype = dart._subtypeMemo((t1, t2) => t1 === t2 || dart._isSubtype(t1, t2, true));
 dart._trapRuntimeErrors = true;
+dart._ignoreWhitelistedErrors = true;
 dart._jsIterator = Symbol("_jsIterator");
 dart._current = Symbol("_current");
 dart._AsyncStarStreamController = class _AsyncStarStreamController {
@@ -4067,6 +4074,13 @@
     children: dart.definiteFunctionType(core.List$(_debugger.NameValuePair), [dart.dynamic])
   })
 });
+_debugger.StackTraceMapper = dart.typedef('StackTraceMapper', () => dart.functionType(core.String, [core.String]));
+dart.copyProperties(_debugger, {
+  get stackTraceMapper() {
+    let _util = dart.global.$dartStackTraceUtility;
+    return _debugger.StackTraceMapper._check(_util != null ? _util.mapper : null);
+  }
+});
 _debugger.registerDevtoolsFormatter = function() {
   let formatters = JSArrayOfJsonMLFormatter().of([_debugger._devtoolsFormatter]);
   dart.global.devtoolsFormatters = formatters;
@@ -9837,7 +9851,7 @@
     let completer = CompleterOfList().new();
     port.first.then(dart.dynamic)(dart.fn(msg => {
       if (dart.equals(dart.dindex(msg, 0), _isolate_helper._SPAWNED_SIGNAL)) {
-        completer.complete(msg);
+        completer.complete(FutureOrOfList()._check(msg));
       } else {
         dart.assert(dart.equals(dart.dindex(msg, 0), _isolate_helper._SPAWN_FAILED_SIGNAL));
         completer.completeError(dart.dindex(msg, 1));
@@ -11936,6 +11950,9 @@
     let trace = null;
     if (this[_exception] !== null && typeof this[_exception] === "object") {
       trace = this[_exception].stack;
+      if (trace != null && _debugger.stackTraceMapper != null) {
+        trace = _debugger.stackTraceMapper(trace);
+      }
     }
     return this[_trace] = trace == null ? '' : trace;
   }
@@ -12829,6 +12846,10 @@
   return regexp[_nativeRegExp];
 };
 dart.lazyFn(_js_helper.regExpGetNative, () => JSSyntaxRegExpTodynamic());
+_js_helper._stringList = function(l) {
+  return ListOfString()._check(l == null ? l : dart.list(l, core.String));
+};
+dart.lazyFn(_js_helper._stringList, () => ListToListOfString());
 const _nativeGlobalVersion = Symbol('_nativeGlobalVersion');
 _js_helper.regExpGetGlobalNative = function(regexp) {
   let nativeRegexp = regexp[_nativeGlobalVersion];
@@ -12895,7 +12916,7 @@
   firstMatch(string) {
     let m = this[_nativeRegExp].exec(_js_helper.checkString(string));
     if (m == null) return null;
-    return new _js_helper._MatchImplementation(this, m);
+    return new _js_helper._MatchImplementation(this, _js_helper._stringList(m));
   }
   hasMatch(string) {
     return this[_nativeRegExp].test(_js_helper.checkString(string));
@@ -12919,7 +12940,7 @@
     regexp.lastIndex = start;
     let match = regexp.exec(string);
     if (match == null) return null;
-    return new _js_helper._MatchImplementation(this, ListOfString()._check(match));
+    return new _js_helper._MatchImplementation(this, _js_helper._stringList(match));
   }
   [_execAnchored](string, start) {
     let regexp = this[_nativeAnchoredVersion];
@@ -12928,7 +12949,7 @@
     if (match == null) return null;
     if (match[dartx._get](dart.notNull(match[dartx.length]) - 1) != null) return null;
     match[dartx.length] = dart.notNull(match[dartx.length]) - 1;
-    return new _js_helper._MatchImplementation(this, ListOfString()._check(match));
+    return new _js_helper._MatchImplementation(this, _js_helper._stringList(match));
   }
   matchAsPrefix(string, start) {
     if (start === void 0) start = 0;
@@ -18308,12 +18329,14 @@
 async._Completer = _Completer();
 const _asyncCompleteError = Symbol('_asyncCompleteError');
 async._AsyncCompleter$ = dart.generic(T => {
+  let FutureOrOfT = () => (FutureOrOfT = dart.constFn(async.FutureOr$(T)))();
   class _AsyncCompleter extends async._Completer$(T) {
     new() {
       super.new();
     }
     complete(value) {
       if (value === void 0) value = null;
+      FutureOrOfT()._check(value);
       if (!dart.test(this.future[_mayComplete])) dart.throw(new core.StateError("Future already completed"));
       this.future[_asyncComplete](value);
     }
@@ -18323,7 +18346,7 @@
   }
   dart.setSignature(_AsyncCompleter, {
     methods: () => ({
-      complete: dart.definiteFunctionType(dart.void, [], [dart.dynamic]),
+      complete: dart.definiteFunctionType(dart.void, [], [FutureOrOfT()]),
       [_completeError]: dart.definiteFunctionType(dart.void, [core.Object, core.StackTrace])
     })
   });
@@ -18331,12 +18354,14 @@
 });
 async._AsyncCompleter = _AsyncCompleter();
 async._SyncCompleter$ = dart.generic(T => {
+  let FutureOrOfT = () => (FutureOrOfT = dart.constFn(async.FutureOr$(T)))();
   class _SyncCompleter extends async._Completer$(T) {
     new() {
       super.new();
     }
     complete(value) {
       if (value === void 0) value = null;
+      FutureOrOfT()._check(value);
       if (!dart.test(this.future[_mayComplete])) dart.throw(new core.StateError("Future already completed"));
       this.future[_complete](value);
     }
@@ -18346,7 +18371,7 @@
   }
   dart.setSignature(_SyncCompleter, {
     methods: () => ({
-      complete: dart.definiteFunctionType(dart.void, [], [dart.dynamic]),
+      complete: dart.definiteFunctionType(dart.void, [], [FutureOrOfT()]),
       [_completeError]: dart.definiteFunctionType(dart.void, [core.Object, core.StackTrace])
     })
   });
@@ -32092,7 +32117,7 @@
     return new core.Duration._microseconds(this[_duration][dartx.abs]());
   }
   _negate() {
-    return new core.Duration._microseconds(-dart.notNull(this[_duration]));
+    return new core.Duration._microseconds(0 - dart.notNull(this[_duration]));
   }
 };
 dart.defineNamedConstructor(core.Duration, '_microseconds');
@@ -72292,6 +72317,7 @@
     timestamp: dart.definiteFunctionType(core.int, [])
   })
 });
+dart.defineExtensionMembers(html$._GeopositionWrapper, ['coords', 'timestamp']);
 dart.defineExtensionNames([
   'coords',
   'timestamp'
@@ -89772,6 +89798,21 @@
     stopPropagation: dart.definiteFunctionType(dart.void, [])
   })
 });
+dart.defineExtensionMembers(html$._WrappedEvent, [
+  'preventDefault',
+  'stopImmediatePropagation',
+  'stopPropagation',
+  'bubbles',
+  'cancelable',
+  'currentTarget',
+  'defaultPrevented',
+  'eventPhase',
+  'target',
+  'timeStamp',
+  'type',
+  'matchingTarget',
+  'path'
+]);
 html$._BeforeUnloadEvent = class _BeforeUnloadEvent extends html$._WrappedEvent {
   new(base) {
     this[_returnValue] = null;
@@ -89793,6 +89834,7 @@
   getters: () => ({returnValue: dart.definiteFunctionType(core.String, [])}),
   setters: () => ({returnValue: dart.definiteFunctionType(dart.void, [core.String])})
 });
+dart.defineExtensionMembers(html$._BeforeUnloadEvent, ['returnValue', 'returnValue']);
 const _eventType = Symbol('_eventType');
 html$._BeforeUnloadEventStreamProvider = class _BeforeUnloadEventStreamProvider extends core.Object {
   new(eventType) {
@@ -93095,6 +93137,25 @@
   }),
   names: ['_makeRecord', '_convertToHexString']
 });
+dart.defineExtensionMembers(html$.KeyEvent, [
+  'getModifierState',
+  'keyCode',
+  'charCode',
+  'altKey',
+  'which',
+  'currentTarget',
+  'code',
+  'ctrlKey',
+  'detail',
+  'key',
+  'keyLocation',
+  'metaKey',
+  'shiftKey',
+  'sourceDevice',
+  'view',
+  'location',
+  'repeat'
+]);
 dart.defineLazy(html$.KeyEvent, {
   get _keyboardEventDispatchRecord() {
     return html$.KeyEvent._makeRecord();
@@ -94800,12 +94861,16 @@
 dart.defineExtensionMembers(html$._DOMWindowCrossFrame, [
   'close',
   'postMessage',
+  'addEventListener',
+  'dispatchEvent',
+  'removeEventListener',
   'history',
   'location',
   'closed',
   'opener',
   'parent',
-  'top'
+  'top',
+  'on'
 ]);
 html$._LocationCrossFrame = class _LocationCrossFrame extends core.Object {
   set href(val) {
@@ -95322,12 +95387,33 @@
 };
 dart.fn(html_common.convertNativeToDart_ContextAttributes, dynamicTodynamic$());
 html_common._TypedImageData = class _TypedImageData extends core.Object {
+  get data() {
+    return this[data$];
+  }
+  set data(value) {
+    super.data = value;
+  }
+  get height() {
+    return this[height$];
+  }
+  set height(value) {
+    super.height = value;
+  }
+  get width() {
+    return this[width$];
+  }
+  set width(value) {
+    super.width = value;
+  }
   new(data, height, width) {
-    this.data = data;
-    this.height = height;
-    this.width = width;
+    this[data$] = data;
+    this[height$] = height;
+    this[width$] = width;
   }
 };
+const data$ = Symbol("_TypedImageData.data");
+const height$ = Symbol("_TypedImageData.height");
+const width$ = Symbol("_TypedImageData.width");
 html_common._TypedImageData[dart.implements] = () => [html$.ImageData];
 dart.setSignature(html_common._TypedImageData, {
   fields: () => ({
@@ -95336,6 +95422,7 @@
     width: core.int
   })
 });
+dart.defineExtensionMembers(html_common._TypedImageData, ['data', 'height', 'width']);
 html_common.convertNativeToDart_ImageData = function(nativeImageData) {
   0;
   if (html$.ImageData.is(nativeImageData)) {
@@ -98616,7 +98703,7 @@
     dart.throw(new core.UnsupportedError("Not supported"));
   }
   get height() {
-    return this[height$];
+    return this[height$0];
   }
   set height(value) {
     super.height = value;
@@ -98628,7 +98715,7 @@
     super.result = value;
   }
   get width() {
-    return this[width$];
+    return this[width$0];
   }
   set width(value) {
     super.width = value;
@@ -98646,9 +98733,9 @@
     super.y = value;
   }
 };
-const height$ = Symbol("FilterPrimitiveStandardAttributes.height");
+const height$0 = Symbol("FilterPrimitiveStandardAttributes.height");
 const result = Symbol("FilterPrimitiveStandardAttributes.result");
-const width$ = Symbol("FilterPrimitiveStandardAttributes.width");
+const width$0 = Symbol("FilterPrimitiveStandardAttributes.width");
 const x = Symbol("FilterPrimitiveStandardAttributes.x");
 const y = Symbol("FilterPrimitiveStandardAttributes.y");
 dart.setSignature(svg$.FilterPrimitiveStandardAttributes, {
@@ -105443,4 +105530,4 @@
   methods: () => ({[dartx.executeSql]: dart.definiteFunctionType(dart.void, [core.String, ListOfObject()], [web_sql.SqlStatementCallback, web_sql.SqlStatementErrorCallback])})
 });
 dart.registerExtension(dart.global.SQLTransaction, web_sql.SqlTransaction);
-dart.trackLibraries("dart_sdk", {"dart:_runtime": dart, "dart:_debugger": _debugger, "dart:_foreign_helper": _foreign_helper, "dart:_interceptors": _interceptors, "dart:_internal": _internal, "dart:_isolate_helper": _isolate_helper, "dart:_js_embedded_names": _js_embedded_names, "dart:_js_helper": _js_helper, "dart:_js_mirrors": _js_mirrors, "dart:_js_primitives": _js_primitives, "dart:_metadata": _metadata, "dart:_native_typed_data": _native_typed_data, "dart:async": async, "dart:collection": collection, "dart:convert": convert, "dart:core": core, "dart:developer": developer, "dart:io": io, "dart:isolate": isolate$, "dart:js": js, "dart:js_util": js_util, "dart:math": math, "dart:mirrors": mirrors, "dart:typed_data": typed_data, "dart:indexed_db": indexed_db, "dart:html": html$, "dart:html_common": html_common, "dart:svg": svg$, "dart:web_audio": web_audio, "dart:web_gl": web_gl, "dart:web_sql": web_sql});
+dart.trackLibraries("dart_sdk", {"dart:_runtime": dart, "dart:_debugger": _debugger, "dart:_foreign_helper": _foreign_helper, "dart:_interceptors": _interceptors, "dart:_internal": _internal, "dart:_isolate_helper": _isolate_helper, "dart:_js_embedded_names": _js_embedded_names, "dart:_js_helper": _js_helper, "dart:_js_mirrors": _js_mirrors, "dart:_js_primitives": _js_primitives, "dart:_metadata": _metadata, "dart:_native_typed_data": _native_typed_data, "dart:async": async, "dart:collection": collection, "dart:convert": convert, "dart:core": core, "dart:developer": developer, "dart:io": io, "dart:isolate": isolate$, "dart:js": js, "dart:js_util": js_util, "dart:math": math, "dart:mirrors": mirrors, "dart:typed_data": typed_data, "dart:indexed_db": indexed_db, "dart:html": html$, "dart:html_common": html_common, "dart:svg": svg$, "dart:web_audio": web_audio, "dart:web_gl": web_gl, "dart:web_sql": web_sql, "dart:nativewrappers": nativewrappers});
diff --git a/pkg/dev_compiler/lib/js/legacy/dart_library.js b/pkg/dev_compiler/lib/js/legacy/dart_library.js
index bb6ab02..89549ae 100644
--- a/pkg/dev_compiler/lib/js/legacy/dart_library.js
+++ b/pkg/dev_compiler/lib/js/legacy/dart_library.js
@@ -153,7 +153,6 @@
   dart_library.library = library;
 
   function import_(libraryName) {
-    bootstrap();
     let loader = libraries.get(libraryName);
     // TODO(vsm): A user might call this directly from JS (as we do in tests).
     // We may want a different error type.
@@ -170,6 +169,10 @@
     let dart_sdk = import_('dart_sdk');
 
     if (!_currentIsolate) {
+      // This import is only needed for chrome debugging. We should provide an
+      // option to compile without it.
+      dart_sdk._debugger.registerDevtoolsFormatter();
+
       // Create isolate.
       _currentIsolate = true;
       dart_sdk._isolate_helper.startRootIsolate(() => {}, []);
@@ -179,15 +182,5 @@
   }
   dart_library.start = start;
 
-  let _bootstrapped = false;
-  function bootstrap() {
-    if (_bootstrapped) return;
-    _bootstrapped = true;
-
-    // This import is only needed for chrome debugging. We should provide an
-    // option to compile without it.
-    dart_sdk._debugger.registerDevtoolsFormatter();
-  }
-
 })(dart_library);
 }
diff --git a/pkg/dev_compiler/lib/js/legacy/dart_sdk.js b/pkg/dev_compiler/lib/js/legacy/dart_sdk.js
index b0a5605..c6c1188 100644
--- a/pkg/dev_compiler/lib/js/legacy/dart_sdk.js
+++ b/pkg/dev_compiler/lib/js/legacy/dart_sdk.js
@@ -33,6 +33,7 @@
   const web_audio = Object.create(null);
   const web_gl = Object.create(null);
   const web_sql = Object.create(null);
+  const nativewrappers = Object.create(null);
   let ListOfObject = () => (ListOfObject = dart.constFn(core.List$(core.Object)))();
   let JSArrayOfListOfObject = () => (JSArrayOfListOfObject = dart.constFn(_interceptors.JSArray$(ListOfObject())))();
   let JSArrayOfObject = () => (JSArrayOfObject = dart.constFn(_interceptors.JSArray$(core.Object)))();
@@ -112,6 +113,7 @@
   let ListOf_IsolateEvent = () => (ListOf_IsolateEvent = dart.constFn(core.List$(_isolate_helper._IsolateEvent)))();
   let QueueOf_IsolateEvent = () => (QueueOf_IsolateEvent = dart.constFn(collection.Queue$(_isolate_helper._IsolateEvent)))();
   let CompleterOfList = () => (CompleterOfList = dart.constFn(async.Completer$(core.List)))();
+  let FutureOrOfList = () => (FutureOrOfList = dart.constFn(async.FutureOr$(core.List)))();
   let dynamicTovoid = () => (dynamicTovoid = dart.constFn(dart.functionType(dart.void, [dart.dynamic])))();
   let StringTovoid = () => (StringTovoid = dart.constFn(dart.functionType(dart.void, [core.String])))();
   let ExpandoOfint = () => (ExpandoOfint = dart.constFn(core.Expando$(core.int)))();
@@ -708,6 +710,7 @@
   let dynamicAndStringAnddynamicTovoid = () => (dynamicAndStringAnddynamicTovoid = dart.constFn(dart.definiteFunctionType(dart.void, [dart.dynamic, core.String, dart.dynamic])))();
   let FAndintToF = () => (FAndintToF = dart.constFn(dart.definiteFunctionType(F => [F, [F, core.int]])))();
   let JSSyntaxRegExpTodynamic = () => (JSSyntaxRegExpTodynamic = dart.constFn(dart.definiteFunctionType(dart.dynamic, [_js_helper.JSSyntaxRegExp])))();
+  let ListToListOfString = () => (ListToListOfString = dart.constFn(dart.definiteFunctionType(ListOfString(), [core.List])))();
   let JSSyntaxRegExpToint = () => (JSSyntaxRegExpToint = dart.constFn(dart.definiteFunctionType(core.int, [_js_helper.JSSyntaxRegExp])))();
   let JSSyntaxRegExpAndStringAndintToMatch = () => (JSSyntaxRegExpAndStringAndintToMatch = dart.constFn(dart.definiteFunctionType(core.Match, [_js_helper.JSSyntaxRegExp, core.String, core.int])))();
   let dynamicAnddynamicAnddynamicToint = () => (dynamicAnddynamicAnddynamicToint = dart.constFn(dart.definiteFunctionType(core.int, [dart.dynamic, dart.dynamic, dart.dynamic])))();
@@ -1885,6 +1888,9 @@
   dart.trapRuntimeErrors = function(flag) {
     dart._trapRuntimeErrors = flag;
   };
+  dart.ignoreWhitelistedErrors = function(flag) {
+    dart._ignoreWhitelistedErrors = flag;
+  };
   dart.throwCastError = function(object, actual, type) {
     var found = dart.typeName(actual);
     var expected = dart.typeName(type);
@@ -2248,7 +2254,7 @@
     let result = dart.isSubtype(actual, type);
     if (result || actual == dart.jsobject || actual == core.int && type == core.double) return true;
     if (result === false) return false;
-    if (ignoreFromWhiteList == void 0) return result;
+    if (!dart._ignoreWhitelistedErrors || ignoreFromWhiteList == void 0) return result;
     if (dart._ignoreTypeFailure(actual, type)) return true;
     return result;
   };
@@ -2992,6 +2998,7 @@
   dart._typeFormalCount = Symbol("_typeFormalCount");
   dart.isSubtype = dart._subtypeMemo((t1, t2) => t1 === t2 || dart._isSubtype(t1, t2, true));
   dart._trapRuntimeErrors = true;
+  dart._ignoreWhitelistedErrors = true;
   dart._jsIterator = Symbol("_jsIterator");
   dart._current = Symbol("_current");
   dart._AsyncStarStreamController = class _AsyncStarStreamController {
@@ -4070,6 +4077,13 @@
       children: dart.definiteFunctionType(core.List$(_debugger.NameValuePair), [dart.dynamic])
     })
   });
+  _debugger.StackTraceMapper = dart.typedef('StackTraceMapper', () => dart.functionType(core.String, [core.String]));
+  dart.copyProperties(_debugger, {
+    get stackTraceMapper() {
+      let _util = dart.global.$dartStackTraceUtility;
+      return _debugger.StackTraceMapper._check(_util != null ? _util.mapper : null);
+    }
+  });
   _debugger.registerDevtoolsFormatter = function() {
     let formatters = JSArrayOfJsonMLFormatter().of([_debugger._devtoolsFormatter]);
     dart.global.devtoolsFormatters = formatters;
@@ -9840,7 +9854,7 @@
       let completer = CompleterOfList().new();
       port.first.then(dart.dynamic)(dart.fn(msg => {
         if (dart.equals(dart.dindex(msg, 0), _isolate_helper._SPAWNED_SIGNAL)) {
-          completer.complete(msg);
+          completer.complete(FutureOrOfList()._check(msg));
         } else {
           dart.assert(dart.equals(dart.dindex(msg, 0), _isolate_helper._SPAWN_FAILED_SIGNAL));
           completer.completeError(dart.dindex(msg, 1));
@@ -11939,6 +11953,9 @@
       let trace = null;
       if (this[_exception] !== null && typeof this[_exception] === "object") {
         trace = this[_exception].stack;
+        if (trace != null && _debugger.stackTraceMapper != null) {
+          trace = _debugger.stackTraceMapper(trace);
+        }
       }
       return this[_trace] = trace == null ? '' : trace;
     }
@@ -12832,6 +12849,10 @@
     return regexp[_nativeRegExp];
   };
   dart.lazyFn(_js_helper.regExpGetNative, () => JSSyntaxRegExpTodynamic());
+  _js_helper._stringList = function(l) {
+    return ListOfString()._check(l == null ? l : dart.list(l, core.String));
+  };
+  dart.lazyFn(_js_helper._stringList, () => ListToListOfString());
   const _nativeGlobalVersion = Symbol('_nativeGlobalVersion');
   _js_helper.regExpGetGlobalNative = function(regexp) {
     let nativeRegexp = regexp[_nativeGlobalVersion];
@@ -12898,7 +12919,7 @@
     firstMatch(string) {
       let m = this[_nativeRegExp].exec(_js_helper.checkString(string));
       if (m == null) return null;
-      return new _js_helper._MatchImplementation(this, m);
+      return new _js_helper._MatchImplementation(this, _js_helper._stringList(m));
     }
     hasMatch(string) {
       return this[_nativeRegExp].test(_js_helper.checkString(string));
@@ -12922,7 +12943,7 @@
       regexp.lastIndex = start;
       let match = regexp.exec(string);
       if (match == null) return null;
-      return new _js_helper._MatchImplementation(this, ListOfString()._check(match));
+      return new _js_helper._MatchImplementation(this, _js_helper._stringList(match));
     }
     [_execAnchored](string, start) {
       let regexp = this[_nativeAnchoredVersion];
@@ -12931,7 +12952,7 @@
       if (match == null) return null;
       if (match[dartx._get](dart.notNull(match[dartx.length]) - 1) != null) return null;
       match[dartx.length] = dart.notNull(match[dartx.length]) - 1;
-      return new _js_helper._MatchImplementation(this, ListOfString()._check(match));
+      return new _js_helper._MatchImplementation(this, _js_helper._stringList(match));
     }
     matchAsPrefix(string, start) {
       if (start === void 0) start = 0;
@@ -18311,12 +18332,14 @@
   async._Completer = _Completer();
   const _asyncCompleteError = Symbol('_asyncCompleteError');
   async._AsyncCompleter$ = dart.generic(T => {
+    let FutureOrOfT = () => (FutureOrOfT = dart.constFn(async.FutureOr$(T)))();
     class _AsyncCompleter extends async._Completer$(T) {
       new() {
         super.new();
       }
       complete(value) {
         if (value === void 0) value = null;
+        FutureOrOfT()._check(value);
         if (!dart.test(this.future[_mayComplete])) dart.throw(new core.StateError("Future already completed"));
         this.future[_asyncComplete](value);
       }
@@ -18326,7 +18349,7 @@
     }
     dart.setSignature(_AsyncCompleter, {
       methods: () => ({
-        complete: dart.definiteFunctionType(dart.void, [], [dart.dynamic]),
+        complete: dart.definiteFunctionType(dart.void, [], [FutureOrOfT()]),
         [_completeError]: dart.definiteFunctionType(dart.void, [core.Object, core.StackTrace])
       })
     });
@@ -18334,12 +18357,14 @@
   });
   async._AsyncCompleter = _AsyncCompleter();
   async._SyncCompleter$ = dart.generic(T => {
+    let FutureOrOfT = () => (FutureOrOfT = dart.constFn(async.FutureOr$(T)))();
     class _SyncCompleter extends async._Completer$(T) {
       new() {
         super.new();
       }
       complete(value) {
         if (value === void 0) value = null;
+        FutureOrOfT()._check(value);
         if (!dart.test(this.future[_mayComplete])) dart.throw(new core.StateError("Future already completed"));
         this.future[_complete](value);
       }
@@ -18349,7 +18374,7 @@
     }
     dart.setSignature(_SyncCompleter, {
       methods: () => ({
-        complete: dart.definiteFunctionType(dart.void, [], [dart.dynamic]),
+        complete: dart.definiteFunctionType(dart.void, [], [FutureOrOfT()]),
         [_completeError]: dart.definiteFunctionType(dart.void, [core.Object, core.StackTrace])
       })
     });
@@ -32095,7 +32120,7 @@
       return new core.Duration._microseconds(this[_duration][dartx.abs]());
     }
     _negate() {
-      return new core.Duration._microseconds(-dart.notNull(this[_duration]));
+      return new core.Duration._microseconds(0 - dart.notNull(this[_duration]));
     }
   };
   dart.defineNamedConstructor(core.Duration, '_microseconds');
@@ -72295,6 +72320,7 @@
       timestamp: dart.definiteFunctionType(core.int, [])
     })
   });
+  dart.defineExtensionMembers(html$._GeopositionWrapper, ['coords', 'timestamp']);
   dart.defineExtensionNames([
     'coords',
     'timestamp'
@@ -89775,6 +89801,21 @@
       stopPropagation: dart.definiteFunctionType(dart.void, [])
     })
   });
+  dart.defineExtensionMembers(html$._WrappedEvent, [
+    'preventDefault',
+    'stopImmediatePropagation',
+    'stopPropagation',
+    'bubbles',
+    'cancelable',
+    'currentTarget',
+    'defaultPrevented',
+    'eventPhase',
+    'target',
+    'timeStamp',
+    'type',
+    'matchingTarget',
+    'path'
+  ]);
   html$._BeforeUnloadEvent = class _BeforeUnloadEvent extends html$._WrappedEvent {
     new(base) {
       this[_returnValue] = null;
@@ -89796,6 +89837,7 @@
     getters: () => ({returnValue: dart.definiteFunctionType(core.String, [])}),
     setters: () => ({returnValue: dart.definiteFunctionType(dart.void, [core.String])})
   });
+  dart.defineExtensionMembers(html$._BeforeUnloadEvent, ['returnValue', 'returnValue']);
   const _eventType = Symbol('_eventType');
   html$._BeforeUnloadEventStreamProvider = class _BeforeUnloadEventStreamProvider extends core.Object {
     new(eventType) {
@@ -93098,6 +93140,25 @@
     }),
     names: ['_makeRecord', '_convertToHexString']
   });
+  dart.defineExtensionMembers(html$.KeyEvent, [
+    'getModifierState',
+    'keyCode',
+    'charCode',
+    'altKey',
+    'which',
+    'currentTarget',
+    'code',
+    'ctrlKey',
+    'detail',
+    'key',
+    'keyLocation',
+    'metaKey',
+    'shiftKey',
+    'sourceDevice',
+    'view',
+    'location',
+    'repeat'
+  ]);
   dart.defineLazy(html$.KeyEvent, {
     get _keyboardEventDispatchRecord() {
       return html$.KeyEvent._makeRecord();
@@ -94803,12 +94864,16 @@
   dart.defineExtensionMembers(html$._DOMWindowCrossFrame, [
     'close',
     'postMessage',
+    'addEventListener',
+    'dispatchEvent',
+    'removeEventListener',
     'history',
     'location',
     'closed',
     'opener',
     'parent',
-    'top'
+    'top',
+    'on'
   ]);
   html$._LocationCrossFrame = class _LocationCrossFrame extends core.Object {
     set href(val) {
@@ -95325,12 +95390,33 @@
   };
   dart.fn(html_common.convertNativeToDart_ContextAttributes, dynamicTodynamic$());
   html_common._TypedImageData = class _TypedImageData extends core.Object {
+    get data() {
+      return this[data$];
+    }
+    set data(value) {
+      super.data = value;
+    }
+    get height() {
+      return this[height$];
+    }
+    set height(value) {
+      super.height = value;
+    }
+    get width() {
+      return this[width$];
+    }
+    set width(value) {
+      super.width = value;
+    }
     new(data, height, width) {
-      this.data = data;
-      this.height = height;
-      this.width = width;
+      this[data$] = data;
+      this[height$] = height;
+      this[width$] = width;
     }
   };
+  const data$ = Symbol("_TypedImageData.data");
+  const height$ = Symbol("_TypedImageData.height");
+  const width$ = Symbol("_TypedImageData.width");
   html_common._TypedImageData[dart.implements] = () => [html$.ImageData];
   dart.setSignature(html_common._TypedImageData, {
     fields: () => ({
@@ -95339,6 +95425,7 @@
       width: core.int
     })
   });
+  dart.defineExtensionMembers(html_common._TypedImageData, ['data', 'height', 'width']);
   html_common.convertNativeToDart_ImageData = function(nativeImageData) {
     0;
     if (html$.ImageData.is(nativeImageData)) {
@@ -98619,7 +98706,7 @@
       dart.throw(new core.UnsupportedError("Not supported"));
     }
     get height() {
-      return this[height$];
+      return this[height$0];
     }
     set height(value) {
       super.height = value;
@@ -98631,7 +98718,7 @@
       super.result = value;
     }
     get width() {
-      return this[width$];
+      return this[width$0];
     }
     set width(value) {
       super.width = value;
@@ -98649,9 +98736,9 @@
       super.y = value;
     }
   };
-  const height$ = Symbol("FilterPrimitiveStandardAttributes.height");
+  const height$0 = Symbol("FilterPrimitiveStandardAttributes.height");
   const result = Symbol("FilterPrimitiveStandardAttributes.result");
-  const width$ = Symbol("FilterPrimitiveStandardAttributes.width");
+  const width$0 = Symbol("FilterPrimitiveStandardAttributes.width");
   const x = Symbol("FilterPrimitiveStandardAttributes.x");
   const y = Symbol("FilterPrimitiveStandardAttributes.y");
   dart.setSignature(svg$.FilterPrimitiveStandardAttributes, {
@@ -105446,7 +105533,7 @@
     methods: () => ({[dartx.executeSql]: dart.definiteFunctionType(dart.void, [core.String, ListOfObject()], [web_sql.SqlStatementCallback, web_sql.SqlStatementErrorCallback])})
   });
   dart.registerExtension(dart.global.SQLTransaction, web_sql.SqlTransaction);
-  dart.trackLibraries("dart_sdk", {"dart:_runtime": dart, "dart:_debugger": _debugger, "dart:_foreign_helper": _foreign_helper, "dart:_interceptors": _interceptors, "dart:_internal": _internal, "dart:_isolate_helper": _isolate_helper, "dart:_js_embedded_names": _js_embedded_names, "dart:_js_helper": _js_helper, "dart:_js_mirrors": _js_mirrors, "dart:_js_primitives": _js_primitives, "dart:_metadata": _metadata, "dart:_native_typed_data": _native_typed_data, "dart:async": async, "dart:collection": collection, "dart:convert": convert, "dart:core": core, "dart:developer": developer, "dart:io": io, "dart:isolate": isolate$, "dart:js": js, "dart:js_util": js_util, "dart:math": math, "dart:mirrors": mirrors, "dart:typed_data": typed_data, "dart:indexed_db": indexed_db, "dart:html": html$, "dart:html_common": html_common, "dart:svg": svg$, "dart:web_audio": web_audio, "dart:web_gl": web_gl, "dart:web_sql": web_sql});
+  dart.trackLibraries("dart_sdk", {"dart:_runtime": dart, "dart:_debugger": _debugger, "dart:_foreign_helper": _foreign_helper, "dart:_interceptors": _interceptors, "dart:_internal": _internal, "dart:_isolate_helper": _isolate_helper, "dart:_js_embedded_names": _js_embedded_names, "dart:_js_helper": _js_helper, "dart:_js_mirrors": _js_mirrors, "dart:_js_primitives": _js_primitives, "dart:_metadata": _metadata, "dart:_native_typed_data": _native_typed_data, "dart:async": async, "dart:collection": collection, "dart:convert": convert, "dart:core": core, "dart:developer": developer, "dart:io": io, "dart:isolate": isolate$, "dart:js": js, "dart:js_util": js_util, "dart:math": math, "dart:mirrors": mirrors, "dart:typed_data": typed_data, "dart:indexed_db": indexed_db, "dart:html": html$, "dart:html_common": html_common, "dart:svg": svg$, "dart:web_audio": web_audio, "dart:web_gl": web_gl, "dart:web_sql": web_sql, "dart:nativewrappers": nativewrappers});
   // Exports:
   exports.dart = dart;
   exports.dartx = dartx;
@@ -105480,4 +105567,5 @@
   exports.web_audio = web_audio;
   exports.web_gl = web_gl;
   exports.web_sql = web_sql;
+  exports.nativewrappers = nativewrappers;
 });
diff --git a/pkg/dev_compiler/lib/sdk/ddc_sdk.sum b/pkg/dev_compiler/lib/sdk/ddc_sdk.sum
index d9d2b37..5c9edfd 100644
--- a/pkg/dev_compiler/lib/sdk/ddc_sdk.sum
+++ b/pkg/dev_compiler/lib/sdk/ddc_sdk.sum
Binary files differ
diff --git a/pkg/dev_compiler/lib/src/compiler/extension_types.dart b/pkg/dev_compiler/lib/src/compiler/extension_types.dart
index 2a3826c..7afb9f3 100644
--- a/pkg/dev_compiler/lib/src/compiler/extension_types.dart
+++ b/pkg/dev_compiler/lib/src/compiler/extension_types.dart
@@ -162,7 +162,7 @@
   void _collectNativeInterfaces(InterfaceType type, Set<ClassElement> types) {
     if (type.isObject) return;
     var element = type.element;
-    if (_isNativeInterface(element)) types.add(element);
+    if (hasNativeSubtype(type)) types.add(element);
     for (var m in element.mixins.reversed) {
       _collectNativeInterfaces(m, types);
     }
diff --git a/pkg/dev_compiler/test/browser/language_tests.js b/pkg/dev_compiler/test/browser/language_tests.js
index 48605ea..f922ca9 100644
--- a/pkg/dev_compiler/test/browser/language_tests.js
+++ b/pkg/dev_compiler/test/browser/language_tests.js
@@ -10,6 +10,7 @@
   let minitest = expect.minitest;
   let mochaOnError = window.onerror;
   dart_sdk.dart.trapRuntimeErrors(false);
+  dart_sdk.dart.ignoreWhitelistedErrors(false);
   dart_sdk._isolate_helper.startRootIsolate(function() {}, []);
   // Make it easier to debug test failures and required for formatter test that
   // assumes custom formatters are enabled.
@@ -26,6 +27,7 @@
   //   'slow' - use 5s timeout instead of default 2s.
   //   'helper'  - not a test, used by other tests.
   //   'unittest' - run separately as a unittest test.
+  //   'whitelist' - run with whitelisted type errors allowed
   //
   // Common combinations:
   const pass = 'pass';
@@ -39,6 +41,7 @@
   // These are typically tests with asynchronous exceptions that our
   // test framework doesn't always catch.
   const flaky = 'skip';
+  const whitelist = 'whitelist';
 
   // Tests marked with this are still using the deprecated unittest package
   // because they rely on its support for futures and asynchronous tests, which
@@ -78,6 +81,8 @@
       'async_star_test_05_multi': async_unittest,
 
       'async_switch_test': fail,
+      'async_test': whitelist,
+      'async_this_bound_test': whitelist,
       'asyncstar_throw_in_catch_test': ['skip', 'fail'],
       'await_future_test': skip_timeout,
       'bit_operations_test_none_multi': fail,  // DDC/dart2js canonicalize bitop results to unsigned
@@ -108,7 +113,10 @@
       'const_switch_test_02_multi': fail,
       'const_switch_test_04_multi': fail,
       'constructor12_test': fail,
+      'covariant_subtyping_tearoff2_test': fail,     
+      'covariant_subtyping_tearoff3_test': fail,
       'covariant_subtyping_unsafe_call2_test': fail,
+      'covariant_subtyping_unsafe_call3_test': fail,
       'cyclic_type2_test': fail,
       'cyclic_type_test_00_multi': fail,
       'cyclic_type_test_01_multi': fail,
@@ -155,10 +163,6 @@
       'function_subtype_call0_test': fail, // Strong mode "is" rejects some type tests.
       'function_subtype_call1_test': fail,
       'function_subtype_call2_test': fail,
-      'function_subtype_cast0_test': fail,
-      'function_subtype_cast1_test': fail,
-      'function_subtype_cast2_test': fail,
-      'function_subtype_cast3_test': fail,
       'function_subtype_factory0_test': fail,
       'function_subtype_inline0_test': fail,
       'function_subtype_local0_test': fail,
@@ -205,6 +209,7 @@
       'list_is_test': fail,
       'list_literal3_test': fail,
       'many_generic_instanceof_test': fail,
+      'many_named_arguments_test': whitelist,
       'map_literal10_test': fail,
       'map_literal7_test': fail,
       'memory_swap_test': skip_timeout,
@@ -232,6 +237,7 @@
       'number_identity2_test': fail,
       'numbers_test': fail,
       'redirecting_factory_reflection_test': fail,
+      'reg_exp_test': whitelist,
       'regress_16640_test': fail,
       'regress_18535_test': fail,
       'regress_22666_test': fail,
@@ -309,10 +315,12 @@
       'int_parse_radix_test_none_multi': ['slow'],
       'integer_to_radix_string_test': fail,
       'integer_to_string_test_01_multi': fail,
-      'iterable_generate_test': fail,
+      'iterable_empty_test': whitelist,
+      'iterable_join_test': whitelist,
       'iterable_return_type_test_02_multi': fail,
       'json_map_test': fail,
       'list_fill_range_test': fail,
+      'list_insert_all_test': whitelist,
       'list_replace_range_test': fail,
       'list_set_all_test': fail,
       'list_to_string2_test': fail,
@@ -324,12 +332,16 @@
       'null_nosuchmethod_test': fail,
       'null_test': fail,
       'num_sign_test': fail,
+      'reg_exp_all_matches_test': whitelist,
+      'reg_exp_start_end_test': whitelist,
       'regress_r21715_test': fail,
       'throw_half_surrogate_pair_test_02_multi': fail,
+      'sort_test': whitelist,
       'splay_tree_from_iterable_test': is.firefox('<=50') ? fail : pass,
       'string_case_test_01_multi': firefox_fail,
       'string_fromcharcodes_test': skip_timeout,
       'string_operations_with_null_test': fail,
+      'string_split_test': whitelist,
       'symbol_reserved_word_test_06_multi': fail,
       'symbol_reserved_word_test_09_multi': fail,
       'symbol_reserved_word_test_12_multi': fail,
@@ -339,7 +351,7 @@
       // TODO(rnystrom): Times out because it tests a huge number of
       // combinations of URLs (4 * 5 * 5 * 8 * 6 * 6 * 4 = 115200).
       'uri_parse_test': skip_timeout,
-      'uri_test': is.firefox('<=50') ? fail : pass,
+      'uri_test': 'slow',
 
       'list_insert_test': fail,
       'list_removeat_test': fail,
@@ -351,23 +363,32 @@
     },
 
     'lib/collection': {
+      'linked_list_test': whitelist,
     },
 
     'lib/convert': {
       'base64_test_01_multi': 'slow',
-      'chunked_conversion_utf85_test': 'slow',
+      'chunked_conversion_utf82_test': whitelist,
+      'chunked_conversion_utf83_test': whitelist,
+      'chunked_conversion_utf85_test': ['whitelist', 'slow'],
+      'chunked_conversion_utf86_test': whitelist,
+      'chunked_conversion_utf87_test': whitelist,
 
       'encoding_test': skip_timeout,
 
       'json_utf8_chunk_test': skip_timeout,
       'latin1_test': skip_timeout,
 
+      'streamed_conversion_json_decode1_test': whitelist,
       'streamed_conversion_json_encode1_test': skip_timeout,
       'streamed_conversion_json_utf8_decode_test': skip_timeout,
       'streamed_conversion_json_utf8_encode_test': skip_timeout,
       'streamed_conversion_utf8_decode_test': skip_timeout,
       'streamed_conversion_utf8_encode_test': skip_timeout,
+      'utf82_test': whitelist,
       'utf85_test': skip_timeout,
+      'utf8_encode_test': whitelist,
+      'utf8_test': whitelist,
     },
 
     'lib/html': {
@@ -391,6 +412,7 @@
       'custom_element_name_clash_test': async_unittest,
       'custom_elements_23127_test': async_unittest,
       'custom_elements_test': async_unittest,
+      'debugger_test': firefox_fail,
       'element_animate_test': 'unittest',
 
       // https://github.com/dart-lang/sdk/issues/27579.
@@ -494,6 +516,7 @@
       'int64_list_load_store_test': fail,
       'typed_data_hierarchy_int64_test': fail,
       'typed_data_list_test': fail,
+      'typed_list_iterable_test': whitelist,
     },
 
     'lib/mirrors': {
@@ -740,6 +763,9 @@
         let negative = /negative_test/.test(name);
         let fail = has('fail');
 
+        let whitelist = has('whitelist');
+        dart_sdk.dart.ignoreWhitelistedErrors(whitelist);
+
         function finish(error) {
           // If the test left any lingering detritus in the DOM, blow it away
           // so it doesn't interfere with later tests.
@@ -766,6 +792,7 @@
           document.body.innerHTML = '';
           console.log("cleared");
           if (error && !(error instanceof Error)) error = new Error(error);
+          dart_sdk.dart.ignoreWhitelistedErrors(false);
           done(error);
         }
 
@@ -814,6 +841,9 @@
   // Dart unittests run and then re-enabling it when the dart tests complete.
   html_config.useHtmlConfiguration();
   test('run all dart unittests', function(done) { // 'function' to allow `this.timeout`
+    // Use the whitelist for all unittests - there may be an error in the framework
+    // itself.
+    dart_sdk.dart.ignoreWhitelistedErrors(whitelist);
     if (unittest_tests.length == 0) return done();
 
     // TODO(vsm): We're using an old deprecated version of unittest.
diff --git a/pkg/dev_compiler/test/codegen_test.dart b/pkg/dev_compiler/test/codegen_test.dart
index 2e1d7be..def1fd6 100644
--- a/pkg/dev_compiler/test/codegen_test.dart
+++ b/pkg/dev_compiler/test/codegen_test.dart
@@ -398,6 +398,7 @@
   // TODO(vsm): Fix these - they import files from a different directory
   // - this triggers an invalid library root build error.
   'lib/html/custom/attribute_changed_callback_test',
+  'lib/html/custom/constructor_calls_created_synchronously_test',
   'lib/html/custom/entered_left_view_test',
   'lib/html/custom/js_custom_test',
   'lib/html/custom/mirrors_test',
diff --git a/pkg/dev_compiler/test/not_yet_strong_tests.dart b/pkg/dev_compiler/test/not_yet_strong_tests.dart
index da7cd00..b4c5e39 100644
--- a/pkg/dev_compiler/test/not_yet_strong_tests.dart
+++ b/pkg/dev_compiler/test/not_yet_strong_tests.dart
@@ -133,6 +133,8 @@
   'language/bad_override_test_04_multi',
   'language/bad_override_test_05_multi',
   'language/bad_override_test_06_multi',
+  'language/bad_raw_string_test_01_multi',
+  'language/bad_raw_string_test_02_multi',
   'language/black_listed_test_01_multi',
   'language/black_listed_test_02_multi',
   'language/black_listed_test_03_multi',
diff --git a/pkg/dev_compiler/tool/input_sdk/lib/html/dart2js/nativewrappers.dart b/pkg/dev_compiler/tool/input_sdk/lib/html/dart2js/nativewrappers.dart
new file mode 100644
index 0000000..bd33769
--- /dev/null
+++ b/pkg/dev_compiler/tool/input_sdk/lib/html/dart2js/nativewrappers.dart
@@ -0,0 +1,7 @@
+// Copyright (c) 2017, 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 is a dummy library that is referred from dart:io.  It's only used for
+// the VM.
+library dart.nativewrappers;
diff --git a/pkg/dev_compiler/tool/input_sdk/libraries.dart b/pkg/dev_compiler/tool/input_sdk/libraries.dart
index 69b4856..d14bf10 100644
--- a/pkg/dev_compiler/tool/input_sdk/libraries.dart
+++ b/pkg/dev_compiler/tool/input_sdk/libraries.dart
@@ -42,18 +42,6 @@
       maturity: Maturity.STABLE,
       dart2jsPatchPath: "_internal/js_runtime/lib/async_patch.dart"),
 
-  "_blink": const LibraryInfo(
-      "_blink/dartium/_blink_dartium.dart",
-      categories: "Client",
-      implementation: true,
-      documented: false,
-      platforms: VM_PLATFORM),
-
-  "_chrome": const LibraryInfo(
-      "_chrome/dart2js/chrome_dart2js.dart",
-      categories: "Client",
-      documented: false),
-
   "collection": const LibraryInfo(
       "collection/collection.dart",
       categories: "Client,Server,Embedded",
@@ -133,6 +121,13 @@
       maturity: Maturity.UNSTABLE,
       dart2jsPatchPath: "_internal/js_runtime/lib/mirrors_patch.dart"),
 
+  "nativewrappers": const LibraryInfo(
+      "html/dartium/nativewrappers.dart",
+      categories: "Client",
+      implementation: true,
+      documented: false,
+      dart2jsPath: "html/dart2js/nativewrappers.dart"),
+
   "typed_data": const LibraryInfo(
       "typed_data/typed_data.dart",
       categories: "Client,Server,Embedded",
@@ -206,12 +201,6 @@
       documented: false,
       platforms: DART2JS_PLATFORM),
 
-  "_js_names": const LibraryInfo(
-      "_internal/js_runtime/lib/js_names.dart",
-      categories: "",
-      documented: false,
-      platforms: DART2JS_PLATFORM),
-
   "_js_primitives": const LibraryInfo(
       "_internal/js_runtime/lib/js_primitives.dart",
       categories: "",
@@ -224,12 +213,6 @@
       documented: false,
       platforms: DART2JS_PLATFORM),
 
-  "_async_await_error_codes": const LibraryInfo(
-      "_internal/js_runtime/lib/shared/async_await_error_codes.dart",
-      categories: "",
-      documented: false,
-      platforms: DART2JS_PLATFORM),
-
   "_metadata": const LibraryInfo(
       "html/html_common/metadata.dart",
       categories: "",
diff --git a/pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/errors.dart b/pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/errors.dart
index 49bc1cc..b432d3e 100644
--- a/pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/errors.dart
+++ b/pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/errors.dart
@@ -4,12 +4,17 @@
 part of dart._runtime;
 
 bool _trapRuntimeErrors = true;
+bool _ignoreWhitelistedErrors = true;
 
 // Override, e.g., for testing
 void trapRuntimeErrors(bool flag) {
   _trapRuntimeErrors = flag;
 }
 
+void ignoreWhitelistedErrors(bool flag) {
+  _ignoreWhitelistedErrors = flag;
+}
+
 throwCastError(object, actual, type) => JS('', '''(() => {
   var found = $typeName($actual);
   var expected = $typeName($type);
diff --git a/pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/operations.dart b/pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/operations.dart
index f89ca0c..f7fa491 100644
--- a/pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/operations.dart
+++ b/pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/operations.dart
@@ -498,7 +498,7 @@
   if (result || actual == $jsobject ||
       actual == $int && type == $double) return true;
   if (result === false) return false;
-  if ($ignoreFromWhiteList == void 0) return result;
+  if (!$_ignoreWhitelistedErrors || ($ignoreFromWhiteList == void 0)) return result;
   if ($_ignoreTypeFailure(actual, $type)) return true;
   return result;
 })()''');
diff --git a/pkg/dev_compiler/tool/input_sdk/private/debugger.dart b/pkg/dev_compiler/tool/input_sdk/private/debugger.dart
index 7fbc2de..c4c65a0 100644
--- a/pkg/dev_compiler/tool/input_sdk/private/debugger.dart
+++ b/pkg/dev_compiler/tool/input_sdk/private/debugger.dart
@@ -850,6 +850,18 @@
   List<NameValuePair> children(object) => [];
 }
 
+typedef String StackTraceMapper(String stackTrace);
+
+/// Hook for other parts of the SDK To use to map JS stack traces to Dart
+/// stack traces.
+///
+/// Raw JS stack traces are used if $dartStackTraceUtility has not been
+/// specified.
+StackTraceMapper get stackTraceMapper {
+  var _util = JS('', r'dart.global.$dartStackTraceUtility');
+  return _util != null ? JS('StackTraceMapper', '#.mapper', _util) : null;
+}
+
 /// This entry point is automatically invoked by the code generated by
 /// Dart Dev Compiler
 registerDevtoolsFormatter() {
diff --git a/pkg/dev_compiler/tool/input_sdk/private/js_helper.dart b/pkg/dev_compiler/tool/input_sdk/private/js_helper.dart
index fee11a5..28cd859 100644
--- a/pkg/dev_compiler/tool/input_sdk/private/js_helper.dart
+++ b/pkg/dev_compiler/tool/input_sdk/private/js_helper.dart
@@ -6,6 +6,8 @@
 
 import 'dart:collection';
 
+import 'dart:_debugger' show stackTraceMapper;
+
 import 'dart:_foreign_helper' show
     JS,
     JS_STRING_CONCAT;
@@ -628,15 +630,19 @@
 class _StackTrace implements StackTrace {
   var _exception;
   String _trace;
+
   _StackTrace(this._exception);
 
   String toString() {
-    if (_trace != null) return JS('String', '#', _trace);
+    if (_trace != null) return _trace;
 
     String trace;
     if (JS('bool', '# !== null', _exception) &&
         JS('bool', 'typeof # === "object"', _exception)) {
       trace = JS("String|Null", r"#.stack", _exception);
+      if (trace != null && stackTraceMapper != null) {
+        trace = stackTraceMapper(trace);
+      }
     }
     return _trace = (trace == null) ? '' : trace;
   }
diff --git a/pkg/dev_compiler/tool/input_sdk/private/regexp_helper.dart b/pkg/dev_compiler/tool/input_sdk/private/regexp_helper.dart
index fbd7895..a8fb4cc 100644
--- a/pkg/dev_compiler/tool/input_sdk/private/regexp_helper.dart
+++ b/pkg/dev_compiler/tool/input_sdk/private/regexp_helper.dart
@@ -7,6 +7,8 @@
 // Helper method used by internal libraries.
 regExpGetNative(JSSyntaxRegExp regexp) => regexp._nativeRegExp;
 
+List<String> _stringList(List l) => l == null ? l : JS('', 'dart.list(#, #)', l, String);
+
 /**
  * Returns a native version of the RegExp with the global flag set.
  *
@@ -105,12 +107,12 @@
   }
 
   Match firstMatch(String string) {
-    List<String> m = JS('JSExtendableArray|Null',
+    List m = JS('JSExtendableArray|Null',
                         r'#.exec(#)',
                         _nativeRegExp,
                         checkString(string));
     if (m == null) return null;
-    return new _MatchImplementation(this, m);
+    return new _MatchImplementation(this, _stringList(m));
   }
 
   bool hasMatch(String string) {
@@ -137,7 +139,7 @@
     JS("void", "#.lastIndex = #", regexp, start);
     List match = JS("JSExtendableArray|Null", "#.exec(#)", regexp, string);
     if (match == null) return null;
-    return new _MatchImplementation(this, match);
+    return new _MatchImplementation(this, _stringList(match));
   }
 
   Match _execAnchored(String string, int start) {
@@ -149,7 +151,7 @@
     // match at the start position.
     if (match[match.length - 1] != null) return null;
     match.length -= 1;
-    return new _MatchImplementation(this, match);
+    return new _MatchImplementation(this, _stringList(match));
   }
 
   Match matchAsPrefix(String string, [int start = 0]) {
diff --git a/pkg/dev_compiler/tool/run.js b/pkg/dev_compiler/tool/run.js
index 6783750..90a2c8a 100644
--- a/pkg/dev_compiler/tool/run.js
+++ b/pkg/dev_compiler/tool/run.js
@@ -42,11 +42,11 @@
 // TODO(vsm): Factor out test framework code in test/browser/language_tests.js
 // and use here.  Async tests and unittests won't work without it.
 var sdk = requirejs('dart_sdk');
+sdk.dart.ignoreWhitelistedErrors(false);
 var module = requirejs(test);
 var lib = test.split('/').slice(-1)[0];
 try {
-  sdk._isolate_helper.startRootIsolate(() => {}, []);
-  module[lib].main();
+  sdk._isolate_helper.startRootIsolate(module[lib].main, []);
   console.log('Test ' + test + ' passed.');
 } catch (e) {
   console.log('Test ' + test + ' failed:\n' + e.toString());
diff --git a/pkg/dev_compiler/tool/sdk_expected_errors.txt b/pkg/dev_compiler/tool/sdk_expected_errors.txt
index 9badbd3..3f935d6 100644
--- a/pkg/dev_compiler/tool/sdk_expected_errors.txt
+++ b/pkg/dev_compiler/tool/sdk_expected_errors.txt
@@ -40,7 +40,6 @@
 [error] Invalid override. The type of 'ZLibEncoder.startChunkedConversion' ('(Sink<List<int>>) → ByteConversionSink') isn't a subtype of 'ChunkedConverter<List<int>, List<int>, List<int>, List<int>>.startChunkedConversion' ('(dynamic) → dynamic'). (dart:io/data_transformer.dart, line 370, col 3)
 [error] The argument type '(RandomAccessFile) → Future<RandomAccessFile>' can't be assigned to the parameter type '(RandomAccessFile) → FutureOr<File>'. (dart:io/file_impl.dart, line 216, col 30)
 [error] The return type 'Future' isn't a 'FutureOr<File>', as defined by the method ''. (dart:io/file_impl.dart, line 614, col 14)
-[error] Target of URI doesn't exist: 'dart:nativewrappers'. (dart:io, line 211, col 8)
 [error] Undefined name 'lineMode'. (dart:io/stdio.dart, line 64, col 10)
 [error] The name 'echoMode=' is already defined. (dart:io/stdio.dart, line 128, col 12)
 [error] The name 'lineMode=' is already defined. (dart:io/stdio.dart, line 149, col 12)
@@ -52,8 +51,6 @@
 [error] Invalid override. The type of 'JsArray.[]=' ('(Object, E) → void') isn't a subtype of 'JsObject.[]=' ('(Object, dynamic) → dynamic'). (dart:js, line 363, col 3)
 [error] The return type 'double' isn't a 'T', as defined by the method 'min'. (dart:math, line 90, col 16)
 [error] The return type 'double' isn't a 'T', as defined by the method 'max'. (dart:math, line 125, col 16)
-[warning] Unsafe implicit cast from 'List<dynamic>' to 'List<String>'. This usually indicates that type information was lost and resulted in 'dynamic' and/or a place that will have a failure at runtime. (dart:_js_helper/regexp_helper.dart, line 140, col 43)
-[warning] Unsafe implicit cast from 'List<dynamic>' to 'List<String>'. This usually indicates that type information was lost and resulted in 'dynamic' and/or a place that will have a failure at runtime. (dart:_js_helper/regexp_helper.dart, line 152, col 43)
 [warning] Unsafe implicit cast from 'Function' to '(dynamic) → FutureOr<T>'. This usually indicates that type information was lost and resulted in 'dynamic' and/or a place that will have a failure at runtime. (dart:async/future_impl.dart, line 151, col 11)
 [warning] Unsafe implicit cast from '(T) → dynamic' to '(T) → FutureOr<E>'. This usually indicates that type information was lost and resulted in 'dynamic' and/or a place that will have a failure at runtime. (dart:async/future_impl.dart, line 249, col 57)
 [warning] Unsafe implicit cast from 'StreamSubscription<dynamic>' to 'StreamSubscription<T>'. This usually indicates that type information was lost and resulted in 'dynamic' and/or a place that will have a failure at runtime. (dart:async/stream_impl.dart, line 1011, col 42)
diff --git a/pkg/dev_compiler/web/stack_trace_mapper.dart b/pkg/dev_compiler/web/stack_trace_mapper.dart
new file mode 100644
index 0000000..557e6fd
--- /dev/null
+++ b/pkg/dev_compiler/web/stack_trace_mapper.dart
@@ -0,0 +1,134 @@
+// Copyright (c) 2017, 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.
+
+/// Standalone utility that manages loading source maps for all Dart scripts
+/// on the page compiled with DDC.
+///
+/// Example JavaScript usage:
+/// $dartStackTraceUtility.addLoadedListener(function() {
+///   // All Dart source maps are now loaded. It is now safe to start your
+///   // Dart application compiled with DDC.
+///   dart_library.start('your_dart_application');
+/// })
+///
+/// If $dartStackTraceUtility is set, the dart:core StackTrace class calls
+/// $dartStackTraceUtility.mapper(someJSStackTrace)
+/// to apply source maps.
+///
+/// This utility can be compiled to JavaScript using Dart2JS while the rest
+/// of the application is compiled with DDC or could be compiled with DDC.
+
+@JS()
+library stack_trace_mapper;
+
+import 'dart:async';
+import 'dart:html';
+
+import 'package:js/js.dart';
+import 'package:path/path.dart' as path;
+import 'package:source_map_stack_trace/source_map_stack_trace.dart';
+import 'package:source_maps/source_maps.dart';
+import 'package:source_span/source_span.dart';
+import 'package:stack_trace/stack_trace.dart';
+
+typedef void ReadyCallback();
+
+/// Global object DDC uses to see if a stack trace utility has been registered.
+@JS(r'$dartStackTraceUtility')
+external set dartStackTraceUtility(DartStackTraceUtility value);
+
+typedef String StackTraceMapper(String stackTrace);
+typedef dynamic LoadSourceMaps(List<String> scripts, ReadyCallback callback);
+
+@JS()
+@anonymous
+class DartStackTraceUtility {
+  external factory DartStackTraceUtility(
+      {StackTraceMapper mapper, LoadSourceMaps loadSourceMaps});
+}
+
+/// Source mapping that is waits to parse source maps until they match the uri
+/// of a requested source map.
+///
+/// This improves startup performance compared to using MappingBundle directly.
+/// The unparsed data for the source maps must still be loaded before
+/// LazyMapping is used.
+class LazyMapping extends Mapping {
+  MappingBundle _bundle = new MappingBundle();
+
+  /// Map from url to unparsed source map.
+  Map<String, String> _sourceMaps;
+
+  LazyMapping(this._sourceMaps) {}
+
+  List toJson() => _bundle.toJson();
+
+  SourceMapSpan spanFor(int line, int column,
+      {Map<String, SourceFile> files, String uri}) {
+    if (uri == null) {
+      throw new ArgumentError.notNull('uri');
+    }
+    var rawMap = _sourceMaps[uri];
+
+    if (rawMap != null && rawMap.isNotEmpty && !_bundle.containsMapping(uri)) {
+      SingleMapping mapping = parse(rawMap);
+      mapping
+        ..targetUrl = uri
+        ..sourceRoot = '${path.dirname(uri)}/';
+      _bundle.addMapping(mapping);
+    }
+
+    return _bundle.spanFor(line, column, files: files, uri: uri);
+  }
+}
+
+String _toSourceMapLocation(String url) {
+  // The url may have cache busting query parameters which we need to maintain
+  // in the source map url.
+  // For example:
+  //   http://localhost/foo.js?cachebusting=23419
+  // Should get source map
+  //   http://localhost/foo.js.map?cachebusting=23419
+  var uri = Uri.parse(url);
+  return uri.replace(path: '${uri.path}.map').toString();
+}
+
+/// Load a source map for the specified url.
+///
+/// Returns a null string rather than reporting an error if the file cannot be
+/// found as we don't want to throw errors if a few source maps are missing.
+Future<String> loadSourceMap(String url) async {
+  try {
+    return await HttpRequest.getString(_toSourceMapLocation(url));
+  } catch (e) {
+    return null;
+  }
+}
+
+LazyMapping _mapping;
+
+String mapper(String rawStackTrace) {
+  if (_mapping == null) {
+    // This should not happen if the user has waited for the ReadyCallback
+    // to start the application.
+    throw new StateError('Source maps are not done loading.');
+  }
+  return mapStackTrace(_mapping, new Trace.parse(rawStackTrace)).toString();
+}
+
+Future<Null> loadSourceMaps(
+    List<String> scripts, ReadyCallback callback) async {
+  List<Future<String>> sourceMapFutures =
+      scripts.map((script) => loadSourceMap(script)).toList();
+  List<String> sourceMaps = await Future.wait(sourceMapFutures);
+  _mapping = new LazyMapping(new Map.fromIterables(scripts, sourceMaps));
+  callback();
+}
+
+main() {
+  // Register with DDC.
+  dartStackTraceUtility = new DartStackTraceUtility(
+      mapper: allowInterop(mapper),
+      loadSourceMaps: allowInterop(loadSourceMaps));
+}
diff --git a/pkg/front_end/lib/src/base/errors.dart b/pkg/front_end/lib/src/base/errors.dart
index d39953f..2f9884a 100644
--- a/pkg/front_end/lib/src/base/errors.dart
+++ b/pkg/front_end/lib/src/base/errors.dart
@@ -2,65 +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.
 
-/**
- * An error code associated with an [AnalysisError].
- *
- * Generally, we want to provide messages that consist of three sentences. From
- * the user's perspective these sentences should explain:
- *
- * 1. what is wrong,
- * 2. why is it wrong, and
- * 3. how do I fix it.
- *
- * However, we combine the first two in the [message] and the last in the
- * [correction].
- *
- * When composing messages (including correction messages) keep the following
- * guidelines in mind.
- *
- * 1. The message should be a complete sentence starting with an uppercase
- * letter, and ending with a period.
- *
- * 2. Reserved words and embedded identifiers should be in single quotes, so
- * prefer double quotes for the complete message. For example,
- * ```
- * "The class '{0}' can't use 'super'."
- * ```
- * Notice that the word 'class' in the preceding message is not quoted as it
- * refers to the concept 'class', not the reserved word. On the other hand,
- * 'super' refers to the reserved word. Do not quote 'null' and numeric literals.
- *
- * 3. Do not try to compose messages, as it can make translating them hard.
- *
- * 4. Try to keep the error messages short, but informative.
- *
- * 5. Use simple words and terminology, assume the reader of the message doesn't
- * have an advanced degree in math, and that English is not the reader's native
- * language. Do not assume any formal computer science training. For example, do
- * not use Latin abbreviations (prefer "that is" over "i.e.", and "for example"
- * over "e.g."). Also avoid phrases such as "if and only if" and "iff"; that
- * level of precision is unnecessary.
- *
- * 6. Prefer contractions when they are in common use, for example, prefer
- * "can't" over "cannot". Using "cannot", "must not", "shall not", etc. is
- * off-putting to people new to programming.
- *
- * 7. Use common terminology, preferably from the Dart Language Specification.
- * This increases the user's chance of finding a good explanation on the web.
- *
- * 8. Do not try to be cute or funny. It is extremely frustrating to work on a
- * product that crashes with a "tongue-in-cheek" message, especially if you did
- * not want to use this product to begin with.
- *
- * 9. Do not lie, that is, do not write error messages containing phrases like
- * "can't happen".  If the user ever saw this message, it would be a lie. Prefer
- * messages like: "Internal error: This function should not be called when 'x'
- * is null.".
- *
- * 10. Prefer to not use the imperative tone. That is, the message should not
- * sound accusing or like it is ordering the user around. The computer should
- * describe the problem, not criticize the user for violating the specification.
- */
+/// An error code associated with an [AnalysisError].
+///
+/// Generally, messages should follow the [Guide for Writing
+/// Diagnostics](../fasta/diagnostics.md).
 abstract class ErrorCode {
   /**
    * The name of the error code.
diff --git a/pkg/front_end/lib/src/fasta/analyzer/ast_builder.dart b/pkg/front_end/lib/src/fasta/analyzer/ast_builder.dart
index c2d1c67..13d66e3 100644
--- a/pkg/front_end/lib/src/fasta/analyzer/ast_builder.dart
+++ b/pkg/front_end/lib/src/fasta/analyzer/ast_builder.dart
@@ -26,7 +26,7 @@
         AnalyzerParameterElement,
         ElementStore,
         KernelClassElement;
-import 'token_utils.dart' show toAnalyzerToken;
+import 'token_utils.dart' show toAnalyzerToken, toAnalyzerCommentToken;
 
 class AstBuilder extends ScopeListener {
   final AstFactory ast = standard.astFactory;
@@ -77,8 +77,12 @@
   }
 
   @override
-  void handleNewExpression(Token token) {
-    debugEvent("NewExpression");
+  void handleConstExpression(Token token) {
+    debugEvent("ConstExpression");
+    _handleInstanceCreation(token);
+  }
+
+  void _handleInstanceCreation(Token token) {
     MethodInvocation arguments = pop();
     ConstructorName constructorName = pop();
     push(ast.instanceCreationExpression(
@@ -86,6 +90,12 @@
   }
 
   @override
+  void handleNewExpression(Token token) {
+    debugEvent("NewExpression");
+    _handleInstanceCreation(token);
+  }
+
+  @override
   void handleParenthesizedExpression(BeginGroupToken token) {
     debugEvent("ParenthesizedExpression");
     Expression expression = pop();
@@ -134,6 +144,11 @@
     }
   }
 
+  void handleScript(Token token) {
+    debugEvent("Script");
+    push(ast.scriptTag(toAnalyzerToken(token)));
+  }
+
   void handleStringJuxtaposition(int literalCount) {
     debugEvent("StringJuxtaposition");
     push(ast.adjacentStrings(popList(literalCount)));
@@ -149,8 +164,14 @@
 
   void handleIdentifier(Token token, IdentifierContext context) {
     debugEvent("handleIdentifier");
-    String name = token.value;
-    SimpleIdentifier identifier = ast.simpleIdentifier(toAnalyzerToken(token));
+    analyzer.Token analyzerToken = toAnalyzerToken(token);
+
+    if (context.inSymbol) {
+      push(analyzerToken);
+      return;
+    }
+
+    SimpleIdentifier identifier = ast.simpleIdentifier(analyzerToken);
     if (context.inLibraryOrPartOfDeclaration) {
       if (!context.isContinuation) {
         push([identifier]);
@@ -161,11 +182,11 @@
       // TODO(paulberry): analyzer's ASTs allow for enumerated values to have
       // metadata, but the spec doesn't permit it.
       List<Annotation> metadata;
-      // TODO(paulberry): capture doc comments.  See dartbug.com/28851.
-      Comment comment = null;
+      Comment comment = _toAnalyzerComment(token.precedingComments);
       push(ast.enumConstantDeclaration(comment, metadata, identifier));
     } else {
       if (context.isScopeReference) {
+        String name = token.value;
         Builder builder = scope.lookup(name, token.charOffset, uri);
         if (builder != null) {
           Element element = elementStore[builder];
@@ -263,6 +284,16 @@
     push(receiver);
   }
 
+  void handleOperator(Token token) {
+    debugEvent("Operator");
+    push(toAnalyzerToken(token));
+  }
+
+  void handleSymbolVoid(Token token) {
+    debugEvent("SymbolVoid");
+    push(toAnalyzerToken(token));
+  }
+
   void handleBinaryExpression(Token token) {
     debugEvent("BinaryExpression");
     if (identical(".", token.stringValue) ||
@@ -388,7 +419,7 @@
   void endVariablesDeclaration(int count, Token endToken) {
     debugEvent("VariablesDeclaration");
     List<VariableDeclaration> variables = popList(count);
-    TypeName type = pop();
+    TypeAnnotation type = pop();
     pop(); // TODO(paulberry): Modifiers.
     push(ast.variableDeclarationStatement(
         ast.variableDeclarationList(null, null, null, type, variables),
@@ -487,13 +518,9 @@
     push(ast.mapLiteralEntry(key, toAnalyzerToken(colon), value));
   }
 
-  void endLiteralSymbol(Token hashToken, int identifierCount) {
+  void endLiteralSymbol(Token hashToken, int tokenCount) {
     debugEvent("LiteralSymbol");
-    List<analyzer.Token> components = new List<analyzer.Token>(identifierCount);
-    for (int i = identifierCount - 1; i >= 0; i--) {
-      SimpleIdentifier identifier = pop();
-      components[i] = identifier.token;
-    }
+    List<analyzer.Token> components = popList(tokenCount);
     push(ast.symbolLiteral(toAnalyzerToken(hashToken), components));
   }
 
@@ -521,14 +548,14 @@
 
   void handleAsOperator(Token operator, Token endToken) {
     debugEvent("AsOperator");
-    TypeName type = pop();
+    TypeAnnotation type = pop();
     Expression expression = pop();
     push(ast.asExpression(expression, toAnalyzerToken(operator), type));
   }
 
   void handleIsOperator(Token operator, Token not, Token endToken) {
     debugEvent("IsOperator");
-    TypeName type = pop();
+    TypeAnnotation type = pop();
     Expression expression = pop();
     push(ast.isExpression(
         expression, toAnalyzerToken(operator), toAnalyzerToken(not), type));
@@ -543,6 +570,15 @@
         thenExpression, toAnalyzerToken(colon), elseExpression));
   }
 
+  @override
+  void endRethrowStatement(Token rethrowToken, Token endToken) {
+    debugEvent("RethrowStatement");
+    RethrowExpression expression =
+        ast.rethrowExpression(toAnalyzerToken(rethrowToken));
+    // TODO(scheglov) According to the specification, 'rethrow' is a statement.
+    push(ast.expressionStatement(expression, toAnalyzerToken(endToken)));
+  }
+
   void endThrowExpression(Token throwToken, Token endToken) {
     debugEvent("ThrowExpression");
     push(ast.throwExpression(toAnalyzerToken(throwToken), pop()));
@@ -561,6 +597,15 @@
     push(new _ParameterDefaultValue(equals, value));
   }
 
+  void handleFunctionType(Token functionToken, Token semicolon) {
+    debugEvent("FunctionType");
+    FormalParameterList parameters = pop();
+    TypeParameterList typeParameters = pop();
+    TypeAnnotation returnType = pop();
+    push(ast.genericFunctionType(returnType, toAnalyzerToken(functionToken),
+        typeParameters, parameters));
+  }
+
   void handleFormalParameterWithoutValue(Token token) {
     debugEvent("FormalParameterWithoutValue");
     push(NullValue.ParameterDefaultValue);
@@ -580,12 +625,14 @@
       name = nameOrFunctionTypedParameter.identifier;
     } else {
       name = nameOrFunctionTypedParameter;
-      TypeName type = pop();
+      TypeAnnotation type = pop();
       _Modifiers modifiers = pop();
       Token keyword = modifiers?.finalConstOrVarKeyword;
       pop(); // TODO(paulberry): Metadata.
+      Comment comment = pop();
       if (thisKeyword == null) {
         node = ast.simpleFormalParameter2(
+            comment: comment,
             covariantKeyword: toAnalyzerToken(covariantKeyword),
             keyword: toAnalyzerToken(keyword),
             type: type,
@@ -596,6 +643,7 @@
             ? thisKeyword.next
             : null;
         node = ast.fieldFormalParameter2(
+            comment: comment,
             covariantKeyword: toAnalyzerToken(covariantKeyword),
             keyword: toAnalyzerToken(keyword),
             type: type,
@@ -605,12 +653,16 @@
       }
     }
 
-    if (defaultValue != null) {
-      node = ast.defaultFormalParameter(node, _toAnalyzerParameterKind(kind),
-          toAnalyzerToken(defaultValue.separator), defaultValue.value);
+    ParameterKind analyzerKind = _toAnalyzerParameterKind(kind);
+    if (analyzerKind != ParameterKind.REQUIRED) {
+      node = ast.defaultFormalParameter(node, analyzerKind,
+          toAnalyzerToken(defaultValue?.separator), defaultValue?.value);
     }
 
-    scope[name.name] = name.staticElement = new AnalyzerParameterElement(node);
+    if (name != null) {
+      scope[name.name] =
+          name.staticElement = new AnalyzerParameterElement(node);
+    }
     push(node);
   }
 
@@ -622,7 +674,7 @@
     FormalParameterList formalParameters = pop();
     TypeParameterList typeParameters = pop();
     SimpleIdentifier name = pop();
-    TypeName returnType = pop();
+    TypeAnnotation returnType = pop();
 
     {
       _Modifiers modifiers = pop();
@@ -633,10 +685,12 @@
     }
 
     pop(); // TODO(paulberry): Metadata.
+    Comment comment = pop();
 
     FormalParameter node;
     if (thisKeyword == null) {
       node = ast.functionTypedFormalParameter2(
+          comment: comment,
           covariantKeyword: toAnalyzerToken(covariantKeyword),
           returnType: returnType,
           identifier: name,
@@ -648,6 +702,7 @@
           ? thisKeyword.next
           : null;
       node = ast.fieldFormalParameter2(
+          comment: comment,
           covariantKeyword: toAnalyzerToken(covariantKeyword),
           type: returnType,
           thisKeyword: toAnalyzerToken(thisKeyword),
@@ -691,7 +746,7 @@
     if (catchKeyword != null) {
       exitLocalScope();
     }
-    TypeName type = popIfNotNull(onKeyword);
+    TypeAnnotation type = popIfNotNull(onKeyword);
     SimpleIdentifier exception;
     SimpleIdentifier stackTrace;
     if (catchParameters != null) {
@@ -795,8 +850,7 @@
     _Modifiers modifiers = pop();
     Token externalKeyword = modifiers?.externalKeyword;
     List<Annotation> metadata = pop();
-    // TODO(paulberry): capture doc comments.  See dartbug.com/28851.
-    Comment comment = null;
+    Comment comment = pop();
     push(ast.functionDeclaration(
         comment,
         metadata,
@@ -816,18 +870,23 @@
   void endCompilationUnit(int count, Token token) {
     debugEvent("CompilationUnit");
     analyzer.Token beginToken = null; // TODO(paulberry)
-    ScriptTag scriptTag = null; // TODO(paulberry)
+    ScriptTag scriptTag = null;
     var directives = <Directive>[];
     var declarations = <CompilationUnitMember>[];
     analyzer.Token endToken = null; // TODO(paulberry)
-    for (AstNode node in popList(count)) {
-      if (node is Directive) {
-        directives.add(node);
-      } else if (node is CompilationUnitMember) {
-        declarations.add(node);
-      } else {
-        internalError(
-            'Unrecognized compilation unit member: ${node.runtimeType}');
+    List<Object> elements = popList(count);
+    if (elements != null) {
+      for (AstNode node in elements) {
+        if (node is ScriptTag) {
+          scriptTag = node;
+        } else if (node is Directive) {
+          directives.add(node);
+        } else if (node is CompilationUnitMember) {
+          declarations.add(node);
+        } else {
+          internalError(
+              'Unrecognized compilation unit member: ${node.runtimeType}');
+        }
       }
     }
     push(ast.compilationUnit(
@@ -843,9 +902,8 @@
     List<Configuration> configurations = pop();
     StringLiteral uri = pop();
     List<Annotation> metadata = pop();
-    assert(metadata == null);
-    // TODO(paulberry): capture doc comments.  See dartbug.com/28851.
-    Comment comment = null;
+    assert(metadata == null); // TODO(paulberry): fix.
+    Comment comment = pop();
     push(ast.importDirective(
         comment,
         metadata,
@@ -866,8 +924,7 @@
     StringLiteral uri = pop();
     List<Annotation> metadata = pop();
     assert(metadata == null);
-    // TODO(paulberry): capture doc comments.  See dartbug.com/28851.
-    Comment comment = null;
+    Comment comment = pop();
     push(ast.exportDirective(comment, metadata, toAnalyzerToken(exportKeyword),
         uri, configurations, combinators, toAnalyzerToken(semicolon)));
   }
@@ -983,8 +1040,7 @@
     _Modifiers modifiers = pop();
     Token abstractKeyword = modifiers?.abstractKeyword;
     List<Annotation> metadata = pop();
-    // TODO(paulberry): capture doc comments.  See dartbug.com/28851.
-    Comment comment = null;
+    Comment comment = pop();
     push(ast.classDeclaration(
         comment,
         metadata,
@@ -1001,12 +1057,9 @@
   }
 
   @override
-  void endMixinApplication() {
+  void endMixinApplication(Token withKeyword) {
     debugEvent("MixinApplication");
     List<TypeName> mixinTypes = pop();
-    // TODO(paulberry,ahe): the parser doesn't give us enough information to
-    // locate the "with" keyword.
-    Token withKeyword;
     TypeName supertype = pop();
     push(new _MixinApplication(supertype, withKeyword, mixinTypes));
   }
@@ -1032,8 +1085,7 @@
     _Modifiers modifiers = pop();
     Token abstractKeyword = modifiers?.abstractKeyword;
     List<Annotation> metadata = pop();
-    // TODO(paulberry): capture doc comments.  See dartbug.com/28851.
-    Comment comment = null;
+    Comment comment = pop();
     push(ast.classTypeAlias(
         comment,
         metadata,
@@ -1054,8 +1106,7 @@
     List<SimpleIdentifier> libraryName = pop();
     var name = ast.libraryIdentifier(libraryName);
     List<Annotation> metadata = pop();
-    // TODO(paulberry): capture doc comments.  See dartbug.com/28851.
-    Comment comment = null;
+    Comment comment = pop();
     push(ast.libraryDirective(comment, metadata,
         toAnalyzerToken(libraryKeyword), name, toAnalyzerToken(semicolon)));
   }
@@ -1083,8 +1134,7 @@
     debugEvent("Part");
     StringLiteral uri = pop();
     List<Annotation> metadata = pop();
-    // TODO(paulberry): capture doc comments.  See dartbug.com/28851.
-    Comment comment = null;
+    Comment comment = pop();
     push(ast.partDirective(comment, metadata, toAnalyzerToken(partKeyword), uri,
         toAnalyzerToken(semicolon)));
   }
@@ -1099,8 +1149,7 @@
     // in a reference to the "of" keyword.
     var ofKeyword = partKeyword.next;
     List<Annotation> metadata = pop();
-    // TODO(paulberry): capture doc comments.  See dartbug.com/28851.
-    Comment comment = null;
+    Comment comment = pop();
     push(ast.partOfDirective(comment, metadata, toAnalyzerToken(partKeyword),
         toAnalyzerToken(ofKeyword), uri, name, toAnalyzerToken(semicolon)));
   }
@@ -1141,8 +1190,7 @@
     var variableList = ast.variableDeclarationList(
         null, null, toAnalyzerToken(keyword), type, variables);
     List<Annotation> metadata = pop();
-    // TODO(paulberry): capture doc comments.  See dartbug.com/28851.
-    Comment comment = null;
+    Comment comment = pop();
     push(ast.topLevelVariableDeclaration(
         comment, metadata, variableList, toAnalyzerToken(endToken)));
   }
@@ -1184,8 +1232,7 @@
     TypeAnnotation returnType = pop(); // TODO(paulberry)
     _Modifiers modifiers = pop();
     List<Annotation> metadata = pop();
-    // TODO(paulberry): capture doc comments.  See dartbug.com/28851.
-    Comment comment = null;
+    Comment comment = pop();
     Token period;
     void unnamedConstructor(
         SimpleIdentifier returnType, SimpleIdentifier name) {
@@ -1259,8 +1306,7 @@
       SimpleIdentifier name = pop();
       TypeAnnotation returnType = pop();
       List<Annotation> metadata = pop();
-      // TODO(paulberry): capture doc comments.  See dartbug.com/28851.
-      Comment comment = null;
+      Comment comment = pop();
       push(ast.functionTypeAlias(
           comment,
           metadata,
@@ -1275,8 +1321,7 @@
       TypeParameterList templateParameters = pop();
       SimpleIdentifier name = pop();
       List<Annotation> metadata = pop();
-      // TODO(paulberry): capture doc comments.  See dartbug.com/28851.
-      Comment comment = null;
+      Comment comment = pop();
       if (type is! GenericFunctionType) {
         // TODO(paulberry) Generate an error and recover (better than
         // this).
@@ -1305,8 +1350,7 @@
     Token closeBrace = openBrace.endGroup;
     SimpleIdentifier name = pop();
     List<Annotation> metadata = pop();
-    // TODO(paulberry): capture doc comments.  See dartbug.com/28851.
-    Comment comment = null;
+    Comment comment = pop();
     push(ast.enumDeclaration(
         comment,
         metadata,
@@ -1335,8 +1379,7 @@
     var variableList = ast.variableDeclarationList(null, null,
         toAnalyzerToken(modifiers?.finalConstOrVarKeyword), type, variables);
     List<Annotation> metadata = pop();
-    // TODO(paulberry): capture doc comments.  See dartbug.com/28851.
-    Comment comment = null;
+    Comment comment = pop();
     push(ast.fieldDeclaration2(
         comment: comment,
         metadata: metadata,
@@ -1353,6 +1396,16 @@
         ast.simpleIdentifier(toAnalyzerToken(token), isDeclaration: true)));
   }
 
+  @override
+  void beginMetadataStar(Token token) {
+    debugEvent("beginMetadataStar");
+    if (token.precedingComments != null) {
+      push(_toAnalyzerComment(token.precedingComments));
+    } else {
+      push(NullValue.Comments);
+    }
+  }
+
   ParameterKind _toAnalyzerParameterKind(FormalParameterType type) {
     if (type == FormalParameterType.POSITIONAL) {
       return ParameterKind.POSITIONAL;
@@ -1362,6 +1415,19 @@
       return ParameterKind.REQUIRED;
     }
   }
+
+  Comment _toAnalyzerComment(Token comments) {
+    if (comments == null) return null;
+
+    // This is temporary placeholder code to get tests to pass.
+    // TODO(paulberry): after analyzer and fasta token representations are
+    // unified, refactor the code in analyzer's parser that handles
+    // documentation comments so that it is reusable, and reuse it here.
+    // See Parser.parseCommentAndMetadata
+    var tokens = <analyzer.Token>[toAnalyzerCommentToken(comments)];
+    var references = <CommentReference>[];
+    return ast.documentationComment(tokens, references);
+  }
 }
 
 /// Data structure placed on the stack to represent a class body.
diff --git a/pkg/front_end/lib/src/fasta/analyzer/token_utils.dart b/pkg/front_end/lib/src/fasta/analyzer/token_utils.dart
index 4d7ccc2..302accc 100644
--- a/pkg/front_end/lib/src/fasta/analyzer/token_utils.dart
+++ b/pkg/front_end/lib/src/fasta/analyzer/token_utils.dart
@@ -54,14 +54,6 @@
   /// tokens have been generated yet.
   analyzer.Token _analyzerTokenTail;
 
-  /// If a sequence of consecutive comment tokens is being processed, the first
-  /// translated analyzer comment token.  Otherwise `null`.
-  analyzer.CommentToken _currentCommentHead;
-
-  /// If a sequence of consecutive comment tokens is being processed, the last
-  /// translated analyzer comment token.  Otherwise `null`.
-  analyzer.CommentToken _currentCommentTail;
-
   /// Stack of analyzer "begin" tokens which need to be linked up to
   /// corresponding "end" tokens once those tokens are translated.
   ///
@@ -86,8 +78,6 @@
     _analyzerTokenHead = new analyzer.Token(TokenType.EOF, -1);
     _analyzerTokenHead.previous = _analyzerTokenHead;
     _analyzerTokenTail = _analyzerTokenHead;
-    _currentCommentHead = null;
-    _currentCommentTail = null;
     _beginTokenStack = [null];
     _endTokenStack = <Token>[null];
 
@@ -95,19 +85,11 @@
       if (token.info.kind == BAD_INPUT_TOKEN) {
         ErrorToken errorToken = token;
         _translateErrorToken(errorToken);
-      } else if (token.info.kind == COMMENT_TOKEN) {
-        var translatedToken = translateCommentToken(token);
-        if (_currentCommentHead == null) {
-          _currentCommentHead = _currentCommentTail = translatedToken;
-        } else {
-          _currentCommentTail.setNext(translatedToken);
-          _currentCommentTail = translatedToken;
-        }
       } else {
-        var translatedToken = translateToken(token, _currentCommentHead);
+        var translatedToken = translateToken(
+            token, translateCommentTokens(token.precedingComments));
         _matchGroups(token, translatedToken);
         translatedToken.setNext(translatedToken);
-        _currentCommentHead = _currentCommentTail = null;
         _analyzerTokenTail.setNext(translatedToken);
         translatedToken.previous = _analyzerTokenTail;
         _analyzerTokenTail = translatedToken;
@@ -125,15 +107,20 @@
   void reportError(analyzer.ScannerErrorCode errorCode, int offset,
       List<Object> arguments) {}
 
-  /// Translates a single fasta comment token to the corresponding analyzer
-  /// token.
-  analyzer.CommentToken translateCommentToken(Token token) {
-    // TODO(paulberry,ahe): It would be nice if the scanner gave us an
-    // easier way to distinguish between the two types of comment.
-    var type = token.value.startsWith('/*')
-        ? TokenType.MULTI_LINE_COMMENT
-        : TokenType.SINGLE_LINE_COMMENT;
-    return new analyzer.CommentToken(type, token.value, token.charOffset);
+  /// Translates a sequence of fasta comment tokens to the corresponding
+  /// analyzer tokens.
+  analyzer.CommentToken translateCommentTokens(Token token) {
+    analyzer.CommentToken head;
+    if (token != null) {
+      head = toAnalyzerCommentToken(token);
+      analyzer.CommentToken tail = head;
+      token = token.next;
+      while (token != null) {
+        tail = tail.setNext(toAnalyzerCommentToken(token));
+        token = token.next;
+      }
+    }
+    return head;
   }
 
   /// Translates a single fasta non-comment token to the corresponding analyzer
@@ -225,6 +212,16 @@
   }
 }
 
+/// Converts a single Fasta comment token to an analyzer comment token.
+analyzer.CommentToken toAnalyzerCommentToken(Token token) {
+  // TODO(paulberry,ahe): It would be nice if the scanner gave us an
+  // easier way to distinguish between the two types of comment.
+  var type = token.value.startsWith('/*')
+      ? TokenType.MULTI_LINE_COMMENT
+      : TokenType.SINGLE_LINE_COMMENT;
+  return new analyzer.CommentToken(type, token.value, token.charOffset);
+}
+
 /// Converts a stream of Analyzer tokens (starting with [token] and continuing
 /// to EOF) to a stream of Fasta tokens.
 ///
@@ -277,22 +274,40 @@
     }
   }
 
+  Token translateComments(analyzer.Token token) {
+    if (token == null) {
+      return null;
+    }
+    Token head = fromAnalyzerToken(token);
+    Token tail = head;
+    token = token.next;
+    while (token != null) {
+      tail.next = fromAnalyzerToken(token);
+      tail.next.previousToken = tail;
+      tail = tail.next;
+      token = token.next;
+    }
+    return head;
+  }
+
   analyzer.Token translateAndAppend(analyzer.Token analyzerToken) {
     var token = fromAnalyzerToken(analyzerToken);
+    token.precedingComments =
+        translateComments(analyzerToken.precedingComments);
     tokenTail.next = token;
+    tokenTail.next.previousToken = tokenTail;
     tokenTail = token;
     matchGroups(analyzerToken, token);
     return analyzerToken.next;
   }
 
   while (true) {
-    analyzer.Token commentToken = analyzerToken.precedingComments;
-    while (commentToken != null) {
-      commentToken = translateAndAppend(commentToken);
-    }
     // TODO(paulberry): join up begingroup/endgroup.
     if (analyzerToken.type == TokenType.EOF) {
       tokenTail.next = new SymbolToken(EOF_INFO, analyzerToken.offset);
+      tokenTail.next.previousToken = tokenTail;
+      tokenTail.next.precedingComments =
+          translateComments(analyzerToken.precedingComments);
       return tokenHead.next;
     }
     analyzerToken = translateAndAppend(analyzerToken);
@@ -547,6 +562,9 @@
       }
       break;
 
+    case SCRIPT_TOKEN:
+      return makeStringToken(TokenType.SCRIPT_TAG);
+
     case STRING_TOKEN:
       return makeStringToken(TokenType.STRING);
 
diff --git a/pkg/front_end/lib/src/fasta/builder/builder.dart b/pkg/front_end/lib/src/fasta/builder/builder.dart
index 666ac09..5b2418b 100644
--- a/pkg/front_end/lib/src/fasta/builder/builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/builder.dart
@@ -54,6 +54,8 @@
 
 export 'dynamic_type_builder.dart' show DynamicTypeBuilder;
 
+export 'function_type_builder.dart' show FunctionTypeBuilder;
+
 import 'library_builder.dart' show LibraryBuilder;
 
 abstract class Builder {
diff --git a/pkg/front_end/lib/src/fasta/builder/function_type_builder.dart b/pkg/front_end/lib/src/fasta/builder/function_type_builder.dart
new file mode 100644
index 0000000..4b66b4c
--- /dev/null
+++ b/pkg/front_end/lib/src/fasta/builder/function_type_builder.dart
@@ -0,0 +1,43 @@
+// Copyright (c) 2017, 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.function_type_builder;
+
+import 'builder.dart' show LibraryBuilder, TypeBuilder, TypeDeclarationBuilder;
+
+import 'scope.dart' show Scope;
+
+abstract class FunctionTypeBuilder extends TypeBuilder {
+  final TypeBuilder returnType;
+  final List typeVariables;
+  final List formals;
+
+  FunctionTypeBuilder(int charOffset, Uri fileUri, this.returnType,
+      this.typeVariables, this.formals)
+      : super(charOffset, fileUri);
+
+  @override
+  void resolveIn(Scope scope) {}
+
+  @override
+  void bind(TypeDeclarationBuilder builder) {}
+
+  @override
+  String get name => null;
+
+  @override
+  String get debugName => "Function";
+
+  @override
+  StringBuffer printOn(StringBuffer buffer) {
+    buffer.write(typeVariables);
+    buffer.write(formals);
+    buffer.write(" -> ");
+    buffer.write(returnType);
+    return buffer;
+  }
+
+  @override
+  build(LibraryBuilder library) {}
+}
diff --git a/pkg/front_end/lib/src/fasta/builder/named_type_builder.dart b/pkg/front_end/lib/src/fasta/builder/named_type_builder.dart
index 0956e6e..62c7f73 100644
--- a/pkg/front_end/lib/src/fasta/builder/named_type_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/named_type_builder.dart
@@ -2,7 +2,7 @@
 // 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.interface_type_builder;
+library fasta.named_type_builder;
 
 import 'scope.dart' show Scope;
 
diff --git a/pkg/front_end/lib/src/fasta/compiler_command_line.dart b/pkg/front_end/lib/src/fasta/compiler_command_line.dart
index 5874bc3..38f09d7 100644
--- a/pkg/front_end/lib/src/fasta/compiler_command_line.dart
+++ b/pkg/front_end/lib/src/fasta/compiler_command_line.dart
@@ -32,6 +32,8 @@
 
   bool get dumpIr => options.containsKey("--dump-ir");
 
+  bool get includeSource => options.containsKey("--include-source");
+
   bool get help {
     return options.containsKey("--help") ||
         options.containsKey("-h") ||
@@ -167,6 +169,9 @@
   --dump-ir
     Print compiled libraries in Kernel source notation.
 
+  --include-source
+    Include source code in the dill file. Used for debugging.
+
   --compile-sdk=<patched_sdk>
     Compile the SDK from scratch instead of reading it from 'platform.dill'.
 
diff --git a/pkg/front_end/lib/src/fasta/diagnostics.md b/pkg/front_end/lib/src/fasta/diagnostics.md
new file mode 100644
index 0000000..d3711ec
--- /dev/null
+++ b/pkg/front_end/lib/src/fasta/diagnostics.md
@@ -0,0 +1,94 @@
+<!--
+  -- Copyright (c) 2017, 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.
+  -->
+
+<!--
+  -- Note: if you move this file to a different location, please make sure that
+  -- you also update these references to it:
+  --  * pkg/compiler/lib/src/diagnostics/messages.dart
+  --  * pkg/dart_messages/lib/shared_messages.dart
+  --  * pkg/front_end/lib/src/base/errors.dart
+  --  * https://github.com/dart-lang/linter/
+  -->
+
+# Guide for Writing Diagnostics
+
+## The Rule of 3
+
+A great message conveys the following three things:
+
+1. What is wrong?
+2. Why is it wrong?
+3. How do I fix it?
+
+## Complete Sentences
+
+The message should be a complete sentence starting with an uppercase letter, and ending with a period. The message shouldn't start with "error:", "warning:", and so on.
+
+## Use Single Quotes in Messages
+
+Reserved words and embedded identifiers should be in single quotes as we have found those are ignored by search engines whereas double quotes can have meaning in search engines.
+
+In practice, this means that messages written in Dart source code should be written in double quotes, which makes it easier to use single quotes inside the message. For example:
+
+    "The class '#{className}' can't use 'super'."
+
+Notice that the word "class" in the preceding message is not quoted as it refers to the concept *class*, not the reserved word. On the other hand, `'super'` refers to the reserved word. Do not quote `null` and numeric literals.
+
+Also, remember that the output isn't Markdown, so be careful to not use Markdown syntax. In particular, do not use <code>\`</code> (backtick) for quoting.
+
+## Avoid Composing Messages Programmatically
+
+Composing messages programmatically can make it hard to translate them.
+
+## Keep Message Short
+
+Try to keep the error messages short, but informative.
+
+## Simple Words and Terminology
+
+Use simple words and terminology.
+
+Do not assume that
+
+* English is the reader's native language,
+* the reader has any formal computer science training, or
+* the reader has an advanced degree in mathematics.
+
+Similarly, do not use Latin abbreviations (prefer "that is" over "i.e.," and "for example" over "e.g."). Also avoid phrases such as "if and only if" and "iff"; that level of precision is unnecessary.
+
+## Prefer Contractions
+
+Prefer contractions when they are in common use, for example, prefer "can't" over "cannot". Using "cannot", "must not", "shall not", and so on, is off-putting to people new to programming.
+
+## Use Common Terminology
+
+Use common terminology, for example, from the [Dart Language Specification](https://www.dartlang.org/guides/language/spec). This increases the user's chance of finding a good explanation on the web. Do not invent your own terminology or obscure terminology. For example, "rune" isn't a great way to describe a Unicode code point (albeit, code points and code units can be confusing).
+
+## Don't Try to be Cute or Funny
+
+It is extremely frustrating to work on a product that crashes with a tongue-in-cheek message, especially if you did not want to use this product to begin with.
+
+## Things Can Happen
+
+Do not lie, that is, do not write error messages containing phrases like "can't happen".  If the user ever saw this message, it would be a lie. Prefer messages like:
+
+    "Internal error: This function shouldn't be called when 'x' is null.".
+
+## Avoid Imperative Tone
+
+Prefer to not use imperative tone. That is, the message should not sound accusing or like it is ordering the user around. The computer should describe the problem, not criticize for violating the specification. Often, it's as simple as adding the word "try". For example:
+
+    "Try changing the return type." // Preferred.
+
+Versus:
+
+    "Change the return type." // Avoid this.
+
+Notice that the style of the language in which this guide is written, is mostly imperative. That's not an example to follow when writing diagnostics.
+
+## Other Resources
+
+One language and community where good error messages have been discussed intensively is [Elm](http://elm-lang.org/blog/compiler-errors-for-humans).
diff --git a/pkg/front_end/lib/src/fasta/dill/dill_target.dart b/pkg/front_end/lib/src/fasta/dill/dill_target.dart
index 5bc79ab..70629fb 100644
--- a/pkg/front_end/lib/src/fasta/dill/dill_target.dart
+++ b/pkg/front_end/lib/src/fasta/dill/dill_target.dart
@@ -31,7 +31,8 @@
     loader = new DillLoader(this);
   }
 
-  void addLineStarts(Uri uri, List<int> lineStarts) {
+  void addSourceInformation(
+      Uri uri, List<int> lineStarts, List<int> sourceCode) {
     internalError("Unsupported operation.");
   }
 
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 532feca..afcabb0 100644
--- a/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
@@ -812,6 +812,11 @@
   }
 
   @override
+  void handleScript(Token token) {
+    debugEvent("Script");
+  }
+
+  @override
   void handleStringJuxtaposition(int literalCount) {
     debugEvent("StringJuxtaposition");
     List<Expression> parts = popListForValue(literalCount);
@@ -2235,6 +2240,11 @@
     push(new Operator(token.stringValue)..fileOffset = token.charOffset);
   }
 
+  @override
+  void handleSymbolVoid(Token token) {
+    logEvent("SymbolVoid");
+  }
+
   dynamic addCompileTimeError(int charOffset, String message) {
     return library.addCompileTimeError(charOffset, message, uri);
   }
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_builder.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_builder.dart
index c2f6b10..f828c7e 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_builder.dart
@@ -12,6 +12,8 @@
 
 export 'kernel_formal_parameter_builder.dart' show KernelFormalParameterBuilder;
 
+export 'kernel_function_type_builder.dart' show KernelFunctionTypeBuilder;
+
 export 'kernel_function_type_alias_builder.dart'
     show KernelFunctionTypeAliasBuilder;
 
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_enum_builder.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_enum_builder.dart
index 4261723..2e660fd 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_enum_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_enum_builder.dart
@@ -75,8 +75,13 @@
       : super(metadata, 0, name, null, null, null, members, parent, null,
             charOffset, cls);
 
-  factory KernelEnumBuilder(List<MetadataBuilder> metadata, String name,
-      List<String> constants, KernelLibraryBuilder parent, int charOffset) {
+  factory KernelEnumBuilder(
+      List<MetadataBuilder> metadata,
+      String name,
+      List<String> constants,
+      KernelLibraryBuilder parent,
+      int charOffset,
+      int charEndOffset) {
     constants ??= const <String>[];
     // TODO(ahe): These types shouldn't be looked up in scope, they come
     // directly from dart:core.
@@ -114,7 +119,8 @@
               null, 0, intType, "index", true, parent, charOffset)
         ],
         parent,
-        charOffset);
+        charOffset,
+        charEndOffset);
     members[""] = constructorBuilder;
     int index = 0;
     List<MapEntry> toStringEntries = <MapEntry>[];
@@ -131,7 +137,8 @@
         AsyncMarker.Sync,
         ProcedureKind.Method,
         parent,
-        charOffset);
+        charOffset,
+        charEndOffset);
     members["toString"] = toStringBuilder;
     String className = name;
     for (String name in constants) {
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_function_type_builder.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_function_type_builder.dart
new file mode 100644
index 0000000..7f7d4fc
--- /dev/null
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_function_type_builder.dart
@@ -0,0 +1,26 @@
+// Copyright (c) 2017, 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_function_type_builder;
+
+import 'package:kernel/ast.dart' show DartType, DynamicType, Supertype;
+
+import 'kernel_builder.dart'
+    show FunctionTypeBuilder, KernelTypeBuilder, LibraryBuilder;
+
+class KernelFunctionTypeBuilder extends FunctionTypeBuilder
+    implements KernelTypeBuilder {
+  KernelFunctionTypeBuilder(int charOffset, Uri fileUri,
+      KernelTypeBuilder returnType, List typeVariables, List formals)
+      : super(charOffset, fileUri, returnType, typeVariables, formals);
+
+  // TODO(ahe): Return a proper function type.
+  DartType build(LibraryBuilder library) => const DynamicType();
+
+  Supertype buildSupertype(LibraryBuilder library) {
+    library.addCompileTimeError(
+        charOffset, "Can't use a function type as supertype.", fileUri);
+    return null;
+  }
+}
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_library_builder.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_library_builder.dart
index c2d6b22..4eac6a1 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_library_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_library_builder.dart
@@ -34,6 +34,7 @@
         KernelFieldBuilder,
         KernelFormalParameterBuilder,
         KernelFunctionTypeAliasBuilder,
+        KernelFunctionTypeBuilder,
         KernelInvalidTypeBuilder,
         KernelMixinApplicationBuilder,
         KernelNamedMixinApplicationBuilder,
@@ -162,6 +163,7 @@
       AsyncMarker asyncModifier,
       ProcedureKind kind,
       int charOffset,
+      int charEndOffset,
       String nativeMethodName,
       {bool isTopLevel}) {
     // Nested declaration began in `OutlineBuilder.beginMethod` or
@@ -180,6 +182,7 @@
           formals,
           this,
           charOffset,
+          charEndOffset,
           nativeMethodName);
     } else {
       procedure = new KernelProcedureBuilder(
@@ -193,6 +196,7 @@
           kind,
           this,
           charOffset,
+          charEndOffset,
           nativeMethodName);
     }
     addBuilder(name, procedure, charOffset);
@@ -209,6 +213,7 @@
       AsyncMarker asyncModifier,
       ConstructorReferenceBuilder redirectionTarget,
       int charOffset,
+      int charEndOffset,
       String nativeMethodName) {
     // Nested declaration began in `OutlineBuilder.beginFactoryMethod`.
     DeclarationBuilder<KernelTypeBuilder> factoryDeclaration =
@@ -228,6 +233,7 @@
         ProcedureKind.Factory,
         this,
         charOffset,
+        charEndOffset,
         nativeMethodName,
         redirectionTarget);
     currentDeclaration.addFactoryDeclaration(procedure, factoryDeclaration);
@@ -238,10 +244,11 @@
   }
 
   void addEnum(List<MetadataBuilder> metadata, String name,
-      List<String> constants, int charOffset) {
+      List<String> constants, int charOffset, int charEndOffset) {
     addBuilder(
         name,
-        new KernelEnumBuilder(metadata, name, constants, this, charOffset),
+        new KernelEnumBuilder(
+            metadata, name, constants, this, charOffset, charEndOffset),
         charOffset);
   }
 
@@ -259,6 +266,15 @@
     addBuilder(name, typedef, charOffset);
   }
 
+  KernelFunctionTypeBuilder addFunctionType(
+      KernelTypeBuilder returnType,
+      List<TypeVariableBuilder> typeVariables,
+      List<FormalParameterBuilder> formals,
+      int charOffset) {
+    return new KernelFunctionTypeBuilder(
+        charOffset, fileUri, returnType, typeVariables, formals);
+  }
+
   KernelFormalParameterBuilder addFormalParameter(
       List<MetadataBuilder> metadata,
       int modifiers,
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_procedure_builder.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_procedure_builder.dart
index cd8ee41..e584e09 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_procedure_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_procedure_builder.dart
@@ -191,10 +191,13 @@
       ProcedureKind kind,
       KernelLibraryBuilder compilationUnit,
       int charOffset,
+      int charEndOffset,
       [String nativeMethodName,
       this.redirectionTarget])
       : procedure = new Procedure(null, kind, null,
-            fileUri: compilationUnit?.relativeFileUri),
+            fileUri: compilationUnit?.relativeFileUri)
+          ..fileOffset = charOffset
+          ..fileEndOffset = charEndOffset,
         super(metadata, modifiers, returnType, name, typeVariables, formals,
             compilationUnit, charOffset, nativeMethodName);
 
@@ -239,7 +242,7 @@
 
 // TODO(ahe): Move this to own file?
 class KernelConstructorBuilder extends KernelFunctionBuilder {
-  final Constructor constructor = new Constructor(null);
+  final Constructor constructor;
 
   bool hasMovedSuperInitializer = false;
 
@@ -256,8 +259,12 @@
       List<FormalParameterBuilder> formals,
       KernelLibraryBuilder compilationUnit,
       int charOffset,
+      int charEndOffset,
       [String nativeMethodName])
-      : super(metadata, modifiers, returnType, name, typeVariables, formals,
+      : constructor = new Constructor(null)
+          ..fileOffset = charOffset
+          ..fileEndOffset = charEndOffset,
+        super(metadata, modifiers, returnType, name, typeVariables, formals,
             compilationUnit, charOffset, nativeMethodName);
 
   bool get isInstanceMember => false;
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 93ef761..babe86b 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart
@@ -72,8 +72,6 @@
     show
         Builder,
         ClassBuilder,
-        DynamicTypeBuilder,
-        InvalidTypeBuilder,
         KernelClassBuilder,
         KernelLibraryBuilder,
         KernelNamedTypeBuilder,
@@ -106,9 +104,10 @@
 
   SourceLoader<Library> createLoader() => new SourceLoader<Library>(this);
 
-  void addLineStarts(Uri uri, List<int> lineStarts) {
+  void addSourceInformation(
+      Uri uri, List<int> lineStarts, List<int> sourceCode) {
     String fileUri = relativizeUri(uri);
-    uriToSource[fileUri] = new Source(lineStarts, fileUri);
+    uriToSource[fileUri] = new Source(lineStarts, sourceCode);
   }
 
   void read(Uri uri) {
@@ -293,6 +292,7 @@
           AsyncMarker.Sync,
           ProcedureKind.Method,
           library,
+          -1,
           -1);
       library.addBuilder(mainBuilder.name, mainBuilder, -1);
       mainBuilder.body = new ExpressionStatement(
@@ -317,7 +317,7 @@
     // TODO(ahe): Remove this line. Kernel seems to generate a default line map
     // that used when there's no fileUri on an element. Instead, ensure all
     // elements have a fileUri.
-    uriToSource[""] = new Source(<int>[0], "");
+    uriToSource[""] = new Source(<int>[0], const <int>[]);
     Program program = new Program(libraries, uriToSource);
     if (loader.first != null) {
       Builder builder = loader.first.members["main"];
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 9a9d774..276bd0b 100644
--- a/pkg/front_end/lib/src/fasta/parser/identifier_context.dart
+++ b/pkg/front_end/lib/src/fasta/parser/identifier_context.dart
@@ -200,12 +200,13 @@
   /// Identifier is the start of a reference occurring in a literal symbol (e.g.
   /// `foo` in `#foo`).
   static const literalSymbol =
-      const IdentifierContext._('literalSymbol', isScopeReference: 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._(
       'literalSymbolContinuation',
+      inSymbol: true,
       isContinuation: true);
 
   /// Identifier appears in an expression, and it does not immediately follow a
@@ -236,6 +237,9 @@
   /// declaration.
   final bool inLibraryOrPartOfDeclaration;
 
+  /// Indicates whether the identifier is within a symbol literal.
+  final bool inSymbol;
+
   /// Indicates whether the identifier follows a `.`.
   final bool isContinuation;
 
@@ -244,6 +248,7 @@
 
   const IdentifierContext._(this._name,
       {this.inLibraryOrPartOfDeclaration: false,
+      this.inSymbol: false,
       this.isContinuation: false,
       this.isScopeReference: false});
 
diff --git a/pkg/front_end/lib/src/fasta/parser/listener.dart b/pkg/front_end/lib/src/fasta/parser/listener.dart
index 3c6c236..a9c1ef6 100644
--- a/pkg/front_end/lib/src/fasta/parser/listener.dart
+++ b/pkg/front_end/lib/src/fasta/parser/listener.dart
@@ -284,7 +284,7 @@
   /// Substructures:
   /// - supertype
   /// - mixin types (TypeList)
-  void endMixinApplication() {
+  void endMixinApplication(Token withKeyword) {
     logEvent("MixinApplication");
   }
 
@@ -680,6 +680,12 @@
     logEvent("NoName");
   }
 
+  /// Handle the end of a generic function type declaration.
+  ///
+  /// Substructures:
+  /// - Return type
+  /// - Type variables
+  /// - Formal parameters
   void handleFunctionType(Token functionToken, Token endToken) {
     logEvent("FunctionType");
   }
@@ -875,6 +881,10 @@
     logEvent("Operator");
   }
 
+  void handleSymbolVoid(Token token) {
+    logEvent("SymbolVoid");
+  }
+
   /// Handle the end of a construct of the form "operator <token>".
   void handleOperatorName(Token operatorKeyword, Token token) {
     logEvent("OperatorName");
@@ -967,6 +977,10 @@
     recoverableErrors
         .add(new ParserError.fromTokens(token, token, kind, arguments));
   }
+
+  void handleScript(Token token) {
+    logEvent("Script");
+  }
 }
 
 class ParserError {
diff --git a/pkg/front_end/lib/src/fasta/parser/parser.dart b/pkg/front_end/lib/src/fasta/parser/parser.dart
index ce6741a..ecbe483 100644
--- a/pkg/front_end/lib/src/fasta/parser/parser.dart
+++ b/pkg/front_end/lib/src/fasta/parser/parser.dart
@@ -27,7 +27,8 @@
         PrecedenceInfo,
         QUESTION_INFO,
         QUESTION_PERIOD_INFO,
-        RELATIONAL_PRECEDENCE;
+        RELATIONAL_PRECEDENCE,
+        SCRIPT_INFO;
 
 import '../scanner/token.dart'
     show
@@ -137,6 +138,9 @@
   }
 
   Token _parseTopLevelDeclaration(Token token) {
+    if (identical(token.info, SCRIPT_INFO)) {
+      return parseScript(token);
+    }
     token = parseMetadataStar(token);
     final String value = token.stringValue;
     if ((identical(value, 'abstract') && optional('class', token.next)) ||
@@ -390,6 +394,11 @@
     return token;
   }
 
+  Token parseScript(Token token) {
+    listener.handleScript(token);
+    return token.next;
+  }
+
   Token parseTypedef(Token token) {
     Token typedefKeyword = token;
     listener.beginFunctionTypeAlias(token);
@@ -413,9 +422,10 @@
   Token parseMixinApplication(Token token) {
     listener.beginMixinApplication(token);
     token = parseType(token);
+    Token withKeyword = token;
     token = expect('with', token);
     token = parseTypeList(token);
-    listener.endMixinApplication();
+    listener.endMixinApplication(withKeyword);
     return token;
   }
 
@@ -2955,6 +2965,10 @@
       listener.handleOperator(token);
       listener.endLiteralSymbol(hashToken, 1);
       return token.next;
+    } else if (identical(token.stringValue, 'void')) {
+      listener.handleSymbolVoid(token);
+      listener.endLiteralSymbol(hashToken, 1);
+      return token.next;
     } else {
       int count = 1;
       token = parseIdentifier(token, IdentifierContext.literalSymbol);
diff --git a/pkg/front_end/lib/src/fasta/parser/token_stream_rewriter.dart b/pkg/front_end/lib/src/fasta/parser/token_stream_rewriter.dart
new file mode 100644
index 0000000..39893c2
--- /dev/null
+++ b/pkg/front_end/lib/src/fasta/parser/token_stream_rewriter.dart
@@ -0,0 +1,104 @@
+// Copyright (c) 2017, 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:front_end/src/fasta/errors.dart';
+import 'package:front_end/src/fasta/scanner/precedence.dart';
+import 'package:front_end/src/fasta/scanner/token.dart';
+
+/// Provides the capability of inserting tokens into a token stream by rewriting
+/// the previous token to point to the inserted token.
+///
+/// This class has been designed to take advantage of "previousToken" pointers
+/// when they are present, but not to depend on them.  When they are not
+/// present, it uses heuristics to try to find the find the previous token as
+/// quickly as possible by walking through tokens starting at the start of the
+/// file.
+class TokenStreamRewriter {
+  /// Synthetic token whose "next" pointer points to the first token in the
+  /// stream.
+  final Token _head;
+
+  /// The token whose "next" pointer was updated in the last call to
+  /// [insertTokenBefore].  This can often be used as a starting point to find
+  /// the a future insertion point quickly.
+  Token _lastPreviousToken;
+
+  /// Creates a [TokenStreamRewriter] which is prepared to rewrite the token
+  /// stream whose first token is [firstToken].
+  TokenStreamRewriter(Token firstToken)
+      : _head = firstToken.previousToken ??
+            (new SymbolToken(EOF_INFO, -1)..next = firstToken);
+
+  /// Gets the first token in the stream (which may not be the same token that
+  /// was passed to the constructor, if something was inserted before it).
+  Token get firstToken => _head.next;
+
+  /// Inserts [newToken] into the token stream just before [insertionPoint], and
+  /// fixes up all "next" and "previous" pointers.
+  ///
+  /// Caller is required to ensure that [insertionPoint] is actually present in
+  /// the token stream.
+  void insertTokenBefore(Token newToken, Token insertionPoint) {
+    Token previous = _findPreviousToken(insertionPoint);
+    _lastPreviousToken = previous;
+    newToken.next = insertionPoint;
+    previous.next = newToken;
+    // Note: even though previousToken is deprecated, we need to hook it up in
+    // case any uses of it remain.  Once previousToken is removed it should be
+    // safe to remove the code below.
+    insertionPoint.previousToken = newToken;
+    newToken.previousToken = previous;
+  }
+
+  /// Finds the token that immediately precedes [target].
+  Token _findPreviousToken(Token target) {
+    // First see if the target has a previous token pointer.  If it does, then
+    // we can find the previous token with no extra effort.  Note: it's ok that
+    // we're accessing the deprecated member previousToken here, because we have
+    // a fallback if it is not available.  Once previousToken is removed, we can
+    // remove the "if" test below, and always use the fallback code.
+    if (target.previousToken != null) {
+      return target.previousToken;
+    }
+
+    // Look for the previous token by scanning forward from [lastPreviousToken],
+    // if it makes sense to do so.
+    if (_lastPreviousToken != null &&
+        target.charOffset >= _lastPreviousToken.charOffset) {
+      Token previous = _scanForPreviousToken(target, _lastPreviousToken);
+      if (previous != null) return previous;
+    }
+
+    // Otherwise scan forward from the start of the token stream.
+    Token previous = _scanForPreviousToken(target, _head);
+    if (previous == null) {
+      internalError('Could not find previous token');
+    }
+    return previous;
+  }
+
+  /// Searches for the token that immediately precedes [target], using [pos] as
+  /// a starting point.
+  ///
+  /// Uses heuristics to skip matching {}, [], (), and <> if possible.
+  ///
+  /// If no such token is found, returns `null`.
+  Token _scanForPreviousToken(Token target, Token pos) {
+    while (!identical(pos.next, target)) {
+      Token nextPos;
+      if (pos is BeginGroupToken &&
+          pos.endGroup != null &&
+          pos.endGroup.charOffset < target.charOffset) {
+        nextPos = pos.endGroup;
+      } else {
+        nextPos = pos.next;
+        if (nextPos == null || nextPos.charOffset > target.charOffset) {
+          return null;
+        }
+      }
+      pos = nextPos;
+    }
+    return pos;
+  }
+}
diff --git a/pkg/front_end/lib/src/fasta/scanner/abstract_scanner.dart b/pkg/front_end/lib/src/fasta/scanner/abstract_scanner.dart
index 68a7adb..8a606ca 100644
--- a/pkg/front_end/lib/src/fasta/scanner/abstract_scanner.dart
+++ b/pkg/front_end/lib/src/fasta/scanner/abstract_scanner.dart
@@ -49,6 +49,18 @@
    */
   Token tail;
 
+  /**
+   * A pointer to the stream of comment tokens created by this scanner
+   * before they are assigned to the [Token] precedingComments field
+   * of a non-comment token. A value of `null` indicates no comment tokens.
+   */
+  Token comments;
+
+  /**
+   * A pointer to the last scanned comment token or `null` if none.
+   */
+  Token commentsTail;
+
   final List<int> lineStarts;
 
   AbstractScanner(this.includeComments, {int numberOfBytesHint})
@@ -226,19 +238,71 @@
       return next;
     }
 
-    if ($a <= next && next <= $z) {
+    int nextLower = next | 0x20;
+
+    if ($a <= nextLower && nextLower <= $z) {
       if (identical($r, next)) {
         return tokenizeRawStringKeywordOrIdentifier(next);
       }
       return tokenizeKeywordOrIdentifier(next, true);
     }
 
-    if (($A <= next && next <= $Z) ||
-        identical(next, $_) ||
-        identical(next, $$)) {
+    if (identical(next, $CLOSE_PAREN)) {
+      return appendEndGroup(CLOSE_PAREN_INFO, OPEN_PAREN_TOKEN);
+    }
+
+    if (identical(next, $OPEN_PAREN)) {
+      appendBeginGroup(OPEN_PAREN_INFO);
+      return advance();
+    }
+
+    if (identical(next, $SEMICOLON)) {
+      appendPrecedenceToken(SEMICOLON_INFO);
+      // Type parameters and arguments cannot contain semicolon.
+      discardOpenLt();
+      return advance();
+    }
+
+    if (identical(next, $PERIOD)) {
+      return tokenizeDotsOrNumber(next);
+    }
+
+    if (identical(next, $COMMA)) {
+      appendPrecedenceToken(COMMA_INFO);
+      return advance();
+    }
+
+    if (identical(next, $EQ)) {
+      return tokenizeEquals(next);
+    }
+
+    if (identical(next, $CLOSE_CURLY_BRACKET)) {
+      return appendEndGroup(CLOSE_CURLY_BRACKET_INFO, OPEN_CURLY_BRACKET_TOKEN);
+    }
+
+    if (identical(next, $SLASH)) {
+      return tokenizeSlashOrComment(next);
+    }
+
+
+    if (identical(next, $OPEN_CURLY_BRACKET)) {
+      appendBeginGroup(OPEN_CURLY_BRACKET_INFO);
+      return advance();
+    }
+
+    if (identical(next, $DQ) || identical(next, $SQ)) {
+      return tokenizeString(next, scanOffset, false);
+    }
+
+    if(identical(next, $_)){
       return tokenizeKeywordOrIdentifier(next, true);
     }
 
+    if (identical(next, $COLON)) {
+      appendPrecedenceToken(COLON_INFO);
+      return advance();
+    }
+
     if (identical(next, $LT)) {
       return tokenizeLessThan(next);
     }
@@ -247,18 +311,51 @@
       return tokenizeGreaterThan(next);
     }
 
-    if (identical(next, $EQ)) {
-      return tokenizeEquals(next);
-    }
-
     if (identical(next, $BANG)) {
       return tokenizeExclamation(next);
     }
 
+    if (identical(next, $OPEN_SQUARE_BRACKET)) {
+      return tokenizeOpenSquareBracket(next);
+    }
+
+    if (identical(next, $CLOSE_SQUARE_BRACKET)) {
+      return appendEndGroup(
+          CLOSE_SQUARE_BRACKET_INFO, OPEN_SQUARE_BRACKET_TOKEN);
+    }
+
+    if (identical(next, $AT)) {
+      return tokenizeAt(next);
+    }
+
+    if (next >= $1 && next <= $9) {
+      return tokenizeNumber(next);
+    }
+
+    if (identical(next, $AMPERSAND)) {
+      return tokenizeAmpersand(next);
+    }
+
+    if (identical(next, $0)) {
+      return tokenizeHexOrNumber(next);
+    }
+
+    if (identical(next, $QUESTION)) {
+      return tokenizeQuestion(next);
+    }
+
+    if (identical(next, $BAR)) {
+      return tokenizeBar(next);
+    }
+
     if (identical(next, $PLUS)) {
       return tokenizePlus(next);
     }
 
+    if(identical(next, $$)){
+      return tokenizeKeywordOrIdentifier(next, true);
+    }
+
     if (identical(next, $MINUS)) {
       return tokenizeMinus(next);
     }
@@ -267,30 +364,23 @@
       return tokenizeMultiply(next);
     }
 
-    if (identical(next, $PERCENT)) {
-      return tokenizePercent(next);
-    }
-
-    if (identical(next, $AMPERSAND)) {
-      return tokenizeAmpersand(next);
-    }
-
-    if (identical(next, $BAR)) {
-      return tokenizeBar(next);
-    }
-
     if (identical(next, $CARET)) {
       return tokenizeCaret(next);
     }
 
-    if (identical(next, $OPEN_SQUARE_BRACKET)) {
-      return tokenizeOpenSquareBracket(next);
-    }
-
     if (identical(next, $TILDE)) {
       return tokenizeTilde(next);
     }
 
+    if (identical(next, $PERCENT)) {
+      return tokenizePercent(next);
+    }
+
+    if (identical(next, $BACKPING)) {
+      appendPrecedenceToken(BACKPING_INFO);
+      return advance();
+    }
+
     if (identical(next, $BACKSLASH)) {
       appendPrecedenceToken(BACKSLASH_INFO);
       return advance();
@@ -300,91 +390,6 @@
       return tokenizeTag(next);
     }
 
-    if (identical(next, $OPEN_PAREN)) {
-      appendBeginGroup(OPEN_PAREN_INFO);
-      return advance();
-    }
-
-    if (identical(next, $CLOSE_PAREN)) {
-      return appendEndGroup(CLOSE_PAREN_INFO, OPEN_PAREN_TOKEN);
-    }
-
-    if (identical(next, $COMMA)) {
-      appendPrecedenceToken(COMMA_INFO);
-      return advance();
-    }
-
-    if (identical(next, $COLON)) {
-      appendPrecedenceToken(COLON_INFO);
-      return advance();
-    }
-
-    if (identical(next, $SEMICOLON)) {
-      appendPrecedenceToken(SEMICOLON_INFO);
-      // Type parameters and arguments cannot contain semicolon.
-      discardOpenLt();
-      return advance();
-    }
-
-    if (identical(next, $QUESTION)) {
-      return tokenizeQuestion(next);
-    }
-
-    if (identical(next, $CLOSE_SQUARE_BRACKET)) {
-      return appendEndGroup(
-          CLOSE_SQUARE_BRACKET_INFO, OPEN_SQUARE_BRACKET_TOKEN);
-    }
-
-    if (identical(next, $BACKPING)) {
-      appendPrecedenceToken(BACKPING_INFO);
-      return advance();
-    }
-
-    if (identical(next, $OPEN_CURLY_BRACKET)) {
-      appendBeginGroup(OPEN_CURLY_BRACKET_INFO);
-      return advance();
-    }
-
-    if (identical(next, $CLOSE_CURLY_BRACKET)) {
-      return appendEndGroup(CLOSE_CURLY_BRACKET_INFO, OPEN_CURLY_BRACKET_TOKEN);
-    }
-
-    if (identical(next, $SLASH)) {
-      return tokenizeSlashOrComment(next);
-    }
-
-    if (identical(next, $AT)) {
-      return tokenizeAt(next);
-    }
-
-    if (identical(next, $DQ) || identical(next, $SQ)) {
-      return tokenizeString(next, scanOffset, false);
-    }
-
-    if (identical(next, $PERIOD)) {
-      return tokenizeDotsOrNumber(next);
-    }
-
-    if (identical(next, $0)) {
-      return tokenizeHexOrNumber(next);
-    }
-
-    // TODO(ahe): Would a range check be faster?
-    if (identical(next, $1) ||
-        identical(next, $2) ||
-        identical(next, $3) ||
-        identical(next, $4) ||
-        identical(next, $5) ||
-        identical(next, $6) ||
-        identical(next, $7) ||
-        identical(next, $8) ||
-        identical(next, $9)) {
-      return tokenizeNumber(next);
-    }
-
-    if (identical(next, $EOF)) {
-      return $EOF;
-    }
     if (next < 0x1f) {
       return unexpected(next);
     }
@@ -398,7 +403,7 @@
     // # or #!.*[\n\r]
     if (scanOffset == 0) {
       if (identical(peek(), $BANG)) {
-        int start = scanOffset + 1;
+        int start = scanOffset;
         bool asciiOnly = true;
         do {
           next = advance();
@@ -407,6 +412,7 @@
             !identical(next, $CR) &&
             !identical(next, $EOF));
         if (!asciiOnly) handleUnicode(start);
+        appendSubstringToken(SCRIPT_INFO, start, asciiOnly);
         return next;
       }
     }
diff --git a/pkg/front_end/lib/src/fasta/scanner/array_based_scanner.dart b/pkg/front_end/lib/src/fasta/scanner/array_based_scanner.dart
index bf033f0..1cb904f 100644
--- a/pkg/front_end/lib/src/fasta/scanner/array_based_scanner.dart
+++ b/pkg/front_end/lib/src/fasta/scanner/array_based_scanner.dart
@@ -10,7 +10,8 @@
 
 import 'precedence.dart' show COMMENT_INFO, EOF_INFO, PrecedenceInfo;
 
-import 'token.dart' show BeginGroupToken, KeywordToken, SymbolToken, Token;
+import 'token.dart'
+    show BeginGroupToken, KeywordToken, StringToken, SymbolToken, Token;
 
 import 'token_constants.dart'
     show LT_TOKEN, OPEN_CURLY_BRACKET_TOKEN, STRING_INTERPOLATION_TOKEN;
@@ -35,6 +36,20 @@
   Link<BeginGroupToken> groupingStack = const Link<BeginGroupToken>();
 
   /**
+   * Append the given token to the [tail] of the current stream of tokens.
+   */
+  void appendToken(Token token) {
+    tail.next = token;
+    tail.next.previousToken = tail;
+    tail = tail.next;
+    if (comments != null) {
+      tail.precedingComments = comments;
+      comments = null;
+      commentsTail = null;
+    }
+  }
+
+  /**
    * Appends a fixed token whose kind and content is determined by [info].
    * Appends an *operator* token from [info].
    *
@@ -42,8 +57,7 @@
    * '=>', etc.
    */
   void appendPrecedenceToken(PrecedenceInfo info) {
-    tail.next = new SymbolToken(info, tokenStart);
-    tail = tail.next;
+    appendToken(new SymbolToken(info, tokenStart));
   }
 
   /**
@@ -72,8 +86,7 @@
     if (identical(syntax, 'this')) {
       discardOpenLt();
     }
-    tail.next = new KeywordToken(keyword, tokenStart);
-    tail = tail.next;
+    appendToken(new KeywordToken(keyword, tokenStart));
   }
 
   void appendEofToken() {
@@ -83,8 +96,7 @@
       unmatchedBeginGroup(groupingStack.head);
       groupingStack = groupingStack.tail;
     }
-    tail.next = new SymbolToken(EOF_INFO, tokenStart);
-    tail = tail.next;
+    appendToken(new SymbolToken(EOF_INFO, tokenStart));
     // EOF points to itself so there's always infinite look-ahead.
     tail.next = tail;
   }
@@ -118,8 +130,7 @@
    */
   void appendBeginGroup(PrecedenceInfo info) {
     Token token = new BeginGroupToken(info, tokenStart);
-    tail.next = token;
-    tail = tail.next;
+    appendToken(token);
 
     // { (  [ ${ cannot appear inside a type parameters / arguments.
     if (!identical(info.kind, LT_TOKEN)) discardOpenLt();
@@ -209,15 +220,40 @@
 
   void appendComment(start, bool asciiOnly) {
     if (!includeComments) return;
-    appendSubstringToken(COMMENT_INFO, start, asciiOnly);
+    Token newComment = createSubstringToken(COMMENT_INFO, start, asciiOnly);
+    if (comments == null) {
+      comments = newComment;
+      commentsTail = comments;
+    } else {
+      commentsTail.next = newComment;
+      commentsTail.next.previousToken = commentsTail;
+      commentsTail = commentsTail.next;
+    }
   }
 
   void appendErrorToken(ErrorToken token) {
     hasErrors = true;
-    tail.next = token;
-    tail = token;
+    appendToken(token);
   }
 
+  void appendSubstringToken(PrecedenceInfo info, int start, bool asciiOnly,
+      [int extraOffset = 0]) {
+    appendToken(createSubstringToken(info, start, asciiOnly, extraOffset));
+  }
+
+  /**
+   * Returns a new substring from the scan offset [start] to the current
+   * [scanOffset] plus the [extraOffset]. For example, if the current
+   * scanOffset is 10, then [appendSubstringToken(5, -1)] will append the
+   * substring string [5,9).
+   *
+   * Note that [extraOffset] can only be used if the covered character(s) are
+   * known to be ASCII.
+   */
+  StringToken createSubstringToken(
+      PrecedenceInfo info, int start, bool asciiOnly,
+      [int extraOffset = 0]);
+
   /**
    * This method is called to discard '<' from the "grouping" stack.
    *
diff --git a/pkg/front_end/lib/src/fasta/scanner/precedence.dart b/pkg/front_end/lib/src/fasta/scanner/precedence.dart
index d7baa32..a4e2f72 100644
--- a/pkg/front_end/lib/src/fasta/scanner/precedence.dart
+++ b/pkg/front_end/lib/src/fasta/scanner/precedence.dart
@@ -232,6 +232,9 @@
 const PrecedenceInfo IDENTIFIER_INFO =
     const PrecedenceInfo('identifier', 0, IDENTIFIER_TOKEN);
 
+const PrecedenceInfo SCRIPT_INFO =
+    const PrecedenceInfo('script', 0, SCRIPT_TOKEN);
+
 const PrecedenceInfo BAD_INPUT_INFO =
     const PrecedenceInfo('malformed input', 0, BAD_INPUT_TOKEN);
 
diff --git a/pkg/front_end/lib/src/fasta/scanner/string_scanner.dart b/pkg/front_end/lib/src/fasta/scanner/string_scanner.dart
index a81d4a8..555dbae 100644
--- a/pkg/front_end/lib/src/fasta/scanner/string_scanner.dart
+++ b/pkg/front_end/lib/src/fasta/scanner/string_scanner.dart
@@ -44,12 +44,13 @@
   Token firstToken() => tokens.next;
   Token previousToken() => tail;
 
-  void appendSubstringToken(PrecedenceInfo info, int start, bool asciiOnly,
+  @override
+  StringToken createSubstringToken(
+      PrecedenceInfo info, int start, bool asciiOnly,
       [int extraOffset = 0]) {
-    tail.next = new StringToken.fromSubstring(
+    return new StringToken.fromSubstring(
         info, string, start, scanOffset + extraOffset, tokenStart,
         canonicalize: true);
-    tail = tail.next;
   }
 
   bool atEndOfFile() => scanOffset >= string.length - 1;
diff --git a/pkg/front_end/lib/src/fasta/scanner/token.dart b/pkg/front_end/lib/src/fasta/scanner/token.dart
index 6cab122..43eed18 100644
--- a/pkg/front_end/lib/src/fasta/scanner/token.dart
+++ b/pkg/front_end/lib/src/fasta/scanner/token.dart
@@ -29,6 +29,23 @@
   Token next;
 
   /**
+   * The previous token in the token stream.
+   *
+   * Deprecated :: This exists for compatibility with the Analyzer token stream
+   * and will be removed at some future date.
+   */
+  @deprecated
+  Token previousToken;
+
+  /**
+   * Return the first comment in the list of comments that precede this token,
+   * or `null` if there are no comments preceding this token. Additional
+   * comments can be reached by following the token stream using [next] until
+   * `null` is returned.
+   */
+  Token precedingComments;
+
+  /**
    * The precedence info for this token. [info] determines the kind and the
    * precedence level of this token.
    *
diff --git a/pkg/front_end/lib/src/fasta/scanner/token_constants.dart b/pkg/front_end/lib/src/fasta/scanner/token_constants.dart
index b5501e4..920a8dc 100644
--- a/pkg/front_end/lib/src/fasta/scanner/token_constants.dart
+++ b/pkg/front_end/lib/src/fasta/scanner/token_constants.dart
@@ -10,6 +10,7 @@
 
 const int KEYWORD_TOKEN = $k;
 const int IDENTIFIER_TOKEN = $a;
+const int SCRIPT_TOKEN = $b;
 const int BAD_INPUT_TOKEN = $X;
 const int DOUBLE_TOKEN = $d;
 const int INT_TOKEN = $i;
diff --git a/pkg/front_end/lib/src/fasta/scanner/utf8_bytes_scanner.dart b/pkg/front_end/lib/src/fasta/scanner/utf8_bytes_scanner.dart
index ca004ed..84ae1554d 100644
--- a/pkg/front_end/lib/src/fasta/scanner/utf8_bytes_scanner.dart
+++ b/pkg/front_end/lib/src/fasta/scanner/utf8_bytes_scanner.dart
@@ -198,11 +198,12 @@
   Token firstToken() => tokens.next;
   Token previousToken() => tail;
 
-  void appendSubstringToken(PrecedenceInfo info, int start, bool asciiOnly,
+  @override
+  StringToken createSubstringToken(
+      PrecedenceInfo info, int start, bool asciiOnly,
       [int extraOffset = 0]) {
-    tail.next = new StringToken.fromUtf8Bytes(
+    return new StringToken.fromUtf8Bytes(
         info, bytes, start, byteOffset + extraOffset, asciiOnly, tokenStart);
-    tail = tail.next;
   }
 
   bool atEndOfFile() => byteOffset >= bytes.length - 1;
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 89cbf4a..63b1723 100644
--- a/pkg/front_end/lib/src/fasta/source/diet_listener.dart
+++ b/pkg/front_end/lib/src/fasta/source/diet_listener.dart
@@ -120,7 +120,7 @@
   }
 
   @override
-  void endMixinApplication() {
+  void endMixinApplication(Token withKeyword) {
     debugEvent("MixinApplication");
   }
 
@@ -166,10 +166,21 @@
   }
 
   @override
+  void handleFunctionType(Token functionToken, Token endToken) {
+    debugEvent("FunctionType");
+  }
+
+  @override
   void endFunctionTypeAlias(
       Token typedefKeyword, Token equals, Token endToken) {
     debugEvent("FunctionTypeAlias");
-    discard(2); // Name + endToken.
+    if (stack.length == 1) {
+      // TODO(ahe): This happens when recovering from `typedef I = A;`. Find a
+      // different way to track tokens of formal parameters.
+      discard(1); // Name.
+    } else {
+      discard(2); // Name + endToken.
+    }
     checkEmpty(typedefKeyword.charOffset);
   }
 
@@ -251,6 +262,11 @@
   }
 
   @override
+  void handleScript(Token token) {
+    debugEvent("Script");
+  }
+
+  @override
   void handleStringJuxtaposition(int literalCount) {
     debugEvent("StringJuxtaposition");
   }
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 215d2eb..5be03bd 100644
--- a/pkg/front_end/lib/src/fasta/source/outline_builder.dart
+++ b/pkg/front_end/lib/src/fasta/source/outline_builder.dart
@@ -261,6 +261,7 @@
         asyncModifier,
         computeProcedureKind(getOrSet),
         beginToken.charOffset,
+        endToken.charOffset,
         nativeMethodName,
         isTopLevel: true);
     nativeMethodName = null;
@@ -311,14 +312,24 @@
     int modifiers =
         Modifier.validate(pop(), isAbstract: bodyKind == MethodBody.Abstract);
     List<MetadataBuilder> metadata = pop();
-    library.addProcedure(metadata, modifiers, returnType, name, typeVariables,
-        formals, asyncModifier, kind, beginToken.charOffset, nativeMethodName,
+    library.addProcedure(
+        metadata,
+        modifiers,
+        returnType,
+        name,
+        typeVariables,
+        formals,
+        asyncModifier,
+        kind,
+        beginToken.charOffset,
+        endToken.charOffset,
+        nativeMethodName,
         isTopLevel: false);
     nativeMethodName = null;
   }
 
   @override
-  void endMixinApplication() {
+  void endMixinApplication(Token withKeyword) {
     debugEvent("MixinApplication");
     List<TypeBuilder> mixins = pop();
     TypeBuilder supertype = pop();
@@ -356,6 +367,11 @@
   }
 
   @override
+  void handleScript(Token token) {
+    debugEvent("Script");
+  }
+
+  @override
   void handleType(Token beginToken, Token endToken) {
     debugEvent("Type");
     List<TypeBuilder> arguments = pop();
@@ -472,7 +488,8 @@
     List<String> constants = popList(count);
     String name = pop();
     List<MetadataBuilder> metadata = pop();
-    library.addEnum(metadata, name, constants, enumKeyword.charOffset);
+    library.addEnum(
+        metadata, name, constants, enumKeyword.charOffset, endBrace.charOffset);
     checkEmpty(enumKeyword.charOffset);
   }
 
@@ -482,13 +499,46 @@
   }
 
   @override
+  void handleFunctionType(Token functionToken, Token endToken) {
+    debugEvent("FunctionType");
+    List<FormalParameterBuilder> formals = pop();
+    List<TypeVariableBuilder> typeVariables = pop();
+    TypeBuilder returnType = pop();
+    push(library.addFunctionType(
+        returnType, typeVariables, formals, functionToken.charOffset));
+  }
+
+  @override
   void endFunctionTypeAlias(
       Token typedefKeyword, Token equals, Token endToken) {
     debugEvent("endFunctionTypeAlias");
-    List<FormalParameterBuilder> formals = pop();
-    List<TypeVariableBuilder> typeVariables = pop();
-    String name = pop();
-    TypeBuilder returnType = pop();
+    List<FormalParameterBuilder> formals;
+    List<TypeVariableBuilder> typeVariables;
+    String name;
+    TypeBuilder returnType;
+    if (equals == null) {
+      formals = pop();
+      typeVariables = pop();
+      name = pop();
+      returnType = pop();
+    } else {
+      var type = pop();
+      typeVariables = pop();
+      name = pop();
+      if (type is FunctionTypeBuilder) {
+        // TODO(ahe): We need to start a nested declaration when parsing the
+        // formals and return type so we can correctly bind
+        // `type.typeVariables`. A typedef can have type variables, and a new
+        // function type can also have type variables (representing the type of
+        // a generic function).
+        formals = type.formals;
+        returnType = type.returnType;
+      } else {
+        // TODO(ahe): Improve this error message.
+        library.addCompileTimeError(
+            equals.charOffset, "Can't create typedef from non-function type.");
+      }
+    }
     List<MetadataBuilder> metadata = pop();
     library.addFunctionTypeAlias(metadata, returnType, name, typeVariables,
         formals, typedefKeyword.charOffset);
@@ -562,8 +612,16 @@
     var name = pop();
     int modifiers = Modifier.validate(pop());
     List<MetadataBuilder> metadata = pop();
-    library.addFactoryMethod(metadata, modifiers, name, formals, asyncModifier,
-        redirectionTarget, beginToken.charOffset, nativeMethodName);
+    library.addFactoryMethod(
+        metadata,
+        modifiers,
+        name,
+        formals,
+        asyncModifier,
+        redirectionTarget,
+        beginToken.charOffset,
+        endToken.charOffset,
+        nativeMethodName);
     nativeMethodName = null;
   }
 
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 498b074..5c21153 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
@@ -24,6 +24,7 @@
         ClassBuilder,
         ConstructorReferenceBuilder,
         FormalParameterBuilder,
+        FunctionTypeBuilder,
         LibraryBuilder,
         MemberBuilder,
         MetadataBuilder,
@@ -195,11 +196,12 @@
       AsyncMarker asyncModifier,
       ProcedureKind kind,
       int charOffset,
+      int charEndOffset,
       String nativeMethodName,
       {bool isTopLevel});
 
   void addEnum(List<MetadataBuilder> metadata, String name,
-      List<String> constants, int charOffset);
+      List<String> constants, int charOffset, int charEndOffset);
 
   void addFunctionTypeAlias(
       List<MetadataBuilder> metadata,
@@ -209,6 +211,12 @@
       List<FormalParameterBuilder> formals,
       int charOffset);
 
+  FunctionTypeBuilder addFunctionType(
+      T returnType,
+      List<TypeVariableBuilder> typeVariables,
+      List<FormalParameterBuilder> formals,
+      int charOffset);
+
   void addFactoryMethod(
       List<MetadataBuilder> metadata,
       int modifiers,
@@ -217,6 +225,7 @@
       AsyncMarker asyncModifier,
       ConstructorReferenceBuilder redirectionTarget,
       int charOffset,
+      int charEndOffset,
       String nativeMethodName);
 
   FormalParameterBuilder addFormalParameter(List<MetadataBuilder> metadata,
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 5e50846..3a5f82b 100644
--- a/pkg/front_end/lib/src/fasta/source/source_loader.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_loader.dart
@@ -8,6 +8,8 @@
 
 import 'dart:io' show FileSystemException;
 
+import 'dart:typed_data' show Uint8List;
+
 import '../scanner/io.dart' show readBytesFromFile;
 
 import '../scanner.dart' show ErrorToken, ScannerResult, Token, scan;
@@ -40,8 +42,11 @@
 
 import 'source_library_builder.dart' show SourceLibraryBuilder;
 
+import '../compiler_context.dart' show CompilerContext;
+
 class SourceLoader<L> extends Loader<L> {
   final Map<Uri, List<int>> sourceBytes = <Uri, List<int>>{};
+  final includeSource = CompilerContext.current.options.includeSource;
 
   // Used when building directly to kernel.
   ClassHierarchy hierarchy;
@@ -64,7 +69,8 @@
       ScannerResult result = scan(bytes);
       Token token = result.tokens;
       if (!suppressLexicalErrors) {
-        target.addLineStarts(library.fileUri, result.lineStarts);
+        List<int> source = getSource(bytes);
+        target.addSourceInformation(library.fileUri, result.lineStarts, source);
       }
       while (token is ErrorToken) {
         if (!suppressLexicalErrors) {
@@ -84,6 +90,17 @@
     }
   }
 
+  List<int> getSource(List<int> bytes) {
+    if (!includeSource) return const <int>[];
+
+    // bytes is 0-terminated. We don't want that included.
+    if (bytes is Uint8List) {
+      return new Uint8List.view(
+          bytes.buffer, bytes.offsetInBytes, bytes.length - 1);
+    }
+    return bytes.sublist(0, bytes.length - 1);
+  }
+
   Future<Null> buildOutline(SourceLibraryBuilder library) async {
     Token tokens = await tokenize(library);
     if (tokens == null) return;
diff --git a/pkg/front_end/lib/src/fasta/source/stack_listener.dart b/pkg/front_end/lib/src/fasta/source/stack_listener.dart
index 9793877..fddbdc2 100644
--- a/pkg/front_end/lib/src/fasta/source/stack_listener.dart
+++ b/pkg/front_end/lib/src/fasta/source/stack_listener.dart
@@ -24,6 +24,7 @@
   BreakTarget,
   CascadeReceiver,
   Combinators,
+  Comments,
   ConditionalUris,
   ConstructorReferenceContinuationAfterTypeArguments,
   ContinueTarget,
@@ -33,6 +34,7 @@
   FunctionBody,
   FunctionBodyAsyncToken,
   FunctionBodyStarToken,
+  Identifier,
   IdentifierList,
   Initializers,
   Metadata,
@@ -113,6 +115,12 @@
   }
 
   @override
+  void handleNoName(Token token) {
+    debugEvent("NoName");
+    push(NullValue.Identifier);
+  }
+
+  @override
   void endInitializer(Token token) {
     debugEvent("Initializer");
   }
diff --git a/pkg/front_end/lib/src/fasta/target_implementation.dart b/pkg/front_end/lib/src/fasta/target_implementation.dart
index a2adbce..45a105f 100644
--- a/pkg/front_end/lib/src/fasta/target_implementation.dart
+++ b/pkg/front_end/lib/src/fasta/target_implementation.dart
@@ -65,5 +65,6 @@
     }
   }
 
-  void addLineStarts(Uri uri, List<int> lineStarts);
+  void addSourceInformation(
+      Uri uri, List<int> lineStarts, List<int> sourceCode);
 }
diff --git a/pkg/front_end/test/fasta/compile.status b/pkg/front_end/test/fasta/compile.status
index 7772214..531c803 100644
--- a/pkg/front_end/test/fasta/compile.status
+++ b/pkg/front_end/test/fasta/compile.status
@@ -7,7 +7,7 @@
 # pkg/fasta/lib/src/kernel/.
 
 await: Fail
-function_type_recovery: Crash
+function_type_recovery: Fail
 invocations: Fail
 statements: Fail # Make async tranformer optional for golden file testing.
 type_variable_as_super: Fail
diff --git a/pkg/front_end/test/fasta/kompile.status b/pkg/front_end/test/fasta/kompile.status
index 3442779..13e99f7 100644
--- a/pkg/front_end/test/fasta/kompile.status
+++ b/pkg/front_end/test/fasta/kompile.status
@@ -16,7 +16,7 @@
 fibonacci: Crash
 for_in_scope: Crash
 function_in_field: Crash
-function_type_recovery: Crash
+function_type_recovery: Fail
 functions: Crash
 implicit_this: Crash
 invocations: Fail
diff --git a/pkg/front_end/test/fasta/outline.status b/pkg/front_end/test/fasta/outline.status
index 6837a05..d57019b 100644
--- a/pkg/front_end/test/fasta/outline.status
+++ b/pkg/front_end/test/fasta/outline.status
@@ -2,7 +2,7 @@
 # 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.
 
-function_type_recovery: Crash
+function_type_recovery: Fail
 
 rasta/bad_redirection: Fail
 rasta/class_hierarchy: Fail
diff --git a/pkg/front_end/test/fasta/parser/token_stream_rewriter_test.dart b/pkg/front_end/test/fasta/parser/token_stream_rewriter_test.dart
new file mode 100644
index 0000000..06524b3
--- /dev/null
+++ b/pkg/front_end/test/fasta/parser/token_stream_rewriter_test.dart
@@ -0,0 +1,149 @@
+// Copyright (c) 2017, 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:front_end/src/fasta/parser/token_stream_rewriter.dart';
+import 'package:front_end/src/fasta/scanner/precedence.dart';
+import 'package:front_end/src/fasta/scanner/token.dart';
+import 'package:test/test.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(TokenStreamRewriterTest_NoPrevious);
+    defineReflectiveTests(TokenStreamRewriterTest_UsingPrevious);
+  });
+}
+
+/// Abstract base class for tests of [TokenStreamRewriter].
+abstract class TokenStreamRewriterTest {
+  /// Indicates whether the tests should set up [Token.previousToken].
+  bool get setPrevious;
+
+  void test_insert_at_end() {
+    var a = _makeToken(0, 'a');
+    var b = _makeToken(1, 'b');
+    var eof = _link([a]);
+    var rewriter = new TokenStreamRewriter(a);
+    rewriter.insertTokenBefore(b, eof);
+    expect(rewriter.firstToken, same(a));
+    expect(a.next, same(b));
+    expect(b.next, same(eof));
+    expect(eof.previousToken, same(b));
+    expect(b.previousToken, same(a));
+  }
+
+  void test_insert_at_start() {
+    var a = _makeToken(0, 'a');
+    var b = _makeToken(1, 'b');
+    _link([b]);
+    var rewriter = new TokenStreamRewriter(b);
+    rewriter.insertTokenBefore(a, b);
+    expect(rewriter.firstToken, same(a));
+    expect(a.next, same(b));
+    expect(a.previousToken.next, same(a));
+    expect(b.previousToken, same(a));
+  }
+
+  void test_resume_at_previous_insertion_point() {
+    var a = _makeToken(0, 'a');
+    var b = _makeToken(1, 'b');
+    var c = _makeToken(2, 'c');
+    var d = _makeToken(3, 'd');
+    var e = _makeToken(4, 'e');
+    _link([a, b, e]);
+    var rewriter = new TokenStreamRewriter(a);
+    rewriter.insertTokenBefore(d, e);
+    expect(b.next, same(d));
+    expect(d.next, same(e));
+    a.next = null;
+    // The next call to rewriter should be able to find the insertion point
+    // without using a.next.
+    rewriter.insertTokenBefore(c, d);
+    expect(b.next, same(c));
+    expect(c.next, same(d));
+  }
+
+  void test_second_insertion_earlier_in_stream() {
+    var a = _makeToken(0, 'a');
+    var b = _makeToken(1, 'b');
+    var c = _makeToken(2, 'c');
+    var d = _makeToken(3, 'd');
+    var e = _makeToken(4, 'e');
+    _link([a, c, e]);
+    var rewriter = new TokenStreamRewriter(a);
+    rewriter.insertTokenBefore(d, e);
+    expect(c.next, same(d));
+    expect(d.next, same(e));
+    // The next call to rewriter should be able to find the insertion point
+    // even though it is before the insertion point used above.
+    rewriter.insertTokenBefore(b, c);
+    expect(a.next, same(b));
+    expect(b.next, same(c));
+  }
+
+  void test_skip_group() {
+    var a = _makeBeginGroupToken(0);
+    var b = _makeToken(1, 'b');
+    var c = _makeToken(2, 'c');
+    var d = _makeToken(3, 'd');
+    var e = _makeToken(4, 'e');
+    a.endGroup = c;
+    _link([a, b, c, e]);
+    // The rewriter should skip from a to c when finding the insertion position;
+    // we test this by corrupting b's next pointer.
+    b.next = null;
+    var rewriter = new TokenStreamRewriter(a);
+    rewriter.insertTokenBefore(d, e);
+    expect(c.next, same(d));
+    expect(d.next, same(e));
+  }
+
+  /// Links together the given [tokens] and adds an EOF token to the end of the
+  /// token stream.
+  ///
+  /// The EOF token is returned.
+  Token _link(Iterable<Token> tokens) {
+    Token head = new SymbolToken(EOF_INFO, -1);
+    for (var token in tokens) {
+      head.next = token;
+      if (setPrevious) token.previousToken = head;
+      head = token;
+    }
+    int eofOffset = head.charOffset + head.value.length;
+    if (eofOffset < 0) eofOffset = 0;
+    Token eof = new SymbolToken(EOF_INFO, eofOffset);
+    head.next = eof;
+    if (setPrevious) eof.previousToken = head;
+    return eof;
+  }
+
+  BeginGroupToken _makeBeginGroupToken(int charOffset) {
+    return new BeginGroupToken(OPEN_PAREN_INFO, charOffset);
+  }
+
+  StringToken _makeToken(int charOffset, String text) {
+    return new StringToken.fromString(null, text, charOffset);
+  }
+}
+
+/// Concrete implementation of [TokenStreamRewriterTest] in which
+/// [Token.previousToken] values are set to null.
+///
+/// This forces [TokenStreamRewriter] to use its more complex heursitc for
+/// finding previous tokens.
+@reflectiveTest
+class TokenStreamRewriterTest_NoPrevious extends TokenStreamRewriterTest {
+  bool get setPrevious => false;
+}
+
+/// Concrete implementation of [TokenStreamRewriterTest] in which
+/// [Token.previousToken] values are set to non-null.
+///
+/// Since [TokenStreamRewriter] makes use of [Token.previousToken] when it can,
+/// these tests do not exercise the more complex heuristics for finding previous
+/// tokens.
+@reflectiveTest
+class TokenStreamRewriterTest_UsingPrevious extends TokenStreamRewriterTest {
+  bool get setPrevious => true;
+}
diff --git a/pkg/front_end/test/fasta/type_variable_as_super.dart b/pkg/front_end/test/fasta/type_variable_as_super.dart
new file mode 100644
index 0000000..dbcfaaa
--- /dev/null
+++ b/pkg/front_end/test/fasta/type_variable_as_super.dart
@@ -0,0 +1,17 @@
+// Copyright (c) 2017, 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.
+
+abstract class A<T> extends T {}
+
+abstract class B<T> extends T {
+  B();
+}
+
+class C<T> extends T {}
+
+main() {
+  new A();
+  new B();
+  new C();
+}
diff --git a/pkg/front_end/test/fasta/type_variable_as_super.dart.dartk.expect b/pkg/front_end/test/fasta/type_variable_as_super.dart.dartk.expect
new file mode 100644
index 0000000..f896d53
--- /dev/null
+++ b/pkg/front_end/test/fasta/type_variable_as_super.dart.dartk.expect
@@ -0,0 +1,24 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+abstract class A<T extends core::Object> extends core::Object {
+  constructor •() → void
+    : super core::Object::•()
+    ;
+}
+abstract class B<T extends core::Object> extends core::Object {
+  constructor •() → void
+    : super core::Object::•()
+    ;
+}
+class C<T extends core::Object> extends core::Object {
+  constructor •() → void
+    : super core::Object::•()
+    ;
+}
+static method main() → dynamic {
+  throw new core::NoSuchMethodError::•(null, #A, <dynamic>[], <dynamic, dynamic>{}, null);
+  throw new core::NoSuchMethodError::•(null, #B, <dynamic>[], <dynamic, dynamic>{}, null);
+  new self::C::•<dynamic>();
+}
diff --git a/pkg/front_end/test/fasta/type_variable_as_super.dart.direct.expect b/pkg/front_end/test/fasta/type_variable_as_super.dart.direct.expect
new file mode 100644
index 0000000..f896d53
--- /dev/null
+++ b/pkg/front_end/test/fasta/type_variable_as_super.dart.direct.expect
@@ -0,0 +1,24 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+abstract class A<T extends core::Object> extends core::Object {
+  constructor •() → void
+    : super core::Object::•()
+    ;
+}
+abstract class B<T extends core::Object> extends core::Object {
+  constructor •() → void
+    : super core::Object::•()
+    ;
+}
+class C<T extends core::Object> extends core::Object {
+  constructor •() → void
+    : super core::Object::•()
+    ;
+}
+static method main() → dynamic {
+  throw new core::NoSuchMethodError::•(null, #A, <dynamic>[], <dynamic, dynamic>{}, null);
+  throw new core::NoSuchMethodError::•(null, #B, <dynamic>[], <dynamic, dynamic>{}, null);
+  new self::C::•<dynamic>();
+}
diff --git a/pkg/front_end/test/fasta/type_variable_as_super.dart.outline.expect b/pkg/front_end/test/fasta/type_variable_as_super.dart.outline.expect
new file mode 100644
index 0000000..d820812
--- /dev/null
+++ b/pkg/front_end/test/fasta/type_variable_as_super.dart.outline.expect
@@ -0,0 +1,18 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+abstract class A<T extends core::Object> extends core::Object {
+  constructor •() → void
+    ;
+}
+abstract class B<T extends core::Object> extends core::Object {
+  constructor •() → void
+    ;
+}
+class C<T extends core::Object> extends core::Object {
+  constructor •() → void
+    ;
+}
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/test/scanner_fasta_test.dart b/pkg/front_end/test/scanner_fasta_test.dart
index 14a5d65..5b87dc3 100644
--- a/pkg/front_end/test/scanner_fasta_test.dart
+++ b/pkg/front_end/test/scanner_fasta_test.dart
@@ -59,6 +59,88 @@
     super.test_bar_bar_eq();
   }
 
+  void test_comments() {
+    const source = '''
+       /// Doc comment before class
+       /// second line
+       /// third
+       class Foo {
+         // Random comment
+         Object someField; // trailing comment
+         dynamic secondField;
+         /// Method doc
+         void someMethod(/* comment before closing paren */) {
+           // body comment
+         }
+         /** Doc comment 2 */
+         Foo2 bar() => new Baz();
+       } // EOF comment
+    ''';
+
+    fasta.Token scanSource({bool includeComments}) {
+      return new fasta.StringScanner(source, includeComments: includeComments)
+          .tokenize();
+    }
+
+    int tokenCount = 0;
+    fasta.Token token = scanSource(includeComments: false);
+    while (!token.isEof) {
+      ++tokenCount;
+      // Assert no comments
+      expect(token.precedingComments, isNull);
+      expect(token.info.kind, isNot(fasta.COMMENT_TOKEN));
+      token = token.next;
+    }
+    expect(token.precedingComments, isNull);
+    expect(tokenCount, 26);
+
+    tokenCount = 0;
+    int previousEnd = 0;
+    int spotCheckCount = 0;
+    int commentTokenCount = 0;
+    token = scanSource(includeComments: true);
+    while (!token.isEof) {
+      ++tokenCount;
+      // Assert valid comments
+      fasta.Token comment = token.precedingComments;
+      while (comment != null) {
+        ++commentTokenCount;
+        expect(comment.info.kind, fasta.COMMENT_TOKEN);
+        expect(comment.charOffset, greaterThanOrEqualTo(previousEnd));
+        previousEnd = comment.charOffset + comment.charCount;
+        comment = comment.next;
+      }
+      expect(token.info.kind, isNot(fasta.COMMENT_TOKEN));
+      expect(token.charOffset, greaterThanOrEqualTo(previousEnd));
+      previousEnd = token.charOffset + token.charCount;
+
+      // Spot check for specific token/comment combinations
+      if (token.value == 'class') {
+        ++spotCheckCount;
+        expect(token.precedingComments?.value, '/// Doc comment before class');
+        expect(token.precedingComments?.next?.value, '/// second line');
+        expect(token.precedingComments?.next?.next?.value, '/// third');
+        expect(token.precedingComments?.next?.next?.next, isNull);
+      } else if (token.value == 'Foo2') {
+        ++spotCheckCount;
+        expect(token.precedingComments?.value, '/** Doc comment 2 */');
+      } else if (token.value == ')') {
+        if (token.precedingComments != null) {
+          ++spotCheckCount;
+          expect(token.precedingComments?.value,
+              '/* comment before closing paren */');
+          expect(token.precedingComments?.next, isNull);
+        }
+      }
+
+      token = token.next;
+    }
+    expect(tokenCount, 26);
+    expect(spotCheckCount, 3);
+    expect(commentTokenCount, 9);
+    expect(token.precedingComments?.value, '// EOF comment');
+  }
+
   @override
   @failingTest
   void test_comment_generic_method_type_assign() {
@@ -105,25 +187,21 @@
     super.test_mismatched_opener();
   }
 
-  @override
-  @failingTest
-  void test_scriptTag_withArgs() {
-    // TODO(paulberry,ahe): script tags are needed by analyzer.
-    super.test_scriptTag_withArgs();
-  }
-
-  @override
-  @failingTest
-  void test_scriptTag_withoutSpace() {
-    // TODO(paulberry,ahe): script tags are needed by analyzer.
-    super.test_scriptTag_withoutSpace();
-  }
-
-  @override
-  @failingTest
-  void test_scriptTag_withSpace() {
-    // TODO(paulberry,ahe): script tags are needed by analyzer.
-    super.test_scriptTag_withSpace();
+  void test_next_previous() {
+    const source = 'int a; /*1*/ /*2*/ /*3*/ B f(){if (a < 2) {}}';
+    fasta.Token token =
+        new fasta.StringScanner(source, includeComments: true).tokenize();
+    while (!token.isEof) {
+      expect(token.next.previousToken, token);
+      fasta.Token commentToken = token.precedingComments;
+      while (commentToken != null) {
+        if (commentToken.next != null) {
+          expect(commentToken.next.previousToken, commentToken);
+        }
+        commentToken = commentToken.next;
+      }
+      token = token.next;
+    }
   }
 
   @override
diff --git a/pkg/front_end/tool/fasta/abcompile.dart b/pkg/front_end/tool/fasta/abcompile.dart
new file mode 100644
index 0000000..3bedc4d
--- /dev/null
+++ b/pkg/front_end/tool/fasta/abcompile.dart
@@ -0,0 +1,160 @@
+import 'dart:async';
+import 'dart:convert';
+import 'dart:math';
+import 'dart:io';
+
+import 'standard_deviation.dart';
+
+const String bRootPath = const String.fromEnvironment("bRoot");
+const int iterations = const int.fromEnvironment("iterations", defaultValue: 1);
+
+/// Compare the performance of two different fast implementations
+/// by alternately launching the compile application in this directory
+/// and the compile application location in the repo specified by "bRoot"
+/// via -DbRoot=/absolute/path/to/other/sdk/repo
+main(List<String> args) async {
+  print(args);
+  if (bRootPath == null) {
+    print('Expected -DbRoot=/absolute/path/to/other/sdk/repo');
+    exit(1);
+  }
+
+  // The root of this Dart SDK repo "A"
+  Uri aRoot = Platform.script.resolve('../../../..');
+
+  // The root of the other Dart SDK repo "B"
+  Uri bRoot = new Uri.directory(bRootPath);
+
+  // Sanity check
+  String relPath = 'pkg/front_end/tool/fasta/compile.dart';
+  Uri aCompile = aRoot.resolve(relPath);
+  if (!new File(aCompile.toFilePath()).existsSync()) {
+    print('Failed to find $aCompile');
+    exit(1);
+  }
+  Uri bCompile = bRoot.resolve(relPath);
+  if (!new File(bCompile.toFilePath()).existsSync()) {
+    print('Failed to find $bCompile');
+    exit(1);
+  }
+
+  print('Comparing:');
+  print('A: $aCompile');
+  print('B: $bCompile');
+  print('');
+
+  List<double> aCold = <double>[];
+  List<double> aWarm = <double>[];
+  List<double> bCold = <double>[];
+  List<double> bWarm = <double>[];
+  for (int count = 0; count < 15; ++count) {
+    await run(aRoot, aCompile, args, aCold, aWarm);
+    await run(bRoot, bCompile, args, bCold, bWarm);
+  }
+
+  print('');
+  print('Raw data:');
+  print('A cold, A warm, B cold, B warm');
+  for (int index = 0; index < aCold.length; ++index) {
+    print('${aCold[index]}, ${aWarm[index]}, ${bCold[index]}, ${bWarm[index]}');
+  }
+
+  double aColdMean = average(aCold);
+  double aWarmMean = average(aWarm);
+  double bColdMean = average(bCold);
+  double bWarmMean = average(bWarm);
+
+  print('');
+  print('Average:');
+  print('$aColdMean, $aWarmMean, $bColdMean, $bWarmMean');
+
+  double aColdStdDev = standardDeviation(aColdMean, aCold);
+  double aWarmStdDev = standardDeviation(aWarmMean, aWarm);
+  double bColdStdDev = standardDeviation(bColdMean, bCold);
+  double bWarmStdDev = standardDeviation(bWarmMean, bWarm);
+
+  double aColdStdDevMean = standardDeviationOfTheMean(aCold, aColdStdDev);
+  double aWarmStdDevMean = standardDeviationOfTheMean(aWarm, aWarmStdDev);
+  double bColdStdDevMean = standardDeviationOfTheMean(bCold, bColdStdDev);
+  double bWarmStdDevMean = standardDeviationOfTheMean(bWarm, bWarmStdDev);
+
+  print('');
+  print('Uncertainty:');
+  print(
+      '$aColdStdDevMean, $aWarmStdDevMean, $bColdStdDevMean, $bWarmStdDevMean');
+
+  double coldDelta = aColdMean - bColdMean;
+  double coldStdDevMean =
+      sqrt(pow(aColdStdDevMean, 2) + pow(bColdStdDevMean, 2));
+  double warmDelta = aWarmMean - bWarmMean;
+  double warmStdDevMean =
+      sqrt(pow(aWarmStdDevMean, 2) + pow(bWarmStdDevMean, 2));
+
+  print('');
+  print('Summary:');
+  print('  A cold start - B cold start : $coldDelta');
+  print('  Uncertainty                 : $coldStdDevMean');
+  print('');
+  print('  A warm runs - B warm runs   : $warmDelta');
+  print('  Uncertainty                 : $warmStdDevMean');
+}
+
+const String _wroteProgram = 'Wrote program to';
+const String _coldStart = 'Cold start (first run):';
+const String _warmRun = 'Warm run average (runs #4';
+
+/// Launch the specified dart program, forwarding all arguments and environment
+/// that was passed to this program
+Future<Null> run(Uri workingDir, Uri dartApp, List<String> args,
+    List<double> cold, List<double> warm) async {
+  print('Running $dartApp');
+
+  void processLine(String line) {
+    if (line.contains(_wroteProgram)) {
+      // Show progress
+      stdout
+        ..write('.')
+        ..flush();
+      return;
+    }
+    int index = line.indexOf(_coldStart);
+    if (index >= 0) {
+      cold.add(double.parse(line.substring(index + _coldStart.length)));
+      print('\ncold: ${cold.last}');
+      return;
+    }
+    index = line.indexOf(_warmRun);
+    if (index >= 0) {
+      index = line.indexOf(':', index + _warmRun.length);
+      warm.add(double.parse(line.substring(index + 1)));
+      print('warm: ${warm.last}');
+      return;
+    }
+  }
+
+  String workingDirPath = workingDir.toFilePath();
+  List<String> procArgs = <String>[
+    '-Diterations=$iterations',
+    dartApp.toFilePath()
+  ];
+  procArgs.addAll(args);
+
+  Process process = await Process.start(Platform.executable, procArgs,
+      workingDirectory: workingDirPath);
+  stderr.addStream(process.stderr);
+  StreamSubscription<String> stdOutSubscription;
+  stdOutSubscription = process.stdout
+      .transform(UTF8.decoder)
+      .transform(new LineSplitter())
+      .listen(processLine, onDone: () {
+    stdOutSubscription.cancel();
+  }, onError: (e) {
+    print('Error: $e');
+    stdOutSubscription.cancel();
+  });
+  int code = await process.exitCode;
+  if (code != 0) {
+    throw 'fail: $code';
+  }
+  print('');
+}
diff --git a/pkg/front_end/tool/fasta/compile.dart b/pkg/front_end/tool/fasta/compile.dart
index fc7ccb3..a087b7a 100644
--- a/pkg/front_end/tool/fasta/compile.dart
+++ b/pkg/front_end/tool/fasta/compile.dart
@@ -2,6 +2,46 @@
 // 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/outline.dart' show compileEntryPoint;
+import 'package:front_end/src/fasta/outline.dart' as outline;
 
-main(List<String> arguments) => compileEntryPoint(arguments);
+import 'standard_deviation.dart';
+
+const int iterations = const int.fromEnvironment("iterations", defaultValue: 1);
+
+main(List<String> arguments) async {
+  // Timing results for each iteration
+  List<double> elapseTimes = <double>[];
+
+  for (int i = 0; i < iterations; i++) {
+    if (i > 0) {
+      print("\n");
+    }
+
+    var stopwatch = new Stopwatch()..start();
+    await outline.compile(arguments);
+    stopwatch.stop();
+
+    elapseTimes.add(stopwatch.elapsedMilliseconds.toDouble());
+  }
+
+  // No summary if less than 4 iterations
+  if (elapseTimes.length < 4) {
+    return;
+  }
+
+  // Calculate the mean of warm runs (#4 to n)
+  List<double> warmTimes = elapseTimes.sublist(3);
+  double mean = average(warmTimes);
+
+  // Calculate the standard deviation
+  double stdDev = standardDeviation(mean, warmTimes);
+
+  // Calculate the standard deviation of the mean
+  double stdDevOfTheMean = standardDeviationOfTheMean(warmTimes, stdDev);
+
+  print('Summary:');
+  print('  Elapse times: $elapseTimes');
+  print('  Cold start (first run): ${elapseTimes[0]}');
+  print('  Warm run average (runs #4 to #$iterations): $mean');
+  print('  Warm run standard deviation of the mean: $stdDevOfTheMean');
+}
diff --git a/pkg/front_end/tool/fasta/standard_deviation.dart b/pkg/front_end/tool/fasta/standard_deviation.dart
new file mode 100644
index 0000000..aa6e784
--- /dev/null
+++ b/pkg/front_end/tool/fasta/standard_deviation.dart
@@ -0,0 +1,18 @@
+import 'dart:math';
+
+double average(List<double> elapsedTimes) {
+  return elapsedTimes.reduce((v, e) => v + e) / elapsedTimes.length;
+}
+
+double standardDeviation(double mean, List<double> elapsedTimes) {
+  double numerator = 0.0;
+  for (double elapseTime in elapsedTimes) {
+    numerator += (elapseTime - mean) * (elapseTime - mean);
+  }
+  double stdDev = sqrt(numerator / (elapsedTimes.length - 1));
+  return stdDev;
+}
+
+double standardDeviationOfTheMean(List<double> elapsedTimes, double stdDev) {
+  return stdDev / sqrt(elapsedTimes.length);
+}
diff --git a/pkg/kernel/binary.md b/pkg/kernel/binary.md
index dc66d5d3..71f3d94 100644
--- a/pkg/kernel/binary.md
+++ b/pkg/kernel/binary.md
@@ -414,6 +414,7 @@
 
 type StaticSet extends Expression {
   Byte tag = 27;
+  FileOffset fileOffset;
   MemberReference target;
   Expression value;
 }
@@ -524,6 +525,7 @@
 
 type AsExpression extends Expression {
   Byte tag = 38;
+  FileOffset fileOffset;
   Expression operand;
   DartType type;
 }
@@ -586,6 +588,7 @@
 
 type Rethrow extends Expression {
   Byte tag = 47;
+  FileOffset fileOffset;
 }
 
 type Throw extends Expression {
@@ -596,12 +599,14 @@
 
 type ListLiteral extends Expression {
   Byte tag = 49;
+  FileOffset fileOffset;
   DartType typeArgument;
   List<Expression> values;
 }
 
 type ConstListLiteral extends Expression {
   Byte tag = 58; // Note: tag is out of order.
+  FileOffset fileOffset;
   DartType typeArgument;
   List<Expression> values;
 }
@@ -686,6 +691,7 @@
 
 type BreakStatement extends Statement {
   Byte tag = 66;
+  FileOffset fileOffset;
 
   // Reference to the Nth LabeledStatement in scope, with 0 being the
   // outermost enclosing labeled statement within the same FunctionNode.
@@ -801,7 +807,14 @@
 }
 
 type VariableDeclaration {
+  // The offset for the variable declaration, i.e. the offset of the start of
+  // the declaration.
   FileOffset fileOffset;
+
+  // The offset for the equal sign in the declaration (if it contains one).
+  // If it does not contain one this should be -1.
+  FileOffset fileEqualsOffset;
+
   Byte flags (isFinal, isConst);
   // For named parameters, this is the parameter name.
   // For other variables, the name is cosmetic, may be empty,
diff --git a/pkg/kernel/lib/analyzer/ast_from_analyzer.dart b/pkg/kernel/lib/analyzer/ast_from_analyzer.dart
index 2312947..fc8e730 100644
--- a/pkg/kernel/lib/analyzer/ast_from_analyzer.dart
+++ b/pkg/kernel/lib/analyzer/ast_from_analyzer.dart
@@ -528,7 +528,8 @@
         if (bodyHasVoidReturn(body)) {
           return new ast.ExpressionStatement(buildExpression(body.expression));
         } else {
-          return new ast.ReturnStatement(buildExpression(body.expression));
+          return new ast.ReturnStatement(buildExpression(body.expression))
+            ..fileOffset = body.expression.offset;
         }
       } else {
         return internalError('Missing function body');
@@ -578,8 +579,8 @@
     }
     int offset = formalParameters?.offset ?? body.offset;
     int endOffset = body.endToken.offset;
-    ast.AsyncMarker asyncMarker = getAsyncMarker(
-        isAsync: body.isAsynchronous, isStar: body.isGenerator);
+    ast.AsyncMarker asyncMarker =
+        getAsyncMarker(isAsync: body.isAsynchronous, isStar: body.isGenerator);
     return new ast.FunctionNode(buildOptionalFunctionBody(body),
         typeParameters: typeParameters,
         positionalParameters: positional,
@@ -670,8 +671,9 @@
   }
 
   ast.VariableDeclaration makeVariableDeclaration(LocalElement element,
-      {ast.DartType type, ast.Expression initializer}) {
+      {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;
@@ -967,7 +969,8 @@
         LocalElement local = decl.element as dynamic; // Cross cast.
         output.add(scope.makeVariableDeclaration(local,
             type: type,
-            initializer: scope.buildOptionalExpression(decl.initializer)));
+            initializer: scope.buildOptionalExpression(decl.initializer),
+            equalsOffset: decl.equals?.offset));
       }
     } else {
       output.add(build(node));
@@ -1181,7 +1184,8 @@
         LocalElement local = variable.element as dynamic; // Cross cast.
         variables.add(scope.makeVariableDeclaration(local,
             initializer: scope.buildOptionalExpression(variable.initializer),
-            type: type));
+            type: type,
+            equalsOffset: variable.equals?.offset));
       }
     } else if (node.initialization != null) {
       initialExpression = scope.buildExpression(node.initialization);
@@ -1370,7 +1374,12 @@
     if (result is Accessor) {
       result = result.buildSimpleRead();
     }
-    return result..fileOffset = _getOffset(node);
+    // 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) {
@@ -1388,10 +1397,14 @@
       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;
   }
@@ -1872,8 +1885,11 @@
 
   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)));
+          build(node.expression), scope.buildTypeAnnotation(node.type))
+        ..fileOffset = _getOffset(node));
     } else {
       return new ast.IsExpression(
           build(node.expression), scope.buildTypeAnnotation(node.type));
@@ -1922,11 +1938,15 @@
           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));
+          scope.resolveInterfaceFunctionCall(element))
+        ..fileOffset = node.methodName.end;
     } else if (isStaticMethod(element)) {
       var method = scope.resolveConcreteMethod(element);
       var arguments = buildArgumentsForInvocation(node);
@@ -1943,11 +1963,15 @@
             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));
+          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) {
@@ -2006,7 +2030,7 @@
         var leftHand = buildLeftHandValue(node.operand);
         var binaryOperator = new ast.Name(operator[0]);
         return leftHand.buildPostfixIncrement(binaryOperator,
-            offset: node.offset,
+            offset: node.operator.offset,
             voidContext: isInVoidContext(node),
             interfaceTarget: scope.resolveInterfaceMethod(node.staticElement));
 
diff --git a/pkg/kernel/lib/analyzer/loader.dart b/pkg/kernel/lib/analyzer/loader.dart
index 644184b..ca50228 100644
--- a/pkg/kernel/lib/analyzer/loader.dart
+++ b/pkg/kernel/lib/analyzer/loader.dart
@@ -4,6 +4,7 @@
 library kernel.analyzer.loader;
 
 import 'dart:async';
+import 'dart:convert';
 import 'dart:io' as io;
 
 import 'package:analyzer/analyzer.dart';
@@ -827,12 +828,13 @@
           in libraryElement.units) {
         var source = compilationUnitElement.source;
         LineInfo lineInfo = context.computeLineInfo(source);
-        String sourceCode;
+        List<int> sourceCode;
         try {
-          sourceCode = context.getContents(source).data;
+          sourceCode =
+              const Utf8Encoder().convert(context.getContents(source).data);
         } catch (e) {
           // The source's contents could not be accessed.
-          sourceCode = '';
+          sourceCode = const <int>[];
         }
         program.uriToSource['${source.uri}'] =
             new ast.Source(lineInfo.lineStarts, sourceCode);
diff --git a/pkg/kernel/lib/ast.dart b/pkg/kernel/lib/ast.dart
index aafafcd..c04a54d 100644
--- a/pkg/kernel/lib/ast.dart
+++ b/pkg/kernel/lib/ast.dart
@@ -95,9 +95,10 @@
 
   TreeNode parent;
 
-  /// Offset in the source file it comes from. Valid values are from 0 and up,
-  /// or -1 ([noOffset]) if the file offset is not available
-  /// (this is the default if none is specifically set).
+  /// Offset in the source file it comes from.
+  ///
+  /// Valid values are from 0 and up, or -1 ([noOffset]) if the file offset is
+  /// not available (this is the default if none is specifically set).
   int fileOffset = noOffset;
 
   accept(TreeVisitor v);
@@ -3313,6 +3314,13 @@
 //
 // DESIGN TODO: Should we remove the 'final' modifier from variables?
 class VariableDeclaration extends Statement {
+  /// Offset of the equals sign in the source file it comes from.
+  ///
+  /// Valid values are from 0 and up, or -1 ([TreeNode.noOffset])
+  /// if the equals sign offset is not available (e.g. if not initialized)
+  /// (this is the default if none is specifically set).
+  int fileEqualsOffset = TreeNode.noOffset;
+
   /// For named parameters, this is the name of the parameter. No two named
   /// parameters (in the same parameter list) can have the same name.
   ///
@@ -4019,7 +4027,7 @@
 
 class Source {
   final List<int> lineStarts;
-  final String source;
+  final List<int> source;
 
   Source(this.lineStarts, this.source);
 }
diff --git a/pkg/kernel/lib/binary/ast_from_binary.dart b/pkg/kernel/lib/binary/ast_from_binary.dart
index 9494706..aa9641b 100644
--- a/pkg/kernel/lib/binary/ast_from_binary.dart
+++ b/pkg/kernel/lib/binary/ast_from_binary.dart
@@ -4,6 +4,7 @@
 library kernel.ast_from_binary;
 
 import 'dart:convert';
+import 'dart:typed_data';
 
 import '../ast.dart';
 import '../transformations/flags.dart';
@@ -74,6 +75,13 @@
         readByte();
   }
 
+  List<int> readUtf8Bytes() {
+    List<int> bytes = new Uint8List(readUInt());
+    bytes.setRange(0, bytes.length, _bytes, _byteIndex);
+    _byteIndex += bytes.length;
+    return bytes;
+  }
+
   String readStringEntry() {
     int numBytes = readUInt();
     // Utf8Decoder will skip leading BOM characters, but we must preserve them.
@@ -271,7 +279,7 @@
     Map<String, Source> uriToSource = <String, Source>{};
     for (int i = 0; i < length; ++i) {
       String uri = _sourceUriTable[i];
-      String sourceCode = readStringEntry();
+      List<int> sourceCode = readUtf8Bytes();
       int lineCount = readUInt();
       List<int> lineStarts = new List<int>(lineCount);
       int previousLineStart = 0;
@@ -689,8 +697,9 @@
         return new StaticGet.byReference(readMemberReference())
           ..fileOffset = offset;
       case Tag.StaticSet:
+        int offset = readOffset();
         return new StaticSet.byReference(
-            readMemberReference(), readExpression());
+            readMemberReference(), readExpression())..fileOffset = offset;
       case Tag.MethodInvocation:
         int offset = readOffset();
         return new MethodInvocation.byReference(
@@ -744,7 +753,9 @@
         return new IsExpression(readExpression(), readDartType())
           ..fileOffset = offset;
       case Tag.AsExpression:
-        return new AsExpression(readExpression(), readDartType());
+        int offset = readOffset();
+        return new AsExpression(readExpression(), readDartType())
+          ..fileOffset = offset;
       case Tag.StringLiteral:
         return new StringLiteral(readStringReference());
       case Tag.SpecializedIntLiteral:
@@ -771,18 +782,21 @@
       case Tag.ThisExpression:
         return new ThisExpression();
       case Tag.Rethrow:
-        return new Rethrow();
+        int offset = readOffset();
+        return new Rethrow()..fileOffset = offset;
       case Tag.Throw:
         int offset = readOffset();
         return new Throw(readExpression())..fileOffset = offset;
       case Tag.ListLiteral:
+        int offset = readOffset();
         var typeArgument = readDartType();
         return new ListLiteral(readExpressionList(),
-            typeArgument: typeArgument, isConst: false);
+            typeArgument: typeArgument, isConst: false)..fileOffset = offset;
       case Tag.ConstListLiteral:
+        int offset = readOffset();
         var typeArgument = readDartType();
         return new ListLiteral(readExpressionList(),
-            typeArgument: typeArgument, isConst: true);
+            typeArgument: typeArgument, isConst: true)..fileOffset = offset;
       case Tag.MapLiteral:
         int offset = readOffset();
         var keyType = readDartType();
@@ -860,8 +874,10 @@
         labelStack.removeLast();
         return label;
       case Tag.BreakStatement:
+        int offset = readOffset();
         int index = readUInt();
-        return new BreakStatement(labelStack[labelStackBase + index]);
+        return new BreakStatement(labelStack[labelStackBase + index])
+          ..fileOffset = offset;
       case Tag.WhileStatement:
         return new WhileStatement(readExpression(), readStatement());
       case Tag.DoStatement:
@@ -1081,13 +1097,16 @@
 
   VariableDeclaration readVariableDeclaration() {
     int offset = readOffset();
+    int fileEqualsOffset = readOffset();
     int flags = readByte();
     return new VariableDeclaration(readStringOrNullIfEmpty(),
         type: readDartType(),
         inferredValue: readOptionalInferredValue(),
         initializer: readExpressionOption(),
         isFinal: flags & 0x1 != 0,
-        isConst: flags & 0x2 != 0)..fileOffset = offset;
+        isConst: flags & 0x2 != 0)
+      ..fileOffset = offset
+      ..fileEqualsOffset = fileEqualsOffset;
   }
 
   int readOffset() {
diff --git a/pkg/kernel/lib/binary/ast_to_binary.dart b/pkg/kernel/lib/binary/ast_to_binary.dart
index a242338..b612154 100644
--- a/pkg/kernel/lib/binary/ast_to_binary.dart
+++ b/pkg/kernel/lib/binary/ast_to_binary.dart
@@ -69,6 +69,11 @@
     writeByte(value & 0xFF);
   }
 
+  void writeUtf8Bytes(List<int> utf8Bytes) {
+    writeUInt30(utf8Bytes.length);
+    writeBytes(utf8Bytes);
+  }
+
   void writeStringTableEntry(String string) {
     List<int> utf8Bytes = const Utf8Encoder().convert(string);
     writeUInt30(utf8Bytes.length);
@@ -171,9 +176,9 @@
     writeStringTable(_sourceUriIndexer);
     for (int i = 0; i < _sourceUriIndexer.entries.length; i++) {
       String uri = _sourceUriIndexer.entries[i].value;
-      Source source = program.uriToSource[uri] ?? new Source([], '');
-      String sourceCode = source.source;
-      writeStringTableEntry(sourceCode);
+      Source source =
+          program.uriToSource[uri] ?? new Source(<int>[], const <int>[]);
+      writeUtf8Bytes(source.source);
       List<int> lineStarts = source.lineStarts;
       writeUInt30(lineStarts.length);
       int previousLineStart = 0;
@@ -515,6 +520,7 @@
 
   visitStaticSet(StaticSet node) {
     writeByte(Tag.StaticSet);
+    writeOffset(node, node.fileOffset);
     writeReference(node.targetReference);
     writeNode(node.value);
   }
@@ -615,6 +621,7 @@
 
   visitAsExpression(AsExpression node) {
     writeByte(Tag.AsExpression);
+    writeOffset(node, node.fileOffset);
     writeNode(node.operand);
     writeNode(node.type);
   }
@@ -675,6 +682,7 @@
 
   visitRethrow(Rethrow node) {
     writeByte(Tag.Rethrow);
+    writeOffset(node, node.fileOffset);
   }
 
   visitThrow(Throw node) {
@@ -685,6 +693,7 @@
 
   visitListLiteral(ListLiteral node) {
     writeByte(node.isConst ? Tag.ConstListLiteral : Tag.ListLiteral);
+    writeOffset(node, node.fileOffset);
     writeNode(node.typeArgument);
     writeNodeList(node.expressions);
   }
@@ -773,6 +782,7 @@
 
   visitBreakStatement(BreakStatement node) {
     writeByte(Tag.BreakStatement);
+    writeOffset(node, node.fileOffset);
     writeUInt30(_labelIndexer[node.target]);
   }
 
@@ -876,6 +886,7 @@
 
   void writeVariableDeclaration(VariableDeclaration node) {
     writeOffset(node, node.fileOffset);
+    writeOffset(node, node.fileEqualsOffset);
     writeByte(node.flags);
     writeStringReference(node.name ?? '');
     writeNode(node.type);
diff --git a/pkg/kernel/lib/transformations/closure/mock.dart b/pkg/kernel/lib/transformations/closure/mock.dart
index 95a4cbd..031501a 100644
--- a/pkg/kernel/lib/transformations/closure/mock.dart
+++ b/pkg/kernel/lib/transformations/closure/mock.dart
@@ -191,6 +191,6 @@
       name: "mock", classes: [contextClass])..fileUri = fileUri;
   program.libraries.add(mock);
   mock.parent = program;
-  program.uriToSource[mock.fileUri] = new Source(<int>[0], "");
+  program.uriToSource[mock.fileUri] = new Source(<int>[0], const <int>[]);
   return contextClass;
 }
diff --git a/pkg/kernel/lib/transformations/continuation.dart b/pkg/kernel/lib/transformations/continuation.dart
index 0b7afca..a8b2820 100644
--- a/pkg/kernel/lib/transformations/continuation.dart
+++ b/pkg/kernel/lib/transformations/continuation.dart
@@ -850,10 +850,9 @@
     var expr = node.expression == null
         ? new NullLiteral()
         : expressionRewriter.rewrite(node.expression, statements);
-    statements
-        .add(new ExpressionStatement(new VariableSet(returnVariable, expr)));
-    statements
-        .add(new BreakStatement(labeledBody)..fileOffset = node.fileOffset);
+    statements.add(new ExpressionStatement(
+        new VariableSet(returnVariable, expr)..fileOffset = node.fileOffset));
+    statements.add(new BreakStatement(labeledBody));
     return null;
   }
 }
diff --git a/pkg/kernel/testcases/strong-mode/call.baseline.txt b/pkg/kernel/testcases/strong-mode/call.baseline.txt
index 65b0561..baccef8 100644
--- a/pkg/kernel/testcases/strong-mode/call.baseline.txt
+++ b/pkg/kernel/testcases/strong-mode/call.baseline.txt
@@ -1,6 +1,6 @@
-// Too few positional arguments (call.dart:30:18)
-// Too few positional arguments (call.dart:31:26)
-// Too few positional arguments (call.dart:35:18)
+// Too few positional arguments (call.dart:30:25)
+// Too few positional arguments (call.dart:31:30)
+// Too few positional arguments (call.dart:35:26)
 // Too few positional arguments (call.dart:36:27)
 // Too few positional arguments (call.dart:37:32)
 library;
diff --git a/runtime/bin/platform_win.cc b/runtime/bin/platform_win.cc
index 640f99b..71a2743 100644
--- a/runtime/bin/platform_win.cc
+++ b/runtime/bin/platform_win.cc
@@ -19,6 +19,16 @@
 #include "bin/utils.h"
 #include "bin/utils_win.h"
 
+// These are not always defined in the header files. See:
+// https://msdn.microsoft.com/en-us/library/windows/desktop/ms686033(v=vs.85).aspx
+#ifndef ENABLE_VIRTUAL_TERMINAL_INPUT
+#define ENABLE_VIRTUAL_TERMINAL_INPUT 0x0200
+#endif
+
+#ifndef ENABLE_VIRTUAL_TERMINAL_PROCESSING
+#define ENABLE_VIRTUAL_TERMINAL_PROCESSING 0x0004
+#endif
+
 namespace dart {
 
 // Defined in vm/os_thread_win.cc
@@ -49,24 +59,52 @@
     SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX);
   }
 
-  static void SaveAndSetOutputCP() {
+  static void SaveAndConfigureConsole() {
     MutexLocker ml(platform_win_mutex_);
     ASSERT(saved_output_cp_ == -1);
     saved_output_cp_ = GetConsoleOutputCP();
     SetConsoleOutputCP(CP_UTF8);
+
+    HANDLE out = GetStdHandle(STD_OUTPUT_HANDLE);
+    if ((out != INVALID_HANDLE_VALUE) &&
+        GetConsoleMode(out, &saved_console_out_mode_)) {
+      const DWORD request =
+          saved_console_out_mode_ | ENABLE_VIRTUAL_TERMINAL_PROCESSING;
+      SetConsoleMode(out, request);
+    }
+
+    HANDLE in = GetStdHandle(STD_INPUT_HANDLE);
+    if ((in != INVALID_HANDLE_VALUE) &&
+        GetConsoleMode(in, &saved_console_in_mode_)) {
+      const DWORD request =
+          saved_console_in_mode_ | ENABLE_VIRTUAL_TERMINAL_INPUT;
+      SetConsoleMode(in, request);
+    }
   }
 
-  static void RestoreOutputCP() {
+  static void RestoreConsole() {
     MutexLocker ml(platform_win_mutex_);
     if (saved_output_cp_ != -1) {
       SetConsoleOutputCP(saved_output_cp_);
       saved_output_cp_ = -1;
     }
+    HANDLE out = GetStdHandle(STD_OUTPUT_HANDLE);
+    if (out != INVALID_HANDLE_VALUE) {
+      SetConsoleMode(out, saved_console_out_mode_);
+      saved_console_out_mode_ = 0;
+    }
+    HANDLE in = GetStdHandle(STD_INPUT_HANDLE);
+    if (in != INVALID_HANDLE_VALUE) {
+      SetConsoleMode(in, saved_console_in_mode_);
+      saved_console_in_mode_ = 0;
+    }
   }
 
  private:
   static Mutex* platform_win_mutex_;
   static int saved_output_cp_;
+  static DWORD saved_console_out_mode_;
+  static DWORD saved_console_in_mode_;
 
   static void InvalidParameterHandler(const wchar_t* expression,
                                       const wchar_t* function,
@@ -82,11 +120,13 @@
 };
 
 int PlatformWin::saved_output_cp_ = -1;
+DWORD PlatformWin::saved_console_out_mode_ = 0;
+DWORD PlatformWin::saved_console_in_mode_ = 0;
 Mutex* PlatformWin::platform_win_mutex_ = NULL;
 
 bool Platform::Initialize() {
   PlatformWin::InitOnce();
-  PlatformWin::SaveAndSetOutputCP();
+  PlatformWin::SaveAndConfigureConsole();
   return true;
 }
 
@@ -183,7 +223,7 @@
   // TODO(zra): Remove once VM shuts down cleanly.
   ::dart::private_flag_windows_run_tls_destructors = false;
   // Restore the console's output code page
-  PlatformWin::RestoreOutputCP();
+  PlatformWin::RestoreConsole();
   // On Windows we use ExitProcess so that threads can't clobber the exit_code.
   // See: https://code.google.com/p/nativeclient/issues/detail?id=2870
   ::ExitProcess(exit_code);
diff --git a/runtime/bin/secure_socket_boringssl.cc b/runtime/bin/secure_socket_boringssl.cc
index 41a6198..99a45f0 100644
--- a/runtime/bin/secure_socket_boringssl.cc
+++ b/runtime/bin/secure_socket_boringssl.cc
@@ -432,7 +432,7 @@
   SSLFilter::InitializeLibrary();
   SSL_CTX* ctx = SSL_CTX_new(TLS_method());
   SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, CertificateCallback);
-  SSL_CTX_set_min_version(ctx, TLS1_VERSION);
+  SSL_CTX_set_min_proto_version(ctx, TLS1_VERSION);
   SSL_CTX_set_cipher_list(ctx, "HIGH:MEDIUM");
   SSLContext* context = new SSLContext(ctx);
   Dart_Handle err = SetSecurityContext(args, context);
diff --git a/runtime/bin/vmservice/server.dart b/runtime/bin/vmservice/server.dart
index c789dcf..3d69463 100644
--- a/runtime/bin/vmservice/server.dart
+++ b/runtime/bin/vmservice/server.dart
@@ -233,21 +233,33 @@
       List fsNameList;
       List fsPathList;
       List fsPathBase64List;
+      List fsUriBase64List;
       Object fsName;
       Object fsPath;
+      Object fsUri;
 
       try {
         // Extract the fs name and fs path from the request headers.
         fsNameList = request.headers['dev_fs_name'];
         fsName = fsNameList[0];
 
-        fsPathList = request.headers['dev_fs_path'];
-        fsPathBase64List = request.headers['dev_fs_path_b64'];
-        // If the 'dev_fs_path_b64' header field was sent, use that instead.
-        if ((fsPathBase64List != null) && (fsPathBase64List.length > 0)) {
-          fsPath = UTF8.decode(BASE64.decode(fsPathBase64List[0]));
-        } else {
-          fsPath = fsPathList[0];
+        // Prefer Uri encoding first.
+        fsUriBase64List = request.headers['dev_fs_uri_b64'];
+        if ((fsUriBase64List != null) && (fsUriBase64List.length > 0)) {
+          String decodedFsUri = UTF8.decode(BASE64.decode(fsUriBase64List[0]));
+          fsUri = Uri.parse(decodedFsUri);
+        }
+
+        // Fallback to path encoding.
+        if (fsUri == null) {
+          fsPathList = request.headers['dev_fs_path'];
+          fsPathBase64List = request.headers['dev_fs_path_b64'];
+          // If the 'dev_fs_path_b64' header field was sent, use that instead.
+          if ((fsPathBase64List != null) && (fsPathBase64List.length > 0)) {
+            fsPath = UTF8.decode(BASE64.decode(fsPathBase64List[0]));
+          } else {
+            fsPath = fsPathList[0];
+          }
         }
       } catch (e) { /* ignore */ }
 
@@ -256,6 +268,7 @@
         result = await _service.devfs.handlePutStream(
             fsName,
             fsPath,
+            fsUri,
             request.transform(GZIP.decoder));
       } catch (e) { /* ignore */ }
 
diff --git a/runtime/lib/object.cc b/runtime/lib/object.cc
index e5cb7e1..308209a 100644
--- a/runtime/lib/object.cc
+++ b/runtime/lib/object.cc
@@ -82,9 +82,7 @@
   dart_arguments.SetAt(3, func_args);
   dart_arguments.SetAt(4, func_named_args);
 
-  if (is_method.value() &&
-      (((invocation_type.Value() >> InvocationMirror::kCallShift) &
-        InvocationMirror::kCallMask) != InvocationMirror::kSuper)) {
+  if (is_method.value()) {
     // Report if a function with same name (but different arguments) has been
     // found.
     Function& function = Function::Handle();
@@ -92,7 +90,12 @@
       function = Closure::Cast(instance).function();
     } else {
       Class& instance_class = Class::Handle(instance.clazz());
-      function = instance_class.LookupDynamicFunction(member_name);
+      const bool is_super_call =
+          ((invocation_type.Value() >> InvocationMirror::kCallShift) &
+           InvocationMirror::kCallMask) == InvocationMirror::kSuper;
+      if (!is_super_call) {
+        function = instance_class.LookupDynamicFunction(member_name);
+      }
       while (function.IsNull()) {
         instance_class = instance_class.SuperClass();
         if (instance_class.IsNull()) break;
diff --git a/runtime/lib/vmservice.cc b/runtime/lib/vmservice.cc
index 9d83c13..ad4e0fa 100644
--- a/runtime/lib/vmservice.cc
+++ b/runtime/lib/vmservice.cc
@@ -16,10 +16,12 @@
 #include "vm/service_event.h"
 #include "vm/service_isolate.h"
 #include "vm/symbols.h"
+#include "vm/kernel_isolate.h"
 
 namespace dart {
 
 DECLARE_FLAG(bool, trace_service);
+DECLARE_FLAG(bool, show_kernel_isolate);
 
 static uint8_t* malloc_allocator(uint8_t* ptr,
                                  intptr_t old_size,
@@ -57,8 +59,14 @@
 
   virtual void VisitIsolate(Isolate* isolate) {
     ASSERT(ServiceIsolate::IsServiceIsolate(Isolate::Current()));
-    if (IsVMInternalIsolate(isolate)) {
-      // We do not register the service (and descendants) or the vm-isolate.
+    bool is_kernel_isolate = false;
+#ifndef DART_PRECOMPILED_RUNTIME
+    is_kernel_isolate =
+        KernelIsolate::IsKernelIsolate(isolate) && !FLAG_show_kernel_isolate;
+#endif
+    if (IsVMInternalIsolate(isolate) || is_kernel_isolate) {
+      // We do not register the service (and descendants), the vm-isolate, or
+      // the kernel isolate.
       return;
     }
     // Setup arguments for call.
diff --git a/runtime/observatory/lib/src/elements/vm_view.dart b/runtime/observatory/lib/src/elements/vm_view.dart
index b635391..be5cdd7 100644
--- a/runtime/observatory/lib/src/elements/vm_view.dart
+++ b/runtime/observatory/lib/src/elements/vm_view.dart
@@ -211,7 +211,7 @@
                     ..text = 'native heap allocation count',
                   new DivElement()
                     ..classes = ['memberValue']
-                    ..text = _vm.heapAllocationCount
+                    ..text = '${_vm.heapAllocationCount}'
                 ],
  
               new BRElement(),
diff --git a/runtime/observatory/tests/service/add_breakpoint_rpc_kernel_test.dart b/runtime/observatory/tests/service/add_breakpoint_rpc_kernel_test.dart
new file mode 100644
index 0000000..39f3dcb
--- /dev/null
+++ b/runtime/observatory/tests/service/add_breakpoint_rpc_kernel_test.dart
@@ -0,0 +1,137 @@
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+// VMOptions=--error_on_bad_type --error_on_bad_override
+
+import 'package:observatory/service_io.dart';
+import 'package:unittest/unittest.dart';
+import 'service_test_common.dart';
+import 'test_helper.dart';
+
+import 'dart:async';
+
+const int LINE_A = 24;
+const int LINE_B = 26;
+
+int value = 0;
+
+int incValue(int amount) {
+  value += amount;
+  return amount;
+}
+
+Future testMain() async {
+  incValue(incValue(1)); // line A.
+
+  incValue(incValue(1)); // line B.
+}
+
+var tests = [
+  hasPausedAtStart,
+
+  // Test future breakpoints.
+  (Isolate isolate) async {
+    var rootLib = isolate.rootLibrary;
+    await rootLib.load();
+    var script = rootLib.scripts[0];
+
+    // Future breakpoint.
+    var futureBpt1 = await isolate.addBreakpoint(script, LINE_A);
+    expect(futureBpt1.number, equals(1));
+    expect(futureBpt1.resolved, isFalse);
+    expect(await futureBpt1.location.getLine(), equals(LINE_A));
+    expect(await futureBpt1.location.getColumn(), equals(null));
+
+    // Future breakpoint with specific column.
+    var futureBpt2 = await isolate.addBreakpoint(script, LINE_A, 3);
+    expect(futureBpt2.number, equals(2));
+    expect(futureBpt2.resolved, isFalse);
+    expect(await futureBpt2.location.getLine(), equals(LINE_A));
+    expect(await futureBpt2.location.getColumn(), equals(3));
+
+    int resolvedCount =
+        await resumeAndCountResolvedBreakpointsUntilPause(isolate);
+
+    // After resolution the breakpoints have assigned line & column.
+    expect(resolvedCount, equals(2));
+    expect(futureBpt1.resolved, isTrue);
+    expect(await futureBpt1.location.getLine(), equals(LINE_A));
+    expect(await futureBpt1.location.getColumn(), equals(12));
+    expect(futureBpt2.resolved, isTrue);
+    expect(await futureBpt2.location.getLine(), equals(LINE_A));
+    expect(await futureBpt2.location.getColumn(), equals(3));
+
+    // The first breakpoint hits before value is modified.
+    expect((await rootLib.evaluate('value')).valueAsString, equals('0'));
+
+    isolate.resume();
+    await hasStoppedAtBreakpoint(isolate);
+
+    // The second breakpoint hits after value has been modified once.
+    expect((await rootLib.evaluate('value')).valueAsString, equals('1'));
+
+    // Remove the breakpoints.
+    expect(
+        (await isolate.removeBreakpoint(futureBpt1)).type, equals('Success'));
+    expect(
+        (await isolate.removeBreakpoint(futureBpt2)).type, equals('Success'));
+  },
+
+  // Test resolution of column breakpoints.
+  (Isolate isolate) async {
+    var script = isolate.rootLibrary.scripts[0];
+    // Try all columns, including some columns that are too big.
+    for (int col = 1; col <= 50; col++) {
+      var bpt = await isolate.addBreakpoint(script, LINE_A, col);
+      expect(bpt.resolved, isTrue);
+      int resolvedLine = await bpt.location.getLine();
+      int resolvedCol = await bpt.location.getColumn();
+      print('$LINE_A:${col} -> ${resolvedLine}:${resolvedCol}');
+      if (col <= 10) {
+        expect(resolvedLine, equals(LINE_A));
+        expect(resolvedCol, equals(3));
+      } else if (col <= 19) {
+        expect(resolvedLine, equals(LINE_A));
+        expect(resolvedCol, equals(12));
+      } else {
+        expect(resolvedLine, equals(LINE_B));
+        expect(resolvedCol, equals(12));
+      }
+      expect((await isolate.removeBreakpoint(bpt)).type, equals('Success'));
+    }
+
+    // Make sure that a zero column is an error.
+    var caughtException = false;
+    try {
+      await isolate.addBreakpoint(script, 20, 0);
+      expect(false, isTrue, reason: 'Unreachable');
+    } on ServerRpcException catch (e) {
+      caughtException = true;
+      expect(e.code, equals(ServerRpcException.kInvalidParams));
+      expect(e.message, "addBreakpoint: invalid 'column' parameter: 0");
+    }
+    expect(caughtException, isTrue);
+  },
+];
+
+Future<int> resumeAndCountResolvedBreakpointsUntilPause(Isolate isolate) async {
+  var stream = await isolate.vm.getEventStream(VM.kDebugStream);
+  Completer completer = new Completer();
+  var subscription;
+  int resolvedCount = 0;
+  subscription = stream.listen((ServiceEvent event) async {
+    if (event.kind == ServiceEvent.kBreakpointResolved) {
+      resolvedCount++;
+    }
+    if (event.kind == ServiceEvent.kPauseBreakpoint) {
+      subscription.cancel();
+      completer.complete();
+    }
+  });
+  await isolate.resume();
+  await completer.future;
+  return resolvedCount;
+}
+
+main(args) => runIsolateTests(args, tests,
+    testeeConcurrent: testMain, pause_on_start: true);
diff --git a/runtime/observatory/tests/service/dev_fs_uri_test.dart b/runtime/observatory/tests/service/dev_fs_uri_test.dart
new file mode 100644
index 0000000..f8ae29c
--- /dev/null
+++ b/runtime/observatory/tests/service/dev_fs_uri_test.dart
@@ -0,0 +1,115 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+// VMOptions=--error_on_bad_type --error_on_bad_override
+
+import 'dart:async';
+import 'dart:convert';
+import 'dart:io';
+import 'package:observatory/service_io.dart';
+import 'package:unittest/unittest.dart';
+import 'test_helper.dart';
+
+Future<String> readResponse(HttpClientResponse response) {
+  var completer = new Completer();
+  var contents = new StringBuffer();
+  response.transform(UTF8.decoder).listen((String data) {
+    contents.write(data);
+  }, onDone: () => completer.complete(contents.toString()));
+  return completer.future;
+}
+
+
+var tests = [
+  // Write a file with the ? character in the filename.
+  (VM vm) async {
+    var fsId = 'test';
+    // NOTE: When using the URI encoding scheme, paths cannot be absolute.
+    var filePath = 'foo/bar.dat';
+    var fileUri = Uri.parse(filePath);
+    var fileUriBase64 = BASE64.encode(UTF8.encode(fileUri.toString()));
+    var fileContents = [0, 1, 2, 3, 4, 5, 6, 255];
+    var fileContentsBase64 = BASE64.encode(fileContents);
+
+    var filePath2 = 'baz/boo.dat';
+    var fileUri2 = Uri.parse(filePath2);
+
+    var result;
+    // Create DevFS.
+    result = await vm.invokeRpcNoUpgrade('_createDevFS', { 'fsName': fsId });
+    expect(result['type'], equals('FileSystem'));
+    expect(result['name'], equals(fsId));
+    expect(result['uri'], new isInstanceOf<String>());
+
+    // Write the file by issuing an HTTP PUT.
+    HttpClient client = new HttpClient();
+    HttpClientRequest request =
+        await client.putUrl(Uri.parse(serviceHttpAddress));
+    request.headers.add('dev_fs_name', fsId);
+    request.headers.add('dev_fs_uri_b64', fileUriBase64);
+    request.add(GZIP.encode([9]));
+    HttpClientResponse response = await request.close();
+    String responseBody = await readResponse(response);
+    result = JSON.decode(responseBody);
+    print(result);
+    expect(result['result']['type'], equals('Success'));
+
+    // Trigger an error by issuing an HTTP PUT.
+    request = await client.putUrl(Uri.parse(serviceHttpAddress));
+    request.headers.add('dev_fs_name', fsId);
+    // omit the 'dev_fs_path' parameter.
+    request.write(GZIP.encode(fileContents));
+    response = await request.close();
+    responseBody = await readResponse(response);
+    result = JSON.decode(responseBody);
+    Map error = result['error']['data'];
+    expect(error, isNotNull);
+    expect(error['details'].contains("expects the 'path' parameter"), isTrue);
+
+    // Write the file again but this time with the true file contents.
+    client = new HttpClient();
+    request =
+        await client.putUrl(Uri.parse(serviceHttpAddress));
+    request.headers.add('dev_fs_name', fsId);
+    request.headers.add('dev_fs_uri_b64', fileUriBase64);
+    request.add(GZIP.encode(fileContents));
+    response = await request.close();
+    responseBody = await readResponse(response);
+    result = JSON.decode(responseBody);
+    expect(result['result']['type'], equals('Success'));
+
+    // Close the HTTP client.
+    client.close();
+
+    // Read the file back.
+    result = await vm.invokeRpcNoUpgrade('_readDevFSFile', {
+        'fsName': fsId,
+        'uri': fileUri.toString(),
+    });
+    expect(result['type'], equals('FSFile'));
+    expect(result['fileContents'], equals(fileContentsBase64));
+
+    // Write a second file via URI.
+    result = await vm.invokeRpcNoUpgrade('_writeDevFSFile', {
+      'fsName': fsId,
+      'uri': fileUri2.toString(),
+      'fileContents': fileContentsBase64
+    });
+
+    // Read the second file back.
+    result = await vm.invokeRpcNoUpgrade('_readDevFSFile', {
+        'fsName': fsId,
+        'uri': fileUri2.toString(),
+    });
+    expect(result['type'], equals('FSFile'));
+    expect(result['fileContents'], equals(fileContentsBase64));
+
+    // Delete DevFS.
+    result = await vm.invokeRpcNoUpgrade('_deleteDevFS', {
+        'fsName': fsId,
+    });
+    expect(result['type'], equals('Success'));
+  },
+];
+
+main(args) async => runVMTests(args, tests);
diff --git a/runtime/observatory/tests/service/field_script_other.dart b/runtime/observatory/tests/service/field_script_other.dart
new file mode 100644
index 0000000..51f5c5a
--- /dev/null
+++ b/runtime/observatory/tests/service/field_script_other.dart
@@ -0,0 +1,7 @@
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+part of field_script_test;
+
+var otherField = 42;
\ No newline at end of file
diff --git a/runtime/observatory/tests/service/field_script_test.dart b/runtime/observatory/tests/service/field_script_test.dart
new file mode 100644
index 0000000..e5e8d44
--- /dev/null
+++ b/runtime/observatory/tests/service/field_script_test.dart
@@ -0,0 +1,42 @@
+// Copyright (c) 2017, 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 field_script_test;
+
+import 'package:observatory/service_io.dart';
+import 'package:unittest/unittest.dart';
+import 'test_helper.dart';
+import 'service_test_common.dart';
+
+part 'field_script_other.dart';
+
+code() {
+  print(otherField);
+}
+
+var tests = [
+  hasPausedAtStart,
+  (Isolate isolate) async {
+    Library lib = await isolate.rootLibrary.load();
+    var fields = lib.variables;
+    expect(fields.length, 2);
+    print(lib.variables);
+    for(Field f in fields) {
+      await f.load();
+      String locationString = await f.location.toUserString();
+      if (f.name == "tests") {
+        expect(locationString, "field_script_test.dart:18:5");
+      } else if (f.name == "otherField") {
+        expect(locationString, "field_script_other.dart:7:5");
+      } else {
+        fail("Unexpected field: ${f.name}");
+      }
+    }
+  }
+];
+
+main(args) {
+  runIsolateTestsSynchronous(args, tests,
+      testeeConcurrent: code, pause_on_start: true, pause_on_exit: true);
+}
diff --git a/runtime/observatory/tests/service/next_through_assign_call_test.dart b/runtime/observatory/tests/service/next_through_assign_call_test.dart
new file mode 100644
index 0000000..cc45913
--- /dev/null
+++ b/runtime/observatory/tests/service/next_through_assign_call_test.dart
@@ -0,0 +1,61 @@
+// Copyright (c) 2017, 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 'test_helper.dart';
+import 'service_test_common.dart';
+
+const int LINE_A = 12;
+const String file = "next_through_assign_call_test.dart";
+
+code() {
+  int a;
+  int b;
+  a = b = foo();
+  print(a);
+  print(b);
+  a = foo();
+  print(a);
+  int d = foo();
+  print(d);
+  int e = foo(), f, g = foo();
+  print(e);
+  print(f);
+  print(g);
+}
+
+foo() {
+  return 42;
+}
+
+List<String> stops = [];
+List<String> expected = [
+  "$file:${LINE_A+0}:7", // on variable 'a'
+  "$file:${LINE_A+1}:7", // on variable 'b'
+  "$file:${LINE_A+2}:11", // on call to 'foo'
+  "$file:${LINE_A+3}:3", // on call to 'print'
+  "$file:${LINE_A+4}:3", // on call to 'print'
+  "$file:${LINE_A+5}:7", // on call to 'foo'
+  "$file:${LINE_A+6}:3", // on call to 'print'
+  "$file:${LINE_A+7}:11", // on call to 'foo'
+  "$file:${LINE_A+8}:3", // on call to 'print'
+  "$file:${LINE_A+9}:11", // on first call to 'foo'
+  "$file:${LINE_A+9}:18", // on variable 'f'
+  "$file:${LINE_A+9}:25", // on second call to 'foo'
+  "$file:${LINE_A+10}:3", // on call to 'print'
+  "$file:${LINE_A+11}:3", // on call to 'print'
+  "$file:${LINE_A+12}:3", // on call to 'print'
+  "$file:${LINE_A+13}:1" // on ending '}'
+];
+
+var tests = [
+  hasPausedAtStart,
+  setBreakpointAtLine(LINE_A),
+  runStepThroughProgramRecordingStops(stops),
+  checkRecordedStops(stops, expected)
+];
+
+main(args) {
+  runIsolateTestsSynchronous(args, tests,
+      testeeConcurrent: code, pause_on_start: true, pause_on_exit: true);
+}
diff --git a/runtime/observatory/tests/service/next_through_assign_int_test.dart b/runtime/observatory/tests/service/next_through_assign_int_test.dart
new file mode 100644
index 0000000..8de5078
--- /dev/null
+++ b/runtime/observatory/tests/service/next_through_assign_int_test.dart
@@ -0,0 +1,57 @@
+// Copyright (c) 2017, 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 'test_helper.dart';
+import 'service_test_common.dart';
+
+const int LINE_A = 12;
+const String file = "next_through_assign_int_test.dart";
+
+code() {
+  int a;
+  int b;
+  a = b = 42;
+  print(a);
+  print(b);
+  a = 42;
+  print(a);
+  int d = 42;
+  print(d);
+  int e = 41, f, g = 42;
+  print(e);
+  print(f);
+  print(g);
+}
+
+List<String> stops = [];
+List<String> expected = [
+  "$file:${LINE_A+0}:7", // on variable 'a'
+  "$file:${LINE_A+1}:7", // on variable 'b'
+  "$file:${LINE_A+2}:7", // on 'b'
+  "$file:${LINE_A+3}:3", // on call to 'print'
+  "$file:${LINE_A+4}:3", // on call to 'print'
+  "$file:${LINE_A+5}:3", // on 'a'
+  "$file:${LINE_A+6}:3", // on call to 'print'
+  "$file:${LINE_A+7}:9", // on '='
+  "$file:${LINE_A+8}:3", // on call to 'print'
+  "$file:${LINE_A+9}:9", // on first '='
+  "$file:${LINE_A+9}:15", // on 'f'
+  "$file:${LINE_A+9}:20", // on second '='
+  "$file:${LINE_A+10}:3", // on call to 'print'
+  "$file:${LINE_A+11}:3", // on call to 'print'
+  "$file:${LINE_A+12}:3", // on call to 'print'
+  "$file:${LINE_A+13}:1" // on ending '}'
+];
+
+var tests = [
+  hasPausedAtStart,
+  setBreakpointAtLine(LINE_A),
+  runStepThroughProgramRecordingStops(stops),
+  checkRecordedStops(stops, expected)
+];
+
+main(args) {
+  runIsolateTestsSynchronous(args, tests,
+      testeeConcurrent: code, pause_on_start: true, pause_on_exit: true);
+}
diff --git a/runtime/observatory/tests/service/next_through_call_on_field_in_class_test.dart b/runtime/observatory/tests/service/next_through_call_on_field_in_class_test.dart
new file mode 100644
index 0000000..5e3d20d
--- /dev/null
+++ b/runtime/observatory/tests/service/next_through_call_on_field_in_class_test.dart
@@ -0,0 +1,47 @@
+// Copyright (c) 2017, 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 'test_helper.dart';
+import 'service_test_common.dart';
+
+const int LINE_A = 11;
+const String file = "next_through_call_on_field_in_class_test.dart";
+
+code() {
+  var foo = new Foo();
+  foo.foo = foo.fooMethod;
+  foo.fooMethod();
+  foo.foo();
+}
+
+class Foo {
+  var foo;
+
+  void fooMethod() {
+    print("Hello from fooMethod");
+  }
+}
+
+List<String> stops = [];
+List<String> expected = [
+  "$file:${LINE_A+0}:5", // after "code", i.e. on "("
+  "$file:${LINE_A+1}:17", // on "Foo"
+  "$file:${LINE_A+2}:17", // on "fooMethod"
+  "$file:${LINE_A+2}:7", // on "foo"
+  "$file:${LINE_A+3}:7", // on "fooMethod"
+  "$file:${LINE_A+4}:7", // on "foo"
+  "$file:${LINE_A+5}:1" // on ending '}'
+];
+
+var tests = [
+  hasPausedAtStart,
+  setBreakpointAtLine(LINE_A),
+  runStepThroughProgramRecordingStops(stops),
+  checkRecordedStops(stops, expected)
+];
+
+main(args) {
+  runIsolateTestsSynchronous(args, tests,
+      testeeConcurrent: code, pause_on_start: true, pause_on_exit: true);
+}
diff --git a/runtime/observatory/tests/service/next_through_call_on_field_test.dart b/runtime/observatory/tests/service/next_through_call_on_field_test.dart
new file mode 100644
index 0000000..a9f9f32
--- /dev/null
+++ b/runtime/observatory/tests/service/next_through_call_on_field_test.dart
@@ -0,0 +1,42 @@
+// Copyright (c) 2017, 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 'test_helper.dart';
+import 'service_test_common.dart';
+
+const int LINE_A = 13;
+const String file = "next_through_call_on_field_test.dart";
+
+var foo;
+
+code() {
+  foo = fooMethod;
+  fooMethod();
+  foo();
+}
+
+void fooMethod() {
+  print("Hello from fooMethod");
+}
+
+List<String> stops = [];
+List<String> expected = [
+  "$file:${LINE_A+0}:5", // after "code", i.e. on "("
+  "$file:${LINE_A+1}:3", // on "foo"
+  "$file:${LINE_A+2}:3", // on "fooMethod"
+  "$file:${LINE_A+3}:6", // after "foo" (on invisible ".call")
+  "$file:${LINE_A+4}:1" // on ending '}'
+];
+
+var tests = [
+  hasPausedAtStart,
+  setBreakpointAtLine(LINE_A),
+  runStepThroughProgramRecordingStops(stops),
+  checkRecordedStops(stops, expected)
+];
+
+main(args) {
+  runIsolateTestsSynchronous(args, tests,
+      testeeConcurrent: code, pause_on_start: true, pause_on_exit: true);
+}
diff --git a/runtime/observatory/tests/service/next_through_call_on_static_field_in_class_test.dart b/runtime/observatory/tests/service/next_through_call_on_static_field_in_class_test.dart
new file mode 100644
index 0000000..ef03214
--- /dev/null
+++ b/runtime/observatory/tests/service/next_through_call_on_static_field_in_class_test.dart
@@ -0,0 +1,44 @@
+// Copyright (c) 2017, 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 'test_helper.dart';
+import 'service_test_common.dart';
+
+const int LINE_A = 11;
+const String file = "next_through_call_on_static_field_in_class_test.dart";
+
+code() {
+  Foo.foo = Foo.fooMethod;
+  Foo.fooMethod();
+  Foo.foo();
+}
+
+class Foo {
+  static var foo;
+
+  static void fooMethod() {
+    print("Hello from fooMethod");
+  }
+}
+
+List<String> stops = [];
+List<String> expected = [
+  "$file:${LINE_A+0}:5", // after "code", i.e. on "("
+  "$file:${LINE_A+1}:7", // on "foo"
+  "$file:${LINE_A+2}:7", // on "fooMethod"
+  "$file:${LINE_A+3}:10", // after "foo" (on invisible ".call")
+  "$file:${LINE_A+4}:1" // on ending '}'
+];
+
+var tests = [
+  hasPausedAtStart,
+  setBreakpointAtLine(LINE_A),
+  runStepThroughProgramRecordingStops(stops),
+  checkRecordedStops(stops, expected)
+];
+
+main(args) {
+  runIsolateTestsSynchronous(args, tests,
+      testeeConcurrent: code, pause_on_start: true, pause_on_exit: true);
+}
diff --git a/runtime/observatory/tests/service/next_through_catch_test.dart b/runtime/observatory/tests/service/next_through_catch_test.dart
new file mode 100644
index 0000000..0b0e924
--- /dev/null
+++ b/runtime/observatory/tests/service/next_through_catch_test.dart
@@ -0,0 +1,49 @@
+// Copyright (c) 2017, 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 'test_helper.dart';
+import 'service_test_common.dart';
+
+const int LINE_A = 12;
+const String file = "next_through_catch_test.dart";
+
+code() {
+  try {
+    var value = "world";
+    throw "Hello, $value";
+  } catch(e, st) {
+    print(e);
+    print(st);
+  }
+  try {
+    throw "Hello, world";
+  } catch(e, st) {
+    print(e);
+    print(st);
+  }
+}
+
+List<String> stops = [];
+List<String> expected = [
+  "$file:${LINE_A+1}:15", // on '='
+  "$file:${LINE_A+2}:26", // after last '"' (i.e. before ';')
+  "$file:${LINE_A+4}:5", // on call to 'print'
+  "$file:${LINE_A+5}:5", // on call to 'print'
+  "$file:${LINE_A+8}:5", // on 'throw'
+  "$file:${LINE_A+10}:5", // on call to 'print'
+  "$file:${LINE_A+11}:5", // on call to 'print'
+  "$file:${LINE_A+13}:1" // on ending '}'
+];
+
+var tests = [
+  hasPausedAtStart,
+  setBreakpointAtLine(LINE_A),
+  runStepThroughProgramRecordingStops(stops),
+  checkRecordedStops(stops, expected)
+];
+
+main(args) {
+  runIsolateTestsSynchronous(args, tests,
+      testeeConcurrent: code, pause_on_start: true, pause_on_exit: true);
+}
diff --git a/runtime/observatory/tests/service/next_through_closure_test.dart b/runtime/observatory/tests/service/next_through_closure_test.dart
new file mode 100644
index 0000000..f7295a7
--- /dev/null
+++ b/runtime/observatory/tests/service/next_through_closure_test.dart
@@ -0,0 +1,40 @@
+// Copyright (c) 2017, 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 'test_helper.dart';
+import 'service_test_common.dart';
+
+const int LINE_A = 14;
+const String file = "next_through_closure_test.dart";
+
+codeXYZ(int i) {
+  var x = () =>
+      // some comment here to allow this formatting
+      i * i; // LINE_A
+  return x();
+}
+
+code() {
+  codeXYZ(42);
+}
+
+List<String> stops = [];
+List<String> expected = [
+  "$file:${LINE_A+0}:9", // on '*'
+  "$file:${LINE_A+0}:7", // on first 'i'
+  "$file:${LINE_A+1}:3", // on 'return'
+  "$file:${LINE_A+6}:1" // on ending '}'
+];
+
+var tests = [
+  hasPausedAtStart,
+  setBreakpointAtLine(LINE_A),
+  runStepThroughProgramRecordingStops(stops),
+  checkRecordedStops(stops, expected)
+];
+
+main(args) {
+  runIsolateTestsSynchronous(args, tests,
+      testeeConcurrent: code, pause_on_start: true, pause_on_exit: true);
+}
diff --git a/runtime/observatory/tests/service/next_through_create_list_and_map_test.dart b/runtime/observatory/tests/service/next_through_create_list_and_map_test.dart
new file mode 100644
index 0000000..9513858
--- /dev/null
+++ b/runtime/observatory/tests/service/next_through_create_list_and_map_test.dart
@@ -0,0 +1,91 @@
+// Copyright (c) 2017, 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 'test_helper.dart';
+import 'service_test_common.dart';
+
+const int LINE_A = 12;
+const String file = "next_through_create_list_and_map_test.dart";
+
+code() {
+  List<int> myList = [
+    1234567890,
+    1234567891,
+    1234567892,
+    1234567893,
+    1234567894
+  ];
+  List<int> myConstList = const [
+    1234567890,
+    1234567891,
+    1234567892,
+    1234567893,
+    1234567894
+  ];
+  Map<int, int> myMap = {
+    1: 42,
+    2: 43,
+    33242344: 432432432,
+    443243232: 543242454
+  };
+  Map<int, int> myConstMap = const {
+    1: 42,
+    2: 43,
+    33242344: 432432432,
+    443243232: 543242454
+  };
+  print(myList);
+  print(myConstList);
+  int lookup = myMap[1];
+  print(lookup);
+  print(myMap);
+  print(myConstMap);
+  print(myMap[2]);
+}
+
+List<String> stops = [];
+List<String> expected = [
+  // Initialize list (on '[')
+  "$file:${LINE_A+0}:22",
+
+  // Initialize const list (on '=')
+  "$file:${LINE_A+7}:25",
+
+  // Initialize map (on '{')
+  "$file:${LINE_A+14}:25",
+
+  // Initialize const map (on '=')
+  "$file:${LINE_A+20}:28",
+
+  // Prints (on call to 'print')
+  "$file:${LINE_A+26}:3",
+  "$file:${LINE_A+27}:3",
+
+  // Lookup (on '[')
+  "$file:${LINE_A+28}:21",
+
+  // Prints (on call to 'print')
+  "$file:${LINE_A+29}:3",
+  "$file:${LINE_A+30}:3",
+  "$file:${LINE_A+31}:3",
+
+  // Lookup (on '[') + print (on call to 'print')
+  "$file:${LINE_A+32}:14",
+  "$file:${LINE_A+32}:3",
+
+  // End (on ending '}')
+  "$file:${LINE_A+33}:1"
+];
+
+var tests = [
+  hasPausedAtStart,
+  setBreakpointAtLine(LINE_A),
+  runStepThroughProgramRecordingStops(stops),
+  checkRecordedStops(stops, expected)
+];
+
+main(args) {
+  runIsolateTestsSynchronous(args, tests,
+      testeeConcurrent: code, pause_on_start: true, pause_on_exit: true);
+}
diff --git a/runtime/observatory/tests/service/next_through_for_each_loop_test.dart b/runtime/observatory/tests/service/next_through_for_each_loop_test.dart
new file mode 100644
index 0000000..20d26bb
--- /dev/null
+++ b/runtime/observatory/tests/service/next_through_for_each_loop_test.dart
@@ -0,0 +1,62 @@
+// Copyright (c) 2017, 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 'test_helper.dart';
+import 'service_test_common.dart';
+
+const int LINE_A = 12;
+const String file = "next_through_for_each_loop_test.dart";
+
+code() {
+  List<int> data = [1, 2, 3, 4];
+  for(int datapoint in data) {
+    print(datapoint);
+  }
+}
+
+List<String> stops = [];
+List<String> expected = [
+  // Initialize data (on '[')
+  "$file:${LINE_A+0}:20",
+
+  // Twice for some reason on data (on 'data')
+  "$file:${LINE_A+1}:24",
+
+  // An iteration of the loop apparently is "data", "{", then inside loop
+  // (on call to 'print')
+  "$file:${LINE_A+1}:24",
+  "$file:${LINE_A+1}:30",
+  "$file:${LINE_A+2}:5",
+
+  // Iteration 2
+  "$file:${LINE_A+1}:24",
+  "$file:${LINE_A+1}:30",
+  "$file:${LINE_A+2}:5",
+
+  // Iteration 3
+  "$file:${LINE_A+1}:24",
+  "$file:${LINE_A+1}:30",
+  "$file:${LINE_A+2}:5",
+
+  // Iteration 4
+  "$file:${LINE_A+1}:24",
+  "$file:${LINE_A+1}:30",
+  "$file:${LINE_A+2}:5",
+
+  // End: Apparently we go to data again, then on the final "}"
+  "$file:${LINE_A+1}:24",
+  "$file:${LINE_A+4}:1"
+];
+
+var tests = [
+  hasPausedAtStart,
+  setBreakpointAtLine(LINE_A),
+  runStepThroughProgramRecordingStops(stops),
+  checkRecordedStops(stops, expected)
+];
+
+main(args) {
+  runIsolateTestsSynchronous(args, tests,
+      testeeConcurrent: code, pause_on_start: true, pause_on_exit: true);
+}
diff --git a/runtime/observatory/tests/service/next_through_for_loop_with_break_and_continue_test.dart b/runtime/observatory/tests/service/next_through_for_loop_with_break_and_continue_test.dart
new file mode 100644
index 0000000..b353a38
--- /dev/null
+++ b/runtime/observatory/tests/service/next_through_for_loop_with_break_and_continue_test.dart
@@ -0,0 +1,74 @@
+// Copyright (c) 2017, 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 'test_helper.dart';
+import 'service_test_common.dart';
+
+const int LINE_A = 12;
+const String file = "next_through_for_loop_with_break_and_continue_test.dart";
+
+code() {
+  int count = 0;
+  for(int i = 0; i < 42; ++i) {
+    if (i == 2) {
+      continue;
+    }
+    if (i == 3) {
+      break;
+    }
+    count++;
+  }
+  print(count);
+}
+
+List<String> stops = [];
+List<String> expected = [
+  // Initialization (on '='), loop start (on '='),
+  // first iteration (on '<', on '==', on '==', on '++')
+  "$file:${LINE_A+0}:13",
+  "$file:${LINE_A+1}:13",
+  "$file:${LINE_A+1}:20",
+  "$file:${LINE_A+2}:11",
+  "$file:${LINE_A+5}:11",
+  "$file:${LINE_A+8}:10",
+
+  // Second iteration of loop: Full run
+  // (on '++', on '<', on '==', on '==', on '++')
+  "$file:${LINE_A+1}:26",
+  "$file:${LINE_A+1}:20",
+  "$file:${LINE_A+2}:11",
+  "$file:${LINE_A+5}:11",
+  "$file:${LINE_A+8}:10",
+
+  // Third iteration of loop: continue
+  // (on '++', on '<', on '==', on 'continue')
+  "$file:${LINE_A+1}:26",
+  "$file:${LINE_A+1}:20",
+  "$file:${LINE_A+2}:11",
+  "$file:${LINE_A+3}:7",
+
+  // Forth iteration of loop: break
+  // (on '++', on '<', on '==' on '==', on 'break')
+  "$file:${LINE_A+1}:26",
+  "$file:${LINE_A+1}:20",
+  "$file:${LINE_A+2}:11",
+  "$file:${LINE_A+5}:11",
+  "$file:${LINE_A+6}:7",
+
+  // End (on call to 'print' and on ending '}')
+  "$file:${LINE_A+10}:3",
+  "$file:${LINE_A+11}:1"
+];
+
+var tests = [
+  hasPausedAtStart,
+  setBreakpointAtLine(LINE_A),
+  runStepThroughProgramRecordingStops(stops),
+  checkRecordedStops(stops, expected)
+];
+
+main(args) {
+  runIsolateTestsSynchronous(args, tests,
+      testeeConcurrent: code, pause_on_start: true, pause_on_exit: true);
+}
diff --git a/runtime/observatory/tests/service/next_through_function_expression_test.dart b/runtime/observatory/tests/service/next_through_function_expression_test.dart
new file mode 100644
index 0000000..eacea55
--- /dev/null
+++ b/runtime/observatory/tests/service/next_through_function_expression_test.dart
@@ -0,0 +1,40 @@
+// Copyright (c) 2017, 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 'test_helper.dart';
+import 'service_test_common.dart';
+
+const int LINE_A = 11;
+const String file = "next_through_function_expression_test.dart";
+
+codeXYZ(int i) {
+  innerOne() {
+    return i * i;
+  }
+  return innerOne();
+}
+
+code() {
+  codeXYZ(42);
+}
+
+List<String> stops = [];
+List<String> expected = [
+  "$file:${LINE_A+0}:13", // on 'i' in 'codeXYZ(int i)'
+  "$file:${LINE_A+1}:3", // on 'innerOne'
+  "$file:${LINE_A+4}:18", // on '(', i.e. after 'innerOne' call
+  "$file:${LINE_A+4}:3" // on 'return'
+];
+
+var tests = [
+  hasPausedAtStart,
+  setBreakpointAtLine(LINE_A),
+  runStepThroughProgramRecordingStops(stops),
+  checkRecordedStops(stops, expected)
+];
+
+main(args) {
+  runIsolateTestsSynchronous(args, tests,
+      testeeConcurrent: code, pause_on_start: true, pause_on_exit: true);
+}
diff --git a/runtime/observatory/tests/service/next_through_is_and_as_test.dart b/runtime/observatory/tests/service/next_through_is_and_as_test.dart
new file mode 100644
index 0000000..5018dcc
--- /dev/null
+++ b/runtime/observatory/tests/service/next_through_is_and_as_test.dart
@@ -0,0 +1,66 @@
+// Copyright (c) 2017, 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 'test_helper.dart';
+import 'service_test_common.dart';
+
+const int LINE_A = 12;
+const String file = "next_through_is_and_as_test.dart";
+
+code() {
+  var i = 42.42;
+  var hex = 0x42;
+  if (i is int) {
+    print("i is int");
+    int x = i as int;
+    if (x.isEven) {
+      print("it's even even!");
+    } else {
+      print("but it's not even even!");
+    }
+  }
+  if (i is! int) {
+    print("i is not int");
+  }
+  if (hex is int) {
+    print("hex is int");
+    int x = hex as int;
+    if (x.isEven) {
+      print("it's even even!");
+    } else {
+      print("but it's not even even!");
+    }
+  }
+  if (hex is! int) {
+    print("hex is not int");
+  }
+}
+
+List<String> stops = [];
+List<String> expected = [
+  "$file:${LINE_A+0}:9", // on '='
+  "$file:${LINE_A+1}:11", // on '"'
+  "$file:${LINE_A+2}:9", // on 'is'
+  "$file:${LINE_A+11}:9", // on 'is!'
+  "$file:${LINE_A+12}:5", // on call to 'print'
+  "$file:${LINE_A+14}:11", // in 'is'
+  "$file:${LINE_A+15}:5", // on call to 'print'
+  "$file:${LINE_A+16}:17", // on 'as'
+  "$file:${LINE_A+17}:11", // on 'isEven'
+  "$file:${LINE_A+18}:7", // on call to 'print'
+  "$file:${LINE_A+23}:11", // on 'is!'
+  "$file:${LINE_A+26}:1" // on ending '}'
+];
+
+var tests = [
+  hasPausedAtStart,
+  setBreakpointAtLine(LINE_A),
+  runStepThroughProgramRecordingStops(stops),
+  checkRecordedStops(stops, expected)
+];
+
+main(args) {
+  runIsolateTestsSynchronous(args, tests,
+      testeeConcurrent: code, pause_on_start: true, pause_on_exit: true);
+}
diff --git a/runtime/observatory/tests/service/next_through_new_test.dart b/runtime/observatory/tests/service/next_through_new_test.dart
new file mode 100644
index 0000000..552b4e6
--- /dev/null
+++ b/runtime/observatory/tests/service/next_through_new_test.dart
@@ -0,0 +1,37 @@
+// Copyright (c) 2017, 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 'test_helper.dart';
+import 'service_test_common.dart';
+
+const int LINE_A = 11;
+const String file = "next_through_new_test.dart";
+
+code() {
+  var x = new Foo();
+  return x;
+}
+
+class Foo {
+  var x;
+}
+
+List<String> stops = [];
+List<String> expected = [
+  "$file:${LINE_A+0}:5", // on '(' in 'code()'
+  "$file:${LINE_A+1}:15", // on 'Foo'
+  "$file:${LINE_A+2}:3" // on 'return'
+];
+
+var tests = [
+  hasPausedAtStart,
+  setBreakpointAtLine(LINE_A),
+  runStepThroughProgramRecordingStops(stops),
+  checkRecordedStops(stops, expected)
+];
+
+main(args) {
+  runIsolateTestsSynchronous(args, tests,
+      testeeConcurrent: code, pause_on_start: true, pause_on_exit: true);
+}
diff --git a/runtime/observatory/tests/service/next_through_simple_async_test.dart b/runtime/observatory/tests/service/next_through_simple_async_test.dart
new file mode 100644
index 0000000..8e948d3
--- /dev/null
+++ b/runtime/observatory/tests/service/next_through_simple_async_test.dart
@@ -0,0 +1,51 @@
+// Copyright (c) 2017, 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 'test_helper.dart';
+import 'service_test_common.dart';
+import 'dart:io';
+
+const int LINE_A = 13;
+const String file = "next_through_simple_async_test.dart";
+
+// line A is at the "code() async" line
+code() async {
+  File f = new File(Platform.script.toFilePath());
+  DateTime modified = await f.lastModified();
+  bool exists = await f.exists();
+  print("Modified: $modified; exists: $exists");
+  foo();
+}
+
+foo() {
+  print("Hello from Foo!");
+}
+
+List<String> stops = [];
+List<String> expected = [
+  "$file:${LINE_A+0}:5", // on '(' in code()'
+  "$file:${LINE_A+1}:30", // on 'script'
+  "$file:${LINE_A+1}:37", // on 'toFilePath'
+  "$file:${LINE_A+1}:16", // on File
+  "$file:${LINE_A+2}:31", // on 'lastModified'
+  "$file:${LINE_A+2}:23", // on 'await'
+  "$file:${LINE_A+3}:25", // on 'exists'
+  "$file:${LINE_A+3}:17", // on 'await'
+  "$file:${LINE_A+4}:47", // on ')', i.e. before ';'
+  "$file:${LINE_A+4}:3", // on call to 'print'
+  "$file:${LINE_A+5}:3", // on call to 'foo'
+  "$file:${LINE_A+6}:1" // ending '}'
+];
+
+var tests = [
+  hasPausedAtStart,
+  setBreakpointAtLine(LINE_A),
+  runStepThroughProgramRecordingStops(stops),
+  checkRecordedStops(stops, expected)
+];
+
+main(args) {
+  runIsolateTestsSynchronous(args, tests,
+      testeeConcurrent: code, pause_on_start: true, pause_on_exit: true);
+}
diff --git a/runtime/observatory/tests/service/next_through_simple_async_with_returns_test.dart b/runtime/observatory/tests/service/next_through_simple_async_with_returns_test.dart
new file mode 100644
index 0000000..e137345
--- /dev/null
+++ b/runtime/observatory/tests/service/next_through_simple_async_with_returns_test.dart
@@ -0,0 +1,47 @@
+// Copyright (c) 2017, 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 'test_helper.dart';
+import 'service_test_common.dart';
+import 'dart:io';
+
+const int LINE_A = 13;
+const String file = "next_through_simple_async_with_returns_test.dart";
+
+// line A is at the "code() async" line
+code() async {
+  File f = new File(Platform.script.toFilePath());
+  bool exists = await f.exists();
+  if (exists) {
+    return 42;
+  }
+  foo();
+}
+
+foo() {
+  print("Hello from Foo!");
+}
+
+List<String> stops = [];
+List<String> expected = [
+  "$file:${LINE_A+0}:5", // on '(' in 'code()'
+  "$file:${LINE_A+1}:30", // on 'script'
+  "$file:${LINE_A+1}:37", // on 'toFilePath'
+  "$file:${LINE_A+1}:16", // on 'File'
+  "$file:${LINE_A+2}:25", // on 'exists'
+  "$file:${LINE_A+2}:17", // on 'await'
+  "$file:${LINE_A+4}:5" // on 'return'
+];
+
+var tests = [
+  hasPausedAtStart,
+  setBreakpointAtLine(LINE_A),
+  runStepThroughProgramRecordingStops(stops),
+  checkRecordedStops(stops, expected)
+];
+
+main(args) {
+  runIsolateTestsSynchronous(args, tests,
+      testeeConcurrent: code, pause_on_start: true, pause_on_exit: true);
+}
diff --git a/runtime/observatory/tests/service/next_through_simple_linear_2_test.dart b/runtime/observatory/tests/service/next_through_simple_linear_2_test.dart
new file mode 100644
index 0000000..cda8f6e
--- /dev/null
+++ b/runtime/observatory/tests/service/next_through_simple_linear_2_test.dart
@@ -0,0 +1,42 @@
+// Copyright (c) 2017, 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 'test_helper.dart';
+import 'service_test_common.dart';
+
+const int LINE_A = 15;
+const String file = "next_through_simple_linear_2_test.dart";
+
+code() {
+  var a = getA();
+  var b = getB();
+
+  print("Hello, World!"); // LINE_A
+  print("a: $a; b: $b");
+  print("Goodbye, world!");
+}
+
+getA() => true;
+getB() => 42;
+
+List<String> stops = [];
+List<String> expected = [
+  "$file:$LINE_A:3", // on call to 'print'
+  "$file:${LINE_A+1}:23", // on ')', i.e. before ';'
+  "$file:${LINE_A+1}:3", // on call to 'print'
+  "$file:${LINE_A+2}:3", // on call to 'print'
+  "$file:${LINE_A+3}:1" // on ending '}'
+];
+
+var tests = [
+  hasPausedAtStart,
+  setBreakpointAtLine(LINE_A),
+  runStepThroughProgramRecordingStops(stops),
+  checkRecordedStops(stops, expected)
+];
+
+main(args) {
+  runIsolateTestsSynchronous(args, tests,
+      testeeConcurrent: code, pause_on_start: true, pause_on_exit: true);
+}
diff --git a/runtime/observatory/tests/service/next_through_simple_linear_test.dart b/runtime/observatory/tests/service/next_through_simple_linear_test.dart
new file mode 100644
index 0000000..278458e
--- /dev/null
+++ b/runtime/observatory/tests/service/next_through_simple_linear_test.dart
@@ -0,0 +1,35 @@
+// Copyright (c) 2017, 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 'test_helper.dart';
+import 'service_test_common.dart';
+
+const int LINE_A = 12;
+const String file = "next_through_simple_linear_test.dart";
+
+code() {
+  print("Hello, World!"); // LINE_A
+  print("Stop here too!");
+  print("Goodbye, world!");
+}
+
+List<String> stops = [];
+List<String> expected = [
+  "$file:${LINE_A+0}:3", // on call to 'print'
+  "$file:${LINE_A+1}:3", // on call to 'print'
+  "$file:${LINE_A+2}:3", // on call to 'print'
+  "$file:${LINE_A+3}:1" // on ending '}'
+];
+
+var tests = [
+  hasPausedAtStart,
+  setBreakpointAtLine(LINE_A),
+  runStepThroughProgramRecordingStops(stops),
+  checkRecordedStops(stops, expected)
+];
+
+main(args) {
+  runIsolateTestsSynchronous(args, tests,
+      testeeConcurrent: code, pause_on_start: true, pause_on_exit: true);
+}
diff --git a/runtime/observatory/tests/service/rewind_optimized_out_test.dart b/runtime/observatory/tests/service/rewind_optimized_out_test.dart
index 23b8c9a..d6a246d 100644
--- a/runtime/observatory/tests/service/rewind_optimized_out_test.dart
+++ b/runtime/observatory/tests/service/rewind_optimized_out_test.dart
@@ -68,9 +68,10 @@
       caughtException = true;
       expect(e.code, equals(ServerRpcException.kCannotResume));
       expect(e.message,
-             'Cannot rewind to frame 1 due to conflicting compiler '
-             'optimizations. Run the vm with --no-prune-dead-locals to '
-             'disallow these optimizations. Next valid rewind frame is 4.');
+             startsWith('Cannot rewind to frame 1 due to conflicting compiler '
+                        'optimizations. Run the vm with --no-prune-dead-locals '
+                        'to disallow these optimizations. Next valid rewind '
+                        'frame is '));
     }
     expect(caughtException, isTrue);
   },
diff --git a/runtime/observatory/tests/service/service.status b/runtime/observatory/tests/service/service.status
index b891f4f..8649402 100644
--- a/runtime/observatory/tests/service/service.status
+++ b/runtime/observatory/tests/service/service.status
@@ -9,10 +9,15 @@
 pause_on_start_and_exit_test: Pass, RuntimeError # Issue 28624
 pause_on_start_then_step_test: Pass, RuntimeError # Issue 28624
 isolate_lifecycle_test: Pass, RuntimeError # Issue 24174
+field_script_test: Pass, RuntimeError
 
 [$runtime == vm && $compiler == none && $system == fuchsia]
 *: Skip  # Not yet triaged.
 
+# Kernel version of tests
+[ $compiler != dartk ]
+add_breakpoint_rpc_kernel_test: SkipByDesign # kernel specific version of add_breakpoint_rpc_test
+
 [ ($compiler == none || $compiler == precompiler) && ($runtime == vm || $runtime == dart_precompiled) ]
 evaluate_activation_test/instance: RuntimeError # http://dartbug.com/20047
 evaluate_activation_test/scope: RuntimeError # http://dartbug.com/20047
@@ -62,6 +67,13 @@
 
 debugger_location_second_test: Skip # Issue 28180
 
+# Snapshots don't include source and generated source is not 1-to-1.
+# The column offsets are thus off.
+next_through_for_each_loop_test: RuntimeError
+next_through_for_loop_with_break_and_continue_test: RuntimeError
+next_through_create_list_and_map_test: RuntimeError
+next_through_closure_test: RuntimeError
+
 [ $compiler == dart2analyzer ]
 evaluate_activation_in_method_class_test: CompileTimeError # Issue 24478
 
@@ -69,8 +81,11 @@
 get_allocation_samples_test: RuntimeError # Profiling unimplemented.
 get_cpu_profile_timeline_rpc_test: RuntimeError # Profiling unimplemented.
 implicit_getter_setter_test: RuntimeError # Field guards unimplemented.
-rewind_test: RuntimeError # Issue 27878
-rewind_optimized_out_test: RuntimeError # Issue 27878
+
+# Debugging StringConcatenation doesn't work the same on simdbc as on other platforms.
+next_through_catch_test: RuntimeError
+next_through_simple_async_test: RuntimeError
+next_through_simple_linear_2_test: RuntimeError
 
 [ $hot_reload || $hot_reload_rollback ]
 # Skip all service tests because random reloads interfere.
diff --git a/runtime/observatory/tests/service/service_kernel.status b/runtime/observatory/tests/service/service_kernel.status
new file mode 100644
index 0000000..2182995
--- /dev/null
+++ b/runtime/observatory/tests/service/service_kernel.status
@@ -0,0 +1,36 @@
+# Copyright (c) 2017, 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.
+
+[ $compiler == dartk ]
+add_breakpoint_rpc_test: SkipByDesign # non-kernel specific version of add_breakpoint_rpc_kernel_test
+get_object_rpc_test: SkipByDesign # non-kernel specific. Currently no kernel-specific one exists.
+set_name_rpc_test: SkipByDesign # non-kernel specific. Currently no kernel-specific one exists.
+get_source_report_test: SkipByDesign # non-kernel specific. Currently no kernel-specific one exists.
+debugger_location_test: SkipByDesign # non-kernel specific. Currently no kernel-specific one exists.
+
+next_through_for_each_loop_test: RuntimeError # Test based on source behaviour which just seems wrong
+
+get_isolate_after_language_error_test: CompileTimeError
+developer_extension_test: CompileTimeError
+
+library_dependency_test: RuntimeError # There are no imports and exports in kernel.
+
+# These 3 tests fail with 'dart:vmservice_io': error: [...] native function
+# 'VMServiceIO_Shutdown' (0 arguments) cannot be found
+# because of '--compile_all'
+capture_stdio_test: CompileTimeError
+vm_restart_test: CompileTimeError
+address_mapper_test: CompileTimeError
+
+###
+### Not supported for now at least
+###
+*_reload_*: Skip # no reload support for now
+eval_internal_class_test: Skip # no evaluation test for now
+evaluate_*: Skip # no evaluation test for now
+causal*: Skip # no causal stack trace test for now
+###
+
+# Inherited from service.status
+isolate_lifecycle_test: Pass, RuntimeError
diff --git a/runtime/observatory/tests/service/service_test_common.dart b/runtime/observatory/tests/service/service_test_common.dart
index 44d82f2..837d237 100644
--- a/runtime/observatory/tests/service/service_test_common.dart
+++ b/runtime/observatory/tests/service/service_test_common.dart
@@ -397,3 +397,45 @@
   await value.load();
   return value;
 }
+
+IsolateTest runStepThroughProgramRecordingStops(List<String> recordStops) {
+  return (Isolate isolate) async {
+    Completer completer = new Completer();
+
+    await subscribeToStream(isolate.vm, VM.kDebugStream,
+        (ServiceEvent event) async {
+      if (event.kind == ServiceEvent.kPauseBreakpoint) {
+        await isolate.reload();
+        // We are paused: Step further.
+        Frame frame = isolate.topFrame;
+        recordStops.add(await frame.location.toUserString());
+        if (event.atAsyncSuspension) {
+          isolate.stepOverAsyncSuspension();
+        } else {
+          isolate.stepOver();
+        }
+      } else if (event.kind == ServiceEvent.kPauseExit) {
+        // We are at the exit: The test is done.
+        await cancelStreamSubscription(VM.kDebugStream);
+        completer.complete();
+      }
+    });
+    isolate.resume();
+    return completer.future;
+  };
+}
+
+IsolateTest checkRecordedStops(
+    List<String> recordStops, List<String> expectedStops) {
+  return (Isolate isolate) async {
+    int end = recordStops.length < expectedStops.length
+        ? recordStops.length
+        : expectedStops.length;
+    for (int i = 0; i < end; ++i) {
+      expect(recordStops[i], expectedStops[i]);
+    }
+
+    expect(recordStops.length >= expectedStops.length, true,
+        reason: "Expects at least ${expectedStops.length} breaks.");
+  };
+}
diff --git a/runtime/observatory/tests/service/step_test.dart b/runtime/observatory/tests/service/step_test.dart
index 480f549..c0fef35 100644
--- a/runtime/observatory/tests/service/step_test.dart
+++ b/runtime/observatory/tests/service/step_test.dart
@@ -1,10 +1,14 @@
+// Copyright (c) 2017, 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 'test_helper.dart';
 import 'service_test_common.dart';
 import 'package:observatory/service_io.dart';
 import 'package:unittest/unittest.dart';
 
-const int LINE_A = 10;
+const int LINE_A = 14;
 
 code() {
   var x = {}; // LINE_A
diff --git a/runtime/tests/vm/vm.status b/runtime/tests/vm/vm.status
index 2287727..c666615 100644
--- a/runtime/tests/vm/vm.status
+++ b/runtime/tests/vm/vm.status
@@ -296,8 +296,3 @@
 [ $hot_reload || $hot_reload_rollback ]
 dart/spawn_shutdown_test: Skip # We can shutdown an isolate before it reloads.
 dart/spawn_infinite_loop_test: Skip # We can shutdown an isolate before it reloads.
-
-[ $arch == simdbc  || $arch == simdbc64 ]
-cc/Debugger_RewindOneFrame_Unoptimized: Skip # Issue 27878
-cc/Debugger_RewindTwoFrames_Unoptimized: Skip # Issue 27878
-cc/Debugger_Rewind_Optimized: Skip # Issue 27878
diff --git a/runtime/vm/aot_optimizer.cc b/runtime/vm/aot_optimizer.cc
index 306fce4..1ff277f 100644
--- a/runtime/vm/aot_optimizer.cc
+++ b/runtime/vm/aot_optimizer.cc
@@ -501,7 +501,7 @@
   if (!call->HasICData()) return false;
   const ICData& ic_data =
       ICData::Handle(Z, call->ic_data()->AsUnaryClassChecks());
-  if (ic_data.NumberOfChecks() != 1) {
+  if (!ic_data.NumberOfChecksIs(1)) {
     return false;
   }
   return FlowGraphInliner::TryReplaceInstanceCallWithInline(
@@ -1303,7 +1303,8 @@
   Class& cls = Class::Handle(Z);
 
   bool results_differ = false;
-  for (int i = 0; i < ic_data.NumberOfChecks(); i++) {
+  const intptr_t number_of_checks = ic_data.NumberOfChecks();
+  for (int i = 0; i < number_of_checks; i++) {
     cls = class_table.At(ic_data.GetReceiverClassIdAt(i));
     if (cls.NumTypeArguments() > 0) {
       return Bool::null();
@@ -1559,12 +1560,12 @@
 
   const ICData& unary_checks =
       ICData::ZoneHandle(Z, call->ic_data()->AsUnaryClassChecks());
-  if ((unary_checks.NumberOfChecks() > 0) &&
-      (unary_checks.NumberOfChecks() <= FLAG_max_polymorphic_checks)) {
+  const intptr_t number_of_checks = unary_checks.NumberOfChecks();
+  if (number_of_checks > 0 && number_of_checks <= FLAG_max_polymorphic_checks) {
     ZoneGrowableArray<intptr_t>* results =
-        new (Z) ZoneGrowableArray<intptr_t>(unary_checks.NumberOfChecks() * 2);
+        new (Z) ZoneGrowableArray<intptr_t>(number_of_checks * 2);
     InstanceOfAsBool(unary_checks, type, results);
-    if (results->length() == unary_checks.NumberOfChecks() * 2) {
+    if (results->length() == number_of_checks * 2) {
       const bool can_deopt = TryExpandTestCidsResult(results, type);
       if (can_deopt && !IsAllowedForInlining(call->deopt_id())) {
         // Guard against repeated speculative inlining.
@@ -1597,10 +1598,10 @@
   ASSERT(!type.IsMalformedOrMalbounded());
   const ICData& unary_checks =
       ICData::ZoneHandle(Z, call->ic_data()->AsUnaryClassChecks());
-  if ((unary_checks.NumberOfChecks() > 0) &&
-      (unary_checks.NumberOfChecks() <= FLAG_max_polymorphic_checks)) {
+  const intptr_t number_of_checks = unary_checks.NumberOfChecks();
+  if (number_of_checks > 0 && number_of_checks <= FLAG_max_polymorphic_checks) {
     ZoneGrowableArray<intptr_t>* results =
-        new (Z) ZoneGrowableArray<intptr_t>(unary_checks.NumberOfChecks() * 2);
+        new (Z) ZoneGrowableArray<intptr_t>(number_of_checks * 2);
     const Bool& as_bool =
         Bool::ZoneHandle(Z, InstanceOfAsBool(unary_checks, type, results));
     if (as_bool.raw() == Bool::True().raw()) {
@@ -1665,7 +1666,7 @@
 
   const ICData& unary_checks =
       ICData::Handle(Z, call->ic_data()->AsUnaryClassChecks());
-  if ((unary_checks.NumberOfChecks() > 0) && (op_kind == Token::kSET) &&
+  if (!unary_checks.NumberOfChecksIs(0) && (op_kind == Token::kSET) &&
       TryInlineInstanceSetter(call, unary_checks)) {
     return true;
   }
@@ -1706,8 +1707,8 @@
 
   const ICData& unary_checks =
       ICData::ZoneHandle(Z, instr->ic_data()->AsUnaryClassChecks());
-  if (IsAllowedForInlining(instr->deopt_id()) &&
-      (unary_checks.NumberOfChecks() > 0)) {
+  const intptr_t number_of_checks = unary_checks.NumberOfChecks();
+  if (IsAllowedForInlining(instr->deopt_id()) && number_of_checks > 0) {
     if ((op_kind == Token::kINDEX) && TryReplaceWithIndexedOp(instr)) {
       return;
     }
@@ -1737,8 +1738,7 @@
     }
   }
 
-  bool has_one_target =
-      (unary_checks.NumberOfChecks() > 0) && unary_checks.HasOneTarget();
+  bool has_one_target = number_of_checks > 0 && unary_checks.HasOneTarget();
   if (has_one_target) {
     // Check if the single target is a polymorphic target, if it is,
     // we don't have one target.
@@ -1932,7 +1932,7 @@
         instr->ReplaceWith(call, current_iterator());
         return;
       } else if ((ic_data.raw() != ICData::null()) &&
-                 (ic_data.NumberOfChecks() > 0)) {
+                 !ic_data.NumberOfChecksIs(0)) {
         PolymorphicInstanceCallInstr* call =
             new (Z) PolymorphicInstanceCallInstr(instr, ic_data,
                                                  /* with_checks = */ true,
@@ -2021,7 +2021,7 @@
       // We can handle only monomorphic min/max call sites with both arguments
       // being either doubles or smis.
       if (CanUnboxDouble() && call->HasICData() &&
-          (call->ic_data()->NumberOfChecks() == 1)) {
+          call->ic_data()->NumberOfChecksIs(1)) {
         const ICData& ic_data = *call->ic_data();
         intptr_t result_cid = kIllegalCid;
         if (ICDataHasReceiverArgumentClassIds(ic_data, kDoubleCid,
@@ -2047,7 +2047,7 @@
       break;
     }
     case MethodRecognizer::kDoubleFromInteger: {
-      if (call->HasICData() && (call->ic_data()->NumberOfChecks() == 1)) {
+      if (call->HasICData() && call->ic_data()->NumberOfChecksIs(1)) {
         const ICData& ic_data = *call->ic_data();
         if (CanUnboxDouble()) {
           if (ArgIsAlways(kSmiCid, ic_data, 1)) {
@@ -2090,7 +2090,7 @@
   }
 
   ASSERT(instr->HasICData());
-  if (unary_ic_data.NumberOfChecks() == 0) {
+  if (unary_ic_data.NumberOfChecksIs(0)) {
     // No type feedback collected.
     return false;
   }
diff --git a/runtime/vm/class_finalizer.cc b/runtime/vm/class_finalizer.cc
index 6d88977..e094d0f 100644
--- a/runtime/vm/class_finalizer.cc
+++ b/runtime/vm/class_finalizer.cc
@@ -1163,21 +1163,25 @@
     const TypeParameter& type_parameter = TypeParameter::Cast(type);
     const Class& parameterized_class =
         Class::Handle(zone, type_parameter.parameterized_class());
-    ASSERT(!parameterized_class.IsNull());
-    // The index must reflect the position of this type parameter in the type
-    // arguments vector of its parameterized class. The offset to add is the
-    // number of type arguments in the super type, which is equal to the
-    // difference in number of type arguments and type parameters of the
-    // parameterized class.
-    const intptr_t offset = parameterized_class.NumTypeArguments() -
-                            parameterized_class.NumTypeParameters();
-    // Calling NumTypeParameters() may finalize this type parameter if it
-    // belongs to a mixin application class.
-    if (!type_parameter.IsFinalized()) {
-      type_parameter.set_index(type_parameter.index() + offset);
-      type_parameter.SetIsFinalized();
+    if (!parameterized_class.IsNull()) {
+      // The index must reflect the position of this type parameter in the type
+      // arguments vector of its parameterized class. The offset to add is the
+      // number of type arguments in the super type, which is equal to the
+      // difference in number of type arguments and type parameters of the
+      // parameterized class.
+      const intptr_t offset = parameterized_class.NumTypeArguments() -
+                              parameterized_class.NumTypeParameters();
+      // Calling NumTypeParameters() may finalize this type parameter if it
+      // belongs to a mixin application class.
+      if (!type_parameter.IsFinalized()) {
+        type_parameter.set_index(type_parameter.index() + offset);
+        type_parameter.SetIsFinalized();
+      } else {
+        ASSERT(cls.IsMixinApplication());
+      }
     } else {
-      ASSERT(cls.IsMixinApplication());
+      // A function type parameter is always finalized.
+      ASSERT(type_parameter.IsFinalized());
     }
 
     if (FLAG_trace_type_finalization) {
diff --git a/runtime/vm/code_descriptors_test.cc b/runtime/vm/code_descriptors_test.cc
index 3d2b6a1..6f02a1c 100644
--- a/runtime/vm/code_descriptors_test.cc
+++ b/runtime/vm/code_descriptors_test.cc
@@ -31,7 +31,6 @@
   l = new LiteralNode(kPos, Smi::ZoneHandle(Smi::New(3)));
   test->node_sequence()->Add(new ReturnNode(kPos, l));
   parsed_function->SetNodeSequence(test->node_sequence());
-  parsed_function->set_instantiator(NULL);
   parsed_function->EnsureExpressionTemp();
   test->node_sequence()->scope()->AddVariable(
       parsed_function->expression_temp_var());
diff --git a/runtime/vm/code_generator.cc b/runtime/vm/code_generator.cc
index 72e3aae..1d73b6b 100644
--- a/runtime/vm/code_generator.cc
+++ b/runtime/vm/code_generator.cc
@@ -938,7 +938,7 @@
   const Instance& arg = Instance::CheckedHandle(arguments.ArgAt(0));
   const ICData& ic_data = ICData::CheckedHandle(arguments.ArgAt(1));
   // IC data for static call is prepopulated with the statically known target.
-  ASSERT(ic_data.NumberOfChecks() == 1);
+  ASSERT(ic_data.NumberOfChecksIs(1));
   const Function& target = Function::Handle(ic_data.GetTargetAt(0));
   if (!target.HasCode()) {
     const Error& error =
@@ -970,7 +970,7 @@
   const Instance& arg1 = Instance::CheckedHandle(arguments.ArgAt(1));
   const ICData& ic_data = ICData::CheckedHandle(arguments.ArgAt(2));
   // IC data for static call is prepopulated with the statically known target.
-  ASSERT(ic_data.NumberOfChecks() > 0);
+  ASSERT(!ic_data.NumberOfChecksIs(0));
   const Function& target = Function::Handle(ic_data.GetTargetAt(0));
   if (!target.HasCode()) {
     const Error& error =
@@ -1310,9 +1310,9 @@
 
   if (ic_data_or_cache.IsICData()) {
     const ICData& ic_data = ICData::Cast(ic_data_or_cache);
+    const intptr_t number_of_checks = ic_data.NumberOfChecks();
 
-    if ((ic_data.NumberOfChecks() == 0) &&
-        !target_function.HasOptionalParameters() &&
+    if (number_of_checks == 0 && !target_function.HasOptionalParameters() &&
         !Isolate::Current()->compilation_allowed()) {
       // This call site is unlinked: transition to a monomorphic direct call.
       // Note we cannot do this if the target has optional parameters because
@@ -1345,7 +1345,7 @@
                                          expected_cid, target_code);
     } else {
       ic_data.AddReceiverCheck(receiver.GetClassId(), target_function);
-      if (ic_data.NumberOfChecks() > FLAG_max_polymorphic_checks) {
+      if (number_of_checks > FLAG_max_polymorphic_checks) {
         // Switch to megamorphic call.
         const MegamorphicCache& cache = MegamorphicCache::Handle(
             zone, MegamorphicCacheTable::Lookup(isolate, name, descriptor));
diff --git a/runtime/vm/constants_dbc.h b/runtime/vm/constants_dbc.h
index 00e0793..49d2910 100644
--- a/runtime/vm/constants_dbc.h
+++ b/runtime/vm/constants_dbc.h
@@ -824,7 +824,8 @@
   V(CheckStackAlwaysExit,            0, ___, ___, ___) \
   V(DebugStep,                       0, ___, ___, ___) \
   V(DebugBreak,                      A, num, ___, ___) \
-  V(Deopt,                         A_D, num, num, ___)
+  V(Deopt,                         A_D, num, num, ___) \
+  V(DeoptRewind,                     0, ___, ___, ___)
 
 // clang-format on
 
diff --git a/runtime/vm/dart_api_impl.cc b/runtime/vm/dart_api_impl.cc
index f8db6b4..4cad96c 100644
--- a/runtime/vm/dart_api_impl.cc
+++ b/runtime/vm/dart_api_impl.cc
@@ -6573,8 +6573,8 @@
             intptr_t num_args_checked = ic_data_.NumArgsTested();
             js_icdata.AddProperty("argsTested", num_args_checked);
             JSONArray js_entries(&js_icdata, "entries");
-            for (intptr_t check = 0; check < ic_data_.NumberOfChecks();
-                 check++) {
+            const intptr_t number_of_checks = ic_data_.NumberOfChecks();
+            for (intptr_t check = 0; check < number_of_checks; check++) {
               GrowableArray<intptr_t> class_ids(num_args_checked);
               ic_data_.GetClassIdsAt(check, &class_ids);
               for (intptr_t k = 0; k < num_args_checked; k++) {
@@ -6608,8 +6608,13 @@
 
 DART_EXPORT void Dart_SortClasses() {
   DARTSCOPE(Thread::Current());
-  ClassFinalizer::SortClasses();
+  // We don't have mechanisms to change class-ids that are embedded in code and
+  // ICData.
   ClassFinalizer::ClearAllCode();
+  // Make sure that ICData etc. that have been cleared are also removed from
+  // the heap so that they are not found by the heap verifier.
+  Isolate::Current()->heap()->CollectAllGarbage();
+  ClassFinalizer::SortClasses();
 }
 
 DART_EXPORT Dart_Handle
diff --git a/runtime/vm/flow_graph_compiler.cc b/runtime/vm/flow_graph_compiler.cc
index 4610cd6..e1c8a01 100644
--- a/runtime/vm/flow_graph_compiler.cc
+++ b/runtime/vm/flow_graph_compiler.cc
@@ -161,13 +161,13 @@
     return false;
   }
   // Precompiled code has no ICData, optimistically inline it.
-  if (ic_data.IsNull() || (ic_data.NumberOfChecks() == 0)) {
+  if (ic_data.IsNull() || ic_data.NumberOfChecksIs(0)) {
     return true;
   }
   // Check if OneByteString is hot enough.
   const ICData& ic_data_sorted =
       ICData::Handle(ic_data.AsUnaryClassChecksSortedByCount());
-  ASSERT(ic_data_sorted.NumberOfChecks() > 0);
+  ASSERT(!ic_data_sorted.NumberOfChecksIs(0));
   if (ic_data_sorted.GetReceiverClassIdAt(0) == kOneByteStringCid) {
     const intptr_t total_count = ic_data_sorted.AggregateCount();
     const intptr_t ratio = (ic_data_sorted.GetCountAt(0) * 100) / total_count;
diff --git a/runtime/vm/flow_graph_compiler_arm.cc b/runtime/vm/flow_graph_compiler_arm.cc
index 700935b..0caab79 100644
--- a/runtime/vm/flow_graph_compiler_arm.cc
+++ b/runtime/vm/flow_graph_compiler_arm.cc
@@ -1537,15 +1537,15 @@
   __ LoadObject(R4, arguments_descriptor);
 
   const bool kFirstCheckIsSmi = ic_data.GetReceiverClassIdAt(0) == kSmiCid;
-  const intptr_t kNumChecks = ic_data.NumberOfChecks();
+  const intptr_t num_checks = ic_data.NumberOfChecks();
 
-  ASSERT(!ic_data.IsNull() && (kNumChecks > 0));
+  ASSERT(!ic_data.IsNull() && (num_checks > 0));
 
   Label after_smi_test;
   if (kFirstCheckIsSmi) {
     __ tst(R0, Operand(kSmiTagMask));
     // Jump if receiver is not Smi.
-    if (kNumChecks == 1) {
+    if (num_checks == 1) {
       __ b(failed, NE);
     } else {
       __ b(&after_smi_test, NE);
@@ -1558,7 +1558,7 @@
                            *StubCode::CallStaticFunction_entry(),
                            RawPcDescriptors::kOther, locs, function);
     __ Drop(argument_count);
-    if (kNumChecks > 1) {
+    if (num_checks > 1) {
       __ b(match_found);
     }
   } else {
@@ -1571,8 +1571,8 @@
   }
   __ Bind(&after_smi_test);
 
-  ASSERT(!ic_data.IsNull() && (kNumChecks > 0));
-  GrowableArray<CidTarget> sorted(kNumChecks);
+  ASSERT(!ic_data.IsNull() && (num_checks > 0));
+  GrowableArray<CidTarget> sorted(num_checks);
   SortICDataByCount(ic_data, &sorted, /* drop_smi = */ true);
 
   // Value is not Smi,
diff --git a/runtime/vm/flow_graph_compiler_arm64.cc b/runtime/vm/flow_graph_compiler_arm64.cc
index d320028..c1d4a0c 100644
--- a/runtime/vm/flow_graph_compiler_arm64.cc
+++ b/runtime/vm/flow_graph_compiler_arm64.cc
@@ -1500,15 +1500,15 @@
   __ LoadObject(R4, arguments_descriptor);
 
   const bool kFirstCheckIsSmi = ic_data.GetReceiverClassIdAt(0) == kSmiCid;
-  const intptr_t kNumChecks = ic_data.NumberOfChecks();
+  const intptr_t num_checks = ic_data.NumberOfChecks();
 
-  ASSERT(!ic_data.IsNull() && (kNumChecks > 0));
+  ASSERT(!ic_data.IsNull() && (num_checks > 0));
 
   Label after_smi_test;
   if (kFirstCheckIsSmi) {
     __ tsti(R0, Immediate(kSmiTagMask));
     // Jump if receiver is not Smi.
-    if (kNumChecks == 1) {
+    if (num_checks == 1) {
       __ b(failed, NE);
     } else {
       __ b(&after_smi_test, NE);
@@ -1521,7 +1521,7 @@
                            *StubCode::CallStaticFunction_entry(),
                            RawPcDescriptors::kOther, locs, function);
     __ Drop(argument_count);
-    if (kNumChecks > 1) {
+    if (num_checks > 1) {
       __ b(match_found);
     }
   } else {
@@ -1534,8 +1534,8 @@
   }
   __ Bind(&after_smi_test);
 
-  ASSERT(!ic_data.IsNull() && (kNumChecks > 0));
-  GrowableArray<CidTarget> sorted(kNumChecks);
+  ASSERT(!ic_data.IsNull() && (num_checks > 0));
+  GrowableArray<CidTarget> sorted(num_checks);
   SortICDataByCount(ic_data, &sorted, /* drop_smi = */ true);
 
   // Value is not Smi,
diff --git a/runtime/vm/flow_graph_compiler_ia32.cc b/runtime/vm/flow_graph_compiler_ia32.cc
index e0d5846..552ac80 100644
--- a/runtime/vm/flow_graph_compiler_ia32.cc
+++ b/runtime/vm/flow_graph_compiler_ia32.cc
@@ -1441,15 +1441,15 @@
   __ LoadObject(EDX, arguments_descriptor);
 
   const bool kFirstCheckIsSmi = ic_data.GetReceiverClassIdAt(0) == kSmiCid;
-  const intptr_t kNumChecks = ic_data.NumberOfChecks();
+  const intptr_t num_checks = ic_data.NumberOfChecks();
 
-  ASSERT(!ic_data.IsNull() && (kNumChecks > 0));
+  ASSERT(!ic_data.IsNull() && (num_checks > 0));
 
   Label after_smi_test;
   __ testl(EAX, Immediate(kSmiTagMask));
   if (kFirstCheckIsSmi) {
     // Jump if receiver is not Smi.
-    if (kNumChecks == 1) {
+    if (num_checks == 1) {
       __ j(NOT_ZERO, failed);
     } else {
       __ j(NOT_ZERO, &after_smi_test);
@@ -1463,7 +1463,7 @@
         Function::ZoneHandle(zone(), ic_data.GetTargetAt(0));
     AddStaticCallTarget(function);
     __ Drop(argument_count);
-    if (kNumChecks > 1) {
+    if (num_checks > 1) {
       __ jmp(match_found);
     }
   } else {
@@ -1473,8 +1473,8 @@
   }
   __ Bind(&after_smi_test);
 
-  ASSERT(!ic_data.IsNull() && (kNumChecks > 0));
-  GrowableArray<CidTarget> sorted(kNumChecks);
+  ASSERT(!ic_data.IsNull() && (num_checks > 0));
+  GrowableArray<CidTarget> sorted(num_checks);
   SortICDataByCount(ic_data, &sorted, /* drop_smi = */ true);
 
   // Value is not Smi,
diff --git a/runtime/vm/flow_graph_compiler_mips.cc b/runtime/vm/flow_graph_compiler_mips.cc
index 7854b08..b8b749b 100644
--- a/runtime/vm/flow_graph_compiler_mips.cc
+++ b/runtime/vm/flow_graph_compiler_mips.cc
@@ -1558,15 +1558,15 @@
   __ LoadObject(S4, arguments_descriptor);
 
   const bool kFirstCheckIsSmi = ic_data.GetReceiverClassIdAt(0) == kSmiCid;
-  const intptr_t kNumChecks = ic_data.NumberOfChecks();
+  const intptr_t num_checks = ic_data.NumberOfChecks();
 
-  ASSERT(!ic_data.IsNull() && (kNumChecks > 0));
+  ASSERT(!ic_data.IsNull() && (num_checks > 0));
 
   Label after_smi_test;
   if (kFirstCheckIsSmi) {
     __ andi(CMPRES1, T0, Immediate(kSmiTagMask));
     // Jump if receiver is not Smi.
-    if (kNumChecks == 1) {
+    if (num_checks == 1) {
       __ bne(CMPRES1, ZR, failed);
     } else {
       __ bne(CMPRES1, ZR, &after_smi_test);
@@ -1579,7 +1579,7 @@
                            *StubCode::CallStaticFunction_entry(),
                            RawPcDescriptors::kOther, locs, function);
     __ Drop(argument_count);
-    if (kNumChecks > 1) {
+    if (num_checks > 1) {
       __ b(match_found);
     }
   } else {
@@ -1593,7 +1593,7 @@
 
   __ Bind(&after_smi_test);
 
-  GrowableArray<CidTarget> sorted(kNumChecks);
+  GrowableArray<CidTarget> sorted(num_checks);
   SortICDataByCount(ic_data, &sorted, /* drop_smi = */ true);
 
   // Value is not Smi,
diff --git a/runtime/vm/flow_graph_compiler_x64.cc b/runtime/vm/flow_graph_compiler_x64.cc
index 6c69c80..1a29be5 100644
--- a/runtime/vm/flow_graph_compiler_x64.cc
+++ b/runtime/vm/flow_graph_compiler_x64.cc
@@ -1465,15 +1465,15 @@
   __ LoadObject(R10, arguments_descriptor);
 
   const bool kFirstCheckIsSmi = ic_data.GetReceiverClassIdAt(0) == kSmiCid;
-  const intptr_t kNumChecks = ic_data.NumberOfChecks();
+  const intptr_t num_checks = ic_data.NumberOfChecks();
 
-  ASSERT(!ic_data.IsNull() && (kNumChecks > 0));
+  ASSERT(!ic_data.IsNull() && (num_checks > 0));
 
   Label after_smi_test;
   if (kFirstCheckIsSmi) {
     __ testq(RAX, Immediate(kSmiTagMask));
     // Jump if receiver is not Smi.
-    if (kNumChecks == 1) {
+    if (num_checks == 1) {
       __ j(NOT_ZERO, failed);
     } else {
       __ j(NOT_ZERO, &after_smi_test);
@@ -1486,7 +1486,7 @@
                            *StubCode::CallStaticFunction_entry(),
                            RawPcDescriptors::kOther, locs, function);
     __ Drop(argument_count, RCX);
-    if (kNumChecks > 1) {
+    if (num_checks > 1) {
       __ jmp(match_found);
     }
   } else {
@@ -1499,8 +1499,8 @@
   }
   __ Bind(&after_smi_test);
 
-  ASSERT(!ic_data.IsNull() && (kNumChecks > 0));
-  GrowableArray<CidTarget> sorted(kNumChecks);
+  ASSERT(!ic_data.IsNull() && (num_checks > 0));
+  GrowableArray<CidTarget> sorted(num_checks);
   SortICDataByCount(ic_data, &sorted, /* drop_smi = */ true);
 
   const intptr_t kSortedLen = sorted.length();
diff --git a/runtime/vm/flow_graph_inliner.cc b/runtime/vm/flow_graph_inliner.cc
index 33f136a..cdcf3f7 100644
--- a/runtime/vm/flow_graph_inliner.cc
+++ b/runtime/vm/flow_graph_inliner.cc
@@ -3473,13 +3473,13 @@
       return InlineDoubleTestOp(flow_graph, call, receiver, kind, entry, last);
     case MethodRecognizer::kGrowableArraySetData:
       ASSERT(receiver_cid == kGrowableObjectArrayCid);
-      ASSERT(ic_data.NumberOfChecks() == 1);
+      ASSERT(ic_data.NumberOfChecksIs(1));
       return InlineGrowableArraySetter(
           flow_graph, GrowableObjectArray::data_offset(), kEmitStoreBarrier,
           call, receiver, entry, last);
     case MethodRecognizer::kGrowableArraySetLength:
       ASSERT(receiver_cid == kGrowableObjectArrayCid);
-      ASSERT(ic_data.NumberOfChecks() == 1);
+      ASSERT(ic_data.NumberOfChecksIs(1));
       return InlineGrowableArraySetter(
           flow_graph, GrowableObjectArray::length_offset(), kNoStoreBarrier,
           call, receiver, entry, last);
diff --git a/runtime/vm/flow_graph_type_propagator.cc b/runtime/vm/flow_graph_type_propagator.cc
index d3cdc84..f7264d9 100644
--- a/runtime/vm/flow_graph_type_propagator.cc
+++ b/runtime/vm/flow_graph_type_propagator.cc
@@ -182,7 +182,7 @@
 void FlowGraphTypePropagator::SetCid(Definition* def, intptr_t cid) {
   CompileType* current = TypeOf(def);
   if (current->IsNone() || (current->ToCid() != cid)) {
-    SetTypeOf(def, ZoneCompileType::Wrap(CompileType::FromCid(cid)));
+    SetTypeOf(def, new CompileType(CompileType::FromCid(cid)));
   }
 }
 
@@ -219,7 +219,7 @@
 
 
 void FlowGraphTypePropagator::VisitCheckClass(CheckClassInstr* check) {
-  if ((check->unary_checks().NumberOfChecks() != 1) ||
+  if (!check->unary_checks().NumberOfChecksIs(1) ||
       !check->Dependencies().IsNone()) {
     // TODO(vegorov): If check is affected by side-effect we can still propagate
     // the type further but not the cid.
@@ -275,7 +275,7 @@
       (current->is_nullable() && !guard->field().is_nullable())) {
     const bool is_nullable =
         guard->field().is_nullable() && current->is_nullable();
-    SetTypeOf(def, ZoneCompileType::Wrap(CompileType(is_nullable, cid, NULL)));
+    SetTypeOf(def, new CompileType(is_nullable, cid, NULL));
   }
 }
 
@@ -283,7 +283,7 @@
 void FlowGraphTypePropagator::VisitAssertAssignable(
     AssertAssignableInstr* instr) {
   SetTypeOf(instr->value()->definition(),
-            ZoneCompileType::Wrap(instr->ComputeType()));
+            new CompileType(instr->ComputeType()));
 }
 
 
diff --git a/runtime/vm/intermediate_language.cc b/runtime/vm/intermediate_language.cc
index 1f72d19..0046c03 100644
--- a/runtime/vm/intermediate_language.cc
+++ b/runtime/vm/intermediate_language.cc
@@ -160,13 +160,14 @@
   ASSERT(unary_checks.IsZoneHandle());
   // Expected useful check data.
   ASSERT(!unary_checks_.IsNull());
-  ASSERT(unary_checks_.NumberOfChecks() > 0);
+  const intptr_t number_of_checks = unary_checks_.NumberOfChecks();
+  ASSERT(number_of_checks > 0);
   ASSERT(unary_checks_.NumArgsTested() == 1);
   SetInputAt(0, value);
   // Otherwise use CheckSmiInstr.
-  ASSERT((unary_checks_.NumberOfChecks() != 1) ||
+  ASSERT(number_of_checks != 1 ||
          (unary_checks_.GetReceiverClassIdAt(0) != kSmiCid));
-  for (intptr_t i = 0; i < unary_checks.NumberOfChecks(); ++i) {
+  for (intptr_t i = 0; i < number_of_checks; ++i) {
     cids_.Add(unary_checks.GetReceiverClassIdAt(i));
   }
   cids_.Sort(LowestFirst);
@@ -176,11 +177,11 @@
 bool CheckClassInstr::AttributesEqual(Instruction* other) const {
   CheckClassInstr* other_check = other->AsCheckClass();
   ASSERT(other_check != NULL);
-  if (unary_checks().NumberOfChecks() !=
-      other_check->unary_checks().NumberOfChecks()) {
+  const intptr_t number_of_checks = unary_checks_.NumberOfChecks();
+  if (number_of_checks != other_check->unary_checks().NumberOfChecks()) {
     return false;
   }
-  for (intptr_t i = 0; i < unary_checks().NumberOfChecks(); ++i) {
+  for (intptr_t i = 0; i < number_of_checks; ++i) {
     // TODO(fschneider): Make sure ic_data are sorted to hit more cases.
     if (unary_checks().GetReceiverClassIdAt(i) !=
         other_check->unary_checks().GetReceiverClassIdAt(i)) {
@@ -219,7 +220,7 @@
 
 
 bool CheckClassInstr::DeoptIfNull() const {
-  if (unary_checks().NumberOfChecks() != 1) {
+  if (!unary_checks().NumberOfChecksIs(1)) {
     return false;
   }
   CompileType* in_type = value()->Type();
@@ -234,7 +235,7 @@
 // transitional temporaries). Instead of checking against the null class only
 // we can check against null instance instead.
 bool CheckClassInstr::DeoptIfNotNull() const {
-  if (unary_checks().NumberOfChecks() != 1) {
+  if (!unary_checks().NumberOfChecksIs(1)) {
     return false;
   }
   const intptr_t cid = unary_checks().GetCidAt(0);
@@ -246,10 +247,11 @@
   ASSERT(unary_checks.NumArgsTested() == 1);
   // TODO(fschneider): Support smis in dense cid checks.
   if (unary_checks.GetReceiverClassIdAt(0) == kSmiCid) return false;
-  if (unary_checks.NumberOfChecks() <= 2) return false;
+  const intptr_t number_of_checks = unary_checks.NumberOfChecks();
+  if (number_of_checks <= 2) return false;
   intptr_t max = 0;
   intptr_t min = kIntptrMax;
-  for (intptr_t i = 0; i < unary_checks.NumberOfChecks(); ++i) {
+  for (intptr_t i = 0; i < number_of_checks; ++i) {
     intptr_t cid = unary_checks.GetCidAt(i);
     if (cid < min) min = cid;
     if (cid > max) max = cid;
@@ -3123,6 +3125,8 @@
       UNIMPLEMENTED();
       break;
   }
+  compiler->AddCurrentDescriptor(RawPcDescriptors::kRewind, deopt_id(),
+                                 token_pos());
   compiler->AddCurrentDescriptor(RawPcDescriptors::kIcCall, deopt_id(),
                                  token_pos());
   compiler->RecordAfterCall(this, FlowGraphCompiler::kHasResult);
@@ -3290,6 +3294,8 @@
                           : Array::Handle(ic_data()->arguments_descriptor());
   const intptr_t argdesc_kidx = __ AddConstant(arguments_descriptor);
 
+  compiler->AddCurrentDescriptor(RawPcDescriptors::kRewind, deopt_id(),
+                                 token_pos());
   if (compiler->is_optimizing()) {
     __ PushConstant(function());
     __ StaticCall(ArgumentCount(), argdesc_kidx);
diff --git a/runtime/vm/intermediate_language.h b/runtime/vm/intermediate_language.h
index b58d9bf..65a16c6 100644
--- a/runtime/vm/intermediate_language.h
+++ b/runtime/vm/intermediate_language.h
@@ -47,7 +47,7 @@
 // Values of CompileType form a lattice with a None type as a bottom and a
 // nullable Dynamic type as a top element. Method Union provides a join
 // operation for the lattice.
-class CompileType : public ValueObject {
+class CompileType : public ZoneAllocated {
  public:
   static const bool kNullable = true;
   static const bool kNonNullable = false;
@@ -56,7 +56,7 @@
       : is_nullable_(is_nullable), cid_(cid), type_(type) {}
 
   CompileType(const CompileType& other)
-      : ValueObject(),
+      : ZoneAllocated(),
         is_nullable_(other.is_nullable_),
         cid_(other.cid_),
         type_(other.type_) {}
@@ -176,23 +176,6 @@
 };
 
 
-// Zone allocated wrapper for the CompileType value.
-class ZoneCompileType : public ZoneAllocated {
- public:
-  static CompileType* Wrap(const CompileType& type) {
-    ZoneCompileType* zone_type = new ZoneCompileType(type);
-    return zone_type->ToCompileType();
-  }
-
-  CompileType* ToCompileType() { return &type_; }
-
- protected:
-  explicit ZoneCompileType(const CompileType& type) : type_(type) {}
-
-  CompileType type_;
-};
-
-
 class EffectSet : public ValueObject {
  public:
   enum Effects {
@@ -1644,7 +1627,7 @@
   // propagation during graph building.
   CompileType* Type() {
     if (type_ == NULL) {
-      type_ = ZoneCompileType::Wrap(ComputeType());
+      type_ = new CompileType(ComputeType());
     }
     return type_;
   }
@@ -1670,7 +1653,7 @@
 
   bool UpdateType(CompileType new_type) {
     if (type_ == NULL) {
-      type_ = ZoneCompileType::Wrap(new_type);
+      type_ = new CompileType(new_type);
       return true;
     }
 
@@ -2793,7 +2776,7 @@
         with_checks_(with_checks),
         complete_(complete) {
     ASSERT(instance_call_ != NULL);
-    ASSERT(ic_data.NumberOfChecks() > 0);
+    ASSERT(!ic_data.NumberOfChecksIs(0));
   }
 
   InstanceCallInstr* instance_call() const { return instance_call_; }
diff --git a/runtime/vm/intermediate_language_arm.cc b/runtime/vm/intermediate_language_arm.cc
index ea29a8a..3f9e1f3 100644
--- a/runtime/vm/intermediate_language_arm.cc
+++ b/runtime/vm/intermediate_language_arm.cc
@@ -5821,7 +5821,7 @@
   __ Push(value_obj);
   ASSERT(instance_call()->HasICData());
   const ICData& ic_data = *instance_call()->ic_data();
-  ASSERT((ic_data.NumberOfChecks() == 1));
+  ASSERT(ic_data.NumberOfChecksIs(1));
   const Function& target = Function::ZoneHandle(ic_data.GetTargetAt(0));
 
   const intptr_t kNumberOfArguments = 1;
diff --git a/runtime/vm/intermediate_language_arm64.cc b/runtime/vm/intermediate_language_arm64.cc
index 1f2a9b2..642bb8f 100644
--- a/runtime/vm/intermediate_language_arm64.cc
+++ b/runtime/vm/intermediate_language_arm64.cc
@@ -5027,7 +5027,7 @@
   __ Push(value_obj);
   ASSERT(instance_call()->HasICData());
   const ICData& ic_data = *instance_call()->ic_data();
-  ASSERT((ic_data.NumberOfChecks() == 1));
+  ASSERT(ic_data.NumberOfChecksIs(1));
   const Function& target = Function::ZoneHandle(ic_data.GetTargetAt(0));
 
   const intptr_t kNumberOfArguments = 1;
diff --git a/runtime/vm/intermediate_language_ia32.cc b/runtime/vm/intermediate_language_ia32.cc
index 1f4f419..8cce18e 100644
--- a/runtime/vm/intermediate_language_ia32.cc
+++ b/runtime/vm/intermediate_language_ia32.cc
@@ -5316,7 +5316,7 @@
   __ pushl(value_obj);
   ASSERT(instance_call()->HasICData());
   const ICData& ic_data = *instance_call()->ic_data();
-  ASSERT((ic_data.NumberOfChecks() == 1));
+  ASSERT(ic_data.NumberOfChecksIs(1));
   const Function& target = Function::ZoneHandle(ic_data.GetTargetAt(0));
 
   const intptr_t kNumberOfArguments = 1;
diff --git a/runtime/vm/intermediate_language_mips.cc b/runtime/vm/intermediate_language_mips.cc
index 51882f8..db8627d 100644
--- a/runtime/vm/intermediate_language_mips.cc
+++ b/runtime/vm/intermediate_language_mips.cc
@@ -4606,7 +4606,7 @@
   __ Push(value_obj);
   ASSERT(instance_call()->HasICData());
   const ICData& ic_data = *instance_call()->ic_data();
-  ASSERT((ic_data.NumberOfChecks() == 1));
+  ASSERT(ic_data.NumberOfChecksIs(1));
   const Function& target = Function::ZoneHandle(ic_data.GetTargetAt(0));
 
   const intptr_t kNumberOfArguments = 1;
diff --git a/runtime/vm/intermediate_language_x64.cc b/runtime/vm/intermediate_language_x64.cc
index c704319..534ed97 100644
--- a/runtime/vm/intermediate_language_x64.cc
+++ b/runtime/vm/intermediate_language_x64.cc
@@ -5288,7 +5288,7 @@
   __ Bind(&do_call);
   ASSERT(instance_call()->HasICData());
   const ICData& ic_data = *instance_call()->ic_data();
-  ASSERT((ic_data.NumberOfChecks() == 1));
+  ASSERT(ic_data.NumberOfChecksIs(1));
   const Function& target = Function::ZoneHandle(ic_data.GetTargetAt(0));
 
   const intptr_t kNumberOfArguments = 1;
diff --git a/runtime/vm/intrinsifier.cc b/runtime/vm/intrinsifier.cc
index 26573ce..9c6d9ee 100644
--- a/runtime/vm/intrinsifier.cc
+++ b/runtime/vm/intrinsifier.cc
@@ -329,8 +329,8 @@
       // The type of |value| has already been checked and it is safe to
       // adjust reaching type. This is done manually because there is no type
       // propagation when building intrinsics.
-      unboxed_value->AsUnbox()->value()->SetReachingType(ZoneCompileType::Wrap(
-          CompileType::FromCid(CidForRepresentation(rep))));
+      unboxed_value->AsUnbox()->value()->SetReachingType(
+          new CompileType(CompileType::FromCid(CidForRepresentation(rep))));
     }
     return unboxed_value;
   }
diff --git a/runtime/vm/jit_optimizer.cc b/runtime/vm/jit_optimizer.cc
index ac9db2d3..cfd3fd4 100644
--- a/runtime/vm/jit_optimizer.cc
+++ b/runtime/vm/jit_optimizer.cc
@@ -438,7 +438,7 @@
   if (!call->HasICData()) return false;
   const ICData& ic_data =
       ICData::Handle(Z, call->ic_data()->AsUnaryClassChecks());
-  if (ic_data.NumberOfChecks() != 1) {
+  if (!ic_data.NumberOfChecksIs(1)) {
     return false;
   }
   return FlowGraphInliner::TryReplaceInstanceCallWithInline(
@@ -1198,7 +1198,8 @@
   Class& cls = Class::Handle(Z);
 
   bool results_differ = false;
-  for (int i = 0; i < ic_data.NumberOfChecks(); i++) {
+  const intptr_t number_of_checks = ic_data.NumberOfChecks();
+  for (int i = 0; i < number_of_checks; i++) {
     cls = class_table.At(ic_data.GetReceiverClassIdAt(i));
     if (cls.NumTypeArguments() > 0) {
       return Bool::null();
@@ -1376,14 +1377,15 @@
   }
   const ICData& unary_checks =
       ICData::ZoneHandle(Z, call->ic_data()->AsUnaryClassChecks());
-  if ((unary_checks.NumberOfChecks() > 0) &&
-      (unary_checks.NumberOfChecks() <= FLAG_max_polymorphic_checks)) {
+  const intptr_t number_of_checks = unary_checks.NumberOfChecks();
+  if ((number_of_checks > 0) &&
+      (number_of_checks <= FLAG_max_polymorphic_checks)) {
     ZoneGrowableArray<intptr_t>* results =
-        new (Z) ZoneGrowableArray<intptr_t>(unary_checks.NumberOfChecks() * 2);
+        new (Z) ZoneGrowableArray<intptr_t>(number_of_checks * 2);
     Bool& as_bool =
         Bool::ZoneHandle(Z, InstanceOfAsBool(unary_checks, type, results));
     if (as_bool.IsNull()) {
-      if (results->length() == unary_checks.NumberOfChecks() * 2) {
+      if (results->length() == number_of_checks * 2) {
         const bool can_deopt = TryExpandTestCidsResult(results, type);
         TestCidsInstr* test_cids = new (Z) TestCidsInstr(
             call->token_pos(), negate ? Token::kISNOT : Token::kIS,
@@ -1445,10 +1447,11 @@
   ASSERT(!type.IsMalformedOrMalbounded());
   const ICData& unary_checks =
       ICData::ZoneHandle(Z, call->ic_data()->AsUnaryClassChecks());
-  if ((unary_checks.NumberOfChecks() > 0) &&
-      (unary_checks.NumberOfChecks() <= FLAG_max_polymorphic_checks)) {
+  const intptr_t number_of_checks = unary_checks.NumberOfChecks();
+  if ((number_of_checks > 0) &&
+      (number_of_checks <= FLAG_max_polymorphic_checks)) {
     ZoneGrowableArray<intptr_t>* results =
-        new (Z) ZoneGrowableArray<intptr_t>(unary_checks.NumberOfChecks() * 2);
+        new (Z) ZoneGrowableArray<intptr_t>(number_of_checks * 2);
     const Bool& as_bool =
         Bool::ZoneHandle(Z, InstanceOfAsBool(unary_checks, type, results));
     if (as_bool.raw() == Bool::True().raw()) {
@@ -1499,7 +1502,8 @@
   const intptr_t max_checks = (op_kind == Token::kEQ)
                                   ? FLAG_max_equality_polymorphic_checks
                                   : FLAG_max_polymorphic_checks;
-  if ((unary_checks.NumberOfChecks() > max_checks) && !is_dense &&
+  const intptr_t number_of_checks = unary_checks.NumberOfChecks();
+  if ((number_of_checks > max_checks) && !is_dense &&
       flow_graph()->InstanceCallNeedsClassCheck(
           instr, RawFunction::kRegularFunction)) {
     // Too many checks, it will be megamorphic which needs unary checks.
@@ -1571,7 +1575,7 @@
     }
   }
 
-  if ((unary_checks.NumberOfChecks() <= FLAG_max_polymorphic_checks) ||
+  if (number_of_checks <= FLAG_max_polymorphic_checks ||
       (has_one_target && is_dense)) {
     bool call_with_checks;
     if (has_one_target && FLAG_polymorphic_with_deopt) {
@@ -1623,7 +1627,7 @@
       // We can handle only monomorphic min/max call sites with both arguments
       // being either doubles or smis.
       if (CanUnboxDouble() && call->HasICData() &&
-          (call->ic_data()->NumberOfChecks() == 1)) {
+          call->ic_data()->NumberOfChecksIs(1)) {
         const ICData& ic_data = *call->ic_data();
         intptr_t result_cid = kIllegalCid;
         if (ICDataHasReceiverArgumentClassIds(ic_data, kDoubleCid,
@@ -1650,7 +1654,7 @@
     }
 
     case MethodRecognizer::kDoubleFromInteger: {
-      if (call->HasICData() && (call->ic_data()->NumberOfChecks() == 1)) {
+      if (call->HasICData() && call->ic_data()->NumberOfChecksIs(1)) {
         const ICData& ic_data = *call->ic_data();
         if (CanUnboxDouble()) {
           if (ArgIsAlways(kSmiCid, ic_data, 1)) {
@@ -1769,7 +1773,7 @@
 
 bool JitOptimizer::TryInlineInstanceSetter(InstanceCallInstr* instr,
                                            const ICData& unary_ic_data) {
-  ASSERT((unary_ic_data.NumberOfChecks() > 0) &&
+  ASSERT(!unary_ic_data.NumberOfChecksIs(0) &&
          (unary_ic_data.NumArgsTested() == 1));
   if (I->type_checks()) {
     // Checked mode setters are inlined like normal methods by conventional
@@ -1778,7 +1782,7 @@
   }
 
   ASSERT(instr->HasICData());
-  if (unary_ic_data.NumberOfChecks() == 0) {
+  if (unary_ic_data.NumberOfChecksIs(0)) {
     // No type feedback collected.
     return false;
   }
diff --git a/runtime/vm/kernel.h b/runtime/vm/kernel.h
index 29f7c7d..7bc2a48 100644
--- a/runtime/vm/kernel.h
+++ b/runtime/vm/kernel.h
@@ -2470,10 +2470,13 @@
   DartType* type() { return type_; }
   InferredValue* inferred_value() { return inferred_value_; }
   Expression* initializer() { return initializer_; }
+  TokenPosition equals_position() { return equals_position_; }
   TokenPosition end_position() { return end_position_; }
 
  private:
-  VariableDeclaration() : end_position_(TokenPosition::kNoSource) {}
+  VariableDeclaration()
+      : equals_position_(TokenPosition::kNoSourcePos),
+        end_position_(TokenPosition::kNoSource) {}
 
   template <typename T>
   friend class List;
@@ -2483,6 +2486,7 @@
   Child<DartType> type_;
   Child<InferredValue> inferred_value_;
   Child<Expression> initializer_;
+  TokenPosition equals_position_;
   TokenPosition end_position_;
 
   DISALLOW_COPY_AND_ASSIGN(VariableDeclaration);
diff --git a/runtime/vm/kernel_binary.cc b/runtime/vm/kernel_binary.cc
index d7e526f..a7f8559 100644
--- a/runtime/vm/kernel_binary.cc
+++ b/runtime/vm/kernel_binary.cc
@@ -1124,6 +1124,7 @@
 StaticSet* StaticSet::ReadFrom(Reader* reader) {
   TRACE_READ_OFFSET();
   StaticSet* set = new StaticSet();
+  set->position_ = reader->ReadPosition();
   set->target_reference_ = Reference::ReadMemberFrom(reader);
   set->expression_ = Expression::ReadFrom(reader);
   return set;
@@ -1245,6 +1246,7 @@
 AsExpression* AsExpression::ReadFrom(Reader* reader) {
   TRACE_READ_OFFSET();
   AsExpression* expr = new AsExpression();
+  expr->position_ = reader->ReadPosition();
   expr->operand_ = Expression::ReadFrom(reader);
   expr->type_ = DartType::ReadFrom(reader);
   return expr;
@@ -1326,7 +1328,9 @@
 
 Rethrow* Rethrow::ReadFrom(Reader* reader) {
   TRACE_READ_OFFSET();
-  return new Rethrow();
+  Rethrow* rethrow = new Rethrow();
+  rethrow->position_ = reader->ReadPosition();
+  return rethrow;
 }
 
 
@@ -1343,6 +1347,7 @@
   TRACE_READ_OFFSET();
   ListLiteral* literal = new ListLiteral();
   literal->is_const_ = is_const;
+  literal->position_ = reader->ReadPosition();
   literal->type_ = DartType::ReadFrom(reader);
   literal->expressions_.ReadFromStatic<Expression>(reader);
   return literal;
@@ -1508,6 +1513,7 @@
 BreakStatement* BreakStatement::ReadFrom(Reader* reader) {
   TRACE_READ_OFFSET();
   BreakStatement* stmt = new BreakStatement();
+  stmt->position_ = reader->ReadPosition();
   stmt->target_ = reader->helper()->labels()->Lookup(reader->ReadUInt());
   return stmt;
 }
@@ -1688,6 +1694,7 @@
 
   VariableDeclaration* decl = new VariableDeclaration();
   decl->position_ = reader->ReadPosition();
+  decl->equals_position_ = reader->ReadPosition();
   decl->flags_ = reader->ReadFlags();
   decl->name_ = Reference::ReadStringFrom(reader);
   decl->type_ = DartType::ReadFrom(reader);
diff --git a/runtime/vm/kernel_isolate.cc b/runtime/vm/kernel_isolate.cc
index 0b6e867..07f72d0 100644
--- a/runtime/vm/kernel_isolate.cc
+++ b/runtime/vm/kernel_isolate.cc
@@ -33,6 +33,10 @@
             use_dart_frontend,
             false,
             "Parse scripts with Dart-to-Kernel parser");
+DEFINE_FLAG(bool,
+            show_kernel_isolate,
+            false,
+            "Show Kernel service isolate as normal isolate.");
 
 const char* KernelIsolate::kName = DART_KERNEL_ISOLATE_NAME;
 Dart_IsolateCreateCallback KernelIsolate::create_callback_ = NULL;
diff --git a/runtime/vm/kernel_reader.cc b/runtime/vm/kernel_reader.cc
index b89479f..558ecd1 100644
--- a/runtime/vm/kernel_reader.cc
+++ b/runtime/vm/kernel_reader.cc
@@ -562,18 +562,30 @@
 void KernelReader::GenerateFieldAccessors(const dart::Class& klass,
                                           const dart::Field& field,
                                           Field* kernel_field) {
-  if (kernel_field->IsStatic() && kernel_field->initializer() != NULL) {
-    // Static fields with initializers either have the static value set to the
-    // initializer value if it is simple enough or else set to an uninitialized
-    // sentinel.
+  if (kernel_field->initializer() != NULL) {
     SimpleExpressionConverter converter(H.thread());
-    if (converter.IsSimple(kernel_field->initializer())) {
-      // We do not need a getter.
-      field.SetStaticValue(converter.SimpleValue(), true);
-      return;
+    const bool has_simple_initializer =
+        converter.IsSimple(kernel_field->initializer());
+    if (kernel_field->IsStatic()) {
+      // Static fields with initializers either have the static value set to the
+      // initializer value if it is simple enough or else set to an
+      // uninitialized sentinel.
+      if (has_simple_initializer) {
+        // We do not need a getter.
+        field.SetStaticValue(converter.SimpleValue(), true);
+        return;
+      }
+      // We do need a getter that evaluates the initializer if necessary.
+      field.SetStaticValue(Object::sentinel(), true);
+    } else if (has_simple_initializer) {
+      // Note: optimizer relies on DoubleInitialized bit in its field-unboxing
+      // heuristics. See JitOptimizer::VisitStoreInstanceField for more details.
+      field.RecordStore(converter.SimpleValue());
+      if (!converter.SimpleValue().IsNull() &&
+          converter.SimpleValue().IsDouble()) {
+        field.set_is_double_initialized(true);
+      }
     }
-    // We do need a getter that evaluates the initializer if necessary.
-    field.SetStaticValue(Object::sentinel(), true);
   }
 
   const dart::String& getter_name = H.DartGetterName(kernel_field->name());
diff --git a/runtime/vm/kernel_to_il.cc b/runtime/vm/kernel_to_il.cc
index 6f1a8c1..194fc9e 100644
--- a/runtime/vm/kernel_to_il.cc
+++ b/runtime/vm/kernel_to_il.cc
@@ -1345,7 +1345,6 @@
   return names;
 }
 
-
 ConstantEvaluator::ConstantEvaluator(FlowGraphBuilder* builder,
                                      Zone* zone,
                                      TranslationHelper* h,
@@ -2084,7 +2083,8 @@
   LocalVariable* context = MakeTemporary();
   instructions += LoadLocal(context);
   instructions += LoadLocal(parsed_function_->current_context_var());
-  instructions += StoreInstanceField(Context::parent_offset());
+  instructions +=
+      StoreInstanceField(TokenPosition::kNoSource, Context::parent_offset());
   instructions += StoreLocal(TokenPosition::kNoSource,
                              parsed_function_->current_context_var());
   ++context_depth_;
@@ -2434,13 +2434,13 @@
 }
 
 
-Fragment FlowGraphBuilder::RethrowException(int catch_try_index) {
+Fragment FlowGraphBuilder::RethrowException(TokenPosition position,
+                                            int catch_try_index) {
   Fragment instructions;
   instructions += Drop();
   instructions += Drop();
   instructions +=
-      Fragment(new (Z) ReThrowInstr(TokenPosition::kNoSource, catch_try_index))
-          .closed();
+      Fragment(new (Z) ReThrowInstr(position, catch_try_index)).closed();
   // Use it's side effect of leaving a constant on the stack (does not change
   // the graph).
   NullConstant();
@@ -2569,10 +2569,8 @@
   ASSERT(stack_ == NULL);
 
   const Function& function = parsed_function_->function();
-  if (FLAG_support_debugger && position.IsDebugPause() &&
-      !function.is_native()) {
-    instructions <<=
-        new (Z) DebugStepCheckInstr(position, RawPcDescriptors::kRuntimeCall);
+  if (NeedsDebugStepCheck(function, position)) {
+    instructions += DebugStepCheck(position);
   }
 
   if (FLAG_causal_async_stacks &&
@@ -2701,6 +2699,7 @@
 
 
 Fragment FlowGraphBuilder::StoreInstanceField(
+    TokenPosition position,
     intptr_t offset,
     StoreBarrierType emit_store_barrier) {
   Value* value = Pop();
@@ -2708,7 +2707,7 @@
     emit_store_barrier = kNoStoreBarrier;
   }
   StoreInstanceFieldInstr* store = new (Z) StoreInstanceFieldInstr(
-      offset, Pop(), value, emit_store_barrier, TokenPosition::kNoSource);
+      offset, Pop(), value, emit_store_barrier, position);
   return Fragment(store);
 }
 
@@ -2720,21 +2719,10 @@
     LocalVariable* value = MakeTemporary();
     instructions += LoadContextAt(variable->owner()->context_level());
     instructions += LoadLocal(value);
-    instructions +=
-        StoreInstanceField(Context::variable_offset(variable->index()));
+    instructions += StoreInstanceField(
+        position, Context::variable_offset(variable->index()));
   } else {
     Value* value = Pop();
-    if (FLAG_support_debugger && position.IsDebugPause() &&
-        !variable->IsInternal()) {
-      if (value->definition()->IsConstant() ||
-          value->definition()->IsAllocateObject() ||
-          (value->definition()->IsLoadLocal() &&
-           !value->definition()->AsLoadLocal()->local().IsInternal())) {
-        instructions <<= new (Z)
-            DebugStepCheckInstr(position, RawPcDescriptors::kRuntimeCall);
-      }
-    }
-
     StoreLocalInstr* store =
         new (Z) StoreLocalInstr(*variable, value, position);
     instructions <<= store;
@@ -2744,9 +2732,10 @@
 }
 
 
-Fragment FlowGraphBuilder::StoreStaticField(const dart::Field& field) {
-  return Fragment(new (Z) StoreStaticFieldInstr(MayCloneField(Z, field), Pop(),
-                                                TokenPosition::kNoSource));
+Fragment FlowGraphBuilder::StoreStaticField(TokenPosition position,
+                                            const dart::Field& field) {
+  return Fragment(
+      new (Z) StoreStaticFieldInstr(MayCloneField(Z, field), Pop(), position));
 }
 
 
@@ -3117,7 +3106,8 @@
         // eligible for garbage collection.
         body += LoadLocal(context);
         body += LoadLocal(parameter);
-        body += StoreInstanceField(Context::variable_offset(variable->index()));
+        body += StoreInstanceField(TokenPosition::kNoSource,
+                                   Context::variable_offset(variable->index()));
         body += NullConstant();
         body += StoreLocal(TokenPosition::kNoSource, parameter);
         body += Drop();
@@ -3277,7 +3267,6 @@
       // which acts like an anchor, so we need to skip it.
       then->LinkTo(yield_continuations_[i].entry->next());
       then->set_try_index(yield_continuations_[i].try_index);
-
       // False branch will contain the next comparison.
       dispatch = Fragment(dispatch.entry, otherwise);
       block = otherwise;
@@ -3318,8 +3307,7 @@
     context_depth_ = current_context_depth;
   }
 
-  if (FLAG_support_debugger && function->position().IsDebugPause() &&
-      !dart_function.is_native() && dart_function.is_debuggable()) {
+  if (NeedsDebugStepCheck(dart_function, function->position())) {
     // If a switch was added above: Start the switch by injecting a debugable
     // safepoint so stepping over an await works.
     // If not, still start the body with a debugable safepoint to ensure
@@ -3339,9 +3327,7 @@
       check_pos = function->position();
       ASSERT(check_pos.IsDebugPause());
     }
-    Fragment check(
-        new (Z) DebugStepCheckInstr(check_pos, RawPcDescriptors::kRuntimeCall));
-    body = check + body;
+    body = DebugStepCheck(check_pos) + body;
   }
 
   normal_entry->LinkTo(body.entry);
@@ -3446,7 +3432,8 @@
       body += LoadLocal(scopes_->this_variable);
       body += LoadLocal(
           LookupVariable(kernel_function->positional_parameters()[0]));
-      body += StoreInstanceField(LinkedHashMap::index_offset());
+      body += StoreInstanceField(TokenPosition::kNoSource,
+                                 LinkedHashMap::index_offset());
       body += NullConstant();
       break;
     case MethodRecognizer::kLinkedHashMap_getData:
@@ -3458,7 +3445,8 @@
       body += LoadLocal(scopes_->this_variable);
       body += LoadLocal(
           LookupVariable(kernel_function->positional_parameters()[0]));
-      body += StoreInstanceField(LinkedHashMap::data_offset());
+      body += StoreInstanceField(TokenPosition::kNoSource,
+                                 LinkedHashMap::data_offset());
       body += NullConstant();
       break;
     case MethodRecognizer::kLinkedHashMap_getHashMask:
@@ -3470,7 +3458,8 @@
       body += LoadLocal(scopes_->this_variable);
       body += LoadLocal(
           LookupVariable(kernel_function->positional_parameters()[0]));
-      body += StoreInstanceField(LinkedHashMap::hash_mask_offset(),
+      body += StoreInstanceField(TokenPosition::kNoSource,
+                                 LinkedHashMap::hash_mask_offset(),
                                  kNoStoreBarrier);
       body += NullConstant();
       break;
@@ -3483,7 +3472,8 @@
       body += LoadLocal(scopes_->this_variable);
       body += LoadLocal(
           LookupVariable(kernel_function->positional_parameters()[0]));
-      body += StoreInstanceField(LinkedHashMap::used_data_offset(),
+      body += StoreInstanceField(TokenPosition::kNoSource,
+                                 LinkedHashMap::used_data_offset(),
                                  kNoStoreBarrier);
       body += NullConstant();
       break;
@@ -3496,7 +3486,8 @@
       body += LoadLocal(scopes_->this_variable);
       body += LoadLocal(
           LookupVariable(kernel_function->positional_parameters()[0]));
-      body += StoreInstanceField(LinkedHashMap::deleted_keys_offset(),
+      body += StoreInstanceField(TokenPosition::kNoSource,
+                                 LinkedHashMap::deleted_keys_offset(),
                                  kNoStoreBarrier);
       body += NullConstant();
       break;
@@ -3537,7 +3528,7 @@
       body += StoreInstanceFieldGuarded(field, false);
     } else {
       body += LoadLocal(setter_value);
-      body += StoreStaticField(field);
+      body += StoreStaticField(TokenPosition::kNoSource, field);
     }
     body += NullConstant();
   } else if (is_method) {
@@ -3606,17 +3597,20 @@
   // Store the function and the context in the closure.
   fragment += LoadLocal(closure);
   fragment += Constant(target);
-  fragment += StoreInstanceField(Closure::function_offset());
+  fragment +=
+      StoreInstanceField(TokenPosition::kNoSource, Closure::function_offset());
 
   fragment += LoadLocal(closure);
   fragment += LoadLocal(context);
-  fragment += StoreInstanceField(Closure::context_offset());
+  fragment +=
+      StoreInstanceField(TokenPosition::kNoSource, Closure::context_offset());
 
   // The context is on top of the operand stack.  Store `this`.  The context
   // doesn't need a parent pointer because it doesn't close over anything
   // else.
   fragment += LoadLocal(scopes_->this_variable);
-  fragment += StoreInstanceField(Context::variable_offset(0));
+  fragment +=
+      StoreInstanceField(TokenPosition::kNoSource, Context::variable_offset(0));
 
   return fragment;
 }
@@ -3648,6 +3642,31 @@
 }
 
 
+bool FlowGraphBuilder::NeedsDebugStepCheck(const Function& function,
+                                           TokenPosition position) {
+  return FLAG_support_debugger && position.IsDebugPause() &&
+         !function.is_native() && function.is_debuggable();
+}
+
+
+bool FlowGraphBuilder::NeedsDebugStepCheck(Value* value,
+                                           TokenPosition position) {
+  if (!FLAG_support_debugger || !position.IsDebugPause()) return false;
+  Definition* definition = value->definition();
+  if (definition->IsConstant() || definition->IsLoadStaticField()) return true;
+  if (definition->IsAllocateObject()) {
+    return !definition->AsAllocateObject()->closure_function().IsNull();
+  }
+  return definition->IsLoadLocal() &&
+         !definition->AsLoadLocal()->local().IsInternal();
+}
+
+Fragment FlowGraphBuilder::DebugStepCheck(TokenPosition position) {
+  return Fragment(
+      new (Z) DebugStepCheckInstr(position, RawPcDescriptors::kRuntimeCall));
+}
+
+
 Fragment FlowGraphBuilder::EvaluateAssertion() {
   const dart::Class& klass = dart::Class::ZoneHandle(
       Z, dart::Library::LookupCoreClass(Symbols::AssertionError()));
@@ -4564,6 +4583,9 @@
 
 void FlowGraphBuilder::VisitVariableSet(VariableSet* node) {
   Fragment instructions = TranslateExpression(node->expression());
+  if (NeedsDebugStepCheck(stack_, node->position())) {
+    instructions = DebugStepCheck(node->position()) + instructions;
+  }
   instructions += CheckVariableTypeInCheckedMode(node->variable());
   instructions +=
       StoreLocal(node->position(), LookupVariable(node->variable()));
@@ -4616,11 +4638,14 @@
         dart::Field::ZoneHandle(Z, H.LookupFieldByKernelField(kernel_field));
     const AbstractType& dst_type = AbstractType::ZoneHandle(Z, field.type());
     Fragment instructions = TranslateExpression(node->expression());
+    if (NeedsDebugStepCheck(stack_, node->position())) {
+      instructions = DebugStepCheck(node->position()) + instructions;
+    }
     instructions += CheckAssignableInCheckedMode(
         dst_type, dart::String::ZoneHandle(Z, field.name()));
     LocalVariable* variable = MakeTemporary();
     instructions += LoadLocal(variable);
-    fragment_ = instructions + StoreStaticField(field);
+    fragment_ = instructions + StoreStaticField(node->position(), field);
   } else {
     ASSERT(target->IsProcedure());
 
@@ -5046,8 +5071,8 @@
     instructions += PushArgument();  // Type.
 
     instructions += InstanceCall(
-        TokenPosition::kNoSource,
-        dart::Library::PrivateCoreLibName(Symbols::_as()), Token::kAS, 3);
+        node->position(), dart::Library::PrivateCoreLibName(Symbols::_as()),
+        Token::kAS, 3);
   }
 
   fragment_ = instructions;
@@ -5271,6 +5296,9 @@
   Fragment instructions;
 
   instructions += TranslateExpression(node->expression());
+  if (NeedsDebugStepCheck(stack_, node->position())) {
+    instructions = DebugStepCheck(node->position()) + instructions;
+  }
   instructions += PushArgument();
   instructions += ThrowException(node->position());
   ASSERT(instructions.is_closed());
@@ -5282,11 +5310,13 @@
 void FlowGraphBuilder::VisitRethrow(Rethrow* node) {
   Fragment instructions;
 
+  instructions = DebugStepCheck(node->position()) + instructions;
   instructions += LoadLocal(catch_block_->exception_var());
   instructions += PushArgument();
   instructions += LoadLocal(catch_block_->stack_trace_var());
   instructions += PushArgument();
-  instructions += RethrowException(catch_block_->catch_try_index());
+  instructions +=
+      RethrowException(node->position(), catch_block_->catch_try_index());
 
   fragment_ = instructions;
 }
@@ -5349,13 +5379,17 @@
   if (instructions.is_open()) {
     if (inside_try_finally) {
       ASSERT(scopes_->finally_return_variable != NULL);
-      instructions += StoreLocal(TokenPosition::kNoSource,
-                                 scopes_->finally_return_variable);
+      const Function& function = parsed_function_->function();
+      if (NeedsDebugStepCheck(function, node->position())) {
+        instructions += DebugStepCheck(node->position());
+      }
+      instructions +=
+          StoreLocal(node->position(), scopes_->finally_return_variable);
       instructions += Drop();
       instructions += TranslateFinallyFinalizers(NULL, -1);
       if (instructions.is_open()) {
         instructions += LoadLocal(scopes_->finally_return_variable);
-        instructions += Return(node->position());
+        instructions += Return(TokenPosition::kNoSource);
       }
     } else {
       instructions += Return(node->position());
@@ -5392,16 +5426,24 @@
       instructions += CheckVariableTypeInCheckedMode(node);
     }
   }
-  instructions += StoreLocal(variable->token_pos(), variable);
+  // Use position of equal sign if it exists. If the equal sign does not exist
+  // use the position of the identifier.
+  TokenPosition debug_position =
+      Utils::Maximum(node->position(), node->equals_position());
+  if (NeedsDebugStepCheck(stack_, debug_position)) {
+    instructions = DebugStepCheck(debug_position) + instructions;
+  }
+  instructions += StoreLocal(node->position(), variable);
   instructions += Drop();
   fragment_ = instructions;
 }
 
 
 void FlowGraphBuilder::VisitFunctionDeclaration(FunctionDeclaration* node) {
-  Fragment instructions = TranslateFunctionNode(node->function(), node);
+  Fragment instructions = DebugStepCheck(node->position());
+  instructions += TranslateFunctionNode(node->function(), node);
   instructions +=
-      StoreLocal(TokenPosition::kNoSource, LookupVariable(node->variable()));
+      StoreLocal(node->position(), LookupVariable(node->variable()));
   instructions += Drop();
   fragment_ = instructions;
 }
@@ -5640,6 +5682,9 @@
   instructions +=
       TranslateFinallyFinalizers(outer_finally, target_context_depth);
   if (instructions.is_open()) {
+    if (NeedsDebugStepCheck(parsed_function_->function(), node->position())) {
+      instructions += DebugStepCheck(node->position());
+    }
     instructions += Goto(destination);
   }
   fragment_ = instructions;
@@ -5982,7 +6027,8 @@
     finally_body += PushArgument();
     finally_body += LoadLocal(CurrentStackTrace());
     finally_body += PushArgument();
-    finally_body += RethrowException(try_handler_index);
+    finally_body +=
+        RethrowException(TokenPosition::kNoSource, try_handler_index);
     Drop();
   }
   --catch_depth_;
@@ -6093,7 +6139,7 @@
     catch_body += PushArgument();
     catch_body += LoadLocal(CurrentStackTrace());
     catch_body += PushArgument();
-    catch_body += RethrowException(try_handler_index);
+    catch_body += RethrowException(TokenPosition::kNoSource, try_handler_index);
     Drop();
   }
   --catch_depth_;
@@ -6167,7 +6213,8 @@
     rethrow += PushArgument();
     rethrow += LoadLocal(stack_trace_var);
     rethrow += PushArgument();
-    rethrow += RethrowException(CatchClauseNode::kInvalidTryIndex);
+    rethrow +=
+        RethrowException(node->position(), CatchClauseNode::kInvalidTryIndex);
     Drop();
 
 
@@ -6268,11 +6315,13 @@
   // Store the function and the context in the closure.
   instructions += LoadLocal(closure);
   instructions += Constant(function);
-  instructions += StoreInstanceField(Closure::function_offset());
+  instructions +=
+      StoreInstanceField(TokenPosition::kNoSource, Closure::function_offset());
 
   instructions += LoadLocal(closure);
   instructions += LoadLocal(parsed_function_->current_context_var());
-  instructions += StoreInstanceField(Closure::context_offset());
+  instructions +=
+      StoreInstanceField(TokenPosition::kNoSource, Closure::context_offset());
 
   return instructions;
 }
diff --git a/runtime/vm/kernel_to_il.h b/runtime/vm/kernel_to_il.h
index 211a61b..5dea401 100644
--- a/runtime/vm/kernel_to_il.h
+++ b/runtime/vm/kernel_to_il.h
@@ -837,7 +837,7 @@
                         intptr_t num_args_checked = 1);
   Fragment ClosureCall(int argument_count, const Array& argument_names);
   Fragment ThrowException(TokenPosition position);
-  Fragment RethrowException(int catch_try_index);
+  Fragment RethrowException(TokenPosition position, int catch_try_index);
   Fragment LoadClassId();
   Fragment LoadField(const dart::Field& field);
   Fragment LoadField(intptr_t offset, intptr_t class_id = kDynamicCid);
@@ -868,10 +868,11 @@
       bool is_initialization_store,
       StoreBarrierType emit_store_barrier = kEmitStoreBarrier);
   Fragment StoreInstanceField(
+      TokenPosition position,
       intptr_t offset,
       StoreBarrierType emit_store_barrier = kEmitStoreBarrier);
   Fragment StoreLocal(TokenPosition position, LocalVariable* variable);
-  Fragment StoreStaticField(const dart::Field& field);
+  Fragment StoreStaticField(TokenPosition position, const dart::Field& field);
   Fragment StringInterpolate(TokenPosition position);
   Fragment ThrowTypeError();
   Fragment ThrowNoSuchMethodError();
@@ -890,6 +891,10 @@
   Fragment AssertAssignable(const dart::AbstractType& dst_type,
                             const dart::String& dst_name);
 
+  bool NeedsDebugStepCheck(const Function& function, TokenPosition position);
+  bool NeedsDebugStepCheck(Value* value, TokenPosition position);
+  Fragment DebugStepCheck(TokenPosition position);
+
   dart::RawFunction* LookupMethodByMember(Member* target,
                                           const dart::String& method_name);
 
@@ -971,6 +976,7 @@
     return scopes_->catch_context_variables[try_depth_];
   }
 
+
   // A chained list of breakable blocks. Chaining and lookup is done by the
   // [BreakableBlock] class.
   BreakableBlock* breakable_block_;
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index 37f76b2..0190804 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -5946,10 +5946,11 @@
         if (type_param_name.Equals(type_name)) {
           if (parent_level > 0) {
             // Clone type parameter and set parent_level.
-            return TypeParameter::New(
+            type_param = TypeParameter::New(
                 Class::Handle(), function, type_param.index(), parent_level,
                 type_param_name, AbstractType::Handle(type_param.bound()),
                 TokenPosition::kNoSource);
+            type_param.SetIsFinalized();
           }
           return type_param.raw();
         }
@@ -9221,9 +9222,18 @@
       *column = offset - smi.Value() + 1;
     }
     if (token_len != NULL) {
-      // We don't explicitly save this data.
-      // TODO(jensj): Load the source and attempt to find it from there.
+      // We don't explicitly save this data: Load the source
+      // and find it from there.
+      const String& source = String::Handle(zone, Source());
       *token_len = 1;
+      if (offset < source.Length() &&
+          Scanner::IsIdentStartChar(source.CharAt(offset))) {
+        for (intptr_t i = offset + 1;
+             i < source.Length() && Scanner::IsIdentChar(source.CharAt(i));
+             ++i) {
+          ++*token_len;
+        }
+      }
     }
     return;
   }
@@ -12994,6 +13004,19 @@
 }
 
 
+bool ICData::NumberOfChecksIs(intptr_t n) const {
+  const intptr_t length = Length();
+  for (intptr_t i = 0; i < length; i++) {
+    if (i == n) {
+      return IsSentinelAt(i);
+    } else {
+      if (IsSentinelAt(i)) return false;
+    }
+  }
+  return n == length;
+}
+
+
 // Discounts any checks with usage of zero.
 intptr_t ICData::NumberOfUsedChecks() const {
   intptr_t n = NumberOfChecks();
@@ -13056,9 +13079,8 @@
 
 
 void ICData::ClearCountAt(intptr_t index) const {
-  const intptr_t len = NumberOfChecks();
   ASSERT(index >= 0);
-  ASSERT(index < len);
+  ASSERT(index < NumberOfChecks());
   SetCountAt(index, 0);
 }
 
@@ -13157,7 +13179,7 @@
   Zone* zone = Thread::Current()->zone();
   const Function& smi_op_target =
       Function::Handle(Resolver::ResolveDynamicAnyArgs(zone, smi_class, name));
-  if (NumberOfChecks() == 0) {
+  if (NumberOfChecksIs(0)) {
     GrowableArray<intptr_t> class_ids(2);
     class_ids.Add(kSmiCid);
     class_ids.Add(kSmiCid);
@@ -13165,7 +13187,7 @@
     // 'AddCheck' sets the initial count to 1.
     SetCountAt(0, 0);
     is_smi_two_args_op = true;
-  } else if (NumberOfChecks() == 1) {
+  } else if (NumberOfChecksIs(1)) {
     GrowableArray<intptr_t> class_ids(2);
     Function& target = Function::Handle();
     GetCheckAt(0, &class_ids, &target);
@@ -13651,7 +13673,7 @@
   aggregate.Sort(CidCount::HighestCountFirst);
 
   ICData& result = ICData::Handle(ICData::NewFrom(*this, kNumArgsTested));
-  ASSERT(result.NumberOfChecks() == 0);
+  ASSERT(result.NumberOfChecksIs(0));
   // Room for all entries and the sentinel.
   const intptr_t data_len = result.TestEntryLength() * (aggregate.length() + 1);
   // Allocate the array but do not assign it to result until we have populated
@@ -13668,13 +13690,13 @@
   }
   WriteSentinel(data, result.TestEntryLength());
   result.set_ic_data_array(data);
-  ASSERT(result.NumberOfChecks() == aggregate.length());
+  ASSERT(result.NumberOfChecksIs(aggregate.length()));
   return result.raw();
 }
 
 
 bool ICData::AllTargetsHaveSameOwner(intptr_t owner_cid) const {
-  if (NumberOfChecks() == 0) return false;
+  if (NumberOfChecksIs(0)) return false;
   Class& cls = Class::Handle();
   const intptr_t len = NumberOfChecks();
   for (intptr_t i = 0; i < len; i++) {
@@ -13707,7 +13729,7 @@
 // Returns true if all targets are the same.
 // TODO(srdjan): if targets are native use their C_function to compare.
 bool ICData::HasOneTarget() const {
-  ASSERT(NumberOfChecks() > 0);
+  ASSERT(!NumberOfChecksIs(0));
   const Function& first_target = Function::Handle(GetTargetAt(0));
   const intptr_t len = NumberOfChecks();
   for (intptr_t i = 1; i < len; i++) {
@@ -17719,11 +17741,15 @@
     return false;
   }
   const TypeParameter& other_type_param = TypeParameter::Cast(other);
-  if (parameterized_class() != other_type_param.parameterized_class()) {
+  if (parameterized_class_id() != other_type_param.parameterized_class_id()) {
+    return false;
+  }
+  if (parameterized_function() != other_type_param.parameterized_function()) {
     return false;
   }
   if (IsFinalized() == other_type_param.IsFinalized()) {
-    return index() == other_type_param.index();
+    return (index() == other_type_param.index()) &&
+           (parent_level() == other_type_param.parent_level());
   }
   return name() == other_type_param.name();
 }
@@ -17917,7 +17943,13 @@
 
 intptr_t TypeParameter::ComputeHash() const {
   ASSERT(IsFinalized());
-  uint32_t result = Class::Handle(parameterized_class()).id();
+  uint32_t result;
+  if (IsClassTypeParameter()) {
+    result = parameterized_class_id();
+  } else {
+    result = Function::Handle(parameterized_function()).Hash();
+    result = CombineHashes(result, parent_level());
+  }
   // No need to include the hash of the bound, since the type parameter is fully
   // identified by its class and index.
   result = CombineHashes(result, index());
diff --git a/runtime/vm/object.h b/runtime/vm/object.h
index 84656ed..6daa414 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -1918,11 +1918,16 @@
   // the final one.
   intptr_t Length() const;
 
+  // Takes O(result) time!
   intptr_t NumberOfChecks() const;
 
   // Discounts any checks with usage of zero.
+  // Takes O(result)) time!
   intptr_t NumberOfUsedChecks() const;
 
+  // Takes O(n) time!
+  bool NumberOfChecksIs(intptr_t n) const;
+
   static intptr_t InstanceSize() {
     return RoundedAllocationSize(sizeof(RawICData));
   }
diff --git a/runtime/vm/parser.cc b/runtime/vm/parser.cc
index f139e76..739f604 100644
--- a/runtime/vm/parser.cc
+++ b/runtime/vm/parser.cc
@@ -60,7 +60,7 @@
             "Enable generic function syntax.");
 DEFINE_FLAG(bool,
             generic_method_semantics,
-            true,
+            false,
             "Enable generic function semantics (not yet supported).");
 DEFINE_FLAG(bool,
             initializing_formal_access,
@@ -1163,7 +1163,7 @@
   }
   parsed_function->SetNodeSequence(node_sequence);
 
-  // The instantiator may be required at run time for generic type checks or
+  // The instantiators may be required at run time for generic type checks or
   // allocation of generic types.
   if (parser.IsInstantiatorRequired()) {
     // In the case of a local function, only set the instantiator if the
@@ -1181,6 +1181,16 @@
       parsed_function->set_instantiator(instantiator);
     }
   }
+  if (FLAG_generic_method_semantics && parser.current_function().IsGeneric()) {
+    const String* variable_name = &Symbols::FunctionInstantiatorVar();
+    const bool kTestOnly = true;
+    LocalVariable* instantiator =
+        node_sequence->scope()->LookupVariable(*variable_name, kTestOnly);
+    ASSERT(instantiator != NULL);
+    parsed_function->set_function_instantiator(instantiator);
+    // Function instantiator variables of parent generic functions, if any, are
+    // captured and accessible via the context.
+  }
 }
 
 
@@ -3460,6 +3470,14 @@
   ASSERT(!func.IsGenerativeConstructor());
   OpenFunctionBlock(func);  // Build local scope for function.
 
+  if (FLAG_generic_method_semantics && func.IsGeneric()) {
+    // Insert function instantiator variable to scope.
+    LocalVariable* function_instantiator = new (Z) LocalVariable(
+        TokenPosition::kNoSource, TokenPosition::kNoSource,
+        Symbols::FunctionInstantiatorVar(), Object::dynamic_type());
+    current_block_->scope->AddVariable(function_instantiator);
+  }
+
   ParamList params;
   // An instance closure function may capture and access the receiver, but via
   // the context and not via the first formal parameter.
@@ -3549,18 +3567,6 @@
 
     // Populate function scope with the formal parameters.
     AddFormalParamsToScope(&params, current_block_->scope);
-
-    if (I->type_checks() && (FunctionLevel() > 0)) {
-      // We are parsing, but not compiling, a local function.
-      // The instantiator may be required at run time for generic type checks.
-      if (IsInstantiatorRequired()) {
-        // Make sure that the receiver of the enclosing instance function
-        // (or implicit first parameter of an enclosing factory) is marked as
-        // captured if type checks are enabled, because they may access it to
-        // instantiate types.
-        CaptureInstantiator();
-      }
-    }
   }
 
   const TokenPosition modifier_pos = TokenPos();
@@ -3620,6 +3626,22 @@
     OpenAsyncGeneratorClosure();
   }
 
+  // Function level is now correctly set to parse the (possibly async) body.
+  if (I->type_checks() && (FunctionLevel() > 0)) {
+    // We are parsing, but not compiling, a local function.
+    // The instantiator may be required at run time for generic type checks.
+    // Note that the source of this local function may not reference the
+    // generic type explicitly. However, it may assign a value to a captured
+    // variable declared with its generic type in the enclosing function.
+    // Make sure that the receiver of the enclosing instance function
+    // (or implicit first parameter of an enclosing factory) is marked as
+    // captured if type checks are enabled, because they may access it to
+    // instantiate types.
+    // If any enclosing parent of the function being parsed is generic, capture
+    // their function instantiators.
+    CaptureAllInstantiators();
+  }
+
   BoolScope allow_await(&this->await_is_keyword_,
                         func.IsAsyncOrGenerator() || func.is_generated_body());
   TokenPosition end_token_pos = TokenPosition::kNoSource;
@@ -3792,10 +3814,8 @@
     return LibraryPrefix::null();
   }
   // Check whether the identifier is shadowed by a function type parameter.
-  // TODO(regis): Shortcut this lookup if no generic functions in scope.
-  if (!innermost_function().IsNull() &&
-      (innermost_function().LookupTypeParameter(ident, NULL) !=
-       TypeParameter::null())) {
+  if (InGenericFunctionScope() && (innermost_function().LookupTypeParameter(
+                                       ident, NULL) != TypeParameter::null())) {
     return LibraryPrefix::null();
   }
   // Check whether the identifier is shadowed by a class type parameter.
@@ -5527,6 +5547,9 @@
           parameterizing_class ? current_class() : Class::Handle(Z),
           parameterizing_class ? Function::Handle(Z) : innermost_function(),
           index, 0, type_parameter_name, type_parameter_bound, declaration_pos);
+      if (!parameterizing_class) {
+        type_parameter.SetIsFinalized();
+      }
       type_parameters_array.Add(
           &AbstractType::ZoneHandle(Z, type_parameter.raw()));
       if (FLAG_enable_mirrors && metadata_pos.IsReal()) {
@@ -7022,13 +7045,6 @@
   OpenFunctionBlock(closure);
   AddFormalParamsToScope(&closure_params, current_block_->scope);
   async_temp_scope_ = current_block_->scope;
-
-  // Capture instantiator in case it may be needed to generate the type
-  // check of the return value. (C.f. handling of Token::kRETURN.)
-  ASSERT(FunctionLevel() > 0);
-  if (I->type_checks() && IsInstantiatorRequired()) {
-    CaptureInstantiator();
-  }
   return closure.raw();
 }
 
@@ -7717,11 +7733,45 @@
 }
 
 
-void Parser::CaptureFunctionInstantiator() {
+void Parser::CaptureFunctionInstantiators() {
+  ASSERT(InGenericFunctionScope());
   ASSERT(FunctionLevel() > 0);
+  if (!FLAG_generic_method_semantics) {
+    return;
+  }
+  // Capture function instantiators starting at parent of innermost function.
+  intptr_t variable_function_level = FunctionLevel() - 1;
   const String* variable_name = &Symbols::FunctionInstantiatorVar();
-  current_block_->scope->CaptureVariable(
-      current_block_->scope->LookupVariable(*variable_name, true));
+  LocalScope* scope = current_block_->scope;
+  do {
+    while (scope->function_level() > variable_function_level) {
+      scope = scope->parent();
+    }
+    // Function instantiator is in top scope at that function level.
+    LocalScope* parent_scope = scope->parent();
+    while ((parent_scope != NULL) &&
+           (parent_scope->function_level() == scope->function_level())) {
+      scope = parent_scope;
+      parent_scope = scope->parent();
+    }
+    LocalVariable* function_instantiator_var =
+        scope->LookupVariable(*variable_name, true);
+    if (function_instantiator_var != NULL) {
+      current_block_->scope->CaptureVariable(function_instantiator_var);
+    }
+    scope = scope->parent();
+    variable_function_level--;
+  } while (variable_function_level >= 0);
+}
+
+
+void Parser::CaptureAllInstantiators() {
+  if (IsInstantiatorRequired()) {
+    CaptureInstantiator();
+  }
+  if (AreFunctionInstantiatorsRequired()) {
+    CaptureFunctionInstantiators();
+  }
 }
 
 
@@ -8065,10 +8115,9 @@
   ASSERT(current_class().is_finalized());
   ASSERT(signature_type.IsFinalized());
 
-  // Make sure that the instantiator is captured.
-  if ((FunctionLevel() > 0) &&
-      Class::Handle(signature_type.type_class()).IsGeneric()) {
-    CaptureInstantiator();
+  // Make sure that the instantiators are captured.
+  if ((FunctionLevel() > 0) && !signature_type.IsInstantiated()) {
+    CaptureAllInstantiators();
   }
 
   // A local signature type itself cannot be malformed or malbounded, only its
@@ -9941,8 +9990,8 @@
       // Has a type specification that is not malformed or malbounded.  Now
       // form an 'if type check' to guard the catch handler code.
       if (!exception_param.type->IsInstantiated() && (FunctionLevel() > 0)) {
-        // Make sure that the instantiator is captured.
-        CaptureInstantiator();
+        // Make sure that the instantiators are captured.
+        CaptureAllInstantiators();
       }
       TypeNode* exception_type =
           new (Z) TypeNode(catch_pos, *exception_param.type);
@@ -10972,8 +11021,8 @@
         const AbstractType& type = AbstractType::ZoneHandle(
             Z, ParseTypeOrFunctionType(false, ClassFinalizer::kCanonicalize));
         if (!type.IsInstantiated() && (FunctionLevel() > 0)) {
-          // Make sure that the instantiator is captured.
-          CaptureInstantiator();
+          // Make sure that the instantiators are captured.
+          CaptureAllInstantiators();
         }
         right_operand = new (Z) TypeNode(type_pos, type);
         // In production mode, the type may be malformed.
@@ -11840,24 +11889,25 @@
                   "from static function",
                   name.ToCString());
     }
-    // TODO(regis): Verify that CaptureInstantiator() was already called
-    // and remove call below.
     if (FunctionLevel() > 0) {
       // Make sure that the class instantiator is captured.
       CaptureInstantiator();
     }
     type_parameter ^= CanonicalizeType(type_parameter);
-    ASSERT(!type_parameter.IsMalformed());
-    return new (Z) TypeNode(primary_pos, type_parameter);
   } else {
     ASSERT(type_parameter.IsFunctionTypeParameter());
-    // TODO(regis): Verify that CaptureFunctionInstantiator() was already
-    // called if necessary.
-    // TODO(regis): Finalize type parameter and return as type node.
-    // For now, map to dynamic type.
-    Type& type = Type::ZoneHandle(Z, Type::DynamicType());
-    return new (Z) TypeNode(primary_pos, type);
+    if (!FLAG_generic_method_semantics) {
+      Type& type = Type::ZoneHandle(Z, Type::DynamicType());
+      return new (Z) TypeNode(primary_pos, type);
+    }
+    if (type_parameter.parent_level() > 0) {
+      // Make sure that the function instantiators are captured.
+      CaptureFunctionInstantiators();
+    }
   }
+  ASSERT(type_parameter.IsFinalized());
+  ASSERT(!type_parameter.IsMalformed());
+  return new (Z) TypeNode(primary_pos, type_parameter);
 }
 
 
@@ -12361,13 +12411,11 @@
         String::Handle(Z, unresolved_class.ident());
     if (unresolved_class.library_or_library_prefix() == Object::null()) {
       // First check if the type is a function type parameter.
-      if (!innermost_function().IsNull()) {
-        // TODO(regis): Shortcut this lookup if no generic functions in scope.
-        // A bit has_generic_parent() would be useful on Function.
-        // Unfortunately, all 32 kind bits are used in Function.
+      if (InGenericFunctionScope()) {
+        intptr_t type_param_func_level = FunctionLevel();
         TypeParameter& type_parameter = TypeParameter::ZoneHandle(
-            Z, innermost_function().LookupTypeParameter(unresolved_class_name,
-                                                        NULL));
+            Z, innermost_function().LookupTypeParameter(
+                   unresolved_class_name, &type_param_func_level));
         if (!type_parameter.IsNull()) {
           // A type parameter cannot be parameterized, so make the type
           // malformed if type arguments have previously been parsed.
@@ -12379,10 +12427,13 @@
                 String::Handle(Z, type_parameter.name()).ToCString());
             return;
           }
-          // TODO(regis): Mark function type parameter as finalized (its index
-          // does not need adjustment upon finalization) and return it.
-          // For now, resolve the function type parameter to dynamic.
-          *type = Type::DynamicType();
+          if (FLAG_generic_method_semantics) {
+            ASSERT(type_parameter.IsFinalized());
+            ASSERT(!type_parameter.IsMalformed());
+            *type = type_parameter.raw();
+          } else {
+            *type = Type::DynamicType();
+          }
           return;
         }
       }
@@ -12518,6 +12569,37 @@
 }
 
 
+bool Parser::AreFunctionInstantiatorsRequired() const {
+  ASSERT(!innermost_function().IsNull());
+  Function& parent = Function::Handle(innermost_function().parent_function());
+  while (!parent.IsNull()) {
+    if (parent.IsGeneric()) {
+      return true;
+    }
+    parent = parent.parent_function();
+  }
+  return false;
+}
+
+
+bool Parser::InGenericFunctionScope() const {
+  if (!innermost_function().IsNull()) {
+    // With one more free tag bit in Function, we could cache this information.
+    if (innermost_function().IsGeneric()) {
+      return true;
+    }
+    Function& parent = Function::Handle(innermost_function().parent_function());
+    while (!parent.IsNull()) {
+      if (parent.IsGeneric()) {
+        return true;
+      }
+      parent = parent.parent_function();
+    }
+  }
+  return false;
+}
+
+
 void Parser::InsertCachedConstantValue(const Script& script,
                                        TokenPosition token_pos,
                                        const Instance& value) {
@@ -12965,8 +13047,7 @@
   AstNode* resolved = NULL;
   intptr_t resolved_func_level = 0;
   ResolveIdentInLocalScope(ident_pos, ident, &resolved, &resolved_func_level);
-  if (!innermost_function().IsNull()) {
-    // TODO(regis): Shortcut this lookup if no generic functions in scope.
+  if (InGenericFunctionScope()) {
     intptr_t type_param_func_level = FunctionLevel();
     const TypeParameter& type_parameter =
         TypeParameter::ZoneHandle(Z, innermost_function().LookupTypeParameter(
@@ -12975,16 +13056,13 @@
       if ((resolved == NULL) || (resolved_func_level < type_param_func_level)) {
         // The identifier is a function type parameter, possibly shadowing
         // 'resolved'.
-        if ((FunctionLevel() > 0) &&
-            (type_param_func_level < FunctionLevel())) {
-          // Make sure that the function instantiator is captured.
-          CaptureFunctionInstantiator();
+        if (!FLAG_generic_method_semantics) {
+          Type& type = Type::ZoneHandle(Z, Type::DynamicType());
+          return new (Z) TypeNode(ident_pos, type);
         }
-        // TODO(regis): Mark function type parameter as finalized (its index
-        // does not need adjustment upon finalization) and return as type node.
-        // For now, resolve the function type parameter to dynamic.
-        Type& type = Type::ZoneHandle(Z, Type::DynamicType());
-        return new (Z) TypeNode(ident_pos, type);
+        ASSERT(type_parameter.IsFinalized());
+        ASSERT(!type_parameter.IsMalformed());
+        return new (Z) TypeNode(ident_pos, type_parameter);
       }
     }
   }
@@ -12994,10 +13072,6 @@
       TypeParameter& type_parameter = TypeParameter::ZoneHandle(
           Z, current_class().LookupTypeParameter(ident));
       if (!type_parameter.IsNull()) {
-        if (FunctionLevel() > 0) {
-          // Make sure that the class instantiator is captured.
-          CaptureInstantiator();
-        }
         type_parameter ^= CanonicalizeType(type_parameter);
         ASSERT(!type_parameter.IsMalformed());
         return new (Z) TypeNode(ident_pos, type_parameter);
@@ -13432,8 +13506,8 @@
     ASSERT(!factory_method.IsNull());
     if (!list_type_arguments.IsNull() &&
         !list_type_arguments.IsInstantiated() && (FunctionLevel() > 0)) {
-      // Make sure that the instantiator is captured.
-      CaptureInstantiator();
+      // Make sure that the instantiators are captured.
+      CaptureAllInstantiators();
     }
     TypeArguments& factory_type_args =
         TypeArguments::ZoneHandle(Z, list_type_arguments.raw());
@@ -13683,7 +13757,7 @@
     if (!map_type_arguments.IsNull() && !map_type_arguments.IsInstantiated() &&
         (FunctionLevel() > 0)) {
       // Make sure that the instantiator is captured.
-      CaptureInstantiator();
+      CaptureAllInstantiators();
     }
     TypeArguments& factory_type_args =
         TypeArguments::ZoneHandle(Z, map_type_arguments.raw());
@@ -14168,10 +14242,9 @@
     // enclosing function if necessary.
     OpenFunctionBlock(tearoff_func);
     // If there are type arguments in the tearoff expression that are
-    // not yet instantiated, capture the instantiator.
-    if (IsInstantiatorRequired() && !type_arguments.IsNull() &&
-        !type_arguments.IsInstantiated()) {
-      CaptureInstantiator();
+    // not yet instantiated, capture the instantiators.
+    if (!type_arguments.IsNull() && !type_arguments.IsInstantiated()) {
+      CaptureAllInstantiators();
     }
     SequenceNode* tearoff_body = CloseBlock();
     ClosureNode* closure_obj =
@@ -14255,8 +14328,8 @@
     CheckConstructorCallTypeArguments(new_pos, constructor, type_arguments);
     if (!type_arguments.IsNull() && !type_arguments.IsInstantiated() &&
         (FunctionLevel() > 0)) {
-      // Make sure that the instantiator is captured.
-      CaptureInstantiator();
+      // Make sure that the instantiators are captured.
+      CaptureAllInstantiators();
     }
     // If the type argument vector is not instantiated, we verify in checked
     // mode at runtime that it is within its declared bounds.
@@ -14440,8 +14513,7 @@
       ResolveIdentInLocalScope(qual_ident_pos, ident, &primary,
                                &primary_func_level);
       // Check whether the identifier is shadowed by a function type parameter.
-      if (!innermost_function().IsNull()) {
-        // TODO(regis): Shortcut this lookup if no generic functions in scope.
+      if (InGenericFunctionScope()) {
         intptr_t type_param_func_level = FunctionLevel();
         TypeParameter& type_param = TypeParameter::ZoneHandle(
             Z, innermost_function().LookupTypeParameter(
@@ -14451,11 +14523,6 @@
               (primary_func_level < type_param_func_level)) {
             // The identifier is a function type parameter, possibly shadowing
             // already resolved 'primary'.
-            if ((FunctionLevel() > 0) &&
-                (type_param_func_level < FunctionLevel())) {
-              // Make sure that the function instantiator is captured.
-              CaptureFunctionInstantiator();
-            }
             return new (Z) PrimaryNode(qual_ident_pos, type_param);
           }
         }
diff --git a/runtime/vm/parser.h b/runtime/vm/parser.h
index 539435b..a696a28 100644
--- a/runtime/vm/parser.h
+++ b/runtime/vm/parser.h
@@ -96,6 +96,7 @@
         node_sequence_(NULL),
         regexp_compile_data_(NULL),
         instantiator_(NULL),
+        function_instantiator_(NULL),
         current_context_var_(NULL),
         expression_temp_var_(NULL),
         finally_return_temp_var_(NULL),
@@ -130,9 +131,16 @@
 
   LocalVariable* instantiator() const { return instantiator_; }
   void set_instantiator(LocalVariable* instantiator) {
-    // May be NULL.
+    ASSERT(instantiator != NULL);
     instantiator_ = instantiator;
   }
+  LocalVariable* function_instantiator() const {
+    return function_instantiator_;
+  }
+  void set_function_instantiator(LocalVariable* function_instantiator) {
+    ASSERT(function_instantiator != NULL);
+    function_instantiator_ = function_instantiator;
+  }
 
   void set_default_parameter_values(ZoneGrowableArray<const Instance*>* list) {
     default_parameter_values_ = list;
@@ -224,6 +232,7 @@
   SequenceNode* node_sequence_;
   RegExpCompileData* regexp_compile_data_;
   LocalVariable* instantiator_;
+  LocalVariable* function_instantiator_;
   LocalVariable* current_context_var_;
   LocalVariable* expression_temp_var_;
   LocalVariable* finally_return_temp_var_;
@@ -670,7 +679,8 @@
   LocalVariable* LookupTypeArgumentsParameter(LocalScope* from_scope,
                                               bool test_only);
   void CaptureInstantiator();
-  void CaptureFunctionInstantiator();
+  void CaptureFunctionInstantiators();
+  void CaptureAllInstantiators();
   AstNode* LoadReceiver(TokenPosition token_pos);
   AstNode* LoadFieldIfUnresolved(AstNode* node);
   AstNode* LoadClosure(PrimaryNode* primary);
@@ -834,6 +844,8 @@
   bool ParsingStaticMember() const;
   const AbstractType* ReceiverType(const Class& cls);
   bool IsInstantiatorRequired() const;
+  bool AreFunctionInstantiatorsRequired() const;
+  bool InGenericFunctionScope() const;
   bool ResolveIdentInLocalScope(TokenPosition ident_pos,
                                 const String& ident,
                                 AstNode** node,
diff --git a/runtime/vm/precompiler.h b/runtime/vm/precompiler.h
index 788182a..3989c1f 100644
--- a/runtime/vm/precompiler.h
+++ b/runtime/vm/precompiler.h
@@ -181,6 +181,9 @@
 
 typedef DirectChainedHashMap<UnlinkedCallKeyValueTrait> UnlinkedCallSet;
 
+static inline intptr_t SimplePointerHash(void* ptr) {
+  return reinterpret_cast<intptr_t>(ptr) * 2654435761UL;
+}
 
 class FunctionKeyValueTrait {
  public:
@@ -193,7 +196,15 @@
 
   static Value ValueOf(Pair kv) { return kv; }
 
-  static inline intptr_t Hashcode(Key key) { return key->token_pos().value(); }
+  static inline intptr_t Hashcode(Key key) {
+    // We are using pointer hash for objects originating from Kernel because
+    // Fasta currently does not assign any position information to them.
+    if (key->kernel_function() != NULL) {
+      return SimplePointerHash(key->kernel_function());
+    } else {
+      return key->token_pos().value();
+    }
+  }
 
   static inline bool IsKeyEqual(Pair pair, Key key) {
     return pair->raw() == key->raw();
@@ -214,7 +225,15 @@
 
   static Value ValueOf(Pair kv) { return kv; }
 
-  static inline intptr_t Hashcode(Key key) { return key->token_pos().value(); }
+  static inline intptr_t Hashcode(Key key) {
+    // We are using pointer hash for objects originating from Kernel because
+    // Fasta currently does not assign any position information to them.
+    if (key->kernel_field() != NULL) {
+      return SimplePointerHash(key->kernel_field());
+    } else {
+      return key->token_pos().value();
+    }
+  }
 
   static inline bool IsKeyEqual(Pair pair, Key key) {
     return pair->raw() == key->raw();
diff --git a/runtime/vm/scanner.h b/runtime/vm/scanner.h
index d26b989..f378b11 100644
--- a/runtime/vm/scanner.h
+++ b/runtime/vm/scanner.h
@@ -89,6 +89,9 @@
                              bool* is_positive,
                              const String** value);
 
+  static bool IsIdentStartChar(int32_t c);
+  static bool IsIdentChar(int32_t c);
+
  private:
   friend class ScanContext;
 
@@ -126,8 +129,6 @@
   static bool IsDecimalDigit(int32_t c);
   static bool IsNumberStart(int32_t);
   static bool IsHexDigit(int32_t c);
-  static bool IsIdentStartChar(int32_t c);
-  static bool IsIdentChar(int32_t c);
 
   // Skips up to next non-whitespace character.
   void ConsumeWhiteSpace();
diff --git a/runtime/vm/service.cc b/runtime/vm/service.cc
index 6b8afb7..855229f 100644
--- a/runtime/vm/service.cc
+++ b/runtime/vm/service.cc
@@ -40,6 +40,7 @@
 #include "vm/type_table.h"
 #include "vm/unicode.h"
 #include "vm/version.h"
+#include "vm/kernel_isolate.h"
 
 namespace dart {
 
@@ -61,6 +62,8 @@
             "Print a message when an isolate is paused but there is no "
             "debugger attached.");
 
+DECLARE_FLAG(bool, show_kernel_isolate);
+
 #ifndef PRODUCT
 // The name of this of this vm as reported by the VM service protocol.
 static char* vm_name = NULL;
@@ -3041,13 +3044,6 @@
   if (step_param != NULL) {
     step = EnumMapper(step_param, step_enum_names, step_enum_values);
   }
-#if defined(TARGET_ARCH_DBC)
-  if (step == Debugger::kStepRewind) {
-    js->PrintError(kCannotResume,
-                   "Rewind not yet implemented on this architecture");
-    return true;
-  }
-#endif
   intptr_t frame_index = 1;
   const char* frame_index_param = js->LookupParam("frameIndex");
   if (frame_index_param != NULL) {
@@ -3811,7 +3807,12 @@
   virtual ~ServiceIsolateVisitor() {}
 
   void VisitIsolate(Isolate* isolate) {
-    if (!IsVMInternalIsolate(isolate)) {
+    bool is_kernel_isolate = false;
+#ifndef DART_PRECOMPILED_RUNTIME
+    is_kernel_isolate =
+        KernelIsolate::IsKernelIsolate(isolate) && !FLAG_show_kernel_isolate;
+#endif
+    if (!IsVMInternalIsolate(isolate) && !is_kernel_isolate) {
       jsarr_->AddValue(isolate);
     }
   }
diff --git a/runtime/vm/simulator_dbc.cc b/runtime/vm/simulator_dbc.cc
index 86ca930..d16a5a3 100644
--- a/runtime/vm/simulator_dbc.cc
+++ b/runtime/vm/simulator_dbc.cc
@@ -1104,6 +1104,64 @@
 
 #define LOAD_CONSTANT(index) (pp->data()[(index)].raw_obj_)
 
+
+// Returns true if deoptimization succeeds.
+DART_FORCE_INLINE bool Simulator::Deoptimize(Thread* thread,
+                                             RawObjectPool** pp,
+                                             uint32_t** pc,
+                                             RawObject*** FP,
+                                             RawObject*** SP,
+                                             bool is_lazy) {
+  // Note: frame translation will take care of preserving result at the
+  // top of the stack. See CompilerDeoptInfo::CreateDeoptInfo.
+
+  // Make sure we preserve SP[0] when entering synthetic frame below.
+  (*SP)++;
+
+  // Leaf runtime function DeoptimizeCopyFrame expects a Dart frame.
+  // The code in this frame may not cause GC.
+  // DeoptimizeCopyFrame and DeoptimizeFillFrame are leaf runtime calls.
+  EnterSyntheticFrame(FP, SP, *pc - (is_lazy ? 1 : 0));
+  const intptr_t frame_size_in_bytes =
+      DLRT_DeoptimizeCopyFrame(reinterpret_cast<uword>(*FP), is_lazy ? 1 : 0);
+  LeaveSyntheticFrame(FP, SP);
+
+  *SP = *FP + (frame_size_in_bytes / kWordSize);
+  EnterSyntheticFrame(FP, SP, *pc - (is_lazy ? 1 : 0));
+  DLRT_DeoptimizeFillFrame(reinterpret_cast<uword>(*FP));
+
+  // We are now inside a valid frame.
+  {
+    *++(*SP) = 0;  // Space for the result: number of materialization args.
+    Exit(thread, *FP, *SP + 1, /*pc=*/0);
+    NativeArguments native_args(thread, 0, *SP, *SP);
+    if (!InvokeRuntime(thread, this, DRT_DeoptimizeMaterialize, native_args)) {
+      return false;
+    }
+  }
+  const intptr_t materialization_arg_count =
+      Smi::Value(RAW_CAST(Smi, *(*SP)--)) / kWordSize;
+
+  // Restore caller PC.
+  *pc = SavedCallerPC(*FP);
+  pc_ = reinterpret_cast<uword>(*pc);  // For the profiler.
+
+  // Check if it is a fake PC marking the entry frame.
+  ASSERT((reinterpret_cast<uword>(*pc) & 2) == 0);
+
+  // Restore SP, FP and PP.
+  // Unoptimized frame SP is one below FrameArguments(...) because
+  // FrameArguments(...) returns a pointer to the first argument.
+  *SP = FrameArguments(*FP, materialization_arg_count) - 1;
+  *FP = SavedCallerFP(*FP);
+
+  // Restore pp.
+  *pp = SimulatorHelpers::FrameCode(*FP)->ptr()->object_pool_->ptr();
+
+  return true;
+}
+
+
 RawObject* Simulator::Call(const Code& code,
                            const Array& arguments_descriptor,
                            const Array& arguments,
@@ -3573,50 +3631,25 @@
 
   {
     BYTECODE(Deopt, A_D);
-
-    // Note: frame translation will take care of preserving result at the
-    // top of the stack. See CompilerDeoptInfo::CreateDeoptInfo.
     const bool is_lazy = rD == 0;
-
-    // Make sure we preserve SP[0] when entering synthetic frame below.
-    SP++;
-
-    // Leaf runtime function DeoptimizeCopyFrame expects a Dart frame.
-    // The code in this frame may not cause GC.
-    // DeoptimizeCopyFrame and DeoptimizeFillFrame are leaf runtime calls.
-    EnterSyntheticFrame(&FP, &SP, pc - (is_lazy ? 1 : 0));
-    const intptr_t frame_size_in_bytes =
-        DLRT_DeoptimizeCopyFrame(reinterpret_cast<uword>(FP), is_lazy ? 1 : 0);
-    LeaveSyntheticFrame(&FP, &SP);
-
-    SP = FP + (frame_size_in_bytes / kWordSize);
-    EnterSyntheticFrame(&FP, &SP, pc - (is_lazy ? 1 : 0));
-    DLRT_DeoptimizeFillFrame(reinterpret_cast<uword>(FP));
-
-    // We are now inside a valid frame.
-    {
-      *++SP = 0;  // Space for the result: number of materialization args.
-      Exit(thread, FP, SP + 1, /*pc=*/0);
-      NativeArguments native_args(thread, 0, SP, SP);
-      INVOKE_RUNTIME(DRT_DeoptimizeMaterialize, native_args);
+    if (!Deoptimize(thread, &pp, &pc, &FP, &SP, is_lazy)) {
+      HANDLE_EXCEPTION;
     }
-    const intptr_t materialization_arg_count =
-        Smi::Value(RAW_CAST(Smi, *SP--)) / kWordSize;
+    DISPATCH();
+  }
 
-    // Restore caller PC.
-    pc = SavedCallerPC(FP);
-    pc_ = reinterpret_cast<uword>(pc);  // For the profiler.
-
-    // Check if it is a fake PC marking the entry frame.
-    ASSERT((reinterpret_cast<uword>(pc) & 2) == 0);
-
-    // Restore SP, FP and PP.
-    // Unoptimized frame SP is one below FrameArguments(...) because
-    // FrameArguments(...) returns a pointer to the first argument.
-    SP = FrameArguments(FP, materialization_arg_count) - 1;
-    FP = SavedCallerFP(FP);
-    pp = SimulatorHelpers::FrameCode(FP)->ptr()->object_pool_->ptr();
-
+  {
+    BYTECODE(DeoptRewind, 0);
+    pc = reinterpret_cast<uint32_t*>(thread->resume_pc());
+    if (!Deoptimize(thread, &pp, &pc, &FP, &SP, false /* eager */)) {
+      HANDLE_EXCEPTION;
+    }
+    {
+      Exit(thread, FP, SP + 1, pc);
+      NativeArguments args(thread, 0, NULL, NULL);
+      INVOKE_RUNTIME(DRT_RewindPostDeopt, args);
+    }
+    UNREACHABLE();  // DRT_RewindPostDeopt does not exit normally.
     DISPATCH();
   }
 
@@ -3699,7 +3732,7 @@
 
 void Simulator::JumpToFrame(uword pc, uword sp, uword fp, Thread* thread) {
   // Walk over all setjmp buffers (simulated --> C++ transitions)
-  // and try to find the setjmp associated with the simulated stack pointer.
+  // and try to find the setjmp associated with the simulated frame pointer.
   SimulatorSetjmpBuffer* buf = last_setjmp_buffer();
   while ((buf->link() != NULL) && (buf->link()->fp() > fp)) {
     buf = buf->link();
@@ -3728,17 +3761,6 @@
     special_[kExceptionSpecialIndex] = raw_exception;
     special_[kStackTraceSpecialIndex] = raw_stacktrace;
     pc_ = thread->resume_pc();
-  } else if (pc == StubCode::DeoptForRewind_entry()->EntryPoint()) {
-    // The DeoptForRewind stub is a placeholder.  We will eventually
-    // implement its behavior here.
-    //
-    // TODO(turnidge): Refactor the Deopt bytecode so that we can use
-    // the implementation here too.  The deopt pc is stored in
-    // Thread::resume_pc().  After invoking deoptimization, we usually
-    // call into Debugger::RewindPostDeopt(), but I need to figure out
-    // if that makes any sense (it would JumpToFrame during a
-    // JumpToFrame, which seems wrong).
-    UNIMPLEMENTED();
   } else {
     pc_ = pc;
   }
diff --git a/runtime/vm/simulator_dbc.h b/runtime/vm/simulator_dbc.h
index 076dedc..2e84f98 100644
--- a/runtime/vm/simulator_dbc.h
+++ b/runtime/vm/simulator_dbc.h
@@ -123,6 +123,13 @@
               RawObject*** FP,
               RawObject*** SP);
 
+  bool Deoptimize(Thread* thread,
+                  RawObjectPool** pp,
+                  uint32_t** pc,
+                  RawObject*** FP,
+                  RawObject*** SP,
+                  bool is_lazy);
+
   void InlineCacheMiss(int checked_args,
                        Thread* thread,
                        RawICData* icdata,
diff --git a/runtime/vm/stub_code_dbc.cc b/runtime/vm/stub_code_dbc.cc
index 545a70e..bf3783b 100644
--- a/runtime/vm/stub_code_dbc.cc
+++ b/runtime/vm/stub_code_dbc.cc
@@ -47,9 +47,8 @@
 }
 
 
-// Not executed, but used as a sentinel in Simulator::JumpToFrame.
 void StubCode::GenerateDeoptForRewindStub(Assembler* assembler) {
-  __ Trap();
+  __ DeoptRewind();
 }
 
 
diff --git a/runtime/vm/unit_test.cc b/runtime/vm/unit_test.cc
index 6a9c5f5..b844067 100644
--- a/runtime/vm/unit_test.cc
+++ b/runtime/vm/unit_test.cc
@@ -445,7 +445,6 @@
   ParsedFunction* parsed_function =
       new ParsedFunction(Thread::Current(), function_);
   parsed_function->SetNodeSequence(node_sequence_);
-  parsed_function->set_instantiator(NULL);
   parsed_function->set_default_parameter_values(default_parameter_values_);
   node_sequence_->scope()->AddVariable(parsed_function->current_context_var());
   parsed_function->EnsureExpressionTemp();
diff --git a/sdk/lib/_internal/js_runtime/lib/core_patch.dart b/sdk/lib/_internal/js_runtime/lib/core_patch.dart
index e5e76bf..45466e3 100644
--- a/sdk/lib/_internal/js_runtime/lib/core_patch.dart
+++ b/sdk/lib/_internal/js_runtime/lib/core_patch.dart
@@ -234,7 +234,8 @@
   @patch
   DateTime.fromMillisecondsSinceEpoch(int millisecondsSinceEpoch,
                                       {bool isUtc: false})
-      : this._withValue(millisecondsSinceEpoch, isUtc: isUtc);
+      // `0 + millisecondsSinceEpoch` forces the inferred result to be non-null.
+      : this._withValue(0 + millisecondsSinceEpoch, isUtc: isUtc);
 
   @patch
   DateTime.fromMicrosecondsSinceEpoch(int microsecondsSinceEpoch,
@@ -318,7 +319,7 @@
   int get millisecondsSinceEpoch => _value;
 
   @patch
-  int get microsecondsSinceEpoch => _value * 1000;
+  int get microsecondsSinceEpoch => 1000 * _value;
 
   @patch
   int get year => Primitives.getYear(this);
diff --git a/sdk/lib/_internal/js_runtime/lib/js_helper.dart b/sdk/lib/_internal/js_runtime/lib/js_helper.dart
index 6e1548d..cb48d2d 100644
--- a/sdk/lib/_internal/js_runtime/lib/js_helper.dart
+++ b/sdk/lib/_internal/js_runtime/lib/js_helper.dart
@@ -2456,9 +2456,11 @@
   return function;
 }
 
-/**
- * Super class for Dart closures.
- */
+/// Superclass for Dart closures.
+///
+/// All static, tear-off, function declaration and function expression closures
+/// extend this class, but classes that implement Function via a `call` method
+/// do not.
 abstract class Closure implements Function {
   // TODO(ahe): These constants must be in sync with
   // reflection_data_parser.dart.
@@ -2891,6 +2893,8 @@
 
   String toString() {
     String name = Primitives.objectTypeName(this);
+    // Mirrors puts a space in front of some names, so remove it.
+    name = JS('String', '#.trim()', name);
     return "Closure '$name'";
   }
 }
diff --git a/sdk/lib/_internal/js_runtime/lib/js_mirrors.dart b/sdk/lib/_internal/js_runtime/lib/js_mirrors.dart
index 36924db..6fd81c0 100644
--- a/sdk/lib/_internal/js_runtime/lib/js_mirrors.dart
+++ b/sdk/lib/_internal/js_runtime/lib/js_mirrors.dart
@@ -45,6 +45,7 @@
         UnimplementedNoSuchMethodError,
         createRuntimeType,
         createUnmangledInvocationMirror,
+        extractFunctionTypeObjectFrom,
         getMangledTypeName,
         getMetadata,
         getType,
@@ -580,7 +581,17 @@
 final JsMirrorSystem currentJsMirrorSystem = new JsMirrorSystem();
 
 InstanceMirror reflect(Object reflectee) {
-  if (reflectee is Closure) {
+  // TODO(sra): This test should be a quick test for something like 'is
+  // Function', but only for classes that implement `Function` via a `call`
+  // method. The JS form of the test could be something like
+  //
+  //     if (reflectee instanceof P.Object && reflectee.$isFunction) ...
+  //
+  // We don't currently have a way get that generated. We should ensure type
+  // analysis can express 'not Interceptor' and recognize a negative type test
+  // against Interceptor can be optimized to the above test. For now we have to
+  // accept the following is compiled to an interceptor-based type check.
+  if (reflectee is Function) {
     return new JsClosureMirror(reflectee);
   } else {
     return new JsInstanceMirror(reflectee);
@@ -2286,6 +2297,21 @@
         Function.apply(reflectee, positionalArguments, namedArguments));
   }
 
+  TypeMirror get type {
+    // Classes that implement [call] do not subclass [Closure], but only
+    // implement [Function], so are rejected by this test.
+    if (reflectee is Closure) {
+      var functionRti = extractFunctionTypeObjectFrom(reflectee);
+      if (functionRti != null) {
+        return new JsFunctionTypeMirror(functionRti, null);
+      }
+    }
+    // Use the JsInstanceMirror method to return the JsClassMirror.
+    // TODO(sra): Should there be a TypeMirror that is both a ClassMirror and
+    // FunctionTypeMirror?
+    return super.type;
+  }
+
   String toString() => "ClosureMirror on '${Error.safeToString(reflectee)}'";
 
   // TODO(ahe): Implement this method.
@@ -2635,6 +2661,7 @@
   String _cachedToString;
   TypeMirror _cachedReturnType;
   UnmodifiableListView<ParameterMirror> _cachedParameters;
+  Type _cachedReflectedType;
   DeclarationMirror owner;
 
   JsFunctionTypeMirror(this._typeData, this.owner);
@@ -2730,6 +2757,10 @@
         new UnmodifiableListView<ParameterMirror>(result);
   }
 
+  bool get hasReflectedType => true;
+  Type get reflectedType => _cachedReflectedType
+      ??= createRuntimeType(runtimeTypeToString(_typeData));
+
   String _unmangleIfPreserved(String mangled) {
     String result = unmangleGlobalNameIfPreservedAnyways(mangled);
     if (result != null) return result;
diff --git a/sdk/lib/_internal/js_runtime/lib/js_rti.dart b/sdk/lib/_internal/js_runtime/lib/js_rti.dart
index 8ee404e..c697b10 100644
--- a/sdk/lib/_internal/js_runtime/lib/js_rti.dart
+++ b/sdk/lib/_internal/js_runtime/lib/js_rti.dart
@@ -290,10 +290,14 @@
  * In minified mode does *not* use unminified identifiers (even when present).
  */
 String getRuntimeTypeString(var object) {
-  // Check for function type first, since non-tearoff closures look like classes
-  // due to closure conversion.
-  var functionRti = extractFunctionTypeObjectFrom(object);
-  if (functionRti != null) return runtimeTypeToString(functionRti);
+  if (object is Closure) {
+    // This excludes classes that implement Function via a `call` method, but
+    // includes classes generated to represent closures in closure conversion.
+    var functionRti = extractFunctionTypeObjectFrom(object);
+    if (functionRti != null) {
+      return runtimeTypeToString(functionRti);
+    }
+  }
   String className = getClassName(object);
   if (object == null) return className;
   String rtiName = JS_GET_NAME(JsGetName.RTI_NAME);
diff --git a/sdk/lib/core/duration.dart b/sdk/lib/core/duration.dart
index f2dd01b..bc1364f 100644
--- a/sdk/lib/core/duration.dart
+++ b/sdk/lib/core/duration.dart
@@ -295,5 +295,6 @@
    * The returned `Duration` has the same length as this one, but will have the
    * opposite sign of this one.
    */
-  Duration operator -() => new Duration._microseconds(-_duration);
+  // Using subtraction helps dart2js avoid negative zeros.
+  Duration operator -() => new Duration._microseconds(0 - _duration);
 }
diff --git a/sdk/lib/vmservice/devfs.dart b/sdk/lib/vmservice/devfs.dart
index 7f940b9..0cdc57a 100644
--- a/sdk/lib/vmservice/devfs.dart
+++ b/sdk/lib/vmservice/devfs.dart
@@ -42,6 +42,10 @@
       return null;
     }
 
+    return resolve(pathUri);
+  }
+
+  Uri resolve(Uri pathUri) {
     try {
       // Make sure that this pathUri can be converted to a file path.
       pathUri.toFilePath();
@@ -123,6 +127,7 @@
 
   Future<String> handlePutStream(Object fsName,
                                  Object path,
+                                 Uri fsUri,
                                  Stream<List<int>> bytes) async {
     // A dummy Message for error message construction.
     Message message = new Message.forMethod('_writeDevFSFile');
@@ -140,15 +145,23 @@
     if (fs == null) {
       return _encodeFileSystemDoesNotExistError(message, fsName);
     }
-    if (path == null) {
-      return encodeMissingParamError(message, 'path');
-    }
-    if (path is! String) {
-      return encodeInvalidParamError(message, 'path');
-    }
-    Uri uri = fs.resolvePath(path);
+    Uri uri = fsUri;
     if (uri == null) {
-      return encodeInvalidParamError(message, 'path');
+      if (path == null) {
+        return encodeMissingParamError(message, 'path');
+      }
+      if (path is! String) {
+        return encodeInvalidParamError(message, 'path');
+      }
+      uri = fs.resolvePath(path);
+      if (uri == null) {
+        return encodeInvalidParamError(message, 'path');
+      }
+    } else {
+      uri = fs.resolve(uri);
+      if (uri == null) {
+        return encodeInvalidParamError(message, 'uri');
+      }
     }
     await writeStreamFile(uri, bytes);
     return encodeSuccess(message);
@@ -219,18 +232,34 @@
     if (fs == null) {
       return _encodeFileSystemDoesNotExistError(message, fsName);
     }
-    var path = message.params['path'];
-    if (path == null) {
-      return encodeMissingParamError(message, 'path');
+    Uri uri;
+    if (message.params['uri'] != null) {
+      try {
+        var uriParam = message.params['uri'];
+        if (uriParam is! String) {
+          return encodeInvalidParamError(message, 'uri');
+        }
+        Uri parsedUri = Uri.parse(uriParam);
+        uri = fs.resolve(parsedUri);
+        if (uri == null) {
+          return encodeInvalidParamError(message, 'uri');
+        }
+      } catch (e) {
+        return encodeInvalidParamError(message, 'uri');
+      }
+    } else {
+      var path = message.params['path'];
+      if (path == null) {
+        return encodeMissingParamError(message, 'path');
+      }
+      if (path is! String) {
+        return encodeInvalidParamError(message, 'path');
+      }
+      uri = fs.resolvePath(path);
+      if (uri == null) {
+        return encodeInvalidParamError(message, 'path');
+      }
     }
-    if (path is! String) {
-      return encodeInvalidParamError(message, 'path');
-    }
-    Uri uri = fs.resolvePath(path);
-    if (uri == null) {
-      return encodeInvalidParamError(message, 'path');
-    }
-
     try {
       List<int> bytes = await readFile(uri);
       var result = {
@@ -261,16 +290,33 @@
     if (fs == null) {
       return _encodeFileSystemDoesNotExistError(message, fsName);
     }
-    var path = message.params['path'];
-    if (path == null) {
-      return encodeMissingParamError(message, 'path');
-    }
-    if (path is! String) {
-      return encodeInvalidParamError(message, 'path');
-    }
-    Uri uri = fs.resolvePath(path);
-    if (uri == null) {
-      return encodeInvalidParamError(message, 'path');
+    Uri uri;
+    if (message.params['uri'] != null) {
+      try {
+        var uriParam = message.params['uri'];
+        if (uriParam is! String) {
+          return encodeInvalidParamError(message, 'uri');
+        }
+        Uri parsedUri = Uri.parse(uriParam);
+        uri = fs.resolve(parsedUri);
+        if (uri == null) {
+          return encodeInvalidParamError(message, 'uri');
+        }
+      } catch (e) {
+        return encodeInvalidParamError(message, 'uri');
+      }
+    } else {
+      var path = message.params['path'];
+      if (path == null) {
+        return encodeMissingParamError(message, 'path');
+      }
+      if (path is! String) {
+        return encodeInvalidParamError(message, 'path');
+      }
+      uri = fs.resolvePath(path);
+      if (uri == null) {
+        return encodeInvalidParamError(message, 'path');
+      }
     }
     var fileContents = message.params['fileContents'];
     if (fileContents == null) {
diff --git a/tests/co19/co19-analyzer2.status b/tests/co19/co19-analyzer2.status
index 58406e6..b6aac22 100644
--- a/tests/co19/co19-analyzer2.status
+++ b/tests/co19/co19-analyzer2.status
@@ -26,22 +26,6 @@
 Language/Expressions/Function_Invocation/Unqualified_Invocation/instance_context_invocation_t04: MissingCompileTimeError # Please triage this failure.
 Language/Expressions/Function_Invocation/Unqualified_Invocation/invocation_t17: MissingCompileTimeError # Please triage this failure
 Language/Expressions/Function_Invocation/Unqualified_Invocation/invocation_t18: MissingCompileTimeError # Please triage this failure
-Language/Expressions/Identifier_Reference/built_in_identifier_t53: MissingCompileTimeError # Issue 25733
-Language/Expressions/Identifier_Reference/built_in_identifier_t54: MissingCompileTimeError # Issue 25733
-Language/Expressions/Identifier_Reference/built_in_identifier_t55: MissingCompileTimeError # Issue 25733
-Language/Expressions/Identifier_Reference/built_in_identifier_t56: MissingCompileTimeError # Issue 25733
-Language/Expressions/Identifier_Reference/built_in_identifier_t57: MissingCompileTimeError # Issue 25733
-Language/Expressions/Identifier_Reference/built_in_identifier_t58: MissingCompileTimeError # Issue 25733
-Language/Expressions/Identifier_Reference/built_in_identifier_t59: MissingCompileTimeError # Issue 25733
-Language/Expressions/Identifier_Reference/built_in_identifier_t60: MissingCompileTimeError # Issue 25733
-Language/Expressions/Identifier_Reference/built_in_identifier_t61: MissingCompileTimeError # Issue 25733
-Language/Expressions/Identifier_Reference/built_in_identifier_t62: MissingCompileTimeError # Issue 25733
-Language/Expressions/Identifier_Reference/built_in_identifier_t63: MissingCompileTimeError # Issue 25733
-Language/Expressions/Identifier_Reference/built_in_identifier_t64: MissingCompileTimeError # Issue 25733
-Language/Expressions/Identifier_Reference/built_in_identifier_t65: MissingCompileTimeError # Issue 25733
-Language/Expressions/Identifier_Reference/built_in_identifier_t66: MissingCompileTimeError # Issue 25733
-Language/Expressions/Identifier_Reference/built_in_identifier_t67: MissingCompileTimeError # Issue 25733
-Language/Expressions/Identifier_Reference/built_in_identifier_t68: MissingCompileTimeError # Issue 25733
 Language/Expressions/Identifier_Reference/built_in_not_dynamic_t17: MissingCompileTimeError # Please triage this failure.
 Language/Expressions/Identifier_Reference/built_in_not_dynamic_t18: MissingCompileTimeError # Please triage this failure.
 Language/Expressions/Identifier_Reference/built_in_not_dynamic_t19: MissingCompileTimeError # Please triage this failure.
diff --git a/tests/co19/co19-dart2js.status b/tests/co19/co19-dart2js.status
index fa74a1d..60aedb7 100644
--- a/tests/co19/co19-dart2js.status
+++ b/tests/co19/co19-dart2js.status
@@ -2749,7 +2749,9 @@
 LayoutTests/fast/canvas/canvas-strokeText-zeroSizeGradient_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/canvas-toDataURL-crash_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/draw-custom-focus-ring_t01: RuntimeError # Please triage this failure
+LayoutTests/fast/canvas/drawImage-with-bad-canvas_t01: RuntimeError # Issue 28983
 LayoutTests/fast/canvas/getPutImageDataPairTest_t01: RuntimeError # Please triage this failure
+LayoutTests/fast/canvas/gradient-addColorStop-with-invalid-color_t01: RuntimeError # Issue 28983
 LayoutTests/fast/canvas/rgba-parsing_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/WebGLContextEvent_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/bad-arguments-test_t01: RuntimeError # Please triage this failure
@@ -2763,8 +2765,8 @@
 LayoutTests/fast/canvas/webgl/gl-enum-tests_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/gl-get-calls_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/gl-object-get-calls_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/object-deletion-behaviour_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/null-object-behaviour_t01: RuntimeError # Please triage this failure
+LayoutTests/fast/canvas/webgl/object-deletion-behaviour_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/renderer-and-vendor-strings_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/tex-image-and-sub-image-2d-with-array-buffer-view_t01: Skip # Times out.
 LayoutTests/fast/canvas/webgl/tex-image-and-sub-image-2d-with-image-rgb565_t01: RuntimeError # Please triage this failure
@@ -2784,10 +2786,8 @@
 LayoutTests/fast/css-generated-content/pseudo-element-events_t01: Skip # Times out. Please triage this failure
 LayoutTests/fast/css-generated-content/pseudo-transition-event_t01: Skip # Times out. Please triage this failure
 LayoutTests/fast/css-generated-content/pseudo-transition_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/css-grid-layout/auto-content-resolution-rows_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css-grid-layout/breadth-size-resolution-grid_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css-grid-layout/calc-resolution-grid-item_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/css-grid-layout/display-grid-set-get_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css-grid-layout/flex-and-minmax-content-resolution-rows_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css-grid-layout/flex-content-resolution-columns_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css-grid-layout/flex-content-resolution-rows_t01: RuntimeError # Please triage this failure
@@ -2814,12 +2814,10 @@
 LayoutTests/fast/css-grid-layout/grid-item-margin-resolution_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css-grid-layout/grid-item-order-auto-flow-resolution_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css-grid-layout/grid-template-areas-get-set_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/css-grid-layout/implicit-rows-auto-resolution_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css-grid-layout/justify-self-cell_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css-grid-layout/minmax-fixed-logical-height-only_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css-grid-layout/minmax-fixed-logical-width-only_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css-grid-layout/percent-grid-item-in-percent-grid-track-in-percent-grid_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/css-grid-layout/percent-grid-item-in-percent-grid-track-update_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css-grid-layout/percent-grid-item-in-percent-grid-track_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css-grid-layout/percent-padding-margin-resolution-grid-item-update_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css-grid-layout/percent-padding-margin-resolution-grid-item_t01: RuntimeError # Please triage this failure
@@ -2991,7 +2989,6 @@
 LayoutTests/fast/dom/Document/CaretRangeFromPoint/hittest-relative-to-viewport_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/Document/CaretRangeFromPoint/replace-element_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/Document/createElement-valid-names_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/dom/Document/createElementNS-namespace-err_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/Document/document-title-get_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/Element/attribute-uppercase_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/Element/fixed-position-offset-parent_t01: RuntimeError # Please triage this failure
@@ -3000,7 +2997,6 @@
 LayoutTests/fast/dom/Element/id-in-insert-hr_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/Element/offsetTop-table-cell_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/Element/scrollWidth_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/dom/Element/setAttributeNS-namespace-err_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/HTMLAnchorElement/remove-href-from-focused-anchor_t01: Skip # Times out. Please triage this failure
 LayoutTests/fast/dom/HTMLAnchorElement/set-href-attribute-hash_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/HTMLAnchorElement/set-href-attribute-host_t01: RuntimeError # Please triage this failure
@@ -3151,7 +3147,6 @@
 LayoutTests/fast/dom/click-method-on-html-element_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/client-width-height-quirks_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/containerNode_t01: Skip # Times out. Please triage this failure
-LayoutTests/fast/dom/createElementNS-namespace-errors_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/css-delete-doc_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/css-rule-functions_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/css-selectorText_t01: RuntimeError # Please triage this failure
@@ -3210,6 +3205,7 @@
 LayoutTests/fast/dom/set-innerHTML_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/shadow/access-document-of-detached-stylesheetlist-crash_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/shadow/base-in-shadow-tree_t01: RuntimeError # Please triage this failure
+LayoutTests/fast/dom/shadow/content-element-api_t01: RuntimeError # Issue 28983
 LayoutTests/fast/dom/shadow/content-element-crash_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/shadow/content-element-includer_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/shadow/content-element-outside-shadow-style_t01: RuntimeError # Please triage this failure
@@ -3224,6 +3220,7 @@
 LayoutTests/fast/dom/shadow/distribution-for-event-path_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/shadow/distribution-update-recalcs-style_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/shadow/elementfrompoint_t01: RuntimeError # Please triage this failure
+LayoutTests/fast/dom/shadow/elements-in-frameless-document_t01: RuntimeError # Issue 28983
 LayoutTests/fast/dom/shadow/event-path-not-in-document_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/shadow/event-path_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/shadow/form-in-shadow_t01: RuntimeError # Please triage this failure
@@ -3256,6 +3253,7 @@
 LayoutTests/fast/dom/shadow/shadow-content-crash_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/shadow/shadow-disable_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/shadow/shadow-element-inactive_t01: RuntimeError # Please triage this failure
+LayoutTests/fast/dom/shadow/shadow-element_t01: RuntimeError # Issue 28983
 LayoutTests/fast/dom/shadow/shadow-hierarchy-exception_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/shadow/shadow-removechild-and-blur-event_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/shadow/shadow-root-append_t01: RuntimeError # Please triage this failure
@@ -3304,6 +3302,7 @@
 LayoutTests/fast/events/event-trace_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/events/fire-scroll-event_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/events/form-onchange_t01: RuntimeError # Please triage this failure
+LayoutTests/fast/events/init-message-event_t01: RuntimeError # Issue 28983
 LayoutTests/fast/events/initkeyboardevent-crash_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/events/input-focus-no-duplicate-events_t01: Pass, RuntimeError # Please triage this failure
 LayoutTests/fast/events/invalid-001_t01: Pass, RuntimeError # Passes on ff 35. Please triage this failure
@@ -3321,6 +3320,7 @@
 LayoutTests/fast/events/selectstart-on-selectall_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/events/selectstart-prevent-selectall_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/events/tabindex-removal-from-focused-element_t01: Pass, RuntimeError # Please triage this failure
+LayoutTests/fast/eventsource/eventsource-attribute-listeners_t01: RuntimeError # Issue 28983
 LayoutTests/fast/eventsource/eventsource-constructor_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/exclusions/parsing/parsing-wrap-flow_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/exclusions/parsing/parsing-wrap-through_t01: RuntimeError # Please triage this failure
@@ -3368,7 +3368,6 @@
 LayoutTests/fast/filesystem/simple-required-arguments-getfile_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/filesystem/simple-temporary_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/filesystem/snapshot-file-with-gc_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/flexbox/box-orient-button_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/flexbox/box-size-integer-overflow_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/forms/11423_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/forms/8250_t01: RuntimeError # Please triage this failure
@@ -3527,15 +3526,11 @@
 LayoutTests/fast/media/mq-append-delete_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/mediastream/RTCPeerConnection-AddRemoveStream_t01: Skip # Issue 23475
 LayoutTests/fast/mediastream/RTCPeerConnection_t01: Skip # Issue 23475
-LayoutTests/fast/multicol/balance-short-trailing-empty-block_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/multicol/balance-trailing-border_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/multicol/balance-trailing-border_t02: RuntimeError # Please triage this failure
 LayoutTests/fast/multicol/balance-unbreakable_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/multicol/break-after-always-bottom-margin_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/multicol/break-properties_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/multicol/column-width-zero_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/multicol/cssom-view_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/multicol/fixed-column-percent-logical-height-orthogonal-writing-mode_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/multicol/flipped-blocks-hit-test_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/multicol/float-truncation_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/multicol/gap-non-negative_t01: RuntimeError # Please triage this failure
@@ -3551,7 +3546,6 @@
 LayoutTests/fast/multicol/inline-getclientrects_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/multicol/newmulticol/balance-images_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/multicol/newmulticol/balance-maxheight_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/multicol/newmulticol/balance-maxheight_t02: RuntimeError # Please triage this failure
 LayoutTests/fast/multicol/newmulticol/balance_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/multicol/newmulticol/balance_t02: RuntimeError # Please triage this failure
 LayoutTests/fast/multicol/newmulticol/balance_t04: RuntimeError # Please triage this failure
@@ -3569,7 +3563,6 @@
 LayoutTests/fast/multicol/vertical-rl/float-truncation_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/multicol/vertical-rl/gap-non-negative_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/multicol/widows_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/multicol/widows_t02: RuntimeError # Please triage this failure
 LayoutTests/fast/multicol/zeroColumnCount_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/overflow/height-during-simplified-layout_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/overflow/overflow-rtl-vertical-origin_t01: RuntimeError # Please triage this failure
@@ -3843,7 +3836,7 @@
 WebPlatformTest/dom/nodes/DOMImplementation-createDocument_t01: RuntimeError # Please triage this failure
 WebPlatformTest/dom/nodes/DOMImplementation-hasFeature_t01: RuntimeError # Please triage this failure
 WebPlatformTest/dom/nodes/Document-adoptNode_t01: RuntimeError # Please triage this failure
-WebPlatformTest/dom/nodes/Document-createElementNS_t01: RuntimeError # Please triage this failure
+WebPlatformTest/dom/nodes/Document-createElementNS_t01: Pass, RuntimeError # Issue 28983
 WebPlatformTest/dom/nodes/Document-getElementsByTagName_t01: RuntimeError # Please triage this failure
 WebPlatformTest/dom/nodes/Element-childElementCount_t01: RuntimeError # Please triage this failure
 WebPlatformTest/dom/nodes/Node-appendChild_t01: RuntimeError # Please triage this failure
diff --git a/tests/co19/co19-kernel.status b/tests/co19/co19-kernel.status
index 51f15c2..23ab005 100644
--- a/tests/co19/co19-kernel.status
+++ b/tests/co19/co19-kernel.status
@@ -685,6 +685,7 @@
 Language/Statements/Local_Variable_Declaration/syntax_t06: CompileTimeError
 Language/Statements/Local_Variable_Declaration/syntax_t18: CompileTimeError
 Language/Statements/Local_Variable_Declaration/syntax_t19: CompileTimeError
+LibTest/isolate/Isolate/spawnUri_A01_t03: Pass, Timeout
 
 # dartk: JIT failures (debug)
 [ $compiler == dartk && $mode == debug ]
diff --git a/tests/compiler/dart2js/scanner_test.dart b/tests/compiler/dart2js/scanner_test.dart
index 82f4d5e..b8cb10f 100644
--- a/tests/compiler/dart2js/scanner_test.dart
+++ b/tests/compiler/dart2js/scanner_test.dart
@@ -184,7 +184,7 @@
   // Regression test for issue 1761.
   // "#!"
   token = scan([0x23, 0x21]);
-  Expect.equals(token.info, EOF_INFO); // Treated as a comment.
+  Expect.equals(token.info, SCRIPT_INFO); // Treated as a comment.
 
   // Regression test for issue 1761.
   // "#! Hello, World!"
@@ -206,5 +206,5 @@
     0x64,
     0x21
   ]);
-  Expect.equals(token.info, EOF_INFO); // Treated as a comment.
+  Expect.equals(token.info, SCRIPT_INFO); // Treated as a comment.
 }
diff --git a/tests/corelib/corelib.status b/tests/corelib/corelib.status
index 9038d6b..a904409 100644
--- a/tests/corelib/corelib.status
+++ b/tests/corelib/corelib.status
@@ -125,6 +125,14 @@
 string_case_test/01: Fail, OK  # Bug in Firefox.
 list_test/none: Fail # Issue 28014
 list_test/01: Fail # Issue 28014
+int_parse_radix_test/none: Pass, RuntimeError # Issue 28983
+string_trim2_test: Pass, RuntimeError # Issue 28983
+string_trimlr_test/01: Pass, RuntimeError # Issue 28983
+string_trimlr_test/none: Pass, RuntimeError # Issue 28983
+double_parse_test/03: Pass, RuntimeError # Issue 28983
+double_parse_test/none: Pass, RuntimeError # Issue 28983
+num_parse_test/01: Pass, RuntimeError # Issue 28983
+num_parse_test/none: Pass, RuntimeError # Issue 28983
 
 [ $compiler == dart2js && $runtime == dartium ]
 string_case_test/02: Fail, OK  # Bug in dartium version of V8.
diff --git a/tests/html/html.status b/tests/html/html.status
index 0735b89..b690f33 100644
--- a/tests/html/html.status
+++ b/tests/html/html.status
@@ -321,8 +321,6 @@
 indexeddb_2_test: RuntimeError # Issue 21433
 indexeddb_4_test: RuntimeError # Issue 21433
 indexeddb_5_test: RuntimeError # Issue 21433
-
-
 indexeddb_3_test: Skip # Times out 1 out of 10.
 
 [  $compiler == dart2js && $runtime == ff ]
@@ -332,6 +330,10 @@
 webgl_1_test: Pass, Fail   # Issue 8219
 text_event_test: Fail # Issue 17893
 element_animate_test/timing_dict: RuntimeError # Issue 26730
+messageevent_test: Pass, RuntimeError # Issue 28983
+serialized_script_value_test: Pass, RuntimeError # Issue 28983
+element_types_test/supported_content: Pass, RuntimeError # Issue 28983
+element_types_test/supported_shadow: Pass, RuntimeError # Issue 28983
 
 # Firefox Feature support statuses-
 # All changes should be accompanied by platform support annotation changes.
diff --git a/tests/language/language_kernel.status b/tests/language/language_kernel.status
index c98b85d..0cfe0c5 100644
--- a/tests/language/language_kernel.status
+++ b/tests/language/language_kernel.status
@@ -388,8 +388,6 @@
 generic_field_mixin4_test: RuntimeError
 generic_field_mixin5_test: RuntimeError
 generic_field_mixin_test: RuntimeError
-generic_function_typedef2_test: DartkCrash # Issue 27969
-generic_function_typedef_test: DartkCrash # Issue 27969
 generic_local_functions_test: DartkCrash
 generic_metadata_test/02: MissingCompileTimeError
 generic_metadata_test/03: MissingCompileTimeError
@@ -474,7 +472,6 @@
 mixin_illegal_cycles_test/06: MissingCompileTimeError
 mixin_illegal_object_test/01: MissingCompileTimeError
 mixin_illegal_object_test/02: MissingCompileTimeError
-mixin_illegal_syntax_test/00: DartkCrash
 mixin_invalid_inheritance2_test/03: DartkCrash
 mixin_issue10216_2_test: RuntimeError
 mixin_mixin2_test: RuntimeError
@@ -797,6 +794,7 @@
 unsupported_operators_test/02: MissingCompileTimeError
 unsupported_operators_test/03: MissingCompileTimeError
 unsupported_operators_test/04: MissingCompileTimeError
+vm/closure_memory_retention_test: Skip  # Hits OOM
 
 # dartk: precompilation failures (debug)
 [ $compiler == dartkp && $mode == debug ]
diff --git a/tests/language_strong/bad_raw_string_negative_test.dart b/tests/language_strong/bad_raw_string_negative_test.dart
deleted file mode 100644
index 89b4659..0000000
--- a/tests/language_strong/bad_raw_string_negative_test.dart
+++ /dev/null
@@ -1,9 +0,0 @@
-// Copyright (c) 2014, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-main() {
-  // Raw String may not contain newline (may not be multi-line).
-  print(r'
-');
-}
diff --git a/tests/language_strong/bad_raw_string_test.dart b/tests/language_strong/bad_raw_string_test.dart
new file mode 100644
index 0000000..8c3890d
--- /dev/null
+++ b/tests/language_strong/bad_raw_string_test.dart
@@ -0,0 +1,23 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+main() {
+  // Raw String may not contain newline (may not be multi-line).
+  String x = ''
+    r'  /// 01: compile-time error
+'       /// 01: continued
+    r"  /// 02: compile-time error
+"       /// 02: continued
+    // Test that a raw string containing just one character, a \n char, fails.
+    // Enclose the test string in a bigger multiline string, except in case 03:
+    '''  /// 03: compile-time error
+    """
+    '''  /// 03: continued
+    r'
+'
+    '''  /// 03: continued
+    """
+    '''  /// 03: continued
+  ;
+}
diff --git a/tests/language_strong/language_strong.status b/tests/language_strong/language_strong.status
index dadc4a0..6d6c8df 100644
--- a/tests/language_strong/language_strong.status
+++ b/tests/language_strong/language_strong.status
@@ -7,7 +7,7 @@
 *: SkipByDesign
 
 # Skip tests that are not yet strong-mode clean.
-[ $strong == true ]
+[ $strong ]
 abstract_exact_selector_test: Skip
 abstract_factory_constructor_test: Skip
 abstract_getter_test: Skip
@@ -680,3 +680,49 @@
 variable_declaration_metadata_test: Skip
 void_type_test: Skip
 wrong_number_type_arguments_test: Skip
+
+[ $compiler == dart2analyzer && $strong ]
+async_await_test/02: StaticWarning # Issue 28823
+async_await_test/03: StaticWarning # Issue 28823
+async_await_test/none: StaticWarning # Issue 28823
+async_star_test/01: StaticWarning # Issue 28823
+async_star_test/02: StaticWarning # Issue 28823
+async_star_test/03: StaticWarning # Issue 28823
+async_star_test/04: StaticWarning # Issue 28823
+async_star_test/05: StaticWarning # Issue 28823
+async_star_test/none: StaticWarning # Issue 28823
+bit_operations_test/01: MissingStaticWarning # Issue 28823
+bit_operations_test/02: MissingStaticWarning # Issue 28823
+bit_operations_test/03: MissingStaticWarning # Issue 28823
+bit_operations_test/04: MissingStaticWarning # Issue 28823
+closure_side_effect_test: StaticWarning # Issue 28823
+constant_type_literal_test/01: MissingCompileTimeError # Issue 28823
+deferred_constraints_type_annotation_test/as_operation: CompileTimeError # Issue 28823
+deferred_constraints_type_annotation_test/catch_check: CompileTimeError # Issue 28823
+deferred_constraints_type_annotation_test/is_check: CompileTimeError # Issue 28823
+deferred_constraints_type_annotation_test/new_before_load: CompileTimeError # Issue 28823
+deferred_constraints_type_annotation_test/new_generic2: CompileTimeError # Issue 28823
+deferred_constraints_type_annotation_test/new_generic3: CompileTimeError # Issue 28823
+deferred_constraints_type_annotation_test/type_annotation1: CompileTimeError # Issue 28823
+deferred_constraints_type_annotation_test/type_annotation_generic1: CompileTimeError # Issue 28823
+deferred_constraints_type_annotation_test/type_annotation_generic2: CompileTimeError # Issue 28823
+deferred_constraints_type_annotation_test/type_annotation_generic3: CompileTimeError # Issue 28823
+deferred_constraints_type_annotation_test/type_annotation_generic4: CompileTimeError # Issue 28823
+deferred_constraints_type_annotation_test/type_annotation_null: CompileTimeError # Issue 28823
+deferred_constraints_type_annotation_test/type_annotation_top_level: CompileTimeError # Issue 28823
+field3a_negative_test: StaticWarning # Issue 28823
+interface_inherit_field_test: StaticWarning # Issue 28823
+internal_library_test/02: MissingStaticWarning # Issue 28823
+main_not_a_function_test/01: MissingStaticWarning # Issue 28823
+main_test/03: MissingStaticWarning # Issue 28823
+many_named_arguments_test: StaticWarning # Issue 28823
+no_main_test/01: MissingStaticWarning # Issue 28823
+regress_23089_test: CompileTimeError # Issue 28823
+reify_typevar_static_test/00: MissingCompileTimeError # Issue 28823
+super_setter_test: StaticWarning # Issue 28823
+top_level_non_prefixed_library_test: CompileTimeError # Issue 28823
+try_catch4_test: StaticWarning # Issue 28823
+try_catch5_test: StaticWarning # Issue 28823
+
+[ $compiler == dart2analyzer && $system != windows ]
+bad_raw_string_test/03: MissingCompileTimeError # Issue 28664
diff --git a/tests/lib/lib.status b/tests/lib/lib.status
index bf7f097..3122609 100644
--- a/tests/lib/lib.status
+++ b/tests/lib/lib.status
@@ -27,7 +27,6 @@
 mirrors/enum_test: RuntimeError # Issue 6490
 mirrors/fake_function_with_call_test: RuntimeError # Issue 11612
 mirrors/fake_function_without_call_test: RuntimeError # Issue 11612
-mirrors/function_type_mirror_test: RuntimeError # Issue 12166
 mirrors/generic_f_bounded_mixin_application_test: RuntimeError # Issue 12087
 mirrors/generic_function_typedef_test: RuntimeError # Issue 12333
 mirrors/generic_interface_test: RuntimeError # Issue 12087
@@ -238,6 +237,9 @@
 convert/streamed_conversion_utf8_decode_test: Pass, Slow  # Issue 12029
 mirrors/mirrors_reader_test: Timeout, Slow, RuntimeError # Issue 16589
 
+[ $compiler == dart2js && $runtime == ff ]
+math/math_parse_double_test: Pass, RuntimeError # Issue 28983
+
 [ $runtime == chrome && $system == macos ]
 async/timer_isActive_test: Fail, Pass, Timeout # Issue 22696
 async/slow_consumer_test: Pass, Timeout # Issue 22696
diff --git a/tests/lib/mirrors/function_apply_test.dart b/tests/lib/mirrors/function_apply_test.dart
new file mode 100644
index 0000000..14a96f5
--- /dev/null
+++ b/tests/lib/mirrors/function_apply_test.dart
@@ -0,0 +1,41 @@
+// Copyright (c) 2017, 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 lib;
+
+@MirrorsUsed(targets: "lib")
+import "dart:mirrors";
+
+import "package:expect/expect.dart";
+
+class A {
+  call(int x) => 123 + x;
+  bar(int y) => 321 + y;
+}
+
+foo(int y) => 456 + y;
+
+main() {
+  // Static function.
+  ClosureMirror f1 = reflect(foo);
+  Expect.equals(1456, f1.apply([1000]).reflectee);
+
+  // Local declaration.
+  chomp(int z) => z + 42;
+  ClosureMirror f2 = reflect(chomp);
+  Expect.equals(1042, f2.apply([1000]).reflectee);
+
+  // Local expression.
+  ClosureMirror f3 = reflect((u) => u + 987);
+  Expect.equals(1987, f3.apply([1000]).reflectee);
+
+  // Instance property extraction.
+  ClosureMirror f4 = reflect(new A().bar);
+  Expect.equals(1321, f4.apply([1000]).reflectee);
+
+  // Instance implementing Function via call method.
+  ClosureMirror f5 = reflect(new A());
+  Expect.equals(1123, f5.apply([1000]).reflectee);
+
+}
diff --git a/tests/lib_strong/html/html_mock_test.dart b/tests/lib_strong/html/html_mock_test.dart
index 9b6daf8..bdf8860 100644
--- a/tests/lib_strong/html/html_mock_test.dart
+++ b/tests/lib_strong/html/html_mock_test.dart
@@ -2,6 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+import 'dart:async';
 import 'dart:html';
 
 import 'package:expect/minitest.dart';
@@ -11,7 +12,26 @@
 }
 
 @proxy
-class MockWindow extends Mock implements Window {}
+class MockBodyElement extends Mock implements BodyElement {
+  Node append(Node e) => e;
+}
+
+@proxy
+class MockHtmlDocument extends Mock implements HtmlDocument {
+  BodyElement get body => new MockBodyElement();
+}
+
+@proxy
+class MockWindow extends Mock implements Window {
+  Stream<Event> get onBeforeUnload => new Stream.fromIterable([]);
+
+  String name = "MOCK_NAME";
+}
+
+@proxy
+class MockLocation extends Mock implements Location {
+  String href = "MOCK_HREF";
+}
 
 main() {
   test('is', () {
@@ -23,4 +43,26 @@
     var win = new MockWindow();
     expect(win.document, equals(document));
   });
+
+  test('override', () {
+    Window win = new MockWindow();
+    expect(win.onBeforeUnload != null, isTrue);
+    expect(win.name, equals("MOCK_NAME"));
+  });
+
+  test('override', () {
+    var loc1 = new MockLocation();
+    Location loc2 = loc1;
+    dynamic loc3 = loc1;
+    expect(loc1.href, equals("MOCK_HREF"));
+    loc1.href = "RESET";
+    expect(loc2.href, equals("RESET"));
+    loc2.href = "RESET2";
+    expect(loc3.href, equals("RESET2"));
+  });
+
+  test('method', () {
+    HtmlDocument doc = new MockHtmlDocument();
+    expect(doc.body.append(null), equals(null));
+  });
 }
diff --git a/tests/lib_strong/lib_strong.status b/tests/lib_strong/lib_strong.status
index 99f3ea5..e5c5d81 100644
--- a/tests/lib_strong/lib_strong.status
+++ b/tests/lib_strong/lib_strong.status
@@ -7,7 +7,7 @@
 *: SkipByDesign
 
 # Skip tests that are not yet strong-mode clean.
-[ $strong == true ]
+[ $strong ]
 convert/chunked_conversion1_test: Skip
 convert/chunked_conversion_json_encode1_test: Skip
 convert/chunked_conversion_utf84_test: Skip
@@ -130,3 +130,42 @@
 typed_data/float32x4_test: Skip
 typed_data/float64x2_functional_test: Skip
 typed_data/int32x4_test: Skip
+
+[ $compiler == dart2analyzer && $strong ]
+convert/ascii_test: StaticWarning # Issue 28969
+convert/chunked_conversion_json_decode1_test: StaticWarning # Issue 28969
+convert/chunked_conversion_utf82_test: StaticWarning # Issue 28969
+convert/chunked_conversion_utf83_test: StaticWarning # Issue 28969
+convert/chunked_conversion_utf85_test: StaticWarning # Issue 28969
+convert/encoding_test: StaticWarning # Issue 28969
+convert/json_utf8_chunk_test: StaticWarning # Issue 28969
+convert/latin1_test: StaticWarning # Issue 28969
+convert/streamed_conversion_json_utf8_decode_test: StaticWarning # Issue 28969
+convert/streamed_conversion_json_utf8_encode_test: StaticWarning # Issue 28969
+convert/streamed_conversion_utf8_decode_test: StaticWarning # Issue 28969
+convert/streamed_conversion_utf8_encode_test: StaticWarning # Issue 28969
+convert/utf8_encode_test: StaticWarning # Issue 28969
+convert/utf8_test: StaticWarning # Issue 28969
+html/canvas_test: StaticWarning # Issue 28969
+html/canvasrenderingcontext2d_test: StaticWarning # Issue 28969
+html/cross_domain_iframe_test: StaticWarning # Issue 28969
+html/cssstyledeclaration_test: StaticWarning # Issue 28969
+html/custom/created_callback_test: CompileTimeError # Issue 28969
+html/custom/document_register_basic_test: CompileTimeError # Issue 28969
+html/custom/document_register_type_extensions_test: CompileTimeError # Issue 28969
+html/custom/element_upgrade_test: CompileTimeError # Issue 28969
+html/debugger_test: CompileTimeError # Issue 28969
+html/element_animate_test: StaticWarning # Issue 28969
+html/form_data_test: StaticWarning # Issue 28969
+html/history_test: StaticWarning # Issue 28969
+html/indexeddb_2_test: StaticWarning # Issue 28969
+html/js_interop_1_test: StaticWarning # Issue 28969
+html/js_typed_interop_default_arg_test/default_value: MissingCompileTimeError # Issue 28969
+html/native_gc_test: StaticWarning # Issue 28969
+html/request_animation_frame_test: StaticWarning # Issue 28969
+html/transition_event_test: StaticWarning # Issue 28969
+html/url_test: StaticWarning # Issue 28969
+html/wheelevent_test: StaticWarning # Issue 28969
+html/worker_test: StaticWarning # Issue 28969
+html/xhr_test: StaticWarning # Issue 28969
+mirrors/deferred_mirrors_metadata_test: StaticWarning # Issue 28969
diff --git a/tools/VERSION b/tools/VERSION
index 00ca6a0..d96ca95 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 1
 MINOR 23
 PATCH 0
-PRERELEASE 4
+PRERELEASE 5
 PRERELEASE_PATCH 0
diff --git a/tools/observatory_tool.py b/tools/observatory_tool.py
index 8450a07..5936b82 100755
--- a/tools/observatory_tool.py
+++ b/tools/observatory_tool.py
@@ -8,6 +8,7 @@
 import os
 import platform
 import shutil
+import socket
 import subprocess
 import sys
 import utils
@@ -217,6 +218,13 @@
     return -1;
 
 def main():
+  # Sanity check that localhost can be resolved.
+  try:
+    socket.gethostbyname('localhost')
+  except:
+    print("The hostname 'localhost' could not be resolved. Please fix your"
+          "/etc/hosts file and try again")
+    return -1
   # Parse the options.
   parser = BuildArguments()
   (options, args) = parser.parse_known_args()
diff --git a/tools/patch_sdk.dart b/tools/patch_sdk.dart
index bcdc635..cdfc24c 100644
--- a/tools/patch_sdk.dart
+++ b/tools/patch_sdk.dart
@@ -78,9 +78,6 @@
   var sdkOut = path.join(outDir, 'lib');
   var packagesFile = argv[4];
 
-  var privateIn = path.join(input, 'private');
-  var INTERNAL_PATH = '_internal/compiler/js_lib/';
-
   // Copy and patch libraries.dart and version
   var libContents = readInputFile(path.join(
       sdkLibIn, '_internal', 'sdk_library_metadata', 'lib', 'libraries.dart'));