Handle dart:html in kernel_impact

R=het@google.com

Review URL: https://codereview.chromium.org/2481113003 .
diff --git a/pkg/compiler/lib/src/common/names.dart b/pkg/compiler/lib/src/common/names.dart
index 56d826c..06ef360 100644
--- a/pkg/compiler/lib/src/common/names.dart
+++ b/pkg/compiler/lib/src/common/names.dart
@@ -171,4 +171,13 @@
   /// The URI for 'dart:_native_typed_data'.
   static final Uri dart__native_typed_data =
       new Uri(scheme: 'dart', path: '_native_typed_data');
+
+  /// The URI for 'dart:svg'.
+  static final Uri dart_svg = new Uri(scheme: 'dart', path: 'svg');
+
+  /// The URI for 'dart:web_audio'.
+  static final Uri dart_web_audio = new Uri(scheme: 'dart', path: 'web_audio');
+
+  /// The URI for 'dart:web_gl'.
+  static final Uri dart_web_gl = new Uri(scheme: 'dart', path: 'web_gl');
 }
diff --git a/pkg/compiler/lib/src/enqueue.dart b/pkg/compiler/lib/src/enqueue.dart
index 12c5a42..b254e0d 100644
--- a/pkg/compiler/lib/src/enqueue.dart
+++ b/pkg/compiler/lib/src/enqueue.dart
@@ -157,7 +157,6 @@
     impactVisitor = new _EnqueuerImpactVisitor(this);
   }
 
-  // TODO(johnniwinther): Move this to [ResolutionEnqueuer].
   Resolution get resolution => compiler.resolution;
 
   ResolutionWorldBuilder get universe => _universe;
diff --git a/pkg/compiler/lib/src/kernel/kernel_debug.dart b/pkg/compiler/lib/src/kernel/kernel_debug.dart
index f86a6a2..d723354 100644
--- a/pkg/compiler/lib/src/kernel/kernel_debug.dart
+++ b/pkg/compiler/lib/src/kernel/kernel_debug.dart
@@ -43,6 +43,11 @@
   }
 
   @override
+  void visitStaticGet(StaticGet node) {
+    openAndCloseNode(node, '${node.runtimeType}', {'target': '${node.target}'});
+  }
+
+  @override
   void visitVariableDeclaration(VariableDeclaration node) {
     openNode(node, '${node.runtimeType}', {
       'name': '${node.name ?? '--unnamed--'}',
diff --git a/pkg/compiler/lib/src/native/behavior.dart b/pkg/compiler/lib/src/native/behavior.dart
index 8609630..e34145a 100644
--- a/pkg/compiler/lib/src/native/behavior.dart
+++ b/pkg/compiler/lib/src/native/behavior.dart
@@ -31,6 +31,8 @@
 
   int get hashCode => name.hashCode;
 
+  String toString() => name;
+
   static SpecialType fromName(String name) {
     if (name == '=Object') {
       return JsObject;
diff --git a/pkg/compiler/lib/src/resolution/members.dart b/pkg/compiler/lib/src/resolution/members.dart
index 00b3725..f93553d 100644
--- a/pkg/compiler/lib/src/resolution/members.dart
+++ b/pkg/compiler/lib/src/resolution/members.dart
@@ -85,6 +85,7 @@
   /// in static contexts, factory methods, and field initializers).
   bool inInstanceContext;
   bool inCheckContext;
+  bool inCatchParameters = false;
   bool inCatchBlock;
   ConstantState constantState;
 
@@ -4703,6 +4704,7 @@
               nodeList, MessageKind.OPTIONAL_PARAMETER_IN_CATCH);
         } else {
           VariableDefinitions declaration = link.head;
+
           for (Node modifier in declaration.modifiers.nodes) {
             reporter.reportErrorMessage(
                 modifier, MessageKind.PARAMETER_WITH_MODIFIER_IN_CATCH);
@@ -4717,15 +4719,17 @@
     }
 
     Scope blockScope = new BlockScope(scope);
-    TypeResult exceptionTypeResult = visitIn(node.type, blockScope);
+    inCatchParameters = true;
     visitIn(node.formals, blockScope);
+    inCatchParameters = false;
     var oldInCatchBlock = inCatchBlock;
     inCatchBlock = true;
     visitIn(node.block, blockScope);
     inCatchBlock = oldInCatchBlock;
 
-    if (exceptionTypeResult != null) {
-      DartType exceptionType = exceptionTypeResult.type;
+    if (node.type != null) {
+      DartType exceptionType =
+          resolveTypeAnnotation(node.type, registerCheckedModeCheck: false);
       if (exceptionDefinition != null) {
         Node exceptionVariable = exceptionDefinition.definitions.nodes.head;
         VariableElementX exceptionElement =
diff --git a/pkg/compiler/lib/src/resolution/variables.dart b/pkg/compiler/lib/src/resolution/variables.dart
index fa7dd75..d6490e0 100644
--- a/pkg/compiler/lib/src/resolution/variables.dart
+++ b/pkg/compiler/lib/src/resolution/variables.dart
@@ -42,8 +42,10 @@
   }
 
   Identifier visitIdentifier(Identifier node) {
-    // The variable is initialized to null.
-    registry.registerFeature(Feature.LOCAL_WITHOUT_INITIALIZER);
+    if (!resolver.inCatchParameters) {
+      // The variable is initialized to null.
+      registry.registerFeature(Feature.LOCAL_WITHOUT_INITIALIZER);
+    }
     if (definitions.modifiers.isConst) {
       if (resolver.inLoopVariable) {
         reporter.reportErrorMessage(node, MessageKind.CONST_LOOP_VARIABLE);
diff --git a/pkg/compiler/lib/src/ssa/kernel_ast_adapter.dart b/pkg/compiler/lib/src/ssa/kernel_ast_adapter.dart
index be4a558..ae86379 100644
--- a/pkg/compiler/lib/src/ssa/kernel_ast_adapter.dart
+++ b/pkg/compiler/lib/src/ssa/kernel_ast_adapter.dart
@@ -15,7 +15,7 @@
 import '../js_backend/js_backend.dart';
 import '../kernel/kernel.dart';
 import '../kernel/kernel_debug.dart';
-import '../native/native.dart' show NativeBehavior;
+import '../native/native.dart' show NativeBehavior, TypeLookup;
 import '../resolution/tree_elements.dart';
 import '../tree/tree.dart' as ast;
 import '../types/masks.dart';
@@ -358,26 +358,32 @@
   // TODO(johnniwinther): Use this in [NativeBehavior] instead of calling the
   // `ForeignResolver`.
   // TODO(johnniwinther): Cache the result to avoid redundant lookups?
-  DartType _typeLookup(String typeName) {
-    DartType findIn(Uri uri) {
-      LibraryElement library = _compiler.libraryLoader.lookupLibrary(uri);
-      if (library != null) {
-        Element element = library.find(typeName);
-        if (element != null && element.isClass) {
-          ClassElement cls = element;
-          return cls.rawType;
+  TypeLookup _typeLookup({bool resolveAsRaw: true}) {
+    return (String typeName) {
+      DartType findIn(Uri uri) {
+        LibraryElement library = _compiler.libraryLoader.lookupLibrary(uri);
+        if (library != null) {
+          Element element = library.find(typeName);
+          if (element != null && element.isClass) {
+            ClassElement cls = element;
+            // TODO(johnniwinther): Align semantics.
+            return resolveAsRaw ? cls.rawType : cls.thisType;
+          }
         }
+        return null;
       }
-      return null;
-    }
 
-    DartType type = findIn(Uris.dart_core);
-    type ??= findIn(BackendHelpers.DART_JS_HELPER);
-    type ??= findIn(BackendHelpers.DART_INTERCEPTORS);
-    type ??= findIn(BackendHelpers.DART_ISOLATE_HELPER);
-    type ??= findIn(Uris.dart_collection);
-    type ??= findIn(Uris.dart_html);
-    return type;
+      DartType type = findIn(Uris.dart_core);
+      type ??= findIn(BackendHelpers.DART_JS_HELPER);
+      type ??= findIn(BackendHelpers.DART_INTERCEPTORS);
+      type ??= findIn(BackendHelpers.DART_ISOLATE_HELPER);
+      type ??= findIn(Uris.dart_collection);
+      type ??= findIn(Uris.dart_html);
+      type ??= findIn(Uris.dart_svg);
+      type ??= findIn(Uris.dart_web_audio);
+      type ??= findIn(Uris.dart_web_gl);
+      return type;
+    };
   }
 
   String _getStringArgument(ir.StaticInvocation node, int index) {
@@ -407,8 +413,13 @@
       return new NativeBehavior();
     }
 
-    return NativeBehavior.ofJsCall(specString, codeString, _typeLookup,
-        CURRENT_ELEMENT_SPANNABLE, reporter, _compiler.coreTypes);
+    return NativeBehavior.ofJsCall(
+        specString,
+        codeString,
+        _typeLookup(resolveAsRaw: true),
+        CURRENT_ELEMENT_SPANNABLE,
+        reporter,
+        _compiler.coreTypes);
   }
 
   /// Computes the [NativeBehavior] for a call to the [JS_BUILTIN] function.
@@ -430,8 +441,12 @@
           CURRENT_ELEMENT_SPANNABLE, "Unexpected first argument.");
       return new NativeBehavior();
     }
-    return NativeBehavior.ofJsBuiltinCall(specString, _typeLookup,
-        CURRENT_ELEMENT_SPANNABLE, reporter, _compiler.coreTypes);
+    return NativeBehavior.ofJsBuiltinCall(
+        specString,
+        _typeLookup(resolveAsRaw: true),
+        CURRENT_ELEMENT_SPANNABLE,
+        reporter,
+        _compiler.coreTypes);
   }
 
   /// Computes the [NativeBehavior] for a call to the [JS_EMBEDDED_GLOBAL]
@@ -461,8 +476,12 @@
           CURRENT_ELEMENT_SPANNABLE, "Unexpected first argument.");
       return new NativeBehavior();
     }
-    return NativeBehavior.ofJsEmbeddedGlobalCall(specString, _typeLookup,
-        CURRENT_ELEMENT_SPANNABLE, reporter, _compiler.coreTypes);
+    return NativeBehavior.ofJsEmbeddedGlobalCall(
+        specString,
+        _typeLookup(resolveAsRaw: true),
+        CURRENT_ELEMENT_SPANNABLE,
+        reporter,
+        _compiler.coreTypes);
   }
 
   /// Returns `true` is [node] has a `@Native(...)` annotation.
@@ -485,8 +504,8 @@
   NativeBehavior getNativeBehaviorForFieldLoad(ir.Field field) {
     DartType type = getDartType(field.type);
     List<ConstantExpression> metadata = getMetadata(field.annotations);
-    return NativeBehavior.ofFieldLoad(
-        CURRENT_ELEMENT_SPANNABLE, type, metadata, _typeLookup, _compiler,
+    return NativeBehavior.ofFieldLoad(CURRENT_ELEMENT_SPANNABLE, type, metadata,
+        _typeLookup(resolveAsRaw: false), _compiler,
         isJsInterop: false);
   }
 
@@ -502,8 +521,8 @@
   NativeBehavior getNativeBehaviorForMethod(ir.Procedure procedure) {
     DartType type = getFunctionType(procedure.function);
     List<ConstantExpression> metadata = getMetadata(procedure.annotations);
-    return NativeBehavior.ofMethod(
-        CURRENT_ELEMENT_SPANNABLE, type, metadata, _typeLookup, _compiler,
+    return NativeBehavior.ofMethod(CURRENT_ELEMENT_SPANNABLE, type, metadata,
+        _typeLookup(resolveAsRaw: false), _compiler,
         isJsInterop: false);
   }
 }
@@ -639,6 +658,17 @@
   }
 
   @override
+  ConstantExpression visitStaticGet(ir.StaticGet node) {
+    Element element = astAdapter.getMember(node.target);
+    if (element.isField) {
+      return new VariableConstantExpression(element);
+    }
+    astAdapter.reporter.internalError(
+        CURRENT_ELEMENT_SPANNABLE, "Unexpected constant target: $element.");
+    return null;
+  }
+
+  @override
   ConstantExpression visitStringLiteral(ir.StringLiteral node) {
     return new StringConstantExpression(node.value);
   }
diff --git a/pkg/compiler/lib/src/ssa/kernel_impact.dart b/pkg/compiler/lib/src/ssa/kernel_impact.dart
index 2bdc08d..155c10e 100644
--- a/pkg/compiler/lib/src/ssa/kernel_impact.dart
+++ b/pkg/compiler/lib/src/ssa/kernel_impact.dart
@@ -532,7 +532,6 @@
   @override
   void visitCatch(ir.Catch node) {
     impactBuilder.registerFeature(Feature.CATCH_STATEMENT);
-    visitNode(node.exception);
     if (node.stackTrace != null) {
       impactBuilder.registerFeature(Feature.STACK_TRACE_IN_CATCH);
     }
diff --git a/tests/compiler/dart2js/kernel/impact_test.dart b/tests/compiler/dart2js/kernel/impact_test.dart
index 4d176ad..363f44d 100644
--- a/tests/compiler/dart2js/kernel/impact_test.dart
+++ b/tests/compiler/dart2js/kernel/impact_test.dart
@@ -27,6 +27,7 @@
 const Map<String, String> SOURCE = const <String, String>{
   'main.dart': r'''
 import 'helper.dart';
+import 'dart:html';
 
 main() {
   testEmpty();
@@ -614,27 +615,56 @@
     compiler.resolution.retainCachesForTesting = true;
     await compiler.run(entryPoint);
     compiler.libraryLoader.libraries.forEach((LibraryElement library) {
-      checkLibrary(compiler, library);
+      checkLibrary(compiler, library, fullTest: args.contains('--full'));
     });
   });
 }
 
-void checkLibrary(Compiler compiler, LibraryElement library) {
+void checkLibrary(Compiler compiler, LibraryElement library,
+    {bool fullTest: false}) {
   library.forEachLocalMember((AstElement element) {
     if (element.isClass) {
       ClassElement cls = element;
       cls.forEachLocalMember((AstElement member) {
-        checkElement(compiler, member);
+        checkElement(compiler, member, fullTest: fullTest);
       });
     } else if (element.isTypedef) {
       // Skip typedefs.
     } else {
-      checkElement(compiler, element);
+      checkElement(compiler, element, fullTest: fullTest);
     }
   });
 }
 
-void checkElement(Compiler compiler, AstElement element) {
+void checkElement(Compiler compiler, AstElement element,
+    {bool fullTest: false}) {
+  if (!fullTest) {
+    if (element.library.isPlatformLibrary) {
+      // Test only selected elements in web-related platform libraries since
+      // this unittest otherwise takes too long to run.
+      switch (element.library.canonicalUri.path) {
+        case 'html':
+          if ('$element' ==
+              'function(_ValidatingTreeSanitizer#_sanitizeUntrustedElement)') {
+            break;
+          }
+          return;
+        case 'web_gl':
+          if ('$element' ==
+              'function(RenderingContext#getFramebufferAttachmentParameter)') {
+            return;
+          }
+          break;
+        case 'indexed_db':
+          if ('$element' == 'field(ObjectStore#keyPath)') {
+            break;
+          }
+          return;
+        case 'web_audio':
+          return;
+      }
+    }
+  }
   if (element.isConstructor) {
     ConstructorElement constructor = element;
     if (constructor.isRedirectingFactory) {
@@ -673,8 +703,8 @@
   }
   impact.dynamicUses.forEach(builder.registerDynamicUse);
   for (TypeUse typeUse in impact.typeUses) {
-    builder.registerTypeUse(new TypeUse.internal(
-        const Unaliaser().visit(typeUse.type), typeUse.kind));
+    builder.registerTypeUse(
+        new TypeUse.internal(unalias(typeUse.type), typeUse.kind));
   }
   impact.constantLiterals.forEach(builder.registerConstantLiteral);
   impact.constSymbolNames.forEach(builder.registerConstSymbolName);
@@ -773,3 +803,8 @@
         visitList(type.namedParameterTypes));
   }
 }
+
+/// Perform unaliasing of all typedefs nested within a [DartType].
+DartType unalias(DartType type) {
+  return const Unaliaser().visit(type);
+}