blob: cb0986dd3b0d9082ffe01473374913a9e926f210 [file] [log] [blame]
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001// 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.
Lei Zhanga6d9f0e2015-06-13 00:48:38 -07004
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07005// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6
Tom Sepez37458412015-10-06 11:33:46 -07007#ifndef FPDFSDK_SRC_JAVASCRIPT_JS_DEFINE_H_
8#define FPDFSDK_SRC_JAVASCRIPT_JS_DEFINE_H_
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07009
Tom Sepez37458412015-10-06 11:33:46 -070010#include "../../include/jsapi/fxjs_v8.h"
Tom Sepez3a832662015-03-02 12:59:05 -080011#include "resource.h"
Tom Sepeza1160452015-02-19 10:00:55 -080012#include "JS_Object.h"
13#include "JS_Value.h"
14
Nico Weber9d8ec5a2015-08-04 13:00:21 -070015struct JSConstSpec {
16 const wchar_t* pName;
17 double number;
18 const wchar_t* string;
19 uint8_t t; // 0:double 1:str
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070020};
21
Nico Weber9d8ec5a2015-08-04 13:00:21 -070022struct JSPropertySpec {
23 const wchar_t* pName;
24 v8::AccessorGetterCallback pPropGet;
25 v8::AccessorSetterCallback pPropPut;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070026};
27
Nico Weber9d8ec5a2015-08-04 13:00:21 -070028struct JSMethodSpec {
29 const wchar_t* pName;
30 v8::FunctionCallback pMethodCall;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070031};
32
Nico Weber9d8ec5a2015-08-04 13:00:21 -070033#define JS_WIDESTRING(widestring) L## #widestring
Nico Weber9d8ec5a2015-08-04 13:00:21 -070034#define BEGIN_JS_STATIC_CONST(js_class_name) \
35 JSConstSpec js_class_name::JS_Class_Consts[] = {
36#define JS_STATIC_CONST_ENTRY_NUMBER(const_name, pValue) \
Nico Weber077f1a32015-08-06 15:08:57 -070037 { const_name, pValue, L"", 0 } \
Nico Weber9d8ec5a2015-08-04 13:00:21 -070038 ,
Tom Sepezcd56a7d2015-10-06 11:45:28 -070039
Nico Weber077f1a32015-08-06 15:08:57 -070040#define JS_STATIC_CONST_ENTRY_STRING(const_name, pValue) \
41 { const_name, 0, pValue, 1 } \
Nico Weber9d8ec5a2015-08-04 13:00:21 -070042 ,
Tom Sepezcd56a7d2015-10-06 11:45:28 -070043
Nico Weber9d8ec5a2015-08-04 13:00:21 -070044#define END_JS_STATIC_CONST() \
45 { 0, 0, 0, 0 } \
46 } \
47 ;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070048
Nico Weber9d8ec5a2015-08-04 13:00:21 -070049#define BEGIN_JS_STATIC_PROP(js_class_name) \
50 JSPropertySpec js_class_name::JS_Class_Properties[] = {
Tom Sepez37458412015-10-06 11:33:46 -070051#define JS_STATIC_PROP_ENTRY(prop_name) \
52 { \
53 JS_WIDESTRING(prop_name), get_##prop_name##_static, \
54 set_##prop_name##_static \
55 } \
Nico Weber9d8ec5a2015-08-04 13:00:21 -070056 ,
Tom Sepezcd56a7d2015-10-06 11:45:28 -070057
Nico Weber9d8ec5a2015-08-04 13:00:21 -070058#define END_JS_STATIC_PROP() \
59 { 0, 0, 0 } \
60 } \
61 ;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070062
Nico Weber9d8ec5a2015-08-04 13:00:21 -070063#define BEGIN_JS_STATIC_METHOD(js_class_name) \
64 JSMethodSpec js_class_name::JS_Class_Methods[] = {
65#define JS_STATIC_METHOD_ENTRY(method_name) \
66 { JS_WIDESTRING(method_name), method_name##_static } \
67 ,
Tom Sepezcd56a7d2015-10-06 11:45:28 -070068
Nico Weber9d8ec5a2015-08-04 13:00:21 -070069#define END_JS_STATIC_METHOD() \
70 { 0, 0 } \
71 } \
72 ;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070073
Nico Weber9d8ec5a2015-08-04 13:00:21 -070074template <class C,
75 FX_BOOL (C::*M)(IFXJS_Context*, CJS_PropValue&, CFX_WideString&)>
Tom Sepeza1160452015-02-19 10:00:55 -080076void JSPropGetter(const char* prop_name_string,
77 const char* class_name_string,
78 v8::Local<v8::String> property,
79 const v8::PropertyCallbackInfo<v8::Value>& info) {
80 v8::Isolate* isolate = info.GetIsolate();
Tom Sepezbd7fabf2015-09-28 10:31:27 -070081 IFXJS_Runtime* pRuntime = FXJS_GetRuntimeFromIsolate(isolate);
82 if (!pRuntime)
Tom Sepeza25fd092015-09-28 09:06:03 -070083 return;
Tom Sepeza25fd092015-09-28 09:06:03 -070084 IFXJS_Context* pRuntimeContext = pRuntime->GetCurrentContext();
Tom Sepez39bfe122015-09-17 15:25:23 -070085 CJS_Object* pJSObj = (CJS_Object*)FXJS_GetPrivate(isolate, info.Holder());
Tom Sepeza1160452015-02-19 10:00:55 -080086 C* pObj = reinterpret_cast<C*>(pJSObj->GetEmbedObject());
Tom Sepez3a832662015-03-02 12:59:05 -080087 CFX_WideString sError;
Tom Sepeza25fd092015-09-28 09:06:03 -070088 CJS_PropValue value(isolate);
89 value.StartGetting();
Tom Sepeza1160452015-02-19 10:00:55 -080090 if (!(pObj->*M)(pRuntimeContext, value, sError)) {
Tom Sepez39bfe122015-09-17 15:25:23 -070091 FXJS_Error(isolate, JSFormatErrorString(class_name_string, prop_name_string,
92 sError));
Tom Sepeza1160452015-02-19 10:00:55 -080093 return;
94 }
Jochen Eisingerdfa2c992015-05-19 00:38:00 +020095 info.GetReturnValue().Set((v8::Local<v8::Value>)value);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070096}
97
Nico Weber9d8ec5a2015-08-04 13:00:21 -070098template <class C,
99 FX_BOOL (C::*M)(IFXJS_Context*, CJS_PropValue&, CFX_WideString&)>
Tom Sepeza1160452015-02-19 10:00:55 -0800100void JSPropSetter(const char* prop_name_string,
101 const char* class_name_string,
102 v8::Local<v8::String> property,
103 v8::Local<v8::Value> value,
104 const v8::PropertyCallbackInfo<void>& info) {
105 v8::Isolate* isolate = info.GetIsolate();
Tom Sepezbd7fabf2015-09-28 10:31:27 -0700106 IFXJS_Runtime* pRuntime = FXJS_GetRuntimeFromIsolate(isolate);
107 if (!pRuntime)
Tom Sepeza25fd092015-09-28 09:06:03 -0700108 return;
Tom Sepeza25fd092015-09-28 09:06:03 -0700109 IFXJS_Context* pRuntimeContext = pRuntime->GetCurrentContext();
Tom Sepez39bfe122015-09-17 15:25:23 -0700110 CJS_Object* pJSObj = (CJS_Object*)FXJS_GetPrivate(isolate, info.Holder());
Tom Sepeza1160452015-02-19 10:00:55 -0800111 C* pObj = reinterpret_cast<C*>(pJSObj->GetEmbedObject());
Tom Sepez3a832662015-03-02 12:59:05 -0800112 CFX_WideString sError;
Tom Sepeza25fd092015-09-28 09:06:03 -0700113 CJS_PropValue propValue(CJS_Value(isolate, value, CJS_Value::VT_unknown));
114 propValue.StartSetting();
Tom Sepeza1160452015-02-19 10:00:55 -0800115 if (!(pObj->*M)(pRuntimeContext, propValue, sError)) {
Tom Sepez39bfe122015-09-17 15:25:23 -0700116 FXJS_Error(isolate, JSFormatErrorString(class_name_string, prop_name_string,
117 sError));
Tom Sepeza1160452015-02-19 10:00:55 -0800118 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700119}
120
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700121#define JS_STATIC_PROP(prop_name, class_name) \
122 static void get_##prop_name##_static( \
123 v8::Local<v8::String> property, \
124 const v8::PropertyCallbackInfo<v8::Value>& info) { \
125 JSPropGetter<class_name, &class_name::prop_name>(#prop_name, #class_name, \
126 property, info); \
127 } \
128 static void set_##prop_name##_static( \
129 v8::Local<v8::String> property, v8::Local<v8::Value> value, \
130 const v8::PropertyCallbackInfo<void>& info) { \
131 JSPropSetter<class_name, &class_name::prop_name>(#prop_name, #class_name, \
132 property, value, info); \
Tom Sepeza1160452015-02-19 10:00:55 -0800133 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700134
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700135template <class C,
136 FX_BOOL (C::*M)(IFXJS_Context*,
137 const CJS_Parameters&,
138 CJS_Value&,
139 CFX_WideString&)>
Tom Sepeza1160452015-02-19 10:00:55 -0800140void JSMethod(const char* method_name_string,
141 const char* class_name_string,
142 const v8::FunctionCallbackInfo<v8::Value>& info) {
143 v8::Isolate* isolate = info.GetIsolate();
Tom Sepezbd7fabf2015-09-28 10:31:27 -0700144 IFXJS_Runtime* pRuntime = FXJS_GetRuntimeFromIsolate(isolate);
145 if (!pRuntime)
Tom Sepeza25fd092015-09-28 09:06:03 -0700146 return;
Tom Sepeza25fd092015-09-28 09:06:03 -0700147 IFXJS_Context* pRuntimeContext = pRuntime->GetCurrentContext();
Tom Sepeza1160452015-02-19 10:00:55 -0800148 CJS_Parameters parameters;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700149 for (unsigned int i = 0; i < (unsigned int)info.Length(); i++) {
Tom Sepez39bfe122015-09-17 15:25:23 -0700150 parameters.push_back(CJS_Value(isolate, info[i], CJS_Value::VT_unknown));
Tom Sepeza1160452015-02-19 10:00:55 -0800151 }
152 CJS_Value valueRes(isolate);
Tom Sepez39bfe122015-09-17 15:25:23 -0700153 CJS_Object* pJSObj = (CJS_Object*)FXJS_GetPrivate(isolate, info.Holder());
Tom Sepeza1160452015-02-19 10:00:55 -0800154 C* pObj = reinterpret_cast<C*>(pJSObj->GetEmbedObject());
Tom Sepez3a832662015-03-02 12:59:05 -0800155 CFX_WideString sError;
Tom Sepeza1160452015-02-19 10:00:55 -0800156 if (!(pObj->*M)(pRuntimeContext, parameters, valueRes, sError)) {
Tom Sepez39bfe122015-09-17 15:25:23 -0700157 FXJS_Error(isolate, JSFormatErrorString(class_name_string,
158 method_name_string, sError));
Tom Sepeza1160452015-02-19 10:00:55 -0800159 return;
160 }
Tom Sepezf4ef3f92015-04-23 11:31:31 -0700161 info.GetReturnValue().Set(valueRes.ToV8Value());
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700162}
163
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700164#define JS_STATIC_METHOD(method_name, class_name) \
165 static void method_name##_static( \
166 const v8::FunctionCallbackInfo<v8::Value>& info) { \
167 JSMethod<class_name, &class_name::method_name>(#method_name, #class_name, \
168 info); \
Tom Sepeza1160452015-02-19 10:00:55 -0800169 }
170
171#define JS_SPECIAL_STATIC_METHOD(method_name, class_alternate, class_name) \
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700172 static void method_name##_static( \
173 const v8::FunctionCallbackInfo<v8::Value>& info) { \
174 JSMethod<class_alternate, &class_alternate::method_name>( \
175 #method_name, #class_name, info); \
Tom Sepeza1160452015-02-19 10:00:55 -0800176 }
177
Tom Sepezcd56a7d2015-10-06 11:45:28 -0700178// All JS classes have a name, an object defintion ID, and the ability to
179// register themselves with FXJS_V8. We never make a BASE class on its own
180// because it can't really do anything.
181#define DECLARE_JS_CLASS_BASE_PART() \
182 static const wchar_t* g_pClassName; \
183 static int g_nObjDefnID; \
184 static void DefineJSObjects(v8::Isolate* pIsolate, FXJSOBJTYPE eObjType);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700185
Tom Sepezcd56a7d2015-10-06 11:45:28 -0700186#define IMPLEMENT_JS_CLASS_BASE_PART(js_class_name, class_name) \
187 const wchar_t* js_class_name::g_pClassName = JS_WIDESTRING(class_name); \
188 int js_class_name::g_nObjDefnID = -1;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700189
Tom Sepezcd56a7d2015-10-06 11:45:28 -0700190// CONST classes provide constants, but not constructors, methods, or props.
191#define DECLARE_JS_CLASS_CONST() \
192 DECLARE_JS_CLASS_BASE_PART() \
193 DECLARE_JS_CLASS_CONST_PART()
194
195#define IMPLEMENT_JS_CLASS_CONST(js_class_name, class_name) \
196 IMPLEMENT_JS_CLASS_BASE_PART(js_class_name, class_name) \
197 IMPLEMENT_JS_CLASS_CONST_PART(js_class_name, class_name) \
198 void js_class_name::DefineJSObjects(v8::Isolate* pIsolate, \
199 FXJSOBJTYPE eObjType) { \
200 g_nObjDefnID = FXJS_DefineObj(pIsolate, js_class_name::g_pClassName, \
201 eObjType, nullptr, nullptr); \
202 DefineConsts(pIsolate); \
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700203 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700204
Tom Sepezcd56a7d2015-10-06 11:45:28 -0700205#define DECLARE_JS_CLASS_CONST_PART() \
206 static JSConstSpec JS_Class_Consts[]; \
207 static void DefineConsts(v8::Isolate* pIsolate);
208
209#define IMPLEMENT_JS_CLASS_CONST_PART(js_class_name, class_name) \
210 void js_class_name::DefineConsts(v8::Isolate* pIsolate) { \
211 for (size_t i = 0; i < FX_ArraySize(JS_Class_Consts) - 1; ++i) { \
212 FXJS_DefineObjConst( \
213 pIsolate, g_nObjDefnID, JS_Class_Consts[i].pName, \
214 JS_Class_Consts[i].t == 0 \
215 ? FXJS_NewNumber(pIsolate, JS_Class_Consts[i].number) \
216 : FXJS_NewString(pIsolate, JS_Class_Consts[i].string)); \
217 } \
218 }
219
220// Convenience macros for declaring classes without an alternate.
221#define DECLARE_JS_CLASS() DECLARE_JS_CLASS_RICH()
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700222#define IMPLEMENT_JS_CLASS(js_class_name, class_name) \
223 IMPLEMENT_JS_CLASS_RICH(js_class_name, class_name, class_name)
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700224
Tom Sepezcd56a7d2015-10-06 11:45:28 -0700225// Rich JS classes provide constants, methods, properties, and the ability
226// to construct native object state.
227#define DECLARE_JS_CLASS_RICH() \
228 DECLARE_JS_CLASS_BASE_PART() \
229 DECLARE_JS_CLASS_CONST_PART() \
230 DECLARE_JS_CLASS_RICH_PART()
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700231
Tom Sepezcd56a7d2015-10-06 11:45:28 -0700232#define IMPLEMENT_JS_CLASS_RICH(js_class_name, class_alternate, class_name) \
233 IMPLEMENT_JS_CLASS_BASE_PART(js_class_name, class_name) \
234 IMPLEMENT_JS_CLASS_CONST_PART(js_class_name, class_name) \
235 IMPLEMENT_JS_CLASS_RICH_PART(js_class_name, class_alternate, class_name) \
236 void js_class_name::DefineJSObjects(v8::Isolate* pIsolate, \
237 FXJSOBJTYPE eObjType) { \
238 g_nObjDefnID = FXJS_DefineObj(pIsolate, js_class_name::g_pClassName, \
239 eObjType, JSConstructor, JSDestructor); \
240 DefineConsts(pIsolate); \
241 DefineProps(pIsolate); \
242 DefineMethods(pIsolate); \
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700243 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700244
Tom Sepezcd56a7d2015-10-06 11:45:28 -0700245#define DECLARE_JS_CLASS_RICH_PART() \
246 static void JSConstructor(IFXJS_Context* cc, v8::Local<v8::Object> obj, \
247 v8::Local<v8::Object> global); \
248 static void JSDestructor(v8::Local<v8::Object> obj); \
249 static void DefineProps(v8::Isolate* pIsoalte); \
250 static void DefineMethods(v8::Isolate* pIsoalte); \
251 static JSPropertySpec JS_Class_Properties[]; \
252 static JSMethodSpec JS_Class_Methods[];
253
254#define IMPLEMENT_JS_CLASS_RICH_PART(js_class_name, class_alternate, \
255 class_name) \
256 void js_class_name::JSConstructor(IFXJS_Context* cc, \
257 v8::Local<v8::Object> obj, \
258 v8::Local<v8::Object> global) { \
259 CJS_Object* pObj = new js_class_name(obj); \
260 pObj->SetEmbedObject(new class_alternate(pObj)); \
261 FXJS_SetPrivate(nullptr, obj, (void*)pObj); \
262 pObj->InitInstance(cc); \
263 } \
264 void js_class_name::JSDestructor(v8::Local<v8::Object> obj) { \
265 js_class_name* pObj = (js_class_name*)FXJS_GetPrivate(nullptr, obj); \
266 pObj->ExitInstance(); \
267 delete pObj; \
268 } \
269 void js_class_name::DefineProps(v8::Isolate* pIsolate) { \
270 for (size_t i = 0; i < FX_ArraySize(JS_Class_Properties) - 1; ++i) { \
271 FXJS_DefineObjProperty( \
272 pIsolate, g_nObjDefnID, JS_Class_Properties[i].pName, \
273 JS_Class_Properties[i].pPropGet, JS_Class_Properties[i].pPropPut); \
274 } \
275 } \
276 void js_class_name::DefineMethods(v8::Isolate* pIsolate) { \
277 for (size_t i = 0; i < FX_ArraySize(JS_Class_Methods) - 1; ++i) { \
278 FXJS_DefineObjMethod(pIsolate, g_nObjDefnID, JS_Class_Methods[i].pName, \
279 JS_Class_Methods[i].pMethodCall); \
280 } \
281 }
282
283// Special JS classes implement methods, props, and queries, but not consts.
284#define DECLARE_SPECIAL_JS_CLASS() \
285 DECLARE_JS_CLASS_BASE_PART() \
286 DECLARE_JS_CLASS_CONST_PART() \
287 DECLARE_JS_CLASS_RICH_PART() \
288 DECLARE_SPECIAL_JS_CLASS_PART()
289
290#define IMPLEMENT_SPECIAL_JS_CLASS(js_class_name, class_alternate, class_name) \
291 IMPLEMENT_JS_CLASS_BASE_PART(js_class_name, class_name) \
292 IMPLEMENT_JS_CLASS_CONST_PART(js_class_name, class_name) \
293 IMPLEMENT_JS_CLASS_RICH_PART(js_class_name, class_alternate, class_name) \
294 IMPLEMENT_SPECIAL_JS_CLASS_PART(js_class_name, class_alternate, class_name) \
295 void js_class_name::DefineJSObjects(v8::Isolate* pIsolate, \
296 FXJSOBJTYPE eObjType) { \
297 g_nObjDefnID = FXJS_DefineObj(pIsolate, js_class_name::g_pClassName, \
298 eObjType, JSConstructor, JSDestructor); \
299 DefineConsts(pIsolate); \
300 DefineProps(pIsolate); \
301 DefineMethods(pIsolate); \
302 DefineAllProperties(pIsolate); \
303 }
304
305#define DECLARE_SPECIAL_JS_CLASS_PART() \
306 static void queryprop_static( \
307 v8::Local<v8::String> property, \
308 const v8::PropertyCallbackInfo<v8::Integer>& info); \
309 static void getprop_static(v8::Local<v8::String> property, \
310 const v8::PropertyCallbackInfo<v8::Value>& info); \
311 static void putprop_static(v8::Local<v8::String> property, \
312 v8::Local<v8::Value> value, \
313 const v8::PropertyCallbackInfo<v8::Value>& info); \
314 static void delprop_static( \
315 v8::Local<v8::String> property, \
316 const v8::PropertyCallbackInfo<v8::Boolean>& info); \
317 static void DefineAllProperties(v8::Isolate* pIsolate);
318
319#define IMPLEMENT_SPECIAL_JS_CLASS_PART(js_class_name, class_alternate, \
320 class_name) \
321 void js_class_name::queryprop_static( \
322 v8::Local<v8::String> property, \
323 const v8::PropertyCallbackInfo<v8::Integer>& info) { \
324 JSSpecialPropQuery<class_alternate>(#class_name, property, info); \
325 } \
326 void js_class_name::getprop_static( \
327 v8::Local<v8::String> property, \
328 const v8::PropertyCallbackInfo<v8::Value>& info) { \
329 JSSpecialPropGet<class_alternate>(#class_name, property, info); \
330 } \
331 void js_class_name::putprop_static( \
332 v8::Local<v8::String> property, v8::Local<v8::Value> value, \
333 const v8::PropertyCallbackInfo<v8::Value>& info) { \
334 JSSpecialPropPut<class_alternate>(#class_name, property, value, info); \
335 } \
336 void js_class_name::delprop_static( \
337 v8::Local<v8::String> property, \
338 const v8::PropertyCallbackInfo<v8::Boolean>& info) { \
339 JSSpecialPropDel<class_alternate>(#class_name, property, info); \
340 } \
341 void js_class_name::DefineAllProperties(v8::Isolate* pIsolate) { \
342 FXJS_DefineObjAllProperties( \
343 pIsolate, g_nObjDefnID, js_class_name::queryprop_static, \
344 js_class_name::getprop_static, js_class_name::putprop_static, \
345 js_class_name::delprop_static); \
346 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700347
Tom Sepez2311b782015-02-23 10:22:51 -0800348template <class Alt>
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700349void JSSpecialPropQuery(const char*,
350 v8::Local<v8::String> property,
351 const v8::PropertyCallbackInfo<v8::Integer>& info) {
Tom Sepez2311b782015-02-23 10:22:51 -0800352 v8::Isolate* isolate = info.GetIsolate();
353 v8::String::Utf8Value utf8_value(property);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700354 CFX_WideString propname =
355 CFX_WideString::FromUTF8(*utf8_value, utf8_value.length());
356 CJS_Object* pJSObj =
Tom Sepez39bfe122015-09-17 15:25:23 -0700357 reinterpret_cast<CJS_Object*>(FXJS_GetPrivate(isolate, info.Holder()));
Tom Sepez2311b782015-02-23 10:22:51 -0800358 Alt* pObj = reinterpret_cast<Alt*>(pJSObj->GetEmbedObject());
359 FX_BOOL bRet = pObj->QueryProperty(propname.c_str());
360 info.GetReturnValue().Set(bRet ? 4 : 0);
361}
362
363template <class Alt>
364void JSSpecialPropGet(const char* class_name,
365 v8::Local<v8::String> property,
366 const v8::PropertyCallbackInfo<v8::Value>& info) {
367 v8::Isolate* isolate = info.GetIsolate();
Tom Sepezbd7fabf2015-09-28 10:31:27 -0700368 IFXJS_Runtime* pRuntime = FXJS_GetRuntimeFromIsolate(isolate);
369 if (!pRuntime)
Tom Sepeza25fd092015-09-28 09:06:03 -0700370 return;
Tom Sepeza25fd092015-09-28 09:06:03 -0700371 IFXJS_Context* pRuntimeContext = pRuntime->GetCurrentContext();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700372 CJS_Object* pJSObj =
Tom Sepez39bfe122015-09-17 15:25:23 -0700373 reinterpret_cast<CJS_Object*>(FXJS_GetPrivate(isolate, info.Holder()));
Tom Sepez2311b782015-02-23 10:22:51 -0800374 Alt* pObj = reinterpret_cast<Alt*>(pJSObj->GetEmbedObject());
375 v8::String::Utf8Value utf8_value(property);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700376 CFX_WideString propname =
377 CFX_WideString::FromUTF8(*utf8_value, utf8_value.length());
Tom Sepez3a832662015-03-02 12:59:05 -0800378 CFX_WideString sError;
Tom Sepez2311b782015-02-23 10:22:51 -0800379 CJS_PropValue value(isolate);
380 value.StartGetting();
381 if (!pObj->DoProperty(pRuntimeContext, propname.c_str(), value, sError)) {
Tom Sepez39bfe122015-09-17 15:25:23 -0700382 FXJS_Error(isolate, JSFormatErrorString(class_name, "GetProperty", sError));
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700383 return;
Tom Sepez2311b782015-02-23 10:22:51 -0800384 }
Jochen Eisingerdfa2c992015-05-19 00:38:00 +0200385 info.GetReturnValue().Set((v8::Local<v8::Value>)value);
Tom Sepez2311b782015-02-23 10:22:51 -0800386}
387
388template <class Alt>
389void JSSpecialPropPut(const char* class_name,
390 v8::Local<v8::String> property,
391 v8::Local<v8::Value> value,
392 const v8::PropertyCallbackInfo<v8::Value>& info) {
393 v8::Isolate* isolate = info.GetIsolate();
Tom Sepezbd7fabf2015-09-28 10:31:27 -0700394 IFXJS_Runtime* pRuntime = FXJS_GetRuntimeFromIsolate(isolate);
395 if (!pRuntime)
Tom Sepeza25fd092015-09-28 09:06:03 -0700396 return;
Tom Sepeza25fd092015-09-28 09:06:03 -0700397 IFXJS_Context* pRuntimeContext = pRuntime->GetCurrentContext();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700398 CJS_Object* pJSObj =
Tom Sepez39bfe122015-09-17 15:25:23 -0700399 reinterpret_cast<CJS_Object*>(FXJS_GetPrivate(isolate, info.Holder()));
Tom Sepez2311b782015-02-23 10:22:51 -0800400 Alt* pObj = reinterpret_cast<Alt*>(pJSObj->GetEmbedObject());
401 v8::String::Utf8Value utf8_value(property);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700402 CFX_WideString propname =
403 CFX_WideString::FromUTF8(*utf8_value, utf8_value.length());
Tom Sepez3a832662015-03-02 12:59:05 -0800404 CFX_WideString sError;
Tom Sepez39bfe122015-09-17 15:25:23 -0700405 CJS_PropValue PropValue(CJS_Value(isolate, value, CJS_Value::VT_unknown));
Tom Sepez2311b782015-02-23 10:22:51 -0800406 PropValue.StartSetting();
407 if (!pObj->DoProperty(pRuntimeContext, propname.c_str(), PropValue, sError)) {
Tom Sepez39bfe122015-09-17 15:25:23 -0700408 FXJS_Error(isolate, JSFormatErrorString(class_name, "PutProperty", sError));
Tom Sepez2311b782015-02-23 10:22:51 -0800409 }
410}
411
412template <class Alt>
413void JSSpecialPropDel(const char* class_name,
414 v8::Local<v8::String> property,
415 const v8::PropertyCallbackInfo<v8::Boolean>& info) {
416 v8::Isolate* isolate = info.GetIsolate();
Tom Sepezbd7fabf2015-09-28 10:31:27 -0700417 IFXJS_Runtime* pRuntime = FXJS_GetRuntimeFromIsolate(isolate);
418 if (!pRuntime)
Tom Sepeza25fd092015-09-28 09:06:03 -0700419 return;
Tom Sepeza25fd092015-09-28 09:06:03 -0700420 IFXJS_Context* pRuntimeContext = pRuntime->GetCurrentContext();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700421 CJS_Object* pJSObj =
Tom Sepez39bfe122015-09-17 15:25:23 -0700422 reinterpret_cast<CJS_Object*>(FXJS_GetPrivate(isolate, info.Holder()));
Tom Sepez2311b782015-02-23 10:22:51 -0800423 Alt* pObj = reinterpret_cast<Alt*>(pJSObj->GetEmbedObject());
424 v8::String::Utf8Value utf8_value(property);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700425 CFX_WideString propname =
426 CFX_WideString::FromUTF8(*utf8_value, utf8_value.length());
Tom Sepez3a832662015-03-02 12:59:05 -0800427 CFX_WideString sError;
Tom Sepez2311b782015-02-23 10:22:51 -0800428 if (!pObj->DelProperty(pRuntimeContext, propname.c_str(), sError)) {
429 CFX_ByteString cbName;
430 cbName.Format("%s.%s", class_name, "DelProperty");
Tom Sepez39bfe122015-09-17 15:25:23 -0700431 // Probably a missing call to JSFX_Error().
Tom Sepez2311b782015-02-23 10:22:51 -0800432 }
433}
434
Tom Sepezcd56a7d2015-10-06 11:45:28 -0700435template <FX_BOOL (*F)(IFXJS_Context* cc,
436 const CJS_Parameters& params,
437 CJS_Value& vRet,
438 CFX_WideString& sError)>
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700439void JSGlobalFunc(const char* func_name_string,
Tom Sepeza1160452015-02-19 10:00:55 -0800440 const v8::FunctionCallbackInfo<v8::Value>& info) {
441 v8::Isolate* isolate = info.GetIsolate();
Tom Sepezbd7fabf2015-09-28 10:31:27 -0700442 IFXJS_Runtime* pRuntime = FXJS_GetRuntimeFromIsolate(isolate);
443 if (!pRuntime)
Tom Sepeza25fd092015-09-28 09:06:03 -0700444 return;
Tom Sepeza25fd092015-09-28 09:06:03 -0700445 IFXJS_Context* pRuntimeContext = pRuntime->GetCurrentContext();
Tom Sepeza1160452015-02-19 10:00:55 -0800446 CJS_Parameters parameters;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700447 for (unsigned int i = 0; i < (unsigned int)info.Length(); i++) {
Tom Sepez39bfe122015-09-17 15:25:23 -0700448 parameters.push_back(CJS_Value(isolate, info[i], CJS_Value::VT_unknown));
Tom Sepeza1160452015-02-19 10:00:55 -0800449 }
450 CJS_Value valueRes(isolate);
Tom Sepez3a832662015-03-02 12:59:05 -0800451 CFX_WideString sError;
452 if (!(*F)(pRuntimeContext, parameters, valueRes, sError)) {
Tom Sepez39bfe122015-09-17 15:25:23 -0700453 FXJS_Error(isolate, JSFormatErrorString(func_name_string, nullptr, sError));
Tom Sepeza1160452015-02-19 10:00:55 -0800454 return;
455 }
Tom Sepezf4ef3f92015-04-23 11:31:31 -0700456 info.GetReturnValue().Set(valueRes.ToV8Value());
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700457}
458
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700459#define JS_STATIC_GLOBAL_FUN(fun_name) \
460 static void fun_name##_static( \
461 const v8::FunctionCallbackInfo<v8::Value>& info) { \
462 JSGlobalFunc<fun_name>(#fun_name, info); \
Tom Sepeza1160452015-02-19 10:00:55 -0800463 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700464
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700465#define JS_STATIC_DECLARE_GLOBAL_FUN() \
466 static JSMethodSpec global_methods[]; \
Tom Sepez142165e2015-09-11 13:21:50 -0700467 static void DefineJSObjects(v8::Isolate* pIsolate)
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700468
469#define BEGIN_JS_STATIC_GLOBAL_FUN(js_class_name) \
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700470 JSMethodSpec js_class_name::global_methods[] = {
471#define JS_STATIC_GLOBAL_FUN_ENTRY(method_name) \
472 JS_STATIC_METHOD_ENTRY(method_name)
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700473
474#define END_JS_STATIC_GLOBAL_FUN() END_JS_STATIC_METHOD()
475
Tom Sepez39bfe122015-09-17 15:25:23 -0700476#define IMPLEMENT_JS_STATIC_GLOBAL_FUN(js_class_name) \
477 void js_class_name::DefineJSObjects(v8::Isolate* pIsolate) { \
Tom Sepezcd56a7d2015-10-06 11:45:28 -0700478 for (size_t i = 0; i < FX_ArraySize(global_methods) - 1; ++i) { \
Tom Sepez39bfe122015-09-17 15:25:23 -0700479 FXJS_DefineGlobalMethod(pIsolate, \
480 js_class_name::global_methods[i].pName, \
481 js_class_name::global_methods[i].pMethodCall); \
482 } \
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700483 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700484
Tom Sepez39bfe122015-09-17 15:25:23 -0700485CJS_Value::Type GET_VALUE_TYPE(v8::Local<v8::Value> p);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700486
Tom Sepez37458412015-10-06 11:33:46 -0700487#endif // FPDFSDK_SRC_JAVASCRIPT_JS_DEFINE_H_