Index: runtime/bin/loader.cc |
diff --git a/runtime/bin/loader.cc b/runtime/bin/loader.cc |
index f43cf30056225291aa737c67d9a5b46e6d4d8145..a391b707e4abf65f1955b2b790b53b5b913dbf82 100644 |
--- a/runtime/bin/loader.cc |
+++ b/runtime/bin/loader.cc |
@@ -212,18 +212,20 @@ void Loader::BlockUntilComplete() { |
} |
-bool Loader::ProcessResultLocked(Loader::IOResult* result) { |
- // A negative result tag indicates a loading error occurred in the service |
- // isolate. The payload is a C string of the error message. |
- if (result->tag < 0) { |
- error_ = |
- Dart_NewUnhandledExceptionError( |
- Dart_NewStringFromUTF8(result->payload, |
- result->payload_length)); |
- |
- return false; |
+static bool LibraryHandleError(Dart_Handle library, Dart_Handle error) { |
+ if (!Dart_IsNull(library) && !Dart_IsError(library)) { |
+ ASSERT(Dart_IsLibrary(library)); |
+ Dart_Handle res = Dart_LibraryHandleError(library, error); |
+ if (Dart_IsNull(res)) { |
+ // Error was handled by library. |
+ return true; |
+ } |
} |
+ return false; |
+} |
+ |
+bool Loader::ProcessResultLocked(Loader::IOResult* result) { |
// We have to copy everything we care about out of |result| because after |
// dropping the lock below |result| may no longer valid. |
Dart_Handle uri = |
@@ -233,6 +235,25 @@ bool Loader::ProcessResultLocked(Loader::IOResult* result) { |
library_uri = |
Dart_NewStringFromCString(reinterpret_cast<char*>(result->library_uri)); |
} |
+ |
+ // A negative result tag indicates a loading error occurred in the service |
+ // isolate. The payload is a C string of the error message. |
+ if (result->tag < 0) { |
+ Dart_Handle library = Dart_LookupLibrary(uri); |
+ Dart_Handle error = Dart_NewStringFromUTF8(result->payload, |
+ result->payload_length); |
+ // If a library with the given uri exists, give it a chance to handle |
+ // the error. If the load requests stems from a deferred library load, |
+ // an IO error is not fatal. |
+ if (LibraryHandleError(library, error)) { |
+ return true; |
+ } |
+ // Fall through |
+ error_ = Dart_NewUnhandledExceptionError(error); |
+ return false; |
+ } |
+ |
+ |
// Check for payload and load accordingly. |
bool is_snapshot = false; |
const uint8_t* payload = result->payload; |
@@ -402,8 +423,11 @@ Dart_Handle Loader::LibraryTagHandler(Dart_LibraryTag tag, |
// The outer invocation of the tag handler for this isolate. We make the outer |
// invocation block and allow any nested invocations to operate in parallel. |
- bool blocking_call = !isolate_data->HasLoader(); |
+ const bool blocking_call = !isolate_data->HasLoader(); |
+ // If we are the outer invocation of the tag handler and the tag is an import |
+ // this means that we are starting a deferred library load. |
+ const bool is_deferred_import = blocking_call && (tag == Dart_kImportTag); |
if (!isolate_data->HasLoader()) { |
// The isolate doesn't have a loader -- this is the outer invocation which |
// will block. |
@@ -440,8 +464,23 @@ Dart_Handle Loader::LibraryTagHandler(Dart_LibraryTag tag, |
delete loader; |
// An error occurred during loading. |
- if (Dart_IsError(error)) { |
- return error; |
+ if (!Dart_IsNull(error)) { |
+ if (false && is_deferred_import) { |
+ // This blocks handles transitive load errors caused by a deferred |
+ // import. Non-transitive load errors are handled above (see callers of |
+ // |LibraryHandleError|). To handle the transitive case, we give the |
+ // originating deferred library an opportunity to handle it. |
+ Dart_Handle deferred_library = Dart_LookupLibrary(url); |
+ if (!LibraryHandleError(deferred_library, error)) { |
+ // Library did not handle it, return to caller as an unhandled |
+ // exception. |
+ return Dart_NewUnhandledExceptionError(error); |
+ } |
+ } else { |
+ // We got an error during loading but we aren't loading a deferred |
+ // library, return the error to the caller. |
+ return error; |
+ } |
} |
// Finalize loading. This will complete any futures for completed deferred |