// 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_);
  Thread::Start("DartDev Runner", RunCallback, reinterpret_cast<uword>(this));
  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)
