[cfe] Initial support for view methods

TEST=pkg/front_end/testcases/views/procedures.dart

Change-Id: I62c26183d8160a3841b74381a256d0a4b5bb9365
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/272624
Reviewed-by: Alexander Markov <alexmarkov@google.com>
Reviewed-by: Jens Johansen <jensj@google.com>
Commit-Queue: Johnni Winther <johnniwinther@google.com>
diff --git a/pkg/front_end/lib/src/fasta/builder/builder.dart b/pkg/front_end/lib/src/fasta/builder/builder.dart
index aea43f9..c17be45 100644
--- a/pkg/front_end/lib/src/fasta/builder/builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/builder.dart
@@ -194,6 +194,29 @@
   ///
   bool get isExtensionInstanceMember;
 
+  /// Returns `true` if this builder is an instance member of an extension
+  /// declaration.
+  ///
+  /// For instance `method3a` in:
+  ///
+  ///     class A {
+  ///       A.constructor();     // Not a view instance member.
+  ///       method1a() {}        // Not a view instance member.
+  ///       static method1b() {} // Not a view instance member.
+  ///     }
+  ///     mixin B {
+  ///       method2a() {}        // Not a view instance member.
+  ///       static method2b() {} // Not a view instance member.
+  ///     }
+  ///     view C {
+  ///       final A it;
+  ///       A(this.is);          // Not a view instance member.
+  ///       method3a() {}
+  ///       static method3b() {} // Not a view instance member.
+  ///     }
+  ///
+  bool get isViewInstanceMember;
+
   bool get isLocal;
 
   bool get isPatch;
@@ -277,6 +300,9 @@
   bool get isExtensionInstanceMember => false;
 
   @override
+  bool get isViewInstanceMember => false;
+
+  @override
   bool get isLocal => false;
 
   @override
diff --git a/pkg/front_end/lib/src/fasta/source/name_scheme.dart b/pkg/front_end/lib/src/fasta/source/name_scheme.dart
index 69a5e27..2ef2d13 100644
--- a/pkg/front_end/lib/src/fasta/source/name_scheme.dart
+++ b/pkg/front_end/lib/src/fasta/source/name_scheme.dart
@@ -32,6 +32,8 @@
 
   bool get isExtensionMember => containerType == ContainerType.Extension;
 
+  bool get isViewMember => containerType == ContainerType.View;
+
   MemberName getFieldMemberName(FieldNameType fieldNameType, String name,
       {required bool isSynthesized}) {
     bool hasSynthesizedName;
@@ -118,31 +120,34 @@
       required bool isStatic,
       required ProcedureKind kind,
       required String name}) {
-    if (containerType == ContainerType.Extension) {
-      String extensionName = containerName!.name;
-      String kindInfix = '';
-      if (!isStatic) {
-        // Instance getter and setter are converted to methods so we use an
-        // infix to make their names unique.
-        switch (kind) {
-          case ProcedureKind.Getter:
-            kindInfix = 'get#';
-            break;
-          case ProcedureKind.Setter:
-            kindInfix = 'set#';
-            break;
-          case ProcedureKind.Method:
-          case ProcedureKind.Operator:
-            kindInfix = '';
-            break;
-          case ProcedureKind.Factory:
-            throw new UnsupportedError(
-                'Unexpected extension method kind ${kind}');
+    switch (containerType) {
+      case ContainerType.Extension:
+      case ContainerType.View:
+        String extensionName = containerName!.name;
+        String kindInfix = '';
+        if (!isStatic) {
+          // Instance getter and setter are converted to methods so we use an
+          // infix to make their names unique.
+          switch (kind) {
+            case ProcedureKind.Getter:
+              kindInfix = 'get#';
+              break;
+            case ProcedureKind.Setter:
+              kindInfix = 'set#';
+              break;
+            case ProcedureKind.Method:
+            case ProcedureKind.Operator:
+              kindInfix = '';
+              break;
+            case ProcedureKind.Factory:
+              throw new UnsupportedError(
+                  'Unexpected extension method kind ${kind}');
+          }
         }
-      }
-      return '${extensionName}|${kindInfix}${name}';
-    } else {
-      return name;
+        return '${extensionName}|${kindInfix}${name}';
+      case ContainerType.Library:
+      case ContainerType.Class:
+        return name;
     }
   }
 
diff --git a/pkg/front_end/lib/src/fasta/source/source_enum_builder.dart b/pkg/front_end/lib/src/fasta/source/source_enum_builder.dart
index a8f9bff..1623bf5 100644
--- a/pkg/front_end/lib/src/fasta/source/source_enum_builder.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_enum_builder.dart
@@ -390,8 +390,6 @@
             containerName: new ClassName(name),
             containerType: ContainerType.Class,
             libraryName: new LibraryName(coreLibrary.library.reference)),
-        isExtensionMember: false,
-        isInstanceMember: true,
         isSynthetic: true);
     members["_enumToString"] = toStringBuilder;
     String className = name;
diff --git a/pkg/front_end/lib/src/fasta/source/source_extension_builder.dart b/pkg/front_end/lib/src/fasta/source/source_extension_builder.dart
index 059e1cc..12bbf68 100644
--- a/pkg/front_end/lib/src/fasta/source/source_extension_builder.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_extension_builder.dart
@@ -122,6 +122,12 @@
       case BuiltMemberKind.RedirectingFactory:
       case BuiltMemberKind.Field:
       case BuiltMemberKind.Method:
+      case BuiltMemberKind.ViewMethod:
+      case BuiltMemberKind.ViewGetter:
+      case BuiltMemberKind.ViewSetter:
+      case BuiltMemberKind.ViewOperator:
+      case BuiltMemberKind.ViewTearOff:
+      case BuiltMemberKind.ViewFactory:
         unhandled("${member.runtimeType}:${memberKind}", "buildMembers",
             memberBuilder.charOffset, memberBuilder.fileUri);
       case BuiltMemberKind.ExtensionField:
diff --git a/pkg/front_end/lib/src/fasta/source/source_library_builder.dart b/pkg/front_end/lib/src/fasta/source/source_library_builder.dart
index 89f6a7a..b97b71c 100644
--- a/pkg/front_end/lib/src/fasta/source/source_library_builder.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_library_builder.dart
@@ -2859,8 +2859,6 @@
         tearOffReference,
         asyncModifier,
         nameScheme,
-        isExtensionMember: isExtensionMember,
-        isInstanceMember: isInstanceMember,
         nativeMethodName: nativeMethodName);
     checkTypeVariables(typeVariables, procedureBuilder);
     addBuilder(name, procedureBuilder, charOffset,
diff --git a/pkg/front_end/lib/src/fasta/source/source_loader.dart b/pkg/front_end/lib/src/fasta/source/source_loader.dart
index 26c8770..3f72911 100644
--- a/pkg/front_end/lib/src/fasta/source/source_loader.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_loader.dart
@@ -1325,9 +1325,7 @@
             containerName: null,
             containerType: ContainerType.Library,
             isInstanceMember: false,
-            libraryName: libraryBuilder.libraryName),
-        isInstanceMember: false,
-        isExtensionMember: false)
+            libraryName: libraryBuilder.libraryName))
       ..parent = parent;
     BodyBuilder listener = dietListener.createListener(
         builder, dietListener.memberScope,
diff --git a/pkg/front_end/lib/src/fasta/source/source_member_builder.dart b/pkg/front_end/lib/src/fasta/source/source_member_builder.dart
index 14adcf3..c87df4d 100644
--- a/pkg/front_end/lib/src/fasta/source/source_member_builder.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_member_builder.dart
@@ -178,6 +178,12 @@
   ExtensionSetter,
   ExtensionOperator,
   ExtensionTearOff,
+  ViewMethod,
+  ViewGetter,
+  ViewSetter,
+  ViewOperator,
+  ViewTearOff,
+  ViewFactory,
   LateIsSetField,
   LateGetter,
   LateSetter,
diff --git a/pkg/front_end/lib/src/fasta/source/source_procedure_builder.dart b/pkg/front_end/lib/src/fasta/source/source_procedure_builder.dart
index 2775428..3607b93 100644
--- a/pkg/front_end/lib/src/fasta/source/source_procedure_builder.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_procedure_builder.dart
@@ -7,7 +7,6 @@
 import 'package:kernel/type_environment.dart';
 
 import '../builder/builder.dart';
-import '../builder/extension_builder.dart';
 import '../builder/formal_parameter_builder.dart';
 import '../builder/member_builder.dart';
 import '../builder/metadata_builder.dart';
@@ -22,9 +21,12 @@
 import '../source/name_scheme.dart';
 import '../source/source_library_builder.dart' show SourceLibraryBuilder;
 import '../source/source_loader.dart' show SourceLoader;
+import 'source_builder_mixins.dart';
 import 'source_class_builder.dart';
+import 'source_extension_builder.dart';
 import 'source_function_builder.dart';
 import 'source_member_builder.dart';
+import 'source_view_builder.dart';
 
 class SourceProcedureBuilder extends SourceFunctionBuilderImpl
     implements ProcedureBuilder {
@@ -36,6 +38,9 @@
   final bool isExtensionInstanceMember;
 
   @override
+  final bool isViewInstanceMember;
+
+  @override
   final TypeBuilder returnType;
 
   late Procedure _procedure;
@@ -85,21 +90,20 @@
       this._tearOffReference,
       AsyncMarker asyncModifier,
       NameScheme nameScheme,
-      {required bool isExtensionMember,
-      required bool isInstanceMember,
-      String? nativeMethodName,
+      {String? nativeMethodName,
       bool isSynthetic = false})
-      // ignore: unnecessary_null_comparison
-      : assert(isExtensionMember != null),
-        // ignore: unnecessary_null_comparison
-        assert(isInstanceMember != null),
-        assert(kind != ProcedureKind.Factory),
-        this.isExtensionInstanceMember = isInstanceMember && isExtensionMember,
+      : assert(kind != ProcedureKind.Factory),
+        this.isExtensionInstanceMember =
+            nameScheme.isInstanceMember && nameScheme.isExtensionMember,
+        this.isViewInstanceMember =
+            nameScheme.isInstanceMember && nameScheme.isViewMember,
         super(metadata, modifiers, name, typeVariables, formals, libraryBuilder,
             charOffset, nativeMethodName) {
     _procedure = new Procedure(
         dummyName,
-        isExtensionInstanceMember ? ProcedureKind.Method : kind,
+        isExtensionInstanceMember || isViewInstanceMember
+            ? ProcedureKind.Method
+            : kind,
         new FunctionNode(null),
         fileUri: libraryBuilder.fileUri,
         reference: procedureReference,
@@ -110,7 +114,10 @@
       ..isNonNullableByDefault = libraryBuilder.isNonNullableByDefault;
     nameScheme.getProcedureMemberName(kind, name).attachMember(_procedure);
     this.asyncModifier = asyncModifier;
-    if (isExtensionMember && isInstanceMember && kind == ProcedureKind.Method) {
+    if ((isExtensionInstanceMember
+        // TODO(johnniwinther): Support view tear offs.
+        /* || isViewInstanceMember*/) &&
+        kind == ProcedureKind.Method) {
       _extensionTearOff = new Procedure(
           dummyName, ProcedureKind.Method, new FunctionNode(null),
           isStatic: true,
@@ -144,7 +151,11 @@
   }
 
   bool get isExtensionMethod {
-    return parent is ExtensionBuilder;
+    return parent is SourceExtensionBuilder;
+  }
+
+  bool get isViewMethod {
+    return parent is SourceViewBuilder;
   }
 
   @override
@@ -266,6 +277,27 @@
       if (extensionTearOff != null) {
         f(extensionTearOff!, BuiltMemberKind.ExtensionTearOff);
       }
+    } else if (isViewMethod) {
+      switch (kind) {
+        case ProcedureKind.Method:
+          f(_procedure, BuiltMemberKind.ViewMethod);
+          break;
+        case ProcedureKind.Getter:
+          f(_procedure, BuiltMemberKind.ViewGetter);
+          break;
+        case ProcedureKind.Setter:
+          f(_procedure, BuiltMemberKind.ViewSetter);
+          break;
+        case ProcedureKind.Operator:
+          f(_procedure, BuiltMemberKind.ViewOperator);
+          break;
+        case ProcedureKind.Factory:
+          f(_procedure, BuiltMemberKind.ViewFactory);
+          break;
+      }
+      if (extensionTearOff != null) {
+        f(extensionTearOff!, BuiltMemberKind.ViewTearOff);
+      }
     } else {
       f(member, BuiltMemberKind.Method);
     }
@@ -284,11 +316,18 @@
       if (isExtensionInstanceMember) {
         assert(_procedure.kind == ProcedureKind.Method);
       }
+    } else if (isViewMethod) {
+      _procedure.isViewMember = true;
+      _procedure.isStatic = true;
+      if (isViewInstanceMember) {
+        assert(_procedure.kind == ProcedureKind.Method);
+      }
     } else {
       _procedure.isStatic = isStatic;
     }
     if (extensionTearOff != null) {
-      _buildExtensionTearOff(libraryBuilder, parent as ExtensionBuilder);
+      _buildExtensionTearOff(
+          libraryBuilder, parent as SourceDeclarationBuilderMixin);
     }
   }
 
@@ -312,7 +351,7 @@
   ///     }
   ///
   void _buildExtensionTearOff(SourceLibraryBuilder sourceLibraryBuilder,
-      ExtensionBuilder extensionBuilder) {
+      SourceDeclarationBuilderMixin declarationBuilder) {
     assert(
         _extensionTearOff != null, "No extension tear off created for $this.");
 
@@ -322,7 +361,7 @@
     int fileEndOffset = _procedure.fileEndOffset;
 
     int extensionTypeParameterCount =
-        extensionBuilder.typeParameters?.length ?? 0;
+        declarationBuilder.typeParameters?.length ?? 0;
 
     List<TypeParameter> typeParameters = <TypeParameter>[];
 
diff --git a/pkg/front_end/lib/src/fasta/source/source_view_builder.dart b/pkg/front_end/lib/src/fasta/source/source_view_builder.dart
index c47d9a1..68b8bf1 100644
--- a/pkg/front_end/lib/src/fasta/source/source_view_builder.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_view_builder.dart
@@ -114,29 +114,37 @@
       case BuiltMemberKind.RedirectingFactory:
       case BuiltMemberKind.Field:
       case BuiltMemberKind.Method:
+      case BuiltMemberKind.ExtensionMethod:
+      case BuiltMemberKind.ExtensionGetter:
+      case BuiltMemberKind.ExtensionSetter:
+      case BuiltMemberKind.ExtensionOperator:
+      case BuiltMemberKind.ExtensionTearOff:
         unhandled("${member.runtimeType}:${memberKind}", "buildMembers",
             memberBuilder.charOffset, memberBuilder.fileUri);
       case BuiltMemberKind.ExtensionField:
       case BuiltMemberKind.LateIsSetField:
         kind = ViewMemberKind.Field;
         break;
-      case BuiltMemberKind.ExtensionMethod:
+      case BuiltMemberKind.ViewMethod:
         kind = ViewMemberKind.Method;
         break;
-      case BuiltMemberKind.ExtensionGetter:
+      case BuiltMemberKind.ViewGetter:
       case BuiltMemberKind.LateGetter:
         kind = ViewMemberKind.Getter;
         break;
-      case BuiltMemberKind.ExtensionSetter:
+      case BuiltMemberKind.ViewSetter:
       case BuiltMemberKind.LateSetter:
         kind = ViewMemberKind.Setter;
         break;
-      case BuiltMemberKind.ExtensionOperator:
+      case BuiltMemberKind.ViewOperator:
         kind = ViewMemberKind.Operator;
         break;
-      case BuiltMemberKind.ExtensionTearOff:
+      case BuiltMemberKind.ViewTearOff:
         kind = ViewMemberKind.TearOff;
         break;
+      case BuiltMemberKind.ViewFactory:
+        kind = ViewMemberKind.Factory;
+        break;
     }
     // ignore: unnecessary_null_comparison
     assert(kind != null);
diff --git a/pkg/front_end/testcases/textual_outline.status b/pkg/front_end/testcases/textual_outline.status
index b8cf805..4c76cf6 100644
--- a/pkg/front_end/testcases/textual_outline.status
+++ b/pkg/front_end/testcases/textual_outline.status
@@ -214,5 +214,6 @@
 variance/generic_covariance_sound_variance: FormatterCrash
 variance/mixin_type_parameter_modifier: FormatterCrash
 variance/unconstrained_inference: FormatterCrash
+views/procedures: FormatterCrash
 views/representation: FormatterCrash
 views/view_class_declaration: FormatterCrash
diff --git a/pkg/front_end/testcases/views/procedures.dart b/pkg/front_end/testcases/views/procedures.dart
new file mode 100644
index 0000000..5dd0042
--- /dev/null
+++ b/pkg/front_end/testcases/views/procedures.dart
@@ -0,0 +1,10 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+view class Class {
+  final int it;
+
+  void instanceMethod() {}
+  static void staticMethod() {}
+}
\ No newline at end of file
diff --git a/pkg/front_end/testcases/views/procedures.dart.strong.expect b/pkg/front_end/testcases/views/procedures.dart.strong.expect
new file mode 100644
index 0000000..74b1bb1
--- /dev/null
+++ b/pkg/front_end/testcases/views/procedures.dart.strong.expect
@@ -0,0 +1,10 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+view Class /* representationType = core::int */ {
+  method instanceMethod = self::Class|instanceMethod;
+  static method staticMethod = self::Class|staticMethod;
+}
+static method Class|instanceMethod() → void {}
+static method Class|staticMethod() → void {}
diff --git a/pkg/front_end/testcases/views/procedures.dart.strong.transformed.expect b/pkg/front_end/testcases/views/procedures.dart.strong.transformed.expect
new file mode 100644
index 0000000..74b1bb1
--- /dev/null
+++ b/pkg/front_end/testcases/views/procedures.dart.strong.transformed.expect
@@ -0,0 +1,10 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+view Class /* representationType = core::int */ {
+  method instanceMethod = self::Class|instanceMethod;
+  static method staticMethod = self::Class|staticMethod;
+}
+static method Class|instanceMethod() → void {}
+static method Class|staticMethod() → void {}
diff --git a/pkg/front_end/testcases/views/procedures.dart.textual_outline.expect b/pkg/front_end/testcases/views/procedures.dart.textual_outline.expect
new file mode 100644
index 0000000..dcde97c
--- /dev/null
+++ b/pkg/front_end/testcases/views/procedures.dart.textual_outline.expect
@@ -0,0 +1,6 @@
+view
+class Class {
+  final int it;
+  void instanceMethod() {}
+  static void staticMethod() {}
+}
diff --git a/pkg/front_end/testcases/views/procedures.dart.weak.expect b/pkg/front_end/testcases/views/procedures.dart.weak.expect
new file mode 100644
index 0000000..74b1bb1
--- /dev/null
+++ b/pkg/front_end/testcases/views/procedures.dart.weak.expect
@@ -0,0 +1,10 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+view Class /* representationType = core::int */ {
+  method instanceMethod = self::Class|instanceMethod;
+  static method staticMethod = self::Class|staticMethod;
+}
+static method Class|instanceMethod() → void {}
+static method Class|staticMethod() → void {}
diff --git a/pkg/front_end/testcases/views/procedures.dart.weak.modular.expect b/pkg/front_end/testcases/views/procedures.dart.weak.modular.expect
new file mode 100644
index 0000000..74b1bb1
--- /dev/null
+++ b/pkg/front_end/testcases/views/procedures.dart.weak.modular.expect
@@ -0,0 +1,10 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+view Class /* representationType = core::int */ {
+  method instanceMethod = self::Class|instanceMethod;
+  static method staticMethod = self::Class|staticMethod;
+}
+static method Class|instanceMethod() → void {}
+static method Class|staticMethod() → void {}
diff --git a/pkg/front_end/testcases/views/procedures.dart.weak.outline.expect b/pkg/front_end/testcases/views/procedures.dart.weak.outline.expect
new file mode 100644
index 0000000..ae30529
--- /dev/null
+++ b/pkg/front_end/testcases/views/procedures.dart.weak.outline.expect
@@ -0,0 +1,12 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+view Class /* representationType = core::int */ {
+  method instanceMethod = self::Class|instanceMethod;
+  static method staticMethod = self::Class|staticMethod;
+}
+static method Class|instanceMethod() → void
+  ;
+static method Class|staticMethod() → void
+  ;
diff --git a/pkg/front_end/testcases/views/procedures.dart.weak.transformed.expect b/pkg/front_end/testcases/views/procedures.dart.weak.transformed.expect
new file mode 100644
index 0000000..74b1bb1
--- /dev/null
+++ b/pkg/front_end/testcases/views/procedures.dart.weak.transformed.expect
@@ -0,0 +1,10 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+view Class /* representationType = core::int */ {
+  method instanceMethod = self::Class|instanceMethod;
+  static method staticMethod = self::Class|staticMethod;
+}
+static method Class|instanceMethod() → void {}
+static method Class|staticMethod() → void {}
diff --git a/pkg/kernel/binary.md b/pkg/kernel/binary.md
index 26cbd99..7048e7b 100644
--- a/pkg/kernel/binary.md
+++ b/pkg/kernel/binary.md
@@ -147,7 +147,7 @@
 
 type ComponentFile {
   UInt32 magic = 0x90ABCDEF;
-  UInt32 formatVersion = 89;
+  UInt32 formatVersion = 90;
   Byte[10] shortSdkHash;
   List<String> problemsAsJson; // Described in problems.md.
   Library[] libraries;
@@ -411,7 +411,7 @@
   UInt flags (isFinal, isConst, isStatic, isCovariantByDeclaration,
                 isCovariantByClass, isLate, isExtensionMember,
                 isNonNullableByDefault, isInternalImplementation,
-                isEnumElement);
+                isEnumElement, isViewMember);
   Name name;
   List<Expression> annotations;
   DartType type;
@@ -466,7 +466,8 @@
   Byte stubKind; // Index into the ProcedureStubKind enum above.
   UInt flags (isStatic, isAbstract, isExternal, isConst,
               isRedirectingFactory, isExtensionMember,
-              isNonNullableByDefault, isSynthetic, isInternalImplementation);
+              isNonNullableByDefault, isSynthetic, isInternalImplementation,
+              isViewMember);
   Name name;
   List<Expression> annotations;
   MemberReference stubTarget; // May be NullReference.
diff --git a/pkg/kernel/lib/ast.dart b/pkg/kernel/lib/ast.dart
index 5e2c078..88f0d4f 100644
--- a/pkg/kernel/lib/ast.dart
+++ b/pkg/kernel/lib/ast.dart
@@ -2239,6 +2239,21 @@
   ///
   bool get isExtensionMember;
 
+  /// If `true` this member is compiled from a member declared in a view class
+  /// declaration.
+  ///
+  /// For instance `field`, `method1` and `method2` in:
+  ///
+  ///     view class A {
+  ///       final B it;
+  ///       A(this.it);
+  ///       static var field;
+  ///       B method1() => this;
+  ///       static B method2() => new B();
+  ///     }
+  ///
+  bool get isViewMember;
+
   /// If `true` this member is defined in a library for which non-nullable by
   /// default is enabled.
   bool get isNonNullableByDefault;
@@ -2474,6 +2489,7 @@
   static const int FlagNonNullableByDefault = 1 << 7;
   static const int FlagInternalImplementation = 1 << 8;
   static const int FlagEnumElement = 1 << 9;
+  static const int FlagViewMember = 1 << 10;
 
   /// Whether the field is declared with the `covariant` keyword.
   bool get isCovariantByDeclaration => flags & FlagCovariant != 0;
@@ -2488,6 +2504,9 @@
   @override
   bool get isExtensionMember => flags & FlagExtensionMember != 0;
 
+  @override
+  bool get isViewMember => flags & FlagViewMember != 0;
+
   /// Indicates whether the implicit setter associated with this field needs to
   /// contain a runtime type check to deal with generic covariance.
   ///
@@ -2559,6 +2578,10 @@
     flags = value ? (flags | FlagEnumElement) : (flags & ~FlagEnumElement);
   }
 
+  void set isViewMember(bool value) {
+    flags = value ? (flags | FlagViewMember) : (flags & ~FlagViewMember);
+  }
+
   @override
   bool get isInstanceMember => !isStatic;
 
@@ -2736,6 +2759,9 @@
   bool get isExtensionMember => false;
 
   @override
+  bool get isViewMember => false;
+
+  @override
   bool get isNonNullableByDefault => flags & FlagNonNullableByDefault != 0;
 
   @override
@@ -2898,6 +2924,9 @@
   @override
   bool get isExtensionMember => false;
 
+  @override
+  bool get isViewMember => false;
+
   bool get isUnresolved => targetReference == null;
 
   @override
@@ -3313,6 +3342,7 @@
   static const int FlagSynthetic = 1 << 7;
   static const int FlagInternalImplementation = 1 << 8;
   static const int FlagIsAbstractFieldAccessor = 1 << 9;
+  static const int FlagViewMember = 1 << 10;
 
   bool get isStatic => flags & FlagStatic != 0;
 
@@ -3392,6 +3422,9 @@
   @override
   bool get isExtensionMember => flags & FlagExtensionMember != 0;
 
+  @override
+  bool get isViewMember => flags & FlagViewMember != 0;
+
   void set isStatic(bool value) {
     flags = value ? (flags | FlagStatic) : (flags & ~FlagStatic);
   }
@@ -3420,6 +3453,10 @@
         value ? (flags | FlagExtensionMember) : (flags & ~FlagExtensionMember);
   }
 
+  void set isViewMember(bool value) {
+    flags = value ? (flags | FlagViewMember) : (flags & ~FlagViewMember);
+  }
+
   void set isSynthetic(bool value) {
     flags = value ? (flags | FlagSynthetic) : (flags & ~FlagSynthetic);
   }
diff --git a/pkg/kernel/lib/binary/tag.dart b/pkg/kernel/lib/binary/tag.dart
index c3c01b5..8215fb6 100644
--- a/pkg/kernel/lib/binary/tag.dart
+++ b/pkg/kernel/lib/binary/tag.dart
@@ -195,7 +195,7 @@
   /// Internal version of kernel binary format.
   /// Bump it when making incompatible changes in kernel binaries.
   /// Keep in sync with runtime/vm/kernel_binary.h, pkg/kernel/binary.md.
-  static const int BinaryFormatVersion = 89;
+  static const int BinaryFormatVersion = 90;
 }
 
 abstract class ConstantTag {
diff --git a/runtime/vm/compiler/frontend/kernel_translation_helper.h b/runtime/vm/compiler/frontend/kernel_translation_helper.h
index a61bbe2..6eaa0fe 100644
--- a/runtime/vm/compiler/frontend/kernel_translation_helper.h
+++ b/runtime/vm/compiler/frontend/kernel_translation_helper.h
@@ -495,6 +495,7 @@
     kNonNullableByDefault = 1 << 7,
     kInternalImplementation = 1 << 8,
     kEnumElement = 1 << 9,
+    kViewMember = 1 << 10,
   };
 
   explicit FieldHelper(KernelReaderHelper* helper)
@@ -520,6 +521,7 @@
   }
   bool IsLate() const { return (flags_ & kIsLate) != 0; }
   bool IsExtensionMember() const { return (flags_ & kExtensionMember) != 0; }
+  bool IsViewMember() const { return (flags_ & kViewMember) != 0; }
 
   NameIndex canonical_name_field_;
   NameIndex canonical_name_getter_;
@@ -593,6 +595,8 @@
     kExtensionMember = 1 << 5,
     kSyntheticProcedure = 1 << 7,
     kInternalImplementation = 1 << 8,
+    kIsAbstractFieldAccessor = 1 << 9,
+    kViewMember = 1 << 10,
   };
 
   explicit ProcedureHelper(KernelReaderHelper* helper)
@@ -626,6 +630,7 @@
     return stub_kind_ == kNoSuchMethodForwarderStubKind;
   }
   bool IsExtensionMember() const { return (flags_ & kExtensionMember) != 0; }
+  bool IsViewMember() const { return (flags_ & kViewMember) != 0; }
   bool IsMemberSignature() const {
     return stub_kind_ == kMemberSignatureStubKind;
   }
diff --git a/runtime/vm/kernel_binary.h b/runtime/vm/kernel_binary.h
index bdcf1d4..c4a11808 100644
--- a/runtime/vm/kernel_binary.h
+++ b/runtime/vm/kernel_binary.h
@@ -18,7 +18,7 @@
 // package:kernel/binary.md.
 
 static const uint32_t kMagicProgramFile = 0x90ABCDEFu;
-static const uint32_t kSupportedKernelFormatVersion = 89;
+static const uint32_t kSupportedKernelFormatVersion = 90;
 
 // Keep in sync with package:kernel/lib/binary/tag.dart
 #define KERNEL_TAG_LIST(V)                                                     \