[dart2bytecode] Throw exception instead of crashing when external member is called

TEST=ci

Change-Id: I60a598dd5f8ac05a4f5f3283d257c2c6a74490e1
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/384820
Reviewed-by: Slava Egorov <vegorov@google.com>
Commit-Queue: Alexander Markov <alexmarkov@google.com>
diff --git a/pkg/dart2bytecode/lib/bytecode_generator.dart b/pkg/dart2bytecode/lib/bytecode_generator.dart
index 468f8a3..66eca8d 100644
--- a/pkg/dart2bytecode/lib/bytecode_generator.dart
+++ b/pkg/dart2bytecode/lib/bytecode_generator.dart
@@ -808,7 +808,7 @@
           _genConstructorInitializers(node);
         }
         if (node.isExternal) {
-          _unimplemented(node, 'external member');
+          _genNoSuchMethodForExternal(node);
         } else {
           _generateNode(node.function?.body);
           // BytecodeAssembler eliminates this bytecode if it is unreachable.
@@ -939,6 +939,9 @@
   late Procedure throwNewAssertionError =
       libraryIndex.getProcedure('dart:core', '_AssertionError', '_throwNew');
 
+  late Procedure throwNewNoSuchMethodError =
+      libraryIndex.getProcedure('dart:core', 'NoSuchMethodError', '_throwNew');
+
   late Procedure allocateInvocationMirror = libraryIndex.getProcedure(
       'dart:core', '_InvocationMirror', '_allocateInvocationMirror');
 
@@ -2726,6 +2729,22 @@
     _genDirectCall(target, objectTable.getArgDescHandle(2), 2);
   }
 
+  void _genNoSuchMethodForExternal(Member node) {
+    if (node.isInstanceMember) {
+      _genPushReceiver(); // receiver.
+    } else {
+      asm.emitPushNull();
+    }
+    asm.emitPushConstant(cp.addString(node.name.text)); // memberName.
+    asm.emitPushInt(0); // invocationType.
+    asm.emitPushInt(0); // typeArgumentsLength.
+    asm.emitPushNull(); // typeArguments.
+    asm.emitPushNull(); // arguments.
+    asm.emitPushNull(); // argumentNames.
+    _genDirectCall(
+        throwNewNoSuchMethodError, objectTable.getArgDescHandle(7), 7);
+  }
+
   @override
   void defaultTreeNode(Node node) => throw new UnsupportedOperationError(
       'Unsupported node ${node.runtimeType}');
@@ -4433,12 +4452,6 @@
       throw 'Unexpected ${enclosingFunction!.dartAsyncMarker}';
     }
   }
-
-  void _unimplemented(TreeNode node, String what) {
-    print('Unimplemented $what at ${node.location}');
-    asm.emitTrap();
-    asm.isUnreachable = false;
-  }
 }
 
 class UnsupportedOperationError {
diff --git a/tests/language/language.status b/tests/language/language.status
index c4008bd..e07152f 100644
--- a/tests/language/language.status
+++ b/tests/language/language.status
@@ -33,8 +33,6 @@
 [ $compiler == dart2bytecode ]
 class_modifiers/trans_legacy/legacy_superdeclaration_test: Crash
 const/inference_test: Crash
-constructor/external_constructor_test: Crash
-external_abstract_fields/external_fields_test: Crash
 final/syntax_test/08: Crash
 regress/regress45763_test: Crash
 vm/reflect_core_vm_test: Crash