| 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
|
|
|