| // Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file | 
 | // for details. All rights reserved. Use of this source code is governed by a | 
 | // BSD-style license that can be found in the LICENSE file. | 
 |  | 
 | #include "bin/loader.h" | 
 |  | 
 | #include "bin/builtin.h" | 
 | #include "bin/dartutils.h" | 
 | #include "bin/dfe.h" | 
 | #include "bin/error_exit.h" | 
 | #include "bin/file.h" | 
 | #include "bin/gzip.h" | 
 | #include "bin/lockers.h" | 
 | #include "bin/snapshot_utils.h" | 
 | #include "bin/utils.h" | 
 | #include "include/dart_tools_api.h" | 
 | #include "platform/growable_array.h" | 
 |  | 
 | namespace dart { | 
 | namespace bin { | 
 |  | 
 | #if !defined(DART_PRECOMPILED_RUNTIME) | 
 | extern DFE dfe; | 
 | #endif | 
 |  | 
 | Dart_Handle Loader::InitForSnapshot(const char* snapshot_uri, | 
 |                                     IsolateData* isolate_data) { | 
 |   ASSERT(isolate_data != nullptr); | 
 |  | 
 |   return Loader::Init(isolate_data->packages_file(), | 
 |                       DartUtils::original_working_directory, snapshot_uri); | 
 | } | 
 |  | 
 | // Initialize package resolution state. | 
 | Dart_Handle Loader::Init(const char* packages_file, | 
 |                          const char* working_directory, | 
 |                          const char* root_script_uri) { | 
 |   const int kNumArgs = 3; | 
 |   Dart_Handle dart_args[kNumArgs]; | 
 |   dart_args[0] = (packages_file == nullptr) | 
 |                      ? Dart_Null() | 
 |                      : Dart_NewStringFromCString(packages_file); | 
 |   dart_args[1] = Dart_NewStringFromCString(working_directory); | 
 |   dart_args[2] = (root_script_uri == nullptr) | 
 |                      ? Dart_Null() | 
 |                      : Dart_NewStringFromCString(root_script_uri); | 
 |   return Dart_Invoke(DartUtils::LookupBuiltinLib(), | 
 |                      DartUtils::NewString("_Init"), kNumArgs, dart_args); | 
 | } | 
 |  | 
 | #if !defined(DART_PRECOMPILED_RUNTIME) | 
 | static void MallocFinalizer(void* isolate_callback_data, void* peer) { | 
 |   free(peer); | 
 | } | 
 | static Dart_Handle WrapMallocedKernelBuffer(uint8_t* kernel_buffer, | 
 |                                             intptr_t kernel_buffer_size) { | 
 |   Dart_Handle result = Dart_NewExternalTypedDataWithFinalizer( | 
 |       Dart_TypedData_kUint8, kernel_buffer, kernel_buffer_size, kernel_buffer, | 
 |       kernel_buffer_size, MallocFinalizer); | 
 |   if (Dart_IsError(result)) { | 
 |     free(kernel_buffer); | 
 |   } | 
 |   return result; | 
 | } | 
 | #endif | 
 |  | 
 | Dart_Handle Loader::LibraryTagHandler(Dart_LibraryTag tag, | 
 |                                       Dart_Handle library, | 
 |                                       Dart_Handle url) { | 
 |   const char* url_string = nullptr; | 
 |   Dart_Handle result = Dart_StringToCString(url, &url_string); | 
 |   if (Dart_IsError(result)) { | 
 |     return result; | 
 |   } | 
 |   if (tag == Dart_kCanonicalizeUrl) { | 
 |     Dart_Handle library_url = Dart_LibraryUrl(library); | 
 |     if (Dart_IsError(library_url)) { | 
 |       return library_url; | 
 |     } | 
 |     const char* library_url_string = nullptr; | 
 |     result = Dart_StringToCString(library_url, &library_url_string); | 
 |     if (Dart_IsError(result)) { | 
 |       return result; | 
 |     } | 
 |     bool is_dart_scheme_url = DartUtils::IsDartSchemeURL(url_string); | 
 |     bool is_dart_library = DartUtils::IsDartSchemeURL(library_url_string); | 
 |     if (is_dart_scheme_url || is_dart_library) { | 
 |       return url; | 
 |     } | 
 |     return Dart_DefaultCanonicalizeUrl(library_url, url); | 
 |   } | 
 | #if !defined(DART_PRECOMPILED_RUNTIME) | 
 |   if (tag == Dart_kKernelTag) { | 
 |     uint8_t* kernel_buffer = nullptr; | 
 |     intptr_t kernel_buffer_size = 0; | 
 |     if (!dfe.TryReadKernelFile(url_string, nullptr, &kernel_buffer, | 
 |                                &kernel_buffer_size)) { | 
 |       return DartUtils::NewError("'%s' is not a kernel file", url_string); | 
 |     } | 
 |     return WrapMallocedKernelBuffer(kernel_buffer, kernel_buffer_size); | 
 |   } | 
 |   if (dfe.CanUseDartFrontend() && dfe.UseDartFrontend() && | 
 |       (tag == Dart_kImportTag)) { | 
 |     // E.g., IsolateMirror.loadUri. | 
 |     char* error = nullptr; | 
 |     int exit_code = 0; | 
 |     uint8_t* kernel_buffer = nullptr; | 
 |     intptr_t kernel_buffer_size = -1; | 
 |     dfe.CompileAndReadScript(url_string, &kernel_buffer, &kernel_buffer_size, | 
 |                              &error, &exit_code, nullptr, | 
 |                              /*for_snapshot=*/false, /*embed_sources=*/true); | 
 |     if (exit_code == 0) { | 
 |       return Dart_LoadLibrary( | 
 |           WrapMallocedKernelBuffer(kernel_buffer, kernel_buffer_size)); | 
 |     } else if (exit_code == kCompilationErrorExitCode) { | 
 |       Dart_Handle result = Dart_NewCompilationError(error); | 
 |       free(error); | 
 |       return result; | 
 |     } else { | 
 |       Dart_Handle result = Dart_NewApiError(error); | 
 |       free(error); | 
 |       return result; | 
 |     } | 
 |   } | 
 |   return DartUtils::NewError("Invalid tag : %d '%s'", tag, url_string); | 
 | #else   // !defined(DART_PRECOMPILED_RUNTIME) | 
 |   return DartUtils::NewError("Unimplemented tag : %d '%s'", tag, url_string); | 
 | #endif  // !defined(DART_PRECOMPILED_RUNTIME) | 
 | } | 
 |  | 
 | Dart_Handle Loader::DeferredLoadHandler(intptr_t loading_unit_id) { | 
 |   // A synchronous implementation. An asynchronous implementation would be | 
 |   // better, but the standalone embedder only implements AOT for testing. | 
 |  | 
 |   auto isolate_group_data = | 
 |       reinterpret_cast<IsolateGroupData*>(Dart_CurrentIsolateGroupData()); | 
 |   char* unit_url = Utils::SCreate( | 
 |       "%s-%" Pd ".part.so", isolate_group_data->script_url, loading_unit_id); | 
 |  | 
 |   AppSnapshot* loading_unit_snapshot = Snapshot::TryReadAppSnapshot(unit_url); | 
 |   Dart_Handle result; | 
 |   if (loading_unit_snapshot != nullptr) { | 
 |     isolate_group_data->AddLoadingUnit(loading_unit_snapshot); | 
 |     const uint8_t* isolate_snapshot_data = nullptr; | 
 |     const uint8_t* isolate_snapshot_instructions = nullptr; | 
 |     const uint8_t* ignore_vm_snapshot_data; | 
 |     const uint8_t* ignore_vm_snapshot_instructions; | 
 |     loading_unit_snapshot->SetBuffers( | 
 |         &ignore_vm_snapshot_data, &ignore_vm_snapshot_instructions, | 
 |         &isolate_snapshot_data, &isolate_snapshot_instructions); | 
 |     result = Dart_DeferredLoadComplete(loading_unit_id, isolate_snapshot_data, | 
 |                                        isolate_snapshot_instructions); | 
 |     if (Dart_IsApiError(result)) { | 
 |       result = | 
 |           Dart_DeferredLoadCompleteError(loading_unit_id, Dart_GetError(result), | 
 |                                          /*transient*/ false); | 
 |     } | 
 |   } else { | 
 |     char* error_message = Utils::SCreate("Failed to load %s", unit_url); | 
 |     result = Dart_DeferredLoadCompleteError(loading_unit_id, error_message, | 
 |                                             /*transient*/ false); | 
 |     free(error_message); | 
 |   } | 
 |  | 
 |   free(unit_url); | 
 |   return result; | 
 | } | 
 |  | 
 | void Loader::InitOnce() {} | 
 |  | 
 | }  // namespace bin | 
 | }  // namespace dart |