// 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 #ifndef FXJS_JS_DEFINE_H_ #define FXJS_JS_DEFINE_H_ #include #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" #include "third_party/base/ptr_util.h" class CJS_Object; double JS_DateParse(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> ExpandKeywordParams( CJS_Runtime* pRuntime, const std::vector>& originals, size_t nKeywords, ...); bool IsExpandedParamKnown(v8::Local 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 static void JSConstructor(CFXJS_Engine* pEngine, v8::Local obj) { pEngine->SetObjectPrivate( obj, pdfium::MakeUnique(obj, static_cast(pEngine))); } // CJS_Object has virtual dtor, template not required. void JSDestructor(v8::Local obj); template UnownedPtr JSGetObject(v8::Local obj) { if (CFXJS_Engine::GetObjDefnID(obj) != C::GetObjDefnID()) return nullptr; CJS_Object* pJSObj = CFXJS_Engine::GetObjectPrivate(obj); if (!pJSObj) return nullptr; return UnownedPtr(static_cast(pJSObj)); } template void JSPropGetter(const char* prop_name_string, const char* class_name_string, v8::Local property, const v8::PropertyCallbackInfo& info) { auto pObj = JSGetObject(info.Holder()); if (!pObj) return; CJS_Runtime* pRuntime = pObj->GetRuntime(); if (!pRuntime) return; CJS_Result result = (pObj.Get()->*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 )> void JSPropSetter(const char* prop_name_string, const char* class_name_string, v8::Local property, v8::Local value, const v8::PropertyCallbackInfo& info) { auto pObj = JSGetObject(info.Holder()); if (!pObj) return; CJS_Runtime* pRuntime = pObj->GetRuntime(); if (!pRuntime) return; CJS_Result result = (pObj.Get()->*M)(pRuntime, value); if (result.HasError()) { pRuntime->Error(JSFormatErrorString(class_name_string, prop_name_string, result.Error())); } } template >&)> void JSMethod(const char* method_name_string, const char* class_name_string, const v8::FunctionCallbackInfo& info) { auto pObj = JSGetObject(info.Holder()); if (!pObj) return; CJS_Runtime* pRuntime = pObj->GetRuntime(); if (!pRuntime) return; std::vector> parameters; for (unsigned int i = 0; i < (unsigned int)info.Length(); i++) parameters.push_back(info[i]); CJS_Result result = (pObj.Get()->*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 property, \ const v8::PropertyCallbackInfo& info) { \ JSPropGetter( \ #err_name, class_name::kName, property, info); \ } \ static void set_##prop_name##_static( \ v8::Local property, v8::Local value, \ const v8::PropertyCallbackInfo& info) { \ JSPropSetter( \ #err_name, class_name::kName, property, value, info); \ } #define JS_STATIC_METHOD(method_name, class_name) \ static void method_name##_static( \ const v8::FunctionCallbackInfo& info) { \ JSMethod(#method_name, \ class_name::kName, info); \ } #endif // FXJS_JS_DEFINE_H_