diff options
Diffstat (limited to 'xfa/fxjse/class.cpp')
-rw-r--r-- | xfa/fxjse/class.cpp | 348 |
1 files changed, 348 insertions, 0 deletions
diff --git a/xfa/fxjse/class.cpp b/xfa/fxjse/class.cpp new file mode 100644 index 0000000000..e87fbbfaf9 --- /dev/null +++ b/xfa/fxjse/class.cpp @@ -0,0 +1,348 @@ +// 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 "xfa/fxjse/class.h" + +#include "xfa/fxjse/context.h" +#include "xfa/fxjse/scope_inline.h" +#include "xfa/fxjse/util_inline.h" +#include "xfa/fxjse/value.h" + +static void FXJSE_V8ConstructorCallback_Wrapper( + const v8::FunctionCallbackInfo<v8::Value>& info); +static void FXJSE_V8FunctionCallback_Wrapper( + const v8::FunctionCallbackInfo<v8::Value>& info); +static void FXJSE_V8GetterCallback_Wrapper( + v8::Local<v8::String> property, + const v8::PropertyCallbackInfo<v8::Value>& info); +static void FXJSE_V8SetterCallback_Wrapper( + v8::Local<v8::String> property, + v8::Local<v8::Value> value, + const v8::PropertyCallbackInfo<void>& info); + +void FXJSE_DefineFunctions(FXJSE_HCONTEXT hContext, + const FXJSE_FUNCTION* lpFunctions, + int nNum) { + CFXJSE_Context* lpContext = reinterpret_cast<CFXJSE_Context*>(hContext); + ASSERT(lpContext); + CFXJSE_ScopeUtil_IsolateHandleContext scope(lpContext); + v8::Isolate* pIsolate = lpContext->GetRuntime(); + v8::Local<v8::Object> hGlobalObject = + FXJSE_GetGlobalObjectFromContext(scope.GetLocalContext()); + for (int32_t i = 0; i < nNum; i++) { + v8::Maybe<bool> maybe_success = hGlobalObject->DefineOwnProperty( + scope.GetLocalContext(), + v8::String::NewFromUtf8(pIsolate, lpFunctions[i].name), + v8::Function::New( + pIsolate, FXJSE_V8FunctionCallback_Wrapper, + v8::External::New(pIsolate, + const_cast<FXJSE_FUNCTION*>(lpFunctions + i))), + static_cast<v8::PropertyAttribute>(v8::ReadOnly | v8::DontDelete)); + if (!maybe_success.FromMaybe(false)) + return; + } +} + +FXJSE_HCLASS FXJSE_DefineClass(FXJSE_HCONTEXT hContext, + const FXJSE_CLASS* lpClass) { + CFXJSE_Context* lpContext = reinterpret_cast<CFXJSE_Context*>(hContext); + ASSERT(lpContext); + return reinterpret_cast<FXJSE_HCLASS>( + CFXJSE_Class::Create(lpContext, lpClass, FALSE)); +} + +FXJSE_HCLASS FXJSE_GetClass(FXJSE_HCONTEXT hContext, + const CFX_ByteStringC& szName) { + return reinterpret_cast<FXJSE_HCLASS>(CFXJSE_Class::GetClassFromContext( + reinterpret_cast<CFXJSE_Context*>(hContext), szName)); +} + +static void FXJSE_V8FunctionCallback_Wrapper( + const v8::FunctionCallbackInfo<v8::Value>& info) { + const FXJSE_FUNCTION* lpFunctionInfo = + static_cast<FXJSE_FUNCTION*>(info.Data().As<v8::External>()->Value()); + if (!lpFunctionInfo) { + return; + } + CFX_ByteStringC szFunctionName(lpFunctionInfo->name); + CFXJSE_Value* lpThisValue = CFXJSE_Value::Create(info.GetIsolate()); + lpThisValue->ForceSetValue(info.This()); + CFXJSE_Value* lpRetValue = CFXJSE_Value::Create(info.GetIsolate()); + CFXJSE_ArgumentsImpl impl = {&info, lpRetValue}; + lpFunctionInfo->callbackProc(reinterpret_cast<FXJSE_HOBJECT>(lpThisValue), + szFunctionName, + reinterpret_cast<CFXJSE_Arguments&>(impl)); + if (!lpRetValue->DirectGetValue().IsEmpty()) { + info.GetReturnValue().Set(lpRetValue->DirectGetValue()); + } + delete lpRetValue; + lpRetValue = NULL; + delete lpThisValue; + lpThisValue = NULL; +} + +static void FXJSE_V8ClassGlobalConstructorCallback_Wrapper( + const v8::FunctionCallbackInfo<v8::Value>& info) { + const FXJSE_CLASS* lpClassDefinition = + static_cast<FXJSE_CLASS*>(info.Data().As<v8::External>()->Value()); + if (!lpClassDefinition) { + return; + } + CFX_ByteStringC szFunctionName(lpClassDefinition->name); + CFXJSE_Value* lpThisValue = CFXJSE_Value::Create(info.GetIsolate()); + lpThisValue->ForceSetValue(info.This()); + CFXJSE_Value* lpRetValue = CFXJSE_Value::Create(info.GetIsolate()); + CFXJSE_ArgumentsImpl impl = {&info, lpRetValue}; + lpClassDefinition->constructor(reinterpret_cast<FXJSE_HOBJECT>(lpThisValue), + szFunctionName, + reinterpret_cast<CFXJSE_Arguments&>(impl)); + if (!lpRetValue->DirectGetValue().IsEmpty()) { + info.GetReturnValue().Set(lpRetValue->DirectGetValue()); + } + delete lpRetValue; + lpRetValue = NULL; + delete lpThisValue; + lpThisValue = NULL; +} + +static void FXJSE_V8GetterCallback_Wrapper( + v8::Local<v8::String> property, + const v8::PropertyCallbackInfo<v8::Value>& info) { + const FXJSE_PROPERTY* lpPropertyInfo = + static_cast<FXJSE_PROPERTY*>(info.Data().As<v8::External>()->Value()); + if (!lpPropertyInfo) { + return; + } + CFX_ByteStringC szPropertyName(lpPropertyInfo->name); + CFXJSE_Value* lpThisValue = CFXJSE_Value::Create(info.GetIsolate()); + CFXJSE_Value* lpPropValue = CFXJSE_Value::Create(info.GetIsolate()); + lpThisValue->ForceSetValue(info.This()); + lpPropertyInfo->getProc(reinterpret_cast<FXJSE_HOBJECT>(lpThisValue), + szPropertyName, + reinterpret_cast<FXJSE_HVALUE>(lpPropValue)); + info.GetReturnValue().Set(lpPropValue->DirectGetValue()); + delete lpThisValue; + lpThisValue = NULL; + delete lpPropValue; + lpPropValue = NULL; +} + +static void FXJSE_V8SetterCallback_Wrapper( + v8::Local<v8::String> property, + v8::Local<v8::Value> value, + const v8::PropertyCallbackInfo<void>& info) { + const FXJSE_PROPERTY* lpPropertyInfo = + static_cast<FXJSE_PROPERTY*>(info.Data().As<v8::External>()->Value()); + if (!lpPropertyInfo) { + return; + } + CFX_ByteStringC szPropertyName(lpPropertyInfo->name); + CFXJSE_Value* lpThisValue = CFXJSE_Value::Create(info.GetIsolate()); + CFXJSE_Value* lpPropValue = CFXJSE_Value::Create(info.GetIsolate()); + lpThisValue->ForceSetValue(info.This()); + lpPropValue->ForceSetValue(value); + lpPropertyInfo->setProc(reinterpret_cast<FXJSE_HOBJECT>(lpThisValue), + szPropertyName, + reinterpret_cast<FXJSE_HVALUE>(lpPropValue)); + delete lpThisValue; + lpThisValue = NULL; + delete lpPropValue; + lpPropValue = NULL; +} + +static void FXJSE_V8ConstructorCallback_Wrapper( + const v8::FunctionCallbackInfo<v8::Value>& info) { + const FXJSE_CLASS* lpClassDefinition = + static_cast<FXJSE_CLASS*>(info.Data().As<v8::External>()->Value()); + if (!lpClassDefinition) { + return; + } + FXSYS_assert(info.This()->InternalFieldCount()); + info.This()->SetAlignedPointerInInternalField(0, NULL); +} + +FXJSE_HRUNTIME CFXJSE_Arguments::GetRuntime() const { + const CFXJSE_ArgumentsImpl* lpArguments = + reinterpret_cast<const CFXJSE_ArgumentsImpl* const>(this); + return reinterpret_cast<FXJSE_HRUNTIME>( + lpArguments->m_pRetValue->GetIsolate()); +} + +int32_t CFXJSE_Arguments::GetLength() const { + const CFXJSE_ArgumentsImpl* lpArguments = + reinterpret_cast<const CFXJSE_ArgumentsImpl* const>(this); + return lpArguments->m_pInfo->Length(); +} + +FXJSE_HVALUE CFXJSE_Arguments::GetValue(int32_t index) const { + const CFXJSE_ArgumentsImpl* lpArguments = + reinterpret_cast<const CFXJSE_ArgumentsImpl* const>(this); + CFXJSE_Value* lpArgValue = CFXJSE_Value::Create(v8::Isolate::GetCurrent()); + ASSERT(lpArgValue); + lpArgValue->ForceSetValue((*lpArguments->m_pInfo)[index]); + return reinterpret_cast<FXJSE_HVALUE>(lpArgValue); +} + +FX_BOOL CFXJSE_Arguments::GetBoolean(int32_t index) const { + const CFXJSE_ArgumentsImpl* lpArguments = + reinterpret_cast<const CFXJSE_ArgumentsImpl* const>(this); + return (*lpArguments->m_pInfo)[index]->BooleanValue(); +} + +int32_t CFXJSE_Arguments::GetInt32(int32_t index) const { + const CFXJSE_ArgumentsImpl* lpArguments = + reinterpret_cast<const CFXJSE_ArgumentsImpl* const>(this); + return static_cast<int32_t>((*lpArguments->m_pInfo)[index]->NumberValue()); +} + +FX_FLOAT CFXJSE_Arguments::GetFloat(int32_t index) const { + const CFXJSE_ArgumentsImpl* lpArguments = + reinterpret_cast<const CFXJSE_ArgumentsImpl* const>(this); + return static_cast<FX_FLOAT>((*lpArguments->m_pInfo)[index]->NumberValue()); +} + +CFX_ByteString CFXJSE_Arguments::GetUTF8String(int32_t index) const { + const CFXJSE_ArgumentsImpl* lpArguments = + reinterpret_cast<const CFXJSE_ArgumentsImpl* const>(this); + v8::Local<v8::String> hString = (*lpArguments->m_pInfo)[index]->ToString(); + v8::String::Utf8Value szStringVal(hString); + return CFX_ByteString(*szStringVal); +} + +void* CFXJSE_Arguments::GetObject(int32_t index, FXJSE_HCLASS hClass) const { + const CFXJSE_ArgumentsImpl* lpArguments = + reinterpret_cast<const CFXJSE_ArgumentsImpl* const>(this); + v8::Local<v8::Value> hValue = (*lpArguments->m_pInfo)[index]; + ASSERT(!hValue.IsEmpty()); + if (!hValue->IsObject()) { + return NULL; + } + CFXJSE_Class* lpClass = reinterpret_cast<CFXJSE_Class*>(hClass); + return FXJSE_RetrieveObjectBinding(hValue.As<v8::Object>(), lpClass); +} + +FXJSE_HVALUE CFXJSE_Arguments::GetReturnValue() { + const CFXJSE_ArgumentsImpl* lpArguments = + reinterpret_cast<const CFXJSE_ArgumentsImpl* const>(this); + return reinterpret_cast<FXJSE_HVALUE>(lpArguments->m_pRetValue); +} +static void FXJSE_Context_GlobalObjToString( + const v8::FunctionCallbackInfo<v8::Value>& info) { + const FXJSE_CLASS* lpClass = + static_cast<FXJSE_CLASS*>(info.Data().As<v8::External>()->Value()); + if (!lpClass) { + return; + } + if (info.This() == info.Holder() && lpClass->name) { + CFX_ByteString szStringVal; + szStringVal.Format("[object %s]", lpClass->name); + info.GetReturnValue().Set(v8::String::NewFromUtf8( + info.GetIsolate(), (const FX_CHAR*)szStringVal, + v8::String::kNormalString, szStringVal.GetLength())); + } else { + v8::Local<v8::String> local_str = + info.This() + ->ObjectProtoToString(info.GetIsolate()->GetCurrentContext()) + .FromMaybe(v8::Local<v8::String>()); + info.GetReturnValue().Set(local_str); + } +} + +CFXJSE_Class* CFXJSE_Class::Create(CFXJSE_Context* lpContext, + const FXJSE_CLASS* lpClassDefinition, + FX_BOOL bIsJSGlobal) { + if (!lpContext || !lpClassDefinition) { + return NULL; + } + CFXJSE_Class* pClass = + GetClassFromContext(lpContext, lpClassDefinition->name); + if (pClass) { + return pClass; + } + v8::Isolate* pIsolate = lpContext->m_pIsolate; + pClass = new CFXJSE_Class(lpContext); + pClass->m_szClassName = lpClassDefinition->name; + pClass->m_lpClassDefinition = lpClassDefinition; + CFXJSE_ScopeUtil_IsolateHandleRootContext scope(pIsolate); + v8::Local<v8::FunctionTemplate> hFunctionTemplate = v8::FunctionTemplate::New( + pIsolate, bIsJSGlobal ? 0 : FXJSE_V8ConstructorCallback_Wrapper, + v8::External::New(pIsolate, const_cast<FXJSE_CLASS*>(lpClassDefinition))); + hFunctionTemplate->SetClassName( + v8::String::NewFromUtf8(pIsolate, lpClassDefinition->name)); + hFunctionTemplate->InstanceTemplate()->SetInternalFieldCount(1); + v8::Local<v8::ObjectTemplate> hObjectTemplate = + hFunctionTemplate->InstanceTemplate(); + SetUpNamedPropHandler(pIsolate, hObjectTemplate, lpClassDefinition); + + if (lpClassDefinition->propNum) { + for (int32_t i = 0; i < lpClassDefinition->propNum; i++) { + hObjectTemplate->SetNativeDataProperty( + v8::String::NewFromUtf8(pIsolate, + lpClassDefinition->properties[i].name), + lpClassDefinition->properties[i].getProc + ? FXJSE_V8GetterCallback_Wrapper + : NULL, + lpClassDefinition->properties[i].setProc + ? FXJSE_V8SetterCallback_Wrapper + : NULL, + v8::External::New(pIsolate, const_cast<FXJSE_PROPERTY*>( + lpClassDefinition->properties + i)), + static_cast<v8::PropertyAttribute>(v8::DontDelete)); + } + } + if (lpClassDefinition->methNum) { + for (int32_t i = 0; i < lpClassDefinition->methNum; i++) { + hObjectTemplate->Set( + v8::String::NewFromUtf8(pIsolate, lpClassDefinition->methods[i].name), + v8::FunctionTemplate::New( + pIsolate, FXJSE_V8FunctionCallback_Wrapper, + v8::External::New(pIsolate, const_cast<FXJSE_FUNCTION*>( + lpClassDefinition->methods + i))), + static_cast<v8::PropertyAttribute>(v8::ReadOnly | v8::DontDelete)); + } + } + if (lpClassDefinition->constructor) { + if (bIsJSGlobal) { + hObjectTemplate->Set( + v8::String::NewFromUtf8(pIsolate, lpClassDefinition->name), + v8::FunctionTemplate::New( + pIsolate, FXJSE_V8ClassGlobalConstructorCallback_Wrapper, + v8::External::New(pIsolate, + const_cast<FXJSE_CLASS*>(lpClassDefinition))), + static_cast<v8::PropertyAttribute>(v8::ReadOnly | v8::DontDelete)); + } else { + v8::Local<v8::Context> hLocalContext = + v8::Local<v8::Context>::New(pIsolate, lpContext->m_hContext); + FXJSE_GetGlobalObjectFromContext(hLocalContext) + ->Set(v8::String::NewFromUtf8(pIsolate, lpClassDefinition->name), + v8::Function::New( + pIsolate, FXJSE_V8ClassGlobalConstructorCallback_Wrapper, + v8::External::New(pIsolate, const_cast<FXJSE_CLASS*>( + lpClassDefinition)))); + } + } + if (bIsJSGlobal) { + hObjectTemplate->Set( + v8::String::NewFromUtf8(pIsolate, "toString"), + v8::FunctionTemplate::New( + pIsolate, FXJSE_Context_GlobalObjToString, + v8::External::New(pIsolate, + const_cast<FXJSE_CLASS*>(lpClassDefinition)))); + } + pClass->m_hTemplate.Reset(lpContext->m_pIsolate, hFunctionTemplate); + lpContext->m_rgClasses.Add(pClass); + return pClass; +} +CFXJSE_Class* CFXJSE_Class::GetClassFromContext(CFXJSE_Context* pContext, + const CFX_ByteStringC& szName) { + for (int count = pContext->m_rgClasses.GetSize(), i = 0; i < count; i++) { + CFXJSE_Class* pClass = pContext->m_rgClasses[i]; + if (pClass->m_szClassName == szName) { + return pClass; + } + } + return NULL; +} |