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

namespace dart {
namespace bin {

// Development flag.
static bool trace_loader = false;
#if !defined(DART_PRECOMPILED_RUNTIME)
extern DFE dfe;
#endif

// Keep in sync with loader.dart.
static const intptr_t _Dart_kImportExtension = 9;
static const intptr_t _Dart_kResolveAsFilePath = 10;

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(9);
  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));
  Dart_ListSetAt(request, 8, Dart_NewBoolean(Dart_IsReloading()));

  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(intptr_t 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_++;
  }
}

// Forward a request from the tag handler to the kernel isolate.
// [ tag, send port, url ]
void Loader::SendKernelRequest(Dart_LibraryTag tag, Dart_Handle url) {
  // This port delivers loading messages to the Kernel isolate.
  Dart_Port kernel_port = Dart_KernelPort();
  ASSERT(kernel_port != ILLEGAL_PORT);

  Dart_Handle request = Dart_NewList(3);
  Dart_ListSetAt(request, 0, Dart_NewInteger(tag));
  Dart_ListSetAt(request, 1, Dart_NewSendPort(port_));
  Dart_ListSetAt(request, 2, url);
  if (Dart_Post(kernel_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));
}

void Loader::AddDependencyLocked(Loader* loader, const char* resolved_uri) {
  MallocGrowableArray<char*>* dependencies =
      loader->isolate_data_->dependencies();
  if (dependencies == NULL) {
    return;
  }
  dependencies->Add(strdup(resolved_uri));
}

void Loader::ResolveDependenciesAsFilePaths() {
  IsolateData* isolate_data =
      reinterpret_cast<IsolateData*>(Dart_CurrentIsolateData());
  ASSERT(isolate_data != NULL);
  MallocGrowableArray<char*>* dependencies = isolate_data->dependencies();
  if (dependencies == NULL) {
    return;
  }

  for (intptr_t i = 0; i < dependencies->length(); i++) {
    char* resolved_uri = (*dependencies)[i];

    uint8_t* scoped_file_path = NULL;
    intptr_t scoped_file_path_length = -1;
    Dart_Handle uri = Dart_NewStringFromCString(resolved_uri);
    ASSERT(!Dart_IsError(uri));
    Dart_Handle result = Loader::ResolveAsFilePath(uri, &scoped_file_path,
                                                   &scoped_file_path_length);
    if (Dart_IsError(result)) {
      Log::Print("Error resolving dependency: %s\n", Dart_GetError(result));
      return;
    }

    (*dependencies)[i] =
        StringUtils::StrNDup(reinterpret_cast<const char*>(scoped_file_path),
                             scoped_file_path_length);
    free(resolved_uri);
  }
}

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

  AddDependencyLocked(loader, result->resolved_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) {
        // TODO(27590): This code path is only hit when trying to spawn
        // isolates. We currently do not have support for neither
        // `Isolate.spawn()` nor `Isolate.spawnUri()` with kernel-based
        // frontend.
        Dart_Handle kernel_binary = reinterpret_cast<Dart_Handle>(
            Dart_ReadKernelBinary(payload, payload_length));
        dart_result = Dart_LoadScript(uri, resolved_uri, kernel_binary, 0, 0);
      } 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::ProcessPayloadResultLocked(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::SendAndProcessReply(intptr_t tag,
                                        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(tag, url, Dart_Null());

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

  // 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::LoadUrlContents(Dart_Handle url,
                                    uint8_t** payload,
                                    intptr_t* payload_length) {
  return SendAndProcessReply(Dart_kScriptTag, url, payload, payload_length);
}

Dart_Handle Loader::ResolveAsFilePath(Dart_Handle url,
                                      uint8_t** payload,
                                      intptr_t* payload_length) {
  return SendAndProcessReply(_Dart_kResolveAsFilePath, url, payload,
                             payload_length);
}

#if defined(DART_PRECOMPILED_RUNTIME)
Dart_Handle Loader::LibraryTagHandler(Dart_LibraryTag tag,
                                      Dart_Handle library,
                                      Dart_Handle url) {
  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) {
  return Dart_Null();
}
#else
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;
  }
  if (tag == Dart_kScriptTag) {
    if (dfe.UseDartFrontend() || dfe.kernel_file_specified()) {
      Dart_Isolate current = Dart_CurrentIsolate();
      // Check if we are trying to reload a kernel file or if the '--dfe'
      // option was specified and we need to compile sources using DFE.
      if (!Dart_IsServiceIsolate(current) && !Dart_IsKernelIsolate(current)) {
        // When using DFE the library tag handler should be called only when
        // we are reloading scripts.
        return dfe.ReloadScript(current, url_string);
      }
    }
    // TODO(asiva) We need to ensure that the kernel and service isolates
    // are always loaded from a kernel IR and do not use this path.
  } else {
    // Special case for handling dart: imports and parts.
    // 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);
  if ((tag == Dart_kScriptTag) && Dart_IsString(library)) {
    // Update packages file for isolate.
    const char* packages_file = NULL;
    Dart_Handle result = Dart_StringToCString(library, &packages_file);
    if (Dart_IsError(result)) {
      return result;
    }
    isolate_data->UpdatePackagesFile(packages_file);
  }
  // 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 {
    if (Dart_KernelIsolateIsRunning()) {
      loader->SendKernelRequest(tag, url);
    } 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();
}
#endif  // !defined(DART_PRECOMPILED_RUNTIME)

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
