1 // Copyright 2014 PDFium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6
7 #ifndef FXJS_JS_DEFINE_H_
8 #define FXJS_JS_DEFINE_H_
9
10 #include <vector>
11
12 #include "core/fxcrt/unowned_ptr.h"
13 #include "fxjs/cfxjs_engine.h"
14 #include "fxjs/cjs_result.h"
15 #include "fxjs/cjs_runtime.h"
16 #include "fxjs/js_resources.h"
17 #include "third_party/base/ptr_util.h"
18
19 class CJS_Object;
20
21 double JS_DateParse(const WideString& str);
22
23 // Some JS methods have the bizarre convention that they may also be called
24 // with a single argument which is an object containing the actual arguments
25 // as its properties. The varying arguments to this method are the property
26 // names as wchar_t string literals corresponding to each positional argument.
27 // The result will always contain |nKeywords| value, check for the unspecified
28 // ones in the result using IsExpandedParamKnown() below.
29 std::vector<v8::Local<v8::Value>> ExpandKeywordParams(
30 CJS_Runtime* pRuntime,
31 const std::vector<v8::Local<v8::Value>>& originals,
32 size_t nKeywords,
33 ...);
34
35 bool IsExpandedParamKnown(v8::Local<v8::Value> value);
36
37 // All JS classes have a name, an object defintion ID, and the ability to
38 // register themselves with FXJS_V8. We never make a BASE class on its own
39 // because it can't really do anything.
40
41 // Rich JS classes provide constants, methods, properties, and the ability
42 // to construct native object state.
43
44 template <class T>
JSConstructor(CFXJS_Engine * pEngine,v8::Local<v8::Object> obj)45 static void JSConstructor(CFXJS_Engine* pEngine, v8::Local<v8::Object> obj) {
46 pEngine->SetObjectPrivate(
47 obj, pdfium::MakeUnique<T>(obj, static_cast<CJS_Runtime*>(pEngine)));
48 }
49
50 // CJS_Object has virtual dtor, template not required.
51 void JSDestructor(v8::Local<v8::Object> obj);
52
53 template <class C>
JSGetObject(v8::Local<v8::Object> obj)54 UnownedPtr<C> JSGetObject(v8::Local<v8::Object> obj) {
55 if (CFXJS_Engine::GetObjDefnID(obj) != C::GetObjDefnID())
56 return nullptr;
57
58 CJS_Object* pJSObj = CFXJS_Engine::GetObjectPrivate(obj);
59 if (!pJSObj)
60 return nullptr;
61
62 return UnownedPtr<C>(static_cast<C*>(pJSObj));
63 }
64
65 template <class C, CJS_Result (C::*M)(CJS_Runtime*)>
JSPropGetter(const char * prop_name_string,const char * class_name_string,v8::Local<v8::String> property,const v8::PropertyCallbackInfo<v8::Value> & info)66 void JSPropGetter(const char* prop_name_string,
67 const char* class_name_string,
68 v8::Local<v8::String> property,
69 const v8::PropertyCallbackInfo<v8::Value>& info) {
70 auto pObj = JSGetObject<C>(info.Holder());
71 if (!pObj)
72 return;
73
74 CJS_Runtime* pRuntime = pObj->GetRuntime();
75 if (!pRuntime)
76 return;
77
78 CJS_Result result = (pObj.Get()->*M)(pRuntime);
79 if (result.HasError()) {
80 pRuntime->Error(JSFormatErrorString(class_name_string, prop_name_string,
81 result.Error()));
82 return;
83 }
84
85 if (result.HasReturn())
86 info.GetReturnValue().Set(result.Return());
87 }
88
89 template <class C, CJS_Result (C::*M)(CJS_Runtime*, v8::Local<v8::Value>)>
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)90 void JSPropSetter(const char* prop_name_string,
91 const char* class_name_string,
92 v8::Local<v8::String> property,
93 v8::Local<v8::Value> value,
94 const v8::PropertyCallbackInfo<void>& info) {
95 auto pObj = JSGetObject<C>(info.Holder());
96 if (!pObj)
97 return;
98
99 CJS_Runtime* pRuntime = pObj->GetRuntime();
100 if (!pRuntime)
101 return;
102
103 CJS_Result result = (pObj.Get()->*M)(pRuntime, value);
104 if (result.HasError()) {
105 pRuntime->Error(JSFormatErrorString(class_name_string, prop_name_string,
106 result.Error()));
107 }
108 }
109
110 template <class C,
111 CJS_Result (C::*M)(CJS_Runtime*,
112 const std::vector<v8::Local<v8::Value>>&)>
JSMethod(const char * method_name_string,const char * class_name_string,const v8::FunctionCallbackInfo<v8::Value> & info)113 void JSMethod(const char* method_name_string,
114 const char* class_name_string,
115 const v8::FunctionCallbackInfo<v8::Value>& info) {
116 auto pObj = JSGetObject<C>(info.Holder());
117 if (!pObj)
118 return;
119
120 CJS_Runtime* pRuntime = pObj->GetRuntime();
121 if (!pRuntime)
122 return;
123
124 std::vector<v8::Local<v8::Value>> parameters;
125 for (unsigned int i = 0; i < (unsigned int)info.Length(); i++)
126 parameters.push_back(info[i]);
127
128 CJS_Result result = (pObj.Get()->*M)(pRuntime, parameters);
129 if (result.HasError()) {
130 pRuntime->Error(JSFormatErrorString(class_name_string, method_name_string,
131 result.Error()));
132 return;
133 }
134
135 if (result.HasReturn())
136 info.GetReturnValue().Set(result.Return());
137 }
138
139 #define JS_STATIC_PROP(err_name, prop_name, class_name) \
140 static void get_##prop_name##_static( \
141 v8::Local<v8::String> property, \
142 const v8::PropertyCallbackInfo<v8::Value>& info) { \
143 JSPropGetter<class_name, &class_name::get_##prop_name>( \
144 #err_name, class_name::kName, property, info); \
145 } \
146 static void set_##prop_name##_static( \
147 v8::Local<v8::String> property, v8::Local<v8::Value> value, \
148 const v8::PropertyCallbackInfo<void>& info) { \
149 JSPropSetter<class_name, &class_name::set_##prop_name>( \
150 #err_name, class_name::kName, property, value, info); \
151 }
152
153 #define JS_STATIC_METHOD(method_name, class_name) \
154 static void method_name##_static( \
155 const v8::FunctionCallbackInfo<v8::Value>& info) { \
156 JSMethod<class_name, &class_name::method_name>(#method_name, \
157 class_name::kName, info); \
158 }
159
160 #endif // FXJS_JS_DEFINE_H_
161