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

#if !defined(DART_PRECOMPILED_RUNTIME)

#include <functional>
#include <memory>

#include "bin/directory.h"
#include "bin/error_exit.h"
#include "bin/exe_utils.h"
#include "bin/file.h"
#include "bin/lockers.h"
#include "bin/main_options.h"
#include "bin/platform.h"
#include "bin/process.h"
#include "include/dart_embedder_api.h"
#include "platform/utils.h"

#define CHECK_RESULT(result)                                                   \
  if (Dart_IsError(result)) {                                                  \
    ProcessError(Dart_GetError(result), kErrorExitCode);                       \
    if (send_port_id != ILLEGAL_PORT) {                                        \
      Dart_CloseNativePort(send_port_id);                                      \
    }                                                                          \
    Dart_ExitScope();                                                          \
    Dart_ShutdownIsolate();                                                    \
    return;                                                                    \
  }

namespace dart {
namespace bin {

DartDevIsolate::DartDevRunner DartDevIsolate::runner_ =
    DartDevIsolate::DartDevRunner();
bool DartDevIsolate::should_run_dart_dev_ = false;
bool DartDevIsolate::print_usage_error_ = false;
Monitor* DartDevIsolate::DartDevRunner::monitor_ = new Monitor();
DartDevIsolate::DartDev_Result DartDevIsolate::DartDevRunner::result_ =
    DartDevIsolate::DartDev_Result_Unknown;
char** DartDevIsolate::DartDevRunner::script_ = nullptr;
char** DartDevIsolate::DartDevRunner::package_config_override_ = nullptr;
std::unique_ptr<char*[], void (*)(char*[])>
    DartDevIsolate::DartDevRunner::argv_ =
        std::unique_ptr<char*[], void (*)(char**)>(nullptr, [](char**) {});
intptr_t DartDevIsolate::DartDevRunner::argc_ = 0;

bool DartDevIsolate::ShouldParseCommand(const char* script_uri) {
  // If script_uri is a known DartDev command, we should not try to run it.
  //
  // Otherwise if script_uri is not a file path or of a known URI scheme, we
  // assume this is a mistyped DartDev command.
  //
  // This should be kept in sync with the commands in
  // `pkg/dartdev/lib/dartdev.dart`.
  return (
      (strcmp(script_uri, "analyze") == 0) ||
      (strcmp(script_uri, "compilation-server") == 0) ||
      (strcmp(script_uri, "build") == 0) ||
      (strcmp(script_uri, "compile") == 0) ||
      (strcmp(script_uri, "create") == 0) ||
      (strcmp(script_uri, "development-service") == 0) ||
      (strcmp(script_uri, "devtools") == 0) ||
      (strcmp(script_uri, "doc") == 0) || (strcmp(script_uri, "fix") == 0) ||
      (strcmp(script_uri, "format") == 0) ||
      (strcmp(script_uri, "info") == 0) || (strcmp(script_uri, "pub") == 0) ||
      (strcmp(script_uri, "run") == 0) || (strcmp(script_uri, "test") == 0) ||
      (strcmp(script_uri, "info") == 0) ||
      (strcmp(script_uri, "language-server") == 0) ||
      (strcmp(script_uri, "tooling-daemon") == 0) ||
      (!File::ExistsUri(nullptr, script_uri) &&
       (strncmp(script_uri, "http://", 7) != 0) &&
       (strncmp(script_uri, "https://", 8) != 0) &&
       (strncmp(script_uri, "file://", 7) != 0) &&
       (strncmp(script_uri, "package:", 8) != 0) &&
       (strncmp(script_uri, "google3://", 10) != 0)));
}

CStringUniquePtr DartDevIsolate::TryResolveArtifactPath(const char* filename) {
  auto try_resolve_path = [&](CStringUniquePtr dir_prefix) {
    // First assume we're in dart-sdk/bin.
    char* snapshot_path =
        Utils::SCreate("%ssnapshots/%s", dir_prefix.get(), filename);
    if (File::Exists(nullptr, snapshot_path)) {
      return CStringUniquePtr(snapshot_path);
    }
    free(snapshot_path);

    // If we're not in dart-sdk/bin, we might be in one of the $SDK/out/*
    // directories. Try to use a snapshot from a previously built SDK.
    snapshot_path = Utils::SCreate("%s%s", dir_prefix.get(), filename);
    if (File::Exists(nullptr, snapshot_path)) {
      return CStringUniquePtr(snapshot_path);
    }
    free(snapshot_path);
    return CStringUniquePtr(nullptr);
  };

  // Try to find the artifact using the resolved EXE path first. This can fail
  // if the Dart SDK file structure is faked using symlinks and the actual
  // artifacts are spread across directories on the file system (e.g., some
  // google3 execution environments).
  auto result =
      try_resolve_path(EXEUtils::GetDirectoryPrefixFromResolvedExeName());
  if (result == nullptr) {
    result =
        try_resolve_path(EXEUtils::GetDirectoryPrefixFromUnresolvedExeName());
  }

  return result;
}

CStringUniquePtr DartDevIsolate::TryResolveDartDevSnapshotPath() {
  return TryResolveArtifactPath("dartdev.dart.snapshot");
}

void DartDevIsolate::DartDevRunner::Run(
    Dart_IsolateGroupCreateCallback create_isolate,
    char** packages_file,
    char** script,
    CommandLineOptions* dart_options) {
  create_isolate_ = create_isolate;
  dart_options_ = dart_options;
  package_config_override_ = packages_file;
  script_ = script;

  // We've encountered an error during preliminary argument parsing so we'll
  // output the standard help message and exit with an error code.
  if (print_usage_error_) {
    dart_options_->Reset();
    dart_options_->AddArgument("--help");
  }

  MonitorLocker locker(monitor_);
  int result = Thread::Start("DartDev Runner", RunCallback,
                             reinterpret_cast<uword>(this));
  if (result != 0) {
    FATAL("Failed to start DartDev thread: %d", result);
  }
  monitor_->WaitMicros(Monitor::kNoTimeout);

  if (result_ == DartDevIsolate::DartDev_Result_Run) {
    // Clear the DartDev dart_options and replace them with the processed
    // options provided by DartDev.
    dart_options_->Reset();
    dart_options_->AddArguments(const_cast<const char**>(argv_.get()), argc_);
  }
}

static Dart_CObject* GetArrayItem(Dart_CObject* message, intptr_t index) {
  return message->value.as_array.values[index];
}

void DartDevIsolate::DartDevRunner::DartDevResultCallback(
    Dart_Port dest_port_id,
    Dart_CObject* message) {
  // These messages are produced in pkg/dartdev/lib/src/vm_interop_handler.dart.
  ASSERT(message->type == Dart_CObject_kArray);
  int32_t type = GetArrayItem(message, 0)->value.as_int32;
  switch (type) {
    case DartDevIsolate::DartDev_Result_Run: {
      result_ = DartDevIsolate::DartDev_Result_Run;
      ASSERT(GetArrayItem(message, 1)->type == Dart_CObject_kString);
      auto item2 = GetArrayItem(message, 2);

      ASSERT(item2->type == Dart_CObject_kString ||
             item2->type == Dart_CObject_kNull);

      auto item3 = GetArrayItem(message, 3);

      ASSERT(item3->type == Dart_CObject_kBool);
      const bool mark_main_isolate_as_system_isolate = item3->value.as_bool;
      if (mark_main_isolate_as_system_isolate) {
        Options::set_mark_main_isolate_as_system_isolate(true);
      }

      if (*script_ != nullptr) {
        free(*script_);
      }
      if (*package_config_override_ != nullptr) {
        free(*package_config_override_);
        *package_config_override_ = nullptr;
      }
      *script_ = Utils::StrDup(GetArrayItem(message, 1)->value.as_string);

      if (item2->type == Dart_CObject_kString) {
        *package_config_override_ = Utils::StrDup(item2->value.as_string);
      }

      ASSERT(GetArrayItem(message, 4)->type == Dart_CObject_kArray);
      Dart_CObject* args = GetArrayItem(message, 4);
      argc_ = args->value.as_array.length;
      Dart_CObject** dart_args = args->value.as_array.values;

      auto deleter = [](char** args) {
        for (intptr_t i = 0; i < argc_; ++i) {
          free(args[i]);
        }
        delete[] args;
      };
      argv_ =
          std::unique_ptr<char*[], void (*)(char**)>(new char*[argc_], deleter);
      for (intptr_t i = 0; i < argc_; ++i) {
        argv_[i] = Utils::StrDup(dart_args[i]->value.as_string);
      }
      break;
    }
    case DartDevIsolate::DartDev_Result_Exit: {
      ASSERT(GetArrayItem(message, 1)->type == Dart_CObject_kInt32);
      int32_t dartdev_exit_code = GetArrayItem(message, 1)->value.as_int32;

      // If we're given a non-zero exit code, DartDev is signaling for us to
      // shutdown.
      int32_t exit_code =
          print_usage_error_ ? kErrorExitCode : dartdev_exit_code;
      Process::SetGlobalExitCode(exit_code);

      // If DartDev hasn't signaled for us to do anything else, we can assume
      // there's nothing else for the VM to run and that we can exit.
      if (result_ == DartDevIsolate::DartDev_Result_Unknown) {
        result_ = DartDevIsolate::DartDev_Result_Exit;
      }

      // DartDev is done processing the command. Unblock the main thread and
      // continue the launch procedure.
      DartDevRunner::monitor_->Notify();
      break;
    }
    default:
      UNREACHABLE();
  }
}

void DartDevIsolate::DartDevRunner::RunCallback(uword args) {
  MonitorLocker locker_(DartDevRunner::monitor_);
  DartDevRunner* runner = reinterpret_cast<DartDevRunner*>(args);

  // Hardcode flags to match those used to generate the DartDev snapshot.
  Dart_IsolateFlags flags;
  Dart_IsolateFlagsInitialize(&flags);
  flags.enable_asserts = false;
  flags.use_field_guards = true;
  flags.use_osr = true;
  flags.is_system_isolate = true;
  flags.branch_coverage = false;
  flags.coverage = false;

  char* error = nullptr;
  Dart_Isolate dartdev_isolate = runner->create_isolate_(
      DART_DEV_ISOLATE_NAME, DART_DEV_ISOLATE_NAME, nullptr,
      runner->packages_file_, &flags, /* callback_data */ nullptr,
      const_cast<char**>(&error));

  if (dartdev_isolate == nullptr) {
    ProcessError(error, kErrorExitCode);
    free(error);
    return;
  }

  Dart_EnterIsolate(dartdev_isolate);
  Dart_EnterScope();

  // Retrieve the DartDev entrypoint.
  Dart_Port send_port_id = ILLEGAL_PORT;
  Dart_Handle root_lib = Dart_RootLibrary();
  Dart_Handle main_closure =
      Dart_GetField(root_lib, Dart_NewStringFromCString("main"));
  CHECK_RESULT(main_closure);

  if (!Dart_IsClosure(main_closure)) {
    ProcessError("Unable to find 'main' in root library 'dartdev'",
                 kErrorExitCode);
    Dart_ExitScope();
    Dart_ShutdownIsolate();
    return;
  }

  // Create a SendPort that DartDev can use to communicate its results over.
  send_port_id =
      Dart_NewNativePort(DART_DEV_ISOLATE_NAME, DartDevResultCallback, false);
  ASSERT(send_port_id != ILLEGAL_PORT);
  Dart_Handle send_port = Dart_NewSendPort(send_port_id);
  CHECK_RESULT(send_port);

  const intptr_t kNumIsolateArgs = 4;
  Dart_Handle isolate_args[kNumIsolateArgs];
  isolate_args[0] = main_closure;  // entryPoint
  isolate_args[1] = runner->dart_options_->CreateRuntimeOptions();  // args
  isolate_args[2] = send_port;                                      // message
  isolate_args[3] = Dart_True();  // isSpawnUri

  Dart_Handle isolate_lib =
      Dart_LookupLibrary(Dart_NewStringFromCString("dart:isolate"));
  Dart_Handle result =
      Dart_Invoke(isolate_lib, Dart_NewStringFromCString("_startIsolate"),
                  kNumIsolateArgs, isolate_args);
  CHECK_RESULT(result);
  CHECK_RESULT(Dart_RunLoop());

  Dart_CloseNativePort(send_port_id);

  Dart_ExitScope();
  Dart_ShutdownIsolate();
}

void DartDevIsolate::DartDevRunner::ProcessError(const char* msg,
                                                 int32_t exit_code) {
  Syslog::PrintErr("%s.\n", msg);
  Process::SetGlobalExitCode(exit_code);
  result_ = DartDevIsolate::DartDev_Result_Exit;
  DartDevRunner::monitor_->Notify();
}

DartDevIsolate::DartDev_Result DartDevIsolate::RunDartDev(
    Dart_IsolateGroupCreateCallback create_isolate,
    char** packages_file,
    char** script,
    CommandLineOptions* dart_options) {
  runner_.Run(create_isolate, packages_file, script, dart_options);
  return runner_.result();
}

}  // namespace bin
}  // namespace dart

#endif  // if !defined(DART_PRECOMPILED_RUNTIME)
