From b3f2467e065fdb36ae7c46e0a3e0b2902c8eb7f8 Mon Sep 17 00:00:00 2001 From: dsinclair Date: Tue, 12 Jul 2016 10:42:14 -0700 Subject: Move fpdfsdk/jsapi into fxjs/ This CL moves the fpdfsdk/sjapi code info fxjs/. The "fxjs" library is moved from being XFA specific to being compiled if V8 is enabled. The fxjs_v8 files are required when building for XFA (they have XFA defines in them) and are used in CFXJS_RuntimeData. The cfxjse_* files are only added if XFA is also enabled. Review-Url: https://codereview.chromium.org/2144603003 --- BUILD.gn | 64 ++- fpdfsdk/javascript/JS_Define.h | 2 +- fpdfsdk/javascript/JS_Object.h | 2 +- fpdfsdk/javascript/JS_Value.h | 2 +- fpdfsdk/javascript/cjs_runtime.h | 2 +- fpdfsdk/jsapi/fxjs_v8.cpp | 856 --------------------------------- fpdfsdk/jsapi/fxjs_v8_embeddertest.cpp | 83 ---- fpdfsdk/jsapi/include/fxjs_v8.h | 290 ----------- fxjs/DEPS | 2 - fxjs/cfxjse_runtimedata.cpp | 2 +- fxjs/fxjs_v8.cpp | 856 +++++++++++++++++++++++++++++++++ fxjs/fxjs_v8_embeddertest.cpp | 83 ++++ fxjs/include/fxjs_v8.h | 290 +++++++++++ pdfium.gyp | 58 ++- testing/DEPS | 2 +- testing/js_embedder_test.h | 2 +- xfa.gyp | 35 -- 17 files changed, 1312 insertions(+), 1319 deletions(-) delete mode 100644 fpdfsdk/jsapi/fxjs_v8.cpp delete mode 100644 fpdfsdk/jsapi/fxjs_v8_embeddertest.cpp delete mode 100644 fpdfsdk/jsapi/include/fxjs_v8.h create mode 100644 fxjs/fxjs_v8.cpp create mode 100644 fxjs/fxjs_v8_embeddertest.cpp create mode 100644 fxjs/include/fxjs_v8.h diff --git a/BUILD.gn b/BUILD.gn index 96df81c039..706ea900bc 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -828,15 +828,9 @@ static_library("javascript") { "fpdfsdk/javascript/resource.h", "fpdfsdk/javascript/util.cpp", "fpdfsdk/javascript/util.h", - "fpdfsdk/jsapi/fxjs_v8.cpp", - "fpdfsdk/jsapi/include/fxjs_v8.h", ] - include_dirs = [ - "//v8", - "//v8/include", - ] - public_deps = [ - "//v8", + deps = [ + ":fxjs", ] configs += [ "//v8:external_startup_data" ] } else { @@ -869,25 +863,32 @@ static_library("formfiller") { configs += [ ":pdfium_core_config" ] } -if (pdf_enable_xfa) { +if (pdf_enable_v8) { static_library("fxjs") { sources = [ - "fxjs/cfxjse_arguments.cpp", - "fxjs/cfxjse_class.cpp", - "fxjs/cfxjse_context.cpp", - "fxjs/cfxjse_isolatetracker.cpp", - "fxjs/cfxjse_isolatetracker.h", - "fxjs/cfxjse_runtimedata.cpp", - "fxjs/cfxjse_runtimedata.h", - "fxjs/cfxjse_value.cpp", - "fxjs/include/cfxjse_arguments.h", - "fxjs/include/cfxjse_class.h", - "fxjs/include/cfxjse_context.h", - "fxjs/include/cfxjse_value.h", - "fxjs/include/fxjse.h", + "fxjs/fxjs_v8.cpp", + "fxjs/include/fxjs_v8.h", ] + if (pdf_enable_xfa) { + sources += [ + "fxjs/cfxjse_arguments.cpp", + "fxjs/cfxjse_class.cpp", + "fxjs/cfxjse_context.cpp", + "fxjs/cfxjse_isolatetracker.cpp", + "fxjs/cfxjse_isolatetracker.h", + "fxjs/cfxjse_runtimedata.cpp", + "fxjs/cfxjse_runtimedata.h", + "fxjs/cfxjse_value.cpp", + "fxjs/include/cfxjse_arguments.h", + "fxjs/include/cfxjse_class.h", + "fxjs/include/cfxjse_context.h", + "fxjs/include/cfxjse_value.h", + "fxjs/include/fxjse.h", + ] + } deps = [ - "//v8:v8_libplatform", + "//v8", + "//v8:v8_libplatform", ] configs += [ ":pdfium_core_config" ] include_dirs = [ @@ -898,7 +899,9 @@ if (pdf_enable_xfa) { "//v8", ] } +} +if (pdf_enable_xfa) { static_library("fpdfxfa") { sources = [ "fpdfsdk/fpdfxfa/fpdfxfa_app.cpp", @@ -1456,9 +1459,7 @@ if (pdf_enable_xfa) { "xfa/fxgraphics/cfx_shading.h", "xfa/fxgraphics/include/cfx_graphics.h", ] - include_dirs = [ - ".", - ] + include_dirs = [ "." ] deps = [ ":fxjs", ] @@ -1565,18 +1566,11 @@ test("pdfium_embeddertests") { if (pdf_enable_v8) { sources += [ "fpdfsdk/javascript/public_methods_embeddertest.cpp", - "fpdfsdk/jsapi/fxjs_v8_embeddertest.cpp", + "fxjs/fxjs_v8_embeddertest.cpp", "testing/js_embedder_test.cpp", "testing/js_embedder_test.h", ] - deps += [ - "//v8", - "//v8:v8_libplatform", - ] - include_dirs += [ - "//v8", - "//v8/include", - ] + deps += [ ":fxjs" ] configs += [ "//v8:external_startup_data" ] } configs += [ ":pdfium_core_config" ] diff --git a/fpdfsdk/javascript/JS_Define.h b/fpdfsdk/javascript/JS_Define.h index 2c00818d08..ffef6267c8 100644 --- a/fpdfsdk/javascript/JS_Define.h +++ b/fpdfsdk/javascript/JS_Define.h @@ -12,7 +12,7 @@ #include "fpdfsdk/javascript/JS_Object.h" #include "fpdfsdk/javascript/JS_Value.h" #include "fpdfsdk/javascript/resource.h" -#include "fpdfsdk/jsapi/include/fxjs_v8.h" +#include "fxjs/include/fxjs_v8.h" struct JSConstSpec { const wchar_t* pName; diff --git a/fpdfsdk/javascript/JS_Object.h b/fpdfsdk/javascript/JS_Object.h index 908645ce33..7105ec6cd0 100644 --- a/fpdfsdk/javascript/JS_Object.h +++ b/fpdfsdk/javascript/JS_Object.h @@ -12,7 +12,7 @@ #include "fpdfsdk/include/fsdk_define.h" #include "fpdfsdk/javascript/cjs_runtime.h" -#include "fpdfsdk/jsapi/include/fxjs_v8.h" +#include "fxjs/include/fxjs_v8.h" class CJS_Context; class CJS_Object; diff --git a/fpdfsdk/javascript/JS_Value.h b/fpdfsdk/javascript/JS_Value.h index 958c5e070e..e8544504d2 100644 --- a/fpdfsdk/javascript/JS_Value.h +++ b/fpdfsdk/javascript/JS_Value.h @@ -10,7 +10,7 @@ #include #include "core/fxcrt/include/fx_basic.h" -#include "fpdfsdk/jsapi/include/fxjs_v8.h" +#include "fxjs/include/fxjs_v8.h" class CJS_Array; class CJS_Date; diff --git a/fpdfsdk/javascript/cjs_runtime.h b/fpdfsdk/javascript/cjs_runtime.h index 2668367c1b..c43a34b720 100644 --- a/fpdfsdk/javascript/cjs_runtime.h +++ b/fpdfsdk/javascript/cjs_runtime.h @@ -16,7 +16,7 @@ #include "core/fxcrt/include/fx_basic.h" #include "fpdfsdk/javascript/JS_EventHandler.h" #include "fpdfsdk/javascript/ijs_runtime.h" -#include "fpdfsdk/jsapi/include/fxjs_v8.h" +#include "fxjs/include/fxjs_v8.h" class CJS_Context; diff --git a/fpdfsdk/jsapi/fxjs_v8.cpp b/fpdfsdk/jsapi/fxjs_v8.cpp deleted file mode 100644 index ddeb28f237..0000000000 --- a/fpdfsdk/jsapi/fxjs_v8.cpp +++ /dev/null @@ -1,856 +0,0 @@ -// 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/jsapi/include/fxjs_v8.h" - -#include - -#include "core/fxcrt/include/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* 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 fun = v8::FunctionTemplate::New(isolate); - fun->InstanceTemplate()->SetInternalFieldCount(2); - if (eObjType == FXJSOBJTYPE_GLOBAL) { - fun->InstanceTemplate()->Set( - v8::Symbol::GetToStringTag(isolate), - v8::String::NewFromUtf8(isolate, "global", v8::NewStringType::kNormal) - .ToLocalChecked()); - } - m_FunctionTemplate.Reset(isolate, fun); - - v8::Local 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 GetInstanceTemplate() { - v8::EscapableHandleScope scope(m_pIsolate); - v8::Local function = - m_FunctionTemplate.Get(m_pIsolate); - return scope.Escape(function->InstanceTemplate()); - } - - v8::Local 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 m_FunctionTemplate; - v8::Global m_Signature; -}; - -static v8::Local 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) { - v8::Local hGlobalTemplate = - v8::ObjectTemplate::New(pIsolate); - hGlobalTemplate->Set( - v8::Symbol::GetToStringTag(pIsolate), - v8::String::NewFromUtf8(pIsolate, "global", v8::NewStringType::kNormal) - .ToLocalChecked()); - g_DefaultGlobalObjectTemplate = - new v8::Global(pIsolate, hGlobalTemplate); - } - 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 value, - void* key) { - v8::Local 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& 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; -} - -V8TemplateMap::V8TemplateMap(v8::Isolate* isolate) : m_map(isolate) {} - -V8TemplateMap::~V8TemplateMap() {} - -void V8TemplateMap::set(void* key, v8::Local handle) { - ASSERT(!m_map.Contains(key)); - m_map.Set(key, handle); -} - -FXJS_PerIsolateData::~FXJS_PerIsolateData() {} - -// 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( - pIsolate->GetData(g_embedderDataSlot)); -} - -#ifndef PDF_ENABLE_XFA -FXJS_PerIsolateData::FXJS_PerIsolateData() : m_pDynamicObjsMap(nullptr) {} -#else // PDF_ENABLE_XFA -FXJS_PerIsolateData::FXJS_PerIsolateData() - : m_pFXJSERuntimeData(nullptr), m_pDynamicObjsMap(nullptr) {} -#endif // PDF_ENABLE_XFA - -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); - v8::Local fun = v8::FunctionTemplate::New( - pIsolate, pMethodCall, v8::Local(), pObjDef->GetSignature()); - fun->RemovePrototype(); - pObjDef->GetInstanceTemplate()->Set( - v8::String::NewFromUtf8(pIsolate, bsMethodName.c_str(), - v8::NewStringType::kNormal) - .ToLocalChecked(), - fun, 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 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(); - v8::Local fun = - v8::FunctionTemplate::New(pIsolate, pMethodCall); - fun->RemovePrototype(); - GetGlobalObjectTemplate(pIsolate)->Set( - v8::String::NewFromUtf8(pIsolate, bsMethodName.c_str(), - v8::NewStringType::kNormal) - .ToLocalChecked(), - fun, v8::ReadOnly); -} - -void FXJS_DefineGlobalConst(v8::Isolate* pIsolate, - const wchar_t* sConstName, - v8::FunctionCallback pConstGetter) { - v8::Isolate::Scope isolate_scope(pIsolate); - v8::HandleScope handle_scope(pIsolate); - CFX_ByteString bsConst = CFX_WideString(sConstName).UTF8Encode(); - v8::Local fun = - v8::FunctionTemplate::New(pIsolate, pConstGetter); - fun->RemovePrototype(); - GetGlobalObjectTemplate(pIsolate)->SetAccessorProperty( - v8::String::NewFromUtf8(pIsolate, bsConst.c_str(), - v8::NewStringType::kNormal) - .ToLocalChecked(), - fun); -} - -void FXJS_InitializeRuntime( - v8::Isolate* pIsolate, - IJS_Runtime* pIRuntime, - v8::Global* pV8PersistentContext, - std::vector*>* pStaticObjects) { - if (pIsolate == g_isolate) - ++g_isolate_ref_count; - - v8::Isolate::Scope isolate_scope(pIsolate); - v8::HandleScope handle_scope(pIsolate); - - // This has to happen before we call GetGlobalObjectTemplate because that - // method gets the PerIsolateData from pIsolate. - FXJS_PerIsolateData::SetUp(pIsolate); - - v8::Local v8Context = - v8::Context::New(pIsolate, nullptr, GetGlobalObjectTemplate(pIsolate)); - v8::Context::Scope context_scope(v8Context); - - 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 m_ObjName = - v8::String::NewFromUtf8(pIsolate, bs.c_str(), - v8::NewStringType::kNormal, bs.GetLength()) - .ToLocalChecked(); - - v8::Local obj = - FXJS_NewFxDynamicObj(pIsolate, pIRuntime, i, true); - v8Context->Global()->Set(v8Context, m_ObjName, obj).FromJust(); - pStaticObjects->at(i) = new v8::Global(pIsolate, obj); - } - } - pV8PersistentContext->Reset(pIsolate, v8Context); -} - -void FXJS_ReleaseRuntime(v8::Isolate* pIsolate, - v8::Global* pV8PersistentContext, - std::vector*>* pStaticObjects) { - v8::Isolate::Scope isolate_scope(pIsolate); - v8::HandleScope handle_scope(pIsolate); - v8::Local context = - v8::Local::New(pIsolate, *pV8PersistentContext); - v8::Context::Scope context_scope(context); - - FXJS_PerIsolateData* pData = FXJS_PerIsolateData::Get(pIsolate); - if (!pData) - return; - - int maxID = CFXJS_ObjDefinition::MaxID(pIsolate); - for (int i = 0; i < maxID; ++i) { - CFXJS_ObjDefinition* pObjDef = CFXJS_ObjDefinition::ForID(pIsolate, i); - v8::Local 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::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; - - pData->ReleaseDynamicObjsMap(); - 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 context = pIsolate->GetCurrentContext(); - return static_cast( - context->GetAlignedPointerFromEmbedderData(kPerContextDataIndex)); -} - -#ifdef PDF_ENABLE_XFA -void FXJS_SetRuntimeForV8Context(v8::Local v8Context, - IJS_Runtime* pIRuntime) { - v8Context->SetAlignedPointerInEmbedderData(kPerContextDataIndex, pIRuntime); -} -#endif // PDF_ENABLE_XFA - -int FXJS_Execute(v8::Isolate* pIsolate, - const CFX_WideString& script, - FXJSErr* pError) { - v8::Isolate::Scope isolate_scope(pIsolate); - v8::TryCatch try_catch(pIsolate); - CFX_ByteString bsScript = script.UTF8Encode(); - v8::Local context = pIsolate->GetCurrentContext(); - v8::Local 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 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 FXJS_NewFxDynamicObj(v8::Isolate* pIsolate, - IJS_Runtime* pIRuntime, - int nObjDefnID, - bool bStatic) { - v8::Isolate::Scope isolate_scope(pIsolate); - v8::Local context = pIsolate->GetCurrentContext(); - if (nObjDefnID == -1) { - v8::Local objTempl = v8::ObjectTemplate::New(pIsolate); - v8::Local obj; - if (!objTempl->NewInstance(context).ToLocal(&obj)) - return v8::Local(); - return obj; - } - - FXJS_PerIsolateData* pData = FXJS_PerIsolateData::Get(pIsolate); - if (!pData) - return v8::Local(); - - if (nObjDefnID < 0 || nObjDefnID >= CFXJS_ObjDefinition::MaxID(pIsolate)) - return v8::Local(); - - CFXJS_ObjDefinition* pObjDef = - CFXJS_ObjDefinition::ForID(pIsolate, nObjDefnID); - v8::Local obj; - if (!pObjDef->GetInstanceTemplate()->NewInstance(context).ToLocal(&obj)) - return v8::Local(); - - 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 FXJS_GetThisObj(v8::Isolate* pIsolate) { - v8::Isolate::Scope isolate_scope(pIsolate); - if (!FXJS_PerIsolateData::Get(pIsolate)) - return v8::Local(); - - // Return the global object. - v8::Local context = pIsolate->GetCurrentContext(); - return context->Global()->GetPrototype()->ToObject(context).ToLocalChecked(); -} - -int FXJS_GetObjDefnID(v8::Local pObj) { - if (pObj.IsEmpty() || !pObj->InternalFieldCount()) - return -1; - CFXJS_PerObjectData* pPerObjectData = static_cast( - 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 pObj) { - if (pObj.IsEmpty()) - return nullptr; - 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 nullptr; -} - -void FXJS_SetPrivate(v8::Isolate* pIsolate, - v8::Local pObj, - void* p) { - if (pObj.IsEmpty() || !pObj->InternalFieldCount()) - return; - CFXJS_PerObjectData* pPerObjectData = static_cast( - pObj->GetAlignedPointerFromInternalField(0)); - if (!pPerObjectData) - return; - pPerObjectData->m_pPrivate = p; -} - -void* FXJS_GetPrivate(v8::Isolate* pIsolate, v8::Local pObj) { - if (pObj.IsEmpty()) - return nullptr; - CFXJS_PerObjectData* pPerObjectData = nullptr; - if (pObj->InternalFieldCount()) { - pPerObjectData = static_cast( - pObj->GetAlignedPointerFromInternalField(0)); - } else { - // It could be a global proxy object. - v8::Local v = pObj->GetPrototype(); - v8::Local context = pIsolate->GetCurrentContext(); - if (v->IsObject()) { - pPerObjectData = static_cast( - v->ToObject(context) - .ToLocalChecked() - ->GetAlignedPointerFromInternalField(0)); - } - } - return pPerObjectData ? pPerObjectData->m_pPrivate : nullptr; -} - -void FXJS_FreePrivate(void* pPerObjectData) { - delete static_cast(pPerObjectData); -} - -void FXJS_FreePrivate(v8::Local pObj) { - if (pObj.IsEmpty() || !pObj->InternalFieldCount()) - return; - FXJS_FreePrivate(pObj->GetAlignedPointerFromInternalField(0)); - pObj->SetAlignedPointerInInternalField(0, nullptr); -} - -v8::Local FXJS_WSToJSString(v8::Isolate* pIsolate, - const CFX_WideString& wsPropertyName) { - CFX_ByteString bs = wsPropertyName.UTF8Encode(); - if (!pIsolate) - pIsolate = v8::Isolate::GetCurrent(); - return v8::String::NewFromUtf8(pIsolate, bs.c_str(), - v8::NewStringType::kNormal, bs.GetLength()) - .ToLocalChecked(); -} - -v8::Local FXJS_GetObjectElement( - v8::Isolate* pIsolate, - v8::Local pObj, - const CFX_WideString& wsPropertyName) { - if (pObj.IsEmpty()) - return v8::Local(); - v8::Local val; - if (!pObj->Get(pIsolate->GetCurrentContext(), - FXJS_WSToJSString(pIsolate, wsPropertyName)) - .ToLocal(&val)) - return v8::Local(); - return val; -} - -v8::Local FXJS_GetObjectElementNames(v8::Isolate* pIsolate, - v8::Local pObj) { - if (pObj.IsEmpty()) - return v8::Local(); - v8::Local val; - if (!pObj->GetPropertyNames(pIsolate->GetCurrentContext()).ToLocal(&val)) - return v8::Local(); - return val; -} - -void FXJS_PutObjectString(v8::Isolate* pIsolate, - v8::Local pObj, - const CFX_WideString& wsPropertyName, - const CFX_WideString& wsValue) { - if (pObj.IsEmpty()) - return; - pObj->Set(pIsolate->GetCurrentContext(), - FXJS_WSToJSString(pIsolate, wsPropertyName), - FXJS_WSToJSString(pIsolate, wsValue)) - .FromJust(); -} - -void FXJS_PutObjectNumber(v8::Isolate* pIsolate, - v8::Local pObj, - const CFX_WideString& wsPropertyName, - int nValue) { - if (pObj.IsEmpty()) - return; - pObj->Set(pIsolate->GetCurrentContext(), - FXJS_WSToJSString(pIsolate, wsPropertyName), - v8::Int32::New(pIsolate, nValue)) - .FromJust(); -} - -void FXJS_PutObjectNumber(v8::Isolate* pIsolate, - v8::Local pObj, - const CFX_WideString& wsPropertyName, - float fValue) { - if (pObj.IsEmpty()) - return; - pObj->Set(pIsolate->GetCurrentContext(), - FXJS_WSToJSString(pIsolate, wsPropertyName), - v8::Number::New(pIsolate, (double)fValue)) - .FromJust(); -} - -void FXJS_PutObjectNumber(v8::Isolate* pIsolate, - v8::Local pObj, - const CFX_WideString& wsPropertyName, - double dValue) { - if (pObj.IsEmpty()) - return; - pObj->Set(pIsolate->GetCurrentContext(), - FXJS_WSToJSString(pIsolate, wsPropertyName), - v8::Number::New(pIsolate, (double)dValue)) - .FromJust(); -} - -void FXJS_PutObjectBoolean(v8::Isolate* pIsolate, - v8::Local pObj, - const CFX_WideString& wsPropertyName, - bool bValue) { - if (pObj.IsEmpty()) - return; - pObj->Set(pIsolate->GetCurrentContext(), - FXJS_WSToJSString(pIsolate, wsPropertyName), - v8::Boolean::New(pIsolate, bValue)) - .FromJust(); -} - -void FXJS_PutObjectObject(v8::Isolate* pIsolate, - v8::Local pObj, - const CFX_WideString& wsPropertyName, - v8::Local pPut) { - if (pObj.IsEmpty()) - return; - pObj->Set(pIsolate->GetCurrentContext(), - FXJS_WSToJSString(pIsolate, wsPropertyName), pPut) - .FromJust(); -} - -void FXJS_PutObjectNull(v8::Isolate* pIsolate, - v8::Local pObj, - const CFX_WideString& wsPropertyName) { - if (pObj.IsEmpty()) - return; - pObj->Set(pIsolate->GetCurrentContext(), - FXJS_WSToJSString(pIsolate, wsPropertyName), - v8::Local()) - .FromJust(); -} - -v8::Local FXJS_NewArray(v8::Isolate* pIsolate) { - return v8::Array::New(pIsolate); -} - -unsigned FXJS_PutArrayElement(v8::Isolate* pIsolate, - v8::Local pArray, - unsigned index, - v8::Local pValue) { - if (pArray.IsEmpty()) - return 0; - if (pArray->Set(pIsolate->GetCurrentContext(), index, pValue).IsNothing()) - return 0; - return 1; -} - -v8::Local FXJS_GetArrayElement(v8::Isolate* pIsolate, - v8::Local pArray, - unsigned index) { - if (pArray.IsEmpty()) - return v8::Local(); - v8::Local val; - if (!pArray->Get(pIsolate->GetCurrentContext(), index).ToLocal(&val)) - return v8::Local(); - return val; -} - -unsigned FXJS_GetArrayLength(v8::Local pArray) { - if (pArray.IsEmpty()) - return 0; - return pArray->Length(); -} - -v8::Local FXJS_NewNumber(v8::Isolate* pIsolate, int number) { - return v8::Int32::New(pIsolate, number); -} - -v8::Local FXJS_NewNumber(v8::Isolate* pIsolate, double number) { - return v8::Number::New(pIsolate, number); -} - -v8::Local FXJS_NewNumber(v8::Isolate* pIsolate, float number) { - return v8::Number::New(pIsolate, (float)number); -} - -v8::Local FXJS_NewBoolean(v8::Isolate* pIsolate, bool b) { - return v8::Boolean::New(pIsolate, b); -} - -v8::Local FXJS_NewObject(v8::Isolate* pIsolate, - v8::Local pObj) { - if (pObj.IsEmpty()) - return v8::Local(); - return pObj->Clone(); -} - -v8::Local FXJS_NewObject2(v8::Isolate* pIsolate, - v8::Local pObj) { - if (pObj.IsEmpty()) - return v8::Local(); - return pObj->Clone(); -} - -v8::Local FXJS_NewString(v8::Isolate* pIsolate, const wchar_t* str) { - return FXJS_WSToJSString(pIsolate, str); -} - -v8::Local FXJS_NewNull() { - return v8::Local(); -} - -v8::Local FXJS_NewDate(v8::Isolate* pIsolate, double d) { - return v8::Date::New(pIsolate->GetCurrentContext(), d).ToLocalChecked(); -} - -int FXJS_ToInt32(v8::Isolate* pIsolate, v8::Local pValue) { - if (pValue.IsEmpty()) - return 0; - v8::Local context = pIsolate->GetCurrentContext(); - return pValue->ToInt32(context).ToLocalChecked()->Value(); -} - -bool FXJS_ToBoolean(v8::Isolate* pIsolate, v8::Local pValue) { - if (pValue.IsEmpty()) - return false; - v8::Local context = pIsolate->GetCurrentContext(); - return pValue->ToBoolean(context).ToLocalChecked()->Value(); -} - -double FXJS_ToNumber(v8::Isolate* pIsolate, v8::Local pValue) { - if (pValue.IsEmpty()) - return 0.0; - v8::Local context = pIsolate->GetCurrentContext(); - return pValue->ToNumber(context).ToLocalChecked()->Value(); -} - -v8::Local FXJS_ToObject(v8::Isolate* pIsolate, - v8::Local pValue) { - if (pValue.IsEmpty()) - return v8::Local(); - v8::Local context = pIsolate->GetCurrentContext(); - return pValue->ToObject(context).ToLocalChecked(); -} - -CFX_WideString FXJS_ToString(v8::Isolate* pIsolate, - v8::Local pValue) { - if (pValue.IsEmpty()) - return L""; - v8::Local context = pIsolate->GetCurrentContext(); - v8::String::Utf8Value s(pValue->ToString(context).ToLocalChecked()); - return CFX_WideString::FromUTF8(CFX_ByteStringC(*s, s.length())); -} - -v8::Local FXJS_ToArray(v8::Isolate* pIsolate, - v8::Local pValue) { - if (pValue.IsEmpty()) - return v8::Local(); - v8::Local context = pIsolate->GetCurrentContext(); - return v8::Local::Cast(pValue->ToObject(context).ToLocalChecked()); -} - -void FXJS_ValueCopy(v8::Local& pTo, v8::Local pFrom) { - pTo = pFrom; -} diff --git a/fpdfsdk/jsapi/fxjs_v8_embeddertest.cpp b/fpdfsdk/jsapi/fxjs_v8_embeddertest.cpp deleted file mode 100644 index b33ddca32d..0000000000 --- a/fpdfsdk/jsapi/fxjs_v8_embeddertest.cpp +++ /dev/null @@ -1,83 +0,0 @@ -// Copyright 2015 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. - -#include "testing/gtest/include/gtest/gtest.h" -#include "testing/js_embedder_test.h" - -namespace { - -const double kExpected0 = 6.0; -const double kExpected1 = 7.0; -const double kExpected2 = 8.0; - -const wchar_t kScript0[] = L"fred = 6"; -const wchar_t kScript1[] = L"fred = 7"; -const wchar_t kScript2[] = L"fred = 8"; - -} // namespace - -class FXJSV8EmbedderTest : public JSEmbedderTest { - public: - void ExecuteInCurrentContext(const CFX_WideString& script) { - FXJSErr error; - int sts = FXJS_Execute(isolate(), script, &error); - EXPECT_EQ(0, sts); - } - void CheckAssignmentInCurrentContext(double expected) { - v8::Local This = FXJS_GetThisObj(isolate()); - v8::Local fred = FXJS_GetObjectElement(isolate(), This, L"fred"); - EXPECT_TRUE(fred->IsNumber()); - EXPECT_EQ(expected, fred->ToNumber(isolate()->GetCurrentContext()) - .ToLocalChecked() - ->Value()); - } -}; - -TEST_F(FXJSV8EmbedderTest, Getters) { - v8::Isolate::Scope isolate_scope(isolate()); - v8::HandleScope handle_scope(isolate()); - v8::Context::Scope context_scope(GetV8Context()); - - ExecuteInCurrentContext(CFX_WideString(kScript1)); - CheckAssignmentInCurrentContext(kExpected1); -} - -TEST_F(FXJSV8EmbedderTest, MultipleRutimes) { - v8::Isolate::Scope isolate_scope(isolate()); - v8::HandleScope handle_scope(isolate()); - - v8::Global global_context1; - std::vector*> static_objects1; - FXJS_InitializeRuntime(isolate(), nullptr, &global_context1, - &static_objects1); - - v8::Global global_context2; - std::vector*> static_objects2; - FXJS_InitializeRuntime(isolate(), nullptr, &global_context2, - &static_objects2); - - v8::Context::Scope context_scope(GetV8Context()); - ExecuteInCurrentContext(CFX_WideString(kScript0)); - CheckAssignmentInCurrentContext(kExpected0); - - { - v8::Local context1 = - v8::Local::New(isolate(), global_context1); - v8::Context::Scope context_scope1(context1); - ExecuteInCurrentContext(CFX_WideString(kScript1)); - CheckAssignmentInCurrentContext(kExpected1); - } - FXJS_ReleaseRuntime(isolate(), &global_context1, &static_objects1); - - { - v8::Local context2 = - v8::Local::New(isolate(), global_context2); - v8::Context::Scope context_scope2(context2); - ExecuteInCurrentContext(CFX_WideString(kScript2)); - CheckAssignmentInCurrentContext(kExpected2); - } - FXJS_ReleaseRuntime(isolate(), &global_context2, &static_objects2); - - CheckAssignmentInCurrentContext(kExpected0); -} diff --git a/fpdfsdk/jsapi/include/fxjs_v8.h b/fpdfsdk/jsapi/include/fxjs_v8.h deleted file mode 100644 index 3ae1d5e0ca..0000000000 --- a/fpdfsdk/jsapi/include/fxjs_v8.h +++ /dev/null @@ -1,290 +0,0 @@ -// 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 - -// FXJS_V8 is a layer that makes it easier to define native objects in V8, but -// has no knowledge of PDF-specific native objects. It could in theory be used -// to implement other sets of native objects. - -// PDFium code should include this file rather than including V8 headers -// directly. - -#ifndef FPDFSDK_JSAPI_INCLUDE_FXJS_V8_H_ -#define FPDFSDK_JSAPI_INCLUDE_FXJS_V8_H_ - -#include -#include - -#include - -#include "core/fxcrt/include/fx_string.h" - -class CFXJS_ObjDefinition; - -// FXJS_V8 places no restrictions on these two classes; it merely passes them -// on to caller-provided methods. -class IJS_Context; // A description of the event that caused JS execution. -class IJS_Runtime; // A native runtime, typically owns the v8::Context. - -#ifdef PDF_ENABLE_XFA -// FXJS_V8 places no interpreation on this calass; it merely passes it -// along to XFA. -class CFXJSE_RuntimeData; -#endif // PDF_ENABLE_XFA - -enum FXJSOBJTYPE { - FXJSOBJTYPE_DYNAMIC = 0, // Created by native method and returned to JS. - FXJSOBJTYPE_STATIC, // Created by init and hung off of global object. - FXJSOBJTYPE_GLOBAL, // The global object itself (may only appear once). -}; - -struct FXJSErr { - const wchar_t* message; - const wchar_t* srcline; - unsigned linnum; -}; - -// Global weak map to save dynamic objects. -class V8TemplateMapTraits : public v8::StdMapTraits { - public: - typedef v8::GlobalValueMap MapType; - typedef void WeakCallbackDataType; - - static WeakCallbackDataType* WeakCallbackParameter( - MapType* map, - void* key, - const v8::Local& value) { - return key; - } - static MapType* MapFromWeakCallbackInfo( - const v8::WeakCallbackInfo&); - - static void* KeyFromWeakCallbackInfo( - const v8::WeakCallbackInfo& data) { - return data.GetParameter(); - } - static const v8::PersistentContainerCallbackType kCallbackType = - v8::kWeakWithInternalFields; - static void DisposeWeak( - const v8::WeakCallbackInfo& data) {} - static void OnWeakCallback( - const v8::WeakCallbackInfo& data) {} - static void Dispose(v8::Isolate* isolate, - v8::Global value, - void* key); - static void DisposeCallbackData(WeakCallbackDataType* callbackData) {} -}; - -class V8TemplateMap { - public: - typedef v8::GlobalValueMap MapType; - - explicit V8TemplateMap(v8::Isolate* isolate); - ~V8TemplateMap(); - - void set(void* key, v8::Local handle); - - friend class V8TemplateMapTraits; - - private: - MapType m_map; -}; - -class FXJS_PerIsolateData { - public: - ~FXJS_PerIsolateData(); - - static void SetUp(v8::Isolate* pIsolate); - static FXJS_PerIsolateData* Get(v8::Isolate* pIsolate); - - void CreateDynamicObjsMap(v8::Isolate* pIsolate) { - if (!m_pDynamicObjsMap) - m_pDynamicObjsMap = new V8TemplateMap(pIsolate); - } - void ReleaseDynamicObjsMap() { - delete m_pDynamicObjsMap; - m_pDynamicObjsMap = nullptr; - } - - std::vector m_ObjectDefnArray; -#ifdef PDF_ENABLE_XFA - CFXJSE_RuntimeData* m_pFXJSERuntimeData; -#endif // PDF_ENABLE_XFA - V8TemplateMap* m_pDynamicObjsMap; - - protected: - FXJS_PerIsolateData(); -}; - -extern const wchar_t kFXJSValueNameString[]; -extern const wchar_t kFXJSValueNameNumber[]; -extern const wchar_t kFXJSValueNameBoolean[]; -extern const wchar_t kFXJSValueNameDate[]; -extern const wchar_t kFXJSValueNameObject[]; -extern const wchar_t kFXJSValueNameFxobj[]; -extern const wchar_t kFXJSValueNameNull[]; -extern const wchar_t kFXJSValueNameUndefined[]; - -class FXJS_ArrayBufferAllocator : public v8::ArrayBuffer::Allocator { - void* Allocate(size_t length) override; - void* AllocateUninitialized(size_t length) override; - void Free(void* data, size_t length) override; -}; - -using FXJS_CONSTRUCTOR = void (*)(IJS_Runtime* cc, v8::Local obj); -using FXJS_DESTRUCTOR = void (*)(v8::Local obj); - -void FXJS_Initialize(unsigned int embedderDataSlot, v8::Isolate* pIsolate); -void FXJS_Release(); - -// Gets the global isolate set by FXJS_Initialize(), or makes a new one each -// time if there is no such isolate. Returns true if a new isolate had to be -// created. -bool FXJS_GetIsolate(v8::Isolate** pResultIsolate); - -// Get the global isolate's ref count. -size_t FXJS_GlobalIsolateRefCount(); - -// Always returns a valid, newly-created objDefnID. -int FXJS_DefineObj(v8::Isolate* pIsolate, - const wchar_t* sObjName, - FXJSOBJTYPE eObjType, - FXJS_CONSTRUCTOR pConstructor, - FXJS_DESTRUCTOR pDestructor); - -void FXJS_DefineObjMethod(v8::Isolate* pIsolate, - int nObjDefnID, - const wchar_t* sMethodName, - v8::FunctionCallback pMethodCall); -void FXJS_DefineObjProperty(v8::Isolate* pIsolate, - int nObjDefnID, - const wchar_t* sPropName, - v8::AccessorGetterCallback pPropGet, - v8::AccessorSetterCallback pPropPut); -void FXJS_DefineObjAllProperties(v8::Isolate* pIsolate, - int nObjDefnID, - v8::NamedPropertyQueryCallback pPropQurey, - v8::NamedPropertyGetterCallback pPropGet, - v8::NamedPropertySetterCallback pPropPut, - v8::NamedPropertyDeleterCallback pPropDel); -void FXJS_DefineObjConst(v8::Isolate* pIsolate, - int nObjDefnID, - const wchar_t* sConstName, - v8::Local pDefault); -void FXJS_DefineGlobalMethod(v8::Isolate* pIsolate, - const wchar_t* sMethodName, - v8::FunctionCallback pMethodCall); -void FXJS_DefineGlobalConst(v8::Isolate* pIsolate, - const wchar_t* sConstName, - v8::FunctionCallback pConstGetter); - -// Called after FXJS_Define* calls made. -void FXJS_InitializeRuntime( - v8::Isolate* pIsolate, - IJS_Runtime* pIRuntime, - v8::Global* pV8PersistentContext, - std::vector*>* pStaticObjects); -void FXJS_ReleaseRuntime(v8::Isolate* pIsolate, - v8::Global* pV8PersistentContext, - std::vector*>* pStaticObjects); -IJS_Runtime* FXJS_GetRuntimeFromIsolate(v8::Isolate* pIsolate); - -#ifdef PDF_ENABLE_XFA -// Called as part of FXJS_InitializeRuntime, exposed so PDF can make its -// own contexts compatible with XFA or vice versa. -void FXJS_SetRuntimeForV8Context(v8::Local v8Context, - IJS_Runtime* pIRuntime); -#endif // PDF_ENABLE_XFA - -// Called after FXJS_InitializeRuntime call made. -int FXJS_Execute(v8::Isolate* pIsolate, - const CFX_WideString& script, - FXJSErr* perror); - -v8::Local FXJS_NewFxDynamicObj(v8::Isolate* pIsolate, - IJS_Runtime* pJSContext, - int nObjDefnID, - bool bStatic = false); -v8::Local FXJS_GetThisObj(v8::Isolate* pIsolate); -int FXJS_GetObjDefnID(v8::Local pObj); -const wchar_t* FXJS_GetTypeof(v8::Local pObj); - -void FXJS_SetPrivate(v8::Isolate* pIsolate, - v8::Local pObj, - void* p); -void* FXJS_GetPrivate(v8::Isolate* pIsolate, v8::Local pObj); -void FXJS_FreePrivate(void* p); -void FXJS_FreePrivate(v8::Local pObj); -void FXJS_Error(v8::Isolate* isolate, const CFX_WideString& message); - -v8::Local FXJS_WSToJSString(v8::Isolate* pIsolate, - const CFX_WideString& wsPropertyName); -v8::Local FXJS_GetObjectElement(v8::Isolate* pIsolate, - v8::Local pObj, - const CFX_WideString& PropertyName); -v8::Local FXJS_GetObjectElementNames(v8::Isolate* pIsolate, - v8::Local pObj); -v8::Local FXJS_GetArrayElement(v8::Isolate* pIsolate, - v8::Local pArray, - unsigned index); - -unsigned FXJS_GetArrayLength(v8::Local pArray); -void FXJS_PutObjectString(v8::Isolate* pIsolate, - v8::Local pObj, - const CFX_WideString& wsPropertyName, - const CFX_WideString& wsValue); -void FXJS_PutObjectNumber(v8::Isolate* pIsolate, - v8::Local pObj, - const CFX_WideString& PropertyName, - int nValue); -void FXJS_PutObjectNumber(v8::Isolate* pIsolate, - v8::Local pObj, - const CFX_WideString& PropertyName, - float fValue); -void FXJS_PutObjectNumber(v8::Isolate* pIsolate, - v8::Local pObj, - const CFX_WideString& PropertyName, - double dValue); -void FXJS_PutObjectBoolean(v8::Isolate* pIsolate, - v8::Local pObj, - const CFX_WideString& PropertyName, - bool bValue); -void FXJS_PutObjectObject(v8::Isolate* pIsolate, - v8::Local pObj, - const CFX_WideString& PropertyName, - v8::Local pPut); -void FXJS_PutObjectNull(v8::Isolate* pIsolate, - v8::Local pObj, - const CFX_WideString& PropertyName); -unsigned FXJS_PutArrayElement(v8::Isolate* pIsolate, - v8::Local pArray, - unsigned index, - v8::Local pValue); - -v8::Local FXJS_NewArray(v8::Isolate* pIsolate); -v8::Local FXJS_NewNumber(v8::Isolate* pIsolate, int number); -v8::Local FXJS_NewNumber(v8::Isolate* pIsolate, double number); -v8::Local FXJS_NewNumber(v8::Isolate* pIsolate, float number); -v8::Local FXJS_NewBoolean(v8::Isolate* pIsolate, bool b); -v8::Local FXJS_NewObject(v8::Isolate* pIsolate, - v8::Local pObj); -v8::Local FXJS_NewObject2(v8::Isolate* pIsolate, - v8::Local pObj); -v8::Local FXJS_NewString(v8::Isolate* pIsolate, const wchar_t* str); -v8::Local FXJS_NewNull(); -v8::Local FXJS_NewDate(v8::Isolate* pIsolate, double d); - -int FXJS_ToInt32(v8::Isolate* pIsolate, v8::Local pValue); -bool FXJS_ToBoolean(v8::Isolate* pIsolate, v8::Local pValue); -double FXJS_ToNumber(v8::Isolate* pIsolate, v8::Local pValue); -v8::Local FXJS_ToObject(v8::Isolate* pIsolate, - v8::Local pValue); -CFX_WideString FXJS_ToString(v8::Isolate* pIsolate, - v8::Local pValue); -v8::Local FXJS_ToArray(v8::Isolate* pIsolate, - v8::Local pValue); -void FXJS_ValueCopy(v8::Local& pTo, v8::Local pFrom); - -#endif // FPDFSDK_JSAPI_INCLUDE_FXJS_V8_H_ diff --git a/fxjs/DEPS b/fxjs/DEPS index 18698e4ce4..ccea0b552a 100644 --- a/fxjs/DEPS +++ b/fxjs/DEPS @@ -1,6 +1,4 @@ include_rules = [ '+core/fxcrt/include', - # TODO(dsinclair): Layering violation. FXJSE can't include FPDFSDK. - '+fpdfsdk/jsapi/include', '+v8/include', ] diff --git a/fxjs/cfxjse_runtimedata.cpp b/fxjs/cfxjse_runtimedata.cpp index f58f5f852d..b203cb71ac 100644 --- a/fxjs/cfxjse_runtimedata.cpp +++ b/fxjs/cfxjse_runtimedata.cpp @@ -6,8 +6,8 @@ #include "fxjs/cfxjse_runtimedata.h" -#include "fpdfsdk/jsapi/include/fxjs_v8.h" #include "fxjs/cfxjse_isolatetracker.h" +#include "fxjs/include/fxjs_v8.h" namespace { diff --git a/fxjs/fxjs_v8.cpp b/fxjs/fxjs_v8.cpp new file mode 100644 index 0000000000..c98de070ab --- /dev/null +++ b/fxjs/fxjs_v8.cpp @@ -0,0 +1,856 @@ +// 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 "fxjs/include/fxjs_v8.h" + +#include + +#include "core/fxcrt/include/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* 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 fun = v8::FunctionTemplate::New(isolate); + fun->InstanceTemplate()->SetInternalFieldCount(2); + if (eObjType == FXJSOBJTYPE_GLOBAL) { + fun->InstanceTemplate()->Set( + v8::Symbol::GetToStringTag(isolate), + v8::String::NewFromUtf8(isolate, "global", v8::NewStringType::kNormal) + .ToLocalChecked()); + } + m_FunctionTemplate.Reset(isolate, fun); + + v8::Local 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 GetInstanceTemplate() { + v8::EscapableHandleScope scope(m_pIsolate); + v8::Local function = + m_FunctionTemplate.Get(m_pIsolate); + return scope.Escape(function->InstanceTemplate()); + } + + v8::Local 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 m_FunctionTemplate; + v8::Global m_Signature; +}; + +static v8::Local 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) { + v8::Local hGlobalTemplate = + v8::ObjectTemplate::New(pIsolate); + hGlobalTemplate->Set( + v8::Symbol::GetToStringTag(pIsolate), + v8::String::NewFromUtf8(pIsolate, "global", v8::NewStringType::kNormal) + .ToLocalChecked()); + g_DefaultGlobalObjectTemplate = + new v8::Global(pIsolate, hGlobalTemplate); + } + 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 value, + void* key) { + v8::Local 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& 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; +} + +V8TemplateMap::V8TemplateMap(v8::Isolate* isolate) : m_map(isolate) {} + +V8TemplateMap::~V8TemplateMap() {} + +void V8TemplateMap::set(void* key, v8::Local handle) { + ASSERT(!m_map.Contains(key)); + m_map.Set(key, handle); +} + +FXJS_PerIsolateData::~FXJS_PerIsolateData() {} + +// 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( + pIsolate->GetData(g_embedderDataSlot)); +} + +#ifndef PDF_ENABLE_XFA +FXJS_PerIsolateData::FXJS_PerIsolateData() : m_pDynamicObjsMap(nullptr) {} +#else // PDF_ENABLE_XFA +FXJS_PerIsolateData::FXJS_PerIsolateData() + : m_pFXJSERuntimeData(nullptr), m_pDynamicObjsMap(nullptr) {} +#endif // PDF_ENABLE_XFA + +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); + v8::Local fun = v8::FunctionTemplate::New( + pIsolate, pMethodCall, v8::Local(), pObjDef->GetSignature()); + fun->RemovePrototype(); + pObjDef->GetInstanceTemplate()->Set( + v8::String::NewFromUtf8(pIsolate, bsMethodName.c_str(), + v8::NewStringType::kNormal) + .ToLocalChecked(), + fun, 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 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(); + v8::Local fun = + v8::FunctionTemplate::New(pIsolate, pMethodCall); + fun->RemovePrototype(); + GetGlobalObjectTemplate(pIsolate)->Set( + v8::String::NewFromUtf8(pIsolate, bsMethodName.c_str(), + v8::NewStringType::kNormal) + .ToLocalChecked(), + fun, v8::ReadOnly); +} + +void FXJS_DefineGlobalConst(v8::Isolate* pIsolate, + const wchar_t* sConstName, + v8::FunctionCallback pConstGetter) { + v8::Isolate::Scope isolate_scope(pIsolate); + v8::HandleScope handle_scope(pIsolate); + CFX_ByteString bsConst = CFX_WideString(sConstName).UTF8Encode(); + v8::Local fun = + v8::FunctionTemplate::New(pIsolate, pConstGetter); + fun->RemovePrototype(); + GetGlobalObjectTemplate(pIsolate)->SetAccessorProperty( + v8::String::NewFromUtf8(pIsolate, bsConst.c_str(), + v8::NewStringType::kNormal) + .ToLocalChecked(), + fun); +} + +void FXJS_InitializeRuntime( + v8::Isolate* pIsolate, + IJS_Runtime* pIRuntime, + v8::Global* pV8PersistentContext, + std::vector*>* pStaticObjects) { + if (pIsolate == g_isolate) + ++g_isolate_ref_count; + + v8::Isolate::Scope isolate_scope(pIsolate); + v8::HandleScope handle_scope(pIsolate); + + // This has to happen before we call GetGlobalObjectTemplate because that + // method gets the PerIsolateData from pIsolate. + FXJS_PerIsolateData::SetUp(pIsolate); + + v8::Local v8Context = + v8::Context::New(pIsolate, nullptr, GetGlobalObjectTemplate(pIsolate)); + v8::Context::Scope context_scope(v8Context); + + 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 m_ObjName = + v8::String::NewFromUtf8(pIsolate, bs.c_str(), + v8::NewStringType::kNormal, bs.GetLength()) + .ToLocalChecked(); + + v8::Local obj = + FXJS_NewFxDynamicObj(pIsolate, pIRuntime, i, true); + v8Context->Global()->Set(v8Context, m_ObjName, obj).FromJust(); + pStaticObjects->at(i) = new v8::Global(pIsolate, obj); + } + } + pV8PersistentContext->Reset(pIsolate, v8Context); +} + +void FXJS_ReleaseRuntime(v8::Isolate* pIsolate, + v8::Global* pV8PersistentContext, + std::vector*>* pStaticObjects) { + v8::Isolate::Scope isolate_scope(pIsolate); + v8::HandleScope handle_scope(pIsolate); + v8::Local context = + v8::Local::New(pIsolate, *pV8PersistentContext); + v8::Context::Scope context_scope(context); + + FXJS_PerIsolateData* pData = FXJS_PerIsolateData::Get(pIsolate); + if (!pData) + return; + + int maxID = CFXJS_ObjDefinition::MaxID(pIsolate); + for (int i = 0; i < maxID; ++i) { + CFXJS_ObjDefinition* pObjDef = CFXJS_ObjDefinition::ForID(pIsolate, i); + v8::Local 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::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; + + pData->ReleaseDynamicObjsMap(); + 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 context = pIsolate->GetCurrentContext(); + return static_cast( + context->GetAlignedPointerFromEmbedderData(kPerContextDataIndex)); +} + +#ifdef PDF_ENABLE_XFA +void FXJS_SetRuntimeForV8Context(v8::Local v8Context, + IJS_Runtime* pIRuntime) { + v8Context->SetAlignedPointerInEmbedderData(kPerContextDataIndex, pIRuntime); +} +#endif // PDF_ENABLE_XFA + +int FXJS_Execute(v8::Isolate* pIsolate, + const CFX_WideString& script, + FXJSErr* pError) { + v8::Isolate::Scope isolate_scope(pIsolate); + v8::TryCatch try_catch(pIsolate); + CFX_ByteString bsScript = script.UTF8Encode(); + v8::Local context = pIsolate->GetCurrentContext(); + v8::Local 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 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 FXJS_NewFxDynamicObj(v8::Isolate* pIsolate, + IJS_Runtime* pIRuntime, + int nObjDefnID, + bool bStatic) { + v8::Isolate::Scope isolate_scope(pIsolate); + v8::Local context = pIsolate->GetCurrentContext(); + if (nObjDefnID == -1) { + v8::Local objTempl = v8::ObjectTemplate::New(pIsolate); + v8::Local obj; + if (!objTempl->NewInstance(context).ToLocal(&obj)) + return v8::Local(); + return obj; + } + + FXJS_PerIsolateData* pData = FXJS_PerIsolateData::Get(pIsolate); + if (!pData) + return v8::Local(); + + if (nObjDefnID < 0 || nObjDefnID >= CFXJS_ObjDefinition::MaxID(pIsolate)) + return v8::Local(); + + CFXJS_ObjDefinition* pObjDef = + CFXJS_ObjDefinition::ForID(pIsolate, nObjDefnID); + v8::Local obj; + if (!pObjDef->GetInstanceTemplate()->NewInstance(context).ToLocal(&obj)) + return v8::Local(); + + 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 FXJS_GetThisObj(v8::Isolate* pIsolate) { + v8::Isolate::Scope isolate_scope(pIsolate); + if (!FXJS_PerIsolateData::Get(pIsolate)) + return v8::Local(); + + // Return the global object. + v8::Local context = pIsolate->GetCurrentContext(); + return context->Global()->GetPrototype()->ToObject(context).ToLocalChecked(); +} + +int FXJS_GetObjDefnID(v8::Local pObj) { + if (pObj.IsEmpty() || !pObj->InternalFieldCount()) + return -1; + CFXJS_PerObjectData* pPerObjectData = static_cast( + 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 pObj) { + if (pObj.IsEmpty()) + return nullptr; + 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 nullptr; +} + +void FXJS_SetPrivate(v8::Isolate* pIsolate, + v8::Local pObj, + void* p) { + if (pObj.IsEmpty() || !pObj->InternalFieldCount()) + return; + CFXJS_PerObjectData* pPerObjectData = static_cast( + pObj->GetAlignedPointerFromInternalField(0)); + if (!pPerObjectData) + return; + pPerObjectData->m_pPrivate = p; +} + +void* FXJS_GetPrivate(v8::Isolate* pIsolate, v8::Local pObj) { + if (pObj.IsEmpty()) + return nullptr; + CFXJS_PerObjectData* pPerObjectData = nullptr; + if (pObj->InternalFieldCount()) { + pPerObjectData = static_cast( + pObj->GetAlignedPointerFromInternalField(0)); + } else { + // It could be a global proxy object. + v8::Local v = pObj->GetPrototype(); + v8::Local context = pIsolate->GetCurrentContext(); + if (v->IsObject()) { + pPerObjectData = static_cast( + v->ToObject(context) + .ToLocalChecked() + ->GetAlignedPointerFromInternalField(0)); + } + } + return pPerObjectData ? pPerObjectData->m_pPrivate : nullptr; +} + +void FXJS_FreePrivate(void* pPerObjectData) { + delete static_cast(pPerObjectData); +} + +void FXJS_FreePrivate(v8::Local pObj) { + if (pObj.IsEmpty() || !pObj->InternalFieldCount()) + return; + FXJS_FreePrivate(pObj->GetAlignedPointerFromInternalField(0)); + pObj->SetAlignedPointerInInternalField(0, nullptr); +} + +v8::Local FXJS_WSToJSString(v8::Isolate* pIsolate, + const CFX_WideString& wsPropertyName) { + CFX_ByteString bs = wsPropertyName.UTF8Encode(); + if (!pIsolate) + pIsolate = v8::Isolate::GetCurrent(); + return v8::String::NewFromUtf8(pIsolate, bs.c_str(), + v8::NewStringType::kNormal, bs.GetLength()) + .ToLocalChecked(); +} + +v8::Local FXJS_GetObjectElement( + v8::Isolate* pIsolate, + v8::Local pObj, + const CFX_WideString& wsPropertyName) { + if (pObj.IsEmpty()) + return v8::Local(); + v8::Local val; + if (!pObj->Get(pIsolate->GetCurrentContext(), + FXJS_WSToJSString(pIsolate, wsPropertyName)) + .ToLocal(&val)) + return v8::Local(); + return val; +} + +v8::Local FXJS_GetObjectElementNames(v8::Isolate* pIsolate, + v8::Local pObj) { + if (pObj.IsEmpty()) + return v8::Local(); + v8::Local val; + if (!pObj->GetPropertyNames(pIsolate->GetCurrentContext()).ToLocal(&val)) + return v8::Local(); + return val; +} + +void FXJS_PutObjectString(v8::Isolate* pIsolate, + v8::Local pObj, + const CFX_WideString& wsPropertyName, + const CFX_WideString& wsValue) { + if (pObj.IsEmpty()) + return; + pObj->Set(pIsolate->GetCurrentContext(), + FXJS_WSToJSString(pIsolate, wsPropertyName), + FXJS_WSToJSString(pIsolate, wsValue)) + .FromJust(); +} + +void FXJS_PutObjectNumber(v8::Isolate* pIsolate, + v8::Local pObj, + const CFX_WideString& wsPropertyName, + int nValue) { + if (pObj.IsEmpty()) + return; + pObj->Set(pIsolate->GetCurrentContext(), + FXJS_WSToJSString(pIsolate, wsPropertyName), + v8::Int32::New(pIsolate, nValue)) + .FromJust(); +} + +void FXJS_PutObjectNumber(v8::Isolate* pIsolate, + v8::Local pObj, + const CFX_WideString& wsPropertyName, + float fValue) { + if (pObj.IsEmpty()) + return; + pObj->Set(pIsolate->GetCurrentContext(), + FXJS_WSToJSString(pIsolate, wsPropertyName), + v8::Number::New(pIsolate, (double)fValue)) + .FromJust(); +} + +void FXJS_PutObjectNumber(v8::Isolate* pIsolate, + v8::Local pObj, + const CFX_WideString& wsPropertyName, + double dValue) { + if (pObj.IsEmpty()) + return; + pObj->Set(pIsolate->GetCurrentContext(), + FXJS_WSToJSString(pIsolate, wsPropertyName), + v8::Number::New(pIsolate, (double)dValue)) + .FromJust(); +} + +void FXJS_PutObjectBoolean(v8::Isolate* pIsolate, + v8::Local pObj, + const CFX_WideString& wsPropertyName, + bool bValue) { + if (pObj.IsEmpty()) + return; + pObj->Set(pIsolate->GetCurrentContext(), + FXJS_WSToJSString(pIsolate, wsPropertyName), + v8::Boolean::New(pIsolate, bValue)) + .FromJust(); +} + +void FXJS_PutObjectObject(v8::Isolate* pIsolate, + v8::Local pObj, + const CFX_WideString& wsPropertyName, + v8::Local pPut) { + if (pObj.IsEmpty()) + return; + pObj->Set(pIsolate->GetCurrentContext(), + FXJS_WSToJSString(pIsolate, wsPropertyName), pPut) + .FromJust(); +} + +void FXJS_PutObjectNull(v8::Isolate* pIsolate, + v8::Local pObj, + const CFX_WideString& wsPropertyName) { + if (pObj.IsEmpty()) + return; + pObj->Set(pIsolate->GetCurrentContext(), + FXJS_WSToJSString(pIsolate, wsPropertyName), + v8::Local()) + .FromJust(); +} + +v8::Local FXJS_NewArray(v8::Isolate* pIsolate) { + return v8::Array::New(pIsolate); +} + +unsigned FXJS_PutArrayElement(v8::Isolate* pIsolate, + v8::Local pArray, + unsigned index, + v8::Local pValue) { + if (pArray.IsEmpty()) + return 0; + if (pArray->Set(pIsolate->GetCurrentContext(), index, pValue).IsNothing()) + return 0; + return 1; +} + +v8::Local FXJS_GetArrayElement(v8::Isolate* pIsolate, + v8::Local pArray, + unsigned index) { + if (pArray.IsEmpty()) + return v8::Local(); + v8::Local val; + if (!pArray->Get(pIsolate->GetCurrentContext(), index).ToLocal(&val)) + return v8::Local(); + return val; +} + +unsigned FXJS_GetArrayLength(v8::Local pArray) { + if (pArray.IsEmpty()) + return 0; + return pArray->Length(); +} + +v8::Local FXJS_NewNumber(v8::Isolate* pIsolate, int number) { + return v8::Int32::New(pIsolate, number); +} + +v8::Local FXJS_NewNumber(v8::Isolate* pIsolate, double number) { + return v8::Number::New(pIsolate, number); +} + +v8::Local FXJS_NewNumber(v8::Isolate* pIsolate, float number) { + return v8::Number::New(pIsolate, (float)number); +} + +v8::Local FXJS_NewBoolean(v8::Isolate* pIsolate, bool b) { + return v8::Boolean::New(pIsolate, b); +} + +v8::Local FXJS_NewObject(v8::Isolate* pIsolate, + v8::Local pObj) { + if (pObj.IsEmpty()) + return v8::Local(); + return pObj->Clone(); +} + +v8::Local FXJS_NewObject2(v8::Isolate* pIsolate, + v8::Local pObj) { + if (pObj.IsEmpty()) + return v8::Local(); + return pObj->Clone(); +} + +v8::Local FXJS_NewString(v8::Isolate* pIsolate, const wchar_t* str) { + return FXJS_WSToJSString(pIsolate, str); +} + +v8::Local FXJS_NewNull() { + return v8::Local(); +} + +v8::Local FXJS_NewDate(v8::Isolate* pIsolate, double d) { + return v8::Date::New(pIsolate->GetCurrentContext(), d).ToLocalChecked(); +} + +int FXJS_ToInt32(v8::Isolate* pIsolate, v8::Local pValue) { + if (pValue.IsEmpty()) + return 0; + v8::Local context = pIsolate->GetCurrentContext(); + return pValue->ToInt32(context).ToLocalChecked()->Value(); +} + +bool FXJS_ToBoolean(v8::Isolate* pIsolate, v8::Local pValue) { + if (pValue.IsEmpty()) + return false; + v8::Local context = pIsolate->GetCurrentContext(); + return pValue->ToBoolean(context).ToLocalChecked()->Value(); +} + +double FXJS_ToNumber(v8::Isolate* pIsolate, v8::Local pValue) { + if (pValue.IsEmpty()) + return 0.0; + v8::Local context = pIsolate->GetCurrentContext(); + return pValue->ToNumber(context).ToLocalChecked()->Value(); +} + +v8::Local FXJS_ToObject(v8::Isolate* pIsolate, + v8::Local pValue) { + if (pValue.IsEmpty()) + return v8::Local(); + v8::Local context = pIsolate->GetCurrentContext(); + return pValue->ToObject(context).ToLocalChecked(); +} + +CFX_WideString FXJS_ToString(v8::Isolate* pIsolate, + v8::Local pValue) { + if (pValue.IsEmpty()) + return L""; + v8::Local context = pIsolate->GetCurrentContext(); + v8::String::Utf8Value s(pValue->ToString(context).ToLocalChecked()); + return CFX_WideString::FromUTF8(CFX_ByteStringC(*s, s.length())); +} + +v8::Local FXJS_ToArray(v8::Isolate* pIsolate, + v8::Local pValue) { + if (pValue.IsEmpty()) + return v8::Local(); + v8::Local context = pIsolate->GetCurrentContext(); + return v8::Local::Cast(pValue->ToObject(context).ToLocalChecked()); +} + +void FXJS_ValueCopy(v8::Local& pTo, v8::Local pFrom) { + pTo = pFrom; +} diff --git a/fxjs/fxjs_v8_embeddertest.cpp b/fxjs/fxjs_v8_embeddertest.cpp new file mode 100644 index 0000000000..b33ddca32d --- /dev/null +++ b/fxjs/fxjs_v8_embeddertest.cpp @@ -0,0 +1,83 @@ +// Copyright 2015 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. + +#include "testing/gtest/include/gtest/gtest.h" +#include "testing/js_embedder_test.h" + +namespace { + +const double kExpected0 = 6.0; +const double kExpected1 = 7.0; +const double kExpected2 = 8.0; + +const wchar_t kScript0[] = L"fred = 6"; +const wchar_t kScript1[] = L"fred = 7"; +const wchar_t kScript2[] = L"fred = 8"; + +} // namespace + +class FXJSV8EmbedderTest : public JSEmbedderTest { + public: + void ExecuteInCurrentContext(const CFX_WideString& script) { + FXJSErr error; + int sts = FXJS_Execute(isolate(), script, &error); + EXPECT_EQ(0, sts); + } + void CheckAssignmentInCurrentContext(double expected) { + v8::Local This = FXJS_GetThisObj(isolate()); + v8::Local fred = FXJS_GetObjectElement(isolate(), This, L"fred"); + EXPECT_TRUE(fred->IsNumber()); + EXPECT_EQ(expected, fred->ToNumber(isolate()->GetCurrentContext()) + .ToLocalChecked() + ->Value()); + } +}; + +TEST_F(FXJSV8EmbedderTest, Getters) { + v8::Isolate::Scope isolate_scope(isolate()); + v8::HandleScope handle_scope(isolate()); + v8::Context::Scope context_scope(GetV8Context()); + + ExecuteInCurrentContext(CFX_WideString(kScript1)); + CheckAssignmentInCurrentContext(kExpected1); +} + +TEST_F(FXJSV8EmbedderTest, MultipleRutimes) { + v8::Isolate::Scope isolate_scope(isolate()); + v8::HandleScope handle_scope(isolate()); + + v8::Global global_context1; + std::vector*> static_objects1; + FXJS_InitializeRuntime(isolate(), nullptr, &global_context1, + &static_objects1); + + v8::Global global_context2; + std::vector*> static_objects2; + FXJS_InitializeRuntime(isolate(), nullptr, &global_context2, + &static_objects2); + + v8::Context::Scope context_scope(GetV8Context()); + ExecuteInCurrentContext(CFX_WideString(kScript0)); + CheckAssignmentInCurrentContext(kExpected0); + + { + v8::Local context1 = + v8::Local::New(isolate(), global_context1); + v8::Context::Scope context_scope1(context1); + ExecuteInCurrentContext(CFX_WideString(kScript1)); + CheckAssignmentInCurrentContext(kExpected1); + } + FXJS_ReleaseRuntime(isolate(), &global_context1, &static_objects1); + + { + v8::Local context2 = + v8::Local::New(isolate(), global_context2); + v8::Context::Scope context_scope2(context2); + ExecuteInCurrentContext(CFX_WideString(kScript2)); + CheckAssignmentInCurrentContext(kExpected2); + } + FXJS_ReleaseRuntime(isolate(), &global_context2, &static_objects2); + + CheckAssignmentInCurrentContext(kExpected0); +} diff --git a/fxjs/include/fxjs_v8.h b/fxjs/include/fxjs_v8.h new file mode 100644 index 0000000000..465feef5e8 --- /dev/null +++ b/fxjs/include/fxjs_v8.h @@ -0,0 +1,290 @@ +// 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 + +// FXJS_V8 is a layer that makes it easier to define native objects in V8, but +// has no knowledge of PDF-specific native objects. It could in theory be used +// to implement other sets of native objects. + +// PDFium code should include this file rather than including V8 headers +// directly. + +#ifndef FXJS_INCLUDE_FXJS_V8_H_ +#define FXJS_INCLUDE_FXJS_V8_H_ + +#include +#include + +#include + +#include "core/fxcrt/include/fx_string.h" + +class CFXJS_ObjDefinition; + +// FXJS_V8 places no restrictions on these two classes; it merely passes them +// on to caller-provided methods. +class IJS_Context; // A description of the event that caused JS execution. +class IJS_Runtime; // A native runtime, typically owns the v8::Context. + +#ifdef PDF_ENABLE_XFA +// FXJS_V8 places no interpreation on this calass; it merely passes it +// along to XFA. +class CFXJSE_RuntimeData; +#endif // PDF_ENABLE_XFA + +enum FXJSOBJTYPE { + FXJSOBJTYPE_DYNAMIC = 0, // Created by native method and returned to JS. + FXJSOBJTYPE_STATIC, // Created by init and hung off of global object. + FXJSOBJTYPE_GLOBAL, // The global object itself (may only appear once). +}; + +struct FXJSErr { + const wchar_t* message; + const wchar_t* srcline; + unsigned linnum; +}; + +// Global weak map to save dynamic objects. +class V8TemplateMapTraits : public v8::StdMapTraits { + public: + typedef v8::GlobalValueMap MapType; + typedef void WeakCallbackDataType; + + static WeakCallbackDataType* WeakCallbackParameter( + MapType* map, + void* key, + const v8::Local& value) { + return key; + } + static MapType* MapFromWeakCallbackInfo( + const v8::WeakCallbackInfo&); + + static void* KeyFromWeakCallbackInfo( + const v8::WeakCallbackInfo& data) { + return data.GetParameter(); + } + static const v8::PersistentContainerCallbackType kCallbackType = + v8::kWeakWithInternalFields; + static void DisposeWeak( + const v8::WeakCallbackInfo& data) {} + static void OnWeakCallback( + const v8::WeakCallbackInfo& data) {} + static void Dispose(v8::Isolate* isolate, + v8::Global value, + void* key); + static void DisposeCallbackData(WeakCallbackDataType* callbackData) {} +}; + +class V8TemplateMap { + public: + typedef v8::GlobalValueMap MapType; + + explicit V8TemplateMap(v8::Isolate* isolate); + ~V8TemplateMap(); + + void set(void* key, v8::Local handle); + + friend class V8TemplateMapTraits; + + private: + MapType m_map; +}; + +class FXJS_PerIsolateData { + public: + ~FXJS_PerIsolateData(); + + static void SetUp(v8::Isolate* pIsolate); + static FXJS_PerIsolateData* Get(v8::Isolate* pIsolate); + + void CreateDynamicObjsMap(v8::Isolate* pIsolate) { + if (!m_pDynamicObjsMap) + m_pDynamicObjsMap = new V8TemplateMap(pIsolate); + } + void ReleaseDynamicObjsMap() { + delete m_pDynamicObjsMap; + m_pDynamicObjsMap = nullptr; + } + + std::vector m_ObjectDefnArray; +#ifdef PDF_ENABLE_XFA + CFXJSE_RuntimeData* m_pFXJSERuntimeData; +#endif // PDF_ENABLE_XFA + V8TemplateMap* m_pDynamicObjsMap; + + protected: + FXJS_PerIsolateData(); +}; + +extern const wchar_t kFXJSValueNameString[]; +extern const wchar_t kFXJSValueNameNumber[]; +extern const wchar_t kFXJSValueNameBoolean[]; +extern const wchar_t kFXJSValueNameDate[]; +extern const wchar_t kFXJSValueNameObject[]; +extern const wchar_t kFXJSValueNameFxobj[]; +extern const wchar_t kFXJSValueNameNull[]; +extern const wchar_t kFXJSValueNameUndefined[]; + +class FXJS_ArrayBufferAllocator : public v8::ArrayBuffer::Allocator { + void* Allocate(size_t length) override; + void* AllocateUninitialized(size_t length) override; + void Free(void* data, size_t length) override; +}; + +using FXJS_CONSTRUCTOR = void (*)(IJS_Runtime* cc, v8::Local obj); +using FXJS_DESTRUCTOR = void (*)(v8::Local obj); + +void FXJS_Initialize(unsigned int embedderDataSlot, v8::Isolate* pIsolate); +void FXJS_Release(); + +// Gets the global isolate set by FXJS_Initialize(), or makes a new one each +// time if there is no such isolate. Returns true if a new isolate had to be +// created. +bool FXJS_GetIsolate(v8::Isolate** pResultIsolate); + +// Get the global isolate's ref count. +size_t FXJS_GlobalIsolateRefCount(); + +// Always returns a valid, newly-created objDefnID. +int FXJS_DefineObj(v8::Isolate* pIsolate, + const wchar_t* sObjName, + FXJSOBJTYPE eObjType, + FXJS_CONSTRUCTOR pConstructor, + FXJS_DESTRUCTOR pDestructor); + +void FXJS_DefineObjMethod(v8::Isolate* pIsolate, + int nObjDefnID, + const wchar_t* sMethodName, + v8::FunctionCallback pMethodCall); +void FXJS_DefineObjProperty(v8::Isolate* pIsolate, + int nObjDefnID, + const wchar_t* sPropName, + v8::AccessorGetterCallback pPropGet, + v8::AccessorSetterCallback pPropPut); +void FXJS_DefineObjAllProperties(v8::Isolate* pIsolate, + int nObjDefnID, + v8::NamedPropertyQueryCallback pPropQurey, + v8::NamedPropertyGetterCallback pPropGet, + v8::NamedPropertySetterCallback pPropPut, + v8::NamedPropertyDeleterCallback pPropDel); +void FXJS_DefineObjConst(v8::Isolate* pIsolate, + int nObjDefnID, + const wchar_t* sConstName, + v8::Local pDefault); +void FXJS_DefineGlobalMethod(v8::Isolate* pIsolate, + const wchar_t* sMethodName, + v8::FunctionCallback pMethodCall); +void FXJS_DefineGlobalConst(v8::Isolate* pIsolate, + const wchar_t* sConstName, + v8::FunctionCallback pConstGetter); + +// Called after FXJS_Define* calls made. +void FXJS_InitializeRuntime( + v8::Isolate* pIsolate, + IJS_Runtime* pIRuntime, + v8::Global* pV8PersistentContext, + std::vector*>* pStaticObjects); +void FXJS_ReleaseRuntime(v8::Isolate* pIsolate, + v8::Global* pV8PersistentContext, + std::vector*>* pStaticObjects); +IJS_Runtime* FXJS_GetRuntimeFromIsolate(v8::Isolate* pIsolate); + +#ifdef PDF_ENABLE_XFA +// Called as part of FXJS_InitializeRuntime, exposed so PDF can make its +// own contexts compatible with XFA or vice versa. +void FXJS_SetRuntimeForV8Context(v8::Local v8Context, + IJS_Runtime* pIRuntime); +#endif // PDF_ENABLE_XFA + +// Called after FXJS_InitializeRuntime call made. +int FXJS_Execute(v8::Isolate* pIsolate, + const CFX_WideString& script, + FXJSErr* perror); + +v8::Local FXJS_NewFxDynamicObj(v8::Isolate* pIsolate, + IJS_Runtime* pJSContext, + int nObjDefnID, + bool bStatic = false); +v8::Local FXJS_GetThisObj(v8::Isolate* pIsolate); +int FXJS_GetObjDefnID(v8::Local pObj); +const wchar_t* FXJS_GetTypeof(v8::Local pObj); + +void FXJS_SetPrivate(v8::Isolate* pIsolate, + v8::Local pObj, + void* p); +void* FXJS_GetPrivate(v8::Isolate* pIsolate, v8::Local pObj); +void FXJS_FreePrivate(void* p); +void FXJS_FreePrivate(v8::Local pObj); +void FXJS_Error(v8::Isolate* isolate, const CFX_WideString& message); + +v8::Local FXJS_WSToJSString(v8::Isolate* pIsolate, + const CFX_WideString& wsPropertyName); +v8::Local FXJS_GetObjectElement(v8::Isolate* pIsolate, + v8::Local pObj, + const CFX_WideString& PropertyName); +v8::Local FXJS_GetObjectElementNames(v8::Isolate* pIsolate, + v8::Local pObj); +v8::Local FXJS_GetArrayElement(v8::Isolate* pIsolate, + v8::Local pArray, + unsigned index); + +unsigned FXJS_GetArrayLength(v8::Local pArray); +void FXJS_PutObjectString(v8::Isolate* pIsolate, + v8::Local pObj, + const CFX_WideString& wsPropertyName, + const CFX_WideString& wsValue); +void FXJS_PutObjectNumber(v8::Isolate* pIsolate, + v8::Local pObj, + const CFX_WideString& PropertyName, + int nValue); +void FXJS_PutObjectNumber(v8::Isolate* pIsolate, + v8::Local pObj, + const CFX_WideString& PropertyName, + float fValue); +void FXJS_PutObjectNumber(v8::Isolate* pIsolate, + v8::Local pObj, + const CFX_WideString& PropertyName, + double dValue); +void FXJS_PutObjectBoolean(v8::Isolate* pIsolate, + v8::Local pObj, + const CFX_WideString& PropertyName, + bool bValue); +void FXJS_PutObjectObject(v8::Isolate* pIsolate, + v8::Local pObj, + const CFX_WideString& PropertyName, + v8::Local pPut); +void FXJS_PutObjectNull(v8::Isolate* pIsolate, + v8::Local pObj, + const CFX_WideString& PropertyName); +unsigned FXJS_PutArrayElement(v8::Isolate* pIsolate, + v8::Local pArray, + unsigned index, + v8::Local pValue); + +v8::Local FXJS_NewArray(v8::Isolate* pIsolate); +v8::Local FXJS_NewNumber(v8::Isolate* pIsolate, int number); +v8::Local FXJS_NewNumber(v8::Isolate* pIsolate, double number); +v8::Local FXJS_NewNumber(v8::Isolate* pIsolate, float number); +v8::Local FXJS_NewBoolean(v8::Isolate* pIsolate, bool b); +v8::Local FXJS_NewObject(v8::Isolate* pIsolate, + v8::Local pObj); +v8::Local FXJS_NewObject2(v8::Isolate* pIsolate, + v8::Local pObj); +v8::Local FXJS_NewString(v8::Isolate* pIsolate, const wchar_t* str); +v8::Local FXJS_NewNull(); +v8::Local FXJS_NewDate(v8::Isolate* pIsolate, double d); + +int FXJS_ToInt32(v8::Isolate* pIsolate, v8::Local pValue); +bool FXJS_ToBoolean(v8::Isolate* pIsolate, v8::Local pValue); +double FXJS_ToNumber(v8::Isolate* pIsolate, v8::Local pValue); +v8::Local FXJS_ToObject(v8::Isolate* pIsolate, + v8::Local pValue); +CFX_WideString FXJS_ToString(v8::Isolate* pIsolate, + v8::Local pValue); +v8::Local FXJS_ToArray(v8::Isolate* pIsolate, + v8::Local pValue); +void FXJS_ValueCopy(v8::Local& pTo, v8::Local pFrom); + +#endif // FXJS_INCLUDE_FXJS_V8_H_ diff --git a/pdfium.gyp b/pdfium.gyp index 76a22a9f8a..79ff0886d5 100644 --- a/pdfium.gyp +++ b/pdfium.gyp @@ -779,15 +779,8 @@ ], 'conditions': [ ['pdf_enable_v8==1', { - 'include_dirs': [ - '<(DEPTH)/v8', - '<(DEPTH)/v8/include', - ], 'dependencies': [ - '<(DEPTH)/v8/src/v8.gyp:v8', - ], - 'export_dependent_settings': [ - '<(DEPTH)/v8/src/v8.gyp:v8', + ':fxjs' ], 'sources!': [ 'fpdfsdk/javascript/JS_Runtime_Stub.cpp', @@ -835,8 +828,6 @@ 'fpdfsdk/javascript/resource.h', 'fpdfsdk/javascript/util.cpp', 'fpdfsdk/javascript/util.h', - 'fpdfsdk/jsapi/include/fxjs_v8.h', - 'fpdfsdk/jsapi/fxjs_v8.cpp', ], }], ], @@ -977,7 +968,7 @@ ], 'sources': [ 'fpdfsdk/javascript/public_methods_embeddertest.cpp', - 'fpdfsdk/jsapi/fxjs_v8_embeddertest.cpp', + 'fxjs/fxjs_v8_embeddertest.cpp', 'testing/js_embedder_test.cpp', 'testing/js_embedder_test.h', ], @@ -1013,12 +1004,57 @@ }, ], 'conditions': [ + ['pdf_enable_v8==1', { + 'targets': [ + { + "target_name": "fxjs", + "type": "static_library", + 'include_dirs': [ + # This is implicit in GN. + '<(DEPTH)', + '.', + '<(DEPTH)/v8', + '<(DEPTH)/v8/include', + ], + 'dependencies': [ + '<(DEPTH)/v8/src/v8.gyp:v8', + ], + 'export_dependent_settings': [ + '<(DEPTH)/v8/src/v8.gyp:v8', + ], + "sources": [ + "fxjs/fxjs_v8.cpp", + "fxjs/include/fxjs_v8.h", + ], + "conditions": [ + ['pdf_enable_xfa==1', { + 'sources': [ + "fxjs/cfxjse_arguments.cpp", + "fxjs/cfxjse_class.cpp", + "fxjs/cfxjse_context.cpp", + "fxjs/cfxjse_isolatetracker.cpp", + "fxjs/cfxjse_isolatetracker.h", + "fxjs/cfxjse_runtimedata.cpp", + "fxjs/cfxjse_runtimedata.h", + "fxjs/cfxjse_value.cpp", + "fxjs/include/cfxjse_arguments.h", + "fxjs/include/cfxjse_class.h", + "fxjs/include/cfxjse_context.h", + "fxjs/include/cfxjse_value.h", + "fxjs/include/fxjse.h", + ] + }], + ], + }, + ] + }], ['pdf_enable_xfa==1', { 'targets': [ { 'target_name': 'fpdfxfa', 'type': 'static_library', 'dependencies': [ + 'fxjs', 'javascript', 'xfa.gyp:xfa', ], diff --git a/testing/DEPS b/testing/DEPS index 44e064607f..babefb8593 100644 --- a/testing/DEPS +++ b/testing/DEPS @@ -3,7 +3,7 @@ include_rules = [ '+core/fxcodec', '+core/fxcrt/include', '+core/fxge/include', - '+fpdfsdk/jsapi/include', + '+fxjs/include', '+public', '+v8', '+xfa/fde', diff --git a/testing/js_embedder_test.h b/testing/js_embedder_test.h index 5583e7e388..b2bd5a87b1 100644 --- a/testing/js_embedder_test.h +++ b/testing/js_embedder_test.h @@ -8,7 +8,7 @@ #include #include -#include "fpdfsdk/jsapi/include/fxjs_v8.h" +#include "fxjs/include/fxjs_v8.h" #include "testing/embedder_test.h" class JSEmbedderTest : public EmbedderTest { diff --git a/xfa.gyp b/xfa.gyp index d8c165ef88..e21f905ed5 100644 --- a/xfa.gyp +++ b/xfa.gyp @@ -15,38 +15,6 @@ ], }, "targets":[ - { - "target_name": "fxjs", - "type": "static_library", - 'include_dirs': [ - # This is implicit in GN. - '<(DEPTH)', - '.', - '<(DEPTH)/v8', - '<(DEPTH)/v8/include', - ], - 'dependencies': [ - '<(DEPTH)/v8/src/v8.gyp:v8', - ], - 'export_dependent_settings': [ - '<(DEPTH)/v8/src/v8.gyp:v8', - ], - "sources": [ - "fxjs/cfxjse_arguments.cpp", - "fxjs/cfxjse_class.cpp", - "fxjs/cfxjse_context.cpp", - "fxjs/cfxjse_isolatetracker.cpp", - "fxjs/cfxjse_isolatetracker.h", - "fxjs/cfxjse_runtimedata.cpp", - "fxjs/cfxjse_runtimedata.h", - "fxjs/cfxjse_value.cpp", - "fxjs/include/cfxjse_arguments.h", - "fxjs/include/cfxjse_class.h", - "fxjs/include/cfxjse_context.h", - "fxjs/include/cfxjse_value.h", - "fxjs/include/fxjse.h", - ] - }, { "target_name":"xfa", "type":"static_library", @@ -60,9 +28,6 @@ 'defines' : [ 'FT2_BUILD_LIBRARY', ], - 'dependencies': [ - ':fxjs', - ], "sources":[ "xfa/fde/cfde_path.cpp", "xfa/fde/cfde_path.h", -- cgit v1.2.3