[vm] Gracefully handle loads not solicited by prefix.loadLibrary().

TEST=flutter
Bug: https://github.com/dart-lang/sdk/issues/41974
Change-Id: Ia0e99c5e84cdff8736c44e4e82ce40b045ed0207
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/174563
Reviewed-by: RĂ©gis Crelier <regis@google.com>
Commit-Queue: Ryan Macnak <rmacnak@google.com>
diff --git a/runtime/vm/dart_api_impl.cc b/runtime/vm/dart_api_impl.cc
index 2071a31..92fa101 100644
--- a/runtime/vm/dart_api_impl.cc
+++ b/runtime/vm/dart_api_impl.cc
@@ -6095,8 +6095,9 @@
 
   if (error) {
     CHECK_NULL(error_message);
-    unit.CompleteLoad(String::Handle(String::New(error_message)),
-                      transient_error);
+    return Api::NewHandle(
+        T, unit.CompleteLoad(String::Handle(String::New(error_message)),
+                             transient_error));
   } else {
 #if defined(SUPPORT_TIMELINE)
     TimelineBeginEndScope tbes(T, Timeline::GetIsolateStream(),
@@ -6120,10 +6121,8 @@
       return Api::NewHandle(T, error.raw());
     }
 
-    unit.CompleteLoad(String::Handle(), false);
+    return Api::NewHandle(T, unit.CompleteLoad(String::Handle(), false));
   }
-
-  return Api::Success();
 }
 
 DART_EXPORT Dart_Handle
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index 57ff8c6..e673c0a 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -17481,8 +17481,8 @@
   return Isolate::Current()->CallDeferredLoadHandler(id());
 }
 
-void LoadingUnit::CompleteLoad(const String& error_message,
-                               bool transient_error) const {
+ObjectPtr LoadingUnit::CompleteLoad(const String& error_message,
+                                    bool transient_error) const {
   ASSERT(!loaded());
   ASSERT(load_outstanding());
   set_loaded(error_message.IsNull());
@@ -17496,12 +17496,7 @@
   args.SetAt(0, Smi::Handle(Smi::New(id())));
   args.SetAt(1, error_message);
   args.SetAt(2, Bool::Get(transient_error));
-  const Object& result = Object::Handle(DartEntry::InvokeFunction(func, args));
-  if (result.IsUnwindError()) {
-    Thread::Current()->set_sticky_error(Error::Cast(result));
-  } else if (result.IsError()) {
-    UNREACHABLE();
-  }
+  return DartEntry::InvokeFunction(func, args);
 }
 
 const char* Error::ToErrorCString() const {
diff --git a/runtime/vm/object.h b/runtime/vm/object.h
index 467e1b1..2a3b73d 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -6996,7 +6996,8 @@
   }
 
   ObjectPtr IssueLoad() const;
-  void CompleteLoad(const String& error_message, bool transient_error) const;
+  ObjectPtr CompleteLoad(const String& error_message,
+                         bool transient_error) const;
 
  private:
   FINAL_HEAP_OBJECT_IMPLEMENTATION(LoadingUnit, Object);
diff --git a/sdk/lib/_internal/vm/lib/lib_prefix.dart b/sdk/lib/_internal/vm/lib/lib_prefix.dart
index 4259640..7604f62 100644
--- a/sdk/lib/_internal/vm/lib/lib_prefix.dart
+++ b/sdk/lib/_internal/vm/lib/lib_prefix.dart
@@ -31,7 +31,11 @@
 
 @pragma("vm:entry-point")
 void _completeLoads(Object unit, String? errorMessage, bool transientError) {
-  Completer<void> load = _LibraryPrefix._loads[unit]!;
+  Completer<void>? load = _LibraryPrefix._loads[unit];
+  if (load == null) {
+    // Embedder loaded even though prefix.loadLibrary() wasn't called.
+    _LibraryPrefix._loads[unit] = load = new Completer<void>();
+  }
   if (errorMessage == null) {
     load.complete(null);
   } else {