// Copyright 2016 The PDFium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com

#include "fxjs/xfa/cfxjse_class.h"

#include <memory>
#include <utility>

#include "core/fxcrt/check.h"
#include "core/fxcrt/check_op.h"
#include "core/fxcrt/compiler_specific.h"
#include "fxjs/cjs_result.h"
#include "fxjs/fxv8.h"
#include "fxjs/js_resources.h"
#include "fxjs/xfa/cfxjse_context.h"
#include "fxjs/xfa/cfxjse_isolatetracker.h"
#include "fxjs/xfa/cfxjse_value.h"
#include "v8/include/v8-container.h"
#include "v8/include/v8-external.h"
#include "v8/include/v8-function-callback.h"
#include "v8/include/v8-function.h"
#include "v8/include/v8-isolate.h"
#include "v8/include/v8-object.h"
#include "v8/include/v8-primitive.h"
#include "v8/include/v8-template.h"

using pdfium::fxjse::kClassTag;
using pdfium::fxjse::kFuncTag;

namespace {

FXJSE_FUNCTION_DESCRIPTOR* AsFunctionDescriptor(void* ptr) {
  auto* result = static_cast<FXJSE_FUNCTION_DESCRIPTOR*>(ptr);
  return result && result->tag == kFuncTag ? result : nullptr;
}

FXJSE_CLASS_DESCRIPTOR* AsClassDescriptor(void* ptr) {
  auto* result = static_cast<FXJSE_CLASS_DESCRIPTOR*>(ptr);
  return result && result->tag == kClassTag ? result : nullptr;
}

void V8FunctionCallback_Wrapper(
    const v8::FunctionCallbackInfo<v8::Value>& info) {
  const FXJSE_FUNCTION_DESCRIPTOR* pFunctionInfo =
      AsFunctionDescriptor(info.Data().As<v8::External>()->Value());
  if (!pFunctionInfo)
    return;

  pFunctionInfo->callbackProc(CFXJSE_HostObject::FromV8(info.This()), info);
}

void V8ConstructorCallback_Wrapper(
    const v8::FunctionCallbackInfo<v8::Value>& info) {
  if (!info.IsConstructCall())
    return;

  const FXJSE_CLASS_DESCRIPTOR* pClassDescriptor =
      AsClassDescriptor(info.Data().As<v8::External>()->Value());
  if (!pClassDescriptor)
    return;

  DCHECK_EQ(info.This()->InternalFieldCount(), 2);
  info.This()->SetAlignedPointerInInternalField(0, nullptr);
  info.This()->SetAlignedPointerInInternalField(1, nullptr);
}

void Context_GlobalObjToString(
    const v8::FunctionCallbackInfo<v8::Value>& info) {
  const FXJSE_CLASS_DESCRIPTOR* pClassDescriptor =
      AsClassDescriptor(info.Data().As<v8::External>()->Value());
  if (!pClassDescriptor)
    return;

  if (pClassDescriptor->name) {
    ByteString szStringVal =
        ByteString::Format("[object %s]", pClassDescriptor->name);
    info.GetReturnValue().Set(
        fxv8::NewStringHelper(info.GetIsolate(), szStringVal.AsStringView()));
    return;
  }
  v8::Local<v8::String> local_str =
      info.This()
          ->ObjectProtoToString(info.GetIsolate()->GetCurrentContext())
          .FromMaybe(v8::Local<v8::String>());
  info.GetReturnValue().Set(local_str);
}

void DynPropGetterAdapter_MethodCallback(
    const v8::FunctionCallbackInfo<v8::Value>& info) {
  v8::Local<v8::Object> hCallBackInfo = info.Data().As<v8::Object>();
  if (hCallBackInfo->InternalFieldCount() != 2)
    return;

  auto* pClassDescriptor = static_cast<const FXJSE_CLASS_DESCRIPTOR*>(
      hCallBackInfo->GetAlignedPointerFromInternalField(0));
  if (pClassDescriptor != &kGlobalClassDescriptor &&
      pClassDescriptor != &kNormalClassDescriptor &&
      pClassDescriptor != &kVariablesClassDescriptor &&
      pClassDescriptor != &kFormCalcDescriptor) {
    return;
  }

  v8::Local<v8::String> hPropName =
      hCallBackInfo->GetInternalField(1).As<v8::Value>().As<v8::String>();
  if (hPropName.IsEmpty())
    return;

  v8::String::Utf8Value szPropName(info.GetIsolate(), hPropName);
  CJS_Result result =
      pClassDescriptor->dynMethodCall(info, WideString::FromUTF8(*szPropName));

  if (result.HasError()) {
    WideString err = JSFormatErrorString(pClassDescriptor->name, *szPropName,
                                         result.Error());
    fxv8::ThrowExceptionHelper(info.GetIsolate(), err.AsStringView());
    return;
  }

  if (result.HasReturn())
    info.GetReturnValue().Set(result.Return());
}

std::unique_ptr<CFXJSE_Value> DynPropGetterAdapter(
    v8::Isolate* pIsolate,
    const FXJSE_CLASS_DESCRIPTOR* pClassDescriptor,
    v8::Local<v8::Object> pObject,
    ByteStringView szPropName) {
  FXJSE_ClassPropType nPropType =
      pClassDescriptor->dynPropTypeGetter
          ? pClassDescriptor->dynPropTypeGetter(pIsolate, pObject, szPropName,
                                                false)
          : FXJSE_ClassPropType::kProperty;
  if (nPropType == FXJSE_ClassPropType::kProperty) {
    if (pClassDescriptor->dynPropGetter) {
      return std::make_unique<CFXJSE_Value>(
          pIsolate,
          pClassDescriptor->dynPropGetter(pIsolate, pObject, szPropName));
    }
  } else if (nPropType == FXJSE_ClassPropType::kMethod) {
    if (pClassDescriptor->dynMethodCall) {
      v8::HandleScope hscope(pIsolate);
      v8::Local<v8::ObjectTemplate> hCallBackInfoTemplate =
          v8::ObjectTemplate::New(pIsolate);
      hCallBackInfoTemplate->SetInternalFieldCount(2);
      v8::Local<v8::Object> hCallBackInfo =
          hCallBackInfoTemplate->NewInstance(pIsolate->GetCurrentContext())
              .ToLocalChecked();
      hCallBackInfo->SetAlignedPointerInInternalField(
          0, const_cast<FXJSE_CLASS_DESCRIPTOR*>(pClassDescriptor));
      hCallBackInfo->SetInternalField(
          1, fxv8::NewStringHelper(pIsolate, szPropName));
      return std::make_unique<CFXJSE_Value>(
          pIsolate,
          v8::Function::New(pIsolate->GetCurrentContext(),
                            DynPropGetterAdapter_MethodCallback, hCallBackInfo,
                            0, v8::ConstructorBehavior::kThrow)
              .ToLocalChecked());
    }
  }
  return std::make_unique<CFXJSE_Value>();
}

void DynPropSetterAdapter(v8::Isolate* pIsolate,
                          const FXJSE_CLASS_DESCRIPTOR* pClassDescriptor,
                          v8::Local<v8::Object> pObject,
                          ByteStringView szPropName,
                          CFXJSE_Value* pValue) {
  DCHECK(pClassDescriptor);
  FXJSE_ClassPropType nPropType =
      pClassDescriptor->dynPropTypeGetter
          ? pClassDescriptor->dynPropTypeGetter(pIsolate, pObject, szPropName,
                                                false)
          : FXJSE_ClassPropType::kProperty;
  if (nPropType != FXJSE_ClassPropType::kMethod) {
    if (pClassDescriptor->dynPropSetter) {
      pClassDescriptor->dynPropSetter(pIsolate, pObject, szPropName,
                                      pValue->GetValue(pIsolate));
    }
  }
}

bool DynPropQueryAdapter(v8::Isolate* pIsolate,
                         const FXJSE_CLASS_DESCRIPTOR* pClassDescriptor,
                         v8::Local<v8::Object> pObject,
                         ByteStringView szPropName) {
  FXJSE_ClassPropType nPropType = pClassDescriptor->dynPropTypeGetter
                                      ? pClassDescriptor->dynPropTypeGetter(
                                            pIsolate, pObject, szPropName, true)
                                      : FXJSE_ClassPropType::kProperty;
  return nPropType != FXJSE_ClassPropType::kNone;
}

v8::Intercepted NamedPropertyQueryCallback(
    v8::Local<v8::Name> property,
    const v8::PropertyCallbackInfo<v8::Integer>& info) {
  const FXJSE_CLASS_DESCRIPTOR* pClass =
      AsClassDescriptor(info.Data().As<v8::External>()->Value());
  if (!pClass) {
    return v8::Intercepted::kNo;
  }

  v8::HandleScope scope(info.GetIsolate());
  v8::String::Utf8Value szPropName(info.GetIsolate(), property);
  // SAFETY: required from V8.
  auto szFxPropName =
      UNSAFE_BUFFERS(ByteStringView::Create(*szPropName, szPropName.length()));
  if (DynPropQueryAdapter(info.GetIsolate(), pClass, info.Holder(),
                          szFxPropName)) {
    info.GetReturnValue().Set(v8::DontDelete);
    return v8::Intercepted::kYes;
  }

  return v8::Intercepted::kNo;
}

v8::Intercepted NamedPropertyGetterCallback(
    v8::Local<v8::Name> property,
    const v8::PropertyCallbackInfo<v8::Value>& info) {
  const FXJSE_CLASS_DESCRIPTOR* pClass =
      AsClassDescriptor(info.Data().As<v8::External>()->Value());
  if (!pClass) {
    return v8::Intercepted::kNo;
  }

  v8::String::Utf8Value szPropName(info.GetIsolate(), property);
  // SAFETY: required from V8.
  auto szFxPropName =
      UNSAFE_BUFFERS(ByteStringView::Create(*szPropName, szPropName.length()));
  std::unique_ptr<CFXJSE_Value> pNewValue = DynPropGetterAdapter(
      info.GetIsolate(), pClass, info.Holder(), szFxPropName);
  info.GetReturnValue().Set(pNewValue->DirectGetValue());
  return v8::Intercepted::kYes;
}

v8::Intercepted NamedPropertySetterCallback(
    v8::Local<v8::Name> property,
    v8::Local<v8::Value> value,
    const v8::PropertyCallbackInfo<void>& info) {
  const FXJSE_CLASS_DESCRIPTOR* pClass =
      AsClassDescriptor(info.Data().As<v8::External>()->Value());
  if (!pClass) {
    return v8::Intercepted::kNo;
  }

  v8::String::Utf8Value szPropName(info.GetIsolate(), property);
  // SAFETY: required from V8.
  auto szFxPropName =
      UNSAFE_BUFFERS(ByteStringView::Create(*szPropName, szPropName.length()));
  auto pNewValue = std::make_unique<CFXJSE_Value>(info.GetIsolate(), value);
  DynPropSetterAdapter(info.GetIsolate(), pClass, info.Holder(), szFxPropName,
                       pNewValue.get());
  info.GetReturnValue().Set(value);
  return v8::Intercepted::kYes;
}

void NamedPropertyEnumeratorCallback(
    const v8::PropertyCallbackInfo<v8::Array>& info) {
  info.GetReturnValue().Set(v8::Array::New(info.GetIsolate()));
}

void SetUpNamedPropHandler(v8::Isolate* pIsolate,
                           v8::Local<v8::ObjectTemplate> pObjectTemplate,
                           const FXJSE_CLASS_DESCRIPTOR* pClassDescriptor) {
  v8::NamedPropertyHandlerConfiguration configuration(
      pClassDescriptor->dynPropGetter ? NamedPropertyGetterCallback : nullptr,
      pClassDescriptor->dynPropSetter ? NamedPropertySetterCallback : nullptr,
      pClassDescriptor->dynPropTypeGetter ? NamedPropertyQueryCallback
                                          : nullptr,
      nullptr, NamedPropertyEnumeratorCallback,
      v8::External::New(pIsolate,
                        const_cast<FXJSE_CLASS_DESCRIPTOR*>(pClassDescriptor)),
      v8::PropertyHandlerFlags::kNonMasking);
  pObjectTemplate->SetHandler(configuration);
}

}  // namespace

// static
CFXJSE_Class* CFXJSE_Class::Create(
    CFXJSE_Context* pContext,
    const FXJSE_CLASS_DESCRIPTOR* pClassDescriptor,
    bool bIsJSGlobal) {
  if (!pContext || !pClassDescriptor)
    return nullptr;

  CFXJSE_Class* pExistingClass =
      pContext->GetClassByName(pClassDescriptor->name);
  if (pExistingClass)
    return pExistingClass;

  v8::Isolate* pIsolate = pContext->GetIsolate();
  auto pClass = std::make_unique<CFXJSE_Class>(pContext);
  pClass->m_szClassName = pClassDescriptor->name;
  pClass->m_pClassDescriptor = pClassDescriptor;
  CFXJSE_ScopeUtil_IsolateHandleRootContext scope(pIsolate);
  v8::Local<v8::FunctionTemplate> hFunctionTemplate = v8::FunctionTemplate::New(
      pIsolate, bIsJSGlobal ? nullptr : V8ConstructorCallback_Wrapper,
      v8::External::New(pIsolate,
                        const_cast<FXJSE_CLASS_DESCRIPTOR*>(pClassDescriptor)));
  v8::Local<v8::String> classname =
      fxv8::NewStringHelper(pIsolate, pClassDescriptor->name);
  hFunctionTemplate->SetClassName(classname);
  hFunctionTemplate->PrototypeTemplate()->Set(
      v8::Symbol::GetToStringTag(pIsolate), classname,
      static_cast<v8::PropertyAttribute>(v8::ReadOnly | v8::DontEnum));
  hFunctionTemplate->InstanceTemplate()->SetInternalFieldCount(2);
  v8::Local<v8::ObjectTemplate> hObjectTemplate =
      hFunctionTemplate->InstanceTemplate();
  SetUpNamedPropHandler(pIsolate, hObjectTemplate, pClassDescriptor);

  for (const auto& method : pClassDescriptor->methods) {
    v8::Local<v8::FunctionTemplate> fun = v8::FunctionTemplate::New(
        pIsolate, V8FunctionCallback_Wrapper,
        v8::External::New(pIsolate,
                          const_cast<FXJSE_FUNCTION_DESCRIPTOR*>(&method)));
    fun->RemovePrototype();
    hObjectTemplate->Set(
        fxv8::NewStringHelper(pIsolate, method.name), fun,
        static_cast<v8::PropertyAttribute>(v8::ReadOnly | v8::DontDelete));
  }

  if (bIsJSGlobal) {
    v8::Local<v8::FunctionTemplate> fn = v8::FunctionTemplate::New(
        pIsolate, Context_GlobalObjToString,
        v8::External::New(
            pIsolate, const_cast<FXJSE_CLASS_DESCRIPTOR*>(pClassDescriptor)));
    fn->RemovePrototype();
    hObjectTemplate->Set(fxv8::NewStringHelper(pIsolate, "toString"), fn);
  }
  pClass->m_hTemplate.Reset(pContext->GetIsolate(), hFunctionTemplate);
  CFXJSE_Class* pResult = pClass.get();
  pContext->AddClass(std::move(pClass));
  return pResult;
}

CFXJSE_Class::CFXJSE_Class(const CFXJSE_Context* pContext)
    : m_pContext(pContext) {}

CFXJSE_Class::~CFXJSE_Class() = default;

v8::Local<v8::FunctionTemplate> CFXJSE_Class::GetTemplate(
    v8::Isolate* pIsolate) {
  return v8::Local<v8::FunctionTemplate>::New(pIsolate, m_hTemplate);
}
