main = <No Member>;
library from "org-dartlang-test:///lib1.dart" as lib1 {
additionalExports = (main::main,
  main::Class,
  main::Extension)

  export "org-dartlang-test:///main.dart";
  import "org-dartlang-test:///main.dart";
  import "org-dartlang-test:///main.dart" as m;

  extension Extension2 on main::Class* {
    method method2 = lib1::Extension2|method2;
    tearoff method2 = lib1::Extension2|get#method2;
  }
  static method Extension2|method2(final main::Class* #this) → void {}
  static method Extension2|get#method2(final main::Class* #this) → () →* void
    return () → void => lib1::Extension2|method2(#this);
  static method lib1() → dynamic {
    main::Class* a = new main::Class::•();
    main::Extension|method(a);
    lib1::Extension2|method2(a);
  }
}
library from "org-dartlang-test:///lib2.dart" as lib2 {

  import "org-dartlang-test:///lib1.dart";
  import "org-dartlang-test:///lib1.dart" as l1;

  extension Extension3 on main::Class* {
    method method3 = lib2::Extension3|method3;
    tearoff method3 = lib2::Extension3|get#method3;
  }
  static method Extension3|method3(final main::Class* #this) → void {}
  static method Extension3|get#method3(final main::Class* #this) → () →* void
    return () → void => lib2::Extension3|method3(#this);
  static method lib2() → dynamic {
    main::Class* a = new main::Class::•();
    main::Extension|method(a);
    lib1::Extension2|method2(a);
  }
}
library from "org-dartlang-test:///main.dart" as main {

  import "org-dartlang-test:///lib1.dart";
  import "org-dartlang-test:///lib1.dart" as l1;
  import "org-dartlang-test:///lib2.dart";
  import "org-dartlang-test:///lib2.dart" as l2;

  class Class extends dart.core::Object {
    synthetic constructor •() → main::Class*
      : super dart.core::Object::•()
      ;
    abstract member-signature get _identityHashCode() → dart.core::int*;
    abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → dart.core::bool*;
    abstract member-signature method _simpleInstanceOf(dynamic type) → dart.core::bool*;
    abstract member-signature method _simpleInstanceOfTrue(dynamic type) → dart.core::bool*;
    abstract member-signature method _simpleInstanceOfFalse(dynamic type) → dart.core::bool*;
    abstract member-signature operator ==(dynamic other) → dart.core::bool*;
    abstract member-signature get hashCode() → dart.core::int*;
    abstract member-signature method toString() → dart.core::String*;
    abstract member-signature method noSuchMethod(dart.core::Invocation* invocation) → dynamic;
    abstract member-signature get runtimeType() → dart.core::Type*;
  }
  extension Extension on main::Class* {
    method method = main::Extension|method;
    tearoff method = main::Extension|get#method;
  }
  static method Extension|method(final main::Class* #this) → void {}
  static method Extension|get#method(final main::Class* #this) → () →* void
    return () → void => main::Extension|method(#this);
  static method main() → dynamic {
    main::Class* a = new main::Class::•();
    main::Extension|method(a);
    lib1::Extension2|method2(a);
    lib1::lib1();
  }
}
