[dartdevc] Fix violations of library_prefix lint

Rename the library prefix used in imports from `JS` to `js_ast`. Create more of
a distinction between:
* `JS` the library.  Now named `js_ast`.
* `js` the const instance of a JSBuilder.
* `JS` the helper to inline javascript in the SDK patches
  and runtime libraries.

Ignore the lint in the js_ast directory to avoid additional diffs for the
eventual un-forking of the package.

Cleanup a few unused imports.

Issue #37218

Change-Id: I039c1048876d9d9ad424fbec3ad555d300845a3d
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/106160
Reviewed-by: Nate Bosch <nbosch@google.com>
Reviewed-by: Mark Zhou <markzipan@google.com>
Commit-Queue: Nicholas Shahan <nshahan@google.com>
diff --git a/pkg/dev_compiler/analysis_options.yaml b/pkg/dev_compiler/analysis_options.yaml
index 13ed31a..249dc5d 100644
--- a/pkg/dev_compiler/analysis_options.yaml
+++ b/pkg/dev_compiler/analysis_options.yaml
@@ -24,6 +24,7 @@
     - empty_catches
     - empty_constructor_bodies
     - library_names
+    - library_prefixes
     - no_duplicate_case_values
     - null_closures
     - prefer_contains
diff --git a/pkg/dev_compiler/lib/src/analyzer/code_generator.dart b/pkg/dev_compiler/lib/src/analyzer/code_generator.dart
index 3ff97b0..1dc1e73 100644
--- a/pkg/dev_compiler/lib/src/analyzer/code_generator.dart
+++ b/pkg/dev_compiler/lib/src/analyzer/code_generator.dart
@@ -29,12 +29,12 @@
 import 'package:path/path.dart' as path;
 import 'package:source_span/source_span.dart' show SourceLocation;
 
-import '../compiler/js_metalet.dart' as JS;
-import '../compiler/js_names.dart' as JS;
-import '../compiler/js_utils.dart' as JS;
+import '../compiler/js_metalet.dart' as js_ast;
+import '../compiler/js_names.dart' as js_ast;
+import '../compiler/js_utils.dart' as js_ast;
 import '../compiler/module_builder.dart' show pathToJSIdentifier;
 import '../compiler/shared_compiler.dart';
-import '../js_ast/js_ast.dart' as JS;
+import '../js_ast/js_ast.dart' as js_ast;
 import '../js_ast/js_ast.dart' show js;
 import '../js_ast/source_map_printer.dart' show NodeEnd, NodeSpan, HoverComment;
 import 'ast_builder.dart';
@@ -68,12 +68,12 @@
 // (which result in (JS.Statement).
 class CodeGenerator extends Object
     with
-        UIAsCodeVisitorMixin<JS.Node>,
+        UIAsCodeVisitorMixin<js_ast.Node>,
         NullableTypeInference,
         SharedCompiler<LibraryElement, ClassElement, InterfaceType,
             FunctionBody>
     implements
-        AstVisitor<JS.Node> {
+        AstVisitor<js_ast.Node> {
   final SummaryDataStore summaryData;
 
   final CompilerOptions options;
@@ -87,7 +87,7 @@
 
   /// The list of dart:_runtime SDK functions; these are assumed by other code
   /// in the SDK to be generated before anything else.
-  final _internalSdkFunctions = <JS.ModuleItem>[];
+  final _internalSdkFunctions = <js_ast.ModuleItem>[];
 
   /// Table of named and possibly hoisted types.
   TypeTable _typeTable;
@@ -105,9 +105,10 @@
   SimpleIdentifier _rethrowParameter;
 
   /// In an async* function, this represents the stream controller parameter.
-  JS.TemporaryId _asyncStarController;
+  js_ast.TemporaryId _asyncStarController;
 
-  final _initializingFormalTemps = HashMap<ParameterElement, JS.TemporaryId>();
+  final _initializingFormalTemps =
+      HashMap<ParameterElement, js_ast.TemporaryId>();
 
   /// The  type provider from the current Analysis [context].
   final TypeProvider types;
@@ -167,13 +168,13 @@
   /// mappings.
   Element _currentElement;
 
-  final _deferredProperties = HashMap<PropertyAccessorElement, JS.Method>();
+  final _deferredProperties = HashMap<PropertyAccessorElement, js_ast.Method>();
 
   String _libraryRoot;
 
   bool _superAllowed = true;
 
-  final _superHelpers = Map<String, JS.Method>();
+  final _superHelpers = Map<String, js_ast.Method>();
 
   /// Whether we are currently generating code for the body of a `JS()` call.
   bool _isInForeignJS = false;
@@ -194,7 +195,7 @@
   /// Tracks the temporary variable used to build collections containing
   /// control flow [IfElement] and [ForElement] nodes. Should be saved when
   /// visiting a new control flow tree and restored after.
-  JS.Expression _currentCollectionVariable;
+  js_ast.Expression _currentCollectionVariable;
 
   CodeGenerator(LinkedAnalysisDriver driver, this.types, this.summaryData,
       this.options, this._extensionTypes, this.errors)
@@ -261,7 +262,7 @@
   ///
   /// Takes the metadata for the build unit, as well as resolved trees and
   /// errors, and computes the output module code and optionally the source map.
-  JS.Program compile(List<CompilationUnit> compilationUnits) {
+  js_ast.Program compile(List<CompilationUnit> compilationUnits) {
     _libraryRoot = options.libraryRoot;
     if (!_libraryRoot.endsWith(path.separator)) {
       _libraryRoot += path.separator;
@@ -373,18 +374,18 @@
     return libraryJSName != null ? '$libraryJSName.$jsName' : jsName;
   }
 
-  JS.PropertyAccess _emitJSInterop(Element e) {
+  js_ast.PropertyAccess _emitJSInterop(Element e) {
     var jsName = _getJSNameWithoutGlobal(e);
     if (jsName == null) return null;
     return _emitJSInteropForGlobal(jsName);
   }
 
-  JS.PropertyAccess _emitJSInteropForGlobal(String name) {
+  js_ast.PropertyAccess _emitJSInteropForGlobal(String name) {
     var parts = name.split('.');
     if (parts.isEmpty) parts = [''];
-    JS.PropertyAccess access;
+    js_ast.PropertyAccess access;
     for (var part in parts) {
-      access = JS.PropertyAccess(
+      access = js_ast.PropertyAccess(
           access ?? runtimeCall('global'), js.escapedString(part, "'"));
     }
     return access;
@@ -474,7 +475,7 @@
     var source = library.source;
     // TODO(jmesserly): we need to split out HTML.
     if (source.uri.scheme == 'dart') {
-      return JS.dartSdkModule;
+      return js_ast.dartSdkModule;
     }
     var summaryPath = (source as InSummarySource).summaryPath;
     var moduleName = options.summaryModules[summaryPath];
@@ -507,7 +508,7 @@
     // only run this on the outermost function, and not any closures.
     inferNullableTypes(node);
 
-    moduleItems.add(node.accept(this) as JS.ModuleItem);
+    moduleItems.add(node.accept(this) as js_ast.ModuleItem);
 
     _currentElement = savedElement;
   }
@@ -566,7 +567,7 @@
       }
 
       inferNullableTypes(declaration);
-      var item = declaration.accept(this) as JS.ModuleItem;
+      var item = declaration.accept(this) as js_ast.ModuleItem;
       if (isInternalSdk && element is FunctionElement) {
         _internalSdkFunctions.add(item);
       } else {
@@ -709,7 +710,7 @@
     return _emitCast(to, jsFrom, implicit: isImplicit);
   }
 
-  JS.Expression _emitCast(DartType type, JS.Expression expr,
+  js_ast.Expression _emitCast(DartType type, js_ast.Expression expr,
       {bool implicit = true}) {
     // If [type] is a top type we can omit the cast.
     if (rules.isSubtypeOf(types.objectType, type)) {
@@ -720,15 +721,15 @@
   }
 
   @override
-  JS.Expression visitIsExpression(IsExpression node) {
+  js_ast.Expression visitIsExpression(IsExpression node) {
     return _emitIsExpression(
         node.expression, node.type.type, node.notOperator != null);
   }
 
-  JS.Expression _emitIsExpression(Expression operand, DartType type,
+  js_ast.Expression _emitIsExpression(Expression operand, DartType type,
       [bool negated = false]) {
     // Generate `is` as `dart.is` or `typeof` depending on the RHS type.
-    JS.Expression result;
+    js_ast.Expression result;
     var lhs = _visitExpression(operand);
     var typeofName = jsTypeRep.typeFor(type).primitiveTypeOf;
     // Inline primitives other than int (which requires a Math.floor check).
@@ -750,12 +751,12 @@
   visitGenericTypeAlias(GenericTypeAlias node) => null;
 
   @override
-  JS.Expression visitTypeName(node) => _emitTypeAnnotation(node);
+  js_ast.Expression visitTypeName(node) => _emitTypeAnnotation(node);
 
   @override
-  JS.Expression visitGenericFunctionType(node) => _emitTypeAnnotation(node);
+  js_ast.Expression visitGenericFunctionType(node) => _emitTypeAnnotation(node);
 
-  JS.Expression _emitTypeAnnotation(TypeAnnotation node) {
+  js_ast.Expression _emitTypeAnnotation(TypeAnnotation node) {
     var type = node.type;
     if (type == null) {
       // TODO(jmesserly): if the type fails to resolve, should we generate code
@@ -767,17 +768,17 @@
   }
 
   @override
-  JS.Statement visitClassTypeAlias(ClassTypeAlias node) {
+  js_ast.Statement visitClassTypeAlias(ClassTypeAlias node) {
     return _emitClassDeclaration(
         node, node.declaredElement as ClassElement, []);
   }
 
   @override
-  JS.Statement visitClassDeclaration(ClassDeclaration node) {
+  js_ast.Statement visitClassDeclaration(ClassDeclaration node) {
     return _emitClassDeclaration(node, node.declaredElement, node.members);
   }
 
-  JS.Statement _emitClassDeclaration(Declaration classNode,
+  js_ast.Statement _emitClassDeclaration(Declaration classNode,
       ClassElement classElem, List<ClassMember> members) {
     // If this class is annotated with `@JS`, then there is nothing to emit.
     if (_hasJSInteropAnnotation(classElem)) return null;
@@ -790,8 +791,8 @@
     // https://github.com/dart-lang/sdk/issues/31003
     var className = classElem.typeParameters.isNotEmpty
         ? (classElem == _jsArray
-            ? JS.Identifier(classElem.name)
-            : JS.TemporaryId(classElem.name))
+            ? js_ast.Identifier(classElem.name)
+            : js_ast.TemporaryId(classElem.name))
         : _emitTopLevelName(classElem);
 
     var savedClassProperties = _classProperties;
@@ -818,9 +819,9 @@
     var jsMethods = _emitClassMethods(classElem, members);
     _emitSuperclassCovarianceChecks(classNode, jsMethods);
 
-    var body = <JS.Statement>[];
+    var body = <js_ast.Statement>[];
     _emitSuperHelperSymbols(body);
-    var deferredSupertypes = <JS.Statement>[];
+    var deferredSupertypes = <js_ast.Statement>[];
 
     // Emit the class, e.g. `core.Object = class Object { ... }`
     _defineClass(classElem, className, jsMethods, body, deferredSupertypes);
@@ -844,7 +845,7 @@
     }
     _emitClassMetadata(classNode.metadata, className, body);
 
-    var classDef = JS.Statement.from(body);
+    var classDef = js_ast.Statement.from(body);
     var typeFormals = classElem.typeParameters;
     if (typeFormals.isNotEmpty) {
       classDef = _defineClassTypeArguments(
@@ -861,12 +862,12 @@
     }
 
     _classProperties = savedClassProperties;
-    return JS.Statement.from(body);
+    return js_ast.Statement.from(body);
   }
 
-  JS.Statement _emitClassTypeTests(ClassElement classElem,
-      JS.Expression className, List<JS.Statement> body) {
-    JS.Expression getInterfaceSymbol(ClassElement c) {
+  js_ast.Statement _emitClassTypeTests(ClassElement classElem,
+      js_ast.Expression className, List<js_ast.Statement> body) {
+    js_ast.Expression getInterfaceSymbol(ClassElement c) {
       var library = c.library;
       if (library.isDartCore || library.isDartAsync) {
         switch (c.name) {
@@ -882,7 +883,7 @@
       return null;
     }
 
-    void markSubtypeOf(JS.Expression testSymbol) {
+    void markSubtypeOf(js_ast.Expression testSymbol) {
       body.add(js.statement('#.prototype[#] = true', [className, testSymbol]));
     }
 
@@ -1052,7 +1053,7 @@
     if (isClassSymbol == null) {
       // TODO(jmesserly): we could export these symbols, if we want to mark
       // implemented interfaces for user-defined classes.
-      var id = JS.TemporaryId("_is_${classElem.name}_default");
+      var id = js_ast.TemporaryId("_is_${classElem.name}_default");
       moduleItems.add(
           js.statement('const # = Symbol(#);', [id, js.string(id.name, "'")]));
       isClassSymbol = id;
@@ -1070,53 +1071,55 @@
     return runtimeStatement('addTypeTests(#, #)', [defaultInst, isClassSymbol]);
   }
 
-  void _emitSymbols(Iterable<JS.TemporaryId> vars, List<JS.ModuleItem> body) {
+  void _emitSymbols(
+      Iterable<js_ast.TemporaryId> vars, List<js_ast.ModuleItem> body) {
     for (var id in vars) {
       body.add(js.statement('const # = Symbol(#)', [id, js.string(id.name)]));
     }
   }
 
-  void _emitSuperHelperSymbols(List<JS.Statement> body) {
+  void _emitSuperHelperSymbols(List<js_ast.Statement> body) {
     _emitSymbols(
-        _superHelpers.values.map((m) => m.name as JS.TemporaryId), body);
+        _superHelpers.values.map((m) => m.name as js_ast.TemporaryId), body);
     _superHelpers.clear();
   }
 
   void _emitVirtualFieldSymbols(
-      ClassElement classElement, List<JS.Statement> body) {
+      ClassElement classElement, List<js_ast.Statement> body) {
     _classProperties.virtualFields.forEach((field, virtualField) {
       body.add(js.statement('const # = Symbol(#);',
           [virtualField, js.string('${classElement.name}.${field.name}')]));
     });
   }
 
-  List<JS.Identifier> _emitTypeFormals(List<TypeParameterElement> typeFormals) {
+  List<js_ast.Identifier> _emitTypeFormals(
+      List<TypeParameterElement> typeFormals) {
     return typeFormals
-        .map((t) => JS.Identifier(t.name))
+        .map((t) => js_ast.Identifier(t.name))
         .toList(growable: false);
   }
 
   @override
-  JS.Statement visitEnumDeclaration(EnumDeclaration node) {
+  js_ast.Statement visitEnumDeclaration(EnumDeclaration node) {
     return _emitClassDeclaration(node, node.declaredElement, []);
   }
 
   @override
-  JS.Statement visitMixinDeclaration(MixinDeclaration node) {
+  js_ast.Statement visitMixinDeclaration(MixinDeclaration node) {
     return _emitClassDeclaration(node, node.declaredElement, node.members);
   }
 
   /// Wraps a possibly generic class in its type arguments.
-  JS.Statement _defineClassTypeArguments(TypeDefiningElement element,
-      List<TypeParameterElement> formals, JS.Statement body,
-      [JS.Expression className, List<JS.Statement> deferredBaseClass]) {
+  js_ast.Statement _defineClassTypeArguments(TypeDefiningElement element,
+      List<TypeParameterElement> formals, js_ast.Statement body,
+      [js_ast.Expression className, List<js_ast.Statement> deferredBaseClass]) {
     assert(formals.isNotEmpty);
     var jsFormals = _emitTypeFormals(formals);
     var typeConstructor = js.call('(#) => { #; #; return #; }', [
       jsFormals,
       _typeTable.discharge(formals),
       body,
-      className ?? JS.Identifier(element.name)
+      className ?? js_ast.Identifier(element.name)
     ]);
 
     var genericArgs = [typeConstructor];
@@ -1131,17 +1134,18 @@
         [genericName, genericCall, _emitTopLevelName(element), genericName]);
   }
 
-  JS.Statement _emitClassStatement(
+  js_ast.Statement _emitClassStatement(
       ClassElement classElem,
-      JS.Expression className,
-      JS.Expression heritage,
-      List<JS.Method> methods) {
+      js_ast.Expression className,
+      js_ast.Expression heritage,
+      List<js_ast.Method> methods) {
     if (classElem.typeParameters.isNotEmpty) {
-      return JS.ClassExpression(className as JS.Identifier, heritage, methods)
+      return js_ast.ClassExpression(
+              className as js_ast.Identifier, heritage, methods)
           .toStatement();
     }
-    var classExpr =
-        JS.ClassExpression(JS.TemporaryId(classElem.name), heritage, methods);
+    var classExpr = js_ast.ClassExpression(
+        js_ast.TemporaryId(classElem.name), heritage, methods);
     return js.statement('# = #;', [className, classExpr]);
   }
 
@@ -1174,10 +1178,10 @@
   /// minimal compiler and runtime changes.
   void _emitMixinStatement(
       ClassElement classElem,
-      JS.Expression className,
-      JS.Expression heritage,
-      List<JS.Method> methods,
-      List<JS.Statement> body) {
+      js_ast.Expression className,
+      js_ast.Expression heritage,
+      List<js_ast.Method> methods,
+      List<js_ast.Statement> body) {
     assert(classElem.isMixin);
 
     var staticMethods = methods.where((m) => m.isStatic).toList();
@@ -1185,42 +1189,43 @@
     body.add(
         _emitClassStatement(classElem, className, heritage, staticMethods));
 
-    var superclassId = JS.TemporaryId(
+    var superclassId = js_ast.TemporaryId(
         classElem.superclassConstraints.map((t) => t.name).join('_'));
-    var classId =
-        className is JS.Identifier ? className : JS.TemporaryId(classElem.name);
+    var classId = className is js_ast.Identifier
+        ? className
+        : js_ast.TemporaryId(classElem.name);
 
     var mixinMemberClass =
-        JS.ClassExpression(classId, superclassId, instanceMethods);
+        js_ast.ClassExpression(classId, superclassId, instanceMethods);
 
-    JS.Node arrowFnBody = mixinMemberClass;
-    var extensionInit = <JS.Statement>[];
+    js_ast.Node arrowFnBody = mixinMemberClass;
+    var extensionInit = <js_ast.Statement>[];
     _defineExtensionMembers(classId, extensionInit);
     if (extensionInit.isNotEmpty) {
       extensionInit.insert(0, mixinMemberClass.toStatement());
       extensionInit.add(classId.toReturn());
-      arrowFnBody = JS.Block(extensionInit);
+      arrowFnBody = js_ast.Block(extensionInit);
     }
 
     body.add(js.statement('#[#.mixinOn] = #', [
       className,
       runtimeModule,
-      JS.ArrowFun([superclassId], arrowFnBody)
+      js_ast.ArrowFun([superclassId], arrowFnBody)
     ]));
   }
 
   void _defineClass(
       ClassElement classElem,
-      JS.Expression className,
-      List<JS.Method> methods,
-      List<JS.Statement> body,
-      List<JS.Statement> deferredSupertypes) {
+      js_ast.Expression className,
+      List<js_ast.Method> methods,
+      List<js_ast.Statement> body,
+      List<js_ast.Statement> deferredSupertypes) {
     if (classElem.type.isObject) {
       body.add(_emitClassStatement(classElem, className, null, methods));
       return;
     }
 
-    JS.Expression emitDeferredType(DartType t) {
+    js_ast.Expression emitDeferredType(DartType t) {
       if (t is InterfaceType && t.typeArguments.isNotEmpty) {
         _declareBeforeUse(t.element);
         return _emitGenericClassType(
@@ -1267,9 +1272,10 @@
     var supertype = classElem.isMixin ? types.objectType : classElem.supertype;
     var hasUnnamedSuper = _hasUnnamedInheritedConstructor(supertype.element);
 
-    void emitMixinConstructors(JS.Expression className, [InterfaceType mixin]) {
+    void emitMixinConstructors(js_ast.Expression className,
+        [InterfaceType mixin]) {
       var supertype = classElem.supertype;
-      JS.Statement mixinCtor;
+      js_ast.Statement mixinCtor;
       if (mixin != null && _hasUnnamedConstructor(mixin.element)) {
         mixinCtor = js.statement('#.#.call(this);', [
           emitClassRef(mixin),
@@ -1281,14 +1287,14 @@
 
       for (var ctor in supertype.constructors) {
         var jsParams = _emitParametersForElement(ctor);
-        var ctorBody = <JS.Statement>[];
+        var ctorBody = <js_ast.Statement>[];
         if (mixinCtor != null) ctorBody.add(mixinCtor);
         if (ctor.name != '' || hasUnnamedSuper) {
           ctorBody
               .add(_emitSuperConstructorCall(className, ctor.name, jsParams));
         }
         body.add(_addConstructorToClass(classElem, className, ctor.name,
-            JS.Fun(jsParams, JS.Block(ctorBody))));
+            js_ast.Fun(jsParams, js_ast.Block(ctorBody))));
       }
     }
 
@@ -1334,8 +1340,8 @@
         //     applyMixin(C, class C$ extends M { <methods>  });
         mixinBody.add(runtimeStatement('applyMixin(#, #)', [
           classExpr,
-          JS.ClassExpression(
-              JS.TemporaryId(classElem.name), mixinClass, methods)
+          js_ast.ClassExpression(
+              js_ast.TemporaryId(classElem.name), mixinClass, methods)
         ]));
       }
 
@@ -1347,10 +1353,10 @@
       var m = classElem.mixins[i];
 
       var mixinString = classElem.supertype.name + '_' + m.name;
-      var mixinClassName = JS.TemporaryId(mixinString);
-      var mixinId = JS.TemporaryId(mixinString + '\$');
+      var mixinClassName = js_ast.TemporaryId(mixinString);
+      var mixinId = js_ast.TemporaryId(mixinString + '\$');
       var mixinClassExpression =
-          JS.ClassExpression(mixinClassName, baseClass, []);
+          js_ast.ClassExpression(mixinClassName, baseClass, []);
       // Bind the mixin class to a name to workaround a V8 bug with es6 classes
       // and anonymous function names.
       // TODO(leafp:) Eliminate this once the bug is fixed:
@@ -1392,28 +1398,28 @@
   /// field.  Note that the Dart names are always symbolized to avoid
   /// conflicts.  They will be installed as extension methods on the underlying
   /// native type.
-  List<JS.Method> _emitNativeFieldAccessors(FieldDeclaration node) {
+  List<js_ast.Method> _emitNativeFieldAccessors(FieldDeclaration node) {
     // TODO(vsm): Can this by meta-programmed?
     // E.g., dart.nativeField(symbol, jsName)
     // Alternatively, perhaps it could be meta-programmed directly in
     // dart.registerExtensions?
-    var jsMethods = <JS.Method>[];
+    var jsMethods = <js_ast.Method>[];
     if (!node.isStatic) {
       for (var decl in node.fields.variables) {
         var field = decl.declaredElement as FieldElement;
         var name = getAnnotationName(field, isJSName) ?? field.name;
         // Generate getter
-        var fn = JS.Fun([], js.block('{ return this.#; }', [name]));
+        var fn = js_ast.Fun([], js.block('{ return this.#; }', [name]));
         var method =
-            JS.Method(_declareMemberName(field.getter), fn, isGetter: true);
+            js_ast.Method(_declareMemberName(field.getter), fn, isGetter: true);
         jsMethods.add(method);
 
         // Generate setter
         if (!decl.isFinal) {
-          var value = JS.TemporaryId('value');
-          fn = JS.Fun([value], js.block('{ this.# = #; }', [name, value]));
-          method =
-              JS.Method(_declareMemberName(field.setter), fn, isSetter: true);
+          var value = js_ast.TemporaryId('value');
+          fn = js_ast.Fun([value], js.block('{ this.# = #; }', [name, value]));
+          method = js_ast.Method(_declareMemberName(field.setter), fn,
+              isSetter: true);
           jsMethods.add(method);
         }
       }
@@ -1421,20 +1427,20 @@
     return jsMethods;
   }
 
-  List<JS.Method> _emitClassMethods(
+  List<js_ast.Method> _emitClassMethods(
       ClassElement classElem, List<ClassMember> memberNodes) {
     var type = classElem.type;
     var virtualFields = _classProperties.virtualFields;
 
-    var jsMethods = <JS.Method>[];
+    var jsMethods = <js_ast.Method>[];
     bool hasJsPeer = _extensionTypes.isNativeClass(classElem);
     bool hasIterator = false;
 
     if (type.isObject) {
       // Dart does not use ES6 constructors.
       // Add an error to catch any invalid usage.
-      jsMethods
-          .add(JS.Method(propertyName('constructor'), js.fun(r'''function() {
+      jsMethods.add(
+          js_ast.Method(propertyName('constructor'), js.fun(r'''function() {
                   throw Error("use `new " + #.typeName(#.getReifiedType(this)) +
                       ".new(...)` to create a Dart object");
               }''', [runtimeModule, runtimeModule])));
@@ -1445,20 +1451,20 @@
       //
       // This will become obsolete when
       // https://github.com/dart-lang/sdk/issues/31003 is addressed.
-      jsMethods.add(JS.Method(
+      jsMethods.add(js_ast.Method(
           propertyName('constructor'), js.fun(r'function() { return []; }')));
     } else if (classElem.isEnum) {
       // Generate Enum.toString()
       var fields = classElem.fields.where((f) => f.type == type).toList();
-      var mapMap = List<JS.Property>(fields.length);
+      var mapMap = List<js_ast.Property>(fields.length);
       for (var i = 0; i < fields.length; ++i) {
-        mapMap[i] = JS.Property(
+        mapMap[i] = js_ast.Property(
             js.number(i), js.string('${type.name}.${fields[i].name}'));
       }
-      jsMethods.add(JS.Method(
+      jsMethods.add(js_ast.Method(
           _declareMemberName(types.objectType.getMethod('toString')),
           js.fun('function() { return #[this.index]; }',
-              JS.ObjectInitializer(mapMap, multiline: true))));
+              js_ast.ObjectInitializer(mapMap, multiline: true))));
     }
 
     for (var m in memberNodes) {
@@ -1515,7 +1521,7 @@
   }
 
   void _emitSuperclassCovarianceChecks(
-      Declaration node, List<JS.Method> methods) {
+      Declaration node, List<js_ast.Method> methods) {
     var covariantParams = getSuperclassCovariantParameters(node);
     if (covariantParams == null) return;
 
@@ -1526,22 +1532,22 @@
       if (member is PropertyAccessorElement) {
         var param =
             covariantParams.lookup(member.parameters[0]) as ParameterElement;
-        methods.add(JS.Method(
+        methods.add(js_ast.Method(
             name,
             js.fun('function(x) { return super.# = #; }',
-                [name, _emitCast(param.type, JS.Identifier('x'))]),
+                [name, _emitCast(param.type, js_ast.Identifier('x'))]),
             isSetter: true));
-        methods.add(JS.Method(
+        methods.add(js_ast.Method(
             name, js.fun('function() { return super.#; }', [name]),
             isGetter: true));
       } else if (member is MethodElement) {
         var type = member.type;
 
-        var body = <JS.Statement>[];
+        var body = <js_ast.Statement>[];
         _emitCovarianceBoundsCheck(type.typeFormals, covariantParams, body);
 
         var typeFormals = _emitTypeFormals(type.typeFormals);
-        var jsParams = List<JS.Parameter>.from(typeFormals);
+        var jsParams = List<js_ast.Parameter>.from(typeFormals);
         bool foundNamedParams = false;
         for (var param in member.parameters) {
           param = covariantParams.lookup(param) as ParameterElement;
@@ -1554,7 +1560,8 @@
             body.add(js.statement('if (# in #) #;', [
               name,
               namedArgumentTemp,
-              _emitCast(param.type, JS.PropertyAccess(namedArgumentTemp, name))
+              _emitCast(
+                  param.type, js_ast.PropertyAccess(namedArgumentTemp, name))
             ]));
           } else {
             var jsParam = _emitParameter(param);
@@ -1579,8 +1586,8 @@
           body.add(js.statement(
               'return super.#(#)(#);', [name, typeFormals, jsParams]));
         }
-        var fn = JS.Fun(jsParams, JS.Block(body));
-        methods.add(JS.Method(name, fn));
+        var fn = js_ast.Fun(jsParams, js_ast.Block(body));
+        methods.add(js_ast.Method(name, fn));
       } else {
         throw StateError(
             'unable to generate a covariant check for element: `$member` '
@@ -1590,12 +1597,12 @@
   }
 
   /// Emits a Dart factory constructor to a JS static method.
-  JS.Method _emitFactoryConstructor(ConstructorDeclaration node) {
+  js_ast.Method _emitFactoryConstructor(ConstructorDeclaration node) {
     if (isUnsupportedFactoryConstructor(node)) return null;
 
     var element = node.declaredElement;
     var name = _constructorName(element.name);
-    JS.Fun fun;
+    js_ast.Fun fun;
 
     var savedFunction = _currentFunction;
     _currentFunction = node.body;
@@ -1610,27 +1617,27 @@
       // rest/spread support, but this should work for now.
       var params = _emitParameters(node.parameters?.parameters);
 
-      fun = JS.Fun(
+      fun = js_ast.Fun(
           params,
-          JS.Block([
+          js_ast.Block([
             js.statement('return $newKeyword #(#)',
                 [visitConstructorName(redirect), params])
               ..sourceInformation = _nodeStart(redirect)
           ]));
     } else {
       // Normal factory constructor
-      var body = <JS.Statement>[];
+      var body = <js_ast.Statement>[];
       var init = _emitArgumentInitializers(element, node.parameters);
       if (init != null) body.add(init);
       body.add(_visitStatement(node.body));
 
       var params = _emitParameters(node.parameters?.parameters);
-      fun = JS.Fun(params, JS.Block(body));
+      fun = js_ast.Fun(params, js_ast.Block(body));
     }
 
     _currentFunction = savedFunction;
 
-    return JS.Method(name, fun, isStatic: true)
+    return js_ast.Method(name, fun, isStatic: true)
       ..sourceInformation = _functionEnd(node);
   }
 
@@ -1653,14 +1660,15 @@
   ///       return core.bool.as(this.noSuchMethod(
   ///           new dart.InvocationImpl.new('eatFood', [food])));
   ///     }
-  JS.Method _implementMockMember(ExecutableElement method, InterfaceType type) {
-    var invocationProps = <JS.Property>[];
-    addProperty(String name, JS.Expression value) {
-      invocationProps.add(JS.Property(js.string(name), value));
+  js_ast.Method _implementMockMember(
+      ExecutableElement method, InterfaceType type) {
+    var invocationProps = <js_ast.Property>[];
+    addProperty(String name, js_ast.Expression value) {
+      invocationProps.add(js_ast.Property(js.string(name), value));
     }
 
     var typeParams = _emitTypeFormals(method.type.typeFormals);
-    var fnArgs = List<JS.Parameter>.from(typeParams);
+    var fnArgs = List<js_ast.Parameter>.from(typeParams);
     var args = _emitParametersForElement(method);
     fnArgs.addAll(args);
     var argInit = _emitArgumentInitializers(method);
@@ -1682,12 +1690,12 @@
       // Sort the names to match dart2js order.
       var sortedNames = (namedParameterTypes.keys.toList())..sort();
       var named = sortedNames
-          .map((n) => JS.Property(propertyName(n), JS.Identifier(n)));
-      addProperty('namedArguments', JS.ObjectInitializer(named.toList()));
+          .map((n) => js_ast.Property(propertyName(n), js_ast.Identifier(n)));
+      addProperty('namedArguments', js_ast.ObjectInitializer(named.toList()));
       positionalArgs.removeLast();
     }
     if (typeParams.isNotEmpty) {
-      addProperty('typeArguments', JS.ArrayInitializer(typeParams));
+      addProperty('typeArguments', js_ast.ArrayInitializer(typeParams));
     }
 
     var fnBody =
@@ -1695,19 +1703,19 @@
       runtimeModule,
       _declareMemberName(method),
       args,
-      JS.ObjectInitializer(invocationProps)
+      js_ast.ObjectInitializer(invocationProps)
     ]);
 
     fnBody = _emitCast(method.returnType, fnBody);
 
     var fnBlock = argInit != null
-        ? JS.Block([argInit, fnBody.toReturn()])
+        ? js_ast.Block([argInit, fnBody.toReturn()])
         : fnBody.toReturn().toBlock();
 
-    return JS.Method(
+    return js_ast.Method(
         _declareMemberName(method,
             useExtension: _extensionTypes.isNativeClass(type.element)),
-        JS.Fun(fnArgs, fnBlock),
+        js_ast.Fun(fnArgs, fnBlock),
         isGetter: method is PropertyAccessorElement && method.isGetter,
         isSetter: method is PropertyAccessorElement && method.isSetter,
         isStatic: false);
@@ -1720,23 +1728,25 @@
   /// would end up calling the getter or setter, and one of those might not even
   /// exist, resulting in a runtime error. Even if they did exist, that's the
   /// wrong behavior if a new field was declared.
-  List<JS.Method> _emitVirtualFieldAccessor(VariableDeclaration field) {
+  List<js_ast.Method> _emitVirtualFieldAccessor(VariableDeclaration field) {
     var element = field.declaredElement as FieldElement;
     var virtualField = _classProperties.virtualFields[element];
-    var result = <JS.Method>[];
+    var result = <js_ast.Method>[];
     var name = _declareMemberName(element.getter);
 
     var mocks = _classProperties.mockMembers;
     if (!mocks.containsKey(element.name)) {
       var getter = js.fun('function() { return this[#]; }', [virtualField]);
-      result.add(JS.Method(name, getter, isGetter: true)
+      result.add(js_ast.Method(name, getter, isGetter: true)
         ..sourceInformation = _functionSpan(field.name));
     }
 
     if (!mocks.containsKey(element.name + '=')) {
-      var args = field.isFinal ? [JS.Super(), name] : [JS.This(), virtualField];
+      var args = field.isFinal
+          ? [js_ast.Super(), name]
+          : [js_ast.This(), virtualField];
 
-      JS.Expression value = JS.Identifier('value');
+      js_ast.Expression value = js_ast.Identifier('value');
 
       var setter = element.setter;
       if (setter != null) {
@@ -1749,7 +1759,8 @@
       }
       args.add(value);
 
-      result.add(JS.Method(name, js.fun('function(value) { #[#] = #; }', args),
+      result.add(js_ast.Method(
+          name, js.fun('function(value) { #[#] = #; }', args),
           isSetter: true)
         ..sourceInformation = _functionSpan(field.name));
     }
@@ -1761,7 +1772,7 @@
   /// setter. This is needed because in ES6, if you only override a getter
   /// (alternatively, a setter), then there is an implicit override of the
   /// setter (alternatively, the getter) that does nothing.
-  JS.Method _emitSuperAccessorWrapper(
+  js_ast.Method _emitSuperAccessorWrapper(
       MethodDeclaration member, InterfaceType type) {
     var accessorElement = member.declaredElement as PropertyAccessorElement;
     var field = accessorElement.variable;
@@ -1775,7 +1786,7 @@
           _classProperties.inheritedSetters.contains(field.name)) {
         // Generate a setter that forwards to super.
         var fn = js.fun('function(value) { super[#] = value; }', [name]);
-        return JS.Method(name, fn, isSetter: true);
+        return js_ast.Method(name, fn, isSetter: true);
       }
     } else {
       var getter = field.getter;
@@ -1783,7 +1794,7 @@
           _classProperties.inheritedGetters.contains(field.name)) {
         // Generate a getter that forwards to super.
         var fn = js.fun('function() { return super[#]; }', [name]);
-        return JS.Method(name, fn, isGetter: true);
+        return js_ast.Method(name, fn, isGetter: true);
       }
     }
     return null;
@@ -1800,7 +1811,7 @@
   /// This will return `null` if the adapter was already added on a super type,
   /// otherwise it returns the adapter code.
   // TODO(jmesserly): should we adapt `Iterator` too?
-  JS.Method _emitIterable(InterfaceType t) {
+  js_ast.Method _emitIterable(InterfaceType t) {
     // If a parent had an `iterator` (concrete or abstract) or implements
     // Iterable, we know the adapter is already there, so we can skip it as a
     // simple code size optimization.
@@ -1816,13 +1827,15 @@
 
     // Otherwise, emit the adapter method, which wraps the Dart iterator in
     // an ES6 iterator.
-    return JS.Method(
+    return js_ast.Method(
         js.call('Symbol.iterator'),
-        js.call('function() { return new #.JsIterator(this.#); }',
-            [runtimeModule, _emitMemberName('iterator', type: t)]) as JS.Fun);
+        js.call('function() { return new #.JsIterator(this.#); }', [
+          runtimeModule,
+          _emitMemberName('iterator', type: t)
+        ]) as js_ast.Fun);
   }
 
-  JS.Expression _instantiateAnnotation(Annotation node) {
+  js_ast.Expression _instantiateAnnotation(Annotation node) {
     var element = node.element;
     if (element is ConstructorElement) {
       return _emitInstanceCreationExpression(
@@ -1836,7 +1849,7 @@
   }
 
   void _registerExtensionType(
-      ClassElement classElem, String jsPeerName, List<JS.Statement> body) {
+      ClassElement classElem, String jsPeerName, List<js_ast.Statement> body) {
     var className = _emitTopLevelName(classElem);
     if (jsTypeRep.isPrimitive(classElem.type)) {
       body.add(runtimeStatement(
@@ -1847,18 +1860,18 @@
   }
 
   /// Defines all constructors for this class as ES5 constructors.
-  List<JS.Statement> _defineConstructors(
+  List<js_ast.Statement> _defineConstructors(
       ClassElement classElem,
-      JS.Expression className,
+      js_ast.Expression className,
       Map<Element, Declaration> memberMap,
       Declaration classNode) {
-    var body = <JS.Statement>[];
+    var body = <js_ast.Statement>[];
     if (classElem.isMixinApplication) {
       // We already handled this when we defined the class.
       return body;
     }
 
-    addConstructor(String name, JS.Expression jsCtor) {
+    addConstructor(String name, js_ast.Expression jsCtor) {
       body.add(_addConstructorToClass(classElem, className, name, jsCtor));
     }
 
@@ -1878,12 +1891,12 @@
       assert(classElem.constructors.length == 1,
           'default constructor only if no other constructors');
       var superCall = _emitSuperConstructorCallIfNeeded(classElem, className);
-      var ctorBody = <JS.Statement>[_initializeFields(fields)];
+      var ctorBody = <js_ast.Statement>[_initializeFields(fields)];
       if (superCall != null) ctorBody.add(superCall);
 
       addConstructor(
           '',
-          JS.Fun([], JS.Block(ctorBody))
+          js_ast.Fun([], js_ast.Block(ctorBody))
             ..sourceInformation = _functionEnd(classNode));
       return body;
     }
@@ -1923,8 +1936,8 @@
             c.isSynthetic && c.name != '' || c.isFactory || c.isExternal);
   }
 
-  JS.Statement _addConstructorToClass(ClassElement c, JS.Expression className,
-      String name, JS.Expression jsCtor) {
+  js_ast.Statement _addConstructorToClass(ClassElement c,
+      js_ast.Expression className, String name, js_ast.Expression jsCtor) {
     jsCtor = defineValueOnClass(c, className, _constructorName(name), jsCtor);
     return js.statement('#.prototype = #.prototype;', [jsCtor, className]);
   }
@@ -1951,22 +1964,22 @@
   /// Emits static fields for a class, and initialize them eagerly if possible,
   /// otherwise define them as lazy properties.
   void _emitStaticFields(ClassElement classElem,
-      Map<Element, Declaration> members, List<JS.Statement> body) {
+      Map<Element, Declaration> members, List<js_ast.Statement> body) {
     if (classElem.isEnum) {
       // Emit enum static fields
       var type = classElem.type;
-      void addField(FieldElement e, JS.Expression value) {
+      void addField(FieldElement e, js_ast.Expression value) {
         body.add(defineValueOnClass(classElem, _emitStaticClassName(e),
                 _declareMemberName(e.getter), value)
             .toStatement());
       }
 
       int index = 0;
-      var values = <JS.Expression>[];
+      var values = <js_ast.Expression>[];
       for (var f in classElem.fields) {
         if (f.type != type) continue;
         // static const E id_i = const E(i);
-        values.add(JS.PropertyAccess(
+        values.add(js_ast.PropertyAccess(
             _emitStaticClassName(f), _declareMemberName(f.getter)));
         var enumValue = runtimeCall('const(new (#.#)(#))', [
           emitConstructorAccess(type),
@@ -1993,8 +2006,8 @@
     }
   }
 
-  void _emitClassMetadata(List<Annotation> metadata, JS.Expression className,
-      List<JS.Statement> body) {
+  void _emitClassMetadata(List<Annotation> metadata,
+      js_ast.Expression className, List<js_ast.Statement> body) {
     // Metadata
     if (options.emitMetadata && metadata.isNotEmpty) {
       body.add(js.statement('#[#.metadata] = () => [#];',
@@ -2019,18 +2032,18 @@
   /// If a concrete class implements one of our extensions, we might need to
   /// add forwarders.
   void _defineExtensionMembers(
-      JS.Expression className, List<JS.Statement> body) {
+      js_ast.Expression className, List<js_ast.Statement> body) {
     void emitExtensions(String helperName, Iterable<String> extensions) {
       if (extensions.isEmpty) return;
 
       var names = extensions
-          .map((e) => propertyName(JS.memberNameForDartMember(e)))
+          .map((e) => propertyName(js_ast.memberNameForDartMember(e)))
           .toList();
       body.add(js.statement('#.#(#, #);', [
         runtimeModule,
         helperName,
         className,
-        JS.ArrayInitializer(names, multiline: names.length > 4)
+        js_ast.ArrayInitializer(names, multiline: names.length > 4)
       ]));
     }
 
@@ -2040,8 +2053,8 @@
   }
 
   /// Emit the signature on the class recording the runtime type information
-  void _emitClassSignature(ClassElement classElem, JS.Expression className,
-      Map<Element, Declaration> annotatedMembers, List<JS.Statement> body) {
+  void _emitClassSignature(ClassElement classElem, js_ast.Expression className,
+      Map<Element, Declaration> annotatedMembers, List<js_ast.Statement> body) {
     if (classElem.interfaces.isNotEmpty ||
         classElem.superclassConstraints.isNotEmpty) {
       var interfaces = classElem.interfaces.toList()
@@ -2051,18 +2064,18 @@
           [className, runtimeModule, interfaces.map(_emitType)]));
     }
 
-    void emitSignature(String name, List<JS.Property> elements) {
+    void emitSignature(String name, List<js_ast.Property> elements) {
       if (elements.isEmpty) return;
 
       if (!name.startsWith('Static')) {
         var proto = classElem.type.isObject
             ? js.call('Object.create(null)')
             : runtimeCall('get${name}s(#.__proto__)', [className]);
-        elements.insert(0, JS.Property(propertyName('__proto__'), proto));
+        elements.insert(0, js_ast.Property(propertyName('__proto__'), proto));
       }
       body.add(runtimeStatement('set${name}Signature(#, () => #)', [
         className,
-        JS.ObjectInitializer(elements, multiline: elements.length > 1)
+        js_ast.ObjectInitializer(elements, multiline: elements.length > 1)
       ]));
     }
 
@@ -2070,8 +2083,8 @@
 
     {
       var extMembers = _classProperties.extensionMethods;
-      var staticMethods = <JS.Property>[];
-      var instanceMethods = <JS.Property>[];
+      var staticMethods = <js_ast.Property>[];
+      var instanceMethods = <js_ast.Property>[];
       var classMethods = List.of(classElem.methods.where((m) => !m.isAbstract));
       for (var m in mockMembers.values) {
         if (m is MethodElement) classMethods.add(m);
@@ -2100,13 +2113,13 @@
           var type = _emitAnnotatedFunctionType(
               reifiedType, annotationNode?.metadata,
               parameters: annotationNode?.parameters?.parameters);
-          var property = JS.Property(_declareMemberName(method), type);
+          var property = js_ast.Property(_declareMemberName(method), type);
           if (isStatic) {
             staticMethods.add(property);
           } else {
             instanceMethods.add(property);
             if (extMembers.contains(name)) {
-              instanceMethods.add(JS.Property(
+              instanceMethods.add(js_ast.Property(
                   _declareMemberName(method, useExtension: true), type));
             }
           }
@@ -2119,10 +2132,10 @@
 
     {
       var extMembers = _classProperties.extensionAccessors;
-      var staticGetters = <JS.Property>[];
-      var instanceGetters = <JS.Property>[];
-      var staticSetters = <JS.Property>[];
-      var instanceSetters = <JS.Property>[];
+      var staticGetters = <js_ast.Property>[];
+      var instanceGetters = <js_ast.Property>[];
+      var staticSetters = <js_ast.Property>[];
+      var instanceSetters = <js_ast.Property>[];
 
       var classAccessors = classElem.accessors
           .where((m) => !m.isAbstract && !m.isSynthetic)
@@ -2163,14 +2176,14 @@
                   cacheType: false),
               annotationNode?.metadata);
 
-          var property = JS.Property(_declareMemberName(accessor), type);
+          var property = js_ast.Property(_declareMemberName(accessor), type);
           if (isStatic) {
             (isGetter ? staticGetters : staticSetters).add(property);
           } else {
             var accessors = isGetter ? instanceGetters : instanceSetters;
             accessors.add(property);
             if (extMembers.contains(accessor.variable.name)) {
-              accessors.add(JS.Property(
+              accessors.add(js_ast.Property(
                   _declareMemberName(accessor, useExtension: true), type));
             }
           }
@@ -2187,8 +2200,8 @@
     }
 
     {
-      var instanceFields = <JS.Property>[];
-      var staticFields = <JS.Property>[];
+      var instanceFields = <js_ast.Property>[];
+      var staticFields = <js_ast.Property>[];
 
       for (var field in classElem.fields) {
         if (field.isSynthetic && !classElem.isEnum) continue;
@@ -2205,21 +2218,21 @@
         var fieldSig = _emitFieldSignature(field.type,
             metadata: metadata, isFinal: field.isFinal);
         (isStatic ? staticFields : instanceFields)
-            .add(JS.Property(memberName, fieldSig));
+            .add(js_ast.Property(memberName, fieldSig));
       }
       emitSignature('Field', instanceFields);
       emitSignature('StaticField', staticFields);
     }
 
     if (options.emitMetadata) {
-      var constructors = <JS.Property>[];
+      var constructors = <js_ast.Property>[];
       for (var ctor in classElem.constructors) {
         var annotationNode = annotatedMembers[ctor] as ConstructorDeclaration;
         var memberName = _constructorName(ctor.name);
         var type = _emitAnnotatedFunctionType(
             ctor.type, annotationNode?.metadata,
             parameters: annotationNode?.parameters?.parameters);
-        constructors.add(JS.Property(memberName, type));
+        constructors.add(js_ast.Property(memberName, type));
       }
 
       emitSignature('Constructor', constructors);
@@ -2234,8 +2247,8 @@
     }
   }
 
-  JS.Expression _emitConstructor(ConstructorDeclaration node,
-      List<VariableDeclaration> fields, JS.Expression className) {
+  js_ast.Expression _emitConstructor(ConstructorDeclaration node,
+      List<VariableDeclaration> fields, js_ast.Expression className) {
     var params = _emitParameters(node.parameters?.parameters);
 
     var savedFunction = _currentFunction;
@@ -2247,7 +2260,7 @@
     _superAllowed = savedSuperAllowed;
     _currentFunction = savedFunction;
 
-    return JS.Fun(params, body)..sourceInformation = _functionEnd(node);
+    return js_ast.Fun(params, body)..sourceInformation = _functionEnd(node);
   }
 
   FunctionType _getMemberRuntimeType(ExecutableElement element) {
@@ -2273,7 +2286,7 @@
     return function.type = FunctionTypeImpl(function);
   }
 
-  JS.Expression _constructorName(String name) {
+  js_ast.Expression _constructorName(String name) {
     if (name == '') {
       // Default constructors (factory or not) use `new` as their name.
       return propertyName('new');
@@ -2281,9 +2294,9 @@
     return _emitStaticMemberName(name);
   }
 
-  JS.Block _emitConstructorBody(ConstructorDeclaration node,
-      List<VariableDeclaration> fields, JS.Expression className) {
-    var body = <JS.Statement>[];
+  js_ast.Block _emitConstructorBody(ConstructorDeclaration node,
+      List<VariableDeclaration> fields, js_ast.Expression className) {
+    var body = <js_ast.Statement>[];
     var cls = node.parent as ClassDeclaration;
 
     // Generate optional/named argument value assignment. These can not have
@@ -2299,7 +2312,7 @@
     for (var init in node.initializers) {
       if (init is RedirectingConstructorInvocation) {
         body.add(_emitRedirectingConstructor(init, className));
-        return JS.Block(body);
+        return js_ast.Block(body);
       }
     }
 
@@ -2326,11 +2339,11 @@
     }
 
     body.add(_emitFunctionScopedBody(node.body, node.declaredElement));
-    return JS.Block(body);
+    return js_ast.Block(body);
   }
 
-  JS.Statement _emitRedirectingConstructor(
-      RedirectingConstructorInvocation node, JS.Expression className) {
+  js_ast.Statement _emitRedirectingConstructor(
+      RedirectingConstructorInvocation node, js_ast.Expression className) {
     var ctor = node.staticElement;
     // We can't dispatch to the constructor with `this.new` as that might hit a
     // derived class constructor with the same name.
@@ -2341,9 +2354,9 @@
     ]);
   }
 
-  JS.Statement _emitSuperConstructorCallIfNeeded(
-      ClassElement element, JS.Expression className,
-      [ConstructorElement superCtor, List<JS.Expression> args]) {
+  js_ast.Statement _emitSuperConstructorCallIfNeeded(
+      ClassElement element, js_ast.Expression className,
+      [ConstructorElement superCtor, List<js_ast.Expression> args]) {
     // Get the supertype's unnamed constructor.
     superCtor ??= element.supertype?.element?.unnamedConstructor;
     if (superCtor == null) {
@@ -2362,8 +2375,8 @@
     return _emitSuperConstructorCall(className, superCtor.name, args);
   }
 
-  JS.Statement _emitSuperConstructorCall(
-      JS.Expression className, String name, List<JS.Expression> args) {
+  js_ast.Statement _emitSuperConstructorCall(
+      js_ast.Expression className, String name, List<js_ast.Expression> args) {
     return js.statement('#.__proto__.#.call(this, #);',
         [className, _constructorName(name), args ?? []]);
   }
@@ -2393,7 +2406,7 @@
   ///   2. field initializing parameters,
   ///   3. constructor field initializers,
   ///   4. initialize fields not covered in 1-3
-  JS.Statement _initializeFields(List<VariableDeclaration> fieldDecls,
+  js_ast.Statement _initializeFields(List<VariableDeclaration> fieldDecls,
       [ConstructorDeclaration ctor]) {
     Set<FieldElement> ctorFields;
     emitFieldInit(FieldElement f, Expression initializer, AstNode hoverInfo) {
@@ -2407,7 +2420,7 @@
           .toStatement();
     }
 
-    var body = <JS.Statement>[];
+    var body = <js_ast.Statement>[];
     if (ctor != null) {
       ctorFields = HashSet<FieldElement>();
 
@@ -2437,7 +2450,7 @@
     // (for example, it's a literal value such as implicit `null`) and where
     // there's another explicit initialization (either in the initializer list
     // like `field = value`, or via a `this.field` parameter).
-    var fieldInit = <JS.Statement>[];
+    var fieldInit = <js_ast.Statement>[];
     for (var field in fieldDecls) {
       var f = field.declaredElement as FieldElement;
       if (f.isStatic) continue;
@@ -2450,14 +2463,14 @@
     }
     // Run field initializers before the other ones.
     fieldInit.addAll(body);
-    return JS.Statement.from(fieldInit);
+    return js_ast.Statement.from(fieldInit);
   }
 
   /// Emits argument initializers, which handles optional/named args, as well
   /// as generic type checks needed due to our covariance.
-  JS.Statement _emitArgumentInitializers(ExecutableElement element,
+  js_ast.Statement _emitArgumentInitializers(ExecutableElement element,
       [FormalParameterList parameterNodes]) {
-    var body = <JS.Statement>[];
+    var body = <js_ast.Statement>[];
 
     _emitCovarianceBoundsCheck(
         element.typeParameters, _classProperties?.covariantParameters, body);
@@ -2471,13 +2484,13 @@
       }
 
       if (param.isOptional) {
-        JS.Expression defaultValue;
+        js_ast.Expression defaultValue;
         if (findAnnotation(param, isUndefinedAnnotation) != null) {
           defaultValue = null;
         } else if (paramNode != null) {
           var paramDefault = (paramNode as DefaultFormalParameter).defaultValue;
           if (paramDefault == null) {
-            defaultValue = JS.LiteralNull();
+            defaultValue = js_ast.LiteralNull();
           } else {
             defaultValue = _visitExpression(paramDefault);
           }
@@ -2528,7 +2541,7 @@
         body.add(_nullParameterCheck(jsParam));
       }
     }
-    return body.isEmpty ? null : JS.Statement.from(body);
+    return body.isEmpty ? null : js_ast.Statement.from(body);
   }
 
   bool _isCovariant(ParameterElement p) {
@@ -2536,26 +2549,27 @@
         (_classProperties?.covariantParameters?.contains(p) ?? false);
   }
 
-  JS.Fun _emitNativeFunctionBody(MethodDeclaration node) {
+  js_ast.Fun _emitNativeFunctionBody(MethodDeclaration node) {
     String name = getAnnotationName(node.declaredElement, isJSAnnotation) ??
         node.name.name;
     if (node.isGetter) {
-      return JS.Fun([], js.block('{ return this.#; }', [name]));
+      return js_ast.Fun([], js.block('{ return this.#; }', [name]));
     } else if (node.isSetter) {
       var params = _emitParameters(node.parameters?.parameters);
-      return JS.Fun(params, js.block('{ this.# = #; }', [name, params.last]));
+      return js_ast.Fun(
+          params, js.block('{ this.# = #; }', [name, params.last]));
     } else {
       return js.fun(
           'function (...args) { return this.#.apply(this, args); }', name);
     }
   }
 
-  JS.Method _emitMethodDeclaration(MethodDeclaration node) {
+  js_ast.Method _emitMethodDeclaration(MethodDeclaration node) {
     if (node.isAbstract) {
       return null;
     }
 
-    JS.Fun fn;
+    js_ast.Fun fn;
     if (node.externalKeyword != null || node.body is NativeFunctionBody) {
       if (node.isStatic) {
         // TODO(vsm): Do we need to handle this case?
@@ -2566,7 +2580,7 @@
       fn = _emitFunction(node.declaredElement, node.parameters, node.body);
     }
 
-    return JS.Method(_declareMemberName(node.declaredElement), fn,
+    return js_ast.Method(_declareMemberName(node.declaredElement), fn,
         isGetter: node.isGetter,
         isSetter: node.isSetter,
         isStatic: node.isStatic)
@@ -2574,7 +2588,7 @@
   }
 
   @override
-  JS.Statement visitFunctionDeclaration(FunctionDeclaration node) {
+  js_ast.Statement visitFunctionDeclaration(FunctionDeclaration node) {
     assert(node.parent is CompilationUnit);
 
     if (node.externalKeyword != null ||
@@ -2589,7 +2603,7 @@
           : element.correspondingGetter;
 
       var jsCode = _emitTopLevelProperty(node);
-      var props = <JS.Method>[jsCode];
+      var props = <js_ast.Method>[jsCode];
       if (pairAccessor != null) {
         // If we have a getter/setter pair, they need to be defined together.
         // If this is the first one, save the generated code for later.
@@ -2605,12 +2619,12 @@
           'copyProperties(#, { # })', [emitLibraryName(currentLibrary), props]);
     }
 
-    var body = <JS.Statement>[];
+    var body = <js_ast.Statement>[];
     var fn = _emitFunctionExpression(node.functionExpression);
 
     if (currentLibrary.source.isInSystemLibrary &&
         _isInlineJSFunction(node.functionExpression)) {
-      fn = JS.simplifyPassThroughArrowFunCallBody(fn);
+      fn = js_ast.simplifyPassThroughArrowFunCallBody(fn);
     }
     fn.sourceInformation = _functionEnd(node);
 
@@ -2626,7 +2640,7 @@
           .toStatement());
     }
 
-    return JS.Statement.from(body);
+    return js_ast.Statement.from(body);
   }
 
   bool _isInlineJSFunction(FunctionExpression functionExpression) {
@@ -2648,9 +2662,9 @@
   bool _isJSInvocation(Expression expr) =>
       expr is MethodInvocation && isInlineJS(expr.methodName.staticElement);
 
-  JS.Method _emitTopLevelProperty(FunctionDeclaration node) {
+  js_ast.Method _emitTopLevelProperty(FunctionDeclaration node) {
     var name = node.name.name;
-    return JS.Method(
+    return js_ast.Method(
         propertyName(name), _emitFunctionExpression(node.functionExpression),
         isGetter: node.isGetter, isSetter: node.isSetter)
       ..sourceInformation = _functionEnd(node);
@@ -2697,7 +2711,7 @@
     return !_declarationNodes.containsKey(type.element);
   }
 
-  JS.Expression _emitFunctionTagged(JS.Expression fn, FunctionType type,
+  js_ast.Expression _emitFunctionTagged(js_ast.Expression fn, FunctionType type,
       {bool topLevel = false}) {
     var lazy = topLevel && !_canEmitTypeAtTopLevel(type);
     var typeRep = _emitFunctionType(type, lazy: lazy);
@@ -2712,7 +2726,7 @@
   ///
   /// Contrast with [_emitFunctionExpression].
   @override
-  JS.Expression visitFunctionExpression(FunctionExpression node) {
+  js_ast.Expression visitFunctionExpression(FunctionExpression node) {
     assert(node.parent is! FunctionDeclaration &&
         node.parent is! MethodDeclaration);
     var fn = _emitArrowFunction(node);
@@ -2721,22 +2735,22 @@
         topLevel: _executesAtTopLevel(node));
   }
 
-  JS.ArrowFun _emitArrowFunction(FunctionExpression node) {
+  js_ast.ArrowFun _emitArrowFunction(FunctionExpression node) {
     var f = _emitFunction(node.declaredElement, node.parameters, node.body);
-    JS.Node body = f.body;
+    js_ast.Node body = f.body;
 
     // Simplify `=> { return e; }` to `=> e`
-    if (body is JS.Block) {
-      var block = body as JS.Block;
+    if (body is js_ast.Block) {
+      var block = body as js_ast.Block;
       if (block.statements.length == 1) {
-        JS.Statement s = block.statements[0];
-        if (s is JS.Return && s.value != null) body = s.value;
+        js_ast.Statement s = block.statements[0];
+        if (s is js_ast.Return && s.value != null) body = s.value;
       }
     }
 
     // Convert `function(...) { ... }` to `(...) => ...`
     // This is for readability, but it also ensures correct `this` binding.
-    return JS.ArrowFun(f.params, body);
+    return js_ast.ArrowFun(f.params, body);
   }
 
   /// Emits a non-arrow FunctionExpression node.
@@ -2746,11 +2760,11 @@
   /// as methods, properties, and top-level functions.
   ///
   /// Contrast with [visitFunctionExpression].
-  JS.Fun _emitFunctionExpression(FunctionExpression node) {
+  js_ast.Fun _emitFunctionExpression(FunctionExpression node) {
     return _emitFunction(node.declaredElement, node.parameters, node.body);
   }
 
-  JS.Fun _emitFunction(ExecutableElement element,
+  js_ast.Fun _emitFunction(ExecutableElement element,
       FormalParameterList parameters, FunctionBody body) {
     FunctionType type = element.type;
 
@@ -2766,19 +2780,19 @@
         () => isPotentiallyMutated(
             body, parameters.parameters.last.declaredElement));
 
-    JS.Block code = isSync
+    js_ast.Block code = isSync
         ? _emitSyncFunctionBody(element, parameters, body)
         : _emitGeneratorFunctionBody(element, parameters, body);
 
     code = super.exitFunction(element.name, formals, code);
-    return JS.Fun(formals, code);
+    return js_ast.Fun(formals, code);
   }
 
   /// Emits a `sync` function body (the default in Dart)
   ///
   /// To emit an `async`, `sync*`, or `async*` function body, use
   /// [_emitGeneratorFunctionBody] instead.
-  JS.Block _emitSyncFunctionBody(ExecutableElement element,
+  js_ast.Block _emitSyncFunctionBody(ExecutableElement element,
       FormalParameterList parameters, FunctionBody body) {
     var savedFunction = _currentFunction;
     _currentFunction = body;
@@ -2786,7 +2800,7 @@
     var initArgs = _emitArgumentInitializers(element, parameters);
     var block = _emitFunctionScopedBody(body, element);
 
-    if (initArgs != null) block = JS.Block([initArgs, block]);
+    if (initArgs != null) block = js_ast.Block([initArgs, block]);
 
     _currentFunction = savedFunction;
 
@@ -2794,7 +2808,7 @@
       // TODO(jmesserly: JS AST printer does not understand the need to emit a
       // nested scoped block in a JS function. So we need to add a non-scoped
       // wrapper to ensure it gets printed.
-      block = JS.Block([block]);
+      block = js_ast.Block([block]);
     }
     return block;
   }
@@ -2810,17 +2824,17 @@
   ///
   /// To emit a `sync` function body (the default in Dart), use
   /// [_emitSyncFunctionBody] instead.
-  JS.Block _emitGeneratorFunctionBody(ExecutableElement element,
+  js_ast.Block _emitGeneratorFunctionBody(ExecutableElement element,
       FormalParameterList parameters, FunctionBody body) {
     var savedFunction = _currentFunction;
     _currentFunction = body;
 
     var initArgs = _emitArgumentInitializers(element, parameters);
-    var block = JS.Block([
+    var block = js_ast.Block([
       _emitGeneratorFunction(element, parameters, body).toReturn()
         ..sourceInformation = _nodeStart(body)
     ]);
-    if (initArgs != null) block = JS.Block([initArgs, block]);
+    if (initArgs != null) block = js_ast.Block([initArgs, block]);
 
     _currentFunction = savedFunction;
 
@@ -2828,14 +2842,14 @@
       // TODO(jmesserly: JS AST printer does not understand the need to emit a
       // nested scoped block in a JS function. So we need to add a non-scoped
       // wrapper to ensure it gets printed.
-      block = JS.Block([block]);
+      block = js_ast.Block([block]);
     }
     return block;
   }
 
-  JS.Block _emitFunctionScopedBody(
+  js_ast.Block _emitFunctionScopedBody(
       FunctionBody body, ExecutableElement element) {
-    var block = body.accept(this) as JS.Block;
+    var block = body.accept(this) as js_ast.Block;
     if (element.parameters.isNotEmpty) {
       // Handle shadowing of parameters by local variables, which is allowed in
       // Dart but not in JS.
@@ -2852,7 +2866,7 @@
   }
 
   void _emitCovarianceBoundsCheck(List<TypeParameterElement> typeFormals,
-      Set<Element> covariantParams, List<JS.Statement> body) {
+      Set<Element> covariantParams, List<js_ast.Statement> body) {
     if (covariantParams == null) return;
     for (var t in typeFormals) {
       t = covariantParams.lookup(t) as TypeParameterElement;
@@ -2863,14 +2877,15 @@
     }
   }
 
-  JS.Expression _emitGeneratorFunction(ExecutableElement element,
+  js_ast.Expression _emitGeneratorFunction(ExecutableElement element,
       FormalParameterList parameters, FunctionBody body) {
     // Transforms `sync*` `async` and `async*` function bodies
     // using ES6 generators.
 
     var returnType = _getExpectedReturnType(element);
 
-    emitGeneratorFn(List<JS.Parameter> jsParams, [JS.TemporaryId asyncStar]) {
+    emitGeneratorFn(List<js_ast.Parameter> jsParams,
+        [js_ast.TemporaryId asyncStar]) {
       var savedSuperAllowed = _superAllowed;
       var savedController = _asyncStarController;
       _superAllowed = false;
@@ -2885,14 +2900,15 @@
       var jsBody = _emitFunctionScopedBody(body, element);
       _currentFunction = savedFunction;
 
-      var genFn = JS.Fun(jsParams, jsBody, isGenerator: true);
+      var genFn = js_ast.Fun(jsParams, jsBody, isGenerator: true);
 
       // Name the function if possible, to get better stack traces.
       var name = element.name;
-      JS.Expression gen = genFn;
+      js_ast.Expression gen = genFn;
       if (name.isNotEmpty) {
-        gen = JS.NamedFunction(
-            JS.TemporaryId(JS.friendlyNameForDartOperator[name] ?? name),
+        gen = js_ast.NamedFunction(
+            js_ast.TemporaryId(
+                js_ast.friendlyNameForDartOperator[name] ?? name),
             genFn);
       }
       gen.sourceInformation = _functionEnd(body);
@@ -2943,7 +2959,7 @@
       // `await` is generated as `yield`.
       //
       // _AsyncStarImpl has an example of the generated code.
-      var asyncStarParam = JS.TemporaryId('stream');
+      var asyncStarParam = js_ast.TemporaryId('stream');
       var gen = emitGeneratorFn([asyncStarParam], asyncStarParam);
 
       var asyncStarImpl = asyncStarImplType.instantiate([returnType]);
@@ -2966,7 +2982,7 @@
   }
 
   @override
-  JS.Statement visitFunctionDeclarationStatement(
+  js_ast.Statement visitFunctionDeclarationStatement(
       FunctionDeclarationStatement node) {
     var func = node.functionDeclaration;
     if (func.isGetter || func.isSetter) {
@@ -2975,11 +2991,11 @@
 
     var fn = _emitFunctionExpression(func.functionExpression);
     var name = _emitVariableDef(func.name);
-    JS.Statement declareFn;
+    js_ast.Statement declareFn;
     declareFn = toBoundFunctionStatement(fn, name);
     var element = func.declaredElement;
     if (_reifyFunctionType(element)) {
-      declareFn = JS.Block(
+      declareFn = js_ast.Block(
           [declareFn, _emitFunctionTagged(name, element.type).toStatement()]);
     }
     return declareFn;
@@ -2988,15 +3004,15 @@
   /// Emits a simple identifier, including handling an inferred generic
   /// function instantiation.
   @override
-  JS.Expression visitSimpleIdentifier(SimpleIdentifier node,
+  js_ast.Expression visitSimpleIdentifier(SimpleIdentifier node,
       [PrefixedIdentifier prefix]) {
     var typeArgs = _getTypeArgs(node.staticElement, node.staticType);
     var simpleId = _emitSimpleIdentifier(node, prefix)
       ..sourceInformation = _nodeSpan(node);
     if (prefix != null &&
         // Check that the JS AST is for a Dart property and not JS interop.
-        simpleId is JS.PropertyAccess &&
-        simpleId.receiver is JS.Identifier) {
+        simpleId is js_ast.PropertyAccess &&
+        simpleId.receiver is js_ast.Identifier) {
       // Attach the span to the library prefix.
       simpleId.receiver.sourceInformation = _nodeSpan(prefix.prefix);
     }
@@ -3007,7 +3023,7 @@
   /// Emits a simple identifier, handling implicit `this` as well as
   /// going through the qualified library name if necessary, but *not* handling
   /// inferred generic function instantiation.
-  JS.Expression _emitSimpleIdentifier(SimpleIdentifier node,
+  js_ast.Expression _emitSimpleIdentifier(SimpleIdentifier node,
       [PrefixedIdentifier prefix]) {
     var accessor = resolutionMap.staticElementForIdentifier(node);
     if (accessor == null) {
@@ -3074,10 +3090,11 @@
       return _emitParameter(element);
     }
 
-    return JS.Identifier(element.name);
+    return js_ast.Identifier(element.name);
   }
 
-  JS.Expression _emitLibraryMemberElement(Element element, Expression node) {
+  js_ast.Expression _emitLibraryMemberElement(
+      Element element, Expression node) {
     var result = _emitTopLevelName(element);
     if (element is FunctionElement && _reifyTearoff(element, node)) {
       return _emitFunctionTagged(result, element.type);
@@ -3085,7 +3102,7 @@
     return result;
   }
 
-  JS.Expression _emitClassMemberElement(
+  js_ast.Expression _emitClassMemberElement(
       ClassMemberElement element, Element accessor, Expression node) {
     bool isStatic = element.isStatic;
     var classElem = element.enclosingElement;
@@ -3095,22 +3112,22 @@
 
     // For instance members, we add implicit-this.
     // For method tear-offs, we ensure it's a bound method.
-    var target = isStatic ? _emitStaticClassName(element) : JS.This();
+    var target = isStatic ? _emitStaticClassName(element) : js_ast.This();
     if (element is MethodElement && _reifyTearoff(element, node)) {
       if (isStatic) {
         // TODO(jmesserly): we could tag static/top-level function types once
         // in the module initialization, rather than at the point where they
         // escape.
         return _emitFunctionTagged(
-            JS.PropertyAccess(target, member), element.type);
+            js_ast.PropertyAccess(target, member), element.type);
       }
       return runtimeCall('bind(#, #)', [target, member]);
     }
-    return JS.PropertyAccess(target, member);
+    return js_ast.PropertyAccess(target, member);
   }
 
-  JS.Identifier _emitVariableDef(SimpleIdentifier id) {
-    return JS.Identifier(id.name)..sourceInformation = _nodeStart(id);
+  js_ast.Identifier _emitVariableDef(SimpleIdentifier id) {
+    return js_ast.Identifier(id.name)..sourceInformation = _nodeStart(id);
   }
 
   /// Returns `true` if the type name referred to by [node] is used in a
@@ -3139,7 +3156,7 @@
     return true;
   }
 
-  JS.Identifier _emitParameter(ParameterElement element,
+  js_ast.Identifier _emitParameter(ParameterElement element,
       {bool declaration = false}) {
     // initializing formal parameter, e.g. `Point(this._x)`
     // TODO(jmesserly): type ref is not attached in this case.
@@ -3148,10 +3165,10 @@
       /// The renamer would handle this, but it would prefer to rename the
       /// temporary used for the private symbol. Instead rename the parameter.
       return _initializingFormalTemps.putIfAbsent(
-          element, () => JS.TemporaryId(element.name.substring(1)));
+          element, () => js_ast.TemporaryId(element.name.substring(1)));
     }
 
-    return JS.Identifier(element.name);
+    return js_ast.Identifier(element.name);
   }
 
   List<Annotation> _parameterMetadata(FormalParameter p) =>
@@ -3161,52 +3178,52 @@
 
   // Wrap a result - usually a type - with its metadata.  The runtime is
   // responsible for unpacking this.
-  JS.Expression _emitAnnotatedResult(
-      JS.Expression result, List<Annotation> metadata) {
+  js_ast.Expression _emitAnnotatedResult(
+      js_ast.Expression result, List<Annotation> metadata) {
     if (options.emitMetadata && metadata != null && metadata.isNotEmpty) {
-      result = JS.ArrayInitializer(
+      result = js_ast.ArrayInitializer(
           [result]..addAll(metadata.map(_instantiateAnnotation)));
     }
     return result;
   }
 
-  JS.Expression _emitFieldSignature(DartType type,
+  js_ast.Expression _emitFieldSignature(DartType type,
       {List<Annotation> metadata, bool isFinal = true}) {
     var args = [_emitType(type)];
     if (options.emitMetadata && metadata != null && metadata.isNotEmpty) {
-      args.add(
-          JS.ArrayInitializer(metadata.map(_instantiateAnnotation).toList()));
+      args.add(js_ast.ArrayInitializer(
+          metadata.map(_instantiateAnnotation).toList()));
     }
     return runtimeCall(isFinal ? 'finalFieldType(#)' : 'fieldType(#)', [args]);
   }
 
-  JS.ArrayInitializer _emitTypeNames(
+  js_ast.ArrayInitializer _emitTypeNames(
       List<DartType> types, List<FormalParameter> parameters,
       {bool cacheType = true}) {
-    var result = <JS.Expression>[];
+    var result = <js_ast.Expression>[];
     for (int i = 0; i < types.length; ++i) {
       var metadata =
           parameters != null ? _parameterMetadata(parameters[i]) : null;
       var typeName = _emitType(types[i], cacheType: cacheType);
       result.add(_emitAnnotatedResult(typeName, metadata));
     }
-    return JS.ArrayInitializer(result);
+    return js_ast.ArrayInitializer(result);
   }
 
-  JS.ObjectInitializer _emitTypeProperties(Map<String, DartType> types,
+  js_ast.ObjectInitializer _emitTypeProperties(Map<String, DartType> types,
       {bool cacheType = true}) {
-    var properties = <JS.Property>[];
+    var properties = <js_ast.Property>[];
     types.forEach((name, type) {
       var key = propertyName(name);
       var value = _emitType(type, cacheType: cacheType);
-      properties.add(JS.Property(key, value));
+      properties.add(js_ast.Property(key, value));
     });
-    return JS.ObjectInitializer(properties);
+    return js_ast.ObjectInitializer(properties);
   }
 
   /// Emit the pieces of a function type, as an array of return type,
   /// regular args, and optional/named args.
-  JS.Expression _emitFunctionType(FunctionType type,
+  js_ast.Expression _emitFunctionType(FunctionType type,
       {List<FormalParameter> parameters,
       bool cacheType = true,
       bool lazy = false}) {
@@ -3217,7 +3234,7 @@
 
     var ra = _emitTypeNames(parameterTypes, parameters, cacheType: cacheType);
 
-    List<JS.Expression> typeParts;
+    List<js_ast.Expression> typeParts;
     if (namedTypes.isNotEmpty) {
       assert(optionalTypes.isEmpty);
       // TODO(vsm): Pass in annotations here as well.
@@ -3233,13 +3250,13 @@
       typeParts = [rt, ra];
     }
 
-    JS.Expression fullType;
+    js_ast.Expression fullType;
     String helperCall;
     var typeFormals = type.typeFormals;
     if (typeFormals.isNotEmpty) {
       var tf = _emitTypeFormals(typeFormals);
 
-      addTypeFormalsAsParameters(List<JS.Expression> elements) {
+      addTypeFormalsAsParameters(List<js_ast.Expression> elements) {
         var names = _typeTable.discharge(typeFormals);
         return names.isEmpty
             ? js.call('(#) => [#]', [tf, elements])
@@ -3264,7 +3281,7 @@
     return _typeTable.nameFunctionType(type, fullType, lazy: lazy);
   }
 
-  JS.Expression _emitAnnotatedFunctionType(
+  js_ast.Expression _emitAnnotatedFunctionType(
       FunctionType type, List<Annotation> metadata,
       {List<FormalParameter> parameters}) {
     var result =
@@ -3273,7 +3290,7 @@
   }
 
   @override
-  JS.Expression emitConstructorAccess(DartType type) {
+  js_ast.Expression emitConstructorAccess(DartType type) {
     return _emitJSInterop(type.element) ?? _emitType(type);
   }
 
@@ -3282,7 +3299,7 @@
   /// Typically this is equivalent to [_declareBeforeUse] followed by
   /// [_emitTopLevelName] on the class, but if the member is external, then the
   /// native class name will be used, for direct access to the native member.
-  JS.Expression _emitStaticClassName(ClassMemberElement member) {
+  js_ast.Expression _emitStaticClassName(ClassMemberElement member) {
     var c = member.enclosingElement;
     _declareBeforeUse(c);
 
@@ -3301,7 +3318,7 @@
   /// Emits a Dart [type] into code.
   ///
   /// If [cacheType] is true, then the type will be cached for the module.
-  JS.Expression _emitType(DartType type, {bool cacheType = true}) {
+  js_ast.Expression _emitType(DartType type, {bool cacheType = true}) {
     // The void and dynamic types are not defined in core.
     if (type.isVoid) {
       return runtimeCall('void');
@@ -3341,7 +3358,7 @@
 
     var name = type.name;
     if (type is TypeParameterType) {
-      return JS.Identifier(name);
+      return js_ast.Identifier(name);
     }
 
     if (type is ParameterizedType) {
@@ -3349,7 +3366,7 @@
         return _emitFunctionType(type, cacheType: cacheType);
       }
       var args = type.typeArguments;
-      List<JS.Expression> jsArgs;
+      List<js_ast.Expression> jsArgs;
       if (args.any((a) => !a.isDynamic)) {
         jsArgs = args.map((x) => _emitType(x, cacheType: cacheType)).toList();
       }
@@ -3363,23 +3380,23 @@
   }
 
   /// Emits the raw type corresponding to the [element].
-  JS.Expression _emitTypeDefiningElement(TypeDefiningElement e) {
+  js_ast.Expression _emitTypeDefiningElement(TypeDefiningElement e) {
     return _emitType(instantiateElementTypeToBounds(rules, e));
   }
 
-  JS.Expression _emitGenericClassType(
-      ParameterizedType t, List<JS.Expression> typeArgs) {
+  js_ast.Expression _emitGenericClassType(
+      ParameterizedType t, List<js_ast.Expression> typeArgs) {
     var genericName = _emitTopLevelNameNoInterop(t.element, suffix: '\$');
     return js.call('#(#)', [genericName, typeArgs]);
   }
 
-  JS.PropertyAccess _emitTopLevelName(Element e, {String suffix = ''}) {
+  js_ast.PropertyAccess _emitTopLevelName(Element e, {String suffix = ''}) {
     return _emitJSInterop(e) ?? _emitTopLevelNameNoInterop(e, suffix: suffix);
   }
 
-  JS.PropertyAccess _emitTopLevelNameNoInterop(Element e,
+  js_ast.PropertyAccess _emitTopLevelNameNoInterop(Element e,
       {String suffix = ''}) {
-    return JS.PropertyAccess(
+    return js_ast.PropertyAccess(
         emitLibraryName(e.library), _emitTopLevelMemberName(e, suffix: suffix));
   }
 
@@ -3387,13 +3404,13 @@
   ///
   /// NOTE: usually you should use [_emitTopLevelName] instead of this. This
   /// function does not handle JS interop.
-  JS.Expression _emitTopLevelMemberName(Element e, {String suffix = ''}) {
+  js_ast.Expression _emitTopLevelMemberName(Element e, {String suffix = ''}) {
     var name = getJSExportName(e) ?? _getElementName(e);
     return propertyName(name + suffix);
   }
 
   @override
-  JS.Expression visitAssignmentExpression(AssignmentExpression node) {
+  js_ast.Expression visitAssignmentExpression(AssignmentExpression node) {
     var left = node.leftHandSide;
     var right = node.rightHandSide;
     if (node.operator.type == TokenType.EQ) return _emitSet(left, right);
@@ -3403,7 +3420,7 @@
     return _emitOpAssign(left, right, op, node.staticElement, context: node);
   }
 
-  JS.MetaLet _emitOpAssign(
+  js_ast.MetaLet _emitOpAssign(
       Expression left, Expression right, String op, MethodElement element,
       {Expression context}) {
     if (op == '??') {
@@ -3414,11 +3431,11 @@
 
       // Handle the left hand side, to ensure each of its subexpressions are
       // evaluated only once.
-      var vars = <JS.MetaLetVariable, JS.Expression>{};
+      var vars = <js_ast.MetaLetVariable, js_ast.Expression>{};
       var x = _bindLeftHandSide(vars, left, context: left);
       // Capture the result of evaluating the left hand side in a temp.
       var t = _bindValue(vars, 't', x, context: x);
-      return JS.MetaLet(vars, [
+      return js_ast.MetaLet(vars, [
         js.call('# == null ? # : #',
             [_visitExpression(t), _emitSet(x, right), _visitExpression(t)])
       ]);
@@ -3426,7 +3443,7 @@
 
     // Desugar `x += y` as `x = x + y`, ensuring that if `x` has subexpressions
     // (for example, x is IndexExpression) we evaluate those once.
-    var vars = <JS.MetaLetVariable, JS.Expression>{};
+    var vars = <js_ast.MetaLetVariable, js_ast.Expression>{};
     var lhs = _bindLeftHandSide(vars, left, context: context);
     // TODO(leafp): The element for lhs here will be the setter element
     // instead of the getter element if lhs is a property access. This
@@ -3437,10 +3454,10 @@
 
     var castTo = getImplicitOperationCast(left);
     if (castTo != null) inc = CoercionReifier.castExpression(inc, castTo);
-    return JS.MetaLet(vars, [_emitSet(lhs, inc)]);
+    return js_ast.MetaLet(vars, [_emitSet(lhs, inc)]);
   }
 
-  JS.Expression _emitSet(Expression left, Expression right) {
+  js_ast.Expression _emitSet(Expression left, Expression right) {
     if (left is IndexExpression) {
       var target = _getTarget(left);
       if (_useNativeJsIndexer(target.staticType)) {
@@ -3500,7 +3517,8 @@
   // access to the target expression there (needed for `dart.replNameLookup`).
   String get _replSuffix => options.replCompile ? 'Repl' : '';
 
-  JS.Expression _badAssignment(String problem, Expression lhs, Expression rhs) {
+  js_ast.Expression _badAssignment(
+      String problem, Expression lhs, Expression rhs) {
     // TODO(sra): We should get here only for compiler bugs or weirdness due to
     // --unsafe-force-compile. Once those paths have been addressed, throw at
     // compile time.
@@ -3512,9 +3530,9 @@
   /// Emits assignment to a simple identifier. Handles all legal simple
   /// identifier assignment targets (local, top level library member, implicit
   /// `this` or class, etc.)
-  JS.Expression _emitSetSimpleIdentifier(
+  js_ast.Expression _emitSetSimpleIdentifier(
       SimpleIdentifier node, Expression right) {
-    JS.Expression unimplemented() {
+    js_ast.Expression unimplemented() {
       return _badAssignment("Unimplemented: unknown name '$node'", node, right);
     }
 
@@ -3543,7 +3561,7 @@
     // Unqualified class member. This could mean implicit `this`, or implicit
     // static from the same class.
     if (element is FieldElement) {
-      return _emitSetField(right, element, JS.This(), node);
+      return _emitSetField(right, element, js_ast.This(), node);
     }
 
     // We should not get here.
@@ -3551,41 +3569,42 @@
   }
 
   /// Emits assignment to a simple local variable or parameter.
-  JS.Expression _emitSetLocal(Element element, Expression rhs, AstNode left) {
-    JS.Expression target;
+  js_ast.Expression _emitSetLocal(
+      Element element, Expression rhs, AstNode left) {
+    js_ast.Expression target;
     if (element is TemporaryVariableElement) {
       // If this is one of our compiler's temporary variables, use its JS form.
       target = element.jsVariable;
     } else if (element is ParameterElement) {
       target = _emitParameter(element);
     } else {
-      target = JS.Identifier(element.name);
+      target = js_ast.Identifier(element.name);
     }
     target.sourceInformation = _nodeSpan(left);
     return _visitExpression(rhs).toAssignExpression(target);
   }
 
   /// Emits assignment to library scope element [element].
-  JS.Expression _emitSetTopLevel(
+  js_ast.Expression _emitSetTopLevel(
       PropertyAccessorElement element, Expression rhs) {
     return _visitExpression(rhs).toAssignExpression(_emitTopLevelName(element));
   }
 
   /// Emits assignment to a static field element or property.
-  JS.Expression _emitSetField(Expression right, FieldElement field,
-      JS.Expression jsTarget, SimpleIdentifier id) {
+  js_ast.Expression _emitSetField(Expression right, FieldElement field,
+      js_ast.Expression jsTarget, SimpleIdentifier id) {
     var classElem = field.enclosingElement;
     var isStatic = field.isStatic;
     var member = _emitMemberName(field.name,
         isStatic: isStatic, type: classElem.type, element: field.setter);
     jsTarget = isStatic
-        ? (JS.PropertyAccess(_emitStaticClassName(field), member)
+        ? (js_ast.PropertyAccess(_emitStaticClassName(field), member)
           ..sourceInformation = _nodeSpan(id))
         : _emitTargetAccess(jsTarget, member, field.setter, id);
     return _visitExpression(right).toAssignExpression(jsTarget);
   }
 
-  JS.Expression _emitNullSafeSet(PropertyAccess node, Expression right) {
+  js_ast.Expression _emitNullSafeSet(PropertyAccess node, Expression right) {
     // Emit `obj?.prop = expr` as:
     //
     //     (_ => _ == null ? null : _.prop = expr)(obj).
@@ -3594,31 +3613,32 @@
     //
     // However with MetaLet, we get clean code in statement or void context,
     // or when one of the expressions is stateless, which seems common.
-    var vars = <JS.MetaLetVariable, JS.Expression>{};
+    var vars = <js_ast.MetaLetVariable, js_ast.Expression>{};
     var left = _bindValue(vars, 'l', node.target);
     var body = js.call('# == null ? null : #', [
       _visitExpression(left),
       _emitSet(_stripNullAwareOp(node, left), right)
     ]);
-    return JS.MetaLet(vars, [body]);
+    return js_ast.MetaLet(vars, [body]);
   }
 
   @override
-  JS.Block visitExpressionFunctionBody(ExpressionFunctionBody node) {
-    return JS.Block([_visitExpression(node.expression).toReturn()]);
+  js_ast.Block visitExpressionFunctionBody(ExpressionFunctionBody node) {
+    return js_ast.Block([_visitExpression(node.expression).toReturn()]);
   }
 
   @override
-  JS.Block visitEmptyFunctionBody(EmptyFunctionBody node) => JS.Block([]);
+  js_ast.Block visitEmptyFunctionBody(EmptyFunctionBody node) =>
+      js_ast.Block([]);
 
   @override
-  JS.Block visitBlockFunctionBody(BlockFunctionBody node) {
-    return JS.Block(_visitStatementList(node.block.statements));
+  js_ast.Block visitBlockFunctionBody(BlockFunctionBody node) {
+    return js_ast.Block(_visitStatementList(node.block.statements));
   }
 
   @override
-  JS.Block visitBlock(Block node) =>
-      JS.Block(_visitStatementList(node.statements), isScope: true);
+  js_ast.Block visitBlock(Block node) =>
+      js_ast.Block(_visitStatementList(node.statements), isScope: true);
 
   @override
   visitMethodInvocation(MethodInvocation node) {
@@ -3672,7 +3692,8 @@
     return _emitMethodCall(target, node);
   }
 
-  JS.Expression _emitTarget(Expression target, Element member, bool isStatic) {
+  js_ast.Expression _emitTarget(
+      Expression target, Element member, bool isStatic) {
     if (isStatic) {
       if (member is ConstructorElement) {
         return emitConstructorAccess(member.enclosingElement.type)
@@ -3699,15 +3720,15 @@
     return result;
   }
 
-  /// Emits the [JS.PropertyAccess] for accessors or method calls to
+  /// Emits the [js_ast.PropertyAccess] for accessors or method calls to
   /// [jsTarget].[jsName], replacing `super` if it is not allowed in scope.
-  JS.Expression _emitTargetAccess(JS.Expression jsTarget, JS.Expression jsName,
-      Element member, AstNode node) {
-    JS.Expression result;
-    if (!_superAllowed && jsTarget is JS.Super && member != null) {
+  js_ast.Expression _emitTargetAccess(js_ast.Expression jsTarget,
+      js_ast.Expression jsName, Element member, AstNode node) {
+    js_ast.Expression result;
+    if (!_superAllowed && jsTarget is js_ast.Super && member != null) {
       result = _getSuperHelper(member, jsName);
     } else {
-      result = JS.PropertyAccess(jsTarget, jsName);
+      result = js_ast.PropertyAccess(jsTarget, jsName);
     }
     if (node != null) {
       // Use the full span for a cascade property so we can hover over `bar` in
@@ -3722,7 +3743,7 @@
     return result;
   }
 
-  JS.Expression _getSuperHelper(Element member, JS.Expression jsName) {
+  js_ast.Expression _getSuperHelper(Element member, js_ast.Expression jsName) {
     var jsMethod = _superHelpers.putIfAbsent(member.name, () {
       if (member is PropertyAccessorElement) {
         var isSetter = member.isSetter;
@@ -3731,31 +3752,31 @@
                 ? 'function(x) { super[#] = x; }'
                 : 'function() { return super[#]; }',
             [jsName]);
-        return JS.Method(JS.TemporaryId(member.variable.name), fn,
+        return js_ast.Method(js_ast.TemporaryId(member.variable.name), fn,
             isGetter: !isSetter, isSetter: isSetter);
       } else {
         var method = member as MethodElement;
-        var params =
-            List<JS.Identifier>.from(_emitTypeFormals(method.typeParameters));
+        var params = List<js_ast.Identifier>.from(
+            _emitTypeFormals(method.typeParameters));
         for (var param in method.parameters) {
           if (param.isNamed) {
             params.add(namedArgumentTemp);
             break;
           }
-          params.add(JS.Identifier(param.name));
+          params.add(js_ast.Identifier(param.name));
         }
 
         var fn = js.fun(
             'function(#) { return super[#](#); }', [params, jsName, params]);
         var name = method.name;
-        name = JS.friendlyNameForDartOperator[name] ?? name;
-        return JS.Method(JS.TemporaryId(name), fn);
+        name = js_ast.friendlyNameForDartOperator[name] ?? name;
+        return js_ast.Method(js_ast.TemporaryId(name), fn);
       }
     });
-    return JS.PropertyAccess(JS.This(), jsMethod.name);
+    return js_ast.PropertyAccess(js_ast.This(), jsMethod.name);
   }
 
-  JS.Expression _emitMethodCall(Expression target, MethodInvocation node) {
+  js_ast.Expression _emitMethodCall(Expression target, MethodInvocation node) {
     var argumentList = node.argumentList;
     var args = _emitArgumentList(argumentList);
     var typeArgs = _emitInvokeTypeArguments(node);
@@ -3768,8 +3789,8 @@
         _emitMemberName(name, type: type, isStatic: isStatic, element: element);
 
     if (isDynamicInvoke(target) || isDynamicInvoke(node.methodName)) {
-      JS.Expression jsTarget = _emitTarget(target, element, isStatic);
-      if (jsTarget is JS.Super) {
+      js_ast.Expression jsTarget = _emitTarget(target, element, isStatic);
+      if (jsTarget is js_ast.Super) {
         jsTarget =
             _emitTargetAccess(jsTarget, jsName, element, node.methodName);
         jsName = null;
@@ -3777,7 +3798,7 @@
       return _emitDynamicInvoke(jsTarget, typeArgs, jsName, args, argumentList);
     }
 
-    JS.Expression jsTarget = _emitTarget(target, element, isStatic);
+    js_ast.Expression jsTarget = _emitTarget(target, element, isStatic);
 
     // Handle Object methods that are supported by `null`.
     if (_isObjectMethodCall(name, argumentList.arguments) &&
@@ -3794,7 +3815,7 @@
       if (fromType is InterfaceType) {
         var callName = _getImplicitCallTarget(fromType);
         if (callName != null) {
-          jsTarget = JS.PropertyAccess(jsTarget, callName);
+          jsTarget = js_ast.PropertyAccess(jsTarget, callName);
         }
       }
     }
@@ -3803,14 +3824,14 @@
       jsTarget = _emitCast(castTo, jsTarget);
     }
     if (typeArgs != null) args.insertAll(0, typeArgs);
-    return JS.Call(jsTarget, args);
+    return js_ast.Call(jsTarget, args);
   }
 
-  JS.Expression _emitDynamicInvoke(
-      JS.Expression fn,
-      List<JS.Expression> typeArgs,
-      JS.Expression methodName,
-      List<JS.Expression> args,
+  js_ast.Expression _emitDynamicInvoke(
+      js_ast.Expression fn,
+      List<js_ast.Expression> typeArgs,
+      js_ast.Expression methodName,
+      List<js_ast.Expression> args,
       ArgumentList argumentList) {
     var jsArgs = <Object>[fn];
     String jsCode;
@@ -3856,19 +3877,19 @@
     return !isNullable(left) || !isNullable(right);
   }
 
-  JS.Expression _emitJSDoubleEq(List<JS.Expression> args,
+  js_ast.Expression _emitJSDoubleEq(List<js_ast.Expression> args,
       {bool negated = false}) {
     var op = negated ? '# != #' : '# == #';
     return js.call(op, args);
   }
 
-  JS.Expression _emitJSTripleEq(List<JS.Expression> args,
+  js_ast.Expression _emitJSTripleEq(List<js_ast.Expression> args,
       {bool negated = false}) {
     var op = negated ? '# !== #' : '# === #';
     return js.call(op, args);
   }
 
-  JS.Expression _emitCoreIdenticalCall(List<Expression> arguments,
+  js_ast.Expression _emitCoreIdenticalCall(List<Expression> arguments,
       {bool negated = false}) {
     if (arguments.length != 2) {
       // Shouldn't happen in typechecked code
@@ -3885,12 +3906,13 @@
       return _emitJSDoubleEq(args, negated: negated);
     }
     var code = negated ? '!#' : '#';
-    return js.call(code, JS.Call(_emitTopLevelName(_coreIdentical), args));
+    return js.call(code, js_ast.Call(_emitTopLevelName(_coreIdentical), args));
   }
 
   /// Emits a function call, to a top-level function, local function, or
   /// an expression.
-  JS.Node _emitFunctionCall(InvocationExpression node, [Expression function]) {
+  js_ast.Node _emitFunctionCall(InvocationExpression node,
+      [Expression function]) {
     function ??= node.function;
     var castTo = getImplicitOperationCast(function);
     if (castTo != null) {
@@ -3925,10 +3947,10 @@
       }
     }
 
-    return JS.Call(fn, args);
+    return js_ast.Call(fn, args);
   }
 
-  JS.Node _emitDebuggerCall(InvocationExpression node) {
+  js_ast.Node _emitDebuggerCall(InvocationExpression node) {
     var args = node.argumentList.arguments;
     var isStatement = node.parent is ExpressionStatement;
     if (args.isEmpty) {
@@ -3948,7 +3970,7 @@
     // to decide whether to break or not.
     //
     // We also need to return the value of `when`.
-    var jsArgs = <JS.Property>[];
+    var jsArgs = <js_ast.Property>[];
     var foundWhen = false;
     for (var arg in args) {
       var namedArg = arg as NamedExpression;
@@ -3960,16 +3982,16 @@
         //
         // For a single `message` argument, use `{message: ...}`, which
         // coerces to true (the default value of `when`).
-        ? (foundWhen ? jsArgs[0].value : JS.ObjectInitializer(jsArgs))
+        ? (foundWhen ? jsArgs[0].value : js_ast.ObjectInitializer(jsArgs))
         // If we have both `message` and `when` arguments, evaluate them in
         // order, then extract the `when` argument.
-        : js.call('#.when', JS.ObjectInitializer(jsArgs));
+        : js.call('#.when', js_ast.ObjectInitializer(jsArgs));
     return isStatement
         ? js.statement('if (#) debugger;', when)
         : js.call('# && (() => { debugger; return true })()', when);
   }
 
-  List<JS.Expression> _emitInvokeTypeArguments(InvocationExpression node) {
+  List<js_ast.Expression> _emitInvokeTypeArguments(InvocationExpression node) {
     // add no reify generic check here: if (node.function)
     // node is Identifier
     var function = node.function;
@@ -3982,7 +4004,7 @@
 
   /// If `g` is a generic function type, and `f` is an instantiation of it,
   /// then this will return the type arguments to apply, otherwise null.
-  List<JS.Expression> _emitFunctionTypeArguments(
+  List<js_ast.Expression> _emitFunctionTypeArguments(
       AstNode node, DartType g, DartType f,
       [TypeArgumentList typeArgs]) {
     if (node is InvocationExpression) {
@@ -4030,7 +4052,7 @@
   }
 
   /// Emits code for the `JS(...)` macro.
-  JS.Node _emitForeignJS(MethodInvocation node, Element e) {
+  js_ast.Node _emitForeignJS(MethodInvocation node, Element e) {
     if (!isInlineJS(e)) return null;
 
     var args = node.argumentList.arguments;
@@ -4069,46 +4091,47 @@
     var result = js.parseForeignJS(source).instantiate(jsArgs);
 
     // `throw` is emitted as a statement by `parseForeignJS`.
-    assert(result is JS.Expression ||
-        result is JS.Statement && node.parent is ExpressionStatement);
+    assert(result is js_ast.Expression ||
+        result is js_ast.Statement && node.parent is ExpressionStatement);
     return result;
   }
 
   @override
-  JS.Node visitFunctionExpressionInvocation(
+  js_ast.Node visitFunctionExpressionInvocation(
           FunctionExpressionInvocation node) =>
       _emitFunctionCall(node);
 
-  List<JS.Expression> _emitArgumentList(ArgumentList node) {
-    var args = <JS.Expression>[];
-    var named = <JS.Property>[];
+  List<js_ast.Expression> _emitArgumentList(ArgumentList node) {
+    var args = <js_ast.Expression>[];
+    var named = <js_ast.Property>[];
     for (var arg in node.arguments) {
       if (arg is NamedExpression) {
         named.add(visitNamedExpression(arg));
       } else if (arg is MethodInvocation && isJsSpreadInvocation(arg)) {
-        args.add(JS.Spread(_visitExpression(arg.argumentList.arguments[0])));
+        args.add(
+            js_ast.Spread(_visitExpression(arg.argumentList.arguments[0])));
       } else {
         args.add(_visitExpression(arg));
       }
     }
     if (named.isNotEmpty) {
-      args.add(JS.ObjectInitializer(named));
+      args.add(js_ast.ObjectInitializer(named));
     }
     return args;
   }
 
   @override
-  JS.Property visitNamedExpression(NamedExpression node) {
+  js_ast.Property visitNamedExpression(NamedExpression node) {
     assert(node.parent is ArgumentList);
-    return JS.Property(
+    return js_ast.Property(
         propertyName(node.name.label.name), _visitExpression(node.expression));
   }
 
-  List<JS.Parameter> _emitParametersForElement(ExecutableElement member) {
-    var jsParams = <JS.Identifier>[];
+  List<js_ast.Parameter> _emitParametersForElement(ExecutableElement member) {
+    var jsParams = <js_ast.Identifier>[];
     for (var p in member.parameters) {
       if (p.isPositional) {
-        jsParams.add(JS.Identifier(p.name));
+        jsParams.add(js_ast.Identifier(p.name));
       } else {
         jsParams.add(namedArgumentTemp);
         break;
@@ -4117,10 +4140,10 @@
     return jsParams;
   }
 
-  List<JS.Parameter> _emitParameters(Iterable<FormalParameter> parameters) {
+  List<js_ast.Parameter> _emitParameters(Iterable<FormalParameter> parameters) {
     if (parameters == null) return [];
 
-    var result = <JS.Parameter>[];
+    var result = <js_ast.Parameter>[];
     for (var param in parameters) {
       if (param.isNamed) {
         result.add(namedArgumentTemp);
@@ -4133,19 +4156,19 @@
   }
 
   @override
-  JS.Statement visitExpressionStatement(ExpressionStatement node) =>
+  js_ast.Statement visitExpressionStatement(ExpressionStatement node) =>
       node.expression.accept(this).toStatement();
 
   @override
-  JS.EmptyStatement visitEmptyStatement(EmptyStatement node) =>
-      JS.EmptyStatement();
+  js_ast.EmptyStatement visitEmptyStatement(EmptyStatement node) =>
+      js_ast.EmptyStatement();
 
   @override
-  JS.Statement visitAssertStatement(AssertStatement node) =>
+  js_ast.Statement visitAssertStatement(AssertStatement node) =>
       _emitAssert(node.condition, node.message);
 
-  JS.Statement _emitAssert(Expression condition, Expression message) {
-    if (!options.enableAsserts) return JS.EmptyStatement();
+  js_ast.Statement _emitAssert(Expression condition, Expression message) {
+    if (!options.enableAsserts) return js_ast.EmptyStatement();
     // TODO(jmesserly): only emit in checked mode.
     var conditionType = condition.staticType;
     var jsCondition = _visitExpression(condition);
@@ -4165,7 +4188,7 @@
       jsCondition,
       runtimeModule,
       if (message == null)
-        JS.LiteralNull()
+        js_ast.LiteralNull()
       else
         _visitExpression(message),
       js.escapedString(location.sourceUrl.toString()),
@@ -4177,12 +4200,12 @@
   }
 
   @override
-  JS.Statement visitReturnStatement(ReturnStatement node) {
+  js_ast.Statement visitReturnStatement(ReturnStatement node) {
     return super.emitReturnStatement(_visitExpression(node.expression));
   }
 
   @override
-  JS.Statement visitYieldStatement(YieldStatement node) {
+  js_ast.Statement visitYieldStatement(YieldStatement node) {
     var jsExpr = _visitExpression(node.expression);
     var star = node.star != null;
     if (_asyncStarController != null) {
@@ -4201,7 +4224,7 @@
         _asyncStarController,
         helperName,
         jsExpr,
-        JS.Yield(null)..sourceInformation = _nodeStart(node)
+        js_ast.Yield(null)..sourceInformation = _nodeStart(node)
       ]);
     }
     // A normal yield in a sync*
@@ -4209,8 +4232,8 @@
   }
 
   @override
-  JS.Expression visitAwaitExpression(AwaitExpression node) {
-    return JS.Yield(_visitExpression(node.expression));
+  js_ast.Expression visitAwaitExpression(AwaitExpression node) {
+    return js_ast.Yield(_visitExpression(node.expression));
   }
 
   /// This is not used--we emit top-level fields as we are emitting the
@@ -4228,7 +4251,7 @@
   }
 
   @override
-  JS.Statement visitVariableDeclarationStatement(
+  js_ast.Statement visitVariableDeclarationStatement(
       VariableDeclarationStatement node) {
     // Special case a single variable with an initializer.
     // This helps emit cleaner code for things like:
@@ -4239,7 +4262,7 @@
       var initializer = variable.initializer;
       if (initializer != null) {
         var name = _emitVariableDef(variable.name);
-        JS.Expression value;
+        js_ast.Expression value;
         if (_annotatedNullCheck(variable.declaredElement)) {
           value = notNull(initializer);
         } else if (initializer is FunctionExpression) {
@@ -4253,7 +4276,7 @@
           //     dart.fn(f, typeOfF);
           //
           value = _emitArrowFunction(initializer);
-          return JS.Block([
+          return js_ast.Block([
             value.toVariableDeclaration(name),
             _emitFunctionTagged(
                     name, getStaticType(initializer) as FunctionType,
@@ -4270,15 +4293,16 @@
   }
 
   @override
-  JS.VariableDeclarationList visitVariableDeclarationList(
+  js_ast.VariableDeclarationList visitVariableDeclarationList(
       VariableDeclarationList node) {
     if (node == null) return null;
-    return JS.VariableDeclarationList(
+    return js_ast.VariableDeclarationList(
         'let', node.variables?.map(visitVariableDeclaration)?.toList());
   }
 
   @override
-  JS.VariableInitialization visitVariableDeclaration(VariableDeclaration node) {
+  js_ast.VariableInitialization visitVariableDeclaration(
+      VariableDeclaration node) {
     if (node.declaredElement is PropertyInducingElement) {
       // All fields are handled elsewhere.
       assert(false);
@@ -4286,7 +4310,7 @@
     }
 
     var name = _emitVariableDef(node.name);
-    return JS.VariableInitialization(
+    return js_ast.VariableInitialization(
         name, _visitInitializer(node.initializer, node.declaredElement));
   }
 
@@ -4319,35 +4343,36 @@
     return lazyFields;
   }
 
-  JS.Expression _visitInitializer(Expression init, Element variable) {
+  js_ast.Expression _visitInitializer(Expression init, Element variable) {
     // explicitly initialize to null, to avoid getting `undefined`.
     // TODO(jmesserly): do this only for vars that aren't definitely assigned.
-    if (init == null) return JS.LiteralNull();
+    if (init == null) return js_ast.LiteralNull();
     return _annotatedNullCheck(variable)
         ? notNull(init)
         : _visitExpression(init);
   }
 
-  JS.Statement _emitLazyFields(
-      JS.Expression objExpr,
+  js_ast.Statement _emitLazyFields(
+      js_ast.Expression objExpr,
       List<VariableDeclaration> fields,
-      JS.Expression Function(Element e) emitFieldName) {
-    var accessors = <JS.Method>[];
+      js_ast.Expression Function(Element e) emitFieldName) {
+    var accessors = <js_ast.Method>[];
 
     for (var node in fields) {
       var element = node.declaredElement;
       var access = emitFieldName(element);
-      accessors.add(JS.Method(
+      accessors.add(js_ast.Method(
           access,
           js.call('function() { return #; }',
-              _visitInitializer(node.initializer, element)) as JS.Fun,
+              _visitInitializer(node.initializer, element)) as js_ast.Fun,
           isGetter: true)
         ..sourceInformation =
-            _hoverComment(JS.PropertyAccess(objExpr, access), node.name));
+            _hoverComment(js_ast.PropertyAccess(objExpr, access), node.name));
 
       // TODO(jmesserly): currently uses a dummy setter to indicate writable.
       if (!node.isFinal && !node.isConst) {
-        accessors.add(JS.Method(access, js.call('function(_) {}') as JS.Fun,
+        accessors.add(js_ast.Method(
+            access, js.call('function(_) {}') as js_ast.Fun,
             isSetter: true));
       }
     }
@@ -4355,18 +4380,19 @@
     return runtimeStatement('defineLazy(#, { # })', [objExpr, accessors]);
   }
 
-  JS.Expression _emitConstructorName(DartType type, String name) {
+  js_ast.Expression _emitConstructorName(DartType type, String name) {
     return _emitJSInterop(type.element) ??
-        JS.PropertyAccess(emitConstructorAccess(type), _constructorName(name));
+        js_ast.PropertyAccess(
+            emitConstructorAccess(type), _constructorName(name));
   }
 
   @override
-  JS.Expression visitConstructorName(ConstructorName node) {
+  js_ast.Expression visitConstructorName(ConstructorName node) {
     return _emitConstructorName(node.type.type, node.staticElement.name);
   }
 
-  JS.Expression _emitInstanceCreationExpression(
-      ConstructorElement element, InterfaceType type, List<JS.Expression> args,
+  js_ast.Expression _emitInstanceCreationExpression(ConstructorElement element,
+      InterfaceType type, List<js_ast.Expression> args,
       {bool isConst = false, ConstructorName ctorNode}) {
     if (element == null) {
       return _throwUnsafe('unresolved constructor: ${type?.name ?? '<null>'}'
@@ -4375,10 +4401,12 @@
 
     var classElem = type.element;
     if (_isObjectLiteral(classElem)) {
-      return args.isEmpty ? js.call('{}') : args.single as JS.ObjectInitializer;
+      return args.isEmpty
+          ? js.call('{}')
+          : args.single as js_ast.ObjectInitializer;
     }
 
-    JS.Expression emitNew() {
+    js_ast.Expression emitNew() {
       var name = element.name;
       if (args.isEmpty && classElem.source.isInSystemLibrary) {
         // Skip the slow SDK factory constructors when possible.
@@ -4414,8 +4442,8 @@
       var ctor = _emitConstructorName(type, name);
       if (ctorNode != null) ctor.sourceInformation = _nodeSpan(ctorNode);
       return element.isFactory && !_hasJSInteropAnnotation(classElem)
-          ? JS.Call(ctor, args)
-          : JS.New(ctor, args);
+          ? js_ast.Call(ctor, args)
+          : js_ast.New(ctor, args);
     }
 
     var result = emitNew();
@@ -4443,10 +4471,10 @@
 
   /// If the constant [value] is primitive, directly emit the
   /// corresponding JavaScript.  Otherwise, return null.
-  JS.Expression _emitDartObject(DartObject value,
+  js_ast.Expression _emitDartObject(DartObject value,
       {bool handleUnknown = false}) {
     if (value == null || value.isNull) {
-      return JS.LiteralNull();
+      return js_ast.LiteralNull();
     }
     var type = value.type;
     // Handle unknown value: when the declared variable wasn't found, and no
@@ -4457,7 +4485,7 @@
     // https://api.dartlang.org/stable/1.20.1/dart-core/bool/bool.fromEnvironment.html
     if (!value.hasKnownValue) {
       if (!handleUnknown) return null;
-      return type == types.boolType ? js.boolean(false) : JS.LiteralNull();
+      return type == types.boolType ? js.boolean(false) : js_ast.LiteralNull();
     }
     if (type == types.boolType) {
       return js.boolean(value.toBoolValue());
@@ -4484,7 +4512,7 @@
             value.toListValue().map(_emitDartObject).toList());
       }
       if (type.element == types.mapType.element) {
-        var entries = <JS.Expression>[];
+        var entries = <js_ast.Expression>[];
         value.toMapValue().forEach((key, value) {
           entries.add(_emitDartObject(key));
           entries.add(_emitDartObject(value));
@@ -4506,11 +4534,12 @@
           return _emitClassMemberElement(field, field.getter, null);
         }
         var args = ctor.positionalArguments.map(_emitDartObject).toList();
-        var named = <JS.Property>[];
+        var named = <js_ast.Property>[];
         ctor.namedArguments.forEach((name, value) {
-          named.add(JS.Property(propertyName(name), _emitDartObject(value)));
+          named
+              .add(js_ast.Property(propertyName(name), _emitDartObject(value)));
         });
-        if (named.isNotEmpty) args.add(JS.ObjectInitializer(named));
+        if (named.isNotEmpty) args.add(js_ast.ObjectInitializer(named));
         return _emitInstanceCreationExpression(ctor.constructor, type, args,
             isConst: true);
       }
@@ -4564,19 +4593,19 @@
         ctorNode: constructor);
   }
 
-  JS.Statement _nullParameterCheck(JS.Expression param) {
+  js_ast.Statement _nullParameterCheck(js_ast.Expression param) {
     var call = runtimeCall('argumentError((#))', [param]);
     return js.statement('if (# == null) #;', [param, call]);
   }
 
-  JS.Expression notNull(Expression expr) {
+  js_ast.Expression notNull(Expression expr) {
     if (expr == null) return null;
     var jsExpr = _visitExpression(expr);
     if (!isNullable(expr)) return jsExpr;
     return runtimeCall('notNull(#)', [jsExpr]);
   }
 
-  JS.Expression _emitEqualityOperator(BinaryExpression node, Token op) {
+  js_ast.Expression _emitEqualityOperator(BinaryExpression node, Token op) {
     var left = node.leftOperand;
     var right = node.rightOperand;
     var leftType = left.staticType;
@@ -4632,7 +4661,7 @@
   }
 
   @override
-  JS.Expression visitBinaryExpression(BinaryExpression node) {
+  js_ast.Expression visitBinaryExpression(BinaryExpression node) {
     var op = node.operator;
 
     // The operands of logical boolean operators are subject to boolean
@@ -4653,10 +4682,10 @@
       // This should be a hint or warning for dead code.
       if (!isNullable(left)) return _visitExpression(left);
 
-      var vars = <JS.MetaLetVariable, JS.Expression>{};
+      var vars = <js_ast.MetaLetVariable, js_ast.Expression>{};
       // Desugar `l ?? r` as `l != null ? l : r`
       var l = _visitExpression(_bindValue(vars, 'l', left, context: left));
-      return JS.MetaLet(vars, [
+      return js_ast.MetaLet(vars, [
         js.call('# != null ? # : #', [l, l, _visitExpression(right)])
       ]);
     }
@@ -4664,7 +4693,7 @@
     var leftType = getStaticType(left);
     var rightType = getStaticType(right);
 
-    JS.Expression operatorCall() {
+    js_ast.Expression operatorCall() {
       return _emitOperatorCall(left, op.lexeme, [right])
         ..sourceInformation = _getLocation(node.operator.offset);
     }
@@ -4677,12 +4706,12 @@
 
       /// Emits an inlined binary operation using the JS [code], adding null
       /// checks if needed to ensure we throw the appropriate error.
-      JS.Expression binary(String code) {
+      js_ast.Expression binary(String code) {
         return js.call(code, [notNull(left), notNull(right)])
           ..sourceInformation = _getLocation(node.operator.offset);
       }
 
-      JS.Expression bitwise(String code) {
+      js_ast.Expression bitwise(String code) {
         return _coerceBitOperationResultToUnsigned(node, binary(code));
       }
 
@@ -4691,7 +4720,7 @@
       ///
       /// Short circuiting operators should not be used in [code], because the
       /// null checks for both operands must happen unconditionally.
-      JS.Expression bitwiseBool(String code) {
+      js_ast.Expression bitwiseBool(String code) {
         return js.call(code, [notNull(left), _visitTest(right)])
           ..sourceInformation = _getLocation(node.operator.offset);
       }
@@ -4764,8 +4793,8 @@
   /// the interpretation of the 32-bit value from signed to unsigned.  Most
   /// JavaScript operations interpret their operands as signed and generate
   /// signed results.
-  JS.Expression _coerceBitOperationResultToUnsigned(
-      Expression node, JS.Expression uncoerced) {
+  js_ast.Expression _coerceBitOperationResultToUnsigned(
+      Expression node, js_ast.Expression uncoerced) {
     // Don't coerce if the parent will coerce.
     AstNode parent = _parentOperation(node);
     if (_nodeIsBitwiseOperation(parent)) return uncoerced;
@@ -4936,7 +4965,7 @@
       expr is NullLiteral || getStaticType(expr).isDartCoreNull;
 
   SimpleIdentifier _createTemporary(String name, DartType type,
-      {bool nullable = true, JS.Expression variable, bool dynamicInvoke}) {
+      {bool nullable = true, js_ast.Expression variable, bool dynamicInvoke}) {
     // We use an invalid source location to signal that this is a temporary.
     // See [_isTemporary].
     // TODO(jmesserly): alternatives are
@@ -4947,7 +4976,7 @@
     var id = astFactory
         .simpleIdentifier(StringToken(TokenType.IDENTIFIER, name, -1));
 
-    variable ??= JS.TemporaryId(name);
+    variable ??= js_ast.TemporaryId(name);
 
     var idElement =
         TemporaryVariableElement.forNode(id, variable, _currentElement);
@@ -4975,7 +5004,7 @@
   /// unless [expr] is a SimpleIdentifier, in which case a temporary is not
   /// needed.
   Expression _bindLeftHandSide(
-      Map<JS.MetaLetVariable, JS.Expression> scope, Expression expr,
+      Map<js_ast.MetaLetVariable, js_ast.Expression> scope, Expression expr,
       {Expression context}) {
     Expression result;
     if (expr is IndexExpression) {
@@ -5019,13 +5048,13 @@
   /// variables), then the resulting code will be simplified automatically.
   ///
   /// [scope] will be mutated to contain the new temporary's initialization.
-  Expression _bindValue(Map<JS.MetaLetVariable, JS.Expression> scope,
+  Expression _bindValue(Map<js_ast.MetaLetVariable, js_ast.Expression> scope,
       String name, Expression expr,
       {Expression context}) {
     // No need to do anything for stateless expressions.
     if (isStateless(_currentFunction, expr, context)) return expr;
 
-    var variable = JS.MetaLetVariable(name);
+    var variable = js_ast.MetaLetVariable(name);
     var t = _createTemporary(name, getStaticType(expr),
         variable: variable,
         dynamicInvoke: isDynamicInvoke(expr),
@@ -5050,10 +5079,10 @@
   ///     // pseudocode mix of Scheme and JS:
   ///     (let* (x1=expr1, x2=expr2, t=expr1[expr2]) { x1[x2] = t + 1; t })
   ///
-  /// The [JS.MetaLet] nodes automatically simplify themselves if they can.
+  /// The [js_ast.MetaLet] nodes automatically simplify themselves if they can.
   /// For example, if the result value is not used, then `t` goes away.
   @override
-  JS.Expression visitPostfixExpression(PostfixExpression node) {
+  js_ast.Expression visitPostfixExpression(PostfixExpression node) {
     var op = node.operator;
     var expr = node.operand;
 
@@ -5073,7 +5102,7 @@
 
     // Handle the left hand side, to ensure each of its subexpressions are
     // evaluated only once.
-    var vars = <JS.MetaLetVariable, JS.Expression>{};
+    var vars = <js_ast.MetaLetVariable, js_ast.Expression>{};
     var left = _bindLeftHandSide(vars, expr, context: expr);
 
     // Desugar `x++` as `(x1 = x0 + 1, x0)` where `x0` is the original value
@@ -5085,12 +5114,15 @@
       ..staticElement = node.staticElement
       ..staticType = getStaticType(expr);
 
-    var body = <JS.Expression>[_emitSet(left, increment), _visitExpression(x)];
-    return JS.MetaLet(vars, body, statelessResult: true);
+    var body = <js_ast.Expression>[
+      _emitSet(left, increment),
+      _visitExpression(x)
+    ];
+    return js_ast.MetaLet(vars, body, statelessResult: true);
   }
 
   @override
-  JS.Expression visitPrefixExpression(PrefixExpression node) {
+  js_ast.Expression visitPrefixExpression(PrefixExpression node) {
     var op = node.operator;
 
     // Logical negation, `!e`, is a boolean conversion context since it is
@@ -5103,7 +5135,7 @@
     if (jsTypeRep.unaryOperationIsPrimitive(dispatchType)) {
       if (op.lexeme == '~') {
         if (jsTypeRep.isNumber(dispatchType)) {
-          JS.Expression jsExpr = js.call('~#', notNull(expr));
+          js_ast.Expression jsExpr = js.call('~#', notNull(expr));
           return _coerceBitOperationResultToUnsigned(node, jsExpr);
         }
         return _emitOperatorCall(expr, op.lexeme[0], []);
@@ -5113,7 +5145,7 @@
       }
       if (op.lexeme == '++' || op.lexeme == '--') {
         // We need a null check, so the increment must be expanded out.
-        var vars = <JS.MetaLetVariable, JS.Expression>{};
+        var vars = <js_ast.MetaLetVariable, js_ast.Expression>{};
         var x = _bindLeftHandSide(vars, expr, context: expr);
 
         var one = ast.integerLiteral(1)..staticType = types.intType;
@@ -5121,7 +5153,7 @@
           ..staticElement = node.staticElement
           ..staticType = getStaticType(expr);
 
-        return JS.MetaLet(vars, [_emitSet(x, increment)]);
+        return js_ast.MetaLet(vars, [_emitSet(x, increment)]);
       }
       return js.call('$op#', notNull(expr));
     }
@@ -5148,33 +5180,35 @@
   visitCascadeExpression(CascadeExpression node) {
     var savedCascadeTemp = _cascadeTarget;
 
-    var vars = <JS.MetaLetVariable, JS.Expression>{};
+    var vars = <js_ast.MetaLetVariable, js_ast.Expression>{};
     _cascadeTarget = _bindValue(vars, '_', node.target, context: node);
     var sections = _visitExpressionList(node.cascadeSections);
     sections.add(_visitExpression(_cascadeTarget));
-    var result = JS.MetaLet(vars, sections, statelessResult: true);
+    var result = js_ast.MetaLet(vars, sections, statelessResult: true);
     _cascadeTarget = savedCascadeTemp;
     return result;
   }
 
   @override
-  JS.Expression visitParenthesizedExpression(ParenthesizedExpression node) =>
+  js_ast.Expression visitParenthesizedExpression(
+          ParenthesizedExpression node) =>
       // The printer handles precedence so we don't need to.
       _visitExpression(node.expression);
 
-  JS.Parameter _emitFormalParameter(FormalParameter node) {
+  js_ast.Parameter _emitFormalParameter(FormalParameter node) {
     var id = _emitParameter(node.declaredElement, declaration: true)
       ..sourceInformation = _nodeSpan(node);
     var isRestArg = node is! DefaultFormalParameter &&
         findAnnotation(node.declaredElement, isJsRestAnnotation) != null;
-    return isRestArg ? JS.RestParameter(id) : id;
+    return isRestArg ? js_ast.RestParameter(id) : id;
   }
 
   @override
-  JS.This visitThisExpression(ThisExpression node) => JS.This();
+  js_ast.This visitThisExpression(ThisExpression node) => js_ast.This();
 
   @override
-  JS.Expression visitSuperExpression(SuperExpression node) => JS.Super();
+  js_ast.Expression visitSuperExpression(SuperExpression node) =>
+      js_ast.Super();
 
   @override
   visitPrefixedIdentifier(PrefixedIdentifier node) {
@@ -5198,14 +5232,14 @@
     return _emitPropertyGet(_getTarget(node), node.propertyName, node);
   }
 
-  JS.Expression _emitNullSafe(Expression node) {
+  js_ast.Expression _emitNullSafe(Expression node) {
     // Desugar `obj?.name` as ((x) => x == null ? null : x.name)(obj)
     var target = _getTarget(node);
-    var vars = <JS.MetaLetVariable, JS.Expression>{};
+    var vars = <js_ast.MetaLetVariable, js_ast.Expression>{};
     var t = _bindValue(vars, 't', target, context: target);
 
     var desugared = _stripNullAwareOp(node, t);
-    return JS.MetaLet(vars, [
+    return js_ast.MetaLet(vars, [
       js.call('# == null ? null : #',
           [_visitExpression(t), _visitExpression(desugared)])
     ]);
@@ -5226,7 +5260,7 @@
     }
   }
 
-  List<JS.Expression> _getTypeArgs(Element member, DartType instantiated) {
+  List<js_ast.Expression> _getTypeArgs(Element member, DartType instantiated) {
     DartType type;
     if (member is ExecutableElement) {
       type = member.type;
@@ -5240,7 +5274,7 @@
   }
 
   /// Shared code for [PrefixedIdentifier] and [PropertyAccess].
-  JS.Expression _emitPropertyGet(
+  js_ast.Expression _emitPropertyGet(
       Expression receiver, SimpleIdentifier memberId, Expression accessNode) {
     var resultType = accessNode.staticType;
     var accessor = memberId.staticElement;
@@ -5262,17 +5296,17 @@
     }
 
     var jsTarget = _emitTarget(receiver, accessor, isStatic);
-    var isSuper = jsTarget is JS.Super;
+    var isSuper = jsTarget is js_ast.Super;
     if (isSuper &&
         accessor.isSynthetic &&
         field is FieldElementImpl &&
         !virtualFields.isVirtual(field)) {
       // If super.x is a sealed field, then x is an instance property since
       // subclasses cannot override x.
-      jsTarget = JS.This()..sourceInformation = jsTarget.sourceInformation;
+      jsTarget = js_ast.This()..sourceInformation = jsTarget.sourceInformation;
     }
 
-    JS.Expression result;
+    js_ast.Expression result;
     if (isObjectMember(memberName) && isNullable(receiver)) {
       if (_isObjectMethodTearoff(memberName)) {
         result = runtimeCall('bind(#, #)', [jsTarget, jsName]);
@@ -5311,7 +5345,7 @@
   bool _isDirectCallable(DartType t) =>
       t is FunctionType || t is InterfaceType && _usesJSInterop(t.element);
 
-  JS.Expression _getImplicitCallTarget(InterfaceType fromType) {
+  js_ast.Expression _getImplicitCallTarget(InterfaceType fromType) {
     var callMethod = fromType.lookUpInheritedMethod('call');
     if (callMethod == null || _usesJSInterop(fromType.element)) return null;
     return _emitMemberName('call', type: fromType, element: callMethod);
@@ -5322,7 +5356,7 @@
   /// **Please note** this function does not support method invocation syntax
   /// `obj.name(args)` because that could be a getter followed by a call.
   /// See [visitMethodInvocation].
-  JS.Expression _emitOperatorCall(
+  js_ast.Expression _emitOperatorCall(
       Expression target, String name, List<Expression> args,
       [Element element]) {
     // TODO(jmesserly): calls that don't pass `element` are probably broken for
@@ -5352,7 +5386,7 @@
   visitIndexExpression(IndexExpression node) {
     var target = _getTarget(node);
     if (_useNativeJsIndexer(target.staticType)) {
-      return JS.PropertyAccess(
+      return js_ast.PropertyAccess(
           _visitExpression(target), _visitExpression(node.index));
     }
     return _emitOperatorCall(target, '[]', [node.index], node.staticElement);
@@ -5378,7 +5412,7 @@
   }
 
   @override
-  JS.Expression visitConditionalExpression(ConditionalExpression node) {
+  js_ast.Expression visitConditionalExpression(ConditionalExpression node) {
     return js.call('# ? # : #', [
       _visitTest(node.condition),
       _visitExpression(node.thenExpression),
@@ -5387,12 +5421,12 @@
   }
 
   @override
-  JS.Expression visitThrowExpression(ThrowExpression node) {
+  js_ast.Expression visitThrowExpression(ThrowExpression node) {
     return runtimeCall('throw(#)', [_visitExpression(node.expression)]);
   }
 
   @override
-  JS.Expression visitRethrowExpression(RethrowExpression node) {
+  js_ast.Expression visitRethrowExpression(RethrowExpression node) {
     return runtimeCall(
         'rethrow(#)', [_emitSimpleIdentifier(_rethrowParameter)]);
   }
@@ -5403,32 +5437,33 @@
   ///
   ///     do var x = 5; while (false); // Dart
   ///     do { let x = 5; } while (false); // JS
-  JS.Statement _visitScope(Statement stmt) {
+  js_ast.Statement _visitScope(Statement stmt) {
     var result = _visitStatement(stmt);
-    if (result is JS.ExpressionStatement &&
-        result.expression is JS.VariableDeclarationList) {
-      return JS.Block([result]);
+    if (result is js_ast.ExpressionStatement &&
+        result.expression is js_ast.VariableDeclarationList) {
+      return js_ast.Block([result]);
     }
     return result;
   }
 
   @override
-  JS.Statement visitIfStatement(IfStatement node) {
-    return JS.If(_visitTest(node.condition), _visitScope(node.thenStatement),
-        _visitScope(node.elseStatement));
+  js_ast.Statement visitIfStatement(IfStatement node) {
+    return js_ast.If(_visitTest(node.condition),
+        _visitScope(node.thenStatement), _visitScope(node.elseStatement));
   }
 
   @override
-  JS.While visitWhileStatement(WhileStatement node) {
-    return JS.While(_visitTest(node.condition), _visitScope(node.body));
+  js_ast.While visitWhileStatement(WhileStatement node) {
+    return js_ast.While(_visitTest(node.condition), _visitScope(node.body));
   }
 
   @override
-  JS.Do visitDoStatement(DoStatement node) {
-    return JS.Do(_visitScope(node.body), _visitTest(node.condition));
+  js_ast.Do visitDoStatement(DoStatement node) {
+    return js_ast.Do(_visitScope(node.body), _visitTest(node.condition));
   }
 
-  JS.Statement _emitAwaitFor(ForEachParts forParts, JS.Statement jsBody) {
+  js_ast.Statement _emitAwaitFor(
+      ForEachParts forParts, js_ast.Statement jsBody) {
     // Emits `await for (var value in stream) ...`, which desugars as:
     //
     // let iter = new StreamIterator(stream);
@@ -5452,9 +5487,9 @@
         streamIterator.element.unnamedConstructor,
         streamIterator,
         [_visitExpression(forParts.iterable)]);
-    var iter = JS.TemporaryId('iter');
+    var iter = js_ast.TemporaryId('iter');
     SimpleIdentifier variable;
-    JS.Expression init;
+    js_ast.Expression init;
     if (forParts is ForEachPartsWithIdentifier) {
       variable = forParts.identifier;
       init = js
@@ -5475,11 +5510,11 @@
         [
           iter,
           createStreamIter,
-          JS.Yield(js.call('#.moveNext()', iter))
+          js_ast.Yield(js.call('#.moveNext()', iter))
             ..sourceInformation = _nodeStart(variable),
           init,
           jsBody,
-          JS.Yield(js.call('#.cancel()', iter))
+          js_ast.Yield(js.call('#.cancel()', iter))
             ..sourceInformation = _nodeStart(variable)
         ]);
   }
@@ -5487,7 +5522,7 @@
   @override
   visitBreakStatement(BreakStatement node) {
     var label = node.label;
-    return JS.Break(label?.name);
+    return js_ast.Break(label?.name);
   }
 
   @override
@@ -5521,7 +5556,7 @@
         }
       }
     }
-    return JS.Continue(label?.name);
+    return js_ast.Continue(label?.name);
   }
 
   @override
@@ -5530,11 +5565,11 @@
     _superAllowed = false;
     var finallyBlock = _visitStatement(node.finallyBlock)?.toBlock();
     _superAllowed = savedSuperAllowed;
-    return JS.Try(_visitStatement(node.body).toBlock(),
+    return js_ast.Try(_visitStatement(node.body).toBlock(),
         _visitCatch(node.catchClauses), finallyBlock);
   }
 
-  JS.Catch _visitCatch(NodeList<CatchClause> clauses) {
+  js_ast.Catch _visitCatch(NodeList<CatchClause> clauses) {
     if (clauses == null || clauses.isEmpty) return null;
 
     var caughtError = _createTemporary('e', types.dynamicType);
@@ -5554,7 +5589,8 @@
                 : null);
 
     // Rethrow if the exception type didn't match.
-    JS.Statement catchBody = JS.Throw(_emitSimpleIdentifier(caughtError));
+    js_ast.Statement catchBody =
+        js_ast.Throw(_emitSimpleIdentifier(caughtError));
     for (var clause in clauses.reversed) {
       catchBody = _catchClauseGuard(
           clause, catchBody, exceptionParameter, stackTraceParameter);
@@ -5575,17 +5611,17 @@
     }
     catchStatements.add(catchBody);
 
-    var catchVarDecl = _emitSimpleIdentifier(caughtError) as JS.Identifier;
+    var catchVarDecl = _emitSimpleIdentifier(caughtError) as js_ast.Identifier;
     _rethrowParameter = savedRethrow;
-    return JS.Catch(catchVarDecl, JS.Block(catchStatements));
+    return js_ast.Catch(catchVarDecl, js_ast.Block(catchStatements));
   }
 
-  JS.Statement _catchClauseGuard(
+  js_ast.Statement _catchClauseGuard(
       CatchClause node,
-      JS.Statement otherwise,
+      js_ast.Statement otherwise,
       SimpleIdentifier exceptionParameter,
       SimpleIdentifier stackTraceParameter) {
-    var body = <JS.Statement>[];
+    var body = <js_ast.Statement>[];
     var vars = HashSet<String>();
 
     void declareVariable(SimpleIdentifier variable, SimpleIdentifier value) {
@@ -5603,7 +5639,7 @@
     }
 
     body.add(_visitStatement(node.body).toScopedBlock(vars));
-    var then = JS.Statement.from(body);
+    var then = js_ast.Statement.from(body);
 
     // Discard following clauses, if any, as they are unreachable.
     if (node.exceptionType == null ||
@@ -5613,32 +5649,32 @@
 
     var condition =
         _emitIsExpression(exceptionParameter, node.exceptionType.type);
-    return JS.If(condition, then, otherwise)
+    return js_ast.If(condition, then, otherwise)
       ..sourceInformation = _nodeStart(node);
   }
 
   @override
-  JS.SwitchCase visitSwitchCase(SwitchCase node) {
+  js_ast.SwitchCase visitSwitchCase(SwitchCase node) {
     var expr = _visitExpression(node.expression);
     var body = _visitStatementList(node.statements);
     if (node.labels.isNotEmpty) {
       body.insert(0, js.comment('Unimplemented case labels: ${node.labels}'));
     }
     // TODO(jmesserly): make sure we are statically checking fall through
-    return JS.SwitchCase(expr, JS.Block(body));
+    return js_ast.SwitchCase(expr, js_ast.Block(body));
   }
 
   @override
-  JS.SwitchCase visitSwitchDefault(SwitchDefault node) {
+  js_ast.SwitchCase visitSwitchDefault(SwitchDefault node) {
     var body = _visitStatementList(node.statements);
     if (node.labels.isNotEmpty) {
       body.insert(0, js.comment('Unimplemented case labels: ${node.labels}'));
     }
     // TODO(jmesserly): make sure we are statically checking fall through
-    return JS.SwitchCase.defaultCase(JS.Block(body));
+    return js_ast.SwitchCase.defaultCase(js_ast.Block(body));
   }
 
-  JS.SwitchCase _emitSwitchMember(SwitchMember node) {
+  js_ast.SwitchCase _emitSwitchMember(SwitchMember node) {
     if (node is SwitchCase) {
       return visitSwitchCase(node);
     } else {
@@ -5647,15 +5683,15 @@
   }
 
   @override
-  JS.Switch visitSwitchStatement(SwitchStatement node) => JS.Switch(
+  js_ast.Switch visitSwitchStatement(SwitchStatement node) => js_ast.Switch(
       _visitExpression(node.expression),
       node.members?.map(_emitSwitchMember)?.toList());
 
   @override
-  JS.Statement visitLabeledStatement(LabeledStatement node) {
+  js_ast.Statement visitLabeledStatement(LabeledStatement node) {
     var result = _visitStatement(node.statement);
     for (var label in node.labels.reversed) {
-      result = JS.LabeledStatement(label.label.name, result);
+      result = js_ast.LabeledStatement(label.label.name, result);
     }
     return result;
   }
@@ -5682,14 +5718,14 @@
           AnalysisError(_currentCompilationUnit.source, node.offset,
               node.length, invalidJSInteger, [lexeme, nearest]));
     }
-    return JS.LiteralNumber('$valueInJS');
+    return js_ast.LiteralNumber('$valueInJS');
   }
 
   @override
   visitDoubleLiteral(DoubleLiteral node) => js.number(node.value);
 
   @override
-  visitNullLiteral(NullLiteral node) => JS.LiteralNull();
+  visitNullLiteral(NullLiteral node) => js_ast.LiteralNull();
 
   @override
   visitSymbolLiteral(SymbolLiteral node) {
@@ -5697,7 +5733,7 @@
   }
 
   @override
-  JS.Expression visitListLiteral(ListLiteral node) {
+  js_ast.Expression visitListLiteral(ListLiteral node) {
     var elementType = (node.staticType as InterfaceType).typeArguments[0];
     var elements = _visitCollectionElementList(node.elements, elementType);
     if (!node.isConst) {
@@ -5706,7 +5742,7 @@
     return _emitConstList(elementType, elements);
   }
 
-  JS.Expression _emitSetLiteral(SetOrMapLiteral node) {
+  js_ast.Expression _emitSetLiteral(SetOrMapLiteral node) {
     var type = node.staticType as InterfaceType;
     var elementType = type.typeArguments[0];
     var jsElements = _visitCollectionElementList(node.elements, elementType);
@@ -5721,16 +5757,17 @@
         runtimeCall('constSet(#, [#])', [_emitType(elementType), jsElements]));
   }
 
-  JS.Expression _emitConstList(
-      DartType elementType, List<JS.Expression> elements) {
+  js_ast.Expression _emitConstList(
+      DartType elementType, List<js_ast.Expression> elements) {
     // dart.constList helper internally depends on _interceptors.JSArray.
     _declareBeforeUse(_jsArray);
     return cacheConst(
         runtimeCall('constList([#], #)', [elements, _emitType(elementType)]));
   }
 
-  JS.Expression _emitList(DartType itemType, List<JS.Expression> items) {
-    var list = JS.ArrayInitializer(items);
+  js_ast.Expression _emitList(
+      DartType itemType, List<js_ast.Expression> items) {
+    var list = js_ast.ArrayInitializer(items);
 
     // TODO(jmesserly): analyzer will usually infer `List<Object>` because
     // that is the least upper bound of the element types. So we rarely
@@ -5742,7 +5779,7 @@
     return js.call('#.of(#)', [_emitType(arrayType), list]);
   }
 
-  JS.Expression _emitMapLiteral(SetOrMapLiteral node) {
+  js_ast.Expression _emitMapLiteral(SetOrMapLiteral node) {
     var type = node.staticType as InterfaceType;
     var elementType = type.typeArguments[0];
     var jsElements = _visitCollectionElementList(node.elements, elementType);
@@ -5756,13 +5793,14 @@
     return _emitConstMap(type, jsElements);
   }
 
-  JS.Expression _emitConstMap(InterfaceType type, List<JS.Expression> entries) {
+  js_ast.Expression _emitConstMap(
+      InterfaceType type, List<js_ast.Expression> entries) {
     var typeArgs = type.typeArguments;
     return cacheConst(runtimeCall('constMap(#, #, [#])',
         [_emitType(typeArgs[0]), _emitType(typeArgs[1]), entries]));
   }
 
-  JS.Expression _emitMapImplType(InterfaceType type, {bool identity}) {
+  js_ast.Expression _emitMapImplType(InterfaceType type, {bool identity}) {
     var typeArgs = type.typeArguments;
     if (typeArgs.isEmpty) return _emitType(type);
     identity ??= jsTypeRep.isPrimitive(typeArgs[0]);
@@ -5770,7 +5808,7 @@
     return _emitType(type.instantiate(typeArgs));
   }
 
-  JS.Expression _emitSetImplType(InterfaceType type, {bool identity}) {
+  js_ast.Expression _emitSetImplType(InterfaceType type, {bool identity}) {
     var typeArgs = type.typeArguments;
     if (typeArgs.isEmpty) return _emitType(type);
     identity ??= jsTypeRep.isPrimitive(typeArgs[0]);
@@ -5779,19 +5817,19 @@
   }
 
   @override
-  JS.LiteralString visitSimpleStringLiteral(SimpleStringLiteral node) =>
+  js_ast.LiteralString visitSimpleStringLiteral(SimpleStringLiteral node) =>
       js.escapedString(node.value, '"');
 
   @override
-  JS.Expression visitAdjacentStrings(AdjacentStrings node) {
+  js_ast.Expression visitAdjacentStrings(AdjacentStrings node) {
     var nodes = node.strings;
     if (nodes == null || nodes.isEmpty) return null;
-    return JS.Expression.binary(_visitExpressionList(nodes), '+');
+    return js_ast.Expression.binary(_visitExpressionList(nodes), '+');
   }
 
   @override
-  JS.Expression visitStringInterpolation(StringInterpolation node) {
-    var parts = <JS.Expression>[];
+  js_ast.Expression visitStringInterpolation(StringInterpolation node) {
+    var parts = <js_ast.Expression>[];
     for (var elem in node.elements) {
       if (elem is InterpolationString) {
         if (elem.value.isEmpty) continue;
@@ -5805,7 +5843,7 @@
       }
     }
     if (parts.isEmpty) return js.string('');
-    return JS.Expression.binary(parts, '+');
+    return js_ast.Expression.binary(parts, '+');
   }
 
   @override
@@ -5818,33 +5856,33 @@
   /// Visit a Dart [node] that produces a JS expression, and attaches a source
   /// location.
   // TODO(jmesserly): parameter type should be `Expression`
-  JS.Expression _visitExpression(AstNode node) {
+  js_ast.Expression _visitExpression(AstNode node) {
     if (node == null) return null;
-    var e = node.accept<JS.Node>(this) as JS.Expression;
+    var e = node.accept<js_ast.Node>(this) as js_ast.Expression;
     e.sourceInformation ??= _nodeStart(node);
     return e;
   }
 
   /// Visits [nodes] with [_visitExpression].
-  List<JS.Expression> _visitExpressionList(Iterable<AstNode> nodes) {
+  List<js_ast.Expression> _visitExpressionList(Iterable<AstNode> nodes) {
     return nodes?.map(_visitExpression)?.toList();
   }
 
   /// Visit a Dart [node] that produces a JS statement, and marks its source
   /// location for debugging.
-  JS.Statement _visitStatement(AstNode node) {
+  js_ast.Statement _visitStatement(AstNode node) {
     if (node == null) return null;
-    var s = node.accept<JS.Node>(this) as JS.Statement;
+    var s = node.accept<js_ast.Node>(this) as js_ast.Statement;
     if (s is! Block) s.sourceInformation = _nodeStart(node);
     return s;
   }
 
   /// Visits [nodes] with [_visitStatement].
-  List<JS.Statement> _visitStatementList(Iterable<AstNode> nodes) {
+  List<js_ast.Statement> _visitStatementList(Iterable<AstNode> nodes) {
     return nodes?.map(_visitStatement)?.toList();
   }
 
-  /// Returns a [JS.Expression] for each [CollectionElement] in [nodes].
+  /// Returns a [js_ast.Expression] for each [CollectionElement] in [nodes].
   ///
   /// Visits all [nodes] in order and nested [CollectionElement]s depth first
   /// to produce [JS.Expresison]s intended to be used when outputing a
@@ -5862,7 +5900,7 @@
   ///       if (true) for (let i = 2; i < 10; i++) temp.push(i);
   ///       return temp;
   ///     })(), 10]
-  List<JS.Expression> _visitCollectionElementList(
+  List<js_ast.Expression> _visitCollectionElementList(
       Iterable<CollectionElement> nodes, DartType elementType) {
     /// Returns [body] wrapped in a function and a call.
     ///
@@ -5870,19 +5908,20 @@
     /// fucntion, call it, and yield the result of [yieldType].
     /// TODO(nshahan) Move to share between compilers. Need to work out a common
     /// emitLibraryName().
-    JS.Expression detectYieldAndCall(JS.Block body, InterfaceType yieldType) {
+    js_ast.Expression detectYieldAndCall(
+        js_ast.Block body, InterfaceType yieldType) {
       var finder = YieldFinder();
       body.accept(finder);
       if (finder.hasYield) {
-        var genFn = JS.Fun([], body, isGenerator: true);
+        var genFn = js_ast.Fun([], body, isGenerator: true);
         var asyncLibrary = emitLibraryName(types.futureType.element.library);
-        return JS.Yield(js.call(
+        return js_ast.Yield(js.call(
             '#.async(#, #)', [asyncLibrary, _emitType(yieldType), genFn]));
       }
-      return JS.Call(JS.ArrowFun([], body), []);
+      return js_ast.Call(js_ast.ArrowFun([], body), []);
     }
 
-    var expressions = <JS.Expression>[];
+    var expressions = <js_ast.Expression>[];
     for (var node in nodes) {
       if (_isUiAsCodeElement(node)) {
         // Create a temporary variable to build a new collection from.
@@ -5895,15 +5934,15 @@
 
         // Build up a list for the control-flow-collections element and wrap in
         // a function call that returns the list.
-        var functionBody = JS.Block([
+        var functionBody = js_ast.Block([
           items,
-          node.accept<JS.Node>(this) as JS.Statement,
-          JS.Return(_currentCollectionVariable)
+          node.accept<js_ast.Node>(this) as js_ast.Statement,
+          js_ast.Return(_currentCollectionVariable)
         ]);
         var functionCall = detectYieldAndCall(functionBody, arrayType);
 
         // Finally, spread the temporary control-flow-collections list.
-        expressions.add(JS.Spread(functionCall));
+        expressions.add(js_ast.Spread(functionCall));
         _currentCollectionVariable = previousCollectionVariable;
       } else if (node is MapLiteralEntry) {
         expressions.add(_visitExpression(node.key));
@@ -5917,12 +5956,12 @@
 
   /// Visits [node] with [_visitExpression] and wraps the result in a call to
   /// append it to the list tracked by [_currentCollectionVariable].
-  JS.Statement _visitNestedCollectionElement(CollectionElement node) {
-    JS.Statement pushToCurrentCollection(Expression value) => js.statement(
+  js_ast.Statement _visitNestedCollectionElement(CollectionElement node) {
+    js_ast.Statement pushToCurrentCollection(Expression value) => js.statement(
         '#.push(#)', [_currentCollectionVariable, _visitExpression(value)]);
 
     if (node is MapLiteralEntry) {
-      return JS.Block([
+      return js_ast.Block([
         pushToCurrentCollection(node.key),
         pushToCurrentCollection(node.value)
       ]);
@@ -5987,7 +6026,7 @@
   /// For example, top-level and static fields are defined as lazy properties,
   /// on the library/class, so their access expressions do not appear in the
   /// source code.
-  HoverComment _hoverComment(JS.Expression expr, AstNode node) {
+  HoverComment _hoverComment(js_ast.Expression expr, AstNode node) {
     var start = _getLocation(node.offset);
     var end = _getLocation(node.end);
     return start != null && end != null ? HoverComment(expr, start, end) : null;
@@ -6022,7 +6061,7 @@
   /// to give a more helpful message.
   // TODO(sra): When nullablility is available earlier, it would be cleaner to
   // build an input AST where the boolean conversion is a single AST node.
-  JS.Expression _visitTest(Expression node) {
+  js_ast.Expression _visitTest(Expression node) {
     if (node == null) return null;
 
     if (node is PrefixExpression && node.operator.lexeme == '!') {
@@ -6034,7 +6073,7 @@
       return _visitTest(node.expression);
     }
     if (node is BinaryExpression) {
-      JS.Expression shortCircuit(String code) {
+      js_ast.Expression shortCircuit(String code) {
         return js.call(code,
             [_visitTest(node.leftOperand), _visitTest(node.rightOperand)]);
       }
@@ -6056,7 +6095,8 @@
   ///
   /// Unlike call sites, we always have an element available, so we can use it
   /// directly rather than computing the relevant options for [_emitMemberName].
-  JS.Expression _declareMemberName(ExecutableElement e, {bool useExtension}) {
+  js_ast.Expression _declareMemberName(ExecutableElement e,
+      {bool useExtension}) {
     return _emitMemberName(_getElementName(e),
         isStatic: e.isStatic,
         useExtension:
@@ -6104,7 +6144,7 @@
   /// Equality is a bit special, it is generated via the Dart `equals` runtime
   /// helper, that checks for null. The user defined method is called '=='.
   ///
-  JS.Expression _emitMemberName(String name,
+  js_ast.Expression _emitMemberName(String name,
       {DartType type,
       bool isStatic = false,
       bool useExtension,
@@ -6123,9 +6163,9 @@
         var parts = runtimeName.split('.');
         if (parts.length < 2) return propertyName(runtimeName);
 
-        JS.Expression result = JS.Identifier(parts[0]);
+        js_ast.Expression result = js_ast.Identifier(parts[0]);
         for (int i = 1; i < parts.length; i++) {
-          result = JS.PropertyAccess(result, propertyName(parts[i]));
+          result = js_ast.PropertyAccess(result, propertyName(parts[i]));
         }
         return result;
       }
@@ -6138,7 +6178,7 @@
     useExtension ??= _isSymbolizedMember(type, name);
     // Rename members that conflict with standard JS members unless we are
     // actually try to access those JS members via interop.
-    name = JS.memberNameForDartMember(name, _isExternal(element));
+    name = js_ast.memberNameForDartMember(name, _isExternal(element));
     if (useExtension) {
       return getExtensionSymbolInternal(name);
     }
@@ -6151,7 +6191,7 @@
   /// The member [name] should be passed, as well as its [element] when it's
   /// available. If the element is `external`, the element is used to statically
   /// resolve the JS interop/dart:html static member. Otherwise it is ignored.
-  JS.Expression _emitStaticMemberName(String name, [Element element]) {
+  js_ast.Expression _emitStaticMemberName(String name, [Element element]) {
     if (element != null && _isExternal(element)) {
       var newName = getAnnotationName(element, isJSName) ??
           _getJSInteropStaticMemberName(element);
@@ -6316,7 +6356,7 @@
     return DynamicTypeImpl.instance;
   }
 
-  JS.Expression _throwUnsafe(String message) => runtimeCall(
+  js_ast.Expression _throwUnsafe(String message) => runtimeCall(
       'throw(Error(#))', [js.escapedString("compile error: $message")]);
 
   Null _unreachable(Object node) {
@@ -6403,7 +6443,7 @@
 
   /// Unused, handled by [visitMixinDeclaration].
   @override
-  JS.Node visitOnClause(OnClause node) => _unreachable(node);
+  js_ast.Node visitOnClause(OnClause node) => _unreachable(node);
 
   /// Unused, handled by imports/exports.
   @override
@@ -6469,8 +6509,8 @@
   @override
   visitWithClause(node) => _unreachable(node);
 
-  JS.For _emitFor(ForParts forParts, JS.Statement body) {
-    JS.Expression init;
+  js_ast.For _emitFor(ForParts forParts, js_ast.Statement body) {
+    js_ast.Expression init;
     if (forParts is ForPartsWithExpression) {
       init = _visitExpression(forParts.initialization);
     } else if (forParts is ForPartsWithDeclarations) {
@@ -6478,64 +6518,66 @@
     } else {
       throw new StateError('Unrecognized for loop parts');
     }
-    JS.Expression update;
+    js_ast.Expression update;
     if (forParts.updaters != null && forParts.updaters.isNotEmpty) {
-      update = JS.Expression.binary(
+      update = js_ast.Expression.binary(
               forParts.updaters.map(_visitExpression).toList(), ',')
           .toVoidExpression();
     }
-    return JS.For(init, _visitTest(forParts.condition), update, body);
+    return js_ast.For(init, _visitTest(forParts.condition), update, body);
   }
 
-  JS.Statement _emitForEach(ForEachParts forParts, JS.Statement jsBody) {
+  js_ast.Statement _emitForEach(
+      ForEachParts forParts, js_ast.Statement jsBody) {
     var jsIterable = _visitExpression(forParts.iterable);
-    JS.Expression jsLeftExpression;
+    js_ast.Expression jsLeftExpression;
     if (forParts is ForEachPartsWithIdentifier) {
       jsLeftExpression = _visitExpression(forParts.identifier);
     } else if (forParts is ForEachPartsWithDeclaration) {
       var id = _emitVariableDef(forParts.loopVariable.identifier);
       jsLeftExpression = js.call('let #', id);
       if (_annotatedNullCheck(forParts.loopVariable.declaredElement)) {
-        jsBody =
-            JS.Block([_nullParameterCheck(JS.Identifier(id.name)), jsBody]);
+        jsBody = js_ast.Block(
+            [_nullParameterCheck(js_ast.Identifier(id.name)), jsBody]);
       }
       if (variableIsReferenced(id.name, jsIterable)) {
-        var temp = JS.TemporaryId('iter');
-        return JS.Block([
+        var temp = js_ast.TemporaryId('iter');
+        return js_ast.Block([
           jsIterable.toVariableDeclaration(temp),
-          JS.ForOf(jsLeftExpression, temp, jsBody)
+          js_ast.ForOf(jsLeftExpression, temp, jsBody)
         ]);
       }
     } else {
       throw new StateError('Unrecognized for loop parts');
     }
-    return JS.ForOf(jsLeftExpression, jsIterable, jsBody);
+    return js_ast.ForOf(jsLeftExpression, jsIterable, jsBody);
   }
 
   @override
-  JS.Statement visitForElement(ForElement node) {
+  js_ast.Statement visitForElement(ForElement node) {
     var jsBody = _isUiAsCodeElement(node.body)
-        ? node.body.accept(this) as JS.Statement
+        ? node.body.accept(this) as js_ast.Statement
         : _visitNestedCollectionElement(node.body);
     return _forAdaptor(node.forLoopParts, node.awaitKeyword, jsBody);
   }
 
   @override
-  JS.Statement visitIfElement(IfElement node) {
+  js_ast.Statement visitIfElement(IfElement node) {
     var thenElement = _isUiAsCodeElement(node.thenElement)
-        ? node.thenElement.accept(this) as JS.Statement
+        ? node.thenElement.accept(this) as js_ast.Statement
         : _visitNestedCollectionElement(node.thenElement);
 
-    JS.Statement elseElement;
+    js_ast.Statement elseElement;
     if (node.elseElement != null) {
       if (_isUiAsCodeElement(node.elseElement)) {
-        elseElement = node.elseElement.accept<JS.Node>(this) as JS.Statement;
+        elseElement =
+            node.elseElement.accept<js_ast.Node>(this) as js_ast.Statement;
       } else {
         elseElement = _visitNestedCollectionElement(node.elseElement);
       }
     }
 
-    return JS.If(_visitTest(node.condition), thenElement, elseElement);
+    return js_ast.If(_visitTest(node.condition), thenElement, elseElement);
   }
 
   @override
@@ -6547,23 +6589,23 @@
       _unreachable(node);
 
   @override
-  JS.Statement visitForStatement(ForStatement node) =>
+  js_ast.Statement visitForStatement(ForStatement node) =>
       _forAdaptor(node.forLoopParts, node.awaitKeyword, _visitScope(node.body));
 
-  JS.Statement _forAdaptor(
-      ForLoopParts forParts, Token awaitKeyword, JS.Statement jsBody) {
+  js_ast.Statement _forAdaptor(
+      ForLoopParts forParts, Token awaitKeyword, js_ast.Statement jsBody) {
     /// Returns a new scoped block starting with [first] followed by [rest].
     ///
     /// Performs one level of scope flattening when [rest] is already a scoped
     /// block.
-    JS.Block insertFirst(JS.Statement first, JS.Statement rest) {
+    js_ast.Block insertFirst(js_ast.Statement first, js_ast.Statement rest) {
       var bodyStatements = [first];
-      if (rest is JS.Block) {
+      if (rest is js_ast.Block) {
         bodyStatements.addAll(rest.statements);
       } else {
         bodyStatements.add(rest);
       }
-      return JS.Block(bodyStatements);
+      return js_ast.Block(bodyStatements);
     }
 
     if (forParts is ForParts) {
@@ -6598,7 +6640,7 @@
       node.isSet ? _emitSetLiteral(node) : _emitMapLiteral(node);
 
   @override
-  JS.Statement visitSpreadElement(SpreadElement node) {
+  js_ast.Statement visitSpreadElement(SpreadElement node) {
     /// Returns `true` if [node] is or is a child element of a map literal.
     bool isMap(AstNode node) {
       if (node is SetOrMapLiteral) return node.isMap;
@@ -6609,8 +6651,8 @@
     /// Returns [expression] wrapped in an implict cast to [castType] or
     /// [expression] as provided if [castType] is `null` signifying that
     /// no cast is needed.
-    JS.Expression wrapInImplicitCast(
-            JS.Expression expression, DartType castType) =>
+    js_ast.Expression wrapInImplicitCast(
+            js_ast.Expression expression, DartType castType) =>
         castType == null ? expression : _emitCast(castType, expression);
 
     /// Returns a statement spreading the elements of [expression] into
@@ -6619,8 +6661,8 @@
     /// Expects the collection literal containing [expression] to be a list or
     /// set literal. Inserts implicit casts to [elementCastType] for each
     /// element if needed.
-    JS.Statement emitListOrSetSpread(
-        JS.Expression expression, DartType elementCastType) {
+    js_ast.Statement emitListOrSetSpread(
+        js_ast.Expression expression, DartType elementCastType) {
       var forEachTemp =
           _emitSimpleIdentifier(_createTemporary('i', types.dynamicType));
       return js.statement('#.forEach((#) => #.push(#))', [
@@ -6637,8 +6679,8 @@
     /// Expects the collection literal containing [expression] to be a map
     /// literal. Inserts implicit casts to [keyCastType] for keys and
     /// [valueCastType] for values if needed.
-    JS.Statement emitMapSpread(JS.Expression expression, DartType keyCastType,
-        DartType valueCastType) {
+    js_ast.Statement emitMapSpread(js_ast.Expression expression,
+        DartType keyCastType, DartType valueCastType) {
       var keyTemp =
           _emitSimpleIdentifier(_createTemporary('k', types.dynamicType));
       var valueTemp =
@@ -6659,7 +6701,7 @@
     /// Uses implict cast information from [node] to insert the correct casts
     /// for the collection elements when spreading. Inspects parents of [node]
     /// to determine the type of the enclosing collection literal.
-    JS.Statement emitSpread(JS.Expression expression, Expression node) {
+    js_ast.Statement emitSpread(js_ast.Expression expression, Expression node) {
       expression = wrapInImplicitCast(expression, getImplicitCast(node));
 
       // Start searching for a map literal at the parent of the SpreadElement.
@@ -6676,11 +6718,12 @@
     /// Uses implict cast information from [node] to insert the correct casts
     /// for the collection elements when spreading. Inspects parents of [node]
     /// to determine the type of the enclosing collection literal.
-    JS.Statement emitNullSafeSpread(JS.Expression expression, Expression node) {
+    js_ast.Statement emitNullSafeSpread(
+        js_ast.Expression expression, Expression node) {
       // TODO(nshahan) Could optimize out if we know the value is null.
       var spreadItems =
           _emitSimpleIdentifier(_createTemporary('items', getStaticType(node)));
-      return JS.Block([
+      return js_ast.Block([
         js.statement('let # = #', [spreadItems, expression]),
         js.statement(
             'if (# != null) #', [spreadItems, emitSpread(spreadItems, node)])
@@ -6714,7 +6757,7 @@
 /// variable. These objects use instance equality, and should be shared
 /// everywhere in the tree where they are treated as the same variable.
 class TemporaryVariableElement extends LocalVariableElementImpl {
-  final JS.Expression jsVariable;
+  final js_ast.Expression jsVariable;
 
   TemporaryVariableElement.forNode(
       Identifier name, this.jsVariable, Element enclosingElement)
diff --git a/pkg/dev_compiler/lib/src/analyzer/module_compiler.dart b/pkg/dev_compiler/lib/src/analyzer/module_compiler.dart
index 3997597..70bdc0a 100644
--- a/pkg/dev_compiler/lib/src/analyzer/module_compiler.dart
+++ b/pkg/dev_compiler/lib/src/analyzer/module_compiler.dart
@@ -15,12 +15,12 @@
 import 'package:path/path.dart' as path;
 import 'package:source_maps/source_maps.dart';
 
-import '../compiler/js_names.dart' as JS;
+import '../compiler/js_names.dart' as js_ast;
 import '../compiler/module_builder.dart'
     show transformModuleFormat, ModuleFormat;
 import '../compiler/shared_command.dart';
 import '../compiler/shared_compiler.dart';
-import '../js_ast/js_ast.dart' as JS;
+import '../js_ast/js_ast.dart' as js_ast;
 import '../js_ast/js_ast.dart' show js;
 import '../js_ast/source_map_printer.dart' show SourceMapPrintingContext;
 import 'code_generator.dart' show CodeGenerator;
@@ -95,7 +95,7 @@
     }
   }
 
-  JS.Program jsProgram;
+  js_ast.Program jsProgram;
   if (options.unsafeForceCompile || !errors.hasFatalErrors) {
     var codeGenerator = CodeGenerator(
         driver,
@@ -227,7 +227,7 @@
 
   /// The AST that will be used to generate the [code] and [sourceMap] for this
   /// module.
-  final JS.Program moduleTree;
+  final js_ast.Program moduleTree;
 
   /// The compiler options used to generate this module.
   final CompilerOptions options;
@@ -256,20 +256,21 @@
   // TODO(jmesserly): this should match our old logic, but I'm not sure we are
   // correctly handling the pointer from the .js file to the .map file.
   JSModuleCode getCode(ModuleFormat format, String jsUrl, String mapUrl) {
-    var opts = JS.JavaScriptPrintingOptions(
+    var opts = js_ast.JavaScriptPrintingOptions(
         allowKeywordsInProperties: true, allowSingleLineIfStatements: true);
-    JS.SimpleJavaScriptPrintingContext printer;
+    js_ast.SimpleJavaScriptPrintingContext printer;
     SourceMapBuilder sourceMap;
     if (options.sourceMap) {
       var sourceMapContext = SourceMapPrintingContext();
       sourceMap = sourceMapContext.sourceMap;
       printer = sourceMapContext;
     } else {
-      printer = JS.SimpleJavaScriptPrintingContext();
+      printer = js_ast.SimpleJavaScriptPrintingContext();
     }
 
     var tree = transformModuleFormat(format, moduleTree);
-    tree.accept(JS.Printer(opts, printer, localNamer: JS.TemporaryNamer(tree)));
+    tree.accept(
+        js_ast.Printer(opts, printer, localNamer: js_ast.TemporaryNamer(tree)));
 
     Map builtMap;
     if (options.sourceMap && sourceMap != null) {
diff --git a/pkg/dev_compiler/lib/src/analyzer/property_model.dart b/pkg/dev_compiler/lib/src/analyzer/property_model.dart
index d63abc3..227afa7 100644
--- a/pkg/dev_compiler/lib/src/analyzer/property_model.dart
+++ b/pkg/dev_compiler/lib/src/analyzer/property_model.dart
@@ -8,8 +8,7 @@
 import 'package:analyzer/dart/element/type.dart' show InterfaceType;
 import 'package:analyzer/src/dart/element/element.dart' show FieldElementImpl;
 
-import '../compiler/js_names.dart' as JS;
-import '../js_ast/js_ast.dart' as JS;
+import '../compiler/js_names.dart' as js_ast;
 import 'element_helpers.dart';
 import 'extension_types.dart';
 
@@ -176,7 +175,7 @@
   /// pair in JavaScript.
   ///
   /// The value property stores the symbol used for the field's storage slot.
-  final virtualFields = <FieldElement, JS.TemporaryId>{};
+  final virtualFields = <FieldElement, js_ast.TemporaryId>{};
 
   /// The set of inherited getters, used because JS getters/setters are paired,
   /// so if we're generating a setter we may need to emit a getter that calls
@@ -250,7 +249,7 @@
                 covariantParameters != null &&
                 covariantParameters.contains(setter.parameters[0]) &&
                 covariantPrivateMembers.contains(setter)) {
-          virtualFields[field] = JS.TemporaryId(name);
+          virtualFields[field] = js_ast.TemporaryId(name);
         }
       }
     }
diff --git a/pkg/dev_compiler/lib/src/analyzer/type_utilities.dart b/pkg/dev_compiler/lib/src/analyzer/type_utilities.dart
index dc52e86..ffa6943 100644
--- a/pkg/dev_compiler/lib/src/analyzer/type_utilities.dart
+++ b/pkg/dev_compiler/lib/src/analyzer/type_utilities.dart
@@ -3,13 +3,14 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'dart:collection';
+
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/src/dart/element/member.dart' show TypeParameterMember;
 import 'package:analyzer/dart/element/type.dart';
 
 import '../analyzer/element_helpers.dart';
-import '../compiler/js_names.dart' as JS;
-import '../js_ast/js_ast.dart' as JS;
+import '../compiler/js_names.dart' as js_ast;
+import '../js_ast/js_ast.dart' as js_ast;
 import '../js_ast/js_ast.dart' show js;
 
 Set<TypeParameterElement> freeTypeParameters(DartType t) {
@@ -54,11 +55,11 @@
   // Use a LinkedHashMap to maintain key insertion order so the generated code
   // is stable under slight perturbation.  (If this is not good enough we could
   // sort by name to canonicalize order.)
-  final _names = LinkedHashMap<DartType, JS.TemporaryId>(
+  final _names = LinkedHashMap<DartType, js_ast.TemporaryId>(
       equals: typesAreEqual, hashCode: typeHashCode);
   Iterable<DartType> get keys => _names.keys.toList();
 
-  JS.Statement _dischargeType(DartType type) {
+  js_ast.Statement _dischargeType(DartType type) {
     var name = _names.remove(type);
     if (name != null) {
       return js.statement('let #;', [name]);
@@ -69,8 +70,8 @@
   /// Emit a list of statements declaring the cache variables for
   /// types tracked by this table.  If [typeFilter] is given,
   /// only emit the types listed in the filter.
-  List<JS.Statement> discharge([Iterable<DartType> typeFilter]) {
-    var decls = <JS.Statement>[];
+  List<js_ast.Statement> discharge([Iterable<DartType> typeFilter]) {
+    var decls = <js_ast.Statement>[];
     var types = typeFilter ?? keys;
     for (var t in types) {
       var stmt = _dischargeType(t);
@@ -119,26 +120,26 @@
 
   /// Heuristically choose a good name for the cache and generator
   /// variables.
-  JS.TemporaryId chooseTypeName(DartType type) {
-    return JS.TemporaryId(_typeString(type));
+  js_ast.TemporaryId chooseTypeName(DartType type) {
+    return js_ast.TemporaryId(_typeString(type));
   }
 }
 
 /// _GeneratorTable tracks types which have been
 /// named and hoisted.
 class _GeneratorTable extends _CacheTable {
-  final _defs = LinkedHashMap<DartType, JS.Expression>(
+  final _defs = LinkedHashMap<DartType, js_ast.Expression>(
       equals: typesAreEqual, hashCode: typeHashCode);
 
-  final JS.Identifier _runtimeModule;
+  final js_ast.Identifier _runtimeModule;
 
   _GeneratorTable(this._runtimeModule);
 
   @override
-  JS.Statement _dischargeType(DartType t) {
+  js_ast.Statement _dischargeType(DartType t) {
     var name = _names.remove(t);
     if (name != null) {
-      JS.Expression init = _defs.remove(t);
+      js_ast.Expression init = _defs.remove(t);
       assert(init != null);
       return js.statement('let # = () => ((# = #.constFn(#))());',
           [name, name, _runtimeModule, init]);
@@ -149,7 +150,7 @@
   /// If [type] does not already have a generator name chosen for it,
   /// assign it one, using [typeRep] as the initializer for it.
   /// Emit the generator name.
-  JS.TemporaryId _nameType(DartType type, JS.Expression typeRep) {
+  js_ast.TemporaryId _nameType(DartType type, js_ast.Expression typeRep) {
     var temp = _names[type];
     if (temp == null) {
       _names[type] = temp = chooseTypeName(type);
@@ -169,12 +170,12 @@
   /// parameter.
   final _scopeDependencies = <TypeParameterElement, List<DartType>>{};
 
-  TypeTable(JS.Identifier runtime) : _generators = _GeneratorTable(runtime);
+  TypeTable(js_ast.Identifier runtime) : _generators = _GeneratorTable(runtime);
 
   /// Emit a list of statements declaring the cache variables and generator
   /// definitions tracked by the table.  If [formals] is present, only
   /// emit the definitions which depend on the formals.
-  List<JS.Statement> discharge([List<TypeParameterElement> formals]) {
+  List<js_ast.Statement> discharge([List<TypeParameterElement> formals]) {
     var filter = formals?.expand((p) => _scopeDependencies[p] ?? <DartType>[]);
     var stmts = [_generators].expand((c) => c.discharge(filter)).toList();
     formals?.forEach(_scopeDependencies.remove);
@@ -205,7 +206,8 @@
   /// Given a type [type], and a JS expression [typeRep] which implements it,
   /// add the type and its representation to the table, returning an
   /// expression which implements the type (but which caches the value).
-  JS.Expression nameType(ParameterizedType type, JS.Expression typeRep) {
+  js_ast.Expression nameType(
+      ParameterizedType type, js_ast.Expression typeRep) {
     if (!_generators.isNamed(type) && recordScopeDependencies(type)) {
       return typeRep;
     }
@@ -223,10 +225,11 @@
   /// should be a function that is invoked to compute the type, rather than the
   /// type itself. This allows better integration with `lazyFn`, avoiding an
   /// extra level of indirection.
-  JS.Expression nameFunctionType(FunctionType type, JS.Expression typeRep,
+  js_ast.Expression nameFunctionType(
+      FunctionType type, js_ast.Expression typeRep,
       {bool lazy = false}) {
     if (!_generators.isNamed(type) && recordScopeDependencies(type)) {
-      return lazy ? JS.ArrowFun([], typeRep) : typeRep;
+      return lazy ? js_ast.ArrowFun([], typeRep) : typeRep;
     }
 
     var name = _generators._nameType(type, typeRep);
diff --git a/pkg/dev_compiler/lib/src/compiler/shared_compiler.dart b/pkg/dev_compiler/lib/src/compiler/shared_compiler.dart
index 6a3182d..21daddb 100644
--- a/pkg/dev_compiler/lib/src/compiler/shared_compiler.dart
+++ b/pkg/dev_compiler/lib/src/compiler/shared_compiler.dart
@@ -5,10 +5,8 @@
 import 'dart:collection';
 import 'package:meta/meta.dart';
 
-import '../compiler/js_metalet.dart' as JS;
-import '../compiler/js_names.dart' as JS;
-import '../compiler/js_utils.dart' as JS;
-import '../js_ast/js_ast.dart' as JS;
+import '../compiler/js_names.dart' as js_ast;
+import '../js_ast/js_ast.dart' as js_ast;
 import '../js_ast/js_ast.dart' show js;
 
 /// Shared code between Analyzer and Kernel backends.
@@ -20,34 +18,34 @@
   /// returned by any `return;` statement.
   ///
   /// This lets DDC use the setter method's return value directly.
-  final List<JS.Identifier> _operatorSetResultStack = [];
+  final List<js_ast.Identifier> _operatorSetResultStack = [];
 
   /// Private member names in this module, organized by their library.
-  final _privateNames = HashMap<Library, HashMap<String, JS.TemporaryId>>();
+  final _privateNames = HashMap<Library, HashMap<String, js_ast.TemporaryId>>();
 
   /// Extension member symbols for adding Dart members to JS types.
   ///
   /// These are added to the [extensionSymbolsModule]; see that field for more
   /// information.
-  final _extensionSymbols = <String, JS.TemporaryId>{};
+  final _extensionSymbols = <String, js_ast.TemporaryId>{};
 
   /// The set of libraries we are currently compiling, and the temporaries used
   /// to refer to them.
-  final _libraries = <Library, JS.Identifier>{};
+  final _libraries = <Library, js_ast.Identifier>{};
 
   /// Imported libraries, and the temporaries used to refer to them.
-  final _imports = <Library, JS.TemporaryId>{};
+  final _imports = <Library, js_ast.TemporaryId>{};
 
   /// The identifier used to reference DDC's core "dart:_runtime" library from
   /// generated JS code, typically called "dart" e.g. `dart.dcall`.
   @protected
-  JS.Identifier runtimeModule;
+  js_ast.Identifier runtimeModule;
 
   /// The identifier used to reference DDC's "extension method" symbols, used to
   /// safely add Dart-specific member names to JavaScript classes, such as
   /// primitive types (e.g. String) or DOM types in "dart:html".
   @protected
-  JS.Identifier extensionSymbolsModule;
+  js_ast.Identifier extensionSymbolsModule;
 
   /// Whether we're currently building the SDK, which may require special
   /// bootstrapping logic.
@@ -60,18 +58,18 @@
   /// The temporary variable that stores named arguments (these are passed via a
   /// JS object literal, to match JS conventions).
   @protected
-  final namedArgumentTemp = JS.TemporaryId('opts');
+  final namedArgumentTemp = js_ast.TemporaryId('opts');
 
   /// The list of output module items, in the order they need to be emitted in.
   @protected
-  final moduleItems = <JS.ModuleItem>[];
+  final moduleItems = <js_ast.ModuleItem>[];
 
   /// Like [moduleItems] but for items that should be emitted after classes.
   ///
   /// This is used for deferred supertypes of mutually recursive non-generic
   /// classes.
   @protected
-  final afterClassDefItems = <JS.ModuleItem>[];
+  final afterClassDefItems = <js_ast.ModuleItem>[];
 
   /// The type used for private Dart [Symbol]s.
   @protected
@@ -126,12 +124,12 @@
 
   /// Emits the expression necessary to access a constructor of [type];
   @protected
-  JS.Expression emitConstructorAccess(InterfaceType type);
+  js_ast.Expression emitConstructorAccess(InterfaceType type);
 
   /// When compiling the body of a `operator []=` method, this will be non-null
   /// and will indicate the the value that should be returned from any `return;`
   /// statements.
-  JS.Identifier get _operatorSetResult {
+  js_ast.Identifier get _operatorSetResult {
     var stack = _operatorSetResultStack;
     return stack.isEmpty ? null : stack.last;
   }
@@ -141,12 +139,12 @@
   ///
   /// See also [exitFunction] and [emitReturnStatement].
   @protected
-  void enterFunction(String name, List<JS.Parameter> formals,
+  void enterFunction(String name, List<js_ast.Parameter> formals,
       bool Function() isLastParamMutated) {
     if (name == '[]=') {
       _operatorSetResultStack.add(isLastParamMutated()
-          ? JS.TemporaryId((formals.last as JS.Identifier).name)
-          : formals.last as JS.Identifier);
+          ? js_ast.TemporaryId((formals.last as js_ast.Identifier).name)
+          : formals.last as js_ast.Identifier);
     } else {
       _operatorSetResultStack.add(null);
     }
@@ -155,8 +153,8 @@
   /// Called when finished emitting methods/functions, and must correspond to a
   /// previous [enterFunction] call.
   @protected
-  JS.Block exitFunction(
-      String name, List<JS.Parameter> formals, JS.Block code) {
+  js_ast.Block exitFunction(
+      String name, List<js_ast.Parameter> formals, js_ast.Block code) {
     if (name == "==" &&
         formals.isNotEmpty &&
         currentLibraryUri.scheme != 'dart') {
@@ -177,7 +175,7 @@
       var valueParam = formals.last;
       var statements = code.statements;
       if (statements.isEmpty || !statements.last.alwaysReturns) {
-        statements.add(JS.Return(setOperatorResult));
+        statements.add(js_ast.Return(setOperatorResult));
       }
       if (!identical(setOperatorResult, valueParam)) {
         // If the value parameter was mutated, then we use a temporary
@@ -193,12 +191,14 @@
   /// Emits a return statement `return <value>;`, handling special rules for
   /// the `operator []=` method.
   @protected
-  JS.Statement emitReturnStatement(JS.Expression value) {
+  js_ast.Statement emitReturnStatement(js_ast.Expression value) {
     if (_operatorSetResult != null) {
-      var result = JS.Return(_operatorSetResult);
-      return value != null ? JS.Block([value.toStatement(), result]) : result;
+      var result = js_ast.Return(_operatorSetResult);
+      return value != null
+          ? js_ast.Block([value.toStatement(), result])
+          : result;
     }
-    return value != null ? value.toReturn() : JS.Return();
+    return value != null ? value.toReturn() : js_ast.Return();
   }
 
   /// Prepends the `dart.` and then uses [js.call] to parse the specified JS
@@ -213,13 +213,13 @@
   ///     dart.asInt(<expr>)
   ///
   @protected
-  JS.Expression runtimeCall(String code, [List<Object> args]) =>
+  js_ast.Expression runtimeCall(String code, [List<Object> args]) =>
       js.call('#.$code', <Object>[runtimeModule, ...?args]);
 
   /// Calls [runtimeCall] and uses `toStatement()` to convert the resulting
   /// expression into a statement.
   @protected
-  JS.Statement runtimeStatement(String code, [List<Object> args]) =>
+  js_ast.Statement runtimeStatement(String code, [List<Object> args]) =>
       runtimeCall(code, args).toStatement();
 
   /// Emits a private name JS Symbol for [name] scoped to the Dart [library].
@@ -229,7 +229,7 @@
   /// member names, that won't collide at runtime, as required by the Dart
   /// language spec.
   @protected
-  JS.TemporaryId emitPrivateNameSymbol(Library library, String name) {
+  js_ast.TemporaryId emitPrivateNameSymbol(Library library, String name) {
     /// Initializes the JS `Symbol` for the private member [name] in [library].
     ///
     /// If the library is in the current JS module ([_libraries] contains it),
@@ -243,9 +243,9 @@
     /// If the library is imported, then the existing private name will be
     /// retrieved from it. In both cases, we use the same `dart.privateName`
     /// runtime call.
-    JS.TemporaryId initPrivateNameSymbol() {
+    js_ast.TemporaryId initPrivateNameSymbol() {
       var idName = name.endsWith('=') ? name.replaceAll('=', '_') : name;
-      var id = JS.TemporaryId(idName);
+      var id = js_ast.TemporaryId(idName);
       moduleItems.add(js.statement('const # = #.privateName(#, #)',
           [id, runtimeModule, emitLibraryName(library), js.string(name)]));
       return id;
@@ -262,12 +262,13 @@
   /// `dart.defineValue(className, name, value)`. This is required when
   /// `FunctionNode.prototype` already defins a getters with the same name.
   @protected
-  JS.Expression defineValueOnClass(Class c, JS.Expression className,
-      JS.Expression nameExpr, JS.Expression value) {
+  js_ast.Expression defineValueOnClass(Class c, js_ast.Expression className,
+      js_ast.Expression nameExpr, js_ast.Expression value) {
     var args = [className, nameExpr, value];
-    if (nameExpr is JS.LiteralString) {
+    if (nameExpr is js_ast.LiteralString) {
       var name = nameExpr.valueWithoutQuotes;
-      if (JS.isFunctionPrototypeGetter(name) || superclassHasStatic(c, name)) {
+      if (js_ast.isFunctionPrototypeGetter(name) ||
+          superclassHasStatic(c, name)) {
         return runtimeCall('defineValue(#, #, #)', args);
       }
     }
@@ -300,10 +301,10 @@
   /// per-module, though, as that would be relatively easy for the compiler to
   /// implement once we have a single Kernel backend).
   @protected
-  JS.Expression cacheConst(JS.Expression jsExpr) {
+  js_ast.Expression cacheConst(js_ast.Expression jsExpr) {
     if (currentFunction == null) return jsExpr;
 
-    var temp = JS.TemporaryId('const');
+    var temp = js_ast.TemporaryId('const');
     moduleItems.add(js.statement('let #;', [temp]));
     return js.call('# || (# = #)', [temp, temp, jsExpr]);
   }
@@ -313,11 +314,11 @@
   /// If the symbol refers to a private name, its library will be set to the
   /// [currentLibrary], so the Symbol is scoped properly.
   @protected
-  JS.Expression emitDartSymbol(String symbolName) {
+  js_ast.Expression emitDartSymbol(String symbolName) {
     // TODO(vsm): Handle qualified symbols correctly.
     var last = symbolName.split('.').last;
     var name = js.escapedString(symbolName, "'");
-    JS.Expression result;
+    js_ast.Expression result;
     if (last.startsWith('_')) {
       var nativeSymbol = emitPrivateNameSymbol(currentLibrary, last);
       result = js.call('new #.new(#, #)',
@@ -332,7 +333,7 @@
   /// Calls the `dart.const` function in "dart:_runtime" to canonicalize a
   /// constant instance of a user-defined class stored in [expr].
   @protected
-  JS.Expression canonicalizeConstObject(JS.Expression expr) =>
+  js_ast.Expression canonicalizeConstObject(js_ast.Expression expr) =>
       cacheConst(runtimeCall('const(#)', [expr]));
 
   /// Emits preamble for the module containing [libraries], and returns the
@@ -351,31 +352,31 @@
   /// [extensionSymbolsModule], as well as the [_libraries] map needed by
   /// [emitLibraryName].
   @protected
-  List<JS.ModuleItem> startModule(Iterable<Library> libraries) {
+  List<js_ast.ModuleItem> startModule(Iterable<Library> libraries) {
     isBuildingSdk = libraries.any(isSdkInternalRuntime);
     if (isBuildingSdk) {
       // Don't allow these to be renamed when we're building the SDK.
       // There is JS code in dart:* that depends on their names.
-      runtimeModule = JS.Identifier('dart');
-      extensionSymbolsModule = JS.Identifier('dartx');
+      runtimeModule = js_ast.Identifier('dart');
+      extensionSymbolsModule = js_ast.Identifier('dartx');
     } else {
       // Otherwise allow these to be renamed so users can write them.
-      runtimeModule = JS.TemporaryId('dart');
-      extensionSymbolsModule = JS.TemporaryId('dartx');
+      runtimeModule = js_ast.TemporaryId('dart');
+      extensionSymbolsModule = js_ast.TemporaryId('dartx');
     }
 
     // Initialize our library variables.
-    var items = <JS.ModuleItem>[];
-    var exports = <JS.NameSpecifier>[];
+    var items = <js_ast.ModuleItem>[];
+    var exports = <js_ast.NameSpecifier>[];
 
     if (isBuildingSdk) {
       // Bootstrap the ability to create Dart library objects.
-      var libraryProto = JS.TemporaryId('_library');
+      var libraryProto = js_ast.TemporaryId('_library');
       items.add(js.statement('const # = Object.create(null)', libraryProto));
       items.add(js.statement(
           'const # = Object.create(#)', [runtimeModule, libraryProto]));
       items.add(js.statement('#.library = #', [runtimeModule, libraryProto]));
-      exports.add(JS.NameSpecifier(runtimeModule));
+      exports.add(js_ast.NameSpecifier(runtimeModule));
     }
 
     for (var library in libraries) {
@@ -383,12 +384,12 @@
         _libraries[library] = runtimeModule;
         continue;
       }
-      var id = JS.TemporaryId(jsLibraryName(library));
+      var id = js_ast.TemporaryId(jsLibraryName(library));
       _libraries[library] = id;
 
       items.add(js.statement(
           'const # = Object.create(#.library)', [id, runtimeModule]));
-      exports.add(JS.NameSpecifier(id));
+      exports.add(js_ast.NameSpecifier(id));
     }
 
     // dart:_runtime has a magic module that holds extension method symbols.
@@ -397,15 +398,15 @@
       var id = extensionSymbolsModule;
       items.add(js.statement(
           'const # = Object.create(#.library)', [id, runtimeModule]));
-      exports.add(JS.NameSpecifier(id));
+      exports.add(js_ast.NameSpecifier(id));
     }
 
-    items.add(JS.ExportDeclaration(JS.ExportClause(exports)));
+    items.add(js_ast.ExportDeclaration(js_ast.ExportClause(exports)));
 
     if (isBuildingSdk) {
       // Initialize the private name function.
       // To bootstrap the SDK, this needs to be emitted before other code.
-      var symbol = JS.TemporaryId('_privateNames');
+      var symbol = js_ast.TemporaryId('_privateNames');
       items.add(js.statement('const # = Symbol("_privateNames")', symbol));
       items.add(js.statement(r'''
         #.privateName = function(library, name) {
@@ -423,16 +424,16 @@
 
   /// Returns the canonical name to refer to the Dart library.
   @protected
-  JS.Identifier emitLibraryName(Library library) {
+  js_ast.Identifier emitLibraryName(Library library) {
     // It's either one of the libraries in this module, or it's an import.
     return _libraries[library] ??
         _imports.putIfAbsent(
-            library, () => JS.TemporaryId(jsLibraryName(library)));
+            library, () => js_ast.TemporaryId(jsLibraryName(library)));
   }
 
   /// Emits imports and extension methods into [items].
   @protected
-  void emitImportsAndExtensionSymbols(List<JS.ModuleItem> items) {
+  void emitImportsAndExtensionSymbols(List<js_ast.ModuleItem> items) {
     var modules = Map<String, List<Library>>();
 
     for (var import in _imports.keys) {
@@ -454,20 +455,20 @@
       //     import {foo as foo$} from 'foo'; // if rename was needed
       //
       var imports =
-          libraries.map((l) => JS.NameSpecifier(_imports[l])).toList();
+          libraries.map((l) => js_ast.NameSpecifier(_imports[l])).toList();
       if (module == coreModuleName) {
-        imports.add(JS.NameSpecifier(runtimeModule));
-        imports.add(JS.NameSpecifier(extensionSymbolsModule));
+        imports.add(js_ast.NameSpecifier(runtimeModule));
+        imports.add(js_ast.NameSpecifier(extensionSymbolsModule));
       }
 
-      items.add(JS.ImportDeclaration(
+      items.add(js_ast.ImportDeclaration(
           namedImports: imports, from: js.string(module, "'")));
     });
 
     // Initialize extension symbols
     _extensionSymbols.forEach((name, id) {
-      JS.Expression value =
-          JS.PropertyAccess(extensionSymbolsModule, propertyName(name));
+      js_ast.Expression value =
+          js_ast.PropertyAccess(extensionSymbolsModule, propertyName(name));
       if (isBuildingSdk) {
         value = js.call('# = Symbol(#)', [value, js.string("dartx.$name")]);
       }
@@ -476,20 +477,20 @@
   }
 
   void _emitDebuggerExtensionInfo(String name) {
-    var properties = <JS.Property>[];
-    var parts = <JS.Property>[];
+    var properties = <js_ast.Property>[];
+    var parts = <js_ast.Property>[];
     _libraries.forEach((library, value) {
       // TODO(jacobr): we could specify a short library name instead of the
       // full library uri if we wanted to save space.
       var libraryName = js.escapedString(jsLibraryDebuggerName(library));
-      properties.add(JS.Property(libraryName, value));
+      properties.add(js_ast.Property(libraryName, value));
       var partNames = jsPartDebuggerNames(library);
       if (partNames.isNotEmpty) {
-        parts.add(JS.Property(libraryName, js.stringArray(partNames)));
+        parts.add(js_ast.Property(libraryName, js.stringArray(partNames)));
       }
     });
-    var module = JS.ObjectInitializer(properties, multiline: true);
-    var partMap = JS.ObjectInitializer(parts, multiline: true);
+    var module = js_ast.ObjectInitializer(properties, multiline: true);
+    var partMap = js_ast.ObjectInitializer(parts, multiline: true);
 
     // Track the module name for each library in the module.
     // This data is only required for debugging.
@@ -509,7 +510,8 @@
   /// Note, this function mutates the items list and returns it as the `body`
   /// field of the result.
   @protected
-  JS.Program finishModule(List<JS.ModuleItem> items, String moduleName) {
+  js_ast.Program finishModule(
+      List<js_ast.ModuleItem> items, String moduleName) {
     // TODO(jmesserly): there's probably further consolidation we can do
     // between DDC's two backends, by moving more code into this method, as the
     // code between `startModule` and `finishModule` is very similar in both.
@@ -520,16 +522,16 @@
     moduleItems.clear();
 
     // Build the module.
-    return JS.Program(items, name: moduleName);
+    return js_ast.Program(items, name: moduleName);
   }
 
   /// Flattens blocks in [items] to a single list.
   ///
   /// This will not flatten blocks that are marked as being scopes.
   void _copyAndFlattenBlocks(
-      List<JS.ModuleItem> result, Iterable<JS.ModuleItem> items) {
+      List<js_ast.ModuleItem> result, Iterable<js_ast.ModuleItem> items) {
     for (var item in items) {
-      if (item is JS.Block && !item.isScope) {
+      if (item is js_ast.Block && !item.isScope) {
         _copyAndFlattenBlocks(result, item.statements);
       } else if (item != null) {
         result.add(item);
@@ -544,11 +546,11 @@
   /// Do not call this directly; you want [_emitMemberName], which knows how to
   /// handle the many details involved in naming.
   @protected
-  JS.TemporaryId getExtensionSymbolInternal(String name) {
+  js_ast.TemporaryId getExtensionSymbolInternal(String name) {
     return _extensionSymbols.putIfAbsent(
         name,
-        () => JS.TemporaryId(
-            '\$${JS.friendlyNameForDartOperator[name] ?? name}'));
+        () => js_ast.TemporaryId(
+            '\$${js_ast.friendlyNameForDartOperator[name] ?? name}'));
   }
 
   /// Shorthand for identifier-like property names.
@@ -556,7 +558,7 @@
   /// identifiers if it can.
   // TODO(jmesserly): avoid the round tripping through quoted form.
   @protected
-  JS.LiteralString propertyName(String name) => js.string(name, "'");
+  js_ast.LiteralString propertyName(String name) => js.string(name, "'");
 
   /// Unique identifier indicating the location to inline the source map.
   ///
@@ -568,7 +570,7 @@
 }
 
 /// Whether a variable with [name] is referenced in the [node].
-bool variableIsReferenced(String name, JS.Node node) {
+bool variableIsReferenced(String name, js_ast.Node node) {
   var finder = _IdentifierFinder.instance;
   finder.nameToFind = name;
   finder.found = false;
@@ -576,7 +578,7 @@
   return finder.found;
 }
 
-class _IdentifierFinder extends JS.BaseVisitor<void> {
+class _IdentifierFinder extends js_ast.BaseVisitor<void> {
   String nameToFind;
   bool found = false;
 
@@ -593,18 +595,18 @@
   }
 }
 
-class YieldFinder extends JS.BaseVisitor {
+class YieldFinder extends js_ast.BaseVisitor {
   bool hasYield = false;
   bool hasThis = false;
   bool _nestedFunction = false;
 
   @override
-  visitThis(JS.This node) {
+  visitThis(js_ast.This node) {
     hasThis = true;
   }
 
   @override
-  visitFunctionExpression(JS.FunctionExpression node) {
+  visitFunctionExpression(js_ast.FunctionExpression node) {
     var savedNested = _nestedFunction;
     _nestedFunction = true;
     super.visitFunctionExpression(node);
@@ -612,13 +614,13 @@
   }
 
   @override
-  visitYield(JS.Yield node) {
+  visitYield(js_ast.Yield node) {
     if (!_nestedFunction) hasYield = true;
     super.visitYield(node);
   }
 
   @override
-  visitNode(JS.Node node) {
+  visitNode(js_ast.Node node) {
     if (hasYield && hasThis) return; // found both, nothing more to do.
     super.visitNode(node);
   }
@@ -626,39 +628,40 @@
 
 /// Given the function [fn], returns a function declaration statement, binding
 /// `this` and `super` if necessary (using an arrow function).
-JS.Statement toBoundFunctionStatement(JS.Fun fn, JS.Identifier name) {
+js_ast.Statement toBoundFunctionStatement(
+    js_ast.Fun fn, js_ast.Identifier name) {
   if (usesThisOrSuper(fn)) {
     return js.statement('const # = (#) => {#}', [name, fn.params, fn.body]);
   } else {
-    return JS.FunctionDeclaration(name, fn);
+    return js_ast.FunctionDeclaration(name, fn);
   }
 }
 
 /// Returns whether [node] uses `this` or `super`.
-bool usesThisOrSuper(JS.Expression node) {
+bool usesThisOrSuper(js_ast.Expression node) {
   var finder = _ThisOrSuperFinder.instance;
   finder.found = false;
   node.accept(finder);
   return finder.found;
 }
 
-class _ThisOrSuperFinder extends JS.BaseVisitor<void> {
+class _ThisOrSuperFinder extends js_ast.BaseVisitor<void> {
   bool found = false;
 
   static final instance = _ThisOrSuperFinder();
 
   @override
-  visitThis(JS.This node) {
+  visitThis(js_ast.This node) {
     found = true;
   }
 
   @override
-  visitSuper(JS.Super node) {
+  visitSuper(js_ast.Super node) {
     found = true;
   }
 
   @override
-  visitNode(JS.Node node) {
+  visitNode(js_ast.Node node) {
     if (!found) super.visitNode(node);
   }
 }
diff --git a/pkg/dev_compiler/lib/src/js_ast/js_ast.dart b/pkg/dev_compiler/lib/src/js_ast/js_ast.dart
index ee8289e..bf84e7a 100644
--- a/pkg/dev_compiler/lib/src/js_ast/js_ast.dart
+++ b/pkg/dev_compiler/lib/src/js_ast/js_ast.dart
@@ -5,6 +5,7 @@
 library js_ast;
 
 import 'precedence.dart';
+// ignore: library_prefixes
 import 'characters.dart' as charCodes;
 
 part 'nodes.dart';
diff --git a/pkg/dev_compiler/lib/src/kernel/command.dart b/pkg/dev_compiler/lib/src/kernel/command.dart
index 2e897f0..ca85c12 100644
--- a/pkg/dev_compiler/lib/src/kernel/command.dart
+++ b/pkg/dev_compiler/lib/src/kernel/command.dart
@@ -18,11 +18,11 @@
 import 'package:path/path.dart' as path;
 import 'package:source_maps/source_maps.dart' show SourceMapBuilder;
 
-import '../compiler/js_names.dart' as JS;
+import '../compiler/js_names.dart' as js_ast;
 import '../compiler/module_builder.dart';
 import '../compiler/shared_command.dart';
 import '../compiler/shared_compiler.dart';
-import '../js_ast/js_ast.dart' as JS;
+import '../js_ast/js_ast.dart' as js_ast;
 import '../js_ast/js_ast.dart' show js;
 import '../js_ast/source_map_printer.dart' show SourceMapPrintingContext;
 
@@ -386,7 +386,7 @@
   JSCode(this.code, this.sourceMap);
 }
 
-JSCode jsProgramToCode(JS.Program moduleTree, ModuleFormat format,
+JSCode jsProgramToCode(js_ast.Program moduleTree, ModuleFormat format,
     {bool buildSourceMap = false,
     bool inlineSourceMap = false,
     String jsUrl,
@@ -394,20 +394,21 @@
     Map<String, String> bazelMapping,
     String customScheme,
     String multiRootOutputPath}) {
-  var opts = JS.JavaScriptPrintingOptions(
+  var opts = js_ast.JavaScriptPrintingOptions(
       allowKeywordsInProperties: true, allowSingleLineIfStatements: true);
-  JS.SimpleJavaScriptPrintingContext printer;
+  js_ast.SimpleJavaScriptPrintingContext printer;
   SourceMapBuilder sourceMap;
   if (buildSourceMap) {
     var sourceMapContext = SourceMapPrintingContext();
     sourceMap = sourceMapContext.sourceMap;
     printer = sourceMapContext;
   } else {
-    printer = JS.SimpleJavaScriptPrintingContext();
+    printer = js_ast.SimpleJavaScriptPrintingContext();
   }
 
   var tree = transformModuleFormat(format, moduleTree);
-  tree.accept(JS.Printer(opts, printer, localNamer: JS.TemporaryNamer(tree)));
+  tree.accept(
+      js_ast.Printer(opts, printer, localNamer: js_ast.TemporaryNamer(tree)));
 
   Map builtMap;
   if (buildSourceMap && sourceMap != null) {
diff --git a/pkg/dev_compiler/lib/src/kernel/compiler.dart b/pkg/dev_compiler/lib/src/kernel/compiler.dart
index 531ca40..5351443 100644
--- a/pkg/dev_compiler/lib/src/kernel/compiler.dart
+++ b/pkg/dev_compiler/lib/src/kernel/compiler.dart
@@ -15,12 +15,12 @@
 import 'package:kernel/type_environment.dart';
 import 'package:source_span/source_span.dart' show SourceLocation;
 
-import '../compiler/js_names.dart' as JS;
-import '../compiler/js_utils.dart' as JS;
+import '../compiler/js_names.dart' as js_ast;
+import '../compiler/js_utils.dart' as js_ast;
 import '../compiler/module_builder.dart' show pathToJSIdentifier;
 import '../compiler/shared_command.dart' show SharedCompilerOptions;
 import '../compiler/shared_compiler.dart';
-import '../js_ast/js_ast.dart' as JS;
+import '../js_ast/js_ast.dart' as js_ast;
 import '../js_ast/js_ast.dart' show js;
 import '../js_ast/source_map_printer.dart' show NodeEnd, NodeSpan, HoverComment;
 import 'constants.dart';
@@ -35,10 +35,10 @@
 class ProgramCompiler extends Object
     with SharedCompiler<Library, Class, InterfaceType, FunctionNode>
     implements
-        StatementVisitor<JS.Statement>,
-        ExpressionVisitor<JS.Expression>,
-        DartTypeVisitor<JS.Expression>,
-        ConstantVisitor<JS.Expression> {
+        StatementVisitor<js_ast.Statement>,
+        ExpressionVisitor<js_ast.Expression>,
+        DartTypeVisitor<js_ast.Expression>,
+        ConstantVisitor<js_ast.Expression> {
   final SharedCompilerOptions options;
 
   /// Maps a library URI import, that is not in [_libraries], to the
@@ -52,15 +52,15 @@
   VariableDeclaration _rethrowParameter;
 
   /// In an async* function, this represents the stream controller parameter.
-  JS.TemporaryId _asyncStarController;
+  js_ast.TemporaryId _asyncStarController;
 
   Set<Class> _pendingClasses;
 
   /// Temporary variables mapped to their corresponding JavaScript variable.
-  final _tempVariables = <VariableDeclaration, JS.TemporaryId>{};
+  final _tempVariables = <VariableDeclaration, js_ast.TemporaryId>{};
 
   /// Let variables collected for the given function.
-  List<JS.TemporaryId> _letVariables;
+  List<js_ast.TemporaryId> _letVariables;
 
   /// The class that is emitting its base class or mixin references, otherwise
   /// null.
@@ -116,7 +116,7 @@
 
   bool _superAllowed = true;
 
-  final _superHelpers = Map<String, JS.Method>();
+  final _superHelpers = Map<String, js_ast.Method>();
 
   // Compilation of Kernel's [BreakStatement].
   //
@@ -257,7 +257,7 @@
 
   bool get emitMetadata => options.emitMetadata;
 
-  JS.Program emitModule(Component component, List<Component> summaries,
+  js_ast.Program emitModule(Component component, List<Component> summaries,
       List<Uri> summaryUris, Map<Uri, String> moduleImportForSummary) {
     if (moduleItems.isNotEmpty) {
       throw StateError('Can only call emitModule once.');
@@ -354,7 +354,7 @@
   String libraryToModule(Library library) {
     if (library.importUri.scheme == 'dart') {
       // TODO(jmesserly): we need to split out HTML.
-      return JS.dartSdkModule;
+      return js_ast.dartSdkModule;
     }
     var summary = _importToSummary[library];
     var moduleName = _summaryToModule[summary];
@@ -466,7 +466,7 @@
     if (c != null && _emittingClassExtends) _emitClass(c);
   }
 
-  JS.Statement _emitClassDeclaration(Class c) {
+  js_ast.Statement _emitClassDeclaration(Class c) {
     // Mixins are unrolled in _defineClass.
     if (c.isAnonymousMixin) return null;
 
@@ -481,8 +481,8 @@
     // https://github.com/dart-lang/sdk/issues/31003
     var className = c.typeParameters.isNotEmpty
         ? (c == _jsArrayClass
-            ? JS.Identifier(c.name)
-            : JS.TemporaryId(getLocalClassName(c)))
+            ? js_ast.Identifier(c.name)
+            : js_ast.TemporaryId(getLocalClassName(c)))
         : _emitTopLevelName(c);
 
     var savedClassProperties = _classProperties;
@@ -492,9 +492,9 @@
     var jsCtors = _defineConstructors(c, className);
     var jsMethods = _emitClassMethods(c);
 
-    var body = <JS.Statement>[];
+    var body = <js_ast.Statement>[];
     _emitSuperHelperSymbols(body);
-    var deferredSupertypes = <JS.Statement>[];
+    var deferredSupertypes = <js_ast.Statement>[];
 
     // Emit the class, e.g. `core.Object = class Object { ... }`
     _defineClass(c, className, jsMethods, body, deferredSupertypes);
@@ -518,7 +518,7 @@
     }
     _emitClassMetadata(c.annotations, className, body);
 
-    var classDef = JS.Statement.from(body);
+    var classDef = js_ast.Statement.from(body);
     var typeFormals = c.typeParameters;
     if (typeFormals.isNotEmpty) {
       classDef = _defineClassTypeArguments(
@@ -535,13 +535,13 @@
     }
 
     _classProperties = savedClassProperties;
-    return JS.Statement.from(body);
+    return js_ast.Statement.from(body);
   }
 
   /// Wraps a possibly generic class in its type arguments.
-  JS.Statement _defineClassTypeArguments(
-      NamedNode c, List<TypeParameter> formals, JS.Statement body,
-      [JS.Expression className, List<JS.Statement> deferredBaseClass]) {
+  js_ast.Statement _defineClassTypeArguments(
+      NamedNode c, List<TypeParameter> formals, js_ast.Statement body,
+      [js_ast.Expression className, List<js_ast.Statement> deferredBaseClass]) {
     assert(formals.isNotEmpty);
     var name = getTopLevelName(c);
     var jsFormals = _emitTypeFormals(formals);
@@ -549,7 +549,7 @@
       jsFormals,
       _typeTable.discharge(formals),
       body,
-      className ?? JS.Identifier(name)
+      className ?? js_ast.Identifier(name)
     ]);
 
     var genericArgs = [
@@ -565,14 +565,15 @@
         [genericName, genericCall, _emitTopLevelName(c), genericName]);
   }
 
-  JS.Statement _emitClassStatement(Class c, JS.Expression className,
-      JS.Expression heritage, List<JS.Method> methods) {
+  js_ast.Statement _emitClassStatement(Class c, js_ast.Expression className,
+      js_ast.Expression heritage, List<js_ast.Method> methods) {
     if (c.typeParameters.isNotEmpty) {
-      return JS.ClassExpression(className as JS.Identifier, heritage, methods)
+      return js_ast.ClassExpression(
+              className as js_ast.Identifier, heritage, methods)
           .toStatement();
     }
-    var classExpr = JS.ClassExpression(
-        JS.TemporaryId(getLocalClassName(c)), heritage, methods);
+    var classExpr = js_ast.ClassExpression(
+        js_ast.TemporaryId(getLocalClassName(c)), heritage, methods);
     return js.statement('# = #;', [className, classExpr]);
   }
 
@@ -605,46 +606,50 @@
   /// minimal compiler and runtime changes.
   void _emitMixinStatement(
       Class c,
-      JS.Expression className,
-      JS.Expression heritage,
-      List<JS.Method> methods,
-      List<JS.Statement> body) {
+      js_ast.Expression className,
+      js_ast.Expression heritage,
+      List<js_ast.Method> methods,
+      List<js_ast.Statement> body) {
     var staticMethods = methods.where((m) => m.isStatic).toList();
     var instanceMethods = methods.where((m) => !m.isStatic).toList();
 
     body.add(_emitClassStatement(c, className, heritage, staticMethods));
-    var superclassId = JS.TemporaryId(getLocalClassName(c.superclass));
-    var classId = className is JS.Identifier
+    var superclassId = js_ast.TemporaryId(getLocalClassName(c.superclass));
+    var classId = className is js_ast.Identifier
         ? className
-        : JS.TemporaryId(getLocalClassName(c));
+        : js_ast.TemporaryId(getLocalClassName(c));
 
     var mixinMemberClass =
-        JS.ClassExpression(classId, superclassId, instanceMethods);
+        js_ast.ClassExpression(classId, superclassId, instanceMethods);
 
-    JS.Node arrowFnBody = mixinMemberClass;
-    var extensionInit = <JS.Statement>[];
+    js_ast.Node arrowFnBody = mixinMemberClass;
+    var extensionInit = <js_ast.Statement>[];
     _defineExtensionMembers(classId, extensionInit);
     if (extensionInit.isNotEmpty) {
       extensionInit.insert(0, mixinMemberClass.toStatement());
       extensionInit.add(classId.toReturn());
-      arrowFnBody = JS.Block(extensionInit);
+      arrowFnBody = js_ast.Block(extensionInit);
     }
 
     body.add(js.statement('#[#.mixinOn] = #', [
       className,
       runtimeModule,
-      JS.ArrowFun([superclassId], arrowFnBody)
+      js_ast.ArrowFun([superclassId], arrowFnBody)
     ]));
   }
 
-  void _defineClass(Class c, JS.Expression className, List<JS.Method> methods,
-      List<JS.Statement> body, List<JS.Statement> deferredSupertypes) {
+  void _defineClass(
+      Class c,
+      js_ast.Expression className,
+      List<js_ast.Method> methods,
+      List<js_ast.Statement> body,
+      List<js_ast.Statement> deferredSupertypes) {
     if (c == coreTypes.objectClass) {
       body.add(_emitClassStatement(c, className, null, methods));
       return;
     }
 
-    JS.Expression emitDeferredType(DartType t) {
+    js_ast.Expression emitDeferredType(DartType t) {
       if (t is InterfaceType && t.typeArguments.isNotEmpty) {
         _declareBeforeUse(t.classNode);
         return _emitGenericClassType(t, t.typeArguments.map(emitDeferredType));
@@ -709,8 +714,9 @@
 
     var hasUnnamedSuper = _hasUnnamedInheritedConstructor(superclass);
 
-    void emitMixinConstructors(JS.Expression className, InterfaceType mixin) {
-      JS.Statement mixinCtor;
+    void emitMixinConstructors(
+        js_ast.Expression className, InterfaceType mixin) {
+      js_ast.Statement mixinCtor;
       if (_hasUnnamedConstructor(mixin.classNode)) {
         mixinCtor = js.statement('#.#.call(this);', [
           emitClassRef(mixin),
@@ -732,7 +738,7 @@
             _emitSuperConstructorCall(className, name, jsParams),
         ];
         body.add(_addConstructorToClass(
-            c, className, name, JS.Fun(jsParams, JS.Block(ctorBody))));
+            c, className, name, js_ast.Fun(jsParams, js_ast.Block(ctorBody))));
       }
     }
 
@@ -775,8 +781,8 @@
         //     applyMixin(C, class C$ extends M { <methods>  });
         mixinBody.add(runtimeStatement('applyMixin(#, #)', [
           classExpr,
-          JS.ClassExpression(
-              JS.TemporaryId(getLocalClassName(c)), mixinClass, methods)
+          js_ast.ClassExpression(
+              js_ast.TemporaryId(getLocalClassName(c)), mixinClass, methods)
         ]));
       }
 
@@ -794,14 +800,14 @@
       var m = mixins[i];
       var mixinName =
           getLocalClassName(superclass) + '_' + getLocalClassName(m.classNode);
-      var mixinId = JS.TemporaryId(mixinName + '\$');
+      var mixinId = js_ast.TemporaryId(mixinName + '\$');
       // Bind the mixin class to a name to workaround a V8 bug with es6 classes
       // and anonymous function names.
       // TODO(leafp:) Eliminate this once the bug is fixed:
       // https://bugs.chromium.org/p/v8/issues/detail?id=7069
       body.add(js.statement("const # = #", [
         mixinId,
-        JS.ClassExpression(JS.TemporaryId(mixinName), baseClass, [])
+        js_ast.ClassExpression(js_ast.TemporaryId(mixinName), baseClass, [])
       ]));
 
       emitMixinConstructors(mixinId, m);
@@ -828,14 +834,15 @@
   }
 
   /// Defines all constructors for this class as ES5 constructors.
-  List<JS.Statement> _defineConstructors(Class c, JS.Expression className) {
-    var body = <JS.Statement>[];
+  List<js_ast.Statement> _defineConstructors(
+      Class c, js_ast.Expression className) {
+    var body = <js_ast.Statement>[];
     if (c.isAnonymousMixin || isMixinAliasClass(c)) {
       // We already handled this when we defined the class.
       return body;
     }
 
-    addConstructor(String name, JS.Expression jsCtor) {
+    addConstructor(String name, js_ast.Expression jsCtor) {
       body.add(_addConstructorToClass(c, className, name, jsCtor));
     }
 
@@ -861,9 +868,9 @@
     return body;
   }
 
-  JS.Statement _emitClassTypeTests(
-      Class c, JS.Expression className, List<JS.Statement> body) {
-    JS.Expression getInterfaceSymbol(Class interface) {
+  js_ast.Statement _emitClassTypeTests(
+      Class c, js_ast.Expression className, List<js_ast.Statement> body) {
+    js_ast.Expression getInterfaceSymbol(Class interface) {
       var library = interface.enclosingLibrary;
       if (library == coreTypes.coreLibrary ||
           library == coreTypes.asyncLibrary) {
@@ -880,7 +887,7 @@
       return null;
     }
 
-    void markSubtypeOf(JS.Expression testSymbol) {
+    void markSubtypeOf(js_ast.Expression testSymbol) {
       body.add(js.statement('#.prototype[#] = true', [className, testSymbol]));
     }
 
@@ -1054,7 +1061,7 @@
     if (isClassSymbol == null) {
       // TODO(jmesserly): we could export these symbols, if we want to mark
       // implemented interfaces for user-defined classes.
-      var id = JS.TemporaryId("_is_${getLocalClassName(c)}_default");
+      var id = js_ast.TemporaryId("_is_${getLocalClassName(c)}_default");
       moduleItems.add(
           js.statement('const # = Symbol(#);', [id, js.string(id.name, "'")]));
       isClassSymbol = id;
@@ -1073,21 +1080,21 @@
   }
 
   void _emitDartSymbols(
-      Iterable<JS.TemporaryId> vars, List<JS.ModuleItem> body) {
+      Iterable<js_ast.TemporaryId> vars, List<js_ast.ModuleItem> body) {
     for (var id in vars) {
       body.add(js.statement('const # = Symbol(#)', [id, js.string(id.name)]));
     }
   }
 
-  void _emitSuperHelperSymbols(List<JS.Statement> body) {
+  void _emitSuperHelperSymbols(List<js_ast.Statement> body) {
     _emitDartSymbols(
-        _superHelpers.values.map((m) => m.name as JS.TemporaryId), body);
+        _superHelpers.values.map((m) => m.name as js_ast.TemporaryId), body);
     _superHelpers.clear();
   }
 
   /// Emits static fields for a class, and initialize them eagerly if possible,
   /// otherwise define them as lazy properties.
-  void _emitStaticFields(Class c, List<JS.Statement> body) {
+  void _emitStaticFields(Class c, List<js_ast.Statement> body) {
     var fields = c.fields
         .where((f) => f.isStatic && getRedirectingFactories(f) == null)
         .toList();
@@ -1113,15 +1120,15 @@
     }
   }
 
-  void _emitClassMetadata(List<Expression> metadata, JS.Expression className,
-      List<JS.Statement> body) {
+  void _emitClassMetadata(List<Expression> metadata,
+      js_ast.Expression className, List<js_ast.Statement> body) {
     // Metadata
     if (emitMetadata && metadata.isNotEmpty) {
       body.add(js.statement('#[#.metadata] = #;', [
         className,
         runtimeModule,
-        _arrowFunctionWithLetScope(() =>
-            JS.ArrayInitializer(metadata.map(_instantiateAnnotation).toList()))
+        _arrowFunctionWithLetScope(() => js_ast.ArrayInitializer(
+            metadata.map(_instantiateAnnotation).toList()))
       ]));
     }
   }
@@ -1140,18 +1147,18 @@
   /// If a concrete class implements one of our extensions, we might need to
   /// add forwarders.
   void _defineExtensionMembers(
-      JS.Expression className, List<JS.Statement> body) {
+      js_ast.Expression className, List<js_ast.Statement> body) {
     void emitExtensions(String helperName, Iterable<String> extensions) {
       if (extensions.isEmpty) return;
 
       var names = extensions
-          .map((e) => propertyName(JS.memberNameForDartMember(e)))
+          .map((e) => propertyName(js_ast.memberNameForDartMember(e)))
           .toList();
       body.add(js.statement('#.#(#, #);', [
         runtimeModule,
         helperName,
         className,
-        JS.ArrayInitializer(names, multiline: names.length > 4)
+        js_ast.ArrayInitializer(names, multiline: names.length > 4)
       ]));
     }
 
@@ -1162,7 +1169,7 @@
 
   /// Emit the signature on the class recording the runtime type information
   void _emitClassSignature(
-      Class c, JS.Expression className, List<JS.Statement> body) {
+      Class c, js_ast.Expression className, List<js_ast.Statement> body) {
     var savedClass = _classEmittingSignatures;
     _classEmittingSignatures = c;
 
@@ -1176,30 +1183,30 @@
       ]));
     }
 
-    void emitSignature(String name, List<JS.Property> elements) {
+    void emitSignature(String name, List<js_ast.Property> elements) {
       if (elements.isEmpty) return;
 
       if (!name.startsWith('Static')) {
         var proto = c == coreTypes.objectClass
             ? js.call('Object.create(null)')
             : runtimeCall('get${name}s(#.__proto__)', [className]);
-        elements.insert(0, JS.Property(propertyName('__proto__'), proto));
+        elements.insert(0, js_ast.Property(propertyName('__proto__'), proto));
       }
       body.add(runtimeStatement('set${name}Signature(#, () => #)', [
         className,
-        JS.ObjectInitializer(elements, multiline: elements.length > 1)
+        js_ast.ObjectInitializer(elements, multiline: elements.length > 1)
       ]));
     }
 
     var extMethods = _classProperties.extensionMethods;
     var extAccessors = _classProperties.extensionAccessors;
-    var staticMethods = <JS.Property>[];
-    var instanceMethods = <JS.Property>[];
-    var staticGetters = <JS.Property>[];
-    var instanceGetters = <JS.Property>[];
-    var staticSetters = <JS.Property>[];
-    var instanceSetters = <JS.Property>[];
-    List<JS.Property> getSignatureList(Procedure p) {
+    var staticMethods = <js_ast.Property>[];
+    var instanceMethods = <js_ast.Property>[];
+    var staticGetters = <js_ast.Property>[];
+    var instanceGetters = <js_ast.Property>[];
+    var staticSetters = <js_ast.Property>[];
+    var instanceSetters = <js_ast.Property>[];
+    List<js_ast.Property> getSignatureList(Procedure p) {
       if (p.isStatic) {
         if (p.isGetter) {
           return staticGetters;
@@ -1242,7 +1249,7 @@
           reifiedType != _getMemberRuntimeType(memberOverride, c);
 
       if (needsSignature) {
-        JS.Expression type;
+        js_ast.Expression type;
         if (member.isAccessor) {
           type = _emitAnnotatedResult(
               _emitType(member.isGetter
@@ -1253,12 +1260,12 @@
         } else {
           type = _emitAnnotatedFunctionType(reifiedType, member);
         }
-        var property = JS.Property(_declareMemberName(member), type);
+        var property = js_ast.Property(_declareMemberName(member), type);
         var signatures = getSignatureList(member);
         signatures.add(property);
         if (!member.isStatic &&
             (extMethods.contains(name) || extAccessors.contains(name))) {
-          signatures.add(JS.Property(
+          signatures.add(js_ast.Property(
               _declareMemberName(member, useExtension: true), type));
         }
       }
@@ -1275,8 +1282,8 @@
       js.escapedString(jsLibraryDebuggerName(c.enclosingLibrary))
     ]));
 
-    var instanceFields = <JS.Property>[];
-    var staticFields = <JS.Property>[];
+    var instanceFields = <js_ast.Property>[];
+    var staticFields = <js_ast.Property>[];
 
     var classFields = c.fields.toList();
     for (var field in classFields) {
@@ -1287,13 +1294,13 @@
       var memberName = _declareMemberName(field);
       var fieldSig = _emitFieldSignature(field, c);
       (isStatic ? staticFields : instanceFields)
-          .add(JS.Property(memberName, fieldSig));
+          .add(js_ast.Property(memberName, fieldSig));
     }
     emitSignature('Field', instanceFields);
     emitSignature('StaticField', staticFields);
 
     if (emitMetadata) {
-      var constructors = <JS.Property>[];
+      var constructors = <js_ast.Property>[];
       var allConstructors = [
         ...c.constructors,
         ...c.procedures.where((p) => p.isFactory),
@@ -1302,7 +1309,7 @@
         var memberName = _constructorName(ctor.name.name);
         var type = _emitAnnotatedFunctionType(
             ctor.function.functionType.withoutTypeParameters, ctor);
-        constructors.add(JS.Property(memberName, type));
+        constructors.add(js_ast.Property(memberName, type));
       }
       emitSignature('Constructor', constructors);
     }
@@ -1317,14 +1324,14 @@
     _classEmittingSignatures = savedClass;
   }
 
-  JS.Expression _emitFieldSignature(Field field, Class fromClass) {
+  js_ast.Expression _emitFieldSignature(Field field, Class fromClass) {
     var type = _getTypeFromClass(field.type, field.enclosingClass, fromClass);
     var args = [_emitType(type)];
     var annotations = field.annotations;
     if (emitMetadata && annotations != null && annotations.isNotEmpty) {
       var savedUri = _currentUri;
       _currentUri = field.enclosingClass.fileUri;
-      args.add(JS.ArrayInitializer(
+      args.add(js_ast.ArrayInitializer(
           annotations.map(_instantiateAnnotation).toList()));
       _currentUri = savedUri;
     }
@@ -1367,8 +1374,8 @@
         .substituteType(type);
   }
 
-  JS.Expression _emitConstructor(
-      Constructor node, List<Field> fields, JS.Expression className) {
+  js_ast.Expression _emitConstructor(
+      Constructor node, List<Field> fields, js_ast.Expression className) {
     var savedUri = _currentUri;
     _currentUri = node.fileUri ?? savedUri;
     var params = _emitParameters(node.function);
@@ -1381,11 +1388,11 @@
     _currentUri = savedUri;
     end ??= _nodeEnd(node.enclosingClass.fileEndOffset);
 
-    return JS.Fun(params, JS.Block(body))..sourceInformation = end;
+    return js_ast.Fun(params, js_ast.Block(body))..sourceInformation = end;
   }
 
-  List<JS.Statement> _emitConstructorBody(
-      Constructor node, List<Field> fields, JS.Expression className) {
+  List<js_ast.Statement> _emitConstructorBody(
+      Constructor node, List<Field> fields, js_ast.Expression className) {
     var cls = node.enclosingClass;
 
     // Generate optional/named argument value assignment. These can not have
@@ -1427,7 +1434,7 @@
     return body;
   }
 
-  JS.Expression _constructorName(String name) {
+  js_ast.Expression _constructorName(String name) {
     if (name == '') {
       // Default constructors (factory or not) use `new` as their name.
       return propertyName('new');
@@ -1435,8 +1442,8 @@
     return _emitStaticMemberName(name);
   }
 
-  JS.Statement _emitRedirectingConstructor(
-      RedirectingInitializer node, JS.Expression className) {
+  js_ast.Statement _emitRedirectingConstructor(
+      RedirectingInitializer node, js_ast.Expression className) {
     var ctor = node.target;
     // We can't dispatch to the constructor with `this.new` as that might hit a
     // derived class constructor with the same name.
@@ -1447,13 +1454,13 @@
     ]);
   }
 
-  JS.Statement _emitSuperConstructorCallIfNeeded(
-      Class c, JS.Expression className,
+  js_ast.Statement _emitSuperConstructorCallIfNeeded(
+      Class c, js_ast.Expression className,
       [SuperInitializer superInit]) {
     if (c == coreTypes.objectClass) return null;
 
     Constructor ctor;
-    List<JS.Expression> args;
+    List<js_ast.Expression> args;
     if (superInit == null) {
       ctor = unnamedConstructor(c.superclass);
       args = [];
@@ -1470,8 +1477,8 @@
     return _emitSuperConstructorCall(className, ctor.name.name, args);
   }
 
-  JS.Statement _emitSuperConstructorCall(
-      JS.Expression className, String name, List<JS.Expression> args) {
+  js_ast.Statement _emitSuperConstructorCall(
+      js_ast.Expression className, String name, List<js_ast.Expression> args) {
     return js.statement('#.__proto__.#.call(this, #);',
         [className, _constructorName(name), args ?? []]);
   }
@@ -1499,7 +1506,7 @@
   ///   2. field initializing parameters,
   ///   3. constructor field initializers,
   ///   4. initialize fields not covered in 1-3
-  JS.Statement _initializeFields(List<Field> fields, [Constructor ctor]) {
+  js_ast.Statement _initializeFields(List<Field> fields, [Constructor ctor]) {
     // Run field initializers if they can have side-effects.
     Set<Field> ctorFields;
     if (ctor != null) {
@@ -1509,7 +1516,7 @@
             ..remove(null);
     }
 
-    var body = <JS.Statement>[];
+    var body = <js_ast.Statement>[];
     emitFieldInit(Field f, Expression initializer, TreeNode hoverInfo) {
       var access = _classProperties.virtualFields[f] ?? _declareMemberName(f);
       var jsInit = _visitInitializer(initializer, f.annotations);
@@ -1543,20 +1550,20 @@
       }
     }
 
-    return JS.Statement.from(body);
+    return js_ast.Statement.from(body);
   }
 
-  JS.Expression _visitInitializer(
+  js_ast.Expression _visitInitializer(
       Expression init, List<Expression> annotations) {
     // explicitly initialize to null, to avoid getting `undefined`.
     // TODO(jmesserly): do this only for vars that aren't definitely assigned.
-    if (init == null) return JS.LiteralNull();
+    if (init == null) return js_ast.LiteralNull();
     return _annotatedNullCheck(annotations)
         ? notNull(init)
         : _visitExpression(init);
   }
 
-  JS.Expression notNull(Expression expr) {
+  js_ast.Expression notNull(Expression expr) {
     if (expr == null) return null;
     var jsExpr = _visitExpression(expr);
     if (!isNullable(expr)) return jsExpr;
@@ -1574,8 +1581,8 @@
             mixin.constructors.every((c) => c.isExternal);
   }
 
-  JS.Statement _addConstructorToClass(
-      Class c, JS.Expression className, String name, JS.Expression jsCtor) {
+  js_ast.Statement _addConstructorToClass(Class c, js_ast.Expression className,
+      String name, js_ast.Expression jsCtor) {
     jsCtor = defineValueOnClass(c, className, _constructorName(name), jsCtor);
     return js.statement('#.prototype = #.prototype;', [jsCtor, className]);
   }
@@ -1597,18 +1604,18 @@
     }
   }
 
-  List<JS.Method> _emitClassMethods(Class c) {
+  List<js_ast.Method> _emitClassMethods(Class c) {
     var virtualFields = _classProperties.virtualFields;
 
-    var jsMethods = <JS.Method>[];
+    var jsMethods = <js_ast.Method>[];
     bool hasJsPeer = _extensionTypes.isNativeClass(c);
     bool hasIterator = false;
 
     if (c == coreTypes.objectClass) {
       // Dart does not use ES6 constructors.
       // Add an error to catch any invalid usage.
-      jsMethods
-          .add(JS.Method(propertyName('constructor'), js.fun(r'''function() {
+      jsMethods.add(
+          js_ast.Method(propertyName('constructor'), js.fun(r'''function() {
                   throw Error("use `new " + #.typeName(#.getReifiedType(this)) +
                       ".new(...)` to create a Dart object");
               }''', [runtimeModule, runtimeModule])));
@@ -1619,7 +1626,7 @@
       //
       // This will become obsolete when
       // https://github.com/dart-lang/sdk/issues/31003 is addressed.
-      jsMethods.add(JS.Method(
+      jsMethods.add(js_ast.Method(
           propertyName('constructor'), js.fun(r'function() { return []; }')));
     }
 
@@ -1715,12 +1722,12 @@
   }
 
   /// Emits a method, getter, or setter.
-  JS.Method _emitMethodDeclaration(Procedure member) {
+  js_ast.Method _emitMethodDeclaration(Procedure member) {
     if (member.isAbstract) {
       return null;
     }
 
-    JS.Fun fn;
+    js_ast.Fun fn;
     if (member.isExternal && !member.isNoSuchMethodForwarder) {
       if (member.isStatic) {
         // TODO(vsm): Do we need to handle this case?
@@ -1731,27 +1738,28 @@
       fn = _emitFunction(member.function, member.name.name);
     }
 
-    return JS.Method(_declareMemberName(member), fn,
+    return js_ast.Method(_declareMemberName(member), fn,
         isGetter: member.isGetter,
         isSetter: member.isSetter,
         isStatic: member.isStatic)
       ..sourceInformation = _nodeEnd(member.fileEndOffset);
   }
 
-  JS.Fun _emitNativeFunctionBody(Procedure node) {
+  js_ast.Fun _emitNativeFunctionBody(Procedure node) {
     String name = getAnnotationName(node, isJSAnnotation) ?? node.name.name;
     if (node.isGetter) {
-      return JS.Fun([], js.block('{ return this.#; }', [name]));
+      return js_ast.Fun([], js.block('{ return this.#; }', [name]));
     } else if (node.isSetter) {
       var params = _emitParameters(node.function);
-      return JS.Fun(params, js.block('{ this.# = #; }', [name, params.last]));
+      return js_ast.Fun(
+          params, js.block('{ this.# = #; }', [name, params.last]));
     } else {
       return js.fun(
           'function (...args) { return this.#.apply(this, args); }', name);
     }
   }
 
-  List<JS.Method> _emitCovarianceCheckStub(Procedure member) {
+  List<js_ast.Method> _emitCovarianceCheckStub(Procedure member) {
     // TODO(jmesserly): kernel stubs have a few problems:
     // - they're generated even when there is no concrete super member
     // - the stub parameter types don't match the types we need to check to
@@ -1781,12 +1789,12 @@
       var setterType = substituteType(superMember.setterType);
       if (types.isTop(setterType)) return const [];
       return [
-        JS.Method(
+        js_ast.Method(
             name,
             js.fun('function(x) { return super.# = #; }',
-                [name, _emitCast(JS.Identifier('x'), setterType)]),
+                [name, _emitCast(js_ast.Identifier('x'), setterType)]),
             isSetter: true),
-        JS.Method(name, js.fun('function() { return super.#; }', [name]),
+        js_ast.Method(name, js.fun('function() { return super.#; }', [name]),
             isGetter: true)
       ];
     }
@@ -1796,16 +1804,16 @@
         substituteType(superMember.function.functionType) as FunctionType;
     var function = member.function;
 
-    var body = <JS.Statement>[];
+    var body = <js_ast.Statement>[];
     var typeParameters = superMethodType.typeParameters;
     _emitCovarianceBoundsCheck(typeParameters, body);
 
     var typeFormals = _emitTypeFormals(typeParameters);
-    var jsParams = List<JS.Parameter>.from(typeFormals);
+    var jsParams = List<js_ast.Parameter>.from(typeFormals);
     var positionalParameters = function.positionalParameters;
     for (var i = 0, n = positionalParameters.length; i < n; i++) {
       var param = positionalParameters[i];
-      var jsParam = JS.Identifier(param.name);
+      var jsParam = js_ast.Identifier(param.name);
       jsParams.add(jsParam);
 
       if (isCovariantParameter(param) &&
@@ -1829,7 +1837,8 @@
         body.add(js.statement('if (# in #) #;', [
           name,
           namedArgumentTemp,
-          _emitCast(JS.PropertyAccess(namedArgumentTemp, name), paramType.type)
+          _emitCast(
+              js_ast.PropertyAccess(namedArgumentTemp, name), paramType.type)
         ]));
       }
     }
@@ -1838,11 +1847,11 @@
 
     if (namedParameters.isNotEmpty) jsParams.add(namedArgumentTemp);
     body.add(js.statement('return super.#(#);', [name, jsParams]));
-    return [JS.Method(name, JS.Fun(jsParams, JS.Block(body)))];
+    return [js_ast.Method(name, js_ast.Fun(jsParams, js_ast.Block(body)))];
   }
 
   /// Emits a Dart factory constructor to a JS static method.
-  JS.Method _emitFactoryConstructor(Procedure node) {
+  js_ast.Method _emitFactoryConstructor(Procedure node) {
     if (node.isExternal || isUnsupportedFactoryConstructor(node)) return null;
 
     var function = node.function;
@@ -1858,14 +1867,14 @@
     /// [_emitFunction] instead.
     var jsBody = _emitSyncFunctionBody(function);
 
-    return JS.Method(_constructorName(node.name.name),
-        JS.Fun(_emitParameters(function), jsBody),
+    return js_ast.Method(_constructorName(node.name.name),
+        js_ast.Fun(_emitParameters(function), jsBody),
         isStatic: true)
       ..sourceInformation = _nodeEnd(node.fileEndOffset);
   }
 
   @override
-  JS.Expression emitConstructorAccess(InterfaceType type) {
+  js_ast.Expression emitConstructorAccess(InterfaceType type) {
     return _emitJSInterop(type.classNode) ?? visitInterfaceType(type);
   }
 
@@ -1876,23 +1885,24 @@
   /// would end up calling the getter or setter, and one of those might not even
   /// exist, resulting in a runtime error. Even if they did exist, that's the
   /// wrong behavior if a new field was declared.
-  List<JS.Method> _emitVirtualFieldAccessor(Field field) {
+  List<js_ast.Method> _emitVirtualFieldAccessor(Field field) {
     var virtualField = _classProperties.virtualFields[field];
     var name = _declareMemberName(field);
 
     var getter = js.fun('function() { return this[#]; }', [virtualField]);
-    var jsGetter = JS.Method(name, getter, isGetter: true)
+    var jsGetter = js_ast.Method(name, getter, isGetter: true)
       ..sourceInformation = _nodeStart(field);
 
-    var args = field.isFinal ? [JS.Super(), name] : [JS.This(), virtualField];
+    var args =
+        field.isFinal ? [js_ast.Super(), name] : [js_ast.This(), virtualField];
 
-    JS.Expression value = JS.Identifier('value');
+    js_ast.Expression value = js_ast.Identifier('value');
     if (!field.isFinal && isCovariantField(field)) {
       value = _emitCast(value, field.type);
     }
     args.add(value);
 
-    var jsSetter = JS.Method(
+    var jsSetter = js_ast.Method(
         name, js.fun('function(value) { #[#] = #; }', args),
         isSetter: true)
       ..sourceInformation = _nodeStart(field);
@@ -1904,25 +1914,25 @@
   /// field.  Note that the Dart names are always symbolized to avoid
   /// conflicts.  They will be installed as extension methods on the underlying
   /// native type.
-  List<JS.Method> _emitNativeFieldAccessors(Field field) {
+  List<js_ast.Method> _emitNativeFieldAccessors(Field field) {
     // TODO(vsm): Can this by meta-programmed?
     // E.g., dart.nativeField(symbol, jsName)
     // Alternatively, perhaps it could be meta-programmed directly in
     // dart.registerExtensions?
-    var jsMethods = <JS.Method>[];
+    var jsMethods = <js_ast.Method>[];
     assert(!field.isStatic);
 
     var name = getAnnotationName(field, isJSName) ?? field.name.name;
     // Generate getter
-    var fn = JS.Fun([], js.block('{ return this.#; }', [name]));
-    var method = JS.Method(_declareMemberName(field), fn, isGetter: true);
+    var fn = js_ast.Fun([], js.block('{ return this.#; }', [name]));
+    var method = js_ast.Method(_declareMemberName(field), fn, isGetter: true);
     jsMethods.add(method);
 
     // Generate setter
     if (!field.isFinal) {
-      var value = JS.TemporaryId('value');
-      fn = JS.Fun([value], js.block('{ this.# = #; }', [name, value]));
-      method = JS.Method(_declareMemberName(field), fn, isSetter: true);
+      var value = js_ast.TemporaryId('value');
+      fn = js_ast.Fun([value], js.block('{ this.# = #; }', [name, value]));
+      method = js_ast.Method(_declareMemberName(field), fn, isSetter: true);
       jsMethods.add(method);
     }
 
@@ -1935,7 +1945,7 @@
   /// This is needed because in ES6, if you only override a getter
   /// (alternatively, a setter), then there is an implicit override of the
   /// setter (alternatively, the getter) that does nothing.
-  JS.Method _emitSuperAccessorWrapper(Procedure member,
+  js_ast.Method _emitSuperAccessorWrapper(Procedure member,
       Map<String, Procedure> getters, Map<String, Procedure> setters) {
     if (member.isAbstract) return null;
 
@@ -1946,7 +1956,7 @@
           _classProperties.inheritedSetters.contains(name)) {
         // Generate a setter that forwards to super.
         var fn = js.fun('function(value) { super[#] = value; }', [memberName]);
-        return JS.Method(memberName, fn, isSetter: true);
+        return js_ast.Method(memberName, fn, isSetter: true);
       }
     } else {
       assert(member.isSetter);
@@ -1954,7 +1964,7 @@
           _classProperties.inheritedGetters.contains(name)) {
         // Generate a getter that forwards to super.
         var fn = js.fun('function() { return super[#]; }', [memberName]);
-        return JS.Method(memberName, fn, isGetter: true);
+        return js_ast.Method(memberName, fn, isGetter: true);
       }
     }
     return null;
@@ -1968,7 +1978,7 @@
   /// This will return `null` if the adapter was already added on a super type,
   /// otherwise it returns the adapter code.
   // TODO(jmesserly): should we adapt `Iterator` too?
-  JS.Method _emitIterable(Class c) {
+  js_ast.Method _emitIterable(Class c) {
     var iterable = hierarchy.getClassAsInstanceOf(c, coreTypes.iterableClass);
     if (iterable == null) return null;
 
@@ -1989,19 +1999,19 @@
 
     // Otherwise, emit the adapter method, which wraps the Dart iterator in
     // an ES6 iterator.
-    return JS.Method(
+    return js_ast.Method(
         js.call('Symbol.iterator'),
         js.call('function() { return new #.JsIterator(this.#); }', [
           runtimeModule,
           _emitMemberName('iterator', memberClass: coreTypes.iterableClass)
-        ]) as JS.Fun);
+        ]) as js_ast.Fun);
   }
 
-  JS.Expression _instantiateAnnotation(Expression node) =>
+  js_ast.Expression _instantiateAnnotation(Expression node) =>
       _visitExpression(node);
 
   void _registerExtensionType(
-      Class c, String jsPeerName, List<JS.Statement> body) {
+      Class c, String jsPeerName, List<js_ast.Statement> body) {
     var className = _emitTopLevelName(c);
     if (_typeRep.isPrimitive(c.rawType)) {
       body.add(runtimeStatement(
@@ -2041,24 +2051,27 @@
         emitLibraryName(_currentLibrary), fields, _emitTopLevelMemberName));
   }
 
-  JS.Statement _emitLazyFields(JS.Expression objExpr, Iterable<Field> fields,
-      JS.Expression Function(Field f) emitFieldName) {
-    var accessors = <JS.Method>[];
+  js_ast.Statement _emitLazyFields(
+      js_ast.Expression objExpr,
+      Iterable<Field> fields,
+      js_ast.Expression Function(Field f) emitFieldName) {
+    var accessors = <js_ast.Method>[];
     var savedUri = _currentUri;
 
     for (var field in fields) {
       _currentUri = field.fileUri;
       var access = emitFieldName(field);
-      accessors.add(
-          JS.Method(access, _emitStaticFieldInitializer(field), isGetter: true)
-            ..sourceInformation = _hoverComment(
-                JS.PropertyAccess(objExpr, access),
-                field.fileOffset,
-                field.name.name.length));
+      accessors.add(js_ast.Method(access, _emitStaticFieldInitializer(field),
+          isGetter: true)
+        ..sourceInformation = _hoverComment(
+            js_ast.PropertyAccess(objExpr, access),
+            field.fileOffset,
+            field.name.name.length));
 
       // TODO(jmesserly): currently uses a dummy setter to indicate writable.
       if (!field.isFinal && !field.isConst) {
-        accessors.add(JS.Method(access, js.call('function(_) {}') as JS.Fun,
+        accessors.add(js_ast.Method(
+            access, js.call('function(_) {}') as js_ast.Fun,
             isSetter: true));
       }
     }
@@ -2068,15 +2081,16 @@
     return runtimeStatement('defineLazy(#, { # })', [objExpr, accessors]);
   }
 
-  JS.Fun _emitStaticFieldInitializer(Field field) {
-    return JS.Fun(
+  js_ast.Fun _emitStaticFieldInitializer(Field field) {
+    return js_ast.Fun(
         [],
-        JS.Block(_withLetScope(() => [
-              JS.Return(_visitInitializer(field.initializer, field.annotations))
+        js_ast.Block(_withLetScope(() => [
+              js_ast.Return(
+                  _visitInitializer(field.initializer, field.annotations))
             ])));
   }
 
-  List<JS.Statement> _withLetScope(List<JS.Statement> visitBody()) {
+  List<js_ast.Statement> _withLetScope(List<js_ast.Statement> visitBody()) {
     var savedLetVariables = _letVariables;
     _letVariables = [];
 
@@ -2088,7 +2102,7 @@
     return body;
   }
 
-  JS.ArrowFun _arrowFunctionWithLetScope(JS.Expression visitBody()) {
+  js_ast.ArrowFun _arrowFunctionWithLetScope(js_ast.Expression visitBody()) {
     var savedLetVariables = _letVariables;
     _letVariables = [];
 
@@ -2096,11 +2110,11 @@
     var letVars = _initLetVariables();
 
     _letVariables = savedLetVariables;
-    return JS.ArrowFun(
-        [], letVars == null ? expr : JS.Block([letVars, expr.toReturn()]));
+    return js_ast.ArrowFun(
+        [], letVars == null ? expr : js_ast.Block([letVars, expr.toReturn()]));
   }
 
-  JS.PropertyAccess _emitTopLevelName(NamedNode n, {String suffix = ''}) {
+  js_ast.PropertyAccess _emitTopLevelName(NamedNode n, {String suffix = ''}) {
     return _emitJSInterop(n) ?? _emitTopLevelNameNoInterop(n, suffix: suffix);
   }
 
@@ -2108,7 +2122,7 @@
   ///
   /// Unlike call sites, we always have an element available, so we can use it
   /// directly rather than computing the relevant options for [_emitMemberName].
-  JS.Expression _declareMemberName(Member m, {bool useExtension}) {
+  js_ast.Expression _declareMemberName(Member m, {bool useExtension}) {
     return _emitMemberName(m.name.name,
         isStatic: m is Field ? m.isStatic : (m as Procedure).isStatic,
         useExtension:
@@ -2156,7 +2170,7 @@
   /// Equality is a bit special, it is generated via the Dart `equals` runtime
   /// helper, that checks for null. The user defined method is called '=='.
   ///
-  JS.Expression _emitMemberName(String name,
+  js_ast.Expression _emitMemberName(String name,
       {bool isStatic = false,
       bool useExtension,
       Member member,
@@ -2175,9 +2189,9 @@
         var parts = runtimeName.split('.');
         if (parts.length < 2) return propertyName(runtimeName);
 
-        JS.Expression result = JS.Identifier(parts[0]);
+        js_ast.Expression result = js_ast.Identifier(parts[0]);
         for (int i = 1; i < parts.length; i++) {
-          result = JS.PropertyAccess(result, propertyName(parts[i]));
+          result = js_ast.PropertyAccess(result, propertyName(parts[i]));
         }
         return result;
       }
@@ -2193,7 +2207,7 @@
     }
 
     useExtension ??= _isSymbolizedMember(memberClass, name);
-    name = JS.memberNameForDartMember(
+    name = js_ast.memberNameForDartMember(
         name, member is Procedure && member.isExternal);
     if (useExtension) {
       return getExtensionSymbolInternal(name);
@@ -2248,7 +2262,7 @@
             hierarchy.getDispatchTarget(c, Name(name), setter: true));
   }
 
-  JS.Expression _emitStaticMemberName(String name, [NamedNode member]) {
+  js_ast.Expression _emitStaticMemberName(String name, [NamedNode member]) {
     if (member != null) {
       var jsName = _emitJSInteropStaticMemberName(member);
       if (jsName != null) return jsName;
@@ -2280,7 +2294,7 @@
     return propertyName(name);
   }
 
-  JS.Expression _emitJSInteropStaticMemberName(NamedNode n) {
+  js_ast.Expression _emitJSInteropStaticMemberName(NamedNode n) {
     if (!usesJSInterop(n)) return null;
     var name = getAnnotationName(n, isPublicJSAnnotation);
     if (name != null) {
@@ -2295,9 +2309,9 @@
     return js.escapedString(name, "'");
   }
 
-  JS.PropertyAccess _emitTopLevelNameNoInterop(NamedNode n,
+  js_ast.PropertyAccess _emitTopLevelNameNoInterop(NamedNode n,
       {String suffix = ''}) {
-    return JS.PropertyAccess(emitLibraryName(getLibrary(n)),
+    return js_ast.PropertyAccess(emitLibraryName(getLibrary(n)),
         _emitTopLevelMemberName(n, suffix: suffix));
   }
 
@@ -2305,7 +2319,7 @@
   ///
   /// NOTE: usually you should use [_emitTopLevelName] instead of this. This
   /// function does not handle JS interop.
-  JS.Expression _emitTopLevelMemberName(NamedNode n, {String suffix = ''}) {
+  js_ast.Expression _emitTopLevelMemberName(NamedNode n, {String suffix = ''}) {
     var name = getJSExportName(n) ?? getTopLevelName(n);
     return propertyName(name + suffix);
   }
@@ -2318,18 +2332,18 @@
     return libraryJSName != null ? '$libraryJSName.$jsName' : jsName;
   }
 
-  JS.PropertyAccess _emitJSInterop(NamedNode n) {
+  js_ast.PropertyAccess _emitJSInterop(NamedNode n) {
     var jsName = _getJSNameWithoutGlobal(n);
     if (jsName == null) return null;
     return _emitJSInteropForGlobal(jsName);
   }
 
-  JS.PropertyAccess _emitJSInteropForGlobal(String name) {
+  js_ast.PropertyAccess _emitJSInteropForGlobal(String name) {
     var parts = name.split('.');
     if (parts.isEmpty) parts = [''];
-    JS.PropertyAccess access;
+    js_ast.PropertyAccess access;
     for (var part in parts) {
-      access = JS.PropertyAccess(
+      access = js_ast.PropertyAccess(
           access ?? runtimeCall('global'), js.escapedString(part, "'"));
     }
     return access;
@@ -2354,12 +2368,12 @@
     ]));
   }
 
-  JS.Method _emitLibraryAccessor(Procedure node) {
+  js_ast.Method _emitLibraryAccessor(Procedure node) {
     var savedUri = _currentUri;
     _currentUri = node.fileUri;
 
     var name = node.name.name;
-    var result = JS.Method(
+    var result = js_ast.Method(
         propertyName(name), _emitFunction(node.function, node.name.name),
         isGetter: node.isGetter, isSetter: node.isSetter)
       ..sourceInformation = _nodeEnd(node.fileEndOffset);
@@ -2368,17 +2382,17 @@
     return result;
   }
 
-  JS.Statement _emitLibraryFunction(Procedure p) {
+  js_ast.Statement _emitLibraryFunction(Procedure p) {
     var savedUri = _currentUri;
     _currentUri = p.fileUri;
 
-    var body = <JS.Statement>[];
+    var body = <js_ast.Statement>[];
     var fn = _emitFunction(p.function, p.name.name)
       ..sourceInformation = _nodeEnd(p.fileEndOffset);
 
     if (_currentLibrary.importUri.scheme == 'dart' &&
         _isInlineJSFunction(p.function.body)) {
-      fn = JS.simplifyPassThroughArrowFunCallBody(fn);
+      fn = js_ast.simplifyPassThroughArrowFunCallBody(fn);
     }
 
     var nameExpr = _emitTopLevelName(p);
@@ -2394,10 +2408,10 @@
     }
 
     _currentUri = savedUri;
-    return JS.Statement.from(body);
+    return js_ast.Statement.from(body);
   }
 
-  JS.Expression _emitFunctionTagged(JS.Expression fn, FunctionType type,
+  js_ast.Expression _emitFunctionTagged(js_ast.Expression fn, FunctionType type,
       {bool topLevel = false}) {
     var lazy = topLevel && !_canEmitTypeAtTopLevel(type);
     var typeRep = visitFunctionType(type, lazy: lazy);
@@ -2436,31 +2450,33 @@
   }
 
   /// Emits a Dart [type] into code.
-  JS.Expression _emitType(DartType type) => type.accept(this) as JS.Expression;
+  js_ast.Expression _emitType(DartType type) =>
+      type.accept(this) as js_ast.Expression;
 
-  JS.Expression _emitInvalidNode(Node node, [String message = '']) {
+  js_ast.Expression _emitInvalidNode(Node node, [String message = '']) {
     if (message.isNotEmpty) message += ' ';
     return runtimeCall('throwUnimplementedError(#)',
         [js.escapedString('node <${node.runtimeType}> $message`$node`')]);
   }
 
   @override
-  JS.Expression defaultDartType(DartType type) => _emitInvalidNode(type);
+  js_ast.Expression defaultDartType(DartType type) => _emitInvalidNode(type);
 
   @override
-  JS.Expression visitInvalidType(InvalidType type) => defaultDartType(type);
+  js_ast.Expression visitInvalidType(InvalidType type) => defaultDartType(type);
 
   @override
-  JS.Expression visitDynamicType(DynamicType type) => runtimeCall('dynamic');
+  js_ast.Expression visitDynamicType(DynamicType type) =>
+      runtimeCall('dynamic');
 
   @override
-  JS.Expression visitVoidType(VoidType type) => runtimeCall('void');
+  js_ast.Expression visitVoidType(VoidType type) => runtimeCall('void');
 
   @override
-  JS.Expression visitBottomType(BottomType type) => runtimeCall('bottom');
+  js_ast.Expression visitBottomType(BottomType type) => runtimeCall('bottom');
 
   @override
-  JS.Expression visitInterfaceType(InterfaceType type) {
+  js_ast.Expression visitInterfaceType(InterfaceType type) {
     var c = type.classNode;
     _declareBeforeUse(c);
 
@@ -2488,7 +2504,7 @@
     }
 
     var args = type.typeArguments;
-    Iterable<JS.Expression> jsArgs;
+    Iterable<js_ast.Expression> jsArgs;
     if (args.any((a) => a != const DynamicType())) {
       jsArgs = args.map(_emitType);
     }
@@ -2511,14 +2527,15 @@
       !_emittingClassExtends && !_emittingClassSignatures ||
       _currentFunction != null;
 
-  JS.Expression _emitGenericClassType(
-      InterfaceType t, Iterable<JS.Expression> typeArgs) {
+  js_ast.Expression _emitGenericClassType(
+      InterfaceType t, Iterable<js_ast.Expression> typeArgs) {
     var genericName = _emitTopLevelNameNoInterop(t.classNode, suffix: '\$');
     return js.call('#(#)', [genericName, typeArgs]);
   }
 
   @override
-  JS.Expression visitFunctionType(type, {Member member, bool lazy = false}) {
+  js_ast.Expression visitFunctionType(type,
+      {Member member, bool lazy = false}) {
     var requiredTypes =
         type.positionalParameters.take(type.requiredParameterCount).toList();
     var function = member?.function;
@@ -2535,7 +2552,7 @@
     var rt = _emitType(type.returnType);
     var ra = _emitTypeNames(requiredTypes, requiredParams, member);
 
-    List<JS.Expression> typeParts;
+    List<js_ast.Expression> typeParts;
     if (namedTypes.isNotEmpty) {
       assert(optionalTypes.isEmpty);
       // TODO(vsm): Pass in annotations here as well.
@@ -2554,7 +2571,7 @@
     if (typeFormals.isNotEmpty) {
       var tf = _emitTypeFormals(typeFormals);
 
-      addTypeFormalsAsParameters(List<JS.Expression> elements) {
+      addTypeFormalsAsParameters(List<js_ast.Expression> elements) {
         var names = _typeTable.discharge(typeFormals);
         return names.isEmpty
             ? js.call('(#) => [#]', [tf, elements])
@@ -2606,7 +2623,8 @@
         : typeRep;
   }
 
-  JS.Expression _emitAnnotatedFunctionType(FunctionType type, Member member) {
+  js_ast.Expression _emitAnnotatedFunctionType(
+      FunctionType type, Member member) {
     var result = visitFunctionType(type, member: member);
 
     var annotations = member.annotations;
@@ -2614,7 +2632,7 @@
       // TODO(jmesserly): should we disable source info for annotations?
       var savedUri = _currentUri;
       _currentUri = member.enclosingClass.fileUri;
-      result = JS.ArrayInitializer(
+      result = js_ast.ArrayInitializer(
           [result]..addAll(annotations.map(_instantiateAnnotation)));
       _currentUri = savedUri;
     }
@@ -2622,46 +2640,46 @@
   }
 
   /// Emits an expression that lets you access statics on a [type] from code.
-  JS.Expression _emitConstructorAccess(InterfaceType type) {
+  js_ast.Expression _emitConstructorAccess(InterfaceType type) {
     return _emitJSInterop(type.classNode) ?? _emitType(type);
   }
 
-  JS.Expression _emitConstructorName(InterfaceType type, Member c) {
+  js_ast.Expression _emitConstructorName(InterfaceType type, Member c) {
     return _emitJSInterop(type.classNode) ??
-        JS.PropertyAccess(
+        js_ast.PropertyAccess(
             _emitConstructorAccess(type), _constructorName(c.name.name));
   }
 
   /// Emits an expression that lets you access statics on an [c] from code.
-  JS.Expression _emitStaticClassName(Class c) {
+  js_ast.Expression _emitStaticClassName(Class c) {
     _declareBeforeUse(c);
     return _emitTopLevelName(c);
   }
 
   // Wrap a result - usually a type - with its metadata.  The runtime is
   // responsible for unpacking this.
-  JS.Expression _emitAnnotatedResult(
-      JS.Expression result, List<Expression> metadata, Member member) {
+  js_ast.Expression _emitAnnotatedResult(
+      js_ast.Expression result, List<Expression> metadata, Member member) {
     if (emitMetadata && metadata.isNotEmpty) {
       // TODO(jmesserly): should we disable source info for annotations?
       var savedUri = _currentUri;
       _currentUri = member.enclosingClass.fileUri;
-      result = JS.ArrayInitializer(
+      result = js_ast.ArrayInitializer(
           [result]..addAll(metadata.map(_instantiateAnnotation)));
       _currentUri = savedUri;
     }
     return result;
   }
 
-  JS.ObjectInitializer _emitTypeProperties(Iterable<NamedType> types) {
-    return JS.ObjectInitializer(types
-        .map((t) => JS.Property(propertyName(t.name), _emitType(t.type)))
+  js_ast.ObjectInitializer _emitTypeProperties(Iterable<NamedType> types) {
+    return js_ast.ObjectInitializer(types
+        .map((t) => js_ast.Property(propertyName(t.name), _emitType(t.type)))
         .toList());
   }
 
-  JS.ArrayInitializer _emitTypeNames(List<DartType> types,
+  js_ast.ArrayInitializer _emitTypeNames(List<DartType> types,
       List<VariableDeclaration> parameters, Member member) {
-    var result = <JS.Expression>[];
+    var result = <js_ast.Expression>[];
     for (int i = 0; i < types.length; ++i) {
       var type = _emitType(types[i]);
       if (parameters != null) {
@@ -2669,21 +2687,21 @@
       }
       result.add(type);
     }
-    return JS.ArrayInitializer(result);
+    return js_ast.ArrayInitializer(result);
   }
 
   @override
-  JS.Expression visitTypeParameterType(TypeParameterType type) =>
+  js_ast.Expression visitTypeParameterType(TypeParameterType type) =>
       _emitTypeParameter(type.parameter);
 
-  JS.Identifier _emitTypeParameter(TypeParameter t) =>
-      JS.Identifier(getTypeParameterName(t));
+  js_ast.Identifier _emitTypeParameter(TypeParameter t) =>
+      js_ast.Identifier(getTypeParameterName(t));
 
   @override
-  JS.Expression visitTypedefType(TypedefType type) =>
+  js_ast.Expression visitTypedefType(TypedefType type) =>
       visitFunctionType(type.unalias as FunctionType);
 
-  JS.Fun _emitFunction(FunctionNode f, String name) {
+  js_ast.Fun _emitFunction(FunctionNode f, String name) {
     // normal function (sync), vs (sync*, async, async*)
     var isSync = f.asyncMarker == AsyncMarker.Sync;
     var formals = _emitParameters(f);
@@ -2698,26 +2716,26 @@
     // potentially mutated in Kernel. For now we assume all parameters are.
     super.enterFunction(name, formals, () => true);
 
-    JS.Block block =
+    js_ast.Block block =
         isSync ? _emitSyncFunctionBody(f) : _emitGeneratorFunctionBody(f, name);
 
     block = super.exitFunction(name, formals, block);
-    return JS.Fun(formals, block);
+    return js_ast.Fun(formals, block);
   }
 
-  List<JS.Parameter> _emitParameters(FunctionNode f) {
+  List<js_ast.Parameter> _emitParameters(FunctionNode f) {
     var positional = f.positionalParameters;
-    var result = List<JS.Parameter>.of(positional.map(_emitVariableDef));
+    var result = List<js_ast.Parameter>.of(positional.map(_emitVariableDef));
     if (positional.isNotEmpty &&
         f.requiredParameterCount == positional.length &&
         positional.last.annotations.any(isJsRestAnnotation)) {
-      result.last = JS.RestParameter(result.last as JS.Identifier);
+      result.last = js_ast.RestParameter(result.last as js_ast.Identifier);
     }
     if (f.namedParameters.isNotEmpty) result.add(namedArgumentTemp);
     return result;
   }
 
-  void _emitVirtualFieldSymbols(Class c, List<JS.Statement> body) {
+  void _emitVirtualFieldSymbols(Class c, List<js_ast.Statement> body) {
     _classProperties.virtualFields.forEach((field, virtualField) {
       body.add(js.statement('const # = Symbol(#);', [
         virtualField,
@@ -2726,9 +2744,9 @@
     });
   }
 
-  List<JS.Identifier> _emitTypeFormals(List<TypeParameter> typeFormals) {
+  List<js_ast.Identifier> _emitTypeFormals(List<TypeParameter> typeFormals) {
     return typeFormals
-        .map((t) => JS.Identifier(getTypeParameterName(t)))
+        .map((t) => js_ast.Identifier(getTypeParameterName(t)))
         .toList();
   }
 
@@ -2737,29 +2755,31 @@
   ///
   /// This is an internal part of [_emitGeneratorFunctionBody] and should not be
   /// called directly.
-  JS.Expression _emitGeneratorFunctionExpression(
+  js_ast.Expression _emitGeneratorFunctionExpression(
       FunctionNode function, String name) {
-    emitGeneratorFn(List<JS.Parameter> getParameters(JS.Block jsBody)) {
+    emitGeneratorFn(List<js_ast.Parameter> getParameters(js_ast.Block jsBody)) {
       var savedController = _asyncStarController;
       _asyncStarController = function.asyncMarker == AsyncMarker.AsyncStar
-          ? JS.TemporaryId('stream')
+          ? js_ast.TemporaryId('stream')
           : null;
 
-      JS.Expression gen;
+      js_ast.Expression gen;
       _superDisallowed(() {
         // Visit the body with our async* controller set.
         //
         // Note: we intentionally don't emit argument initializers here, because
         // they were already emitted outside of the generator expression.
-        var jsBody = JS.Block(_withCurrentFunction(
+        var jsBody = js_ast.Block(_withCurrentFunction(
             function, () => [_emitFunctionScopedBody(function)]));
-        var genFn = JS.Fun(getParameters(jsBody), jsBody, isGenerator: true);
+        var genFn =
+            js_ast.Fun(getParameters(jsBody), jsBody, isGenerator: true);
 
         // Name the function if possible, to get better stack traces.
         gen = genFn;
         if (name != null) {
-          gen = JS.NamedFunction(
-              JS.TemporaryId(JS.friendlyNameForDartOperator[name] ?? name),
+          gen = js_ast.NamedFunction(
+              js_ast.TemporaryId(
+                  js_ast.friendlyNameForDartOperator[name] ?? name),
               genFn);
         }
 
@@ -2792,7 +2812,7 @@
       var jsParams = _emitParameters(function);
       var mutatedParams = jsParams;
       var gen = emitGeneratorFn((fnBody) {
-        var mutatedVars = JS.findMutatedVariables(fnBody);
+        var mutatedVars = js_ast.findMutatedVariables(fnBody);
         mutatedParams = jsParams
             .where((id) => mutatedVars.contains(id.parameterName))
             .toList();
@@ -2857,7 +2877,7 @@
   ///
   /// To emit an `async`, `sync*`, or `async*` function body, use
   /// [_emitGeneratorFunctionBody] instead.
-  JS.Block _emitSyncFunctionBody(FunctionNode f) {
+  js_ast.Block _emitSyncFunctionBody(FunctionNode f) {
     assert(f.asyncMarker == AsyncMarker.Sync);
 
     var block = _withCurrentFunction(f, () {
@@ -2868,7 +2888,7 @@
       return block;
     });
 
-    return JS.Block(block);
+    return js_ast.Block(block);
   }
 
   /// Emits an `async`, `sync*`, or `async*` function body.
@@ -2882,18 +2902,18 @@
   ///
   /// To emit a `sync` function body (the default in Dart), use
   /// [_emitSyncFunctionBody] instead.
-  JS.Block _emitGeneratorFunctionBody(FunctionNode f, String name) {
+  js_ast.Block _emitGeneratorFunctionBody(FunctionNode f, String name) {
     assert(f.asyncMarker != AsyncMarker.Sync);
 
     var statements =
         _withCurrentFunction(f, () => _emitArgumentInitializers(f));
     statements.add(_emitGeneratorFunctionExpression(f, name).toReturn()
       ..sourceInformation = _nodeStart(f));
-    return JS.Block(statements);
+    return js_ast.Block(statements);
   }
 
-  List<JS.Statement> _withCurrentFunction(
-      FunctionNode fn, List<JS.Statement> action()) {
+  List<js_ast.Statement> _withCurrentFunction(
+      FunctionNode fn, List<js_ast.Statement> action()) {
     var savedFunction = _currentFunction;
     _currentFunction = fn;
     _nullableInference.enterFunction(fn);
@@ -2915,12 +2935,12 @@
 
   /// Emits argument initializers, which handles optional/named args, as well
   /// as generic type checks needed due to our covariance.
-  List<JS.Statement> _emitArgumentInitializers(FunctionNode f) {
-    var body = <JS.Statement>[];
+  List<js_ast.Statement> _emitArgumentInitializers(FunctionNode f) {
+    var body = <js_ast.Statement>[];
 
     _emitCovarianceBoundsCheck(f.typeParameters, body);
 
-    initParameter(VariableDeclaration p, JS.Identifier jsParam) {
+    initParameter(VariableDeclaration p, js_ast.Identifier jsParam) {
       if (isCovariantParameter(p)) {
         var castExpr = _emitCast(jsParam, p.type);
         if (!identical(castExpr, jsParam)) body.add(castExpr.toStatement());
@@ -2931,11 +2951,11 @@
     }
 
     for (var p in f.positionalParameters.take(f.requiredParameterCount)) {
-      var jsParam = JS.Identifier(p.name);
+      var jsParam = js_ast.Identifier(p.name);
       initParameter(p, jsParam);
     }
     for (var p in f.positionalParameters.skip(f.requiredParameterCount)) {
-      var jsParam = JS.Identifier(p.name);
+      var jsParam = js_ast.Identifier(p.name);
       var defaultValue = _defaultParamValue(p);
       if (defaultValue != null) {
         body.add(js.statement(
@@ -2982,23 +3002,23 @@
       !m.annotations
           .any((a) => isBuiltinAnnotation(a, '_js_helper', 'NoReifyGeneric'));
 
-  JS.Statement _nullParameterCheck(JS.Expression param) {
+  js_ast.Statement _nullParameterCheck(js_ast.Expression param) {
     var call = runtimeCall('argumentError((#))', [param]);
     return js.statement('if (# == null) #;', [param, call]);
   }
 
-  JS.Expression _defaultParamValue(VariableDeclaration p) {
+  js_ast.Expression _defaultParamValue(VariableDeclaration p) {
     if (p.annotations.any(isUndefinedAnnotation)) {
       return null;
     } else if (p.initializer != null) {
       return _visitExpression(p.initializer);
     } else {
-      return JS.LiteralNull();
+      return js_ast.LiteralNull();
     }
   }
 
   void _emitCovarianceBoundsCheck(
-      List<TypeParameter> typeFormals, List<JS.Statement> body) {
+      List<TypeParameter> typeFormals, List<js_ast.Statement> body) {
     for (var t in typeFormals) {
       if (t.isGenericCovariantImpl && !types.isTop(t.bound)) {
         body.add(runtimeStatement('checkTypeBound(#, #, #)', [
@@ -3010,19 +3030,19 @@
     }
   }
 
-  JS.Statement _visitStatement(Statement s) {
+  js_ast.Statement _visitStatement(Statement s) {
     if (s == null) return null;
-    var result = s.accept(this) as JS.Statement;
+    var result = s.accept(this) as js_ast.Statement;
     // TODO(jmesserly): is the `is! Block` still necessary?
     if (s is! Block) result.sourceInformation = _nodeStart(s);
 
     // The statement might be the target of a break or continue with a label.
     var name = _labelNames[s];
-    if (name != null) result = JS.LabeledStatement(name, result);
+    if (name != null) result = js_ast.LabeledStatement(name, result);
     return result;
   }
 
-  JS.Statement _emitFunctionScopedBody(FunctionNode f) {
+  js_ast.Statement _emitFunctionScopedBody(FunctionNode f) {
     var jsBody = _visitStatement(f.body);
     if (f.positionalParameters.isNotEmpty || f.namedParameters.isNotEmpty) {
       // Handle shadowing of parameters by local varaibles, which is allowed in
@@ -3043,7 +3063,7 @@
   }
 
   /// Visits [nodes] with [_visitExpression].
-  List<JS.Expression> _visitExpressionList(Iterable<Expression> nodes) {
+  List<js_ast.Expression> _visitExpressionList(Iterable<Expression> nodes) {
     return nodes?.map(_visitExpression)?.toList();
   }
 
@@ -3052,14 +3072,14 @@
   /// to give a more helpful message.
   // TODO(sra): When nullablility is available earlier, it would be cleaner to
   // build an input AST where the boolean conversion is a single AST node.
-  JS.Expression _visitTest(Expression node) {
+  js_ast.Expression _visitTest(Expression node) {
     if (node == null) return null;
 
     if (node is Not) {
       return visitNot(node);
     }
     if (node is LogicalExpression) {
-      JS.Expression shortCircuit(String code) {
+      js_ast.Expression shortCircuit(String code) {
         return js.call(code, [_visitTest(node.left), _visitTest(node.right)]);
       }
 
@@ -3078,9 +3098,9 @@
     return result;
   }
 
-  JS.Expression _visitExpression(Expression e) {
+  js_ast.Expression _visitExpression(Expression e) {
     if (e == null) return null;
-    var result = e.accept(this) as JS.Expression;
+    var result = e.accept(this) as js_ast.Expression;
     result.sourceInformation ??= _nodeStart(e);
     return result;
   }
@@ -3138,18 +3158,19 @@
   /// For example, top-level and static fields are defined as lazy properties,
   /// on the library/class, so their access expressions do not appear in the
   /// source code.
-  HoverComment _hoverComment(JS.Expression expr, int offset, int nameLength) {
+  HoverComment _hoverComment(
+      js_ast.Expression expr, int offset, int nameLength) {
     var start = _getLocation(offset);
     var end = _getLocation(offset + nameLength);
     return start != null && end != null ? HoverComment(expr, start, end) : null;
   }
 
   @override
-  JS.Statement defaultStatement(Statement node) =>
+  js_ast.Statement defaultStatement(Statement node) =>
       _emitInvalidNode(node).toStatement();
 
   @override
-  JS.Statement visitExpressionStatement(ExpressionStatement node) {
+  js_ast.Statement visitExpressionStatement(ExpressionStatement node) {
     var expr = node.expression;
     if (expr is StaticInvocation) {
       if (isInlineJS(expr.target)) {
@@ -3163,7 +3184,7 @@
   }
 
   @override
-  JS.Statement visitBlock(Block node) {
+  js_ast.Statement visitBlock(Block node) {
     // If this is the block body of a function, don't mark it as a separate
     // scope, because the function is the scope. This avoids generating an
     // unncessary nested block.
@@ -3172,23 +3193,24 @@
     // slightly different (in Dart, there is a nested scope), but that's handled
     // by _emitSyncFunctionBody.
     var isScope = !identical(node.parent, _currentFunction);
-    return JS.Block(node.statements.map(_visitStatement).toList(),
+    return js_ast.Block(node.statements.map(_visitStatement).toList(),
         isScope: isScope);
   }
 
   @override
-  JS.Statement visitEmptyStatement(EmptyStatement node) => JS.EmptyStatement();
+  js_ast.Statement visitEmptyStatement(EmptyStatement node) =>
+      js_ast.EmptyStatement();
 
   @override
-  JS.Statement visitAssertBlock(AssertBlock node) {
+  js_ast.Statement visitAssertBlock(AssertBlock node) {
     // AssertBlocks are introduced by the VM-specific async elimination
     // transformation.  We do not expect them to arise here.
     throw UnsupportedError('compilation of an assert block');
   }
 
   @override
-  JS.Statement visitAssertStatement(AssertStatement node) {
-    if (!options.enableAsserts) return JS.EmptyStatement();
+  js_ast.Statement visitAssertStatement(AssertStatement node) {
+    if (!options.enableAsserts) return js_ast.EmptyStatement();
     var condition = node.condition;
     var conditionType = condition.getStaticType(types);
     var jsCondition = _visitExpression(condition);
@@ -3213,7 +3235,7 @@
       jsCondition,
       runtimeModule,
       if (node.message == null)
-        JS.LiteralNull()
+        js_ast.LiteralNull()
       else
         _visitExpression(node.message),
       js.escapedString(location.sourceUrl.toString()),
@@ -3235,7 +3257,7 @@
   }
 
   @override
-  JS.Statement visitLabeledStatement(LabeledStatement node) {
+  js_ast.Statement visitLabeledStatement(LabeledStatement node) {
     List<LabeledStatement> saved;
     var target = _effectiveTargets[node];
     // If the effective target is known then this statement is either contained
@@ -3273,20 +3295,20 @@
   }
 
   @override
-  JS.Statement visitBreakStatement(BreakStatement node) {
+  js_ast.Statement visitBreakStatement(BreakStatement node) {
     // Switch statements with continue labels must explicitly break to their
     // implicit label due to their being wrapped in a loop.
     if (_inLabeledContinueSwitch &&
         _switchLabelStates.containsKey(node.target.body)) {
-      return JS.Break(_switchLabelStates[node.target.body].label);
+      return js_ast.Break(_switchLabelStates[node.target.body].label);
     }
     // Can it be compiled to a break without a label?
     if (_currentBreakTargets.contains(node.target)) {
-      return JS.Break(null);
+      return js_ast.Break(null);
     }
     // Can it be compiled to a continue without a label?
     if (_currentContinueTargets.contains(node.target)) {
-      return JS.Continue(null);
+      return js_ast.Continue(null);
     }
 
     // Ensure the effective target is labeled.  Labels are named globally per
@@ -3304,10 +3326,10 @@
       current = (current as LabeledStatement).body;
     }
     if (identical(current, target)) {
-      return JS.Break(name);
+      return js_ast.Break(name);
     }
     // Otherwise it is a continue.
-    return JS.Continue(name);
+    return js_ast.Continue(name);
   }
 
   // Labeled loop bodies can be the target of a continue without a label
@@ -3327,7 +3349,7 @@
     return body;
   }
 
-  T translateLoop<T extends JS.Statement>(Statement node, T action()) {
+  T translateLoop<T extends js_ast.Statement>(Statement node, T action()) {
     List<LabeledStatement> savedBreakTargets;
     if (_currentBreakTargets.isNotEmpty &&
         _effectiveTargets[_currentBreakTargets.first] != node) {
@@ -3347,48 +3369,49 @@
   }
 
   @override
-  JS.While visitWhileStatement(WhileStatement node) {
+  js_ast.While visitWhileStatement(WhileStatement node) {
     return translateLoop(node, () {
       var condition = _visitTest(node.condition);
       var body = _visitScope(effectiveBodyOf(node, node.body));
-      return JS.While(condition, body);
+      return js_ast.While(condition, body);
     });
   }
 
   @override
-  JS.Do visitDoStatement(DoStatement node) {
+  js_ast.Do visitDoStatement(DoStatement node) {
     return translateLoop(node, () {
       var body = _visitScope(effectiveBodyOf(node, node.body));
       var condition = _visitTest(node.condition);
-      return JS.Do(body, condition);
+      return js_ast.Do(body, condition);
     });
   }
 
   @override
-  JS.For visitForStatement(ForStatement node) {
+  js_ast.For visitForStatement(ForStatement node) {
     return translateLoop(node, () {
-      emitForInitializer(VariableDeclaration v) => JS.VariableInitialization(
-          _emitVariableDef(v), _visitInitializer(v.initializer, v.annotations));
+      emitForInitializer(VariableDeclaration v) =>
+          js_ast.VariableInitialization(_emitVariableDef(v),
+              _visitInitializer(v.initializer, v.annotations));
 
       var init = node.variables.map(emitForInitializer).toList();
       var initList =
-          init.isEmpty ? null : JS.VariableDeclarationList('let', init);
+          init.isEmpty ? null : js_ast.VariableDeclarationList('let', init);
       var updates = node.updates;
-      JS.Expression update;
+      js_ast.Expression update;
       if (updates.isNotEmpty) {
-        update =
-            JS.Expression.binary(updates.map(_visitExpression).toList(), ',')
-                .toVoidExpression();
+        update = js_ast.Expression.binary(
+                updates.map(_visitExpression).toList(), ',')
+            .toVoidExpression();
       }
       var condition = _visitTest(node.condition);
       var body = _visitScope(effectiveBodyOf(node, node.body));
 
-      return JS.For(initList, condition, update, body);
+      return js_ast.For(initList, condition, update, body);
     });
   }
 
   @override
-  JS.Statement visitForInStatement(ForInStatement node) {
+  js_ast.Statement visitForInStatement(ForInStatement node) {
     return translateLoop(node, () {
       if (node.isAsync) {
         return _emitAwaitFor(node);
@@ -3399,20 +3422,22 @@
 
       var init = js.call('let #', _emitVariableDef(node.variable));
       if (_annotatedNullCheck(node.variable.annotations)) {
-        body = JS.Block(
+        body = js_ast.Block(
             [_nullParameterCheck(_emitVariableRef(node.variable)), body]);
       }
 
       if (variableIsReferenced(node.variable.name, iterable)) {
-        var temp = JS.TemporaryId('iter');
-        return JS.Block(
-            [iterable.toVariableDeclaration(temp), JS.ForOf(init, temp, body)]);
+        var temp = js_ast.TemporaryId('iter');
+        return js_ast.Block([
+          iterable.toVariableDeclaration(temp),
+          js_ast.ForOf(init, temp, body)
+        ]);
       }
-      return JS.ForOf(init, iterable, body);
+      return js_ast.ForOf(init, iterable, body);
     });
   }
 
-  JS.Statement _emitAwaitFor(ForInStatement node) {
+  js_ast.Statement _emitAwaitFor(ForInStatement node) {
     // Emits `await for (var value in stream) ...`, which desugars as:
     //
     // var iter = new StreamIterator(stream);
@@ -3431,14 +3456,14 @@
     // TODO(jmesserly): we may want a helper if these become common. For now the
     // full desugaring seems okay.
     var streamIterator = _asyncStreamIteratorClass.rawType;
-    var createStreamIter = JS.Call(
+    var createStreamIter = js_ast.Call(
         _emitConstructorName(
             streamIterator,
             _asyncStreamIteratorClass.procedures
                 .firstWhere((p) => p.isFactory && p.name.name == '')),
         [_visitExpression(node.iterable)]);
 
-    var iter = JS.TemporaryId('iter');
+    var iter = js_ast.TemporaryId('iter');
     return js.statement(
         '{'
         '  let # = #;'
@@ -3449,18 +3474,18 @@
         [
           iter,
           createStreamIter,
-          JS.Yield(js.call('#.moveNext()', iter))
+          js_ast.Yield(js.call('#.moveNext()', iter))
             ..sourceInformation = _nodeStart(node.variable),
           _emitVariableDef(node.variable),
           iter,
           _visitStatement(node.body),
-          JS.Yield(js.call('#.cancel()', iter))
+          js_ast.Yield(js.call('#.cancel()', iter))
             ..sourceInformation = _nodeStart(node.variable)
         ]);
   }
 
   @override
-  JS.Statement visitSwitchStatement(SwitchStatement node) {
+  js_ast.Statement visitSwitchStatement(SwitchStatement node) {
     // Switches with labeled continues are generated as an infinite loop with
     // an explicit variable for holding the switch's next case state and an
     // explicit label. Any implicit breaks are made explicit (e.g., when break
@@ -3468,10 +3493,10 @@
     var previous = _inLabeledContinueSwitch;
     _inLabeledContinueSwitch = hasLabeledContinue(node);
 
-    var cases = <JS.SwitchCase>[];
+    var cases = <js_ast.SwitchCase>[];
 
     if (_inLabeledContinueSwitch) {
-      var labelState = JS.TemporaryId("labelState");
+      var labelState = js_ast.TemporaryId("labelState");
       // TODO(markzipan): Retrieve the real label name with source offsets
       var labelName = 'SL${_switchLabelStates.length}';
       _switchLabelStates[node] = SwitchLabelState(labelName, labelState);
@@ -3483,13 +3508,13 @@
       }
 
       var switchExpr = _visitExpression(node.expression);
-      var switchStmt = JS.Switch(labelState, cases);
-      var loopBody = JS.Block([switchStmt, JS.Break(null)]);
-      var loopStmt = JS.While(js.boolean(true), loopBody);
+      var switchStmt = js_ast.Switch(labelState, cases);
+      var loopBody = js_ast.Block([switchStmt, js_ast.Break(null)]);
+      var loopStmt = js_ast.While(js.boolean(true), loopBody);
       // Note: Cannot use _labelNames, as the label must be on the loop.
       // not the block surrounding the switch statement.
-      var labeledStmt = JS.LabeledStatement(labelName, loopStmt);
-      var block = JS.Block([
+      var labeledStmt = js_ast.LabeledStatement(labelName, loopStmt);
+      var block = js_ast.Block([
         js.statement('let # = #', [labelState, switchExpr]),
         labeledStmt
       ]);
@@ -3502,7 +3527,7 @@
       if (subcases.isNotEmpty) cases.addAll(subcases);
     }
 
-    var stmt = JS.Switch(_visitExpression(node.expression), cases);
+    var stmt = js_ast.Switch(_visitExpression(node.expression), cases);
     _inLabeledContinueSwitch = previous;
     return stmt;
   }
@@ -3513,10 +3538,10 @@
   /// labeled continues. Dart permits the final case to implicitly break, but
   /// switch statements with labeled continues must explicitly break/continue
   /// to escape the surrounding infinite loop.
-  List<JS.SwitchCase> _visitSwitchCase(SwitchCase node,
+  List<js_ast.SwitchCase> _visitSwitchCase(SwitchCase node,
       {bool lastSwitchCase = false}) {
-    var cases = <JS.SwitchCase>[];
-    var emptyBlock = JS.Block.empty();
+    var cases = <js_ast.SwitchCase>[];
+    var emptyBlock = js_ast.Block.empty();
     // TODO(jmesserly): make sure we are statically checking fall through
     var body = _visitStatement(node.body).toBlock();
     var expressions = node.expressions;
@@ -3524,19 +3549,19 @@
         expressions.isNotEmpty && !node.isDefault ? expressions.last : null;
     for (var e in expressions) {
       var jsExpr = _visitExpression(e);
-      cases.add(JS.SwitchCase(jsExpr, e == lastExpr ? body : emptyBlock));
+      cases.add(js_ast.SwitchCase(jsExpr, e == lastExpr ? body : emptyBlock));
     }
     if (node.isDefault) {
-      cases.add(JS.SwitchCase.defaultCase(body));
+      cases.add(js_ast.SwitchCase.defaultCase(body));
     }
     // Switch statements with continue labels must explicitly break from their
     // last case to escape the additional loop around the switch.
     if (lastSwitchCase && _inLabeledContinueSwitch && cases.isNotEmpty) {
       // TODO(markzipan): avoid generating unreachable breaks
       assert(_switchLabelStates.containsKey(node.parent));
-      var breakStmt = JS.Break(_switchLabelStates[node.parent].label);
-      var switchBody = JS.Block(cases.last.body.statements..add(breakStmt));
-      var updatedSwitch = JS.SwitchCase(cases.last.expression, switchBody);
+      var breakStmt = js_ast.Break(_switchLabelStates[node.parent].label);
+      var switchBody = js_ast.Block(cases.last.body.statements..add(breakStmt));
+      var updatedSwitch = js_ast.SwitchCase(cases.last.expression, switchBody);
       cases.removeLast();
       cases.add(updatedSwitch);
     }
@@ -3544,7 +3569,7 @@
   }
 
   @override
-  JS.Statement visitContinueSwitchStatement(ContinueSwitchStatement node) {
+  js_ast.Statement visitContinueSwitchStatement(ContinueSwitchStatement node) {
     var switchStmt = node.target.parent;
     if (_inLabeledContinueSwitch &&
         _switchLabelStates.containsKey(switchStmt)) {
@@ -3555,8 +3580,8 @@
           ? js.call("Symbol('_default')", [])
           : _visitExpression(node.target.expressions[0]);
       var setStateStmt = js.statement("# = #", [switchState.variable, jsExpr]);
-      var continueStmt = JS.Continue(switchState.label);
-      return JS.Block([setStateStmt, continueStmt]);
+      var continueStmt = js_ast.Continue(switchState.label);
+      return js_ast.Block([setStateStmt, continueStmt]);
     }
     return _emitInvalidNode(
             node, 'see https://github.com/dart-lang/sdk/issues/29352')
@@ -3564,8 +3589,8 @@
   }
 
   @override
-  JS.Statement visitIfStatement(IfStatement node) {
-    return JS.If(_visitTest(node.condition), _visitScope(node.then),
+  js_ast.Statement visitIfStatement(IfStatement node) {
+    return js_ast.If(_visitTest(node.condition), _visitScope(node.then),
         _visitScope(node.otherwise));
   }
 
@@ -3575,27 +3600,27 @@
   ///
   ///     do var x = 5; while (false); // Dart
   ///     do { let x = 5; } while (false); // JS
-  JS.Statement _visitScope(Statement stmt) {
+  js_ast.Statement _visitScope(Statement stmt) {
     var result = _visitStatement(stmt);
-    if (result is JS.ExpressionStatement &&
-        result.expression is JS.VariableDeclarationList) {
-      return JS.Block([result]);
+    if (result is js_ast.ExpressionStatement &&
+        result.expression is js_ast.VariableDeclarationList) {
+      return js_ast.Block([result]);
     }
     return result;
   }
 
   @override
-  JS.Statement visitReturnStatement(ReturnStatement node) {
+  js_ast.Statement visitReturnStatement(ReturnStatement node) {
     return super.emitReturnStatement(_visitExpression(node.expression));
   }
 
   @override
-  JS.Statement visitTryCatch(TryCatch node) {
-    return JS.Try(
+  js_ast.Statement visitTryCatch(TryCatch node) {
+    return js_ast.Try(
         _visitStatement(node.body).toBlock(), _visitCatch(node.catches), null);
   }
 
-  JS.Catch _visitCatch(List<Catch> clauses) {
+  js_ast.Catch _visitCatch(List<Catch> clauses) {
     if (clauses.isEmpty) return null;
 
     var caughtError = VariableDeclaration('#e');
@@ -3614,7 +3639,7 @@
                 ? VariableDeclaration('#st')
                 : null);
 
-    JS.Statement catchBody = JS.Throw(_emitVariableRef(caughtError));
+    js_ast.Statement catchBody = js_ast.Throw(_emitVariableRef(caughtError));
     for (var clause in clauses.reversed) {
       catchBody = _catchClauseGuard(
           clause, catchBody, exceptionParameter, stackTraceParameter);
@@ -3634,15 +3659,16 @@
       catchBody,
     ];
     _rethrowParameter = savedRethrow;
-    return JS.Catch(_emitVariableDef(caughtError), JS.Block(catchStatements));
+    return js_ast.Catch(
+        _emitVariableDef(caughtError), js_ast.Block(catchStatements));
   }
 
-  JS.Statement _catchClauseGuard(
+  js_ast.Statement _catchClauseGuard(
       Catch node,
-      JS.Statement otherwise,
+      js_ast.Statement otherwise,
       VariableDeclaration exceptionParameter,
       VariableDeclaration stackTraceParameter) {
-    var body = <JS.Statement>[];
+    var body = <js_ast.Statement>[];
     var vars = HashSet<String>();
 
     void declareVariable(
@@ -3659,34 +3685,34 @@
     declareVariable(node.stackTrace, stackTraceParameter);
 
     body.add(_visitStatement(node.body).toScopedBlock(vars));
-    var then = JS.Block(body);
+    var then = js_ast.Block(body);
 
     // Discard following clauses, if any, as they are unreachable.
     if (types.isTop(node.guard)) return then;
 
     var condition =
         _emitIsExpression(VariableGet(exceptionParameter), node.guard);
-    return JS.If(condition, then, otherwise)
+    return js_ast.If(condition, then, otherwise)
       ..sourceInformation = _nodeStart(node);
   }
 
   @override
-  JS.Statement visitTryFinally(TryFinally node) {
+  js_ast.Statement visitTryFinally(TryFinally node) {
     var body = _visitStatement(node.body);
     var finallyBlock =
         _superDisallowed(() => _visitStatement(node.finalizer).toBlock());
 
-    if (body is JS.Try && body.finallyPart == null) {
+    if (body is js_ast.Try && body.finallyPart == null) {
       // Kernel represents Dart try/catch/finally as try/catch nested inside of
       // try/finally.  Flatten that pattern in the output into JS try/catch/
       // finally.
-      return JS.Try(body.body, body.catchPart, finallyBlock);
+      return js_ast.Try(body.body, body.catchPart, finallyBlock);
     }
-    return JS.Try(body.toBlock(), null, finallyBlock);
+    return js_ast.Try(body.toBlock(), null, finallyBlock);
   }
 
   @override
-  JS.Statement visitYieldStatement(YieldStatement node) {
+  js_ast.Statement visitYieldStatement(YieldStatement node) {
     var jsExpr = _visitExpression(node.expression);
     var star = node.isYieldStar;
     if (_asyncStarController != null) {
@@ -3705,7 +3731,7 @@
         _asyncStarController,
         helperName,
         jsExpr,
-        JS.Yield(null)..sourceInformation = _nodeStart(node)
+        js_ast.Yield(null)..sourceInformation = _nodeStart(node)
       ]);
     }
     // A normal yield in a sync*
@@ -3713,7 +3739,7 @@
   }
 
   @override
-  JS.Statement visitVariableDeclaration(VariableDeclaration node) {
+  js_ast.Statement visitVariableDeclaration(VariableDeclaration node) {
     // TODO(jmesserly): casts are sometimes required here.
     // Kernel does not represent these explicitly.
     var v = _emitVariableDef(node);
@@ -3722,15 +3748,15 @@
   }
 
   @override
-  JS.Statement visitFunctionDeclaration(FunctionDeclaration node) {
+  js_ast.Statement visitFunctionDeclaration(FunctionDeclaration node) {
     var func = node.function;
     var fn = _emitFunction(func, node.variable.name);
 
     var name = _emitVariableDef(node.variable);
-    JS.Statement declareFn;
+    js_ast.Statement declareFn;
     declareFn = toBoundFunctionStatement(fn, name);
     if (_reifyFunctionType(func)) {
-      declareFn = JS.Block([
+      declareFn = js_ast.Block([
         declareFn,
         _emitFunctionTagged(_emitVariableRef(node.variable), func.functionType)
             .toStatement()
@@ -3740,22 +3766,23 @@
   }
 
   @override
-  JS.Expression defaultExpression(Expression node) => _emitInvalidNode(node);
+  js_ast.Expression defaultExpression(Expression node) =>
+      _emitInvalidNode(node);
 
   @override
-  JS.Expression defaultBasicLiteral(BasicLiteral node) =>
+  js_ast.Expression defaultBasicLiteral(BasicLiteral node) =>
       defaultExpression(node);
 
   @override
-  JS.Expression visitInvalidExpression(InvalidExpression node) =>
+  js_ast.Expression visitInvalidExpression(InvalidExpression node) =>
       defaultExpression(node);
 
   @override
-  JS.Expression visitConstantExpression(ConstantExpression node) =>
-      node.constant.accept(this) as JS.Expression;
+  js_ast.Expression visitConstantExpression(ConstantExpression node) =>
+      node.constant.accept(this) as js_ast.Expression;
 
   @override
-  JS.Expression visitVariableGet(VariableGet node) {
+  js_ast.Expression visitVariableGet(VariableGet node) {
     var v = node.variable;
     var id = _emitVariableRef(v);
     if (id.name == v.name) {
@@ -3764,29 +3791,29 @@
     return id;
   }
 
-  JS.Identifier _emitVariableRef(VariableDeclaration v) {
+  js_ast.Identifier _emitVariableRef(VariableDeclaration v) {
     var name = v.name;
     if (name == null || name.startsWith('#')) {
       name = name == null ? 't${_tempVariables.length}' : name.substring(1);
-      return _tempVariables.putIfAbsent(v, () => JS.TemporaryId(name));
+      return _tempVariables.putIfAbsent(v, () => js_ast.TemporaryId(name));
     }
-    return JS.Identifier(name);
+    return js_ast.Identifier(name);
   }
 
   /// Emits the declaration of a variable.
   ///
   /// This is similar to [_emitVariableRef] but it also attaches source
   /// location information, so hover will work as expected.
-  JS.Identifier _emitVariableDef(VariableDeclaration v) {
+  js_ast.Identifier _emitVariableDef(VariableDeclaration v) {
     return _emitVariableRef(v)..sourceInformation = _nodeStart(v);
   }
 
-  JS.Statement _initLetVariables() {
+  js_ast.Statement _initLetVariables() {
     if (_letVariables.isEmpty) return null;
-    var result = JS.VariableDeclarationList(
+    var result = js_ast.VariableDeclarationList(
             'let',
             _letVariables
-                .map((v) => JS.VariableInitialization(v, null))
+                .map((v) => js_ast.VariableInitialization(v, null))
                 .toList())
         .toStatement();
     _letVariables.clear();
@@ -3795,33 +3822,33 @@
 
   // TODO(jmesserly): resugar operators for kernel, such as ++x, x++, x+=.
   @override
-  JS.Expression visitVariableSet(VariableSet node) =>
+  js_ast.Expression visitVariableSet(VariableSet node) =>
       _visitExpression(node.value)
           .toAssignExpression(_emitVariableRef(node.variable));
 
   @override
-  JS.Expression visitPropertyGet(PropertyGet node) {
+  js_ast.Expression visitPropertyGet(PropertyGet node) {
     return _emitPropertyGet(
         node.receiver, node.interfaceTarget, node.name.name);
   }
 
   @override
-  JS.Expression visitPropertySet(PropertySet node) {
+  js_ast.Expression visitPropertySet(PropertySet node) {
     return _emitPropertySet(
         node.receiver, node.interfaceTarget, node.value, node.name.name);
   }
 
   @override
-  JS.Expression visitDirectPropertyGet(DirectPropertyGet node) {
+  js_ast.Expression visitDirectPropertyGet(DirectPropertyGet node) {
     return _emitPropertyGet(node.receiver, node.target);
   }
 
   @override
-  JS.Expression visitDirectPropertySet(DirectPropertySet node) {
+  js_ast.Expression visitDirectPropertySet(DirectPropertySet node) {
     return _emitPropertySet(node.receiver, node.target, node.value);
   }
 
-  JS.Expression _emitPropertyGet(Expression receiver, Member member,
+  js_ast.Expression _emitPropertyGet(Expression receiver, Member member,
       [String memberName]) {
     memberName ??= member.name.name;
     // TODO(jmesserly): should tearoff of `.call` on a function type be
@@ -3856,7 +3883,7 @@
     if (_reifyTearoff(member)) {
       return runtimeCall('bind(#, #)', [jsReceiver, jsName]);
     } else {
-      return JS.PropertyAccess(jsReceiver, jsName);
+      return js_ast.PropertyAccess(jsReceiver, jsName);
     }
   }
 
@@ -3865,7 +3892,7 @@
   // access to the target expression there (needed for `dart.replNameLookup`).
   String get _replSuffix => options.replCompile ? 'Repl' : '';
 
-  JS.Expression _emitPropertySet(
+  js_ast.Expression _emitPropertySet(
       Expression receiver, Member member, Expression value,
       [String memberName]) {
     var jsName =
@@ -3882,7 +3909,7 @@
   }
 
   @override
-  JS.Expression visitSuperPropertyGet(SuperPropertyGet node) {
+  js_ast.Expression visitSuperPropertyGet(SuperPropertyGet node) {
     var target = node.interfaceTarget;
     var jsTarget = _emitSuperTarget(target);
     if (_reifyTearoff(target)) {
@@ -3892,16 +3919,17 @@
   }
 
   @override
-  JS.Expression visitSuperPropertySet(SuperPropertySet node) {
+  js_ast.Expression visitSuperPropertySet(SuperPropertySet node) {
     var target = node.interfaceTarget;
     var jsTarget = _emitSuperTarget(target, setter: true);
     return _visitExpression(node.value).toAssignExpression(jsTarget);
   }
 
   @override
-  JS.Expression visitStaticGet(StaticGet node) => _emitStaticGet(node.target);
+  js_ast.Expression visitStaticGet(StaticGet node) =>
+      _emitStaticGet(node.target);
 
-  JS.Expression _emitStaticGet(Member target) {
+  js_ast.Expression _emitStaticGet(Member target) {
     // TODO(vsm): Re-inline constants.  See:
     // https://github.com/dart-lang/sdk/issues/36285
     var result = _emitStaticTarget(target);
@@ -3915,23 +3943,23 @@
   }
 
   @override
-  JS.Expression visitStaticSet(StaticSet node) {
+  js_ast.Expression visitStaticSet(StaticSet node) {
     return _visitExpression(node.value)
         .toAssignExpression(_emitStaticTarget(node.target));
   }
 
   @override
-  JS.Expression visitMethodInvocation(MethodInvocation node) {
+  js_ast.Expression visitMethodInvocation(MethodInvocation node) {
     return _emitMethodCall(
         node.receiver, node.interfaceTarget, node.arguments, node);
   }
 
   @override
-  JS.Expression visitDirectMethodInvocation(DirectMethodInvocation node) {
+  js_ast.Expression visitDirectMethodInvocation(DirectMethodInvocation node) {
     return _emitMethodCall(node.receiver, node.target, node.arguments, node);
   }
 
-  JS.Expression _emitMethodCall(Expression receiver, Member target,
+  js_ast.Expression _emitMethodCall(Expression receiver, Member target,
       Arguments arguments, InvocationExpression node) {
     var name = node.name.name;
 
@@ -3957,7 +3985,7 @@
         return _emitDynamicInvoke(jsReceiver, null, args, arguments);
       } else if (_isDirectCallable(receiverType)) {
         // Call methods on function types should be handled as function calls.
-        return JS.Call(jsReceiver, args);
+        return js_ast.Call(jsReceiver, args);
       }
     }
 
@@ -3988,8 +4016,11 @@
     return js.call('#.#(#)', [jsReceiver, jsName, args]);
   }
 
-  JS.Expression _emitDynamicInvoke(JS.Expression fn, JS.Expression methodName,
-      Iterable<JS.Expression> args, Arguments arguments) {
+  js_ast.Expression _emitDynamicInvoke(
+      js_ast.Expression fn,
+      js_ast.Expression methodName,
+      Iterable<js_ast.Expression> args,
+      Arguments arguments) {
     var jsArgs = <Object>[fn];
     String jsCode;
 
@@ -4026,7 +4057,7 @@
   bool _isDirectCallable(DartType t) =>
       t is FunctionType || t is InterfaceType && usesJSInterop(t.classNode);
 
-  JS.Expression _getImplicitCallTarget(InterfaceType from) {
+  js_ast.Expression _getImplicitCallTarget(InterfaceType from) {
     var c = from.classNode;
     var member = hierarchy.getInterfaceMember(c, Name("call"));
     if (member is Procedure && !member.isAccessor && !usesJSInterop(c)) {
@@ -4038,7 +4069,7 @@
   bool _isDynamicOrFunction(DartType t) =>
       t == coreTypes.functionClass.rawType || t == const DynamicType();
 
-  JS.Expression _emitUnaryOperator(
+  js_ast.Expression _emitUnaryOperator(
       Expression expr, Member target, InvocationExpression node) {
     var op = node.name.name;
     if (target != null) {
@@ -4062,8 +4093,8 @@
   /// the interpretation of the 32-bit value from signed to unsigned.  Most
   /// JavaScript operations interpret their operands as signed and generate
   /// signed results.
-  JS.Expression _coerceBitOperationResultToUnsigned(
-      Expression node, JS.Expression uncoerced) {
+  js_ast.Expression _coerceBitOperationResultToUnsigned(
+      Expression node, js_ast.Expression uncoerced) {
     // Don't coerce if the parent will coerce.
     var parent = node.parent;
     if (parent is InvocationExpression && _nodeIsBitwiseOperation(parent)) {
@@ -4203,7 +4234,7 @@
     return bitWidth(expr, 0) < 32;
   }
 
-  JS.Expression _emitBinaryOperator(Expression left, Member target,
+  js_ast.Expression _emitBinaryOperator(Expression left, Member target,
       Expression right, InvocationExpression node) {
     var op = node.name.name;
     if (op == '==') return _emitEqualityOperator(left, target, right);
@@ -4223,11 +4254,11 @@
 
         /// Emits an inlined binary operation using the JS [code], adding null
         /// checks if needed to ensure we throw the appropriate error.
-        JS.Expression binary(String code) {
+        js_ast.Expression binary(String code) {
           return js.call(code, [notNull(left), notNull(right)]);
         }
 
-        JS.Expression bitwise(String code) {
+        js_ast.Expression bitwise(String code) {
           return _coerceBitOperationResultToUnsigned(node, binary(code));
         }
 
@@ -4236,7 +4267,7 @@
         ///
         /// Short circuiting operators should not be used in [code], because the
         /// null checks for both operands must happen unconditionally.
-        JS.Expression bitwiseBool(String code) {
+        js_ast.Expression bitwiseBool(String code) {
           return js.call(code, [notNull(left), _visitTest(right)]);
         }
 
@@ -4307,7 +4338,7 @@
     return _emitOperatorCall(left, target, op, [right]);
   }
 
-  JS.Expression _emitEqualityOperator(
+  js_ast.Expression _emitEqualityOperator(
       Expression left, Member target, Expression right,
       {bool negated = false}) {
     var targetClass = target?.enclosingClass;
@@ -4364,7 +4395,7 @@
   /// **Please note** this function does not support method invocation syntax
   /// `obj.name(args)` because that could be a getter followed by a call.
   /// See [visitMethodInvocation].
-  JS.Expression _emitOperatorCall(
+  js_ast.Expression _emitOperatorCall(
       Expression receiver, Member target, String name, List<Expression> args) {
     // TODO(jmesserly): calls that don't pass `element` are probably broken for
     // `super` calls from disallowed super locations.
@@ -4391,20 +4422,20 @@
 
   // TODO(jmesserly): optimize super operators for kernel
   @override
-  JS.Expression visitSuperMethodInvocation(SuperMethodInvocation node) {
+  js_ast.Expression visitSuperMethodInvocation(SuperMethodInvocation node) {
     var target = node.interfaceTarget;
-    return JS.Call(_emitSuperTarget(target),
+    return js_ast.Call(_emitSuperTarget(target),
         _emitArgumentList(node.arguments, target: target));
   }
 
-  /// Emits the [JS.PropertyAccess] for accessors or method calls to
+  /// Emits the [js_ast.PropertyAccess] for accessors or method calls to
   /// [jsTarget].[jsName], replacing `super` if it is not allowed in scope.
-  JS.PropertyAccess _emitSuperTarget(Member member, {bool setter = false}) {
+  js_ast.PropertyAccess _emitSuperTarget(Member member, {bool setter = false}) {
     var jsName = _emitMemberName(member.name.name, member: member);
     if (member is Field && !virtualFields.isVirtual(member)) {
-      return JS.PropertyAccess(JS.This(), jsName);
+      return js_ast.PropertyAccess(js_ast.This(), jsName);
     }
-    if (_superAllowed) return JS.PropertyAccess(JS.Super(), jsName);
+    if (_superAllowed) return js_ast.PropertyAccess(js_ast.Super(), jsName);
 
     // If we can't emit `super` in this context, generate a helper that does it
     // for us, and call the helper.
@@ -4421,30 +4452,30 @@
                 : 'function() { return super[#]; }',
             [jsName]);
 
-        return JS.Method(JS.TemporaryId(name), fn,
+        return js_ast.Method(js_ast.TemporaryId(name), fn,
             isGetter: !setter, isSetter: setter);
       } else {
         var function = member.function;
         var params = [
           ..._emitTypeFormals(function.typeParameters),
           for (var param in function.positionalParameters)
-            JS.Identifier(param.name),
+            js_ast.Identifier(param.name),
           if (function.namedParameters.isNotEmpty) namedArgumentTemp,
         ];
 
         var fn = js.fun(
             'function(#) { return super[#](#); }', [params, jsName, params]);
-        name = JS.friendlyNameForDartOperator[name] ?? name;
-        return JS.Method(JS.TemporaryId(name), fn);
+        name = js_ast.friendlyNameForDartOperator[name] ?? name;
+        return js_ast.Method(js_ast.TemporaryId(name), fn);
       }
     });
-    return JS.PropertyAccess(JS.This(), jsMethod.name);
+    return js_ast.PropertyAccess(js_ast.This(), jsMethod.name);
   }
 
   @override
-  JS.Expression visitStaticInvocation(StaticInvocation node) {
+  js_ast.Expression visitStaticInvocation(StaticInvocation node) {
     var target = node.target;
-    if (isInlineJS(target)) return _emitInlineJSCode(node) as JS.Expression;
+    if (isInlineJS(target)) return _emitInlineJSCode(node) as js_ast.Expression;
     if (target.isFactory) return _emitFactoryInvocation(node);
 
     // Optimize some internal SDK calls.
@@ -4469,12 +4500,12 @@
       return _emitCoreIdenticalCall(node.arguments.positional);
     }
     if (_isDebuggerCall(target)) {
-      return _emitDebuggerCall(node) as JS.Expression;
+      return _emitDebuggerCall(node) as js_ast.Expression;
     }
 
     var fn = _emitStaticTarget(target);
     var args = _emitArgumentList(node.arguments, target: target);
-    return JS.Call(fn, args);
+    return js_ast.Call(fn, args);
   }
 
   bool _isDebuggerCall(Procedure target) {
@@ -4482,7 +4513,7 @@
         target.enclosingLibrary.importUri.toString() == 'dart:developer';
   }
 
-  JS.Node _emitDebuggerCall(StaticInvocation node) {
+  js_ast.Node _emitDebuggerCall(StaticInvocation node) {
     var args = node.arguments.named;
     var isStatement = node.parent is ExpressionStatement;
     if (args.isEmpty) {
@@ -4510,17 +4541,17 @@
         // coerces to true (the default value of `when`).
         ? (args[0].name == 'when'
             ? jsArgs[0].value
-            : JS.ObjectInitializer(jsArgs))
+            : js_ast.ObjectInitializer(jsArgs))
         // If we have both `message` and `when` arguments, evaluate them in
         // order, then extract the `when` argument.
-        : js.call('#.when', JS.ObjectInitializer(jsArgs));
+        : js.call('#.when', js_ast.ObjectInitializer(jsArgs));
     return isStatement
         ? js.statement('if (#) debugger;', when)
         : js.call('# && (() => { debugger; return true })()', when);
   }
 
   /// Emits the target of a [StaticInvocation], [StaticGet], or [StaticSet].
-  JS.Expression _emitStaticTarget(Member target) {
+  js_ast.Expression _emitStaticTarget(Member target) {
     var c = target.enclosingClass;
     if (c != null) {
       // A static native element should just forward directly to the JS type's
@@ -4534,13 +4565,13 @@
           return runtimeCall('global.#.#', [nativeName[0], memberName]);
         }
       }
-      return JS.PropertyAccess(_emitStaticClassName(c),
+      return js_ast.PropertyAccess(_emitStaticClassName(c),
           _emitStaticMemberName(target.name.name, target));
     }
     return _emitTopLevelName(target);
   }
 
-  List<JS.Expression> _emitArgumentList(Arguments node,
+  List<js_ast.Expression> _emitArgumentList(Arguments node,
       {bool types = true, Member target}) {
     types = types && _reifyGenericFunction(target);
     return [
@@ -4549,20 +4580,20 @@
         if (arg is StaticInvocation &&
             isJSSpreadInvocation(arg.target) &&
             arg.arguments.positional.length == 1)
-          JS.Spread(_visitExpression(arg.arguments.positional[0]))
+          js_ast.Spread(_visitExpression(arg.arguments.positional[0]))
         else
           _visitExpression(arg),
       if (node.named.isNotEmpty)
-        JS.ObjectInitializer(node.named.map(_emitNamedExpression).toList()),
+        js_ast.ObjectInitializer(node.named.map(_emitNamedExpression).toList()),
     ];
   }
 
-  JS.Property _emitNamedExpression(NamedExpression arg) {
-    return JS.Property(propertyName(arg.name), _visitExpression(arg.value));
+  js_ast.Property _emitNamedExpression(NamedExpression arg) {
+    return js_ast.Property(propertyName(arg.name), _visitExpression(arg.value));
   }
 
   /// Emits code for the `JS(...)` macro.
-  JS.Node _emitInlineJSCode(StaticInvocation node) {
+  js_ast.Node _emitInlineJSCode(StaticInvocation node) {
     var args = node.arguments.positional;
     // arg[0] is static return type, used in `RestrictedStaticTypeAnalyzer`
     var code = args[1];
@@ -4604,8 +4635,8 @@
 
     var result = js.parseForeignJS(source).instantiate(jsArgs);
 
-    assert(result is JS.Expression ||
-        result is JS.Statement && node.parent is ExpressionStatement);
+    assert(result is js_ast.Expression ||
+        result is js_ast.Statement && node.parent is ExpressionStatement);
     return result;
   }
 
@@ -4635,19 +4666,19 @@
   /// [_notNullLocals].
   bool isNullable(Expression expr) => _nullableInference.isNullable(expr);
 
-  JS.Expression _emitJSDoubleEq(List<JS.Expression> args,
+  js_ast.Expression _emitJSDoubleEq(List<js_ast.Expression> args,
       {bool negated = false}) {
     var op = negated ? '# != #' : '# == #';
     return js.call(op, args);
   }
 
-  JS.Expression _emitJSTripleEq(List<JS.Expression> args,
+  js_ast.Expression _emitJSTripleEq(List<js_ast.Expression> args,
       {bool negated = false}) {
     var op = negated ? '# !== #' : '# === #';
     return js.call(op, args);
   }
 
-  JS.Expression _emitCoreIdenticalCall(List<Expression> args,
+  js_ast.Expression _emitCoreIdenticalCall(List<Expression> args,
       {bool negated = false}) {
     if (args.length != 2) {
       // Shouldn't happen in typechecked code
@@ -4664,21 +4695,21 @@
       return _emitJSDoubleEq(jsArgs, negated: negated);
     }
     var code = negated ? '!#' : '#';
-    return js.call(
-        code, JS.Call(_emitTopLevelName(coreTypes.identicalProcedure), jsArgs));
+    return js.call(code,
+        js_ast.Call(_emitTopLevelName(coreTypes.identicalProcedure), jsArgs));
   }
 
   @override
-  JS.Expression visitConstructorInvocation(ConstructorInvocation node) {
+  js_ast.Expression visitConstructorInvocation(ConstructorInvocation node) {
     var ctor = node.target;
     var args = node.arguments;
-    var result = JS.New(_emitConstructorName(node.constructedType, ctor),
+    var result = js_ast.New(_emitConstructorName(node.constructedType, ctor),
         _emitArgumentList(args, types: false));
 
     return node.isConst ? canonicalizeConstObject(result) : result;
   }
 
-  JS.Expression _emitFactoryInvocation(StaticInvocation node) {
+  js_ast.Expression _emitFactoryInvocation(StaticInvocation node) {
     var args = node.arguments;
     var ctor = node.target;
     var ctorClass = ctor.enclosingClass;
@@ -4693,7 +4724,7 @@
     if (isFromEnvironmentInvocation(coreTypes, node)) {
       var value = _constants.evaluate(node);
       if (value is PrimitiveConstant) {
-        return value.accept(this) as JS.Expression;
+        return value.accept(this) as js_ast.Expression;
       }
     }
 
@@ -4730,20 +4761,20 @@
       }
     }
 
-    var result = JS.Call(_emitConstructorName(type, ctor),
+    var result = js_ast.Call(_emitConstructorName(type, ctor),
         _emitArgumentList(args, types: false));
 
     return node.isConst ? canonicalizeConstObject(result) : result;
   }
 
-  JS.Expression _emitJSInteropNew(Member ctor, Arguments args) {
+  js_ast.Expression _emitJSInteropNew(Member ctor, Arguments args) {
     var ctorClass = ctor.enclosingClass;
     if (isJSAnonymousType(ctorClass)) return _emitObjectLiteral(args);
-    return JS.New(_emitConstructorName(ctorClass.rawType, ctor),
+    return js_ast.New(_emitConstructorName(ctorClass.rawType, ctor),
         _emitArgumentList(args, types: false));
   }
 
-  JS.Expression _emitMapImplType(InterfaceType type, {bool identity}) {
+  js_ast.Expression _emitMapImplType(InterfaceType type, {bool identity}) {
     var typeArgs = type.typeArguments;
     if (typeArgs.isEmpty) return _emitType(type);
     identity ??= _typeRep.isPrimitive(typeArgs[0]);
@@ -4751,7 +4782,7 @@
     return _emitType(InterfaceType(c, typeArgs));
   }
 
-  JS.Expression _emitSetImplType(InterfaceType type, {bool identity}) {
+  js_ast.Expression _emitSetImplType(InterfaceType type, {bool identity}) {
     var typeArgs = type.typeArguments;
     if (typeArgs.isEmpty) return _emitType(type);
     identity ??= _typeRep.isPrimitive(typeArgs[0]);
@@ -4759,15 +4790,15 @@
     return _emitType(InterfaceType(c, typeArgs));
   }
 
-  JS.Expression _emitObjectLiteral(Arguments node) {
+  js_ast.Expression _emitObjectLiteral(Arguments node) {
     var args = _emitArgumentList(node, types: false);
     if (args.isEmpty) return js.call('{}');
-    assert(args.single is JS.ObjectInitializer);
+    assert(args.single is js_ast.ObjectInitializer);
     return args.single;
   }
 
   @override
-  JS.Expression visitNot(Not node) {
+  js_ast.Expression visitNot(Not node) {
     var operand = node.operand;
     if (operand is MethodInvocation && operand.name.name == '==') {
       return _emitEqualityOperator(operand.receiver, operand.interfaceTarget,
@@ -4789,14 +4820,14 @@
   }
 
   @override
-  JS.Expression visitLogicalExpression(LogicalExpression node) {
+  js_ast.Expression visitLogicalExpression(LogicalExpression node) {
     // The operands of logical boolean operators are subject to boolean
     // conversion.
     return _visitTest(node);
   }
 
   @override
-  JS.Expression visitConditionalExpression(ConditionalExpression node) {
+  js_ast.Expression visitConditionalExpression(ConditionalExpression node) {
     return js.call('# ? # : #', [
       _visitTest(node.condition),
       _visitExpression(node.then),
@@ -4806,11 +4837,11 @@
   }
 
   @override
-  JS.Expression visitStringConcatenation(StringConcatenation node) {
-    var parts = <JS.Expression>[];
+  js_ast.Expression visitStringConcatenation(StringConcatenation node) {
+    var parts = <js_ast.Expression>[];
     for (var e in node.expressions) {
       var jsExpr = _visitExpression(e);
-      if (jsExpr is JS.LiteralString && jsExpr.valueWithoutQuotes.isEmpty) {
+      if (jsExpr is js_ast.LiteralString && jsExpr.valueWithoutQuotes.isEmpty) {
         continue;
       }
       parts.add(e.getStaticType(types) == types.stringType && !isNullable(e)
@@ -4818,13 +4849,13 @@
           : runtimeCall('str(#)', [jsExpr]));
     }
     if (parts.isEmpty) return js.string('');
-    return JS.Expression.binary(parts, '+');
+    return js_ast.Expression.binary(parts, '+');
   }
 
   @override
-  JS.Expression visitListConcatenation(ListConcatenation node) {
+  js_ast.Expression visitListConcatenation(ListConcatenation node) {
     // Only occurs inside unevaluated constants.
-    List<JS.Expression> entries = [];
+    List<js_ast.Expression> entries = [];
     _concatenate(Expression node) {
       if (node is ListConcatenation) {
         node.lists.forEach(_concatenate);
@@ -4844,9 +4875,9 @@
   }
 
   @override
-  JS.Expression visitSetConcatenation(SetConcatenation node) {
+  js_ast.Expression visitSetConcatenation(SetConcatenation node) {
     // Only occurs inside unevaluated constants.
-    List<JS.Expression> entries = [];
+    List<js_ast.Expression> entries = [];
     _concatenate(Expression node) {
       if (node is SetConcatenation) {
         node.sets.forEach(_concatenate);
@@ -4866,9 +4897,9 @@
   }
 
   @override
-  JS.Expression visitMapConcatenation(MapConcatenation node) {
+  js_ast.Expression visitMapConcatenation(MapConcatenation node) {
     // Only occurs inside unevaluated constants.
-    List<JS.Expression> entries = [];
+    List<js_ast.Expression> entries = [];
     _concatenate(Expression node) {
       if (node is MapConcatenation) {
         node.maps.forEach(_concatenate);
@@ -4894,17 +4925,17 @@
   }
 
   @override
-  JS.Expression visitInstanceCreation(InstanceCreation node) {
+  js_ast.Expression visitInstanceCreation(InstanceCreation node) {
     // Only occurs inside unevaluated constants.
     throw new UnsupportedError("Instance creation");
   }
 
   @override
-  JS.Expression visitIsExpression(IsExpression node) {
+  js_ast.Expression visitIsExpression(IsExpression node) {
     return _emitIsExpression(node.operand, node.type);
   }
 
-  JS.Expression _emitIsExpression(Expression operand, DartType type) {
+  js_ast.Expression _emitIsExpression(Expression operand, DartType type) {
     // Generate `is` as `dart.is` or `typeof` depending on the RHS type.
     var lhs = _visitExpression(operand);
     var typeofName = _typeRep.typeFor(type).primitiveTypeOf;
@@ -4917,7 +4948,7 @@
   }
 
   @override
-  JS.Expression visitAsExpression(AsExpression node) {
+  js_ast.Expression visitAsExpression(AsExpression node) {
     Expression fromExpr = node.operand;
     var to = node.type;
     var jsFrom = _visitExpression(fromExpr);
@@ -4961,7 +4992,7 @@
     return _emitCast(jsFrom, to, implicit: isTypeError);
   }
 
-  JS.Expression _emitCast(JS.Expression expr, DartType type,
+  js_ast.Expression _emitCast(js_ast.Expression expr, DartType type,
       {bool implicit = true}) {
     if (types.isTop(type)) return expr;
 
@@ -4970,14 +5001,14 @@
   }
 
   @override
-  JS.Expression visitSymbolLiteral(SymbolLiteral node) =>
+  js_ast.Expression visitSymbolLiteral(SymbolLiteral node) =>
       emitDartSymbol(node.value);
 
   @override
-  JS.Expression visitTypeLiteral(TypeLiteral node) =>
+  js_ast.Expression visitTypeLiteral(TypeLiteral node) =>
       _emitTypeLiteral(node.type);
 
-  JS.Expression _emitTypeLiteral(DartType type) {
+  js_ast.Expression _emitTypeLiteral(DartType type) {
     var typeRep = _emitType(type);
     // If the type is a type literal expression in Dart code, wrap the raw
     // runtime type in a "Type" instance.
@@ -4985,19 +5016,19 @@
   }
 
   @override
-  JS.Expression visitThisExpression(ThisExpression node) => JS.This();
+  js_ast.Expression visitThisExpression(ThisExpression node) => js_ast.This();
 
   @override
-  JS.Expression visitRethrow(Rethrow node) {
+  js_ast.Expression visitRethrow(Rethrow node) {
     return runtimeCall('rethrow(#)', [_emitVariableRef(_rethrowParameter)]);
   }
 
   @override
-  JS.Expression visitThrow(Throw node) =>
+  js_ast.Expression visitThrow(Throw node) =>
       runtimeCall('throw(#)', [_visitExpression(node.expression)]);
 
   @override
-  JS.Expression visitListLiteral(ListLiteral node) {
+  js_ast.Expression visitListLiteral(ListLiteral node) {
     var elementType = node.typeArgument;
     var elements = _visitExpressionList(node.expressions);
     // TODO(markzipan): remove const check when we use front-end const eval
@@ -5007,8 +5038,9 @@
     return _emitConstList(elementType, elements);
   }
 
-  JS.Expression _emitList(DartType itemType, List<JS.Expression> items) {
-    var list = JS.ArrayInitializer(items);
+  js_ast.Expression _emitList(
+      DartType itemType, List<js_ast.Expression> items) {
+    var list = js_ast.ArrayInitializer(items);
 
     // TODO(jmesserly): analyzer will usually infer `List<Object>` because
     // that is the least upper bound of the element types. So we rarely
@@ -5020,8 +5052,8 @@
     return js.call('#.of(#)', [_emitType(arrayType), list]);
   }
 
-  JS.Expression _emitConstList(
-      DartType elementType, List<JS.Expression> elements) {
+  js_ast.Expression _emitConstList(
+      DartType elementType, List<js_ast.Expression> elements) {
     // dart.constList helper internally depends on _interceptors.JSArray.
     _declareBeforeUse(_jsArrayClass);
     return cacheConst(
@@ -5029,7 +5061,7 @@
   }
 
   @override
-  JS.Expression visitSetLiteral(SetLiteral node) {
+  js_ast.Expression visitSetLiteral(SetLiteral node) {
     // TODO(markzipan): remove const check when we use front-end const eval
     if (!node.isConst) {
       var setType = visitInterfaceType(
@@ -5044,14 +5076,14 @@
         node.typeArgument, _visitExpressionList(node.expressions));
   }
 
-  JS.Expression _emitConstSet(
-      DartType elementType, List<JS.Expression> elements) {
+  js_ast.Expression _emitConstSet(
+      DartType elementType, List<js_ast.Expression> elements) {
     return cacheConst(
         runtimeCall('constSet(#, [#])', [_emitType(elementType), elements]));
   }
 
   @override
-  JS.Expression visitMapLiteral(MapLiteral node) {
+  js_ast.Expression visitMapLiteral(MapLiteral node) {
     var entries = [
       for (var e in node.entries) ...[
         _visitExpression(e.key),
@@ -5071,71 +5103,72 @@
     return _emitConstMap(node.keyType, node.valueType, entries);
   }
 
-  JS.Expression _emitConstMap(
-      DartType keyType, DartType valueType, List<JS.Expression> entries) {
+  js_ast.Expression _emitConstMap(
+      DartType keyType, DartType valueType, List<js_ast.Expression> entries) {
     return cacheConst(runtimeCall('constMap(#, #, [#])',
         [_emitType(keyType), _emitType(valueType), entries]));
   }
 
   @override
-  JS.Expression visitAwaitExpression(AwaitExpression node) =>
-      JS.Yield(_visitExpression(node.operand));
+  js_ast.Expression visitAwaitExpression(AwaitExpression node) =>
+      js_ast.Yield(_visitExpression(node.operand));
 
   @override
-  JS.Expression visitFunctionExpression(FunctionExpression node) {
+  js_ast.Expression visitFunctionExpression(FunctionExpression node) {
     var fn = _emitArrowFunction(node);
     if (!_reifyFunctionType(node.function)) return fn;
     return _emitFunctionTagged(fn, node.getStaticType(types) as FunctionType);
   }
 
-  JS.ArrowFun _emitArrowFunction(FunctionExpression node) {
-    JS.Fun f = _emitFunction(node.function, null);
-    JS.Node body = f.body;
+  js_ast.ArrowFun _emitArrowFunction(FunctionExpression node) {
+    js_ast.Fun f = _emitFunction(node.function, null);
+    js_ast.Node body = f.body;
 
     // Simplify `=> { return e; }` to `=> e`
-    if (body is JS.Block) {
-      var block = body as JS.Block;
+    if (body is js_ast.Block) {
+      var block = body as js_ast.Block;
       if (block.statements.length == 1) {
-        JS.Statement s = block.statements[0];
-        if (s is JS.Block) {
-          block = s as JS.Block;
+        js_ast.Statement s = block.statements[0];
+        if (s is js_ast.Block) {
+          block = s as js_ast.Block;
           s = block.statements.length == 1 ? block.statements[0] : null;
         }
-        if (s is JS.Return && s.value != null) body = s.value;
+        if (s is js_ast.Return && s.value != null) body = s.value;
       }
     }
 
     // Convert `function(...) { ... }` to `(...) => ...`
     // This is for readability, but it also ensures correct `this` binding.
-    return JS.ArrowFun(f.params, body);
+    return js_ast.ArrowFun(f.params, body);
   }
 
   @override
-  JS.Expression visitStringLiteral(StringLiteral node) =>
+  js_ast.Expression visitStringLiteral(StringLiteral node) =>
       js.escapedString(node.value, '"');
 
   @override
-  JS.Expression visitIntLiteral(IntLiteral node) => js.uint64(node.value);
+  js_ast.Expression visitIntLiteral(IntLiteral node) => js.uint64(node.value);
 
   @override
-  JS.Expression visitDoubleLiteral(DoubleLiteral node) => js.number(node.value);
+  js_ast.Expression visitDoubleLiteral(DoubleLiteral node) =>
+      js.number(node.value);
 
   @override
-  JS.Expression visitBoolLiteral(BoolLiteral node) =>
-      JS.LiteralBool(node.value);
+  js_ast.Expression visitBoolLiteral(BoolLiteral node) =>
+      js_ast.LiteralBool(node.value);
 
   @override
-  JS.Expression visitNullLiteral(NullLiteral node) => JS.LiteralNull();
+  js_ast.Expression visitNullLiteral(NullLiteral node) => js_ast.LiteralNull();
 
   @override
-  JS.Expression visitLet(Let node) {
+  js_ast.Expression visitLet(Let node) {
     var v = node.variable;
     var init = _visitExpression(v.initializer);
     var body = _visitExpression(node.body);
     var temp = _tempVariables.remove(v);
     if (temp != null) {
       if (_letVariables != null) {
-        init = JS.Assignment(temp, init);
+        init = js_ast.Assignment(temp, init);
         _letVariables.add(temp);
       } else {
         // TODO(jmesserly): make sure this doesn't happen on any performance
@@ -5143,37 +5176,37 @@
         //
         // Annotations on a top-level, non-lazy function type should be the only
         // remaining use.
-        return JS.Call(JS.ArrowFun([temp], body), [init]);
+        return js_ast.Call(js_ast.ArrowFun([temp], body), [init]);
       }
     }
-    return JS.Binary(',', init, body);
+    return js_ast.Binary(',', init, body);
   }
 
   @override
-  JS.Expression visitBlockExpression(BlockExpression node) {
+  js_ast.Expression visitBlockExpression(BlockExpression node) {
     var jsExpr = _visitExpression(node.value);
     var jsStmts = [
       for (var s in node.body.statements) _visitStatement(s),
-      JS.Return(jsExpr),
+      js_ast.Return(jsExpr),
     ];
-    var jsBlock = JS.Block(jsStmts);
+    var jsBlock = js_ast.Block(jsStmts);
     // BlockExpressions with async operations must be constructed
     // with a generator instead of a lambda.
     var finder = YieldFinder();
     jsBlock.accept(finder);
     if (finder.hasYield) {
-      var genFn = JS.Fun([], jsBlock, isGenerator: true);
+      var genFn = js_ast.Fun([], jsBlock, isGenerator: true);
       var asyncLibrary = emitLibraryName(coreTypes.asyncLibrary);
       var returnType = _emitType(node.getStaticType(types));
       var asyncCall =
           js.call('#.async(#, #)', [asyncLibrary, returnType, genFn]);
-      return JS.Yield(asyncCall);
+      return js_ast.Yield(asyncCall);
     }
-    return JS.Call(JS.ArrowFun([], jsBlock), []);
+    return js_ast.Call(js_ast.ArrowFun([], jsBlock), []);
   }
 
   @override
-  JS.Expression visitInstantiation(Instantiation node) {
+  js_ast.Expression visitInstantiation(Instantiation node) {
     return runtimeCall('gbind(#, #)', [
       _visitExpression(node.expression),
       node.typeArguments.map(_emitType).toList()
@@ -5181,7 +5214,7 @@
   }
 
   @override
-  JS.Expression visitLoadLibrary(LoadLibrary node) =>
+  js_ast.Expression visitLoadLibrary(LoadLibrary node) =>
       runtimeCall('loadLibrary()');
 
   // TODO(jmesserly): DDC loads all libraries eagerly.
@@ -5189,7 +5222,7 @@
   // https://github.com/dart-lang/sdk/issues/27776
   // https://github.com/dart-lang/sdk/issues/27777
   @override
-  JS.Expression visitCheckLibraryIsLoaded(CheckLibraryIsLoaded node) =>
+  js_ast.Expression visitCheckLibraryIsLoaded(CheckLibraryIsLoaded node) =>
       js.boolean(true);
 
   bool _reifyFunctionType(FunctionNode f) {
@@ -5236,16 +5269,18 @@
         findAnnotation(node, test), 'name') as String;
   }
 
-  JS.Expression visitConstant(Constant node) =>
-      node.accept(this) as JS.Expression;
+  js_ast.Expression visitConstant(Constant node) =>
+      node.accept(this) as js_ast.Expression;
   @override
-  JS.Expression visitNullConstant(NullConstant node) => JS.LiteralNull();
+  js_ast.Expression visitNullConstant(NullConstant node) =>
+      js_ast.LiteralNull();
   @override
-  JS.Expression visitBoolConstant(BoolConstant node) => js.boolean(node.value);
+  js_ast.Expression visitBoolConstant(BoolConstant node) =>
+      js.boolean(node.value);
   @override
-  JS.Expression visitIntConstant(IntConstant node) => js.number(node.value);
+  js_ast.Expression visitIntConstant(IntConstant node) => js.number(node.value);
   @override
-  JS.Expression visitDoubleConstant(DoubleConstant node) {
+  js_ast.Expression visitDoubleConstant(DoubleConstant node) {
     var value = node.value;
 
     // Emit the constant as an integer, if possible.
@@ -5263,20 +5298,20 @@
   }
 
   @override
-  JS.Expression visitStringConstant(StringConstant node) =>
+  js_ast.Expression visitStringConstant(StringConstant node) =>
       js.escapedString(node.value, '"');
 
   // DDC does not currently use the non-primivite constant nodes; rather these
   // are emitted via their normal expression nodes.
   @override
-  JS.Expression defaultConstant(Constant node) => _emitInvalidNode(node);
+  js_ast.Expression defaultConstant(Constant node) => _emitInvalidNode(node);
 
   @override
-  JS.Expression visitSymbolConstant(SymbolConstant node) =>
+  js_ast.Expression visitSymbolConstant(SymbolConstant node) =>
       emitDartSymbol(node.name);
 
   @override
-  JS.Expression visitMapConstant(MapConstant node) {
+  js_ast.Expression visitMapConstant(MapConstant node) {
     var entries = [
       for (var e in node.entries) ...[
         visitConstant(e.key),
@@ -5287,42 +5322,42 @@
   }
 
   @override
-  JS.Expression visitListConstant(ListConstant node) => _emitConstList(
+  js_ast.Expression visitListConstant(ListConstant node) => _emitConstList(
       node.typeArgument, node.entries.map(visitConstant).toList());
 
   @override
-  JS.Expression visitSetConstant(SetConstant node) => _emitConstSet(
+  js_ast.Expression visitSetConstant(SetConstant node) => _emitConstSet(
       node.typeArgument, node.entries.map(visitConstant).toList());
 
   @override
-  JS.Expression visitInstanceConstant(InstanceConstant node) {
+  js_ast.Expression visitInstanceConstant(InstanceConstant node) {
     entryToProperty(MapEntry<Reference, Constant> entry) {
-      var constant = entry.value.accept(this) as JS.Expression;
+      var constant = entry.value.accept(this) as js_ast.Expression;
       var member = entry.key.asField;
-      return JS.Property(
+      return js_ast.Property(
           _emitMemberName(member.name.name, member: member), constant);
     }
 
     var type = visitInterfaceType(node.getType(types) as InterfaceType);
     var prototype = js.call("#.prototype", [type]);
     var properties = [
-      JS.Property(propertyName("__proto__"), prototype),
+      js_ast.Property(propertyName("__proto__"), prototype),
       for (var e in node.fieldValues.entries) entryToProperty(e),
     ];
     return canonicalizeConstObject(
-        JS.ObjectInitializer(properties, multiline: true));
+        js_ast.ObjectInitializer(properties, multiline: true));
   }
 
   @override
-  JS.Expression visitTearOffConstant(TearOffConstant node) =>
+  js_ast.Expression visitTearOffConstant(TearOffConstant node) =>
       _emitStaticGet(node.procedure);
 
   @override
-  JS.Expression visitTypeLiteralConstant(TypeLiteralConstant node) =>
+  js_ast.Expression visitTypeLiteralConstant(TypeLiteralConstant node) =>
       _emitTypeLiteral(node.type);
 
   @override
-  JS.Expression visitPartialInstantiationConstant(
+  js_ast.Expression visitPartialInstantiationConstant(
           PartialInstantiationConstant node) =>
       runtimeCall('gbind(#, #)', [
         visitConstant(node.tearOffConstant),
@@ -5330,7 +5365,7 @@
       ]);
 
   @override
-  JS.Expression visitUnevaluatedConstant(UnevaluatedConstant node) =>
+  js_ast.Expression visitUnevaluatedConstant(UnevaluatedConstant node) =>
       _visitExpression(node.expression);
 }
 
@@ -5383,7 +5418,7 @@
 
 class SwitchLabelState {
   String label;
-  JS.Identifier variable;
+  js_ast.Identifier variable;
 
   SwitchLabelState(this.label, this.variable);
 }
diff --git a/pkg/dev_compiler/lib/src/kernel/property_model.dart b/pkg/dev_compiler/lib/src/kernel/property_model.dart
index df0444b..7c5bcee 100644
--- a/pkg/dev_compiler/lib/src/kernel/property_model.dart
+++ b/pkg/dev_compiler/lib/src/kernel/property_model.dart
@@ -7,8 +7,8 @@
 import 'package:kernel/core_types.dart';
 import 'package:kernel/kernel.dart';
 import 'package:kernel/type_environment.dart';
-import '../compiler/js_names.dart' as JS;
-import '../js_ast/js_ast.dart' as JS;
+
+import '../compiler/js_names.dart' as js_ast;
 import 'kernel_helpers.dart';
 import 'native_types.dart';
 
@@ -183,7 +183,7 @@
   /// pair in JavaScript.
   ///
   /// The value property stores the symbol used for the field's storage slot.
-  final virtualFields = <Field, JS.TemporaryId>{};
+  final virtualFields = <Field, js_ast.TemporaryId>{};
 
   /// The set of inherited getters, used because JS getters/setters are paired,
   /// so if we're generating a setter we may need to emit a getter that calls
@@ -246,7 +246,7 @@
           fieldModel.isVirtual(field) ||
           field.isCovariant ||
           field.isGenericCovariantImpl) {
-        virtualFields[field] = JS.TemporaryId(name);
+        virtualFields[field] = js_ast.TemporaryId(name);
       }
     }
   }
diff --git a/pkg/dev_compiler/lib/src/kernel/type_table.dart b/pkg/dev_compiler/lib/src/kernel/type_table.dart
index 7dd63c9..076075c 100644
--- a/pkg/dev_compiler/lib/src/kernel/type_table.dart
+++ b/pkg/dev_compiler/lib/src/kernel/type_table.dart
@@ -4,9 +4,9 @@
 
 import 'package:kernel/kernel.dart';
 
-import '../js_ast/js_ast.dart' as JS;
+import '../compiler/js_names.dart' as js_ast;
+import '../js_ast/js_ast.dart' as js_ast;
 import '../js_ast/js_ast.dart' show js;
-import '../compiler/js_names.dart' as JS;
 
 Set<TypeParameter> freeTypeParameters(DartType t) {
   var result = Set<TypeParameter>();
@@ -37,10 +37,10 @@
   // Use a LinkedHashMap to maintain key insertion order so the generated code
   // is stable under slight perturbation.  (If this is not good enough we could
   // sort by name to canonicalize order.)
-  final _names = <DartType, JS.TemporaryId>{};
+  final _names = <DartType, js_ast.TemporaryId>{};
   Iterable<DartType> get keys => _names.keys.toList();
 
-  JS.Statement _dischargeType(DartType type) {
+  js_ast.Statement _dischargeType(DartType type) {
     var name = _names.remove(type);
     if (name != null) {
       return js.statement('let #;', [name]);
@@ -51,8 +51,8 @@
   /// Emit a list of statements declaring the cache variables for
   /// types tracked by this table.  If [typeFilter] is given,
   /// only emit the types listed in the filter.
-  List<JS.Statement> discharge([Iterable<DartType> typeFilter]) {
-    var decls = <JS.Statement>[];
+  List<js_ast.Statement> discharge([Iterable<DartType> typeFilter]) {
+    var decls = <js_ast.Statement>[];
     var types = typeFilter ?? keys;
     for (var t in types) {
       var stmt = _dischargeType(t);
@@ -102,25 +102,25 @@
 
   /// Heuristically choose a good name for the cache and generator
   /// variables.
-  JS.TemporaryId chooseTypeName(DartType type) {
-    return JS.TemporaryId(_typeString(type));
+  js_ast.TemporaryId chooseTypeName(DartType type) {
+    return js_ast.TemporaryId(_typeString(type));
   }
 }
 
 /// _GeneratorTable tracks types which have been
 /// named and hoisted.
 class _GeneratorTable extends _CacheTable {
-  final _defs = <DartType, JS.Expression>{};
+  final _defs = <DartType, js_ast.Expression>{};
 
-  final JS.Identifier _runtimeModule;
+  final js_ast.Identifier _runtimeModule;
 
   _GeneratorTable(this._runtimeModule);
 
   @override
-  JS.Statement _dischargeType(DartType t) {
+  js_ast.Statement _dischargeType(DartType t) {
     var name = _names.remove(t);
     if (name != null) {
-      JS.Expression init = _defs.remove(t);
+      js_ast.Expression init = _defs.remove(t);
       assert(init != null);
       return js.statement('let # = () => ((# = #.constFn(#))());',
           [name, name, _runtimeModule, init]);
@@ -131,7 +131,7 @@
   /// If [type] does not already have a generator name chosen for it,
   /// assign it one, using [typeRep] as the initializer for it.
   /// Emit the generator name.
-  JS.TemporaryId _nameType(DartType type, JS.Expression typeRep) {
+  js_ast.TemporaryId _nameType(DartType type, js_ast.Expression typeRep) {
     var temp = _names[type];
     if (temp == null) {
       _names[type] = temp = chooseTypeName(type);
@@ -151,12 +151,12 @@
   /// parameter.
   final _scopeDependencies = <TypeParameter, List<DartType>>{};
 
-  TypeTable(JS.Identifier runtime) : _generators = _GeneratorTable(runtime);
+  TypeTable(js_ast.Identifier runtime) : _generators = _GeneratorTable(runtime);
 
   /// Emit a list of statements declaring the cache variables and generator
   /// definitions tracked by the table.  If [formals] is present, only
   /// emit the definitions which depend on the formals.
-  List<JS.Statement> discharge([List<TypeParameter> formals]) {
+  List<js_ast.Statement> discharge([List<TypeParameter> formals]) {
     var filter = formals?.expand((p) => _scopeDependencies[p] ?? <DartType>[]);
     var stmts = _generators.discharge(filter);
     formals?.forEach(_scopeDependencies.remove);
@@ -186,7 +186,7 @@
   /// Given a type [type], and a JS expression [typeRep] which implements it,
   /// add the type and its representation to the table, returning an
   /// expression which implements the type (but which caches the value).
-  JS.Expression nameType(DartType type, JS.Expression typeRep) {
+  js_ast.Expression nameType(DartType type, js_ast.Expression typeRep) {
     if (!_generators.isNamed(type) && recordScopeDependencies(type)) {
       return typeRep;
     }
@@ -200,10 +200,11 @@
   /// should be a function that is invoked to compute the type, rather than the
   /// type itself. This allows better integration with `lazyFn`, avoiding an
   /// extra level of indirection.
-  JS.Expression nameFunctionType(FunctionType type, JS.Expression typeRep,
+  js_ast.Expression nameFunctionType(
+      FunctionType type, js_ast.Expression typeRep,
       {bool lazy = false}) {
     if (!_generators.isNamed(type) && recordScopeDependencies(type)) {
-      return lazy ? JS.ArrowFun([], typeRep) : typeRep;
+      return lazy ? js_ast.ArrowFun([], typeRep) : typeRep;
     }
     var name = _generators._nameType(type, typeRep);
     return lazy ? name : js.call('#()', [name]);