// Copyright 2018 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "src/async-hooks-wrapper.h"
#include "src/d8.h"
#include "src/isolate-inl.h"

namespace v8 {

void AsyncHooksWrap::Enable() { enabled_ = true; }

void AsyncHooksWrap::Disable() { enabled_ = false; }

v8::Local<v8::Function> AsyncHooksWrap::init_function() const {
  return init_function_.Get(isolate_);
}
void AsyncHooksWrap::set_init_function(v8::Local<v8::Function> value) {
  init_function_.Reset(isolate_, value);
}
v8::Local<v8::Function> AsyncHooksWrap::before_function() const {
  return before_function_.Get(isolate_);
}
void AsyncHooksWrap::set_before_function(v8::Local<v8::Function> value) {
  before_function_.Reset(isolate_, value);
}
v8::Local<v8::Function> AsyncHooksWrap::after_function() const {
  return after_function_.Get(isolate_);
}
void AsyncHooksWrap::set_after_function(v8::Local<v8::Function> value) {
  after_function_.Reset(isolate_, value);
}
v8::Local<v8::Function> AsyncHooksWrap::promiseResolve_function() const {
  return promiseResolve_function_.Get(isolate_);
}
void AsyncHooksWrap::set_promiseResolve_function(
    v8::Local<v8::Function> value) {
  promiseResolve_function_.Reset(isolate_, value);
}

static AsyncHooksWrap* UnwrapHook(
    const v8::FunctionCallbackInfo<v8::Value>& args) {
  Isolate* isolate = args.GetIsolate();
  HandleScope scope(isolate);
  Local<Object> hook = args.This();

  AsyncHooks* hooks = PerIsolateData::Get(isolate)->GetAsyncHooks();

  if (!hooks->async_hook_ctor.Get(isolate)->HasInstance(hook)) {
    isolate->ThrowException(
        String::NewFromUtf8(
            isolate, "Invalid 'this' passed instead of AsyncHooks instance",
            NewStringType::kNormal)
            .ToLocalChecked());
    return nullptr;
  }

  Local<External> wrap = Local<External>::Cast(hook->GetInternalField(0));
  void* ptr = wrap->Value();
  return static_cast<AsyncHooksWrap*>(ptr);
}

static void EnableHook(const v8::FunctionCallbackInfo<v8::Value>& args) {
  AsyncHooksWrap* wrap = UnwrapHook(args);
  if (wrap) {
    wrap->Enable();
  }
}

static void DisableHook(const v8::FunctionCallbackInfo<v8::Value>& args) {
  AsyncHooksWrap* wrap = UnwrapHook(args);
  if (wrap) {
    wrap->Disable();
  }
}

async_id_t AsyncHooks::GetExecutionAsyncId() const {
  return asyncContexts.top().execution_async_id;
}

async_id_t AsyncHooks::GetTriggerAsyncId() const {
  return asyncContexts.top().trigger_async_id;
}

Local<Object> AsyncHooks::CreateHook(
    const v8::FunctionCallbackInfo<v8::Value>& args) {
  Isolate* isolate = args.GetIsolate();
  EscapableHandleScope handle_scope(isolate);

  Local<Context> currentContext = isolate->GetCurrentContext();

  if (args.Length() != 1 || !args[0]->IsObject()) {
    isolate->ThrowException(
        String::NewFromUtf8(isolate, "Invalid arguments passed to createHook",
                            NewStringType::kNormal)
            .ToLocalChecked());
    return Local<Object>();
  }

  AsyncHooksWrap* wrap = new AsyncHooksWrap(isolate);

  Local<Object> fn_obj = args[0].As<Object>();

#define SET_HOOK_FN(name)                                                   \
  Local<Value> name##_v =                                                   \
      fn_obj                                                                \
          ->Get(currentContext,                                             \
                String::NewFromUtf8(isolate, #name, NewStringType::kNormal) \
                    .ToLocalChecked())                                      \
          .ToLocalChecked();                                                \
  if (name##_v->IsFunction()) {                                             \
    wrap->set_##name##_function(name##_v.As<Function>());                   \
  }

  SET_HOOK_FN(init);
  SET_HOOK_FN(before);
  SET_HOOK_FN(after);
  SET_HOOK_FN(promiseResolve);
#undef SET_HOOK_FN

  async_wraps_.push_back(wrap);

  Local<Object> obj = async_hooks_templ.Get(isolate)
                          ->NewInstance(currentContext)
                          .ToLocalChecked();
  obj->SetInternalField(0, External::New(isolate, wrap));

  return handle_scope.Escape(obj);
}

void AsyncHooks::ShellPromiseHook(PromiseHookType type, Local<Promise> promise,
                                  Local<Value> parent) {
  AsyncHooks* hooks =
      PerIsolateData::Get(promise->GetIsolate())->GetAsyncHooks();

  HandleScope handle_scope(hooks->isolate_);

  Local<Context> currentContext = hooks->isolate_->GetCurrentContext();

  if (type == PromiseHookType::kInit) {
    ++hooks->current_async_id;
    Local<Integer> async_id =
        Integer::New(hooks->isolate_, hooks->current_async_id);

    CHECK(!promise
               ->HasPrivate(currentContext,
                            hooks->async_id_smb.Get(hooks->isolate_))
               .ToChecked());
    promise->SetPrivate(currentContext,
                        hooks->async_id_smb.Get(hooks->isolate_), async_id);

    if (parent->IsPromise()) {
      Local<Promise> parent_promise = parent.As<Promise>();
      Local<Value> parent_async_id =
          parent_promise
              ->GetPrivate(hooks->isolate_->GetCurrentContext(),
                           hooks->async_id_smb.Get(hooks->isolate_))
              .ToLocalChecked();
      promise->SetPrivate(currentContext,
                          hooks->trigger_id_smb.Get(hooks->isolate_),
                          parent_async_id);
    } else {
      CHECK(parent->IsUndefined());
      Local<Integer> trigger_id = Integer::New(hooks->isolate_, 0);
      promise->SetPrivate(currentContext,
                          hooks->trigger_id_smb.Get(hooks->isolate_),
                          trigger_id);
    }
  } else if (type == PromiseHookType::kBefore) {
    AsyncContext ctx;
    ctx.execution_async_id =
        promise
            ->GetPrivate(hooks->isolate_->GetCurrentContext(),
                         hooks->async_id_smb.Get(hooks->isolate_))
            .ToLocalChecked()
            .As<Integer>()
            ->Value();
    ctx.trigger_async_id =
        promise
            ->GetPrivate(hooks->isolate_->GetCurrentContext(),
                         hooks->trigger_id_smb.Get(hooks->isolate_))
            .ToLocalChecked()
            .As<Integer>()
            ->Value();
    hooks->asyncContexts.push(ctx);
  } else if (type == PromiseHookType::kAfter) {
    hooks->asyncContexts.pop();
  }

  for (AsyncHooksWrap* wrap : hooks->async_wraps_) {
    PromiseHookDispatch(type, promise, parent, wrap, hooks);
  }
}

void AsyncHooks::Initialize() {
  HandleScope handle_scope(isolate_);

  async_hook_ctor.Reset(isolate_, FunctionTemplate::New(isolate_));
  async_hook_ctor.Get(isolate_)->SetClassName(
      String::NewFromUtf8(isolate_, "AsyncHook", NewStringType::kNormal)
          .ToLocalChecked());

  async_hooks_templ.Reset(isolate_,
                          async_hook_ctor.Get(isolate_)->InstanceTemplate());
  async_hooks_templ.Get(isolate_)->SetInternalFieldCount(1);
  async_hooks_templ.Get(isolate_)->Set(
      String::NewFromUtf8(isolate_, "enable", v8::NewStringType::kNormal)
          .ToLocalChecked(),
      FunctionTemplate::New(isolate_, EnableHook));
  async_hooks_templ.Get(isolate_)->Set(
      String::NewFromUtf8(isolate_, "disable", v8::NewStringType::kNormal)
          .ToLocalChecked(),
      FunctionTemplate::New(isolate_, DisableHook));

  async_id_smb.Reset(isolate_, Private::New(isolate_));
  trigger_id_smb.Reset(isolate_, Private::New(isolate_));

  isolate_->SetPromiseHook(ShellPromiseHook);
}

void AsyncHooks::Deinitialize() {
  isolate_->SetPromiseHook(nullptr);
  for (AsyncHooksWrap* wrap : async_wraps_) {
    delete wrap;
  }
}

void AsyncHooks::PromiseHookDispatch(PromiseHookType type,
                                     Local<Promise> promise,
                                     Local<Value> parent, AsyncHooksWrap* wrap,
                                     AsyncHooks* hooks) {
  if (!wrap->IsEnabled()) {
    return;
  }

  HandleScope handle_scope(hooks->isolate_);

  TryCatch try_catch(hooks->isolate_);
  try_catch.SetVerbose(true);

  i::Isolate* isolate = reinterpret_cast<i::Isolate*>(hooks->isolate_);
  if (isolate->has_scheduled_exception()) {
    isolate->ScheduleThrow(isolate->scheduled_exception());

    DCHECK(try_catch.HasCaught());
    Shell::ReportException(hooks->isolate_, &try_catch);
    return;
  }

  Local<Value> rcv = Undefined(hooks->isolate_);
  Local<Context> context = hooks->isolate_->GetCurrentContext();
  Local<Value> async_id =
      promise->GetPrivate(context, hooks->async_id_smb.Get(hooks->isolate_))
          .ToLocalChecked();
  Local<Value> args[1] = {async_id};

  // This is unused. It's here to silence the warning about
  // not using the MaybeLocal return value from Call.
  MaybeLocal<Value> result;

  // Sacrifice the brevity for readability and debugfulness
  if (type == PromiseHookType::kInit) {
    if (!wrap->init_function().IsEmpty()) {
      Local<Value> initArgs[4] = {
          async_id,
          String::NewFromUtf8(hooks->isolate_, "PROMISE",
                              NewStringType::kNormal)
              .ToLocalChecked(),
          promise
              ->GetPrivate(context, hooks->trigger_id_smb.Get(hooks->isolate_))
              .ToLocalChecked(),
          promise};
      result = wrap->init_function()->Call(context, rcv, 4, initArgs);
    }
  } else if (type == PromiseHookType::kBefore) {
    if (!wrap->before_function().IsEmpty()) {
      result = wrap->before_function()->Call(context, rcv, 1, args);
    }
  } else if (type == PromiseHookType::kAfter) {
    if (!wrap->after_function().IsEmpty()) {
      result = wrap->after_function()->Call(context, rcv, 1, args);
    }
  } else if (type == PromiseHookType::kResolve) {
    if (!wrap->promiseResolve_function().IsEmpty()) {
      result = wrap->promiseResolve_function()->Call(context, rcv, 1, args);
    }
  }

  if (try_catch.HasCaught()) {
    Shell::ReportException(hooks->isolate_, &try_catch);
  }
}

}  // namespace v8
