// 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/d8/async-hooks-wrapper.h"
#include "src/d8/d8.h"
#include "src/execution/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
