// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

library kernel.ast_from_binary;

import 'dart:developer';
import 'dart:convert';
import 'dart:typed_data';

import '../ast.dart';
import '../transformations/flags.dart';
import 'tag.dart';

class ParseError {
  final String? filename;
  final int byteIndex;
  final String message;
  final String path;

  ParseError(this.message,
      {required this.filename, required this.byteIndex, required this.path});

  @override
  String toString() => '$filename:$byteIndex: $message at $path';
}

class InvalidKernelVersionError {
  final String? filename;
  final int version;

  InvalidKernelVersionError(this.filename, this.version);

  @override
  String toString() {
    StringBuffer sb = new StringBuffer();
    sb.write('Unexpected Kernel Format Version ${version} '
        '(expected ${Tag.BinaryFormatVersion})');
    if (filename != null) {
      sb.write(' when reading $filename.');
    }
    return '$sb';
  }
}

class InvalidKernelSdkVersionError {
  final String version;

  InvalidKernelSdkVersionError(this.version);

  @override
  String toString() {
    return 'Unexpected Kernel SDK Version ${version} '
        '(expected ${expectedSdkHash}).';
  }
}

class CompilationModeError {
  final String message;

  CompilationModeError(this.message);

  @override
  String toString() => "CompilationModeError[$message]";
}

class _ComponentIndex {
  static const int numberOfFixedFields = 12;

  final int binaryOffsetForSourceTable;
  final int binaryOffsetForCanonicalNames;
  final int binaryOffsetForMetadataPayloads;
  final int binaryOffsetForMetadataMappings;
  final int binaryOffsetForStringTable;
  final int binaryOffsetForConstantTable;
  final int binaryOffsetForConstantTableIndex;
  final int binaryOffsetForStartOfComponentIndex;
  final int mainMethodReference;
  final NonNullableByDefaultCompiledMode compiledMode;
  final List<int> libraryOffsets;
  final int libraryCount;
  final int componentFileSizeInBytes;

  _ComponentIndex(
      {required this.binaryOffsetForSourceTable,
      required this.binaryOffsetForCanonicalNames,
      required this.binaryOffsetForMetadataPayloads,
      required this.binaryOffsetForMetadataMappings,
      required this.binaryOffsetForStringTable,
      required this.binaryOffsetForConstantTable,
      required this.binaryOffsetForConstantTableIndex,
      required this.binaryOffsetForStartOfComponentIndex,
      required this.mainMethodReference,
      required this.compiledMode,
      required this.libraryOffsets,
      required this.libraryCount,
      required this.componentFileSizeInBytes});
}

class SubComponentView {
  final List<Library> libraries;
  final int componentStartOffset;
  final int componentFileSize;

  SubComponentView(
      this.libraries, this.componentStartOffset, this.componentFileSize);
}

/// [StringInterner] allows Strings created from the binary to be shared with
/// other components.
///
/// The [StringInterner] is an optional parameter to [BinaryBuilder], so sharing
/// should not be required for correctness, and an implementation of
/// [StringInterner] method may be partial (sometimes not finding an existing
/// object) or trivial (returning the argument).
abstract class StringInterner {
  /// Returns a string with the same contents as [string].
  String internString(String string);
}

class BinaryBuilder {
  final List<VariableDeclaration> variableStack = <VariableDeclaration>[];
  final List<LabeledStatement> labelStack = <LabeledStatement>[];
  int labelStackBase = 0;
  int switchCaseStackBase = 0;
  final List<SwitchCase> switchCaseStack = <SwitchCase>[];
  final List<TypeParameter> typeParameterStack = <TypeParameter>[];
  final String? filename;
  final List<int> _bytes;
  int _byteOffset = 0;
  List<String> _stringTable = const [];
  List<Uri> _sourceUriTable = const [];
  List<Constant> _constantTable = const <Constant>[];
  late List<CanonicalName> _linkTable;
  int _transformerFlags = 0;
  Library? _currentLibrary;
  int _componentStartOffset = 0;
  NonNullableByDefaultCompiledMode? compilationMode;

  // If something goes wrong, this list should indicate what library,
  // class, and member was being built.
  List<String> debugPath = <String>[];

  final bool alwaysCreateNewNamedNodes;

  /// If binary contains metadata section with payloads referencing other nodes
  /// such Kernel binary can't be read lazily because metadata cross references
  /// will not be resolved correctly.
  bool _disableLazyReading = false;

  /// If binary contains metadata section with payloads referencing other nodes
  /// such Kernel binary can't be read lazily because metadata cross references
  /// will not be resolved correctly.
  bool _disableLazyClassReading = false;

  /// [stringInterner] (optional) may be used to allow components to share
  /// instances of [String] that have the same contents.
  final StringInterner? stringInterner;

  /// When creating lists that *might* be growable, use this boolean as the
  /// setting to pass to `growable` so the dill can be loaded in a more compact
  /// manner if the caller knows that the growability isn't needed.
  final bool useGrowableLists;

  /// Note that [disableLazyClassReading] is incompatible
  /// with checkCanonicalNames on readComponent.
  BinaryBuilder(this._bytes,
      {this.filename,
      bool disableLazyReading = false,
      bool disableLazyClassReading = false,
      bool? alwaysCreateNewNamedNodes,
      this.stringInterner,
      this.useGrowableLists = true})
      : _disableLazyReading = disableLazyReading,
        _disableLazyClassReading = disableLazyReading ||
            disableLazyClassReading ||
            // Disable lazy class reading when forcing the creation of new named
            // nodes as it is a logical "relink" to the new version (overwriting
            // the old one) - which doesn't play well with lazy loading class
            // content as old loaded references will then potentially still
            // point to the old content until the new class has been lazy
            // loaded.
            (alwaysCreateNewNamedNodes == true),
        this.alwaysCreateNewNamedNodes = alwaysCreateNewNamedNodes ?? false;

  Never fail(String message) {
    throw ParseError(message,
        byteIndex: _byteOffset, filename: filename, path: debugPath.join('::'));
  }

  int get byteOffset => _byteOffset;

  int readByte() => _bytes[_byteOffset++];

  int readUInt30() {
    int byte = readByte();
    if (byte & 0x80 == 0) {
      // 0xxxxxxx
      return byte;
    } else if (byte & 0x40 == 0) {
      // 10xxxxxx
      return ((byte & 0x3F) << 8) | readByte();
    } else {
      // 11xxxxxx
      return ((byte & 0x3F) << 24) |
          (readByte() << 16) |
          (readByte() << 8) |
          readByte();
    }
  }

  int readUint32() {
    return (readByte() << 24) |
        (readByte() << 16) |
        (readByte() << 8) |
        readByte();
  }

  final Float64List _doubleBuffer = new Float64List(1);
  Uint8List? _doubleBufferUint8;

  double readDouble() {
    Uint8List doubleBufferUint8 =
        _doubleBufferUint8 ??= _doubleBuffer.buffer.asUint8List();
    doubleBufferUint8[0] = readByte();
    doubleBufferUint8[1] = readByte();
    doubleBufferUint8[2] = readByte();
    doubleBufferUint8[3] = readByte();
    doubleBufferUint8[4] = readByte();
    doubleBufferUint8[5] = readByte();
    doubleBufferUint8[6] = readByte();
    doubleBufferUint8[7] = readByte();
    return _doubleBuffer[0];
  }

  Uint8List readBytes(int length) {
    Uint8List bytes = new Uint8List(length);
    bytes.setRange(0, bytes.length, _bytes, _byteOffset);
    _byteOffset += bytes.length;
    return bytes;
  }

  Uint8List readByteList() {
    return readBytes(readUInt30());
  }

  String readString() {
    return readStringEntry(readUInt30());
  }

  String readStringEntry(int numBytes) {
    String string = _readStringEntry(numBytes);
    if (stringInterner == null) return string;
    return stringInterner!.internString(string);
  }

  String _readStringEntry(int numBytes) {
    int start = _byteOffset;
    int end = start + numBytes;
    _byteOffset = end;
    for (int i = start; i < end; i++) {
      if (_bytes[i] > 127) {
        return _decodeWtf8(start, end);
      }
    }
    return new String.fromCharCodes(_bytes, start, end);
  }

  String _decodeWtf8(int start, int end) {
    // WTF-8 decoder that trusts its input, meaning that the correctness of
    // the code depends on the bytes from start to end being valid and
    // complete WTF-8. Instead of masking off the control bits from every
    // byte, it simply xor's the byte values together at their appropriate
    // bit shifts, and then xor's out all of the control bits at once.
    Uint16List charCodes = new Uint16List(end - start);
    int i = start;
    int j = 0;
    while (i < end) {
      int byte = _bytes[i++];
      if (byte < 0x80) {
        // ASCII.
        charCodes[j++] = byte;
      } else if (byte < 0xE0) {
        // Two-byte sequence (11-bit unicode value).
        int byte2 = _bytes[i++];
        int value = (byte << 6) ^ byte2 ^ 0x3080;
        assert(value >= 0x80 && value < 0x800);
        charCodes[j++] = value;
      } else if (byte < 0xF0) {
        // Three-byte sequence (16-bit unicode value).
        int byte2 = _bytes[i++];
        int byte3 = _bytes[i++];
        int value = (byte << 12) ^ (byte2 << 6) ^ byte3 ^ 0xE2080;
        assert(value >= 0x800 && value < 0x10000);
        charCodes[j++] = value;
      } else {
        // Four-byte sequence (non-BMP unicode value).
        int byte2 = _bytes[i++];
        int byte3 = _bytes[i++];
        int byte4 = _bytes[i++];
        int value =
            (byte << 18) ^ (byte2 << 12) ^ (byte3 << 6) ^ byte4 ^ 0x3C82080;
        assert(value >= 0x10000 && value < 0x110000);
        charCodes[j++] = 0xD7C0 + (value >> 10);
        charCodes[j++] = 0xDC00 + (value & 0x3FF);
      }
    }
    assert(i == end);
    return new String.fromCharCodes(charCodes, 0, j);
  }

  /// Read metadataMappings section from the binary.
  void _readMetadataMappings(
      Component component, int binaryOffsetForMetadataPayloads) {
    // Default reader ignores metadata section entirely.
  }

  /// Reads metadata for the given [node].
  T _associateMetadata<T extends Node>(T node, int nodeOffset) {
    // Default reader ignores metadata section entirely.
    return node;
  }

  void readStringTable() {
    // Read the table of end offsets.
    int length = readUInt30();
    List<int> endOffsets =
        new List<int>.generate(length, (_) => readUInt30(), growable: false);
    // Read the WTF-8 encoded strings.
    int startOffset = 0;
    _stringTable = new List<String>.generate(length, (int index) {
      String result = readStringEntry(endOffsets[index] - startOffset);
      startOffset = endOffsets[index];
      return result;
    }, growable: false);
  }

  void readConstantTable() {
    final int length = readUInt30();
    // Because of "back-references" (e.g. the 10th constant referencing the 3rd
    // constant) we can't use List.generate.
    _constantTable =
        new List<Constant>.filled(length, dummyConstant, growable: false);
    for (int i = 0; i < length; i++) {
      _constantTable[i] = readConstantTableEntry();
    }
  }

  Constant readConstantTableEntry() {
    final int constantTag = readByte();
    switch (constantTag) {
      case ConstantTag.NullConstant:
        return _readNullConstant();
      case ConstantTag.BoolConstant:
        return _readBoolConstant();
      case ConstantTag.IntConstant:
        return _readIntConstant();
      case ConstantTag.DoubleConstant:
        return _readDoubleConstant();
      case ConstantTag.StringConstant:
        return _readStringConstant();
      case ConstantTag.SymbolConstant:
        return _readSymbolConstant();
      case ConstantTag.MapConstant:
        return _readMapConstant();
      case ConstantTag.ListConstant:
        return _readListConstant();
      case ConstantTag.SetConstant:
        return _readSetConstant();
      case ConstantTag.InstanceConstant:
        return _readInstanceConstant();
      case ConstantTag.InstantiationConstant:
        return _readInstantiationConstant();
      case ConstantTag.TypedefTearOffConstant:
        return _readTypedefTearOffConstant();
      case ConstantTag.StaticTearOffConstant:
        return _readStaticTearOffConstant();
      case ConstantTag.ConstructorTearOffConstant:
        return _readConstructorTearOffConstant();
      case ConstantTag.RedirectingFactoryTearOffConstant:
        return _readRedirectingFactoryTearOffConstant();
      case ConstantTag.TypeLiteralConstant:
        return _readTypeLiteralConstant();
      case ConstantTag.UnevaluatedConstant:
        return _readUnevaluatedConstant();
    }

    throw fail('unexpected constant tag: $constantTag');
  }

  Constant _readNullConstant() {
    return new NullConstant();
  }

  Constant _readBoolConstant() {
    return new BoolConstant(readByte() == 1);
  }

  Constant _readIntConstant() {
    return new IntConstant((readExpression() as IntLiteral).value);
  }

  Constant _readDoubleConstant() {
    return new DoubleConstant(readDouble());
  }

  Constant _readStringConstant() {
    return new StringConstant(readStringReference());
  }

  Constant _readSymbolConstant() {
    Reference? libraryReference = readNullableLibraryReference();
    return new SymbolConstant(readStringReference(), libraryReference);
  }

  Constant _readMapConstant() {
    final DartType keyType = readDartType();
    final DartType valueType = readDartType();
    final int length = readUInt30();
    final List<ConstantMapEntry> entries =
        new List<ConstantMapEntry>.generate(length, (_) {
      final Constant key = readConstantReference();
      final Constant value = readConstantReference();
      return new ConstantMapEntry(key, value);
    }, growable: useGrowableLists);
    return new MapConstant(keyType, valueType, entries);
  }

  Constant _readListConstant() {
    final DartType typeArgument = readDartType();
    List<Constant> entries = _readConstantReferenceList();
    return new ListConstant(typeArgument, entries);
  }

  Constant _readSetConstant() {
    final DartType typeArgument = readDartType();
    List<Constant> entries = _readConstantReferenceList();
    return new SetConstant(typeArgument, entries);
  }

  Constant _readInstanceConstant() {
    final Reference classReference = readNonNullClassReference();
    final List<DartType> typeArguments = readDartTypeList();
    final int fieldValueCount = readUInt30();
    final Map<Reference, Constant> fieldValues = <Reference, Constant>{};
    for (int i = 0; i < fieldValueCount; i++) {
      final Reference fieldRef = readNonNullCanonicalNameReference().reference;
      final Constant constant = readConstantReference();
      fieldValues[fieldRef] = constant;
    }
    return new InstanceConstant(classReference, typeArguments, fieldValues);
  }

  Constant _readInstantiationConstant() {
    final Constant tearOffConstant = readConstantReference();
    final List<DartType> types = readDartTypeList();
    return new InstantiationConstant(tearOffConstant, types);
  }

  Constant _readTypedefTearOffConstant() {
    final List<TypeParameter> parameters = readAndPushTypeParameterList();
    final TearOffConstant tearOffConstant =
        readConstantReference() as TearOffConstant;
    final List<DartType> types = readDartTypeList();
    typeParameterStack.length -= parameters.length;
    return new TypedefTearOffConstant(parameters, tearOffConstant, types);
  }

  Constant _readStaticTearOffConstant() {
    final Reference reference = readNonNullCanonicalNameReference().reference;
    return new StaticTearOffConstant.byReference(reference);
  }

  Constant _readConstructorTearOffConstant() {
    final Reference reference = readNonNullCanonicalNameReference().reference;
    return new ConstructorTearOffConstant.byReference(reference);
  }

  Constant _readRedirectingFactoryTearOffConstant() {
    final Reference reference = readNonNullCanonicalNameReference().reference;
    return new RedirectingFactoryTearOffConstant.byReference(reference);
  }

  Constant _readTypeLiteralConstant() {
    final DartType type = readDartType();
    return new TypeLiteralConstant(type);
  }

  Constant _readUnevaluatedConstant() {
    final Expression expression = readExpression();
    return new UnevaluatedConstant(expression);
  }

  Constant readConstantReference() {
    final int index = readUInt30();
    Constant constant = _constantTable[index];
    assert(!identical(constant, dummyConstant),
        "No constant found at index $index.");
    return constant;
  }

  List<Constant> _readConstantReferenceList() {
    final int length = readUInt30();
    if (!useGrowableLists && length == 0) {
      // When lists don't have to be growable anyway, we might as well use an
      // almost constant one for the empty list.
      return emptyListOfConstant;
    }
    return new List<Constant>.generate(length, (_) => readConstantReference(),
        growable: useGrowableLists);
  }

  Uri readUriReference() {
    return _sourceUriTable[readUInt30()];
  }

  String readStringReference() {
    return _stringTable[readUInt30()];
  }

  List<String> readStringReferenceList() {
    int length = readUInt30();
    if (!useGrowableLists && length == 0) {
      // When lists don't have to be growable anyway, we might as well use an
      // almost constant one for the empty list.
      return emptyListOfString;
    }
    return new List<String>.generate(length, (_) => readStringReference(),
        growable: useGrowableLists);
  }

  List<Reference> readNonNullReferenceList(List<Reference> result) {
    int length = readUInt30();
    if (!useGrowableLists && length == 0) {
      return emptyListOfReference;
    }
    for (int i = 0; i < length; ++i) {
      result.add(readNonNullMemberReference());
    }
    return result;
  }

  String? readStringOrNullIfEmpty() {
    String string = readStringReference();
    return string.isEmpty ? null : string;
  }

  bool readAndCheckOptionTag() {
    int tag = readByte();
    if (tag == Tag.Nothing) {
      return false;
    } else if (tag == Tag.Something) {
      return true;
    } else {
      throw fail('unexpected option tag: $tag');
    }
  }

  List<Expression> readAnnotationList([TreeNode? parent]) {
    int length = readUInt30();
    if (length == 0) return const <Expression>[];
    return new List<Expression>.generate(
        length, (_) => readExpression()..parent = parent,
        growable: useGrowableLists);
  }

  void readLinkTable(CanonicalName linkRoot) {
    int length = readUInt30();
    _linkTable = new List<CanonicalName>.filled(
        length,
        // Use [linkRoot] as a dummy default value.
        linkRoot,
        growable: false);
    for (int i = 0; i < length; ++i) {
      int biasedParentIndex = readUInt30();
      String name = readStringReference();
      CanonicalName parent =
          biasedParentIndex == 0 ? linkRoot : _linkTable[biasedParentIndex - 1];
      _linkTable[i] = parent.getChild(name);
    }
  }

  List<int> _indexComponents() {
    _checkEmptyInput();
    int savedByteOffset = _byteOffset;
    _byteOffset = _bytes.length - 4;
    List<int> index = <int>[];
    while (_byteOffset > 0) {
      int size = readUint32();
      if (size <= 0) {
        throw fail("invalid size '$size' reported at offset $byteOffset");
      }
      int start = _byteOffset - size;
      if (start < 0) {
        throw fail("indicated size does not match file size");
      }
      index.add(size);
      _byteOffset = start - 4;
    }
    _byteOffset = savedByteOffset;
    return new List.of(index.reversed);
  }

  void _checkEmptyInput() {
    if (_bytes.length == 0) throw new StateError("Empty input given.");
  }

  void _readAndVerifySdkHash() {
    final String sdkHash = ascii.decode(readBytes(sdkHashLength));
    if (!isValidSdkHash(sdkHash)) {
      throw InvalidKernelSdkVersionError(sdkHash);
    }
  }

  /// Deserializes a kernel component and stores it in [component].
  ///
  /// When linking with a non-empty component, canonical names must have been
  /// computed ahead of time.
  ///
  /// The input bytes may contain multiple files concatenated.
  ///
  /// If [createView] is true, returns a list of [SubComponentView] - one for
  /// each concatenated dill - each of which knowing where in the combined dill
  /// it came from. If [createView] is false null will be returned.
  List<SubComponentView>? readComponent(Component component,
      {bool checkCanonicalNames: false, bool createView: false}) {
    return Timeline.timeSync<List<SubComponentView>?>(
        "BinaryBuilder.readComponent", () {
      _checkEmptyInput();

      // Check that we have a .dill file and it has the correct version before
      // we start decoding it.  Otherwise we will fail for cryptic reasons.
      int offset = _byteOffset;
      int magic = readUint32();
      if (magic != Tag.ComponentFile) {
        throw ArgumentError('Not a .dill file (wrong magic number).');
      }
      int version = readUint32();
      if (version != Tag.BinaryFormatVersion) {
        throw InvalidKernelVersionError(filename, version);
      }

      _readAndVerifySdkHash();

      _byteOffset = offset;
      List<int> componentFileSizes = _indexComponents();
      if (componentFileSizes.length > 1) {
        _disableLazyReading = true;
        _disableLazyClassReading = true;
      }
      int componentFileIndex = 0;
      List<SubComponentView>? views;
      if (createView) {
        views = <SubComponentView>[];
      }
      while (_byteOffset < _bytes.length) {
        SubComponentView? view = _readOneComponent(
            component, componentFileSizes[componentFileIndex],
            createView: createView);
        if (createView) {
          views!.add(view!);
        }
        ++componentFileIndex;
      }

      if (checkCanonicalNames) {
        component.root.checkCanonicalNameChildren();
      }
      return views;
    });
  }

  /// Deserializes the source and stores it in [component].
  /// Note that the _coverage_ normally included in the source in the
  /// uri-to-source mapping is _not_ included.
  ///
  /// The input bytes may contain multiple files concatenated.
  void readComponentSource(Component component) {
    List<int> componentFileSizes = _indexComponents();
    if (componentFileSizes.length > 1) {
      _disableLazyReading = true;
      _disableLazyClassReading = true;
    }
    int componentFileIndex = 0;
    while (_byteOffset < _bytes.length) {
      _readOneComponentSource(
          component, componentFileSizes[componentFileIndex]);
      ++componentFileIndex;
    }
  }

  /// Reads a single component file from the input and loads it into
  /// [component], overwriting and reusing any existing data in the component.
  ///
  /// When linking with a non-empty component, canonical names must have been
  /// computed ahead of time.
  ///
  /// This should *only* be used when there is a reason to not allow
  /// concatenated files.
  void readSingleFileComponent(Component component,
      {bool checkCanonicalNames: false}) {
    List<int> componentFileSizes = _indexComponents();
    if (componentFileSizes.isEmpty) throw fail("invalid component data");
    _readOneComponent(component, componentFileSizes[0]);
    if (_byteOffset < _bytes.length) {
      if (_byteOffset + 3 < _bytes.length) {
        int magic = readUint32();
        if (magic == Tag.ComponentFile) {
          throw 'Concatenated component file given when a single component '
              'was expected.';
        }
      }
      throw 'Unrecognized bytes following component data';
    }

    if (checkCanonicalNames) {
      component.root.checkCanonicalNameChildren();
    }
  }

  _ComponentIndex _readComponentIndex(int componentFileSize) {
    int savedByteIndex = _byteOffset;

    // There are two fields: file size and library count.
    _byteOffset = _componentStartOffset + componentFileSize - (2) * 4;
    int libraryCount = readUint32();
    // Library offsets are used for start and end offsets, so there is one extra
    // element that this the end offset of the last library
    List<int> libraryOffsets = new List<int>.filled(
        libraryCount + 1,
        // Use `-1` as a dummy default value.
        -1,
        growable: false);
    int componentFileSizeInBytes = readUint32();
    if (componentFileSizeInBytes != componentFileSize) {
      throw "Malformed binary: This component file's component index indicates "
          "that the file size should be $componentFileSize but other component "
          "indexes has indicated that the size should be "
          "${componentFileSizeInBytes}.";
    }

    // Skip to the start of the index.
    _byteOffset -=
        ((libraryCount + 1) + _ComponentIndex.numberOfFixedFields) * 4;

    // Now read the component index.
    int binaryOffsetForSourceTable = _componentStartOffset + readUint32();
    int binaryOffsetForConstantTable = _componentStartOffset + readUint32();
    int binaryOffsetForConstantTableIndex =
        _componentStartOffset + readUint32();
    int binaryOffsetForCanonicalNames = _componentStartOffset + readUint32();
    int binaryOffsetForMetadataPayloads = _componentStartOffset + readUint32();
    int binaryOffsetForMetadataMappings = _componentStartOffset + readUint32();
    int binaryOffsetForStringTable = _componentStartOffset + readUint32();
    int binaryOffsetForStartOfComponentIndex =
        _componentStartOffset + readUint32();
    int mainMethodReference = readUint32();
    NonNullableByDefaultCompiledMode compiledMode =
        NonNullableByDefaultCompiledMode.values[readUint32()];
    for (int i = 0; i < libraryCount + 1; ++i) {
      libraryOffsets[i] = _componentStartOffset + readUint32();
    }

    _byteOffset = savedByteIndex;

    return new _ComponentIndex(
        libraryCount: libraryCount,
        libraryOffsets: libraryOffsets,
        componentFileSizeInBytes: componentFileSizeInBytes,
        binaryOffsetForSourceTable: binaryOffsetForSourceTable,
        binaryOffsetForCanonicalNames: binaryOffsetForCanonicalNames,
        binaryOffsetForMetadataPayloads: binaryOffsetForMetadataPayloads,
        binaryOffsetForMetadataMappings: binaryOffsetForMetadataMappings,
        binaryOffsetForStringTable: binaryOffsetForStringTable,
        binaryOffsetForConstantTable: binaryOffsetForConstantTable,
        binaryOffsetForConstantTableIndex: binaryOffsetForConstantTableIndex,
        binaryOffsetForStartOfComponentIndex:
            binaryOffsetForStartOfComponentIndex,
        mainMethodReference: mainMethodReference,
        compiledMode: compiledMode);
  }

  void _readOneComponentSource(Component component, int componentFileSize) {
    _componentStartOffset = _byteOffset;

    final int magic = readUint32();
    if (magic != Tag.ComponentFile) {
      throw ArgumentError('Not a .dill file (wrong magic number).');
    }

    final int formatVersion = readUint32();
    if (formatVersion != Tag.BinaryFormatVersion) {
      throw InvalidKernelVersionError(filename, formatVersion);
    }

    _readAndVerifySdkHash();

    // Read component index from the end of this ComponentFiles serialized data.
    _ComponentIndex index = _readComponentIndex(componentFileSize);

    _byteOffset = index.binaryOffsetForSourceTable;
    Map<Uri, Source> uriToSource = readUriToSource(readCoverage: false);
    _mergeUriToSource(component.uriToSource, uriToSource);

    _byteOffset = _componentStartOffset + componentFileSize;
  }

  SubComponentView? _readOneComponent(
      Component component, int componentFileSize,
      {bool createView: false}) {
    _componentStartOffset = _byteOffset;

    final int magic = readUint32();
    if (magic != Tag.ComponentFile) {
      throw ArgumentError('Not a .dill file (wrong magic number).');
    }

    final int formatVersion = readUint32();
    if (formatVersion != Tag.BinaryFormatVersion) {
      throw InvalidKernelVersionError(filename, formatVersion);
    }

    _readAndVerifySdkHash();

    List<String>? problemsAsJson = readListOfStrings();
    if (problemsAsJson != null) {
      component.problemsAsJson ??= <String>[];
      component.problemsAsJson!.addAll(problemsAsJson);
    }

    // Read component index from the end of this ComponentFiles serialized data.
    _ComponentIndex index = _readComponentIndex(componentFileSize);
    if (compilationMode == null) {
      compilationMode = component.modeRaw;
    }
    compilationMode =
        mergeCompilationModeOrThrow(compilationMode, index.compiledMode);

    _byteOffset = index.binaryOffsetForStringTable;
    readStringTable();

    _byteOffset = index.binaryOffsetForCanonicalNames;
    readLinkTable(component.root);

    // TODO(alexmarkov): reverse metadata mappings and read forwards
    _byteOffset = index.binaryOffsetForStringTable; // Read backwards.
    _readMetadataMappings(component, index.binaryOffsetForMetadataPayloads);

    _associateMetadata(component, _componentStartOffset);

    _byteOffset = index.binaryOffsetForSourceTable;
    Map<Uri, Source> uriToSource = readUriToSource(readCoverage: true);
    _mergeUriToSource(component.uriToSource, uriToSource);

    _byteOffset = index.binaryOffsetForConstantTable;
    readConstantTable();
    // We don't need the constant table index on the dart side.

    int numberOfLibraries = index.libraryCount;

    SubComponentView? result;
    if (createView) {
      result = new SubComponentView(
          new List<Library>.generate(numberOfLibraries, (int i) {
            _byteOffset = index.libraryOffsets[i];
            return readLibrary(component, index.libraryOffsets[i + 1]);
          }, growable: false),
          _componentStartOffset,
          componentFileSize);
    } else {
      for (int i = 0; i < numberOfLibraries; ++i) {
        _byteOffset = index.libraryOffsets[i];
        readLibrary(component, index.libraryOffsets[i + 1]);
      }
    }

    Reference? mainMethod =
        getNullableMemberReferenceFromInt(index.mainMethodReference);
    component.setMainMethodAndMode(mainMethod, false, compilationMode!);

    _byteOffset = _componentStartOffset + componentFileSize;

    assert(typeParameterStack.isEmpty);

    return result;
  }

  /// Read a list of strings. If the list is empty, [null] is returned.
  List<String>? readListOfStrings() {
    int length = readUInt30();
    if (length == 0) return null;
    return new List<String>.generate(length, (_) => readString(),
        growable: useGrowableLists);
  }

  /// Read the uri-to-source part of the binary.
  /// Note that this can include coverage, but that it is only included if
  /// [readCoverage] is true, otherwise coverage will be skipped. Note also that
  /// if [readCoverage] is true, references are read and that the link table
  /// thus has to be read first.
  Map<Uri, Source> readUriToSource({required bool readCoverage}) {
    // ignore: unnecessary_null_comparison
    assert(!readCoverage || (readCoverage && _linkTable != null));

    int length = readUint32();

    // Read data.
    _sourceUriTable = new List<Uri>.filled(length, dummyUri, growable: false);
    Map<Uri, Source> uriToSource = <Uri, Source>{};
    for (int i = 0; i < length; ++i) {
      String uriString = readString();
      Uri uri = Uri.parse(uriString);
      _sourceUriTable[i] = uri;
      Uint8List sourceCode = readByteList();
      int lineCount = readUInt30();
      List<int> lineStarts = new List<int>.filled(
          lineCount,
          // Use `-1` as a dummy default value.
          -1,
          growable: false);
      int previousLineStart = 0;
      for (int j = 0; j < lineCount; ++j) {
        int lineStart = readUInt30() + previousLineStart;
        lineStarts[j] = lineStart;
        previousLineStart = lineStart;
      }
      String importUriString = readString();
      Uri importUri = Uri.parse(importUriString);

      Set<Reference>? coverageConstructors;
      {
        int constructorCoverageCount = readUInt30();
        if (constructorCoverageCount > 0) {
          if (readCoverage) {
            coverageConstructors = new Set<Reference>();
            for (int j = 0; j < constructorCoverageCount; ++j) {
              coverageConstructors.add(readNonNullMemberReference());
            }
          } else {
            for (int j = 0; j < constructorCoverageCount; ++j) {
              skipMemberReference();
            }
          }
        }
      }

      uriToSource[uri] = new Source(lineStarts, sourceCode, importUri, uri)
        ..constantCoverageConstructors = coverageConstructors;
    }

    // Read index.
    for (int i = 0; i < length; ++i) {
      readUint32();
    }
    return uriToSource;
  }

  // Add everything from [src] into [dst], but don't overwrite a non-empty
  // source with an empty source. Empty sources may be introduced by
  // synthetic, copy-down implementations such as mixin applications or
  // noSuchMethod forwarders.
  void _mergeUriToSource(Map<Uri, Source> dst, Map<Uri, Source> src) {
    if (dst.isEmpty) {
      // Fast path for the common case of one component per binary.
      dst.addAll(src);
    } else {
      src.forEach((Uri key, Source value) {
        Source? originalDestinationSource = dst[key];
        Source? mergeFrom;
        Source mergeTo;
        if (value.source.isNotEmpty || originalDestinationSource == null) {
          dst[key] = value;
          mergeFrom = originalDestinationSource;
          mergeTo = value;
        } else {
          mergeFrom = value;
          mergeTo = originalDestinationSource;
        }

        // TODO(jensj): Find out what the right thing to do is --- it probably
        // depends on what we do if read the same library twice - do we merge or
        // do we overwrite, and should we even support such a thing?

        // Merge coverage. Note that mergeFrom might be null.
        if (mergeTo.constantCoverageConstructors == null) {
          mergeTo.constantCoverageConstructors =
              mergeFrom?.constantCoverageConstructors;
        } else if (mergeFrom?.constantCoverageConstructors == null) {
          // Nothing to do.
        } else {
          // Both are non-null: Merge.
          mergeTo.constantCoverageConstructors!
              .addAll(mergeFrom!.constantCoverageConstructors!);
        }
      });
    }
  }

  void skipCanonicalNameReference() {
    readUInt30();
  }

  CanonicalName? readNullableCanonicalNameReference() {
    int index = readUInt30();
    if (index == 0) return null;
    return _linkTable[index - 1];
  }

  CanonicalName readNonNullCanonicalNameReference() {
    CanonicalName? canonicalName = readNullableCanonicalNameReference();
    if (canonicalName == null) {
      throw new StateError('No canonical name found.');
    }
    return canonicalName;
  }

  CanonicalName? getNullableCanonicalNameReferenceFromInt(int index) {
    if (index == 0) return null;
    return _linkTable[index - 1];
  }

  Reference? readNullableLibraryReference() {
    CanonicalName? canonicalName = readNullableCanonicalNameReference();
    return canonicalName?.reference;
  }

  Reference readNonNullLibraryReference() {
    CanonicalName? canonicalName = readNullableCanonicalNameReference();
    if (canonicalName != null) return canonicalName.reference;
    throw 'Expected a library reference to be valid but was `null`.';
  }

  LibraryDependency readLibraryDependencyReference() {
    int index = readUInt30();
    return _currentLibrary!.dependencies[index];
  }

  Reference? readNullableClassReference() {
    CanonicalName? name = readNullableCanonicalNameReference();
    return name?.reference;
  }

  Reference readNonNullClassReference() {
    CanonicalName? name = readNullableCanonicalNameReference();
    if (name == null) {
      throw 'Expected a class reference to be valid but was `null`.';
    }
    return name.reference;
  }

  void skipMemberReference() {
    skipCanonicalNameReference();
  }

  Reference? readNullableMemberReference() {
    CanonicalName? name = readNullableCanonicalNameReference();
    return name?.reference;
  }

  Reference readNonNullMemberReference() {
    CanonicalName? name = readNullableCanonicalNameReference();
    if (name == null) {
      throw 'Expected a member reference to be valid but was `null`.';
    }
    return name.reference;
  }

  Reference? readNullableInstanceMemberReference() {
    Reference? reference = readNullableMemberReference();
    readNullableMemberReference(); // Skip origin
    return reference;
  }

  Reference readNonNullInstanceMemberReference() {
    Reference reference = readNonNullMemberReference();
    readNullableMemberReference(); // Skip origin
    return reference;
  }

  Reference? getNullableMemberReferenceFromInt(int index) {
    return getNullableCanonicalNameReferenceFromInt(index)?.reference;
  }

  Reference? readNullableTypedefReference() {
    return readNullableCanonicalNameReference()?.reference;
  }

  Reference readNonNullTypedefReference() {
    return readNonNullCanonicalNameReference().reference;
  }

  Name readName() {
    String text = readStringReference();
    if (text.isNotEmpty && text[0] == '_') {
      return new Name.byReference(text, readNonNullLibraryReference());
    } else {
      return new Name(text);
    }
  }

  Library readLibrary(Component component, int endOffset) {
    // Read index.
    int savedByteOffset = _byteOffset;

    // There is a field for the procedure count.
    _byteOffset = endOffset - (1) * 4;
    int procedureCount = readUint32();

    // There is a field for the procedure count, that number + 1 (for the end)
    // offsets, and then the class count (i.e. procedure count + 3 fields).
    _byteOffset = endOffset - (procedureCount + 3) * 4;
    int classCount = readUint32();
    List<int> procedureOffsets = new List<int>.generate(
        procedureCount + 1, (int index) => _componentStartOffset + readUint32(),
        growable: false);

    // There is a field for the procedure count, that number + 1 (for the end)
    // offsets, then the class count and that number + 1 (for the end) offsets.
    // (i.e. procedure count + class count + 4 fields).
    _byteOffset = endOffset - (procedureCount + classCount + 4) * 4;
    List<int> classOffsets = new List<int>.generate(
        classCount + 1, (int index) => _componentStartOffset + readUint32(),
        growable: false);
    _byteOffset = savedByteOffset;

    int flags = readByte();

    int languageVersionMajor = readUInt30();
    int languageVersionMinor = readUInt30();

    CanonicalName canonicalName = readNonNullCanonicalNameReference();
    Reference reference = canonicalName.reference;
    Library? library = reference.node as Library?;
    String? name = readStringOrNullIfEmpty();

    // TODO(jensj): We currently save (almost the same) uri twice.
    Uri fileUri = readUriReference();

    if (alwaysCreateNewNamedNodes) {
      library = null;
    }
    if (library == null) {
      library = new Library(Uri.parse(canonicalName.name),
          reference: reference, fileUri: fileUri);
      component.libraries.add(library..parent = component);
    }
    _currentLibrary = library;

    List<String>? problemsAsJson = readListOfStrings();

    library.flags = flags;
    library.setLanguageVersion(
        new Version(languageVersionMajor, languageVersionMinor));
    library.name = name;
    library.fileUri = fileUri;
    library.problemsAsJson = problemsAsJson;

    assert(
        mergeCompilationModeOrThrow(
                compilationMode, library.nonNullableByDefaultCompiledMode) ==
            compilationMode,
        "Cannot load ${library.nonNullableByDefaultCompiledMode} "
        "into component with mode $compilationMode");

    assert(() {
      debugPath.add(library!.name ?? library.importUri.toString());
      return true;
    }());

    library.annotations = readAnnotationList(library);
    _readLibraryDependencies(library);
    _readAdditionalExports(library);
    _readLibraryParts(library);
    _readTypedefList(library);
    _readClassList(library, classOffsets);
    _readExtensionList(library);
    library.fieldsInternal = _readFieldList(library);
    library.proceduresInternal = _readProcedureList(library, procedureOffsets);

    assert(((_) => true)(debugPath.removeLast()));
    _currentLibrary = null;
    return library;
  }

  void _readTypedefList(Library library) {
    int length = readUInt30();
    if (!useGrowableLists && length == 0) {
      // When lists don't have to be growable anyway, we might as well use an
      // almost constant one for the empty list.
      library.typedefsInternal = emptyListOfTypedef;
    } else {
      library.typedefsInternal = new List<Typedef>.generate(
          length, (int index) => readTypedef()..parent = library,
          growable: useGrowableLists);
    }
  }

  void _readClassList(Library library, List<int> classOffsets) {
    int length = readUInt30();
    if (!useGrowableLists && length == 0) {
      // When lists don't have to be growable anyway, we might as well use an
      // almost constant one for the empty list.
      library.classesInternal = emptyListOfClass;
    } else {
      library.classesInternal = new List<Class>.generate(length, (int index) {
        _byteOffset = classOffsets[index];
        return readClass(classOffsets[index + 1])..parent = library;
      }, growable: useGrowableLists);
      _byteOffset = classOffsets.last;
    }
  }

  void _readExtensionList(Library library) {
    int length = readUInt30();
    if (!useGrowableLists && length == 0) {
      // When lists don't have to be growable anyway, we might as well use an
      // almost constant one for the empty list.
      library.extensionsInternal = emptyListOfExtension;
    } else {
      library.extensionsInternal = new List<Extension>.generate(
          length, (int index) => readExtension()..parent = library,
          growable: useGrowableLists);
    }
  }

  List<Field> _readFieldList(TreeNode parent) {
    int length = readUInt30();
    if (!useGrowableLists && length == 0) {
      // When lists don't have to be growable anyway, we might as well use an
      // almost constant one for the empty list.
      return emptyListOfField;
    }
    return new List<Field>.generate(
        length, (int index) => readField()..parent = parent,
        growable: useGrowableLists);
  }

  List<Procedure> _readProcedureList(
      TreeNode parent, List<int> procedureOffsets) {
    int length = readUInt30();
    if (!useGrowableLists && length == 0) {
      // When lists don't have to be growable anyway, we might as well use an
      // almost constant one for the empty list.
      return emptyListOfProcedure;
    }
    List<Procedure> list = new List<Procedure>.generate(length, (int index) {
      _byteOffset = procedureOffsets[index];
      return readProcedure(procedureOffsets[index + 1])..parent = parent;
    }, growable: useGrowableLists);
    _byteOffset = procedureOffsets.last;
    return list;
  }

  void _readLibraryDependencies(Library library) {
    int length = readUInt30();
    if (!useGrowableLists && length == 0) {
      // When lists don't have to be growable anyway, we might as well use an
      // almost constant one for the empty list.
      library.dependencies = emptyListOfLibraryDependency;
    } else {
      library.dependencies = new List<LibraryDependency>.generate(
          length, (int index) => readLibraryDependency()..parent = library,
          growable: useGrowableLists);
    }
  }

  LibraryDependency readLibraryDependency() {
    int fileOffset = readOffset();
    int flags = readByte();
    List<Expression> annotations = readExpressionList();
    Reference targetLibrary = readNonNullLibraryReference();
    String? prefixName = readStringOrNullIfEmpty();
    List<Combinator> names = readCombinatorList();
    return new LibraryDependency.byReference(
        flags, annotations, targetLibrary, prefixName, names)
      ..fileOffset = fileOffset;
  }

  void _readAdditionalExports(Library library) {
    int numExportedReference = readUInt30();
    if (numExportedReference != 0) {
      library.additionalExports.clear();
      for (int i = 0; i < numExportedReference; i++) {
        CanonicalName exportedName = readNonNullCanonicalNameReference();
        Reference reference = exportedName.reference;
        library.additionalExports.add(reference);
      }
    }
  }

  Combinator readCombinator() {
    bool isShow = readByte() == 1;
    List<String> names = readStringReferenceList();
    return new Combinator(isShow, names);
  }

  List<Combinator> readCombinatorList() {
    int length = readUInt30();
    if (!useGrowableLists && length == 0) {
      // When lists don't have to be growable anyway, we might as well use an
      // almost constant one for the empty list.
      return emptyListOfCombinator;
    }
    return new List<Combinator>.generate(length, (_) => readCombinator(),
        growable: useGrowableLists);
  }

  void _readLibraryParts(Library library) {
    int length = readUInt30();
    if (!useGrowableLists && length == 0) {
      // When lists don't have to be growable anyway, we might as well use an
      // almost constant one for the empty list.
      library.parts = emptyListOfLibraryPart;
    } else {
      library.parts = new List<LibraryPart>.generate(
          length, (int index) => readLibraryPart()..parent = library,
          growable: useGrowableLists);
    }
  }

  LibraryPart readLibraryPart() {
    List<Expression> annotations = readExpressionList();
    String partUri = readStringReference();
    return new LibraryPart(annotations, partUri);
  }

  Typedef readTypedef() {
    CanonicalName canonicalName = readNonNullCanonicalNameReference();
    Reference reference = canonicalName.reference;
    Typedef? node = reference.node as Typedef?;
    if (alwaysCreateNewNamedNodes) {
      node = null;
    }
    Uri fileUri = readUriReference();
    int fileOffset = readOffset();
    String name = readStringReference();
    if (node == null) {
      node = new Typedef(name, null, reference: reference, fileUri: fileUri);
    }
    node.annotations = readAnnotationList(node);
    readAndPushTypeParameterList(node.typeParameters, node);
    DartType type = readDartType();
    readAndPushTypeParameterList(node.typeParametersOfFunctionType, node);
    node.positionalParameters.clear();
    node.positionalParameters.addAll(readAndPushVariableDeclarationList());
    setParents(node.positionalParameters, node);
    node.namedParameters.clear();
    node.namedParameters.addAll(readAndPushVariableDeclarationList());
    setParents(node.namedParameters, node);
    typeParameterStack.length = 0;
    variableStack.length = 0;
    node.fileOffset = fileOffset;
    node.name = name;
    node.fileUri = fileUri;
    node.type = type;
    return node;
  }

  Class readClass(int endOffset) {
    int tag = readByte();
    assert(tag == Tag.Class);

    // Read index.
    int savedByteOffset = _byteOffset;
    // There is a field for the procedure count.
    _byteOffset = endOffset - (1) * 4;
    int procedureCount = readUint32();
    // There is a field for the procedure count, that number + 1 (for the end)
    // offsets (i.e. procedure count + 2 fields).
    _byteOffset = endOffset - (procedureCount + 2) * 4;
    List<int> procedureOffsets = new List<int>.generate(
        procedureCount + 1, (_) => _componentStartOffset + readUint32(),
        growable: false);
    _byteOffset = savedByteOffset;

    CanonicalName canonicalName = readNonNullCanonicalNameReference();
    Reference reference = canonicalName.reference;
    Class? node = reference.node as Class?;
    if (alwaysCreateNewNamedNodes) {
      node = null;
    }
    Uri fileUri = readUriReference();
    int startFileOffset = readOffset();
    int fileOffset = readOffset();
    int fileEndOffset = readOffset();
    int flags = readByte();
    String name = readStringReference();
    if (node == null) {
      node = new Class(name: name, reference: reference, fileUri: fileUri)
        ..dirty = false;
    }

    node.startFileOffset = startFileOffset;
    node.fileOffset = fileOffset;
    node.fileEndOffset = fileEndOffset;
    node.flags = flags;
    List<Expression> annotations = readAnnotationList(node);
    assert(() {
      debugPath.add(name);
      return true;
    }());

    assert(typeParameterStack.length == 0);

    readAndPushTypeParameterList(node.typeParameters, node);
    Supertype? supertype = readSupertypeOption();
    Supertype? mixedInType = readSupertypeOption();
    node.implementedTypes = readSupertypeList();
    if (_disableLazyClassReading) {
      readClassPartialContent(node, procedureOffsets);
    } else {
      _setLazyLoadClass(node, procedureOffsets);
    }

    typeParameterStack.length = 0;
    // ignore: unnecessary_null_comparison
    assert(debugPath.removeLast() != null);
    node.name = name;
    node.fileUri = fileUri;
    node.annotations = annotations;
    node.supertype = supertype;
    node.mixedInType = mixedInType;

    _byteOffset = endOffset;

    return node;
  }

  Extension readExtension() {
    int tag = readByte();
    assert(tag == Tag.Extension);

    CanonicalName canonicalName = readNonNullCanonicalNameReference();
    Reference reference = canonicalName.reference;
    Extension? node = reference.node as Extension?;
    if (alwaysCreateNewNamedNodes) {
      node = null;
    }

    String name = readStringReference();
    assert(() {
      debugPath.add(name);
      return true;
    }());

    List<Expression> annotations = readAnnotationList();

    Uri fileUri = readUriReference();

    if (node == null) {
      node = new Extension(name: name, reference: reference, fileUri: fileUri);
    }
    node.annotations = annotations;
    setParents(annotations, node);

    node.fileOffset = readOffset();

    node.flags = readByte();

    readAndPushTypeParameterList(node.typeParameters, node);
    DartType onType = readDartType();

    if (readAndCheckOptionTag()) {
      ExtensionTypeShowHideClause showHideClause =
          node.showHideClause = new ExtensionTypeShowHideClause();
      readSupertypeList(showHideClause.shownSupertypes);
      readNonNullReferenceList(showHideClause.shownMethods);
      readNonNullReferenceList(showHideClause.shownGetters);
      readNonNullReferenceList(showHideClause.shownSetters);
      readNonNullReferenceList(showHideClause.shownOperators);
      readSupertypeList(showHideClause.hiddenSupertypes);
      readNonNullReferenceList(showHideClause.hiddenMethods);
      readNonNullReferenceList(showHideClause.hiddenGetters);
      readNonNullReferenceList(showHideClause.hiddenSetters);
      readNonNullReferenceList(showHideClause.hiddenOperators);
    }

    typeParameterStack.length = 0;

    node.name = name;
    node.fileUri = fileUri;
    node.onType = onType;

    node.members = _readExtensionMemberDescriptorList();

    return node;
  }

  List<ExtensionMemberDescriptor> _readExtensionMemberDescriptorList() {
    int length = readUInt30();
    if (!useGrowableLists && length == 0) {
      // When lists don't have to be growable anyway, we might as well use a
      // constant one for the empty list.
      return emptyListOfExtensionMemberDescriptor;
    }
    return new List<ExtensionMemberDescriptor>.generate(
        length, (_) => _readExtensionMemberDescriptor(),
        growable: useGrowableLists);
  }

  ExtensionMemberDescriptor _readExtensionMemberDescriptor() {
    Name name = readName();
    int kind = readByte();
    int flags = readByte();
    CanonicalName canonicalName = readNonNullCanonicalNameReference();
    return new ExtensionMemberDescriptor(
        name: name,
        kind: ExtensionMemberKind.values[kind],
        member: canonicalName.reference)
      ..flags = flags;
  }

  /// Reads the partial content of a class, namely fields, procedures,
  /// constructors and redirecting factory constructors.
  void readClassPartialContent(Class node, List<int> procedureOffsets) {
    node.fieldsInternal = _readFieldList(node);
    _readConstructorList(node);
    node.proceduresInternal = _readProcedureList(node, procedureOffsets);
    _readRedirectingFactoryList(node);
  }

  void _readConstructorList(Class node) {
    int length = readUInt30();
    if (!useGrowableLists && length == 0) {
      // When lists don't have to be growable anyway, we might as well use a
      // constant one for the empty list.
      node.constructorsInternal = emptyListOfConstructor;
    } else {
      node.constructorsInternal = new List<Constructor>.generate(
          length, (int index) => readConstructor()..parent = node,
          growable: useGrowableLists);
    }
  }

  void _readRedirectingFactoryList(Class node) {
    int length = readUInt30();
    if (!useGrowableLists && length == 0) {
      // When lists don't have to be growable anyway, we might as well use a
      // constant one for the empty list.
      node.redirectingFactoryConstructorsInternal =
          emptyListOfRedirectingFactory;
    } else {
      node.redirectingFactoryConstructorsInternal =
          new List<RedirectingFactory>.generate(
              length, (int index) => readRedirectingFactory()..parent = node,
              growable: useGrowableLists);
    }
  }

  /// Set the lazyBuilder on the class so it can be lazy loaded in the future.
  void _setLazyLoadClass(Class node, List<int> procedureOffsets) {
    final int savedByteOffset = _byteOffset;
    final int componentStartOffset = _componentStartOffset;
    final Library? currentLibrary = _currentLibrary;
    node.lazyBuilder = () {
      _byteOffset = savedByteOffset;
      _currentLibrary = currentLibrary;
      assert(typeParameterStack.isEmpty);
      _componentStartOffset = componentStartOffset;
      typeParameterStack.addAll(node.typeParameters);

      readClassPartialContent(node, procedureOffsets);
      typeParameterStack.length = 0;
    };
  }

  int getAndResetTransformerFlags() {
    int flags = _transformerFlags;
    _transformerFlags = 0;
    return flags;
  }

  /// Adds the given flag to the current [Member.transformerFlags].
  void addTransformerFlag(int flags) {
    _transformerFlags |= flags;
  }

  Field readField() {
    int tag = readByte();
    assert(tag == Tag.Field);
    CanonicalName fieldCanonicalName = readNonNullCanonicalNameReference();
    Reference fieldReference = fieldCanonicalName.reference;
    CanonicalName getterCanonicalName = readNonNullCanonicalNameReference();
    Reference getterReference = getterCanonicalName.reference;
    CanonicalName? setterCanonicalName = readNullableCanonicalNameReference();
    Reference? setterReference = setterCanonicalName?.reference;
    Field? node = fieldReference.node as Field?;
    if (alwaysCreateNewNamedNodes) {
      node = null;
    }
    Uri fileUri = readUriReference();
    int fileOffset = readOffset();
    int fileEndOffset = readOffset();
    int flags = readUInt30();
    Name name = readName();
    if (node == null) {
      if (setterReference != null) {
        node = new Field.mutable(name,
            fieldReference: fieldReference,
            getterReference: getterReference,
            setterReference: setterReference,
            fileUri: fileUri);
      } else {
        node = new Field.immutable(name,
            fieldReference: fieldReference,
            getterReference: getterReference,
            fileUri: fileUri);
      }
    }
    List<Expression> annotations = readAnnotationList(node);
    assert(() {
      debugPath.add(name.text);
      return true;
    }());
    DartType type = readDartType();
    Expression? initializer = readExpressionOption();
    int transformerFlags = getAndResetTransformerFlags();
    assert(((_) => true)(debugPath.removeLast()));
    node.fileOffset = fileOffset;
    node.fileEndOffset = fileEndOffset;
    node.flags = flags;
    node.name = name;
    node.fileUri = fileUri;
    node.annotations = annotations;
    node.type = type;
    node.initializer = initializer;
    node.initializer?.parent = node;
    node.transformerFlags = transformerFlags;
    return node;
  }

  Constructor readConstructor() {
    int tag = readByte();
    assert(tag == Tag.Constructor);
    CanonicalName canonicalName = readNonNullCanonicalNameReference();
    Reference reference = canonicalName.reference;
    Constructor? node = reference.node as Constructor?;
    if (alwaysCreateNewNamedNodes) {
      node = null;
    }
    Uri fileUri = readUriReference();
    int startFileOffset = readOffset();
    int fileOffset = readOffset();
    int fileEndOffset = readOffset();
    int flags = readByte();
    Name name = readName();
    List<Expression> annotations = readAnnotationList();
    assert(() {
      debugPath.add(name.text);
      return true;
    }());
    FunctionNode function = readFunctionNode();
    if (node == null) {
      node = new Constructor(function,
          reference: reference, name: name, fileUri: fileUri);
    }
    pushVariableDeclarations(function.positionalParameters);
    pushVariableDeclarations(function.namedParameters);
    _readInitializers(node);
    variableStack.length = 0;
    int transformerFlags = getAndResetTransformerFlags();
    assert(((_) => true)(debugPath.removeLast()));
    node.startFileOffset = startFileOffset;
    node.fileOffset = fileOffset;
    node.fileEndOffset = fileEndOffset;
    node.flags = flags;
    node.name = name;
    node.fileUri = fileUri;
    node.annotations = annotations;
    setParents(annotations, node);
    node.function = function..parent = node;
    node.transformerFlags = transformerFlags;
    return node;
  }

  Procedure readProcedure(int endOffset) {
    int tag = readByte();
    assert(tag == Tag.Procedure);
    CanonicalName canonicalName = readNonNullCanonicalNameReference();
    Reference reference = canonicalName.reference;
    Procedure? node = reference.node as Procedure?;
    if (alwaysCreateNewNamedNodes) {
      node = null;
    }
    Uri fileUri = readUriReference();
    int startFileOffset = readOffset();
    int fileOffset = readOffset();
    int fileEndOffset = readOffset();
    int kindIndex = readByte();
    ProcedureKind kind = ProcedureKind.values[kindIndex];
    ProcedureStubKind stubKind = ProcedureStubKind.values[readByte()];
    int flags = readUInt30();
    Name name = readName();
    List<Expression> annotations = readAnnotationList();
    assert(() {
      debugPath.add(name.text);
      return true;
    }());
    int functionNodeSize = endOffset - _byteOffset;
    // Read small factories up front. Postpone everything else.
    bool readFunctionNodeNow =
        (kind == ProcedureKind.Factory && functionNodeSize <= 50) ||
            _disableLazyReading;
    Reference? stubTargetReference = readNullableMemberReference();
    FunctionType? signatureType = readDartTypeOption() as FunctionType?;
    FunctionNode function = readFunctionNode(
        lazyLoadBody: !readFunctionNodeNow, outerEndOffset: endOffset);
    if (node == null) {
      node = new Procedure(name, kind, function,
          reference: reference, fileUri: fileUri);
    } else {
      assert(node.kind == kind);
    }
    int transformerFlags = getAndResetTransformerFlags();
    assert(((_) => true)(debugPath.removeLast()));
    node.startFileOffset = startFileOffset;
    node.fileOffset = fileOffset;
    node.fileEndOffset = fileEndOffset;
    node.flags = flags;
    node.name = name;
    node.fileUri = fileUri;
    node.annotations = annotations;
    setParents(annotations, node);
    node.function = function..parent = node;
    node.setTransformerFlagsWithoutLazyLoading(transformerFlags);
    node.stubKind = stubKind;
    node.stubTargetReference = stubTargetReference;
    node.signatureType = signatureType;

    assert((node.stubKind == ProcedureStubKind.ConcreteForwardingStub &&
            node.stubTargetReference != null) ||
        !(node.isForwardingStub && node.function.body != null));
    assert(!(node.isMemberSignature && node.stubTargetReference == null),
        "No member signature origin for member signature $node.");
    return node;
  }

  RedirectingFactory readRedirectingFactory() {
    int tag = readByte();
    assert(tag == Tag.RedirectingFactory);
    CanonicalName canonicalName = readNonNullCanonicalNameReference();
    Reference reference = canonicalName.reference;
    RedirectingFactory? node = reference.node as RedirectingFactory?;
    if (alwaysCreateNewNamedNodes) {
      node = null;
    }
    Uri fileUri = readUriReference();
    int fileOffset = readOffset();
    int fileEndOffset = readOffset();
    int flags = readByte();
    Name name = readName();
    assert(() {
      debugPath.add(name.text);
      return true;
    }());
    List<Expression> annotations = readAnnotationList();
    Reference targetReference = readNonNullMemberReference();
    List<DartType> typeArguments = readDartTypeList();
    FunctionNode function = readFunctionNode(outerEndOffset: fileEndOffset);
    if (node == null) {
      node = new RedirectingFactory(targetReference,
          reference: reference,
          name: name,
          fileUri: fileUri,
          function: function,
          typeArguments: typeArguments);
    } else {
      node.name = name;
      node.fileUri = fileUri;
      node.targetReference = targetReference;
      node.typeArguments.addAll(typeArguments);
      node.function = function..parent = node;
    }
    node.fileOffset = fileOffset;
    node.fileEndOffset = fileEndOffset;
    node.flags = flags;
    node.annotations = annotations;
    setParents(annotations, node);
    debugPath.removeLast();
    return node;
  }

  void _readInitializers(Constructor constructor) {
    int length = readUInt30();
    if (!useGrowableLists && length == 0) {
      // When lists don't have to be growable anyway, we might as well use a
      // constant one for the empty list.
      constructor.initializers = emptyListOfInitializer;
    } else {
      constructor.initializers = new List<Initializer>.generate(
          length, (int index) => readInitializer()..parent = constructor,
          growable: useGrowableLists);
    }
  }

  Initializer readInitializer() {
    int tag = readByte();
    bool isSynthetic = readByte() == 1;
    switch (tag) {
      case Tag.InvalidInitializer:
        return _readInvalidInitializer();
      case Tag.FieldInitializer:
        return _readFieldInitializer(isSynthetic);
      case Tag.SuperInitializer:
        return _readSuperInitializer(isSynthetic);
      case Tag.RedirectingInitializer:
        return _readRedirectingInitializer();
      case Tag.LocalInitializer:
        return _readLocalInitializer();
      case Tag.AssertInitializer:
        return _readAssertInitializer();
      default:
        throw fail('unexpected initializer tag: $tag');
    }
  }

  Initializer _readInvalidInitializer() {
    return new InvalidInitializer();
  }

  Initializer _readFieldInitializer(bool isSynthetic) {
    Reference reference = readNonNullMemberReference();
    Expression value = readExpression();
    return new FieldInitializer.byReference(reference, value)
      ..isSynthetic = isSynthetic;
  }

  Initializer _readSuperInitializer(bool isSynthetic) {
    int offset = readOffset();
    Reference reference = readNonNullMemberReference();
    Arguments arguments = readArguments();
    return new SuperInitializer.byReference(reference, arguments)
      ..isSynthetic = isSynthetic
      ..fileOffset = offset;
  }

  Initializer _readRedirectingInitializer() {
    int offset = readOffset();
    return new RedirectingInitializer.byReference(
        readNonNullMemberReference(), readArguments())
      ..fileOffset = offset;
  }

  Initializer _readLocalInitializer() {
    return new LocalInitializer(readAndPushVariableDeclaration());
  }

  Initializer _readAssertInitializer() {
    return new AssertInitializer(readStatement() as AssertStatement);
  }

  FunctionNode readFunctionNode(
      {bool lazyLoadBody: false, int outerEndOffset: -1}) {
    int tag = readByte();
    assert(tag == Tag.FunctionNode);
    int offset = readOffset();
    int endOffset = readOffset();
    AsyncMarker asyncMarker = AsyncMarker.values[readByte()];
    AsyncMarker dartAsyncMarker = AsyncMarker.values[readByte()];
    int typeParameterStackHeight = typeParameterStack.length;
    List<TypeParameter> typeParameters = readAndPushTypeParameterList();
    readUInt30(); // total parameter count.
    int requiredParameterCount = readUInt30();
    int variableStackHeight = variableStack.length;
    List<VariableDeclaration> positional = readAndPushVariableDeclarationList();
    List<VariableDeclaration> named = readAndPushVariableDeclarationList();
    DartType returnType = readDartType();
    DartType? futureValueType = readDartTypeOption();
    int oldLabelStackBase = labelStackBase;
    int oldSwitchCaseStackBase = switchCaseStackBase;

    if (lazyLoadBody && outerEndOffset > 0) {
      lazyLoadBody = outerEndOffset - _byteOffset >
          2; // e.g. outline has Tag.Something and Tag.EmptyStatement
    }

    Statement? body;
    if (!lazyLoadBody) {
      labelStackBase = labelStack.length;
      switchCaseStackBase = switchCaseStack.length;
      body = readStatementOption();
    }

    FunctionNode result = new FunctionNode(body,
        typeParameters: typeParameters,
        requiredParameterCount: requiredParameterCount,
        positionalParameters: positional,
        namedParameters: named,
        returnType: returnType,
        asyncMarker: asyncMarker,
        dartAsyncMarker: dartAsyncMarker,
        futureValueType: futureValueType)
      ..fileOffset = offset
      ..fileEndOffset = endOffset;

    if (lazyLoadBody) {
      _setLazyLoadFunction(result, oldLabelStackBase, oldSwitchCaseStackBase,
          variableStackHeight);
    }

    labelStackBase = oldLabelStackBase;
    switchCaseStackBase = oldSwitchCaseStackBase;
    variableStack.length = variableStackHeight;
    typeParameterStack.length = typeParameterStackHeight;

    return result;
  }

  void _setLazyLoadFunction(FunctionNode result, int oldLabelStackBase,
      int oldSwitchCaseStackBase, int variableStackHeight) {
    final int savedByteOffset = _byteOffset;
    final int componentStartOffset = _componentStartOffset;
    final List<TypeParameter> typeParameters = typeParameterStack.toList();
    final List<VariableDeclaration> variables = variableStack.toList();
    final Library currentLibrary = _currentLibrary!;
    result.lazyBuilder = () {
      _byteOffset = savedByteOffset;
      _currentLibrary = currentLibrary;
      typeParameterStack.clear();
      typeParameterStack.addAll(typeParameters);
      variableStack.clear();
      variableStack.addAll(variables);
      _componentStartOffset = componentStartOffset;

      result.body = readStatementOption();
      result.body?.parent = result;
      labelStackBase = oldLabelStackBase;
      switchCaseStackBase = oldSwitchCaseStackBase;
      variableStack.length = variableStackHeight;
      typeParameterStack.clear();
      TreeNode? parent = result.parent;
      if (parent is Procedure) {
        parent.transformerFlags |= getAndResetTransformerFlags();
      }
    };
  }

  void pushVariableDeclaration(VariableDeclaration variable) {
    variableStack.add(variable);
  }

  void pushVariableDeclarations(List<VariableDeclaration> variables) {
    variableStack.addAll(variables);
  }

  VariableDeclaration readVariableReference() {
    int index = readUInt30();
    if (index >= variableStack.length) {
      throw fail('Unexpected variable index: $index. '
          'Current variable count: ${variableStack.length}.');
    }
    return variableStack[index];
  }

  LogicalExpressionOperator logicalOperatorToEnum(int index) {
    switch (index) {
      case 0:
        return LogicalExpressionOperator.AND;
      case 1:
        return LogicalExpressionOperator.OR;
      default:
        throw fail('unexpected logical operator index: $index');
    }
  }

  List<Expression> readExpressionList() {
    int length = readUInt30();
    if (!useGrowableLists && length == 0) {
      // When lists don't have to be growable anyway, we might as well use a
      // constant one for the empty list.
      return emptyListOfExpression;
    }
    return new List<Expression>.generate(length, (_) => readExpression(),
        growable: useGrowableLists);
  }

  Expression? readExpressionOption() {
    return readAndCheckOptionTag() ? readExpression() : null;
  }

  Expression readExpression() {
    int tagByte = readByte();
    int tag = tagByte & Tag.SpecializedTagHighBit == 0
        ? tagByte
        : (tagByte & Tag.SpecializedTagMask);
    switch (tag) {
      case Tag.LoadLibrary:
        return _readLoadLibrary();
      case Tag.CheckLibraryIsLoaded:
        return _readCheckLibraryIsLoaded();
      case Tag.InvalidExpression:
        return _readInvalidExpression();
      case Tag.VariableGet:
        return _readVariableGet();
      case Tag.SpecializedVariableGet:
        return _readSpecializedVariableGet(tagByte);
      case Tag.VariableSet:
        return _readVariableSet();
      case Tag.SpecializedVariableSet:
        return _readSpecializedVariableSet(tagByte);
      case Tag.InstanceGet:
        return _readInstanceGet();
      case Tag.InstanceTearOff:
        return _readInstanceTearOff();
      case Tag.DynamicGet:
        return _readDynamicGet();
      case Tag.InstanceSet:
        return _readInstanceSet();
      case Tag.DynamicSet:
        return _readDynamicSet();
      case Tag.SuperPropertyGet:
        return _readSuperPropertyGet();
      case Tag.SuperPropertySet:
        return _readSuperPropertySet();
      case Tag.StaticGet:
        return _readStaticGet();
      case Tag.StaticTearOff:
        return _readStaticTearOff();
      case Tag.StaticSet:
        return _readStaticSet();
      case Tag.ConstructorTearOff:
        return _readConstructorTearOff();
      case Tag.TypedefTearOff:
        return _readTypedefTearOff();
      case Tag.RedirectingFactoryTearOff:
        return _readRedirectingFactoryTearOff();
      case Tag.InstanceInvocation:
        return _readInstanceInvocation();
      case Tag.InstanceGetterInvocation:
        return _readInstanceGetterInvocation();
      case Tag.DynamicInvocation:
        return _readDynamicInvocation();
      case Tag.FunctionInvocation:
        return _readFunctionInvocation();
      case Tag.FunctionTearOff:
        return _readFunctionTearOff();
      case Tag.LocalFunctionInvocation:
        return _readLocalFunctionInvocation();
      case Tag.EqualsNull:
        return _readEqualsNull();
      case Tag.EqualsCall:
        return _readEqualsCall();
      case Tag.SuperMethodInvocation:
        return _readSuperMethodInvocation();
      case Tag.StaticInvocation:
        return _readStaticInvocation();
      case Tag.ConstStaticInvocation:
        return _readConstStaticInvocation();
      case Tag.ConstructorInvocation:
        return _readConstructorInvocation();
      case Tag.ConstConstructorInvocation:
        return _readConstConstructorInvocation();
      case Tag.Not:
        return _readNot();
      case Tag.NullCheck:
        return _readNullCheck();
      case Tag.LogicalExpression:
        return _readLogicalExpression();
      case Tag.ConditionalExpression:
        return _readConditionalExpression();
      case Tag.StringConcatenation:
        return _readStringConcatenation();
      case Tag.ListConcatenation:
        return _readListConcatenation();
      case Tag.SetConcatenation:
        return _readSetConcatenation();
      case Tag.MapConcatenation:
        return _readMapConcatenation();
      case Tag.InstanceCreation:
        return _readInstanceCreation();
      case Tag.FileUriExpression:
        return _readFileUriExpression();
      case Tag.IsExpression:
        return _readIsExpression();
      case Tag.AsExpression:
        return _readAsExpression();
      case Tag.StringLiteral:
        return _readStringLiteral();
      case Tag.SpecializedIntLiteral:
        return _readSpecializedIntLiteral(tagByte);
      case Tag.PositiveIntLiteral:
        return _readPositiveIntLiteral();
      case Tag.NegativeIntLiteral:
        return _readNegativeIntLiteral();
      case Tag.BigIntLiteral:
        return _readBigIntLiteral();
      case Tag.DoubleLiteral:
        return _readDoubleLiteral();
      case Tag.TrueLiteral:
        return _readTrueLiteral();
      case Tag.FalseLiteral:
        return _readFalseLiteral();
      case Tag.NullLiteral:
        return _readNullLiteral();
      case Tag.SymbolLiteral:
        return _readSymbolLiteral();
      case Tag.TypeLiteral:
        return _readTypeLiteral();
      case Tag.ThisExpression:
        return _readThisLiteral();
      case Tag.Rethrow:
        return _readRethrow();
      case Tag.Throw:
        return _readThrow();
      case Tag.ListLiteral:
        return _readListLiteral();
      case Tag.ConstListLiteral:
        return _readConstListLiteral();
      case Tag.SetLiteral:
        return _readSetLiteral();
      case Tag.ConstSetLiteral:
        return _readConstSetLiteral();
      case Tag.MapLiteral:
        return _readMapLiteral();
      case Tag.ConstMapLiteral:
        return _readConstMapLiteral();
      case Tag.AwaitExpression:
        return _readAwaitExpression();
      case Tag.FunctionExpression:
        return _readFunctionExpression();
      case Tag.Let:
        return _readLet();
      case Tag.BlockExpression:
        return _readBlockExpression();
      case Tag.Instantiation:
        return _readInstantiation();
      case Tag.ConstantExpression:
        return _readConstantExpression();
      default:
        throw fail('unexpected expression tag: $tag');
    }
  }

  Expression _readLoadLibrary() {
    return new LoadLibrary(readLibraryDependencyReference());
  }

  Expression _readCheckLibraryIsLoaded() {
    return new CheckLibraryIsLoaded(readLibraryDependencyReference());
  }

  Expression _readInvalidExpression() {
    int offset = readOffset();
    return new InvalidExpression(
        readStringOrNullIfEmpty(), readExpressionOption())
      ..fileOffset = offset;
  }

  Expression _readVariableGet() {
    int offset = readOffset();
    readUInt30(); // offset of the variable declaration in the binary.
    return new VariableGet(readVariableReference(), readDartTypeOption())
      ..fileOffset = offset;
  }

  Expression _readSpecializedVariableGet(int tagByte) {
    int index = tagByte & Tag.SpecializedPayloadMask;
    int offset = readOffset();
    readUInt30(); // offset of the variable declaration in the binary.
    return new VariableGet(variableStack[index])..fileOffset = offset;
  }

  Expression _readVariableSet() {
    int offset = readOffset();
    readUInt30(); // offset of the variable declaration in the binary.
    return new VariableSet(readVariableReference(), readExpression())
      ..fileOffset = offset;
  }

  Expression _readSpecializedVariableSet(int tagByte) {
    int index = tagByte & Tag.SpecializedPayloadMask;
    int offset = readOffset();
    readUInt30(); // offset of the variable declaration in the binary.
    return new VariableSet(variableStack[index], readExpression())
      ..fileOffset = offset;
  }

  Expression _readInstanceGet() {
    InstanceAccessKind kind = InstanceAccessKind.values[readByte()];
    int offset = readOffset();
    return new InstanceGet.byReference(kind, readExpression(), readName(),
        resultType: readDartType(),
        interfaceTargetReference: readNonNullInstanceMemberReference())
      ..fileOffset = offset;
  }

  Expression _readInstanceTearOff() {
    InstanceAccessKind kind = InstanceAccessKind.values[readByte()];
    int offset = readOffset();
    return new InstanceTearOff.byReference(kind, readExpression(), readName(),
        resultType: readDartType(),
        interfaceTargetReference: readNonNullInstanceMemberReference())
      ..fileOffset = offset;
  }

  Expression _readDynamicGet() {
    DynamicAccessKind kind = DynamicAccessKind.values[readByte()];
    int offset = readOffset();
    return new DynamicGet(kind, readExpression(), readName())
      ..fileOffset = offset;
  }

  Expression _readInstanceSet() {
    InstanceAccessKind kind = InstanceAccessKind.values[readByte()];
    int offset = readOffset();
    return new InstanceSet.byReference(
        kind, readExpression(), readName(), readExpression(),
        interfaceTargetReference: readNonNullInstanceMemberReference())
      ..fileOffset = offset;
  }

  Expression _readDynamicSet() {
    DynamicAccessKind kind = DynamicAccessKind.values[readByte()];
    int offset = readOffset();
    return new DynamicSet(kind, readExpression(), readName(), readExpression())
      ..fileOffset = offset;
  }

  Expression _readSuperPropertyGet() {
    int offset = readOffset();
    addTransformerFlag(TransformerFlag.superCalls);
    return new SuperPropertyGet.byReference(
        readName(), readNullableInstanceMemberReference())
      ..fileOffset = offset;
  }

  Expression _readSuperPropertySet() {
    int offset = readOffset();
    addTransformerFlag(TransformerFlag.superCalls);
    return new SuperPropertySet.byReference(
        readName(), readExpression(), readNullableInstanceMemberReference())
      ..fileOffset = offset;
  }

  Expression _readStaticGet() {
    int offset = readOffset();
    return new StaticGet.byReference(readNonNullMemberReference())
      ..fileOffset = offset;
  }

  Expression _readConstructorTearOff() {
    int offset = readOffset();
    Reference constructorReference = readNonNullMemberReference();
    return new ConstructorTearOff.byReference(constructorReference)
      ..fileOffset = offset;
  }

  Expression _readTypedefTearOff() {
    List<TypeParameter> typeParameters = readAndPushTypeParameterList();
    Expression expression = readExpression();
    List<DartType> typeArguments = readDartTypeList();
    typeParameterStack.length -= typeParameters.length;
    return new TypedefTearOff(typeParameters, expression, typeArguments);
  }

  Expression _readRedirectingFactoryTearOff() {
    int offset = readOffset();
    Reference constructorReference = readNonNullMemberReference();
    return new RedirectingFactoryTearOff.byReference(constructorReference)
      ..fileOffset = offset;
  }

  Expression _readStaticTearOff() {
    int offset = readOffset();
    return new StaticTearOff.byReference(readNonNullMemberReference())
      ..fileOffset = offset;
  }

  Expression _readStaticSet() {
    int offset = readOffset();
    return new StaticSet.byReference(
        readNonNullMemberReference(), readExpression())
      ..fileOffset = offset;
  }

  Expression _readInstanceInvocation() {
    InstanceAccessKind kind = InstanceAccessKind.values[readByte()];
    int flags = readByte();
    int offset = readOffset();
    return new InstanceInvocation.byReference(
        kind, readExpression(), readName(), readArguments(),
        functionType: readDartType() as FunctionType,
        interfaceTargetReference: readNonNullInstanceMemberReference())
      ..fileOffset = offset
      ..flags = flags;
  }

  Expression _readInstanceGetterInvocation() {
    InstanceAccessKind kind = InstanceAccessKind.values[readByte()];
    int flags = readByte();
    int offset = readOffset();
    Expression receiver = readExpression();
    Name name = readName();
    Arguments arguments = readArguments();
    DartType functionType = readDartType();
    // `const DynamicType()` is used to encode a missing function type.
    assert(functionType is FunctionType || functionType is DynamicType,
        "Unexpected function type $functionType for InstanceGetterInvocation");
    Reference interfaceTargetReference = readNonNullInstanceMemberReference();
    return new InstanceGetterInvocation.byReference(
        kind, receiver, name, arguments,
        functionType: functionType is FunctionType ? functionType : null,
        interfaceTargetReference: interfaceTargetReference)
      ..fileOffset = offset
      ..flags = flags;
  }

  Expression _readDynamicInvocation() {
    DynamicAccessKind kind = DynamicAccessKind.values[readByte()];
    int offset = readOffset();
    return new DynamicInvocation(
        kind, readExpression(), readName(), readArguments())
      ..fileOffset = offset;
  }

  Expression _readFunctionInvocation() {
    FunctionAccessKind kind = FunctionAccessKind.values[readByte()];
    int offset = readOffset();
    Expression receiver = readExpression();
    Arguments arguments = readArguments();
    DartType functionType = readDartType();
    // `const DynamicType()` is used to encode a missing function type.
    assert(functionType is FunctionType || functionType is DynamicType,
        "Unexpected function type $functionType for FunctionInvocation");
    return new FunctionInvocation(kind, receiver, arguments,
        functionType: functionType is FunctionType ? functionType : null)
      ..fileOffset = offset;
  }

  Expression _readFunctionTearOff() {
    int offset = readOffset();
    return new FunctionTearOff(readExpression())..fileOffset = offset;
  }

  Expression _readLocalFunctionInvocation() {
    int offset = readOffset();
    readUInt30(); // offset of the variable declaration in the binary.
    VariableDeclaration variable = readVariableReference();
    return new LocalFunctionInvocation(variable, readArguments(),
        functionType: readDartType() as FunctionType)
      ..fileOffset = offset;
  }

  Expression _readEqualsNull() {
    int offset = readOffset();
    return new EqualsNull(readExpression())..fileOffset = offset;
  }

  Expression _readEqualsCall() {
    int offset = readOffset();
    return new EqualsCall.byReference(readExpression(), readExpression(),
        functionType: readDartType() as FunctionType,
        interfaceTargetReference: readNonNullInstanceMemberReference())
      ..fileOffset = offset;
  }

  Expression _readSuperMethodInvocation() {
    int offset = readOffset();
    addTransformerFlag(TransformerFlag.superCalls);
    return new SuperMethodInvocation.byReference(
        readName(), readArguments(), readNullableInstanceMemberReference())
      ..fileOffset = offset;
  }

  Expression _readStaticInvocation() {
    int offset = readOffset();
    return new StaticInvocation.byReference(
        readNonNullMemberReference(), readArguments(),
        isConst: false)
      ..fileOffset = offset;
  }

  Expression _readConstStaticInvocation() {
    int offset = readOffset();
    return new StaticInvocation.byReference(
        readNonNullMemberReference(), readArguments(),
        isConst: true)
      ..fileOffset = offset;
  }

  Expression _readConstructorInvocation() {
    int offset = readOffset();
    return new ConstructorInvocation.byReference(
        readNonNullMemberReference(), readArguments(),
        isConst: false)
      ..fileOffset = offset;
  }

  Expression _readConstConstructorInvocation() {
    int offset = readOffset();
    return new ConstructorInvocation.byReference(
        readNonNullMemberReference(), readArguments(),
        isConst: true)
      ..fileOffset = offset;
  }

  Expression _readNot() {
    return new Not(readExpression());
  }

  Expression _readNullCheck() {
    int offset = readOffset();
    return new NullCheck(readExpression())..fileOffset = offset;
  }

  Expression _readLogicalExpression() {
    return new LogicalExpression(
        readExpression(), logicalOperatorToEnum(readByte()), readExpression());
  }

  Expression _readConditionalExpression() {
    return new ConditionalExpression(
        readExpression(),
        readExpression(),
        readExpression(),
        // TODO(johnniwinther): Change this to use `readDartType`.
        readDartTypeOption()!);
  }

  Expression _readStringConcatenation() {
    int offset = readOffset();
    return new StringConcatenation(readExpressionList())..fileOffset = offset;
  }

  Expression _readListConcatenation() {
    int offset = readOffset();
    DartType typeArgument = readDartType();
    return new ListConcatenation(readExpressionList(),
        typeArgument: typeArgument)
      ..fileOffset = offset;
  }

  Expression _readSetConcatenation() {
    int offset = readOffset();
    DartType typeArgument = readDartType();
    return new SetConcatenation(readExpressionList(),
        typeArgument: typeArgument)
      ..fileOffset = offset;
  }

  Expression _readMapConcatenation() {
    int offset = readOffset();
    DartType keyType = readDartType();
    DartType valueType = readDartType();
    return new MapConcatenation(readExpressionList(),
        keyType: keyType, valueType: valueType)
      ..fileOffset = offset;
  }

  Expression _readInstanceCreation() {
    int offset = readOffset();
    Reference classReference = readNonNullClassReference();
    List<DartType> typeArguments = readDartTypeList();
    int fieldValueCount = readUInt30();
    Map<Reference, Expression> fieldValues = <Reference, Expression>{};
    for (int i = 0; i < fieldValueCount; i++) {
      final Reference fieldRef = readNonNullCanonicalNameReference().reference;
      final Expression value = readExpression();
      fieldValues[fieldRef] = value;
    }
    int assertCount = readUInt30();
    List<AssertStatement> asserts;

    if (!useGrowableLists && assertCount == 0) {
      // When lists don't have to be growable anyway, we might as well use an
      // almost constant one for the empty list.
      asserts = emptyListOfAssertStatement;
    } else {
      asserts = new List<AssertStatement>.generate(
          assertCount, (_) => readStatement() as AssertStatement,
          growable: false);
    }
    List<Expression> unusedArguments = readExpressionList();
    return new InstanceCreation(
        classReference, typeArguments, fieldValues, asserts, unusedArguments)
      ..fileOffset = offset;
  }

  Expression _readFileUriExpression() {
    Uri fileUri = readUriReference();
    int offset = readOffset();
    return new FileUriExpression(readExpression(), fileUri)
      ..fileOffset = offset;
  }

  Expression _readIsExpression() {
    int offset = readOffset();
    int flags = readByte();
    return new IsExpression(readExpression(), readDartType())
      ..fileOffset = offset
      ..flags = flags;
  }

  Expression _readAsExpression() {
    int offset = readOffset();
    int flags = readByte();
    return new AsExpression(readExpression(), readDartType())
      ..fileOffset = offset
      ..flags = flags;
  }

  Expression _readStringLiteral() {
    return new StringLiteral(readStringReference());
  }

  Expression _readSpecializedIntLiteral(int tagByte) {
    int biasedValue = tagByte & Tag.SpecializedPayloadMask;
    return new IntLiteral(biasedValue - Tag.SpecializedIntLiteralBias);
  }

  Expression _readPositiveIntLiteral() {
    return new IntLiteral(readUInt30());
  }

  Expression _readNegativeIntLiteral() {
    return new IntLiteral(-readUInt30());
  }

  Expression _readBigIntLiteral() {
    return new IntLiteral(int.parse(readStringReference()));
  }

  Expression _readDoubleLiteral() {
    return new DoubleLiteral(readDouble());
  }

  Expression _readTrueLiteral() {
    return new BoolLiteral(true);
  }

  Expression _readFalseLiteral() {
    return new BoolLiteral(false);
  }

  Expression _readNullLiteral() {
    return new NullLiteral();
  }

  Expression _readSymbolLiteral() {
    return new SymbolLiteral(readStringReference());
  }

  Expression _readTypeLiteral() {
    return new TypeLiteral(readDartType());
  }

  Expression _readThisLiteral() {
    return new ThisExpression();
  }

  Expression _readRethrow() {
    int offset = readOffset();
    return new Rethrow()..fileOffset = offset;
  }

  Expression _readThrow() {
    int offset = readOffset();
    return new Throw(readExpression())..fileOffset = offset;
  }

  Expression _readListLiteral() {
    int offset = readOffset();
    DartType typeArgument = readDartType();
    return new ListLiteral(readExpressionList(),
        typeArgument: typeArgument, isConst: false)
      ..fileOffset = offset;
  }

  Expression _readConstListLiteral() {
    int offset = readOffset();
    DartType typeArgument = readDartType();
    return new ListLiteral(readExpressionList(),
        typeArgument: typeArgument, isConst: true)
      ..fileOffset = offset;
  }

  Expression _readSetLiteral() {
    int offset = readOffset();
    DartType typeArgument = readDartType();
    return new SetLiteral(readExpressionList(),
        typeArgument: typeArgument, isConst: false)
      ..fileOffset = offset;
  }

  Expression _readConstSetLiteral() {
    int offset = readOffset();
    DartType typeArgument = readDartType();
    return new SetLiteral(readExpressionList(),
        typeArgument: typeArgument, isConst: true)
      ..fileOffset = offset;
  }

  Expression _readMapLiteral() {
    int offset = readOffset();
    DartType keyType = readDartType();
    DartType valueType = readDartType();
    return new MapLiteral(readMapLiteralEntryList(),
        keyType: keyType, valueType: valueType, isConst: false)
      ..fileOffset = offset;
  }

  Expression _readConstMapLiteral() {
    int offset = readOffset();
    DartType keyType = readDartType();
    DartType valueType = readDartType();
    return new MapLiteral(readMapLiteralEntryList(),
        keyType: keyType, valueType: valueType, isConst: true)
      ..fileOffset = offset;
  }

  Expression _readAwaitExpression() {
    return new AwaitExpression(readExpression());
  }

  Expression _readFunctionExpression() {
    int offset = readOffset();
    return new FunctionExpression(readFunctionNode())..fileOffset = offset;
  }

  Expression _readLet() {
    int offset = readOffset();
    VariableDeclaration variable = readVariableDeclaration();
    int stackHeight = variableStack.length;
    pushVariableDeclaration(variable);
    Expression body = readExpression();
    variableStack.length = stackHeight;
    return new Let(variable, body)..fileOffset = offset;
  }

  Expression _readBlockExpression() {
    int stackHeight = variableStack.length;
    List<Statement> statements = readStatementListAlwaysGrowable();
    Expression value = readExpression();
    variableStack.length = stackHeight;
    return new BlockExpression(new Block(statements), value);
  }

  Expression _readInstantiation() {
    Expression expression = readExpression();
    List<DartType> typeArguments = readDartTypeList();
    return new Instantiation(expression, typeArguments);
  }

  Expression _readConstantExpression() {
    int offset = readOffset();
    DartType type = readDartType();
    Constant constant = readConstantReference();
    return new ConstantExpression(constant, type)..fileOffset = offset;
  }

  List<MapLiteralEntry> readMapLiteralEntryList() {
    int length = readUInt30();
    if (!useGrowableLists && length == 0) {
      // When lists don't have to be growable anyway, we might as well use an
      // almost constant one for the empty list.
      return emptyListOfMapLiteralEntry;
    }
    return new List<MapLiteralEntry>.generate(length, (_) => readMapEntry(),
        growable: useGrowableLists);
  }

  MapLiteralEntry readMapEntry() {
    return new MapLiteralEntry(readExpression(), readExpression());
  }

  List<Statement> readStatementList() {
    int length = readUInt30();
    if (!useGrowableLists && length == 0) {
      // When lists don't have to be growable anyway, we might as well use an
      // almost constant one for the empty list.
      return emptyListOfStatement;
    }
    return new List<Statement>.generate(length, (_) => readStatement(),
        growable: useGrowableLists);
  }

  List<Statement> readStatementListAlwaysGrowable() {
    int length = readUInt30();
    return new List<Statement>.generate(length, (_) => readStatement(),
        growable: true);
  }

  Statement? readStatementOrNullIfEmpty() {
    Statement node = readStatement();
    if (node is EmptyStatement) {
      return null;
    } else {
      return node;
    }
  }

  Statement? readStatementOption() {
    return readAndCheckOptionTag() ? readStatement() : null;
  }

  Statement readStatement() {
    int tag = readByte();
    switch (tag) {
      case Tag.ExpressionStatement:
        return _readExpressionStatement();
      case Tag.Block:
        return _readBlock();
      case Tag.AssertBlock:
        return _readAssertBlock();
      case Tag.EmptyStatement:
        return _readEmptyStatement();
      case Tag.AssertStatement:
        return _readAssertStatement();
      case Tag.LabeledStatement:
        return _readLabeledStatement();
      case Tag.BreakStatement:
        return _readBreakStatement();
      case Tag.WhileStatement:
        return _readWhileStatement();
      case Tag.DoStatement:
        return _readDoStatement();
      case Tag.ForStatement:
        return _readForStatement();
      case Tag.ForInStatement:
      case Tag.AsyncForInStatement:
        return _readForInStatement(tag);
      case Tag.SwitchStatement:
        return _readSwitchStatement();
      case Tag.ContinueSwitchStatement:
        return _readContinueSwitchStatement();
      case Tag.IfStatement:
        return _readIfStatement();
      case Tag.ReturnStatement:
        return _readReturnStatement();
      case Tag.TryCatch:
        return _readTryCatch();
      case Tag.TryFinally:
        return _readTryFinally();
      case Tag.YieldStatement:
        return _readYieldStatement();
      case Tag.VariableDeclaration:
        return _readVariableDeclaration();
      case Tag.FunctionDeclaration:
        return _readFunctionDeclaration();
      default:
        throw fail('unexpected statement tag: $tag');
    }
  }

  Statement _readExpressionStatement() {
    return new ExpressionStatement(readExpression());
  }

  Statement _readEmptyStatement() {
    return new EmptyStatement();
  }

  Statement _readAssertStatement() {
    return new AssertStatement(readExpression(),
        conditionStartOffset: readOffset(),
        conditionEndOffset: readOffset(),
        message: readExpressionOption());
  }

  Statement _readLabeledStatement() {
    LabeledStatement label = new LabeledStatement(null);
    labelStack.add(label);
    label.body = readStatement()..parent = label;
    labelStack.removeLast();
    return label;
  }

  Statement _readBreakStatement() {
    int offset = readOffset();
    int index = readUInt30();
    return new BreakStatement(labelStack[labelStackBase + index])
      ..fileOffset = offset;
  }

  Statement _readWhileStatement() {
    int offset = readOffset();
    return new WhileStatement(readExpression(), readStatement())
      ..fileOffset = offset;
  }

  Statement _readDoStatement() {
    int offset = readOffset();
    return new DoStatement(readStatement(), readExpression())
      ..fileOffset = offset;
  }

  Statement _readForStatement() {
    int variableStackHeight = variableStack.length;
    int offset = readOffset();
    List<VariableDeclaration> variables = readAndPushVariableDeclarationList();
    Expression? condition = readExpressionOption();
    List<Expression> updates = readExpressionList();
    Statement body = readStatement();
    variableStack.length = variableStackHeight;
    return new ForStatement(variables, condition, updates, body)
      ..fileOffset = offset;
  }

  Statement _readForInStatement(int tag) {
    bool isAsync = tag == Tag.AsyncForInStatement;
    int variableStackHeight = variableStack.length;
    int offset = readOffset();
    int bodyOffset = readOffset();
    VariableDeclaration variable = readAndPushVariableDeclaration();
    Expression iterable = readExpression();
    Statement body = readStatement();
    variableStack.length = variableStackHeight;
    return new ForInStatement(variable, iterable, body, isAsync: isAsync)
      ..fileOffset = offset
      ..bodyOffset = bodyOffset;
  }

  Statement _readSwitchStatement() {
    int offset = readOffset();
    Expression expression = readExpression();
    int count = readUInt30();
    List<SwitchCase> cases;
    if (!useGrowableLists && count == 0) {
      // When lists don't have to be growable anyway, we might as well use an
      // almost constant one for the empty list.
      cases = emptyListOfSwitchCase;
    } else {
      cases = new List<SwitchCase>.generate(
          count,
          (_) => new SwitchCase(<Expression>[], <int>[], dummyStatement,
              isDefault: false),
          growable: useGrowableLists);
    }
    switchCaseStack.addAll(cases);
    for (int i = 0; i < cases.length; ++i) {
      _readSwitchCaseInto(cases[i]);
    }
    switchCaseStack.length -= count;
    return new SwitchStatement(expression, cases)..fileOffset = offset;
  }

  Statement _readContinueSwitchStatement() {
    int offset = readOffset();
    int index = readUInt30();
    return new ContinueSwitchStatement(
        switchCaseStack[switchCaseStackBase + index])
      ..fileOffset = offset;
  }

  Statement _readIfStatement() {
    int offset = readOffset();
    return new IfStatement(
        readExpression(), readStatement(), readStatementOrNullIfEmpty())
      ..fileOffset = offset;
  }

  Statement _readReturnStatement() {
    int offset = readOffset();
    return new ReturnStatement(readExpressionOption())..fileOffset = offset;
  }

  Statement _readTryCatch() {
    Statement body = readStatement();
    int flags = readByte();
    return new TryCatch(body, readCatchList(), isSynthetic: flags & 2 == 2);
  }

  Statement _readTryFinally() {
    return new TryFinally(readStatement(), readStatement());
  }

  Statement _readYieldStatement() {
    int offset = readOffset();
    int flags = readByte();
    return new YieldStatement(readExpression(),
        isYieldStar: flags & YieldStatement.FlagYieldStar != 0,
        isNative: flags & YieldStatement.FlagNative != 0)
      ..fileOffset = offset;
  }

  Statement _readVariableDeclaration() {
    VariableDeclaration variable = readVariableDeclaration();
    variableStack.add(variable); // Will be popped by the enclosing scope.
    return variable;
  }

  Statement _readFunctionDeclaration() {
    int offset = readOffset();
    VariableDeclaration variable = readVariableDeclaration();
    variableStack.add(variable); // Will be popped by the enclosing scope.
    return new FunctionDeclaration(variable, readFunctionNode())
      ..fileOffset = offset;
  }

  void _readSwitchCaseInto(SwitchCase caseNode) {
    int length = readUInt30();
    for (int i = 0; i < length; ++i) {
      caseNode.expressionOffsets.add(readOffset());
      caseNode.expressions.add(readExpression()..parent = caseNode);
    }
    caseNode.isDefault = readByte() == 1;
    caseNode.body = readStatement()..parent = caseNode;
  }

  List<Catch> readCatchList() {
    int length = readUInt30();
    if (!useGrowableLists && length == 0) {
      // When lists don't have to be growable anyway, we might as well use an
      // almost constant one for the empty list.
      return emptyListOfCatch;
    }
    return new List<Catch>.generate(length, (_) => readCatch(),
        growable: useGrowableLists);
  }

  Catch readCatch() {
    int variableStackHeight = variableStack.length;
    int offset = readOffset();
    DartType guard = readDartType();
    VariableDeclaration? exception = readAndPushVariableDeclarationOption();
    VariableDeclaration? stackTrace = readAndPushVariableDeclarationOption();
    Statement body = readStatement();
    variableStack.length = variableStackHeight;
    return new Catch(exception, body, guard: guard, stackTrace: stackTrace)
      ..fileOffset = offset;
  }

  Block _readBlock() {
    int stackHeight = variableStack.length;
    int offset = readOffset();
    int endOffset = readOffset();
    List<Statement> body = readStatementListAlwaysGrowable();
    variableStack.length = stackHeight;
    return new Block(body)
      ..fileOffset = offset
      ..fileEndOffset = endOffset;
  }

  AssertBlock _readAssertBlock() {
    int stackHeight = variableStack.length;
    List<Statement> body = readStatementListAlwaysGrowable();
    variableStack.length = stackHeight;
    return new AssertBlock(body);
  }

  Supertype readSupertype() {
    InterfaceType type = readDartType(forSupertype: true) as InterfaceType;
    assert(
        type.nullability == _currentLibrary!.nonNullable,
        "In serialized form supertypes should have Nullability.legacy if they "
        "are in a library that is opted out of the NNBD feature.  If they are "
        "in an opted-in library, they should have Nullability.nonNullable.");
    return new Supertype.byReference(type.className, type.typeArguments);
  }

  Supertype? readSupertypeOption() {
    return readAndCheckOptionTag() ? readSupertype() : null;
  }

  List<Supertype> readSupertypeList([List<Supertype>? result]) {
    int length = readUInt30();
    if (!useGrowableLists && length == 0) {
      // When lists don't have to be growable anyway, we might as well use an
      // almost constant one for the empty list.
      return emptyListOfSupertype;
    }
    if (result != null) {
      for (int i = 0; i < length; ++i) {
        result.add(readSupertype());
      }
      return result;
    } else {
      return new List<Supertype>.generate(length, (_) => readSupertype(),
          growable: useGrowableLists);
    }
  }

  List<DartType> readDartTypeList() {
    int length = readUInt30();
    if (!useGrowableLists && length == 0) {
      // When lists don't have to be growable anyway, we might as well use an
      // almost constant one for the empty list.
      return emptyListOfDartType;
    }
    return new List<DartType>.generate(length, (_) => readDartType(),
        growable: useGrowableLists);
  }

  List<NamedType> readNamedTypeList() {
    int length = readUInt30();
    if (!useGrowableLists && length == 0) {
      // When lists don't have to be growable anyway, we might as well use a
      // constant one for the empty list.
      return emptyListOfNamedType;
    }
    return new List<NamedType>.generate(length, (_) => readNamedType(),
        growable: useGrowableLists);
  }

  NamedType readNamedType() {
    String name = readStringReference();
    DartType type = readDartType();
    int flags = readByte();
    return new NamedType(name, type,
        isRequired: (flags & NamedType.FlagRequiredNamedType) != 0);
  }

  DartType? readDartTypeOption() {
    return readAndCheckOptionTag() ? readDartType() : null;
  }

  DartType readDartType({bool forSupertype: false}) {
    int tag = readByte();
    switch (tag) {
      case Tag.TypedefType:
        return _readTypedefType();
      case Tag.InvalidType:
        return _readInvalidType();
      case Tag.DynamicType:
        return _readDynamicType();
      case Tag.VoidType:
        return _readVoidType();
      case Tag.NeverType:
        return _readNeverType();
      case Tag.InterfaceType:
        return _readInterfaceType();
      case Tag.SimpleInterfaceType:
        return _readSimpleInterfaceType(forSupertype);
      case Tag.FunctionType:
        return _readFunctionType();
      case Tag.SimpleFunctionType:
        return _readSimpleFunctionType();
      case Tag.TypeParameterType:
        return _readTypeParameterType();
      default:
        throw fail('unexpected dart type tag: $tag');
    }
  }

  DartType _readTypedefType() {
    int nullabilityIndex = readByte();
    return new TypedefType.byReference(readNonNullTypedefReference(),
        Nullability.values[nullabilityIndex], readDartTypeList());
  }

  DartType _readInvalidType() {
    return const InvalidType();
  }

  DartType _readDynamicType() {
    return const DynamicType();
  }

  DartType _readVoidType() {
    return const VoidType();
  }

  DartType _readNeverType() {
    int nullabilityIndex = readByte();
    return NeverType.fromNullability(Nullability.values[nullabilityIndex]);
  }

  DartType _readInterfaceType() {
    int nullabilityIndex = readByte();
    Reference reference = readNonNullClassReference();
    List<DartType> typeArguments = readDartTypeList();
    CanonicalName? canonicalName = reference.canonicalName;
    if (canonicalName != null &&
        canonicalName.name == "FutureOr" &&
        canonicalName.parent!.name == "dart:async" &&
        canonicalName.parent!.parent != null &&
        canonicalName.parent!.parent!.isRoot) {
      return new FutureOrType(
          typeArguments.single, Nullability.values[nullabilityIndex]);
    }
    return new InterfaceType.byReference(
        reference, Nullability.values[nullabilityIndex], typeArguments);
  }

  DartType _readSimpleInterfaceType(bool forSupertype) {
    int nullabilityIndex = readByte();
    Reference classReference = readNonNullClassReference();
    CanonicalName? canonicalName = classReference.canonicalName;
    if (canonicalName != null &&
        !forSupertype &&
        canonicalName.name == "Null" &&
        canonicalName.parent!.name == "dart:core" &&
        canonicalName.parent!.parent!.isRoot) {
      return const NullType();
    }
    return new InterfaceType.byReference(classReference,
        Nullability.values[nullabilityIndex], const <DartType>[]);
  }

  DartType _readFunctionType() {
    int typeParameterStackHeight = typeParameterStack.length;
    int nullabilityIndex = readByte();
    List<TypeParameter> typeParameters = readAndPushTypeParameterList();
    int requiredParameterCount = readUInt30();
    int totalParameterCount = readUInt30();
    List<DartType> positional = readDartTypeList();
    List<NamedType> named = readNamedTypeList();
    TypedefType? typedefType = readDartTypeOption() as TypedefType?;
    assert(positional.length + named.length == totalParameterCount);
    DartType returnType = readDartType();
    typeParameterStack.length = typeParameterStackHeight;
    return new FunctionType(
        positional, returnType, Nullability.values[nullabilityIndex],
        typeParameters: typeParameters,
        requiredParameterCount: requiredParameterCount,
        namedParameters: named,
        typedefType: typedefType);
  }

  DartType _readSimpleFunctionType() {
    int nullabilityIndex = readByte();
    List<DartType> positional = readDartTypeList();
    DartType returnType = readDartType();
    return new FunctionType(
        positional, returnType, Nullability.values[nullabilityIndex]);
  }

  DartType _readTypeParameterType() {
    int declaredNullabilityIndex = readByte();
    int index = readUInt30();
    DartType? bound = readDartTypeOption();
    return new TypeParameterType(typeParameterStack[index],
        Nullability.values[declaredNullabilityIndex], bound);
  }

  List<TypeParameter> readAndPushTypeParameterList(
      [List<TypeParameter>? list, TreeNode? parent]) {
    int length = readUInt30();
    if (length == 0) {
      if (list != null) return list;
      if (useGrowableLists) {
        return <TypeParameter>[];
      } else {
        return emptyListOfTypeParameter;
      }
    }
    if (list == null) {
      list = new List<TypeParameter>.generate(
          length, (_) => new TypeParameter(null, null)..parent = parent,
          growable: useGrowableLists);
    } else if (list.length != length) {
      for (int i = 0; i < length; ++i) {
        list.add(new TypeParameter(null, null)..parent = parent);
      }
    }
    typeParameterStack.addAll(list);
    for (int i = 0; i < list.length; ++i) {
      readTypeParameter(list[i]);
    }
    return list;
  }

  void readTypeParameter(TypeParameter node) {
    node.flags = readByte();
    node.annotations = readAnnotationList(node);
    int variance = readByte();
    if (variance == TypeParameter.legacyCovariantSerializationMarker) {
      node.variance = null;
    } else {
      node.variance = variance;
    }
    node.name = readStringOrNullIfEmpty();
    node.bound = readDartType();
    node.defaultType = readDartType();
  }

  Arguments readArguments() {
    int numArguments = readUInt30();
    List<DartType> typeArguments = readDartTypeList();
    List<Expression> positional = readExpressionList();
    List<NamedExpression> named = readNamedExpressionList();
    assert(numArguments == positional.length + named.length);
    return new Arguments(positional, types: typeArguments, named: named);
  }

  List<NamedExpression> readNamedExpressionList() {
    int length = readUInt30();
    if (!useGrowableLists && length == 0) {
      // When lists don't have to be growable anyway, we might as well use an
      // almost-constant one for the empty list.
      return emptyListOfNamedExpression;
    }
    return new List<NamedExpression>.generate(
        length, (_) => readNamedExpression(),
        growable: useGrowableLists);
  }

  NamedExpression readNamedExpression() {
    return new NamedExpression(readStringReference(), readExpression());
  }

  List<VariableDeclaration> readAndPushVariableDeclarationList() {
    int length = readUInt30();
    if (!useGrowableLists && length == 0) {
      // When lists don't have to be growable anyway, we might as well use an
      // almost constant one for the empty list.
      return emptyListOfVariableDeclaration;
    }
    return new List<VariableDeclaration>.generate(
        length, (_) => readAndPushVariableDeclaration(),
        growable: useGrowableLists);
  }

  VariableDeclaration? readAndPushVariableDeclarationOption() {
    return readAndCheckOptionTag() ? readAndPushVariableDeclaration() : null;
  }

  VariableDeclaration readAndPushVariableDeclaration() {
    VariableDeclaration variable = readVariableDeclaration();
    variableStack.add(variable);
    return variable;
  }

  VariableDeclaration readVariableDeclaration() {
    int offset = readOffset();
    int fileEqualsOffset = readOffset();
    // The [VariableDeclaration] instance is not created at this point yet,
    // so `null` is temporarily set as the parent of the annotation nodes.
    List<Expression> annotations = readAnnotationList(null);
    int flags = readByte();
    VariableDeclaration node = new VariableDeclaration(
        readStringOrNullIfEmpty(),
        type: readDartType(),
        initializer: readExpressionOption(),
        flags: flags)
      ..fileOffset = offset
      ..fileEqualsOffset = fileEqualsOffset;
    if (annotations.isNotEmpty) {
      for (int i = 0; i < annotations.length; ++i) {
        Expression annotation = annotations[i];
        annotation.parent = node;
      }
      node.annotations = annotations;
    }
    return node;
  }

  int readOffset() {
    // Offset is saved as unsigned,
    // but actually ranges from -1 and up (thus the -1)
    return readUInt30() - 1;
  }
}

class BinaryBuilderWithMetadata extends BinaryBuilder implements BinarySource {
  /// List of metadata subsections that have corresponding [MetadataRepository]
  /// and are awaiting to be parsed and attached to nodes.
  List<_MetadataSubsection>? _subsections;

  BinaryBuilderWithMetadata(List<int> bytes,
      {String? filename,
      bool disableLazyReading = false,
      bool disableLazyClassReading = false,
      bool? alwaysCreateNewNamedNodes})
      : super(bytes,
            filename: filename,
            disableLazyReading: disableLazyReading,
            disableLazyClassReading: disableLazyClassReading,
            alwaysCreateNewNamedNodes: alwaysCreateNewNamedNodes);

  @override
  void _readMetadataMappings(
      Component component, int binaryOffsetForMetadataPayloads) {
    // At the beginning of this function _byteOffset points right past
    // metadataMappings to string table.

    // Read the length of metadataMappings.
    _byteOffset -= 4;
    final int subSectionCount = readUint32();

    int endOffset = _byteOffset - 4; // End offset of the current subsection.
    for (int i = 0; i < subSectionCount; i++) {
      // RList<Pair<UInt32, UInt32>> nodeOffsetToMetadataOffset
      _byteOffset = endOffset - 4;
      final int mappingLength = readUint32();
      final int mappingStart = (endOffset - 4) - 4 * 2 * mappingLength;
      _byteOffset = mappingStart - 4;

      // UInt32 tag (fixed size StringReference)
      final String tag = _stringTable[readUint32()];

      final MetadataRepository<dynamic>? repository = component.metadata[tag];
      if (repository != null) {
        // Read nodeOffsetToMetadataOffset mapping.
        final Map<int, int> mapping = <int, int>{};
        _byteOffset = mappingStart;
        for (int j = 0; j < mappingLength; j++) {
          final int nodeOffset = readUint32();
          final int metadataOffset =
              binaryOffsetForMetadataPayloads + readUint32();
          mapping[nodeOffset] = metadataOffset;
        }

        (_subsections ??= <_MetadataSubsection>[])
            .add(new _MetadataSubsection(repository, mapping));
      }

      // Start of the subsection and the end of the previous one.
      endOffset = mappingStart - 4;
    }
  }

  Object _readMetadata(Node node, MetadataRepository repository, int offset) {
    final int savedOffset = _byteOffset;
    _byteOffset = offset;

    final Object metadata = repository.readFromBinary(node, this);

    _byteOffset = savedOffset;
    return metadata;
  }

  @override
  void enterScope({List<TypeParameter>? typeParameters}) {
    if (typeParameters != null) {
      typeParameterStack.addAll(typeParameters);
    }
  }

  @override
  void leaveScope({List<TypeParameter>? typeParameters}) {
    if (typeParameters != null) {
      typeParameterStack.length -= typeParameters.length;
    }
  }

  @override
  T _associateMetadata<T extends Node>(T node, int nodeOffset) {
    if (_subsections == null) {
      return node;
    }

    for (_MetadataSubsection subsection in _subsections!) {
      // First check if there is any metadata associated with this node.
      final int? metadataOffset = subsection.mapping[nodeOffset];
      if (metadataOffset != null) {
        subsection.repository.mapping[node] =
            _readMetadata(node, subsection.repository, metadataOffset);
      }
    }

    return node;
  }

  @override
  DartType readDartType({bool forSupertype = false}) {
    final int nodeOffset = _byteOffset;
    final DartType result = super.readDartType(forSupertype: forSupertype);
    return _associateMetadata(result, nodeOffset);
  }

  @override
  Library readLibrary(Component component, int endOffset) {
    final int nodeOffset = _byteOffset;
    final Library result = super.readLibrary(component, endOffset);
    return _associateMetadata(result, nodeOffset);
  }

  @override
  Typedef readTypedef() {
    final int nodeOffset = _byteOffset;
    final Typedef result = super.readTypedef();
    return _associateMetadata(result, nodeOffset);
  }

  @override
  Class readClass(int endOffset) {
    final int nodeOffset = _byteOffset;
    final Class result = super.readClass(endOffset);
    return _associateMetadata(result, nodeOffset);
  }

  @override
  Extension readExtension() {
    final int nodeOffset = _byteOffset;
    final Extension result = super.readExtension();
    return _associateMetadata(result, nodeOffset);
  }

  @override
  Field readField() {
    final int nodeOffset = _byteOffset;
    final Field result = super.readField();
    return _associateMetadata(result, nodeOffset);
  }

  @override
  Constructor readConstructor() {
    final int nodeOffset = _byteOffset;
    final Constructor result = super.readConstructor();
    return _associateMetadata(result, nodeOffset);
  }

  @override
  Procedure readProcedure(int endOffset) {
    final int nodeOffset = _byteOffset;
    final Procedure result = super.readProcedure(endOffset);
    return _associateMetadata(result, nodeOffset);
  }

  @override
  RedirectingFactory readRedirectingFactory() {
    final int nodeOffset = _byteOffset;
    final RedirectingFactory result = super.readRedirectingFactory();
    return _associateMetadata(result, nodeOffset);
  }

  @override
  Initializer readInitializer() {
    final int nodeOffset = _byteOffset;
    final Initializer result = super.readInitializer();
    return _associateMetadata(result, nodeOffset);
  }

  @override
  FunctionNode readFunctionNode(
      {bool lazyLoadBody: false, int outerEndOffset: -1}) {
    final int nodeOffset = _byteOffset;
    final FunctionNode result = super.readFunctionNode(
        lazyLoadBody: lazyLoadBody, outerEndOffset: outerEndOffset);
    return _associateMetadata(result, nodeOffset);
  }

  @override
  Expression readExpression() {
    final int nodeOffset = _byteOffset;
    final Expression result = super.readExpression();
    return _associateMetadata(result, nodeOffset);
  }

  @override
  Arguments readArguments() {
    final int nodeOffset = _byteOffset;
    final Arguments result = super.readArguments();
    return _associateMetadata(result, nodeOffset);
  }

  @override
  NamedExpression readNamedExpression() {
    final int nodeOffset = _byteOffset;
    final NamedExpression result = super.readNamedExpression();
    return _associateMetadata(result, nodeOffset);
  }

  @override
  VariableDeclaration readVariableDeclaration() {
    final int nodeOffset = _byteOffset;
    final VariableDeclaration result = super.readVariableDeclaration();
    return _associateMetadata(result, nodeOffset);
  }

  @override
  Statement readStatement() {
    final int nodeOffset = _byteOffset;
    final Statement result = super.readStatement();
    return _associateMetadata(result, nodeOffset);
  }

  @override
  Combinator readCombinator() {
    final int nodeOffset = _byteOffset;
    final Combinator result = super.readCombinator();
    return _associateMetadata(result, nodeOffset);
  }

  @override
  LibraryDependency readLibraryDependency() {
    final int nodeOffset = _byteOffset;
    final LibraryDependency result = super.readLibraryDependency();
    return _associateMetadata(result, nodeOffset);
  }

  @override
  LibraryPart readLibraryPart() {
    final int nodeOffset = _byteOffset;
    final LibraryPart result = super.readLibraryPart();
    return _associateMetadata(result, nodeOffset);
  }

  @override
  void _readSwitchCaseInto(SwitchCase caseNode) {
    _associateMetadata(caseNode, _byteOffset);
    super._readSwitchCaseInto(caseNode);
  }

  @override
  void readTypeParameter(TypeParameter param) {
    _associateMetadata(param, _byteOffset);
    super.readTypeParameter(param);
  }

  @override
  Supertype readSupertype() {
    final int nodeOffset = _byteOffset;
    InterfaceType type =
        super.readDartType(forSupertype: true) as InterfaceType;
    return _associateMetadata(
        new Supertype.byReference(type.className, type.typeArguments),
        nodeOffset);
  }

  @override
  Name readName() {
    final int nodeOffset = _byteOffset;
    final Name result = super.readName();
    return _associateMetadata(result, nodeOffset);
  }

  @override
  int get currentOffset => _byteOffset;

  @override
  List<int> get bytes => _bytes;
}

/// Deserialized MetadataMapping corresponding to the given metadata repository.
class _MetadataSubsection {
  /// [MetadataRepository] that can read this subsection.
  final MetadataRepository repository;

  /// Deserialized mapping from node offsets to metadata offsets.
  final Map<int, int> mapping;

  _MetadataSubsection(this.repository, this.mapping);
}

/// Merges two compilation modes or throws if they are not compatible.
NonNullableByDefaultCompiledMode mergeCompilationModeOrThrow(
    NonNullableByDefaultCompiledMode? a, NonNullableByDefaultCompiledMode b) {
  if (a == null || a == b) {
    return b;
  }

  // If something is invalid, it should always merge as invalid.
  if (a == NonNullableByDefaultCompiledMode.Invalid) {
    return a;
  }
  if (b == NonNullableByDefaultCompiledMode.Invalid) {
    return b;
  }

  if (a == NonNullableByDefaultCompiledMode.Agnostic) {
    return b;
  }
  if (b == NonNullableByDefaultCompiledMode.Agnostic) {
    // Keep as-is.
    return a;
  }

  // Mixed mode where agnostic isn't involved.
  throw new CompilationModeError("Mixed compilation mode found: $a and $b");
}
