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 "fxjs/cjs_object.h"
13 #include "fxjs/cjs_return.h"
14 #include "fxjs/fxjs_v8.h"
15 #include "fxjs/js_resources.h"
16 
17 double JS_GetDateTime();
18 int JS_GetYearFromTime(double dt);
19 int JS_GetMonthFromTime(double dt);
20 int JS_GetDayFromTime(double dt);
21 int JS_GetHourFromTime(double dt);
22 int JS_GetMinFromTime(double dt);
23 int JS_GetSecFromTime(double dt);
24 double JS_LocalTime(double d);
25 double JS_DateParse(const WideString& str);
26 double JS_MakeDay(int nYear, int nMonth, int nDay);
27 double JS_MakeTime(int nHour, int nMin, int nSec, int nMs);
28 double JS_MakeDate(double day, double time);
29 
30 // Some JS methods have the bizarre convention that they may also be called
31 // with a single argument which is an object containing the actual arguments
32 // as its properties. The varying arguments to this method are the property
33 // names as wchar_t string literals corresponding to each positional argument.
34 // The result will always contain |nKeywords| value, with unspecified ones
35 // being set to type VT_unknown.
36 std::vector<v8::Local<v8::Value>> ExpandKeywordParams(
37     CJS_Runtime* pRuntime,
38     const std::vector<v8::Local<v8::Value>>& originals,
39     size_t nKeywords,
40     ...);
41 
42 // All JS classes have a name, an object defintion ID, and the ability to
43 // register themselves with FXJS_V8. We never make a BASE class on its own
44 // because it can't really do anything.
45 
46 // Rich JS classes provide constants, methods, properties, and the ability
47 // to construct native object state.
48 
49 template <class T, class A>
JSConstructor(CFXJS_Engine * pEngine,v8::Local<v8::Object> obj)50 static void JSConstructor(CFXJS_Engine* pEngine, v8::Local<v8::Object> obj) {
51   CJS_Object* pObj = new T(obj);
52   pObj->SetEmbedObject(new A(pObj));
53   pEngine->SetObjectPrivate(obj, pObj);
54   pObj->InitInstance(static_cast<CJS_Runtime*>(pEngine));
55 }
56 
57 template <class T>
JSDestructor(CFXJS_Engine * pEngine,v8::Local<v8::Object> obj)58 static void JSDestructor(CFXJS_Engine* pEngine, v8::Local<v8::Object> obj) {
59   delete static_cast<T*>(pEngine->GetObjectPrivate(obj));
60 }
61 
62 template <class C, CJS_Return (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)63 void JSPropGetter(const char* prop_name_string,
64                   const char* class_name_string,
65                   v8::Local<v8::String> property,
66                   const v8::PropertyCallbackInfo<v8::Value>& info) {
67   CJS_Runtime* pRuntime =
68       CJS_Runtime::CurrentRuntimeFromIsolate(info.GetIsolate());
69   if (!pRuntime)
70     return;
71 
72   CJS_Object* pJSObj =
73       static_cast<CJS_Object*>(pRuntime->GetObjectPrivate(info.Holder()));
74   if (!pJSObj)
75     return;
76 
77   C* pObj = reinterpret_cast<C*>(pJSObj->GetEmbedObject());
78   CJS_Return result = (pObj->*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_Return (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   CJS_Runtime* pRuntime =
96       CJS_Runtime::CurrentRuntimeFromIsolate(info.GetIsolate());
97   if (!pRuntime)
98     return;
99 
100   CJS_Object* pJSObj =
101       static_cast<CJS_Object*>(pRuntime->GetObjectPrivate(info.Holder()));
102   if (!pJSObj)
103     return;
104 
105   C* pObj = reinterpret_cast<C*>(pJSObj->GetEmbedObject());
106   CJS_Return result = (pObj->*M)(pRuntime, value);
107   if (result.HasError()) {
108     pRuntime->Error(JSFormatErrorString(class_name_string, prop_name_string,
109                                         result.Error()));
110   }
111 }
112 
113 template <class C,
114           CJS_Return (C::*M)(CJS_Runtime*,
115                              const std::vector<v8::Local<v8::Value>>&)>
JSMethod(const char * method_name_string,const char * class_name_string,const v8::FunctionCallbackInfo<v8::Value> & info)116 void JSMethod(const char* method_name_string,
117               const char* class_name_string,
118               const v8::FunctionCallbackInfo<v8::Value>& info) {
119   CJS_Runtime* pRuntime =
120       CJS_Runtime::CurrentRuntimeFromIsolate(info.GetIsolate());
121   if (!pRuntime)
122     return;
123 
124   CJS_Object* pJSObj =
125       static_cast<CJS_Object*>(pRuntime->GetObjectPrivate(info.Holder()));
126   if (!pJSObj)
127     return;
128 
129   std::vector<v8::Local<v8::Value>> parameters;
130   for (unsigned int i = 0; i < (unsigned int)info.Length(); i++)
131     parameters.push_back(info[i]);
132 
133   C* pObj = reinterpret_cast<C*>(pJSObj->GetEmbedObject());
134   CJS_Return result = (pObj->*M)(pRuntime, parameters);
135   if (result.HasError()) {
136     pRuntime->Error(JSFormatErrorString(class_name_string, method_name_string,
137                                         result.Error()));
138     return;
139   }
140 
141   if (result.HasReturn())
142     info.GetReturnValue().Set(result.Return());
143 }
144 
145 #define JS_STATIC_PROP(err_name, prop_name, class_name)           \
146   static void get_##prop_name##_static(                           \
147       v8::Local<v8::String> property,                             \
148       const v8::PropertyCallbackInfo<v8::Value>& info) {          \
149     JSPropGetter<class_name, &class_name::get_##prop_name>(       \
150         #err_name, #class_name, property, info);                  \
151   }                                                               \
152   static void set_##prop_name##_static(                           \
153       v8::Local<v8::String> property, v8::Local<v8::Value> value, \
154       const v8::PropertyCallbackInfo<void>& info) {               \
155     JSPropSetter<class_name, &class_name::set_##prop_name>(       \
156         #err_name, #class_name, property, value, info);           \
157   }
158 
159 #define JS_STATIC_METHOD(method_name, class_name)                             \
160   static void method_name##_static(                                           \
161       const v8::FunctionCallbackInfo<v8::Value>& info) {                      \
162     JSMethod<class_name, &class_name::method_name>(#method_name, #class_name, \
163                                                    info);                     \
164   }
165 
166 #endif  // FXJS_JS_DEFINE_H_
167