// Copyright (c) 2012, 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/dartutils.h"

#include "bin/crypto.h"
#include "bin/directory.h"
#include "bin/file.h"
#include "bin/io_buffer.h"
#include "bin/typed_data_utils.h"
#include "bin/utils.h"
#include "include/dart_api.h"
#include "include/dart_native_api.h"
#include "platform/assert.h"
#include "platform/globals.h"
#include "platform/mach_o.h"
#include "platform/utils.h"

// Return the error from the containing function if handle is in error handle.
#define RETURN_IF_ERROR(handle)                                                \
  {                                                                            \
    Dart_Handle __handle = handle;                                             \
    if (Dart_IsError((__handle))) {                                            \
      return __handle;                                                         \
    }                                                                          \
  }

namespace dart {
namespace bin {

const char* DartUtils::original_working_directory = nullptr;

dart::SimpleHashMap* DartUtils::environment_ = nullptr;

MagicNumberData appjit_magic_number = {8, {0xdc, 0xdc, 0xf6, 0xf6, 0, 0, 0, 0}};
MagicNumberData aotelf_magic_number = {4, {0x7F, 0x45, 0x4C, 0x46, 0x0}};
MagicNumberData aotcoff_arm32_magic_number = {2, {0x01, 0xC0}};
MagicNumberData aotcoff_arm64_magic_number = {2, {0xAA, 0x64}};
MagicNumberData aotcoff_riscv32_magic_number = {2, {0x50, 0x32}};
MagicNumberData aotcoff_riscv64_magic_number = {2, {0x50, 0x64}};
MagicNumberData kernel_magic_number = {4, {0x90, 0xab, 0xcd, 0xef}};
MagicNumberData kernel_list_magic_number = {
    7,
    {0x23, 0x40, 0x64, 0x69, 0x6c, 0x6c, 0x0a}};  // #@dill\n
MagicNumberData gzip_magic_number = {2, {0x1f, 0x8b, 0, 0}};

static bool IsWindowsHost() {
#if defined(DART_HOST_OS_WINDOWS)
  return true;
#else   // defined(DART_HOST_OS_WINDOWS)
  return false;
#endif  // defined(DART_HOST_OS_WINDOWS)
}

Dart_Handle CommandLineOptions::CreateRuntimeOptions() {
  Dart_Handle string_type = DartUtils::GetDartType("dart:core", "String");
  if (Dart_IsError(string_type)) {
    return string_type;
  }
  Dart_Handle dart_arguments =
      Dart_NewListOfTypeFilled(string_type, Dart_EmptyString(), count_);
  if (Dart_IsError(dart_arguments)) {
    return dart_arguments;
  }
  for (int i = 0; i < count_; i++) {
    Dart_Handle argument_value = DartUtils::NewString(GetArgument(i));
    if (Dart_IsError(argument_value)) {
      return argument_value;
    }
    Dart_Handle result = Dart_ListSetAt(dart_arguments, i, argument_value);
    if (Dart_IsError(result)) {
      return result;
    }
  }
  return dart_arguments;
}

int64_t DartUtils::GetIntegerValue(Dart_Handle value_obj) {
  int64_t value = 0;
  Dart_Handle result = Dart_IntegerToInt64(value_obj, &value);
  if (Dart_IsError(result)) {
    Dart_PropagateError(result);
  }
  return value;
}

int64_t DartUtils::GetInt64ValueCheckRange(Dart_Handle value_obj,
                                           int64_t lower,
                                           int64_t upper) {
  int64_t value = DartUtils::GetIntegerValue(value_obj);
  if (value < lower || upper < value) {
    Dart_PropagateError(Dart_NewApiError("Value outside expected range"));
  }
  return value;
}

intptr_t DartUtils::GetIntptrValue(Dart_Handle value_obj) {
  int64_t value = 0;
  Dart_Handle result = Dart_IntegerToInt64(value_obj, &value);
  if (Dart_IsError(result)) {
    Dart_PropagateError(result);
  }
  if (value < kIntptrMin || kIntptrMax < value) {
    Dart_PropagateError(Dart_NewApiError("Value outside intptr_t range"));
  }
  return static_cast<intptr_t>(value);
}

bool DartUtils::GetInt64Value(Dart_Handle value_obj, int64_t* value) {
  bool valid = Dart_IsInteger(value_obj);
  if (valid) {
    Dart_Handle result = Dart_IntegerFitsIntoInt64(value_obj, &valid);
    if (Dart_IsError(result)) {
      Dart_PropagateError(result);
    }
  }
  if (!valid) return false;
  Dart_Handle result = Dart_IntegerToInt64(value_obj, value);
  if (Dart_IsError(result)) {
    Dart_PropagateError(result);
  }
  return true;
}

const char* DartUtils::GetStringValue(Dart_Handle str_obj) {
  const char* cstring = nullptr;
  Dart_Handle result = Dart_StringToCString(str_obj, &cstring);
  if (Dart_IsError(result)) {
    Dart_PropagateError(result);
  }
  return cstring;
}

bool DartUtils::GetBooleanValue(Dart_Handle bool_obj) {
  bool value = false;
  Dart_Handle result = Dart_BooleanValue(bool_obj, &value);
  if (Dart_IsError(result)) {
    Dart_PropagateError(result);
  }
  return value;
}

bool DartUtils::GetNativeBooleanArgument(Dart_NativeArguments args,
                                         intptr_t index) {
  bool value = false;
  Dart_Handle result = Dart_GetNativeBooleanArgument(args, index, &value);
  if (Dart_IsError(result)) {
    Dart_PropagateError(result);
  }
  return value;
}

int64_t DartUtils::GetNativeIntegerArgument(Dart_NativeArguments args,
                                            intptr_t index) {
  int64_t value = 0;
  Dart_Handle result = Dart_GetNativeIntegerArgument(args, index, &value);
  if (Dart_IsError(result)) {
    Dart_PropagateError(result);
  }
  return value;
}

intptr_t DartUtils::GetNativeIntptrArgument(Dart_NativeArguments args,
                                            intptr_t index) {
  int64_t value = GetNativeIntegerArgument(args, index);
  if (value < kIntptrMin || kIntptrMax < value) {
    Dart_PropagateError(Dart_NewApiError("Value outside intptr_t range"));
  }
  return static_cast<intptr_t>(value);
}

const char* DartUtils::GetNativeStringArgument(Dart_NativeArguments args,
                                               intptr_t index) {
  char* tmp = nullptr;
  Dart_Handle result =
      Dart_GetNativeStringArgument(args, index, reinterpret_cast<void**>(&tmp));
  if (Dart_IsError(result)) {
    Dart_PropagateError(result);
  }
  if (tmp != nullptr) {
    return tmp;
  }
  const char* cstring = nullptr;
  result = Dart_StringToCString(result, &cstring);
  if (Dart_IsError(result)) {
    Dart_PropagateError(result);
  }
  ASSERT(cstring != nullptr);
  return cstring;
}

const char* DartUtils::GetNativeTypedDataArgument(Dart_NativeArguments args,
                                                  intptr_t index) {
  Dart_Handle handle = Dart_GetNativeArgument(args, index);
  TypedDataScope data(handle);
  ASSERT(data.type() == Dart_TypedData_kUint8);
  return data.GetScopedCString();
}

Dart_Handle DartUtils::SetIntegerField(Dart_Handle handle,
                                       const char* name,
                                       int64_t val) {
  return Dart_SetField(handle, NewString(name), Dart_NewInteger(val));
}

Dart_Handle DartUtils::SetStringField(Dart_Handle handle,
                                      const char* name,
                                      const char* val) {
  return Dart_SetField(handle, NewString(name), NewString(val));
}

bool DartUtils::IsDartSchemeURL(const char* url_name) {
  static const intptr_t kDartSchemeLen = strlen(kDartScheme);
  // If the URL starts with "dart:" then it is considered as a special
  // library URL which is handled differently from other URLs.
  return (strncmp(url_name, kDartScheme, kDartSchemeLen) == 0);
}

bool DartUtils::IsHttpSchemeURL(const char* url_name) {
  static const intptr_t kHttpSchemeLen = strlen(kHttpScheme);
  return (strncmp(url_name, kHttpScheme, kHttpSchemeLen) == 0);
}

bool DartUtils::IsDartIOLibURL(const char* url_name) {
  return (strcmp(url_name, kIOLibURL) == 0);
}

bool DartUtils::IsDartCLILibURL(const char* url_name) {
  return (strcmp(url_name, kCLILibURL) == 0);
}

bool DartUtils::IsDartHttpLibURL(const char* url_name) {
  return (strcmp(url_name, kHttpLibURL) == 0);
}

bool DartUtils::IsDartBuiltinLibURL(const char* url_name) {
  return (strcmp(url_name, kBuiltinLibURL) == 0);
}

const char* DartUtils::RemoveScheme(const char* url) {
  const char* colon = strchr(url, ':');
  if (colon == nullptr) {
    return url;
  } else {
    return colon + 1;
  }
}

char* DartUtils::DirName(const char* url) {
  const char* slash = strrchr(url, File::PathSeparator()[0]);
  if (slash == nullptr) {
    return Utils::StrDup(url);
  } else {
    return Utils::StrNDup(url, slash - url + 1);
  }
}

void* DartUtils::OpenFile(const char* name, bool write) {
  File* file =
      File::Open(nullptr, name, write ? File::kWriteTruncate : File::kRead);
  return reinterpret_cast<void*>(file);
}

void* DartUtils::OpenFileUri(const char* uri, bool write) {
  File* file =
      File::OpenUri(nullptr, uri, write ? File::kWriteTruncate : File::kRead);
  return reinterpret_cast<void*>(file);
}

void DartUtils::ReadFile(uint8_t** data, intptr_t* len, void* stream) {
  ASSERT(data != nullptr);
  ASSERT(len != nullptr);
  ASSERT(stream != nullptr);
  File* file_stream = reinterpret_cast<File*>(stream);
  int64_t file_len = file_stream->Length();
  if ((file_len < 0) || (file_len > kIntptrMax)) {
    *data = nullptr;
    *len = -1;  // Indicates read was not successful.
    return;
  }
  *len = static_cast<intptr_t>(file_len);
  *data = reinterpret_cast<uint8_t*>(malloc(*len));
  if (!file_stream->ReadFully(*data, *len)) {
    free(*data);
    *data = nullptr;
    *len = -1;  // Indicates read was not successful.
    return;
  }
}

void DartUtils::WriteFile(const void* buffer,
                          intptr_t num_bytes,
                          void* stream) {
  ASSERT(stream != nullptr);
  File* file_stream = reinterpret_cast<File*>(stream);
  bool bytes_written = file_stream->WriteFully(buffer, num_bytes);
  ASSERT(bytes_written);
}

void DartUtils::CloseFile(void* stream) {
  File* file = reinterpret_cast<File*>(stream);
  file->Release();
}

bool DartUtils::EntropySource(uint8_t* buffer, intptr_t length) {
  return Crypto::GetRandomBytes(length, buffer);
}

static Dart_Handle SingleArgDart_Invoke(Dart_Handle lib,
                                        const char* method,
                                        Dart_Handle arg) {
  const int kNumArgs = 1;
  Dart_Handle dart_args[kNumArgs];
  dart_args[0] = arg;
  return Dart_Invoke(lib, DartUtils::NewString(method), kNumArgs, dart_args);
}

// TODO(iposva): Allocate from the zone instead of leaking error string
// here. On the other hand the binary is about to exit anyway.
#define SET_ERROR_MSG(error_msg, format, ...)                                  \
  intptr_t len = snprintf(nullptr, 0, format, __VA_ARGS__);                    \
  char* msg = reinterpret_cast<char*>(malloc(len + 1));                        \
  snprintf(msg, len + 1, format, __VA_ARGS__);                                 \
  *error_msg = msg

static uint8_t* ReadFileFully(const char* filename,
                              intptr_t* file_len,
                              const char** error_msg) {
  *file_len = -1;
  void* stream = DartUtils::OpenFile(filename, false);
  if (stream == nullptr) {
    SET_ERROR_MSG(error_msg, "Unable to open file: %s", filename);
    return nullptr;
  }
  uint8_t* text_buffer = nullptr;
  DartUtils::ReadFile(&text_buffer, file_len, stream);
  if (text_buffer == nullptr || *file_len == -1) {
    *error_msg = "Unable to read file contents";
    text_buffer = nullptr;
  }
  DartUtils::CloseFile(stream);
  return text_buffer;
}

Dart_Handle DartUtils::ReadStringFromFile(const char* filename) {
  const char* error_msg = nullptr;
  intptr_t len;
  uint8_t* text_buffer = ReadFileFully(filename, &len, &error_msg);
  if (text_buffer == nullptr) {
    return Dart_NewApiError(error_msg);
  }
  Dart_Handle str = Dart_NewStringFromUTF8(text_buffer, len);
  free(text_buffer);
  return str;
}

Dart_Handle DartUtils::MakeUint8Array(const void* buffer, intptr_t len) {
  Dart_Handle array = Dart_NewTypedData(Dart_TypedData_kUint8, len);
  RETURN_IF_ERROR(array);
  {
    Dart_TypedData_Type td_type;
    void* td_data;
    intptr_t td_len;
    Dart_Handle result =
        Dart_TypedDataAcquireData(array, &td_type, &td_data, &td_len);
    RETURN_IF_ERROR(result);
    ASSERT(td_type == Dart_TypedData_kUint8);
    ASSERT(td_len == len);
    ASSERT(td_data != nullptr);
    memmove(td_data, buffer, td_len);
    result = Dart_TypedDataReleaseData(array);
    RETURN_IF_ERROR(result);
  }
  return array;
}

Dart_Handle DartUtils::SetWorkingDirectory() {
  Dart_Handle directory = NewString(original_working_directory);
  return SingleArgDart_Invoke(LookupBuiltinLib(), "_setWorkingDirectory",
                              directory);
}

Dart_Handle DartUtils::ResolveScript(Dart_Handle url) {
  const int kNumArgs = 1;
  Dart_Handle dart_args[kNumArgs];
  dart_args[0] = url;
  return Dart_Invoke(DartUtils::LookupBuiltinLib(),
                     NewString("_resolveScriptUri"), kNumArgs, dart_args);
}

static bool CheckMagicNumber(const uint8_t* buffer,
                             intptr_t buffer_length,
                             const MagicNumberData& magic_number) {
  if ((buffer_length >= magic_number.length)) {
    return memcmp(buffer, magic_number.bytes, magic_number.length) == 0;
  }
  return false;
}

DartUtils::MagicNumber DartUtils::SniffForMagicNumber(const char* filename) {
  MagicNumber magic_number = DartUtils::kUnknownMagicNumber;
  ASSERT(kMaxMagicNumberSize == appjit_magic_number.length);
  ASSERT(aotelf_magic_number.length <= appjit_magic_number.length);
  ASSERT(static_cast<intptr_t>(sizeof(mach_o::mach_header::magic)) <=
         appjit_magic_number.length);
  ASSERT(aotcoff_arm32_magic_number.length <= appjit_magic_number.length);
  ASSERT(aotcoff_arm64_magic_number.length <= appjit_magic_number.length);
  ASSERT(aotcoff_riscv32_magic_number.length <= appjit_magic_number.length);
  ASSERT(aotcoff_riscv64_magic_number.length <= appjit_magic_number.length);
  ASSERT(kernel_magic_number.length <= appjit_magic_number.length);
  ASSERT(kernel_list_magic_number.length <= appjit_magic_number.length);
  ASSERT(gzip_magic_number.length <= appjit_magic_number.length);
  if (File::GetType(nullptr, filename, true) == File::kIsFile) {
    File* file = File::Open(nullptr, filename, File::kRead);
    if (file != nullptr) {
      RefCntReleaseScope<File> rs(file);
      uint8_t header[kMaxMagicNumberSize];
      if (file->ReadFully(&header, kMaxMagicNumberSize)) {
        magic_number = DartUtils::SniffForMagicNumber(header, sizeof(header));
      }
    }
  }
  return magic_number;
}

DartUtils::MagicNumber DartUtils::SniffForMagicNumber(const uint8_t* buffer,
                                                      intptr_t buffer_length) {
  if (CheckMagicNumber(buffer, buffer_length, appjit_magic_number)) {
    return kAppJITMagicNumber;
  }

  if (CheckMagicNumber(buffer, buffer_length, kernel_magic_number)) {
    return kKernelMagicNumber;
  }

  if (CheckMagicNumber(buffer, buffer_length, kernel_list_magic_number)) {
    return kKernelListMagicNumber;
  }

  if (CheckMagicNumber(buffer, buffer_length, gzip_magic_number)) {
    return kGzipMagicNumber;
  }

  if (CheckMagicNumber(buffer, buffer_length, gzip_magic_number)) {
    return kGzipMagicNumber;
  }

  if (CheckMagicNumber(buffer, buffer_length, aotelf_magic_number)) {
    return kAotELFMagicNumber;
  }

  // Mach-O magic numbers are reported by whether the endianness of the file
  // matches the endianness of the system. Here, we only bother looking for
  // host-endian magic numbers, as our Mach-O parsing code won't handle the
  // reverse endian case.
  if (static_cast<intptr_t>(sizeof(mach_o::mach_header::magic)) <=
      buffer_length) {
    const uint32_t magic =
        reinterpret_cast<const mach_o::mach_header*>(buffer)->magic;
    if (magic == mach_o::MH_MAGIC) {
      return kAotMachO32MagicNumber;
    } else if (magic == mach_o::MH_MAGIC_64) {
      return kAotMachO64MagicNumber;
    }
  }

  if (CheckMagicNumber(buffer, buffer_length, aotcoff_arm32_magic_number)) {
    return kAotCoffARM32MagicNumber;
  }

  if (CheckMagicNumber(buffer, buffer_length, aotcoff_arm64_magic_number)) {
    return kAotCoffARM64MagicNumber;
  }

  if (CheckMagicNumber(buffer, buffer_length, aotcoff_riscv32_magic_number)) {
    return kAotCoffRISCV32MagicNumber;
  }

  if (CheckMagicNumber(buffer, buffer_length, aotcoff_riscv64_magic_number)) {
    return kAotCoffRISCV64MagicNumber;
  }

  return kUnknownMagicNumber;
}

Dart_Handle DartUtils::PrepareBuiltinLibrary(Dart_Handle builtin_lib,
                                             Dart_Handle internal_lib,
                                             bool is_service_isolate,
                                             bool trace_loading) {
  // Setup the internal library's 'internalPrint' function.
  Dart_Handle print =
      Dart_Invoke(builtin_lib, NewString("_getPrintClosure"), 0, nullptr);
  RETURN_IF_ERROR(print);
  Dart_Handle result =
      Dart_SetField(internal_lib, NewString("_printClosure"), print);
  RETURN_IF_ERROR(result);

  if (!is_service_isolate) {
    if (IsWindowsHost()) {
      result = Dart_SetField(builtin_lib, NewString("_isWindows"), Dart_True());
      RETURN_IF_ERROR(result);
    }
    if (trace_loading) {
      result =
          Dart_SetField(builtin_lib, NewString("_traceLoading"), Dart_True());
      RETURN_IF_ERROR(result);
    }
    // Set current working directory.
    result = SetWorkingDirectory();
    RETURN_IF_ERROR(result);
  }
  return Dart_True();
}

Dart_Handle DartUtils::PrepareCoreLibrary(Dart_Handle core_lib,
                                          Dart_Handle io_lib,
                                          bool is_service_isolate) {
  if (!is_service_isolate) {
    // Setup the 'Uri.base' getter in dart:core.
    Dart_Handle uri_base =
        Dart_Invoke(io_lib, NewString("_getUriBaseClosure"), 0, nullptr);
    RETURN_IF_ERROR(uri_base);
    Dart_Handle result =
        Dart_SetField(core_lib, NewString("_uriBaseClosure"), uri_base);
    RETURN_IF_ERROR(result);
  }
  return Dart_True();
}

Dart_Handle DartUtils::PrepareAsyncLibrary(Dart_Handle async_lib,
                                           Dart_Handle isolate_lib,
                                           bool flag_profile_microtasks) {
#if !defined(PRODUCT)
  if (flag_profile_microtasks) {
    Dart_Handle microtask_mirror_queue_type_name =
        Dart_NewStringFromCString("_MicrotaskMirrorQueue");
    RETURN_IF_ERROR(microtask_mirror_queue_type_name);

    Dart_Handle microtask_mirror_queue_type =
        Dart_GetNonNullableType(async_lib, microtask_mirror_queue_type_name,
                                /*number_of_type_arguments=*/0,
                                /*type_arguments=*/nullptr);
    RETURN_IF_ERROR(microtask_mirror_queue_type);

    Dart_Handle should_profile_microtasks_field_name =
        Dart_NewStringFromCString("_shouldProfileMicrotasks");
    RETURN_IF_ERROR(should_profile_microtasks_field_name);

    Dart_Handle set_field_result =
        Dart_SetField(microtask_mirror_queue_type,
                      should_profile_microtasks_field_name, Dart_True());
    RETURN_IF_ERROR(set_field_result);
  }
#endif  // !defined(PRODUCT)

  Dart_Handle schedule_immediate_closure =
      Dart_Invoke(isolate_lib, NewString("_getIsolateScheduleImmediateClosure"),
                  0, nullptr);
  RETURN_IF_ERROR(schedule_immediate_closure);
  Dart_Handle args[1];
  args[0] = schedule_immediate_closure;
  return Dart_Invoke(async_lib, NewString("_setScheduleImmediateClosure"), 1,
                     args);
}

Dart_Handle DartUtils::PrepareIOLibrary(Dart_Handle io_lib) {
  return Dart_Invoke(io_lib, NewString("_setupHooks"), 0, nullptr);
}

Dart_Handle DartUtils::PrepareIsolateLibrary(Dart_Handle isolate_lib) {
  return Dart_Invoke(isolate_lib, NewString("_setupHooks"), 0, nullptr);
}

Dart_Handle DartUtils::PrepareCLILibrary(Dart_Handle cli_lib) {
  return Dart_Null();
}

Dart_Handle DartUtils::SetupPackageConfig(const char* packages_config) {
  Dart_Handle result = Dart_Null();

  if (packages_config != nullptr) {
    result = NewString(packages_config);
    RETURN_IF_ERROR(result);
    const int kNumArgs = 1;
    Dart_Handle dart_args[kNumArgs];
    dart_args[0] = result;
    result = Dart_Invoke(DartUtils::LookupBuiltinLib(),
                         NewString("_setPackagesMap"), kNumArgs, dart_args);
  }
  return result;
}

Dart_Handle DartUtils::PrepareForScriptLoading(bool is_service_isolate,
                                               bool trace_loading,
                                               bool flag_profile_microtasks) {
  // First ensure all required libraries are available.
  Dart_Handle url = NewString(kCoreLibURL);
  RETURN_IF_ERROR(url);
  Dart_Handle core_lib = Dart_LookupLibrary(url);
  RETURN_IF_ERROR(core_lib);
  url = NewString(kAsyncLibURL);
  RETURN_IF_ERROR(url);
  Dart_Handle async_lib = Dart_LookupLibrary(url);
  RETURN_IF_ERROR(async_lib);
  url = NewString(kIsolateLibURL);
  RETURN_IF_ERROR(url);
  Dart_Handle isolate_lib = Dart_LookupLibrary(url);
  RETURN_IF_ERROR(isolate_lib);
  url = NewString(kInternalLibURL);
  RETURN_IF_ERROR(url);
  Dart_Handle internal_lib = Dart_LookupLibrary(url);
  RETURN_IF_ERROR(internal_lib);
  Dart_Handle builtin_lib =
      Builtin::LoadAndCheckLibrary(Builtin::kBuiltinLibrary);
  RETURN_IF_ERROR(builtin_lib);
  Builtin::SetNativeResolver(Builtin::kBuiltinLibrary);
  Dart_Handle io_lib = Builtin::LoadAndCheckLibrary(Builtin::kIOLibrary);
  RETURN_IF_ERROR(io_lib);
  Builtin::SetNativeResolver(Builtin::kIOLibrary);
  Dart_Handle cli_lib = Builtin::LoadAndCheckLibrary(Builtin::kCLILibrary);
  RETURN_IF_ERROR(cli_lib);
  Builtin::SetNativeResolver(Builtin::kCLILibrary);
  Dart_Handle concurrent_lib =
      Builtin::LoadAndCheckLibrary(Builtin::kConcurrentLibrary);
  RETURN_IF_ERROR(concurrent_lib);
  Builtin::SetNativeResolver(Builtin::kConcurrentLibrary);

  // We need to ensure that all the scripts loaded so far are finalized
  // as we are about to invoke some Dart code below to setup closures.
  Dart_Handle result = Dart_FinalizeLoading(false);
  RETURN_IF_ERROR(result);

  result = PrepareBuiltinLibrary(builtin_lib, internal_lib, is_service_isolate,
                                 trace_loading);
  RETURN_IF_ERROR(result);

  RETURN_IF_ERROR(
      PrepareAsyncLibrary(async_lib, isolate_lib, flag_profile_microtasks));
  RETURN_IF_ERROR(PrepareCoreLibrary(core_lib, io_lib, is_service_isolate));
  RETURN_IF_ERROR(PrepareIsolateLibrary(isolate_lib));
  RETURN_IF_ERROR(PrepareIOLibrary(io_lib));
  RETURN_IF_ERROR(PrepareCLILibrary(cli_lib));
  RETURN_IF_ERROR(PrepareCLILibrary(concurrent_lib));
  return result;
}

Dart_Handle DartUtils::SetupIOLibrary(const char* namespc_path,
                                      const char* script_uri,
                                      bool disable_exit) {
  Dart_Handle io_lib_url = NewString(kIOLibURL);
  RETURN_IF_ERROR(io_lib_url);
  Dart_Handle io_lib = Dart_LookupLibrary(io_lib_url);
  RETURN_IF_ERROR(io_lib);

  if (namespc_path != nullptr) {
    Dart_Handle namespc_type = GetDartType(DartUtils::kIOLibURL, "_Namespace");
    RETURN_IF_ERROR(namespc_type);
    Dart_Handle args[1];
    args[0] = NewString(namespc_path);
    RETURN_IF_ERROR(args[0]);
    Dart_Handle result =
        Dart_Invoke(namespc_type, NewString("_setupNamespace"), 1, args);
    RETURN_IF_ERROR(result);
  }

  if (disable_exit) {
    Dart_Handle embedder_config_type =
        GetDartType(DartUtils::kIOLibURL, "_EmbedderConfig");
    RETURN_IF_ERROR(embedder_config_type);
    Dart_Handle result = Dart_SetField(embedder_config_type,
                                       NewString("_mayExit"), Dart_False());
    RETURN_IF_ERROR(result);
  }

  Dart_Handle platform_type = GetDartType(DartUtils::kIOLibURL, "_Platform");
  RETURN_IF_ERROR(platform_type);
  Dart_Handle script_name = NewString("_nativeScript");
  RETURN_IF_ERROR(script_name);
  Dart_Handle dart_script = NewString(script_uri);
  RETURN_IF_ERROR(dart_script);
  Dart_Handle set_script_name =
      Dart_SetField(platform_type, script_name, dart_script);
  RETURN_IF_ERROR(set_script_name);

#if !defined(PRODUCT)
  Dart_Handle network_profiling_type =
      GetDartType(DartUtils::kIOLibURL, "_NetworkProfiling");
  RETURN_IF_ERROR(network_profiling_type);
  Dart_Handle result =
      Dart_Invoke(network_profiling_type,
                  NewString("_registerServiceExtension"), 0, nullptr);
  RETURN_IF_ERROR(result);
#endif  // !defined(PRODUCT)
  return Dart_Null();
}

bool DartUtils::PostNull(Dart_Port port_id) {
  // Post a message with just the null object.
  return Dart_PostCObject(port_id, CObject::Null()->AsApiCObject());
}

bool DartUtils::PostInt32(Dart_Port port_id, int32_t value) {
  // Post a message with the integer value.
  int32_t min = 0xc0000000;  // -1073741824
  int32_t max = 0x3fffffff;  // 1073741823
  ASSERT(min <= value && value < max);
  Dart_CObject object;
  object.type = Dart_CObject_kInt32;
  object.value.as_int32 = value;
  return Dart_PostCObject(port_id, &object);
}

bool DartUtils::PostInt64(Dart_Port port_id, int64_t value) {
  // Post a message with the integer value.
  Dart_CObject object;
  object.type = Dart_CObject_kInt64;
  object.value.as_int64 = value;
  return Dart_PostCObject(port_id, &object);
}

bool DartUtils::PostString(Dart_Port port_id, const char* value) {
  Dart_CObject* object = CObject::NewString(value);
  return Dart_PostCObject(port_id, object);
}

Dart_Handle DartUtils::GetDartType(const char* library_url,
                                   const char* class_name) {
  return Dart_GetNonNullableType(Dart_LookupLibrary(NewString(library_url)),
                                 NewString(class_name), 0, nullptr);
}

Dart_Handle DartUtils::NewDartOSError() {
  // Extract the current OS error.
  OSError os_error;
  return NewDartOSError(&os_error);
}

Dart_Handle DartUtils::NewDartOSError(OSError* os_error) {
  // Create a dart:io OSError object with the information retrieved from the OS.
  Dart_Handle type = GetDartType(kIOLibURL, "OSError");
  ASSERT(!Dart_IsError(type));
  Dart_Handle args[2];
  args[0] = NewString(os_error->message());
  args[1] = Dart_NewInteger(os_error->code());
  return Dart_New(type, Dart_Null(), 2, args);
}

Dart_Handle DartUtils::NewDartExceptionWithOSError(const char* library_url,
                                                   const char* exception_name,
                                                   const char* message,
                                                   Dart_Handle os_error) {
  // Create a Dart Exception object with a message and an OSError.
  Dart_Handle type = GetDartType(library_url, exception_name);
  ASSERT(!Dart_IsError(type));
  Dart_Handle args[2];
  args[0] = NewString(message);
  args[1] = os_error;
  return Dart_New(type, Dart_Null(), 2, args);
}

Dart_Handle DartUtils::NewDartExceptionWithMessage(const char* library_url,
                                                   const char* exception_name,
                                                   const char* message) {
  // Create a Dart Exception object with a message.
  Dart_Handle type = GetDartType(library_url, exception_name);
  ASSERT(!Dart_IsError(type));
  if (message != nullptr) {
    Dart_Handle args[1];
    args[0] = NewString(message);
    return Dart_New(type, Dart_Null(), 1, args);
  } else {
    return Dart_New(type, Dart_Null(), 0, nullptr);
  }
}

Dart_Handle DartUtils::NewDartArgumentError(const char* message) {
  return NewDartExceptionWithMessage(kCoreLibURL, "ArgumentError", message);
}

Dart_Handle DartUtils::NewDartFormatException(const char* message) {
  return NewDartExceptionWithMessage(kCoreLibURL, "FormatException", message);
}

Dart_Handle DartUtils::NewDartUnsupportedError(const char* message) {
  return NewDartExceptionWithMessage(kCoreLibURL, "UnsupportedError", message);
}

Dart_Handle DartUtils::NewDartIOException(const char* exception_name,
                                          const char* message,
                                          Dart_Handle os_error) {
  // Create a dart:io exception object of the given type.
  return NewDartExceptionWithOSError(kIOLibURL, exception_name, message,
                                     os_error);
}

Dart_Handle DartUtils::NewError(const char* format, ...) {
  va_list measure_args;
  va_start(measure_args, format);
  intptr_t len = Utils::VSNPrint(nullptr, 0, format, measure_args);
  va_end(measure_args);

  char* buffer = reinterpret_cast<char*>(Dart_ScopeAllocate(len + 1));
  va_list print_args;
  va_start(print_args, format);
  Utils::VSNPrint(buffer, (len + 1), format, print_args);
  va_end(print_args);

  return Dart_NewApiError(buffer);
}

Dart_Handle DartUtils::NewInternalError(const char* message) {
  return NewDartExceptionWithMessage(kCoreLibURL, "_InternalError", message);
}

Dart_Handle DartUtils::NewStringFormatted(const char* format, ...) {
  va_list args;
  va_start(args, format);
  char* result = ScopedCStringVFormatted(format, args);
  va_end(args);
  return NewString(result);
}

char* DartUtils::ScopedCStringVFormatted(const char* format, va_list args) {
  va_list measure_args;
  va_copy(measure_args, args);
  intptr_t len = Utils::VSNPrint(nullptr, 0, format, measure_args);
  if (len < 0) {
    return nullptr;
  }
  va_end(measure_args);

  char* buffer = ScopedCString(len + 1);
  va_list print_args;
  va_copy(print_args, args);
  len = Utils::VSNPrint(buffer, (len + 1), format, print_args);
  if (len < 0) {
    return nullptr;
  }
  va_end(print_args);
  return buffer;
}

char* DartUtils::ScopedCStringFormatted(const char* format, ...) {
  va_list args;
  va_start(args, format);
  char* result = ScopedCStringVFormatted(format, args);
  va_end(args);
  return result;
}

bool DartUtils::SetOriginalWorkingDirectory() {
  // If we happen to re-initialize the Dart VM multiple times, make sure to free
  // the old string (allocated by getcwd()) before setting a new one.
  if (original_working_directory != nullptr) {
    free(const_cast<char*>(original_working_directory));
  }
  original_working_directory = Directory::CurrentNoScope();
  return original_working_directory != nullptr;
}

void DartUtils::SetEnvironment(dart::SimpleHashMap* environment) {
  environment_ = environment;
}

Dart_Handle DartUtils::EnvironmentCallback(Dart_Handle name) {
  uint8_t* utf8_array;
  intptr_t utf8_len;
  Dart_Handle result = Dart_Null();
  Dart_Handle handle = Dart_StringToUTF8(name, &utf8_array, &utf8_len);
  if (Dart_IsError(handle)) {
    handle = Dart_ThrowException(
        DartUtils::NewDartArgumentError(Dart_GetError(handle)));
  } else {
    char* name_chars = reinterpret_cast<char*>(malloc(utf8_len + 1));
    memmove(name_chars, utf8_array, utf8_len);
    name_chars[utf8_len] = '\0';
    const char* value = nullptr;
    if (environment_ != nullptr) {
      SimpleHashMap::Entry* entry =
          environment_->Lookup(GetHashmapKeyFromString(name_chars),
                               SimpleHashMap::StringHash(name_chars), false);
      if (entry != nullptr) {
        value = reinterpret_cast<char*>(entry->value);
      }
    }
    if (value != nullptr) {
      result = Dart_NewStringFromUTF8(reinterpret_cast<const uint8_t*>(value),
                                      strlen(value));
      if (Dart_IsError(result)) {
        result = Dart_Null();
      }
    }
    free(name_chars);
  }
  return result;
}

// Statically allocated Dart_CObject instances for immutable
// objects. As these will be used by different threads the use of
// these depends on the fact that the marking internally in the
// Dart_CObject structure is not marking simple value objects.
Dart_CObject CObject::api_null_ = {Dart_CObject_kNull, {false}};
Dart_CObject CObject::api_true_ = {Dart_CObject_kBool, {true}};
Dart_CObject CObject::api_false_ = {Dart_CObject_kBool, {false}};
CObject CObject::null_(&api_null_);
CObject CObject::true_(&api_true_);
CObject CObject::false_(&api_false_);

CObject* CObject::Null() {
  return &null_;
}

CObject* CObject::True() {
  return &true_;
}

CObject* CObject::False() {
  return &false_;
}

CObject* CObject::Bool(bool value) {
  return value ? &true_ : &false_;
}

Dart_CObject* CObject::New(Dart_CObject_Type type, int additional_bytes) {
  Dart_CObject* cobject = reinterpret_cast<Dart_CObject*>(
      Dart_ScopeAllocate(sizeof(Dart_CObject) + additional_bytes));
  cobject->type = type;
  return cobject;
}

Dart_CObject* CObject::NewInt32(int32_t value) {
  Dart_CObject* cobject = New(Dart_CObject_kInt32);
  cobject->value.as_int32 = value;
  return cobject;
}

Dart_CObject* CObject::NewInt64(int64_t value) {
  Dart_CObject* cobject = New(Dart_CObject_kInt64);
  cobject->value.as_int64 = value;
  return cobject;
}

Dart_CObject* CObject::NewIntptr(intptr_t value) {
  // Pointer values passed as intptr_t are always send as int64_t.
  Dart_CObject* cobject = New(Dart_CObject_kInt64);
  cobject->value.as_int64 = value;
  return cobject;
}

Dart_CObject* CObject::NewDouble(double value) {
  Dart_CObject* cobject = New(Dart_CObject_kDouble);
  cobject->value.as_double = value;
  return cobject;
}

Dart_CObject* CObject::NewString(const char* str) {
  intptr_t length = strlen(str);
  Dart_CObject* cobject = New(Dart_CObject_kString, length + 1);
  char* payload = reinterpret_cast<char*>(cobject + 1);
  memmove(payload, str, length + 1);
  cobject->value.as_string = payload;
  return cobject;
}

Dart_CObject* CObject::NewArray(intptr_t length) {
  Dart_CObject* cobject =
      New(Dart_CObject_kArray, length * sizeof(Dart_CObject*));  // NOLINT
  cobject->value.as_array.length = length;
  cobject->value.as_array.values =
      reinterpret_cast<Dart_CObject**>(cobject + 1);
  return cobject;
}

Dart_CObject* CObject::NewUint8Array(const void* data, intptr_t length) {
  Dart_CObject* cobject = New(Dart_CObject_kTypedData, length);
  memmove(reinterpret_cast<uint8_t*>(cobject + 1), data, length);
  cobject->value.as_typed_data.type = Dart_TypedData_kUint8;
  cobject->value.as_typed_data.length = length;
  cobject->value.as_typed_data.values =
      reinterpret_cast<const uint8_t*>(cobject + 1);
  return cobject;
}

Dart_CObject* CObject::NewExternalUint8Array(intptr_t length,
                                             uint8_t* data,
                                             void* peer,
                                             Dart_HandleFinalizer callback) {
  Dart_CObject* cobject = New(Dart_CObject_kExternalTypedData);
  cobject->value.as_external_typed_data.type = Dart_TypedData_kUint8;
  cobject->value.as_external_typed_data.length = length;
  cobject->value.as_external_typed_data.data = data;
  cobject->value.as_external_typed_data.peer = peer;
  cobject->value.as_external_typed_data.callback = callback;
  return cobject;
}

Dart_CObject* CObject::NewNativePointer(intptr_t ptr,
                                        intptr_t size,
                                        Dart_HandleFinalizer callback) {
  Dart_CObject* cobject = New(Dart_CObject_kNativePointer);
  cobject->value.as_native_pointer.ptr = ptr;
  cobject->value.as_native_pointer.size = size;
  cobject->value.as_native_pointer.callback = callback;
  return cobject;
}

Dart_CObject* CObject::NewIOBuffer(int64_t length) {
  // Make sure that we do not have an integer overflow here. Actual check
  // against max elements will be done at the time of writing, as the constant
  // is not part of the public API.
  if ((length < 0) || (length > kIntptrMax)) {
    return nullptr;
  }
  uint8_t* data = IOBuffer::Allocate(static_cast<intptr_t>(length));
  if (data == nullptr) {
    return nullptr;
  }
  return NewExternalUint8Array(static_cast<intptr_t>(length), data, data,
                               IOBuffer::Finalizer);
}

void CObject::ShrinkIOBuffer(Dart_CObject* cobject, int64_t new_length) {
  if (cobject == nullptr) return;
  ASSERT(cobject->type == Dart_CObject_kExternalTypedData);

  const auto old_data = cobject->value.as_external_typed_data.data;
  const auto old_length = cobject->value.as_external_typed_data.length;

  // We only shrink IOBuffers, never grow them.
  ASSERT(0 <= new_length && new_length <= old_length);

  // We only reallocate if we think the freed space is worth reallocating.
  // We consider it worthwhile when freed space is >=25% and we have at
  // least 100 free bytes.
  const auto free_memory = old_length - new_length;
  if ((old_length >> 2) <= free_memory && 100 <= free_memory) {
    const auto new_data = IOBuffer::Reallocate(old_data, new_length);
    if (new_data != nullptr) {
      cobject->value.as_external_typed_data.data = new_data;
      cobject->value.as_external_typed_data.peer = new_data;
    }
  }

  // The typed data object always has to have the shranken length.
  cobject->value.as_external_typed_data.length = new_length;
}

void CObject::FreeIOBufferData(Dart_CObject* cobject) {
  ASSERT(cobject->type == Dart_CObject_kExternalTypedData);
  cobject->value.as_external_typed_data.callback(
      nullptr, cobject->value.as_external_typed_data.peer);
  cobject->value.as_external_typed_data.data = nullptr;
}

CObject* CObject::IllegalArgumentError() {
  CObjectArray* result = new CObjectArray(CObject::NewArray(1));
  result->SetAt(0, new CObjectInt32(CObject::NewInt32(kArgumentError)));
  return result;
}

CObject* CObject::FileClosedError() {
  CObjectArray* result = new CObjectArray(CObject::NewArray(1));
  result->SetAt(0, new CObjectInt32(CObject::NewInt32(kFileClosedError)));
  return result;
}

CObject* CObject::NewOSError() {
  OSError os_error;
  return NewOSError(&os_error);
}

CObject* CObject::NewOSError(OSError* os_error) {
  CObject* error_message =
      new CObjectString(CObject::NewString(os_error->message()));
  CObjectArray* result = new CObjectArray(CObject::NewArray(3));
  result->SetAt(0, new CObjectInt32(CObject::NewInt32(kOSError)));
  result->SetAt(1, new CObjectInt32(CObject::NewInt32(os_error->code())));
  result->SetAt(2, error_message);
  return result;
}

}  // namespace bin
}  // namespace dart
