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