From 5110c4743751145c4ae1934cd1d83bc6c55bb43f Mon Sep 17 00:00:00 2001 From: John Abd-El-Malek Date: Sat, 17 May 2014 22:33:34 -0700 Subject: Initial commit. --- fpdfsdk/src/jsapi/fxjs_v8.cpp | 1043 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1043 insertions(+) create mode 100644 fpdfsdk/src/jsapi/fxjs_v8.cpp (limited to 'fpdfsdk/src/jsapi') diff --git a/fpdfsdk/src/jsapi/fxjs_v8.cpp b/fpdfsdk/src/jsapi/fxjs_v8.cpp new file mode 100644 index 0000000000..bbf9eec67d --- /dev/null +++ b/fpdfsdk/src/jsapi/fxjs_v8.cpp @@ -0,0 +1,1043 @@ +// 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 "../../../core/include/fxcrt/fx_basic.h" +#include "../../../core/include/fxcrt/fx_ext.h" +#include "../../include/jsapi/fxjs_v8.h" +#include "../../include/fsdk_define.h" +#include "time.h" +#include +#include + +#define VALUE_NAME_STRING L"string" +#define VALUE_NAME_NUMBER L"number" +#define VALUE_NAME_BOOLEAN L"boolean" +#define VALUE_NAME_DATE L"date" +#define VALUE_NAME_OBJECT L"object" +#define VALUE_NAME_FXOBJ L"fxobj" +#define VALUE_NAME_NULL L"null" +#define VALUE_NAME_UNDEFINED L"undefined" + +static FX_DWORD g_nan[2] = {0,0x7FF80000 }; +double g_NaN = (*(double *)g_nan); + + +class CJS_PrivateData: public CFX_Object +{ +public: + CJS_PrivateData():ObjDefID(-1), pPrivate(NULL) {} + int ObjDefID; + FX_LPVOID pPrivate; +}; + + +class CJS_ObjDefintion: public CFX_Object +{ +public: + CJS_ObjDefintion(v8::Isolate* isolate, const wchar_t* sObjName, FXJSOBJTYPE eObjType, LP_CONSTRUCTOR pConstructor, LP_DESTRUCTOR pDestructor, unsigned bApplyNew): + objName(sObjName), objType(eObjType), m_pConstructor(pConstructor), m_pDestructor(pDestructor),m_bApplyNew(bApplyNew),m_bSetAsGlobalObject(FALSE) + { + v8::Isolate::Scope isolate_scope(isolate); + HandleScope handle_scope(isolate); + + v8::Handle objTemplate = ObjectTemplate::New(isolate); + objTemplate->SetInternalFieldCount(1); + m_objTemplate.Reset(isolate, objTemplate); + + //Document as the global object. + if(FXSYS_wcscmp(sObjName, L"Document") == 0) + { + m_bSetAsGlobalObject = TRUE; + } + + } + ~CJS_ObjDefintion() + { + m_objTemplate.Reset(); + m_StaticObj.Reset(); + } +public: + const wchar_t* objName; + FXJSOBJTYPE objType; + LP_CONSTRUCTOR m_pConstructor; + LP_DESTRUCTOR m_pDestructor; + unsigned m_bApplyNew; + FX_BOOL m_bSetAsGlobalObject; + + v8::Persistent m_objTemplate; + v8::Persistent m_StaticObj; +}; + +int JS_DefineObj(IJS_Runtime* pJSRuntime, const wchar_t* sObjName, FXJSOBJTYPE eObjType, LP_CONSTRUCTOR pConstructor, LP_DESTRUCTOR pDestructor, unsigned bApplyNew) +{ + v8::Isolate* isolate = (v8::Isolate*)pJSRuntime; + v8::Isolate::Scope isolate_scope(isolate); + HandleScope handle_scope(isolate); + CFX_PtrArray* pArray = (CFX_PtrArray*)isolate->GetData(0); + if(!pArray) + { + pArray = FX_NEW CFX_PtrArray(); + isolate->SetData(0, pArray); + } + CJS_ObjDefintion* pObjDef = FX_NEW CJS_ObjDefintion(isolate, sObjName, eObjType, pConstructor, pDestructor, bApplyNew); + pArray->Add(pObjDef); + return pArray->GetSize()-1; +} + +int JS_DefineObjMethod(IJS_Runtime* pJSRuntime, int nObjDefnID, const wchar_t* sMethodName, FunctionCallback pMethodCall, unsigned nParamNum) +{ + v8::Isolate* isolate = (v8::Isolate*)pJSRuntime; + v8::Isolate::Scope isolate_scope(isolate); + HandleScope handle_scope(isolate); + + CFX_WideString ws = CFX_WideString((FX_LPCWSTR)sMethodName); + CFX_ByteString bsMethodName = ws.UTF8Encode(); + + CFX_PtrArray* pArray = (CFX_PtrArray*)isolate->GetData(0); + if(!pArray) return 0; + + if(nObjDefnID<0 || nObjDefnID>= pArray->GetSize()) return 0; + CJS_ObjDefintion* pObjDef = (CJS_ObjDefintion*)pArray->GetAt(nObjDefnID); + v8::Local objTemp = v8::Local::New(isolate, pObjDef->m_objTemplate); + objTemp->Set(v8::String::NewFromUtf8(isolate, FX_LPCSTR(bsMethodName)), FunctionTemplate::New(isolate, pMethodCall), ReadOnly); + pObjDef->m_objTemplate.Reset(isolate,objTemp); + return 0; +} + +int JS_DefineObjProperty(IJS_Runtime* pJSRuntime, int nObjDefnID, const wchar_t* sPropName, AccessorGetterCallback pPropGet, AccessorSetterCallback pPropPut) +{ + v8::Isolate* isolate = (v8::Isolate*)pJSRuntime; + v8::Isolate::Scope isolate_scope(isolate); + HandleScope handle_scope(isolate); + + CFX_WideString ws = CFX_WideString((FX_LPCWSTR)sPropName); + CFX_ByteString bsPropertyName = ws.UTF8Encode(); + + CFX_PtrArray* pArray = (CFX_PtrArray*)isolate->GetData(0); + if(!pArray) return 0; + + if(nObjDefnID<0 || nObjDefnID>= pArray->GetSize()) return 0; + CJS_ObjDefintion* pObjDef = (CJS_ObjDefintion*)pArray->GetAt(nObjDefnID); + v8::Local objTemp = v8::Local::New(isolate, pObjDef->m_objTemplate); + objTemp->SetAccessor(v8::String::NewFromUtf8(isolate, FX_LPCSTR(bsPropertyName)), pPropGet, pPropPut); + pObjDef->m_objTemplate.Reset(isolate,objTemp); + return 0; +} + +int JS_DefineObjAllProperties(IJS_Runtime* pJSRuntime, int nObjDefnID, NamedPropertyQueryCallback pPropQurey, NamedPropertyGetterCallback pPropGet, NamedPropertySetterCallback pPropPut, NamedPropertyDeleterCallback pPropDel) +{ + v8::Isolate* isolate = (v8::Isolate*)pJSRuntime; + v8::Isolate::Scope isolate_scope(isolate); + HandleScope handle_scope(isolate); + + CFX_PtrArray* pArray = (CFX_PtrArray*)isolate->GetData(0); + if(!pArray) return 0; + + if(nObjDefnID<0 || nObjDefnID>= pArray->GetSize()) return 0; + CJS_ObjDefintion* pObjDef = (CJS_ObjDefintion*)pArray->GetAt(nObjDefnID); + v8::Local objTemp = v8::Local::New(isolate, pObjDef->m_objTemplate); + objTemp->SetNamedPropertyHandler(pPropGet, pPropPut, pPropQurey, pPropDel); + pObjDef->m_objTemplate.Reset(isolate,objTemp); + return 0; +} + +int JS_DefineObjConst(IJS_Runtime* pJSRuntime, int nObjDefnID, const wchar_t* sConstName, v8::Handle pDefault) +{ + v8::Isolate* isolate = (v8::Isolate*)pJSRuntime; + v8::Isolate::Scope isolate_scope(isolate); + HandleScope handle_scope(isolate); + + CFX_PtrArray* pArray = (CFX_PtrArray*)isolate->GetData(0); + if(!pArray) return 0; + + CFX_WideString ws = CFX_WideString((FX_LPCWSTR)sConstName); + CFX_ByteString bsConstName = ws.UTF8Encode(); + + if(nObjDefnID<0 || nObjDefnID>= pArray->GetSize()) return 0; + CJS_ObjDefintion* pObjDef = (CJS_ObjDefintion*)pArray->GetAt(nObjDefnID); + v8::Local objTemp = v8::Local::New(isolate, pObjDef->m_objTemplate); + objTemp->Set(isolate, FX_LPCSTR(bsConstName), pDefault); + pObjDef->m_objTemplate.Reset(isolate,objTemp); + return 0; +} + +static v8::Persistent& _getGlobalObjectTemplate(IJS_Runtime* pJSRuntime) +{ + v8::Isolate* isolate = (v8::Isolate*)pJSRuntime; + v8::Isolate::Scope isolate_scope(isolate); + HandleScope handle_scope(isolate); + + CFX_PtrArray* pArray = (CFX_PtrArray*)isolate->GetData(0); + ASSERT(pArray != NULL); + for(int i=0; iGetSize(); i++) + { + CJS_ObjDefintion* pObjDef = (CJS_ObjDefintion*)pArray->GetAt(i); + if(pObjDef->m_bSetAsGlobalObject) + return pObjDef->m_objTemplate; + } + static v8::Persistent gloabalObjectTemplate; + return gloabalObjectTemplate; +} + +int JS_DefineGlobalMethod(IJS_Runtime* pJSRuntime, const wchar_t* sMethodName, FunctionCallback pMethodCall, unsigned nParamNum) +{ + v8::Isolate* isolate = (v8::Isolate*)pJSRuntime; + v8::Isolate::Scope isolate_scope(isolate); + HandleScope handle_scope(isolate); + + CFX_WideString ws = CFX_WideString((FX_LPCWSTR)sMethodName); + CFX_ByteString bsMethodName = ws.UTF8Encode(); + + v8::Local funTempl = FunctionTemplate::New(isolate, pMethodCall); + v8::Local objTemp; + + v8::Persistent& globalObjTemp = _getGlobalObjectTemplate(pJSRuntime); + if(globalObjTemp.IsEmpty()) + objTemp = ObjectTemplate::New(isolate); + else + objTemp = v8::Local::New(isolate, globalObjTemp); + objTemp->Set(v8::String::NewFromUtf8(isolate, FX_LPCSTR(bsMethodName)), funTempl, ReadOnly); + + globalObjTemp.Reset(isolate,objTemp); + + return 0; +} + +int JS_DefineGlobalConst(IJS_Runtime* pJSRuntime, const wchar_t* sConstName, v8::Handle pDefault) +{ + v8::Isolate* isolate = (v8::Isolate*)pJSRuntime; + v8::Isolate::Scope isolate_scope(isolate); + HandleScope handle_scope(isolate); + + CFX_WideString ws = CFX_WideString((FX_LPCWSTR)sConstName); + CFX_ByteString bsConst= ws.UTF8Encode(); + + v8::Local objTemp; + + v8::Persistent& globalObjTemp = _getGlobalObjectTemplate(pJSRuntime); + if(globalObjTemp.IsEmpty()) + objTemp = ObjectTemplate::New(isolate); + else + objTemp = v8::Local::New(isolate, globalObjTemp); + objTemp->Set(v8::String::NewFromUtf8(isolate, FX_LPCSTR(bsConst)), pDefault, ReadOnly); + + globalObjTemp.Reset(isolate,objTemp); + + return 0; +} + + +void JS_InitialRuntime(IJS_Runtime* pJSRuntime,IFXJS_Runtime* pFXRuntime, IFXJS_Context* context, v8::Persistent& v8PersistentContext) +{ + v8::Isolate* isolate = (v8::Isolate*)pJSRuntime; + v8::Isolate::Scope isolate_scope(isolate); + HandleScope handle_scope(isolate); + + v8::Persistent& globalObjTemp = _getGlobalObjectTemplate(pJSRuntime); + v8::Handle v8Context = v8::Context::New(isolate, NULL, v8::Local::New(isolate, globalObjTemp)); + v8::Context::Scope context_scope(v8Context); + + v8::Handle ptr = External::New(isolate, pFXRuntime); + v8Context->SetEmbedderData(1, ptr); + + CFX_PtrArray* pArray = (CFX_PtrArray*)isolate->GetData(0); + if(!pArray) return; + + for(int i=0; iGetSize(); i++) + { + CJS_ObjDefintion* pObjDef = (CJS_ObjDefintion*)pArray->GetAt(i); + CFX_WideString ws = CFX_WideString(pObjDef->objName); + CFX_ByteString bs = ws.UTF8Encode(); + v8::Handle objName = v8::String::NewFromUtf8(isolate,(FX_LPCSTR)bs, v8::String::kNormalString, bs.GetLength()); + + + if(pObjDef->objType == JS_DYNAMIC) + { + //Document is set as global object, need to construct it first. + if(ws.Equal(L"Document")) + { + + CJS_PrivateData* pPrivateData = FX_NEW CJS_PrivateData; + pPrivateData->ObjDefID = i; + v8::Handle ptr = External::New(isolate, pPrivateData); + + v8Context->Global()->GetPrototype()->ToObject()->SetInternalField(0, ptr); + + if(pObjDef->m_pConstructor) + pObjDef->m_pConstructor(context, v8Context->Global()->GetPrototype()->ToObject(), v8Context->Global()->GetPrototype()->ToObject()); + } + } + else + { + v8::Handle obj = JS_NewFxDynamicObj(pJSRuntime, context, i); + v8Context->Global()->Set(objName, obj); + pObjDef->m_StaticObj.Reset(isolate, obj); + } + } + v8PersistentContext.Reset(isolate, v8Context); +} + +void JS_ReleaseRuntime(IJS_Runtime* pJSRuntime, v8::Persistent& v8PersistentContext) +{ + v8::Isolate* isolate = (v8::Isolate*)pJSRuntime; + v8::Isolate::Scope isolate_scope(isolate); + HandleScope handle_scope(isolate); + v8::Local context = v8::Local::New(isolate, v8PersistentContext); + v8::Context::Scope context_scope(context); + + CFX_PtrArray* pArray = (CFX_PtrArray*)isolate->GetData(0); + if(!pArray) return ; + + for(int i=0; iGetSize(); i++) + { + CJS_ObjDefintion* pObjDef = (CJS_ObjDefintion*)pArray->GetAt(i); + if(!pObjDef->m_StaticObj.IsEmpty()) + { + v8::Local pObj = v8::Local::New(isolate, pObjDef->m_StaticObj); + if(pObjDef->m_pDestructor) + pObjDef->m_pDestructor(pObj); + JS_FreePrivate(pObj); + } + delete pObjDef; + } + delete pArray; + isolate->SetData(0,NULL); +} + +void JS_Initial() +{ +#ifndef FOXIT_CHROME_BUILD + v8::V8::InitializeICU(); +#endif +} +void JS_Release() +{ + +} +int JS_Parse(IJS_Runtime* pJSRuntime, IFXJS_Context* pJSContext, const wchar_t* script, long length, FXJSErr* perror) +{ + v8::Isolate* isolate = (v8::Isolate*)pJSRuntime; + v8::Isolate::Scope isolate_scope(isolate); + TryCatch try_catch; + + CFX_WideString wsScript(script); + CFX_ByteString bsScript = wsScript.UTF8Encode(); + + + v8::Handle