// Copyright 2014 PDFium Authors. All rights reserved.
// 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 "fpdfsdk/include/jsapi/fxjs_v8.h"

#include "core/include/fxcrt/fx_basic.h"

const wchar_t kFXJSValueNameString[] = L"string";
const wchar_t kFXJSValueNameNumber[] = L"number";
const wchar_t kFXJSValueNameBoolean[] = L"boolean";
const wchar_t kFXJSValueNameDate[] = L"date";
const wchar_t kFXJSValueNameObject[] = L"object";
const wchar_t kFXJSValueNameFxobj[] = L"fxobj";
const wchar_t kFXJSValueNameNull[] = L"null";
const wchar_t kFXJSValueNameUndefined[] = L"undefined";

// Keep this consistent with the values defined in gin/public/context_holder.h
// (without actually requiring a dependency on gin itself for the standalone
// embedders of PDFIum). The value we want to use is:
//   kPerContextDataStartIndex + kEmbedderPDFium, which is 3.
static const unsigned int kPerContextDataIndex = 3u;
static unsigned int g_embedderDataSlot = 1u;
static v8::Isolate* g_isolate = nullptr;
static size_t g_isolate_ref_count = 0;
static FXJS_ArrayBufferAllocator* g_arrayBufferAllocator = nullptr;
static v8::Global<v8::ObjectTemplate>* g_DefaultGlobalObjectTemplate = nullptr;

class CFXJS_PerObjectData {
 public:
  explicit CFXJS_PerObjectData(int nObjDefID)
      : m_ObjDefID(nObjDefID), m_pPrivate(nullptr) {}

  const int m_ObjDefID;
  void* m_pPrivate;
};

class CFXJS_ObjDefinition {
 public:
  static int MaxID(v8::Isolate* pIsolate) {
    return FXJS_PerIsolateData::Get(pIsolate)->m_ObjectDefnArray.size();
  }

  static CFXJS_ObjDefinition* ForID(v8::Isolate* pIsolate, int id) {
    // Note: GetAt() halts if out-of-range even in release builds.
    return FXJS_PerIsolateData::Get(pIsolate)->m_ObjectDefnArray[id];
  }

  CFXJS_ObjDefinition(v8::Isolate* isolate,
                      const wchar_t* sObjName,
                      FXJSOBJTYPE eObjType,
                      FXJS_CONSTRUCTOR pConstructor,
                      FXJS_DESTRUCTOR pDestructor)
      : m_ObjName(sObjName),
        m_ObjType(eObjType),
        m_pConstructor(pConstructor),
        m_pDestructor(pDestructor),
        m_pIsolate(isolate) {
    v8::Isolate::Scope isolate_scope(isolate);
    v8::HandleScope handle_scope(isolate);

    v8::Local<v8::FunctionTemplate> fun = v8::FunctionTemplate::New(isolate);
    fun->InstanceTemplate()->SetInternalFieldCount(2);
    m_FunctionTemplate.Reset(isolate, fun);

    v8::Local<v8::Signature> sig = v8::Signature::New(isolate, fun);
    m_Signature.Reset(isolate, sig);
  }

  int AssignID() {
    FXJS_PerIsolateData* pData = FXJS_PerIsolateData::Get(m_pIsolate);
    pData->m_ObjectDefnArray.push_back(this);
    return pData->m_ObjectDefnArray.size() - 1;
  }

  v8::Local<v8::ObjectTemplate> GetInstanceTemplate() {
    v8::EscapableHandleScope scope(m_pIsolate);
    v8::Local<v8::FunctionTemplate> function =
        m_FunctionTemplate.Get(m_pIsolate);
    return scope.Escape(function->InstanceTemplate());
  }

  v8::Local<v8::Signature> GetSignature() {
    v8::EscapableHandleScope scope(m_pIsolate);
    return scope.Escape(m_Signature.Get(m_pIsolate));
  }

  const wchar_t* const m_ObjName;
  const FXJSOBJTYPE m_ObjType;
  const FXJS_CONSTRUCTOR m_pConstructor;
  const FXJS_DESTRUCTOR m_pDestructor;

  v8::Isolate* m_pIsolate;
  v8::Global<v8::FunctionTemplate> m_FunctionTemplate;
  v8::Global<v8::Signature> m_Signature;
};

static v8::Local<v8::ObjectTemplate> GetGlobalObjectTemplate(
    v8::Isolate* pIsolate) {
  int maxID = CFXJS_ObjDefinition::MaxID(pIsolate);
  for (int i = 0; i < maxID; ++i) {
    CFXJS_ObjDefinition* pObjDef = CFXJS_ObjDefinition::ForID(pIsolate, i);
    if (pObjDef->m_ObjType == FXJSOBJTYPE_GLOBAL)
      return pObjDef->GetInstanceTemplate();
  }
  if (!g_DefaultGlobalObjectTemplate) {
    g_DefaultGlobalObjectTemplate = new v8::Global<v8::ObjectTemplate>;
    g_DefaultGlobalObjectTemplate->Reset(pIsolate,
                                         v8::ObjectTemplate::New(pIsolate));
  }
  return g_DefaultGlobalObjectTemplate->Get(pIsolate);
}

void* FXJS_ArrayBufferAllocator::Allocate(size_t length) {
  return calloc(1, length);
}

void* FXJS_ArrayBufferAllocator::AllocateUninitialized(size_t length) {
  return malloc(length);
}

void FXJS_ArrayBufferAllocator::Free(void* data, size_t length) {
  free(data);
}

void V8TemplateMapTraits::Dispose(v8::Isolate* isolate,
                                  v8::Global<v8::Object> value,
                                  void* key) {
  v8::Local<v8::Object> obj = value.Get(isolate);
  if (obj.IsEmpty())
    return;
  int id = FXJS_GetObjDefnID(obj);
  if (id == -1)
    return;

  CFXJS_ObjDefinition* pObjDef = CFXJS_ObjDefinition::ForID(isolate, id);
  if (!pObjDef)
    return;
  if (pObjDef->m_pDestructor)
    pObjDef->m_pDestructor(obj);
  FXJS_FreePrivate(obj);
}

V8TemplateMapTraits::MapType* V8TemplateMapTraits::MapFromWeakCallbackInfo(
    const v8::WeakCallbackInfo<WeakCallbackDataType>& data) {
  V8TemplateMap* pMap =
      (FXJS_PerIsolateData::Get(data.GetIsolate()))->m_pDynamicObjsMap;
  return pMap ? &pMap->m_map : nullptr;
}

void FXJS_Initialize(unsigned int embedderDataSlot, v8::Isolate* pIsolate) {
  if (g_isolate) {
    ASSERT(g_embedderDataSlot == embedderDataSlot);
    ASSERT(g_isolate == pIsolate);
    return;
  }
  g_embedderDataSlot = embedderDataSlot;
  g_isolate = pIsolate;
}

void FXJS_Release() {
  ASSERT(!g_isolate || g_isolate_ref_count == 0);
  delete g_DefaultGlobalObjectTemplate;
  g_DefaultGlobalObjectTemplate = nullptr;
  g_isolate = nullptr;

  delete g_arrayBufferAllocator;
  g_arrayBufferAllocator = nullptr;
}

bool FXJS_GetIsolate(v8::Isolate** pResultIsolate) {
  if (g_isolate) {
    *pResultIsolate = g_isolate;
    return false;
  }
  // Provide backwards compatibility when no external isolate.
  if (!g_arrayBufferAllocator)
    g_arrayBufferAllocator = new FXJS_ArrayBufferAllocator();
  v8::Isolate::CreateParams params;
  params.array_buffer_allocator = g_arrayBufferAllocator;
  *pResultIsolate = v8::Isolate::New(params);
  return true;
}

size_t FXJS_GlobalIsolateRefCount() {
  return g_isolate_ref_count;
}

// static
void FXJS_PerIsolateData::SetUp(v8::Isolate* pIsolate) {
  if (!pIsolate->GetData(g_embedderDataSlot))
    pIsolate->SetData(g_embedderDataSlot, new FXJS_PerIsolateData());
}

// static
FXJS_PerIsolateData* FXJS_PerIsolateData::Get(v8::Isolate* pIsolate) {
  return static_cast<FXJS_PerIsolateData*>(
      pIsolate->GetData(g_embedderDataSlot));
}

int FXJS_DefineObj(v8::Isolate* pIsolate,
                   const wchar_t* sObjName,
                   FXJSOBJTYPE eObjType,
                   FXJS_CONSTRUCTOR pConstructor,
                   FXJS_DESTRUCTOR pDestructor) {
  v8::Isolate::Scope isolate_scope(pIsolate);
  v8::HandleScope handle_scope(pIsolate);

  FXJS_PerIsolateData::SetUp(pIsolate);
  CFXJS_ObjDefinition* pObjDef = new CFXJS_ObjDefinition(
      pIsolate, sObjName, eObjType, pConstructor, pDestructor);
  return pObjDef->AssignID();
}

void FXJS_DefineObjMethod(v8::Isolate* pIsolate,
                          int nObjDefnID,
                          const wchar_t* sMethodName,
                          v8::FunctionCallback pMethodCall) {
  v8::Isolate::Scope isolate_scope(pIsolate);
  v8::HandleScope handle_scope(pIsolate);
  CFX_ByteString bsMethodName = CFX_WideString(sMethodName).UTF8Encode();
  CFXJS_ObjDefinition* pObjDef =
      CFXJS_ObjDefinition::ForID(pIsolate, nObjDefnID);
  pObjDef->GetInstanceTemplate()->Set(
      v8::String::NewFromUtf8(pIsolate, bsMethodName.c_str(),
                              v8::NewStringType::kNormal).ToLocalChecked(),
      v8::FunctionTemplate::New(pIsolate, pMethodCall, v8::Local<v8::Value>(),
                                pObjDef->GetSignature()),
      v8::ReadOnly);
}

void FXJS_DefineObjProperty(v8::Isolate* pIsolate,
                            int nObjDefnID,
                            const wchar_t* sPropName,
                            v8::AccessorGetterCallback pPropGet,
                            v8::AccessorSetterCallback pPropPut) {
  v8::Isolate::Scope isolate_scope(pIsolate);
  v8::HandleScope handle_scope(pIsolate);
  CFX_ByteString bsPropertyName = CFX_WideString(sPropName).UTF8Encode();
  CFXJS_ObjDefinition* pObjDef =
      CFXJS_ObjDefinition::ForID(pIsolate, nObjDefnID);
  pObjDef->GetInstanceTemplate()->SetAccessor(
      v8::String::NewFromUtf8(pIsolate, bsPropertyName.c_str(),
                              v8::NewStringType::kNormal).ToLocalChecked(),
      pPropGet, pPropPut);
}

void FXJS_DefineObjAllProperties(v8::Isolate* pIsolate,
                                 int nObjDefnID,
                                 v8::NamedPropertyQueryCallback pPropQurey,
                                 v8::NamedPropertyGetterCallback pPropGet,
                                 v8::NamedPropertySetterCallback pPropPut,
                                 v8::NamedPropertyDeleterCallback pPropDel) {
  v8::Isolate::Scope isolate_scope(pIsolate);
  v8::HandleScope handle_scope(pIsolate);
  CFXJS_ObjDefinition* pObjDef =
      CFXJS_ObjDefinition::ForID(pIsolate, nObjDefnID);
  pObjDef->GetInstanceTemplate()->SetNamedPropertyHandler(pPropGet, pPropPut,
                                                          pPropQurey, pPropDel);
}

void FXJS_DefineObjConst(v8::Isolate* pIsolate,
                         int nObjDefnID,
                         const wchar_t* sConstName,
                         v8::Local<v8::Value> pDefault) {
  v8::Isolate::Scope isolate_scope(pIsolate);
  v8::HandleScope handle_scope(pIsolate);
  CFX_ByteString bsConstName = CFX_WideString(sConstName).UTF8Encode();
  CFXJS_ObjDefinition* pObjDef =
      CFXJS_ObjDefinition::ForID(pIsolate, nObjDefnID);
  pObjDef->GetInstanceTemplate()->Set(pIsolate, bsConstName.c_str(), pDefault);
}

void FXJS_DefineGlobalMethod(v8::Isolate* pIsolate,
                             const wchar_t* sMethodName,
                             v8::FunctionCallback pMethodCall) {
  v8::Isolate::Scope isolate_scope(pIsolate);
  v8::HandleScope handle_scope(pIsolate);
  CFX_ByteString bsMethodName = CFX_WideString(sMethodName).UTF8Encode();
  GetGlobalObjectTemplate(pIsolate)->Set(
      v8::String::NewFromUtf8(pIsolate, bsMethodName.c_str(),
                              v8::NewStringType::kNormal).ToLocalChecked(),
      v8::FunctionTemplate::New(pIsolate, pMethodCall), v8::ReadOnly);
}

void FXJS_DefineGlobalConst(v8::Isolate* pIsolate,
                            const wchar_t* sConstName,
                            v8::Local<v8::Value> pDefault) {
  v8::Isolate::Scope isolate_scope(pIsolate);
  v8::HandleScope handle_scope(pIsolate);
  CFX_ByteString bsConst = CFX_WideString(sConstName).UTF8Encode();
  GetGlobalObjectTemplate(pIsolate)->Set(
      v8::String::NewFromUtf8(pIsolate, bsConst.c_str(),
                              v8::NewStringType::kNormal).ToLocalChecked(),
      pDefault, v8::ReadOnly);
}

void FXJS_InitializeRuntime(
    v8::Isolate* pIsolate,
    IJS_Runtime* pIRuntime,
    v8::Global<v8::Context>* pV8PersistentContext,
    std::vector<v8::Global<v8::Object>*>* pStaticObjects) {
  if (pIsolate == g_isolate)
    ++g_isolate_ref_count;

  v8::Isolate::Scope isolate_scope(pIsolate);
#ifdef PDF_ENABLE_XFA
  v8::Locker locker(pIsolate);
#endif  // PDF_ENABLE_XFA
  v8::HandleScope handle_scope(pIsolate);
  v8::Local<v8::Context> v8Context =
      v8::Context::New(pIsolate, NULL, GetGlobalObjectTemplate(pIsolate));
  v8::Context::Scope context_scope(v8Context);

  FXJS_PerIsolateData::SetUp(pIsolate);
  FXJS_PerIsolateData* pData = FXJS_PerIsolateData::Get(pIsolate);
  if (!pData)
    return;
  pData->CreateDynamicObjsMap(pIsolate);
  v8Context->SetAlignedPointerInEmbedderData(kPerContextDataIndex, pIRuntime);

  int maxID = CFXJS_ObjDefinition::MaxID(pIsolate);
  pStaticObjects->resize(maxID + 1);
  for (int i = 0; i < maxID; ++i) {
    CFXJS_ObjDefinition* pObjDef = CFXJS_ObjDefinition::ForID(pIsolate, i);
    if (pObjDef->m_ObjType == FXJSOBJTYPE_GLOBAL) {
      v8Context->Global()
          ->GetPrototype()
          ->ToObject(v8Context)
          .ToLocalChecked()
          ->SetAlignedPointerInInternalField(0, new CFXJS_PerObjectData(i));

      if (pObjDef->m_pConstructor)
        pObjDef->m_pConstructor(pIRuntime, v8Context->Global()
                                               ->GetPrototype()
                                               ->ToObject(v8Context)
                                               .ToLocalChecked());
    } else if (pObjDef->m_ObjType == FXJSOBJTYPE_STATIC) {
      CFX_ByteString bs = CFX_WideString(pObjDef->m_ObjName).UTF8Encode();
      v8::Local<v8::String> m_ObjName =
          v8::String::NewFromUtf8(pIsolate, bs.c_str(),
                                  v8::NewStringType::kNormal,
                                  bs.GetLength()).ToLocalChecked();

      v8::Local<v8::Object> obj =
          FXJS_NewFxDynamicObj(pIsolate, pIRuntime, i, true);
      v8Context->Global()->Set(v8Context, m_ObjName, obj).FromJust();
      pStaticObjects->at(i) = new v8::Global<v8::Object>(pIsolate, obj);
    }
  }
  pV8PersistentContext->Reset(pIsolate, v8Context);
}

void FXJS_ReleaseRuntime(v8::Isolate* pIsolate,
                         v8::Global<v8::Context>* pV8PersistentContext,
                         std::vector<v8::Global<v8::Object>*>* pStaticObjects) {
  v8::Isolate::Scope isolate_scope(pIsolate);
#ifdef PDF_ENABLE_XFA
  v8::Locker locker(pIsolate);
#endif  // PDF_ENABLE_XFA
  v8::HandleScope handle_scope(pIsolate);
  v8::Local<v8::Context> context =
      v8::Local<v8::Context>::New(pIsolate, *pV8PersistentContext);
  v8::Context::Scope context_scope(context);

  FXJS_PerIsolateData* pData = FXJS_PerIsolateData::Get(pIsolate);
  if (!pData)
    return;
  pData->ReleaseDynamicObjsMap();

  int maxID = CFXJS_ObjDefinition::MaxID(pIsolate);
  for (int i = 0; i < maxID; ++i) {
    CFXJS_ObjDefinition* pObjDef = CFXJS_ObjDefinition::ForID(pIsolate, i);
    v8::Local<v8::Object> pObj;
    if (pObjDef->m_ObjType == FXJSOBJTYPE_GLOBAL) {
      pObj =
          context->Global()->GetPrototype()->ToObject(context).ToLocalChecked();
    } else if (pStaticObjects->at(i) && !pStaticObjects->at(i)->IsEmpty()) {
      pObj = v8::Local<v8::Object>::New(pIsolate, *pStaticObjects->at(i));
      delete pStaticObjects->at(i);
      pStaticObjects->at(i) = nullptr;
    }

    if (!pObj.IsEmpty()) {
      if (pObjDef->m_pDestructor)
        pObjDef->m_pDestructor(pObj);
      FXJS_FreePrivate(pObj);
    }
  }

  if (pIsolate == g_isolate && --g_isolate_ref_count > 0)
    return;

  for (int i = 0; i < maxID; ++i)
    delete CFXJS_ObjDefinition::ForID(pIsolate, i);

  pIsolate->SetData(g_embedderDataSlot, nullptr);
  delete pData;
}

IJS_Runtime* FXJS_GetRuntimeFromIsolate(v8::Isolate* pIsolate) {
  v8::Local<v8::Context> context = pIsolate->GetCurrentContext();
  return static_cast<IJS_Runtime*>(
      context->GetAlignedPointerFromEmbedderData(kPerContextDataIndex));
}

#ifdef PDF_ENABLE_XFA
void FXJS_SetRuntimeForV8Context(v8::Local<v8::Context> v8Context,
                                 IJS_Runtime* pIRuntime) {
  v8Context->SetAlignedPointerInEmbedderData(kPerContextDataIndex, pIRuntime);
}
#endif  // PDF_ENABLE_XFA

int FXJS_Execute(v8::Isolate* pIsolate,
                 IJS_Context* pJSContext,
                 const wchar_t* script,
                 FXJSErr* pError) {
  v8::Isolate::Scope isolate_scope(pIsolate);
  v8::TryCatch try_catch(pIsolate);
  CFX_ByteString bsScript = CFX_WideString(script).UTF8Encode();
  v8::Local<v8::Context> context = pIsolate->GetCurrentContext();
  v8::Local<v8::Script> compiled_script;
  if (!v8::Script::Compile(
           context, v8::String::NewFromUtf8(
                        pIsolate, bsScript.c_str(), v8::NewStringType::kNormal,
                        bsScript.GetLength()).ToLocalChecked())
           .ToLocal(&compiled_script)) {
    v8::String::Utf8Value error(try_catch.Exception());
    // TODO(tsepez): return error via pError->message.
    return -1;
  }

  v8::Local<v8::Value> result;
  if (!compiled_script->Run(context).ToLocal(&result)) {
    v8::String::Utf8Value error(try_catch.Exception());
    // TODO(tsepez): return error via pError->message.
    return -1;
  }
  return 0;
}

v8::Local<v8::Object> FXJS_NewFxDynamicObj(v8::Isolate* pIsolate,
                                           IJS_Runtime* pIRuntime,
                                           int nObjDefnID,
                                           bool bStatic) {
  v8::Isolate::Scope isolate_scope(pIsolate);
  v8::Local<v8::Context> context = pIsolate->GetCurrentContext();
  if (nObjDefnID == -1) {
    v8::Local<v8::ObjectTemplate> objTempl = v8::ObjectTemplate::New(pIsolate);
    v8::Local<v8::Object> obj;
    if (!objTempl->NewInstance(context).ToLocal(&obj))
      return v8::Local<v8::Object>();
    return obj;
  }

  FXJS_PerIsolateData* pData = FXJS_PerIsolateData::Get(pIsolate);
  if (!pData)
    return v8::Local<v8::Object>();

  if (nObjDefnID < 0 || nObjDefnID >= CFXJS_ObjDefinition::MaxID(pIsolate))
    return v8::Local<v8::Object>();

  CFXJS_ObjDefinition* pObjDef =
      CFXJS_ObjDefinition::ForID(pIsolate, nObjDefnID);
  v8::Local<v8::Object> obj;
  if (!pObjDef->GetInstanceTemplate()->NewInstance(context).ToLocal(&obj))
    return v8::Local<v8::Object>();

  CFXJS_PerObjectData* pPerObjData = new CFXJS_PerObjectData(nObjDefnID);
  obj->SetAlignedPointerInInternalField(0, pPerObjData);
  if (pObjDef->m_pConstructor)
    pObjDef->m_pConstructor(pIRuntime, obj);

  if (!bStatic && FXJS_PerIsolateData::Get(pIsolate)->m_pDynamicObjsMap) {
    FXJS_PerIsolateData::Get(pIsolate)
        ->m_pDynamicObjsMap->set(pPerObjData, obj);
  }
  return obj;
}

v8::Local<v8::Object> FXJS_GetThisObj(v8::Isolate* pIsolate) {
  v8::Isolate::Scope isolate_scope(pIsolate);
  if (!FXJS_PerIsolateData::Get(pIsolate))
    return v8::Local<v8::Object>();

  // Return the global object.
  v8::Local<v8::Context> context = pIsolate->GetCurrentContext();
  return context->Global()->GetPrototype()->ToObject(context).ToLocalChecked();
}

int FXJS_GetObjDefnID(v8::Local<v8::Object> pObj) {
  if (pObj.IsEmpty() || !pObj->InternalFieldCount())
    return -1;
  CFXJS_PerObjectData* pPerObjectData = static_cast<CFXJS_PerObjectData*>(
      pObj->GetAlignedPointerFromInternalField(0));
  if (pPerObjectData)
    return pPerObjectData->m_ObjDefID;
  return -1;
}

void FXJS_Error(v8::Isolate* pIsolate, const CFX_WideString& message) {
  // Conversion from pdfium's wchar_t wide-strings to v8's uint16_t
  // wide-strings isn't handled by v8, so use UTF8 as a common
  // intermediate format.
  CFX_ByteString utf8_message = message.UTF8Encode();
  pIsolate->ThrowException(
      v8::String::NewFromUtf8(pIsolate, utf8_message.c_str(),
                              v8::NewStringType::kNormal).ToLocalChecked());
}

const wchar_t* FXJS_GetTypeof(v8::Local<v8::Value> pObj) {
  if (pObj.IsEmpty())
    return NULL;
  if (pObj->IsString())
    return kFXJSValueNameString;
  if (pObj->IsNumber())
    return kFXJSValueNameNumber;
  if (pObj->IsBoolean())
    return kFXJSValueNameBoolean;
  if (pObj->IsDate())
    return kFXJSValueNameDate;
  if (pObj->IsObject())
    return kFXJSValueNameObject;
  if (pObj->IsNull())
    return kFXJSValueNameNull;
  if (pObj->IsUndefined())
    return kFXJSValueNameUndefined;
  return NULL;
}

void FXJS_SetPrivate(v8::Isolate* pIsolate,
                     v8::Local<v8::Object> pObj,
                     void* p) {
  if (pObj.IsEmpty() || !pObj->InternalFieldCount())
    return;
  CFXJS_PerObjectData* pPerObjectData = static_cast<CFXJS_PerObjectData*>(
      pObj->GetAlignedPointerFromInternalField(0));
  if (!pPerObjectData)
    return;
  pPerObjectData->m_pPrivate = p;
}

void* FXJS_GetPrivate(v8::Isolate* pIsolate, v8::Local<v8::Object> pObj) {
  if (pObj.IsEmpty())
    return nullptr;
  CFXJS_PerObjectData* pPerObjectData = nullptr;
  if (pObj->InternalFieldCount()) {
    pPerObjectData = static_cast<CFXJS_PerObjectData*>(
        pObj->GetAlignedPointerFromInternalField(0));
  } else {
    // It could be a global proxy object.
    v8::Local<v8::Value> v = pObj->GetPrototype();
    v8::Local<v8::Context> context = pIsolate->GetCurrentContext();
    if (v->IsObject()) {
      pPerObjectData = static_cast<CFXJS_PerObjectData*>(
          v->ToObject(context)
              .ToLocalChecked()
              ->GetAlignedPointerFromInternalField(0));
    }
  }
  return pPerObjectData ? pPerObjectData->m_pPrivate : nullptr;
}

void FXJS_FreePrivate(void* pPerObjectData) {
  delete static_cast<CFXJS_PerObjectData*>(pPerObjectData);
}

void FXJS_FreePrivate(v8::Local<v8::Object> pObj) {
  if (pObj.IsEmpty() || !pObj->InternalFieldCount())
    return;
  FXJS_FreePrivate(pObj->GetAlignedPointerFromInternalField(0));
  pObj->SetAlignedPointerInInternalField(0, NULL);
}

v8::Local<v8::String> FXJS_WSToJSString(v8::Isolate* pIsolate,
                                        const wchar_t* PropertyName,
                                        int Len) {
  CFX_WideString ws = CFX_WideString(PropertyName, Len);
  CFX_ByteString bs = ws.UTF8Encode();
  if (!pIsolate)
    pIsolate = v8::Isolate::GetCurrent();
  return v8::String::NewFromUtf8(pIsolate, bs.c_str(),
                                 v8::NewStringType::kNormal).ToLocalChecked();
}

v8::Local<v8::Value> FXJS_GetObjectElement(v8::Isolate* pIsolate,
                                           v8::Local<v8::Object> pObj,
                                           const wchar_t* PropertyName) {
  if (pObj.IsEmpty())
    return v8::Local<v8::Value>();
  v8::Local<v8::Value> val;
  if (!pObj->Get(pIsolate->GetCurrentContext(),
                 FXJS_WSToJSString(pIsolate, PropertyName)).ToLocal(&val))
    return v8::Local<v8::Value>();
  return val;
}

v8::Local<v8::Array> FXJS_GetObjectElementNames(v8::Isolate* pIsolate,
                                                v8::Local<v8::Object> pObj) {
  if (pObj.IsEmpty())
    return v8::Local<v8::Array>();
  v8::Local<v8::Array> val;
  if (!pObj->GetPropertyNames(pIsolate->GetCurrentContext()).ToLocal(&val))
    return v8::Local<v8::Array>();
  return val;
}

void FXJS_PutObjectString(v8::Isolate* pIsolate,
                          v8::Local<v8::Object> pObj,
                          const wchar_t* PropertyName,
                          const wchar_t* sValue) {
  if (pObj.IsEmpty())
    return;
  pObj->Set(pIsolate->GetCurrentContext(),
            FXJS_WSToJSString(pIsolate, PropertyName),
            FXJS_WSToJSString(pIsolate, sValue)).FromJust();
}

void FXJS_PutObjectNumber(v8::Isolate* pIsolate,
                          v8::Local<v8::Object> pObj,
                          const wchar_t* PropertyName,
                          int nValue) {
  if (pObj.IsEmpty())
    return;
  pObj->Set(pIsolate->GetCurrentContext(),
            FXJS_WSToJSString(pIsolate, PropertyName),
            v8::Int32::New(pIsolate, nValue)).FromJust();
}

void FXJS_PutObjectNumber(v8::Isolate* pIsolate,
                          v8::Local<v8::Object> pObj,
                          const wchar_t* PropertyName,
                          float fValue) {
  if (pObj.IsEmpty())
    return;
  pObj->Set(pIsolate->GetCurrentContext(),
            FXJS_WSToJSString(pIsolate, PropertyName),
            v8::Number::New(pIsolate, (double)fValue)).FromJust();
}

void FXJS_PutObjectNumber(v8::Isolate* pIsolate,
                          v8::Local<v8::Object> pObj,
                          const wchar_t* PropertyName,
                          double dValue) {
  if (pObj.IsEmpty())
    return;
  pObj->Set(pIsolate->GetCurrentContext(),
            FXJS_WSToJSString(pIsolate, PropertyName),
            v8::Number::New(pIsolate, (double)dValue)).FromJust();
}

void FXJS_PutObjectBoolean(v8::Isolate* pIsolate,
                           v8::Local<v8::Object> pObj,
                           const wchar_t* PropertyName,
                           bool bValue) {
  if (pObj.IsEmpty())
    return;
  pObj->Set(pIsolate->GetCurrentContext(),
            FXJS_WSToJSString(pIsolate, PropertyName),
            v8::Boolean::New(pIsolate, bValue)).FromJust();
}

void FXJS_PutObjectObject(v8::Isolate* pIsolate,
                          v8::Local<v8::Object> pObj,
                          const wchar_t* PropertyName,
                          v8::Local<v8::Object> pPut) {
  if (pObj.IsEmpty())
    return;
  pObj->Set(pIsolate->GetCurrentContext(),
            FXJS_WSToJSString(pIsolate, PropertyName), pPut).FromJust();
}

void FXJS_PutObjectNull(v8::Isolate* pIsolate,
                        v8::Local<v8::Object> pObj,
                        const wchar_t* PropertyName) {
  if (pObj.IsEmpty())
    return;
  pObj->Set(pIsolate->GetCurrentContext(),
            FXJS_WSToJSString(pIsolate, PropertyName),
            v8::Local<v8::Object>()).FromJust();
}

v8::Local<v8::Array> FXJS_NewArray(v8::Isolate* pIsolate) {
  return v8::Array::New(pIsolate);
}

unsigned FXJS_PutArrayElement(v8::Isolate* pIsolate,
                              v8::Local<v8::Array> pArray,
                              unsigned index,
                              v8::Local<v8::Value> pValue) {
  if (pArray.IsEmpty())
    return 0;
  if (pArray->Set(pIsolate->GetCurrentContext(), index, pValue).IsNothing())
    return 0;
  return 1;
}

v8::Local<v8::Value> FXJS_GetArrayElement(v8::Isolate* pIsolate,
                                          v8::Local<v8::Array> pArray,
                                          unsigned index) {
  if (pArray.IsEmpty())
    return v8::Local<v8::Value>();
  v8::Local<v8::Value> val;
  if (!pArray->Get(pIsolate->GetCurrentContext(), index).ToLocal(&val))
    return v8::Local<v8::Value>();
  return val;
}

unsigned FXJS_GetArrayLength(v8::Local<v8::Array> pArray) {
  if (pArray.IsEmpty())
    return 0;
  return pArray->Length();
}

v8::Local<v8::Value> FXJS_NewNumber(v8::Isolate* pIsolate, int number) {
  return v8::Int32::New(pIsolate, number);
}

v8::Local<v8::Value> FXJS_NewNumber(v8::Isolate* pIsolate, double number) {
  return v8::Number::New(pIsolate, number);
}

v8::Local<v8::Value> FXJS_NewNumber(v8::Isolate* pIsolate, float number) {
  return v8::Number::New(pIsolate, (float)number);
}

v8::Local<v8::Value> FXJS_NewBoolean(v8::Isolate* pIsolate, bool b) {
  return v8::Boolean::New(pIsolate, b);
}

v8::Local<v8::Value> FXJS_NewObject(v8::Isolate* pIsolate,
                                    v8::Local<v8::Object> pObj) {
  if (pObj.IsEmpty())
    return v8::Local<v8::Value>();
  return pObj->Clone();
}

v8::Local<v8::Value> FXJS_NewObject2(v8::Isolate* pIsolate,
                                     v8::Local<v8::Array> pObj) {
  if (pObj.IsEmpty())
    return v8::Local<v8::Value>();
  return pObj->Clone();
}

v8::Local<v8::Value> FXJS_NewString(v8::Isolate* pIsolate,
                                    const wchar_t* string) {
  return FXJS_WSToJSString(pIsolate, string);
}

v8::Local<v8::Value> FXJS_NewNull() {
  return v8::Local<v8::Value>();
}

v8::Local<v8::Value> FXJS_NewDate(v8::Isolate* pIsolate, double d) {
  return v8::Date::New(pIsolate->GetCurrentContext(), d).ToLocalChecked();
}

int FXJS_ToInt32(v8::Isolate* pIsolate, v8::Local<v8::Value> pValue) {
  if (pValue.IsEmpty())
    return 0;
  v8::Local<v8::Context> context = pIsolate->GetCurrentContext();
  return pValue->ToInt32(context).ToLocalChecked()->Value();
}

bool FXJS_ToBoolean(v8::Isolate* pIsolate, v8::Local<v8::Value> pValue) {
  if (pValue.IsEmpty())
    return false;
  v8::Local<v8::Context> context = pIsolate->GetCurrentContext();
  return pValue->ToBoolean(context).ToLocalChecked()->Value();
}

double FXJS_ToNumber(v8::Isolate* pIsolate, v8::Local<v8::Value> pValue) {
  if (pValue.IsEmpty())
    return 0.0;
  v8::Local<v8::Context> context = pIsolate->GetCurrentContext();
  return pValue->ToNumber(context).ToLocalChecked()->Value();
}

v8::Local<v8::Object> FXJS_ToObject(v8::Isolate* pIsolate,
                                    v8::Local<v8::Value> pValue) {
  if (pValue.IsEmpty())
    return v8::Local<v8::Object>();
  v8::Local<v8::Context> context = pIsolate->GetCurrentContext();
  return pValue->ToObject(context).ToLocalChecked();
}

CFX_WideString FXJS_ToString(v8::Isolate* pIsolate,
                             v8::Local<v8::Value> pValue) {
  if (pValue.IsEmpty())
    return L"";
  v8::Local<v8::Context> context = pIsolate->GetCurrentContext();
  v8::String::Utf8Value s(pValue->ToString(context).ToLocalChecked());
  return CFX_WideString::FromUTF8(*s, s.length());
}

v8::Local<v8::Array> FXJS_ToArray(v8::Isolate* pIsolate,
                                  v8::Local<v8::Value> pValue) {
  if (pValue.IsEmpty())
    return v8::Local<v8::Array>();
  v8::Local<v8::Context> context = pIsolate->GetCurrentContext();
  return v8::Local<v8::Array>::Cast(pValue->ToObject(context).ToLocalChecked());
}

void FXJS_ValueCopy(v8::Local<v8::Value>& pTo, v8::Local<v8::Value> pFrom) {
  pTo = pFrom;
}


