| // Copyright 2014 The PDFium Authors | |
| // Use of this source code is governed by a BSD-style license that can be | |
| // found in the LICENSE file. | |
| // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com | |
| #ifndef FXJS_JS_DEFINE_H_ | |
| #define FXJS_JS_DEFINE_H_ | |
| #include <memory> | |
| #include <vector> | |
| #include "core/fxcrt/unowned_ptr.h" | |
| #include "fxjs/cfxjs_engine.h" | |
| #include "fxjs/cjs_result.h" | |
| #include "fxjs/cjs_runtime.h" | |
| #include "fxjs/js_resources.h" | |
| class CJS_Object; | |
| double JS_DateParse(v8::Isolate* pIsolate, const WideString& str); | |
| // Some JS methods have the bizarre convention that they may also be called | |
| // with a single argument which is an object containing the actual arguments | |
| // as its properties. The varying arguments to this method are the property | |
| // names as wchar_t string literals corresponding to each positional argument. | |
| // The result will always contain |nKeywords| value, check for the unspecified | |
| // ones in the result using IsExpandedParamKnown() below. | |
| std::vector<v8::Local<v8::Value>> ExpandKeywordParams( | |
| CJS_Runtime* pRuntime, | |
| const std::vector<v8::Local<v8::Value>>& originals, | |
| size_t nKeywords, | |
| ...); | |
| bool IsExpandedParamKnown(v8::Local<v8::Value> value); | |
| // All JS classes have a name, an object defintion ID, and the ability to | |
| // register themselves with FXJS_V8. We never make a BASE class on its own | |
| // because it can't really do anything. | |
| // Rich JS classes provide constants, methods, properties, and the ability | |
| // to construct native object state. | |
| template <class T> | |
| static void JSConstructor(CFXJS_Engine* pEngine, v8::Local<v8::Object> obj) { | |
| pEngine->SetObjectPrivate( | |
| obj, std::make_unique<T>(obj, static_cast<CJS_Runtime*>(pEngine))); | |
| } | |
| // CJS_Object has virtual dtor, template not required. | |
| void JSDestructor(v8::Local<v8::Object> obj); | |
| template <class C> | |
| UnownedPtr<C> JSGetObject(v8::Isolate* isolate, v8::Local<v8::Object> obj) { | |
| if (CFXJS_Engine::GetObjDefnID(obj) != C::GetObjDefnID()) | |
| return nullptr; | |
| CJS_Object* pJSObj = CFXJS_Engine::GetObjectPrivate(isolate, obj); | |
| if (!pJSObj) | |
| return nullptr; | |
| return UnownedPtr<C>(static_cast<C*>(pJSObj)); | |
| } | |
| template <class C, CJS_Result (C::*M)(CJS_Runtime*)> | |
| void JSPropGetter(const char* prop_name_string, | |
| const char* class_name_string, | |
| v8::Local<v8::String> property, | |
| const v8::PropertyCallbackInfo<v8::Value>& info) { | |
| auto pObj = JSGetObject<C>(info.GetIsolate(), info.Holder()); | |
| if (!pObj) | |
| return; | |
| CJS_Runtime* pRuntime = pObj->GetRuntime(); | |
| if (!pRuntime) | |
| return; | |
| CJS_Result result = (pObj->*M)(pRuntime); | |
| if (result.HasError()) { | |
| pRuntime->Error(JSFormatErrorString(class_name_string, prop_name_string, | |
| result.Error())); | |
| return; | |
| } | |
| if (result.HasReturn()) | |
| info.GetReturnValue().Set(result.Return()); | |
| } | |
| template <class C, CJS_Result (C::*M)(CJS_Runtime*, v8::Local<v8::Value>)> | |
| void JSPropSetter(const char* prop_name_string, | |
| const char* class_name_string, | |
| v8::Local<v8::String> property, | |
| v8::Local<v8::Value> value, | |
| const v8::PropertyCallbackInfo<void>& info) { | |
| auto pObj = JSGetObject<C>(info.GetIsolate(), info.Holder()); | |
| if (!pObj) | |
| return; | |
| CJS_Runtime* pRuntime = pObj->GetRuntime(); | |
| if (!pRuntime) | |
| return; | |
| CJS_Result result = (pObj->*M)(pRuntime, value); | |
| if (result.HasError()) { | |
| pRuntime->Error(JSFormatErrorString(class_name_string, prop_name_string, | |
| result.Error())); | |
| } | |
| } | |
| template <class C, | |
| CJS_Result (C::*M)(CJS_Runtime*, | |
| const std::vector<v8::Local<v8::Value>>&)> | |
| void JSMethod(const char* method_name_string, | |
| const char* class_name_string, | |
| const v8::FunctionCallbackInfo<v8::Value>& info) { | |
| auto pObj = JSGetObject<C>(info.GetIsolate(), info.Holder()); | |
| if (!pObj) | |
| return; | |
| CJS_Runtime* pRuntime = pObj->GetRuntime(); | |
| if (!pRuntime) | |
| return; | |
| std::vector<v8::Local<v8::Value>> parameters; | |
| for (unsigned int i = 0; i < (unsigned int)info.Length(); i++) | |
| parameters.push_back(info[i]); | |
| CJS_Result result = (pObj->*M)(pRuntime, parameters); | |
| if (result.HasError()) { | |
| pRuntime->Error(JSFormatErrorString(class_name_string, method_name_string, | |
| result.Error())); | |
| return; | |
| } | |
| if (result.HasReturn()) | |
| info.GetReturnValue().Set(result.Return()); | |
| } | |
| #define JS_STATIC_PROP(err_name, prop_name, class_name) \ | |
| static void get_##prop_name##_static( \ | |
| v8::Local<v8::String> property, \ | |
| const v8::PropertyCallbackInfo<v8::Value>& info) { \ | |
| JSPropGetter<class_name, &class_name::get_##prop_name>( \ | |
| #err_name, class_name::kName, property, info); \ | |
| } \ | |
| static void set_##prop_name##_static( \ | |
| v8::Local<v8::String> property, v8::Local<v8::Value> value, \ | |
| const v8::PropertyCallbackInfo<void>& info) { \ | |
| JSPropSetter<class_name, &class_name::set_##prop_name>( \ | |
| #err_name, class_name::kName, property, value, info); \ | |
| } | |
| #define JS_STATIC_METHOD(method_name, class_name) \ | |
| static void method_name##_static( \ | |
| const v8::FunctionCallbackInfo<v8::Value>& info) { \ | |
| JSMethod<class_name, &class_name::method_name>(#method_name, \ | |
| class_name::kName, info); \ | |
| } | |
| #endif // FXJS_JS_DEFINE_H_ |