// 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/extensions.h"
#include "bin/file.h"
#include "bin/lockers.h"
#include "bin/utils.h"
#include "include/dart_tools_api.h"

namespace dart {
namespace bin {

// Development flag.
static bool trace_loader = false;
// Keep in sync with loader.dart.
static const intptr_t _Dart_kImportExtension = 9;

Loader::Loader(IsolateData* isolate_data)
    : port_(ILLEGAL_PORT),
      isolate_data_(isolate_data),
      error_(Dart_Null()),
      monitor_(NULL),
      pending_operations_(0),
      results_(NULL),
      results_length_(0),
      results_capacity_(0),
      payload_(NULL),
      payload_length_(0) {
  monitor_ = new Monitor();
  ASSERT(isolate_data_ != NULL);
  port_ = Dart_NewNativePort("Loader", Loader::NativeMessageHandler, false);
  isolate_data_->set_loader(this);
  AddLoader(port_, isolate_data_);
}


Loader::~Loader() {
  ASSERT(port_ != ILLEGAL_PORT);
  // Enter the monitor while we close the Dart port. After the Dart port is
  // closed, no more results can be queued.
  monitor_->Enter();
  Dart_CloseNativePort(port_);
  monitor_->Exit();
  RemoveLoader(port_);
  port_ = ILLEGAL_PORT;
  isolate_data_->set_loader(NULL);
  isolate_data_ = NULL;
  delete monitor_;
  monitor_ = NULL;
  for (intptr_t i = 0; i < results_length_; i++) {
    results_[i].Cleanup();
  }
  free(results_);
  results_ = NULL;
  payload_ = NULL;
  payload_length_ = 0;
}


// Copy the contents of |message| into an |IOResult|.
void Loader::IOResult::Setup(Dart_CObject* message) {
  ASSERT(message->type == Dart_CObject_kArray);
  ASSERT(message->value.as_array.length == 5);
  Dart_CObject* tag_message = message->value.as_array.values[0];
  ASSERT(tag_message != NULL);
  Dart_CObject* uri_message = message->value.as_array.values[1];
  ASSERT(uri_message != NULL);
  Dart_CObject* resolved_uri_message = message->value.as_array.values[2];
  ASSERT(resolved_uri_message != NULL);
  Dart_CObject* library_uri_message = message->value.as_array.values[3];
  ASSERT(library_uri_message != NULL);
  Dart_CObject* payload_message = message->value.as_array.values[4];
  ASSERT(payload_message != NULL);

  // Grab the tag.
  ASSERT(tag_message->type == Dart_CObject_kInt32);
  tag = tag_message->value.as_int32;

  // Grab the uri id.
  ASSERT(uri_message->type == Dart_CObject_kString);
  uri = strdup(uri_message->value.as_string);

  // Grab the resolved uri.
  ASSERT(resolved_uri_message->type == Dart_CObject_kString);
  resolved_uri = strdup(resolved_uri_message->value.as_string);

  // Grab the library uri if one is present.
  if (library_uri_message->type != Dart_CObject_kNull) {
    ASSERT(library_uri_message->type == Dart_CObject_kString);
    library_uri = strdup(library_uri_message->value.as_string);
  } else {
    library_uri = NULL;
  }

  // Grab the payload.
  if (payload_message->type == Dart_CObject_kString) {
    // Payload is an error message.
    payload_length = strlen(payload_message->value.as_string);
    payload =
        reinterpret_cast<uint8_t*>(strdup(payload_message->value.as_string));
  } else {
    // Payload is the contents of a file.
    ASSERT(payload_message->type == Dart_CObject_kTypedData);
    ASSERT(payload_message->value.as_typed_data.type == Dart_TypedData_kUint8);
    payload_length = payload_message->value.as_typed_data.length;
    payload = reinterpret_cast<uint8_t*>(malloc(payload_length));
    memmove(payload, payload_message->value.as_typed_data.values,
            payload_length);
  }
}


void Loader::IOResult::Cleanup() {
  free(uri);
  free(resolved_uri);
  free(library_uri);
  free(payload);
}


// Send the Loader Initialization message to the service isolate. This
// message is sent the first time a loader is constructed for an isolate and
// seeds the service isolate with some initial state about this isolate.
void Loader::Init(const char* package_root,
                  const char* packages_file,
                  const char* working_directory,
                  const char* root_script_uri) {
  // This port delivers loading messages to the service isolate.
  Dart_Port loader_port = Builtin::LoadPort();
  ASSERT(loader_port != ILLEGAL_PORT);

  // Keep in sync with loader.dart.
  const intptr_t _Dart_kInitLoader = 4;

  Dart_Handle request = Dart_NewList(8);
  Dart_ListSetAt(request, 0, trace_loader ? Dart_True() : Dart_False());
  Dart_ListSetAt(request, 1, Dart_NewInteger(Dart_GetMainPortId()));
  Dart_ListSetAt(request, 2, Dart_NewInteger(_Dart_kInitLoader));
  Dart_ListSetAt(request, 3, Dart_NewSendPort(port_));
  Dart_ListSetAt(request, 4, (package_root == NULL)
                                 ? Dart_Null()
                                 : Dart_NewStringFromCString(package_root));
  Dart_ListSetAt(request, 5, (packages_file == NULL)
                                 ? Dart_Null()
                                 : Dart_NewStringFromCString(packages_file));
  Dart_ListSetAt(request, 6, Dart_NewStringFromCString(working_directory));
  Dart_ListSetAt(request, 7, (root_script_uri == NULL)
                                 ? Dart_Null()
                                 : Dart_NewStringFromCString(root_script_uri));

  bool success = Dart_Post(loader_port, request);
  ASSERT(success);
}


void Loader::SendImportExtensionRequest(Dart_Handle url,
                                        Dart_Handle library_url) {
  // This port delivers loading messages to the service isolate.
  Dart_Port loader_port = Builtin::LoadPort();
  ASSERT(loader_port != ILLEGAL_PORT);


  Dart_Handle request = Dart_NewList(6);
  Dart_ListSetAt(request, 0, trace_loader ? Dart_True() : Dart_False());
  Dart_ListSetAt(request, 1, Dart_NewInteger(Dart_GetMainPortId()));
  Dart_ListSetAt(request, 2, Dart_NewInteger(_Dart_kImportExtension));
  Dart_ListSetAt(request, 3, Dart_NewSendPort(port_));

  Dart_ListSetAt(request, 4, url);
  Dart_ListSetAt(request, 5, library_url);

  if (Dart_Post(loader_port, request)) {
    MonitorLocker ml(monitor_);
    pending_operations_++;
  }
}


// Forward a request from the tag handler to the service isolate.
void Loader::SendRequest(Dart_LibraryTag tag,
                         Dart_Handle url,
                         Dart_Handle library_url) {
  // This port delivers loading messages to the service isolate.
  Dart_Port loader_port = Builtin::LoadPort();
  ASSERT(loader_port != ILLEGAL_PORT);

  Dart_Handle request = Dart_NewList(6);
  Dart_ListSetAt(request, 0, trace_loader ? Dart_True() : Dart_False());
  Dart_ListSetAt(request, 1, Dart_NewInteger(Dart_GetMainPortId()));
  Dart_ListSetAt(request, 2, Dart_NewInteger(tag));
  Dart_ListSetAt(request, 3, Dart_NewSendPort(port_));

  Dart_ListSetAt(request, 4, url);
  Dart_ListSetAt(request, 5, library_url);

  if (Dart_Post(loader_port, request)) {
    MonitorLocker ml(monitor_);
    pending_operations_++;
  }
}


void Loader::QueueMessage(Dart_CObject* message) {
  MonitorLocker ml(monitor_);
  if (results_length_ == results_capacity_) {
    // Grow to an initial capacity or double in size.
    results_capacity_ = (results_capacity_ == 0) ? 4 : results_capacity_ * 2;
    results_ = reinterpret_cast<IOResult*>(
        realloc(results_, sizeof(IOResult) * results_capacity_));
    ASSERT(results_ != NULL);
  }
  ASSERT(results_ != NULL);
  ASSERT(results_length_ < results_capacity_);
  results_[results_length_].Setup(message);
  results_length_++;
  ml.Notify();
}


void Loader::BlockUntilComplete(ProcessResult process_result) {
  MonitorLocker ml(monitor_);

  while (true) {
    // If |ProcessQueueLocked| returns false, we've hit an error and should
    // stop loading.
    if (!ProcessQueueLocked(process_result)) {
      break;
    }

    // When |pending_operations_| hits 0, we are done loading.
    if (pending_operations_ == 0) {
      break;
    }

    // Wait to be notified about new I/O results.
    ml.Wait();
  }
}


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


static bool PathContainsSeparator(const char* path) {
  return (strchr(path, '/') != NULL) ||
         ((strncmp(File::PathSeparator(), "/", 1) != 0) &&
          (strstr(path, File::PathSeparator()) != NULL));
}


bool Loader::ProcessResultLocked(Loader* loader, 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 =
      Dart_NewStringFromCString(reinterpret_cast<char*>(result->uri));
  Dart_Handle resolved_uri =
      Dart_NewStringFromCString(reinterpret_cast<char*>(result->resolved_uri));
  Dart_Handle library_uri = Dart_Null();
  if (result->library_uri != NULL) {
    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
    loader->error_ = Dart_NewUnhandledExceptionError(error);
    return false;
  }

  if (result->tag == _Dart_kImportExtension) {
    ASSERT(library_uri != Dart_Null());
    Dart_Handle library = Dart_LookupLibrary(library_uri);
    ASSERT(!Dart_IsError(library));
    const char* lib_uri = reinterpret_cast<const char*>(result->payload);
    if (strncmp(lib_uri, "http://", 7) == 0 ||
        strncmp(lib_uri, "https://", 8) == 0) {
      loader->error_ = Dart_NewApiError(
          "Cannot load native extensions over http: or https:");
      return false;
    }
    const char* extension_uri = reinterpret_cast<const char*>(result->uri);
    const char* lib_path = NULL;
    if (strncmp(lib_uri, "file://", 7) == 0) {
      lib_path = DartUtils::RemoveScheme(lib_uri);
    } else {
      lib_path = lib_uri;
    }
    const char* extension_path = DartUtils::RemoveScheme(extension_uri);
    if (!File::IsAbsolutePath(extension_path) &&
        PathContainsSeparator(extension_path)) {
      loader->error_ = DartUtils::NewError(
          "Native extension path must be absolute, or simply the file name: %s",
          extension_path);
      return false;
    }
    Dart_Handle result =
        Extensions::LoadExtension(lib_path, extension_path, library);
    if (Dart_IsError(result)) {
      loader->error_ = result;
      return false;
    }
    return true;
  }

  // Check for payload and load accordingly.
  const uint8_t* payload = result->payload;
  intptr_t payload_length = result->payload_length;
  const DartUtils::MagicNumber payload_type =
      DartUtils::SniffForMagicNumber(&payload, &payload_length);
  Dart_Handle source = Dart_Null();
  if (payload_type == DartUtils::kUnknownMagicNumber) {
    source = Dart_NewStringFromUTF8(result->payload, result->payload_length);
    if (Dart_IsError(source)) {
      loader->error_ =
          DartUtils::NewError("%s is not a valid UTF-8 script",
                              reinterpret_cast<char*>(result->uri));
      return false;
    }
  }
  intptr_t tag = result->tag;

  // No touching.
  result = NULL;

  // We must drop the lock here because the tag handler may be recursively
  // invoked and it will attempt to acquire the lock to queue more work.
  loader->monitor_->Exit();

  Dart_Handle dart_result = Dart_Null();
  bool reload_extensions = false;

  switch (tag) {
    case Dart_kImportTag:
      dart_result = Dart_LoadLibrary(uri, resolved_uri, source, 0, 0);
      break;
    case Dart_kSourceTag: {
      ASSERT(library_uri != Dart_Null());
      Dart_Handle library = Dart_LookupLibrary(library_uri);
      ASSERT(!Dart_IsError(library));
      dart_result = Dart_LoadSource(library, uri, resolved_uri, source, 0, 0);
    } break;
    case Dart_kScriptTag:
      if (payload_type == DartUtils::kSnapshotMagicNumber) {
        dart_result = Dart_LoadScriptFromSnapshot(payload, payload_length);
        reload_extensions = true;
      } else if (payload_type == DartUtils::kKernelMagicNumber) {
        dart_result = Dart_LoadKernel(payload, payload_length);
      } else {
        dart_result = Dart_LoadScript(uri, resolved_uri, source, 0, 0);
      }
      break;
    default:
      UNREACHABLE();
  }

  // Re-acquire the lock before exiting the function (it was held before entry),
  loader->monitor_->Enter();
  if (Dart_IsError(dart_result)) {
    // Remember the error if we encountered one.
    loader->error_ = dart_result;
    return false;
  }

  if (reload_extensions) {
    dart_result = ReloadNativeExtensions();
    if (Dart_IsError(dart_result)) {
      // Remember the error if we encountered one.
      loader->error_ = dart_result;
      return false;
    }
  }

  return true;
}


bool Loader::ProcessUrlLoadResultLocked(Loader* loader,
                                        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) {
    Dart_Handle error =
        Dart_NewStringFromUTF8(result->payload, result->payload_length);
    loader->error_ = Dart_NewUnhandledExceptionError(error);
    return false;
  }
  loader->payload_length_ = result->payload_length;
  loader->payload_ =
      reinterpret_cast<uint8_t*>(::malloc(loader->payload_length_));
  memmove(loader->payload_, result->payload, loader->payload_length_);
  return true;
}


bool Loader::ProcessQueueLocked(ProcessResult process_result) {
  bool hit_error = false;
  for (intptr_t i = 0; i < results_length(); i++) {
    if (!hit_error) {
      hit_error = !(*process_result)(this, &results_[i]);
    }
    pending_operations_--;
    ASSERT(hit_error || (pending_operations_ >= 0));
    results_[i].Cleanup();
  }
  results_length_ = 0;
  return !hit_error;
}


void Loader::InitForSnapshot(const char* snapshot_uri) {
  IsolateData* isolate_data =
      reinterpret_cast<IsolateData*>(Dart_CurrentIsolateData());
  ASSERT(isolate_data != NULL);
  ASSERT(!isolate_data->HasLoader());
  // Setup a loader. The constructor does a bunch of leg work.
  Loader* loader = new Loader(isolate_data);
  // Send the init message.
  loader->Init(isolate_data->package_root, isolate_data->packages_file,
               DartUtils::original_working_directory, snapshot_uri);
  // Destroy the loader. The destructor does a bunch of leg work.
  delete loader;
}


#define RETURN_ERROR(result)                                                   \
  if (Dart_IsError(result)) return result;

Dart_Handle Loader::ReloadNativeExtensions() {
  Dart_Handle scheme =
      Dart_NewStringFromCString(DartUtils::kDartExtensionScheme);
  Dart_Handle extension_imports = Dart_GetImportsOfScheme(scheme);
  RETURN_ERROR(extension_imports);

  intptr_t length = -1;
  Dart_Handle result = Dart_ListLength(extension_imports, &length);
  RETURN_ERROR(result);
  Dart_Handle* import_handles = reinterpret_cast<Dart_Handle*>(
      Dart_ScopeAllocate(sizeof(Dart_Handle) * length));
  result = Dart_ListGetRange(extension_imports, 0, length, import_handles);
  RETURN_ERROR(result);
  for (intptr_t i = 0; i < length; i += 2) {
    Dart_Handle importer = import_handles[i];
    Dart_Handle importee = import_handles[i + 1];

    const char* extension_uri = NULL;
    result = Dart_StringToCString(Dart_LibraryUrl(importee), &extension_uri);
    RETURN_ERROR(result);
    const char* extension_path = DartUtils::RemoveScheme(extension_uri);

    const char* lib_uri = NULL;
    result = Dart_StringToCString(Dart_LibraryUrl(importer), &lib_uri);
    RETURN_ERROR(result);

    char* lib_path = NULL;
    if (strncmp(lib_uri, "file://", 7) == 0) {
      lib_path = DartUtils::DirName(DartUtils::RemoveScheme(lib_uri));
    } else {
      lib_path = strdup(lib_uri);
    }

    result = Extensions::LoadExtension(lib_path, extension_path, importer);
    free(lib_path);
    RETURN_ERROR(result);
  }

  return Dart_True();
}


Dart_Handle Loader::LoadUrlContents(Dart_Handle url,
                                    uint8_t** payload,
                                    intptr_t* payload_length) {
  IsolateData* isolate_data =
      reinterpret_cast<IsolateData*>(Dart_CurrentIsolateData());
  ASSERT(isolate_data != NULL);
  ASSERT(!isolate_data->HasLoader());
  Loader* loader = NULL;

  // Setup the loader. The constructor does a bunch of leg work.
  loader = new Loader(isolate_data);
  loader->Init(isolate_data->package_root, isolate_data->packages_file,
               DartUtils::original_working_directory, NULL);
  ASSERT(loader != NULL);
  ASSERT(isolate_data->HasLoader());

  // Now send a load request to the service isolate.
  loader->SendRequest(Dart_kScriptTag, url, Dart_Null());

  // Wait for a reply to the load request.
  loader->BlockUntilComplete(ProcessUrlLoadResultLocked);

  // Copy fields from the loader before deleting it.
  // The payload array itself which was malloced above is freed by
  // the caller of LoadUrlContents.
  Dart_Handle error = loader->error();
  *payload = loader->payload_;
  *payload_length = loader->payload_length_;

  // Destroy the loader. The destructor does a bunch of leg work.
  delete loader;

  // An error occurred during loading.
  if (!Dart_IsNull(error)) {
    return error;
  }
  return Dart_Null();
}


Dart_Handle Loader::LibraryTagHandler(Dart_LibraryTag tag,
                                      Dart_Handle library,
                                      Dart_Handle url) {
  if (tag == Dart_kCanonicalizeUrl) {
    Dart_Handle library_url = Dart_LibraryUrl(library);
    if (Dart_IsError(library_url)) {
      return library_url;
    }
    return Dart_DefaultCanonicalizeUrl(library_url, url);
  }
  const char* url_string = NULL;
  Dart_Handle result = Dart_StringToCString(url, &url_string);
  if (Dart_IsError(result)) {
    return result;
  }

  // Special case for handling dart: imports and parts.
  if (tag != Dart_kScriptTag) {
    // Grab the library's url.
    Dart_Handle library_url = Dart_LibraryUrl(library);
    if (Dart_IsError(library_url)) {
      return library_url;
    }
    const char* library_url_string = NULL;
    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 DartColonLibraryTagHandler(tag, library, url, library_url_string,
                                        url_string);
    }
  }

  if (DartUtils::IsDartExtensionSchemeURL(url_string)) {
    // Handle early error cases for dart-ext: imports.
    if (tag != Dart_kImportTag) {
      return DartUtils::NewError("Dart extensions must use import: '%s'",
                                 url_string);
    }
    Dart_Handle library_url = Dart_LibraryUrl(library);
    if (Dart_IsError(library_url)) {
      return library_url;
    }
  }

  IsolateData* isolate_data =
      reinterpret_cast<IsolateData*>(Dart_CurrentIsolateData());
  ASSERT(isolate_data != NULL);

  // Grab this isolate's loader.
  Loader* loader = NULL;

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

    // Setup the loader. The constructor does a bunch of leg work.
    loader = new Loader(isolate_data);
    loader->Init(isolate_data->package_root, isolate_data->packages_file,
                 DartUtils::original_working_directory,
                 (tag == Dart_kScriptTag) ? url_string : NULL);
  } else {
    ASSERT(tag != Dart_kScriptTag);
    // The isolate has a loader -- this is an inner invocation that will queue
    // work with the service isolate.
    // Use the existing loader.
    loader = isolate_data->loader();
  }
  ASSERT(loader != NULL);
  ASSERT(isolate_data->HasLoader());

  if (DartUtils::IsDartExtensionSchemeURL(url_string)) {
    loader->SendImportExtensionRequest(url, Dart_LibraryUrl(library));
  } else {
    loader->SendRequest(tag, url, (library != Dart_Null())
                                      ? Dart_LibraryUrl(library)
                                      : Dart_Null());
  }


  if (blocking_call) {
    // The outer invocation of the tag handler will block here until all nested
    // invocations complete.
    loader->BlockUntilComplete(ProcessResultLocked);

    // Remember the error (if any).
    Dart_Handle error = loader->error();
    // Destroy the loader. The destructor does a bunch of leg work.
    delete loader;

    // An error occurred during loading.
    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
    // loads.
    error = Dart_FinalizeLoading(true);
    if (Dart_IsError(error)) {
      return error;
    }
  }
  return Dart_Null();
}


Dart_Handle Loader::DartColonLibraryTagHandler(Dart_LibraryTag tag,
                                               Dart_Handle library,
                                               Dart_Handle url,
                                               const char* library_url_string,
                                               const char* url_string) {
  // Handle canonicalization, 'import' and 'part' of 'dart:' libraries.
  if (tag == Dart_kCanonicalizeUrl) {
    // These will be handled internally.
    return url;
  } else if (tag == Dart_kImportTag) {
    Builtin::BuiltinLibraryId id = Builtin::FindId(url_string);
    if (id == Builtin::kInvalidLibrary) {
      return DartUtils::NewError(
          "The built-in library '%s' is not available"
          " on the stand-alone VM.\n",
          url_string);
    }
    return Builtin::LoadLibrary(url, id);
  } else {
    ASSERT(tag == Dart_kSourceTag);
    Builtin::BuiltinLibraryId id = Builtin::FindId(library_url_string);
    if (id == Builtin::kInvalidLibrary) {
      return DartUtils::NewError(
          "The built-in library '%s' is not available"
          " on the stand-alone VM. Trying to load"
          " '%s'.\n",
          library_url_string, url_string);
    }
    // Prepend the library URI to form a unique script URI for the part.
    intptr_t len = snprintf(NULL, 0, "%s/%s", library_url_string, url_string);
    char* part_uri = reinterpret_cast<char*>(malloc(len + 1));
    snprintf(part_uri, len + 1, "%s/%s", library_url_string, url_string);
    Dart_Handle part_uri_obj = DartUtils::NewString(part_uri);
    free(part_uri);
    return Dart_LoadSource(library, part_uri_obj, Dart_Null(),
                           Builtin::PartSource(id, url_string), 0, 0);
  }
  // All cases should have been handled above.
  UNREACHABLE();
  return Dart_Null();
}


void Loader::InitOnce() {
  loader_infos_lock_ = new Mutex();
}


Mutex* Loader::loader_infos_lock_;
Loader::LoaderInfo* Loader::loader_infos_ = NULL;
intptr_t Loader::loader_infos_length_ = 0;
intptr_t Loader::loader_infos_capacity_ = 0;


// Add a mapping from |port| to |isolate_data| (really the loader). When a
// native message arrives, we use this map to report the I/O result to the
// correct loader.
// This happens whenever an isolate begins loading.
void Loader::AddLoader(Dart_Port port, IsolateData* isolate_data) {
  MutexLocker ml(loader_infos_lock_);
  ASSERT(LoaderForLocked(port) == NULL);
  if (loader_infos_length_ == loader_infos_capacity_) {
    // Grow to an initial capacity or double in size.
    loader_infos_capacity_ =
        (loader_infos_capacity_ == 0) ? 4 : loader_infos_capacity_ * 2;
    loader_infos_ = reinterpret_cast<Loader::LoaderInfo*>(realloc(
        loader_infos_, sizeof(Loader::LoaderInfo) * loader_infos_capacity_));
    ASSERT(loader_infos_ != NULL);
    // Initialize new entries.
    for (intptr_t i = loader_infos_length_; i < loader_infos_capacity_; i++) {
      loader_infos_[i].port = ILLEGAL_PORT;
      loader_infos_[i].isolate_data = NULL;
    }
  }
  ASSERT(loader_infos_length_ < loader_infos_capacity_);
  loader_infos_[loader_infos_length_].port = port;
  loader_infos_[loader_infos_length_].isolate_data = isolate_data;
  loader_infos_length_++;
  ASSERT(LoaderForLocked(port) != NULL);
}


// Remove |port| from the map.
// This happens once an isolate has finished loading.
void Loader::RemoveLoader(Dart_Port port) {
  MutexLocker ml(loader_infos_lock_);
  const intptr_t index = LoaderIndexFor(port);
  ASSERT(index >= 0);
  const intptr_t last = loader_infos_length_ - 1;
  ASSERT(last >= 0);
  if (index != last) {
    // Swap with the tail.
    loader_infos_[index] = loader_infos_[last];
  }
  loader_infos_length_--;
}


intptr_t Loader::LoaderIndexFor(Dart_Port port) {
  for (intptr_t i = 0; i < loader_infos_length_; i++) {
    if (loader_infos_[i].port == port) {
      return i;
    }
  }
  return -1;
}


Loader* Loader::LoaderForLocked(Dart_Port port) {
  intptr_t index = LoaderIndexFor(port);
  if (index < 0) {
    return NULL;
  }
  return loader_infos_[index].isolate_data->loader();
}


Loader* Loader::LoaderFor(Dart_Port port) {
  MutexLocker ml(loader_infos_lock_);
  return LoaderForLocked(port);
}


void Loader::NativeMessageHandler(Dart_Port dest_port_id,
                                  Dart_CObject* message) {
  MutexLocker ml(loader_infos_lock_);
  Loader* loader = LoaderForLocked(dest_port_id);
  if (loader == NULL) {
    return;
  }
  loader->QueueMessage(message);
}

}  // namespace bin
}  // namespace dart
