blob: 252c50ff1b12862e86c7f33858b13bc158ff5187 [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,
Tom Sepezba038bc2015-10-08 12:03:00 -070075 FX_BOOL (C::*M)(IJS_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 Sepez67fd5df2015-10-08 12:24:19 -070081 CJS_Runtime* pRuntime =
82 static_cast<CJS_Runtime*>(FXJS_GetRuntimeFromIsolate(isolate));
Tom Sepezbd7fabf2015-09-28 10:31:27 -070083 if (!pRuntime)
Tom Sepeza25fd092015-09-28 09:06:03 -070084 return;
Tom Sepezba038bc2015-10-08 12:03:00 -070085 IJS_Context* pRuntimeContext = pRuntime->GetCurrentContext();
Tom Sepez39bfe122015-09-17 15:25:23 -070086 CJS_Object* pJSObj = (CJS_Object*)FXJS_GetPrivate(isolate, info.Holder());
Tom Sepeza1160452015-02-19 10:00:55 -080087 C* pObj = reinterpret_cast<C*>(pJSObj->GetEmbedObject());
Tom Sepez3a832662015-03-02 12:59:05 -080088 CFX_WideString sError;
Tom Sepez67fd5df2015-10-08 12:24:19 -070089 CJS_PropValue value(pRuntime);
Tom Sepeza25fd092015-09-28 09:06:03 -070090 value.StartGetting();
Tom Sepeza1160452015-02-19 10:00:55 -080091 if (!(pObj->*M)(pRuntimeContext, value, sError)) {
Tom Sepez39bfe122015-09-17 15:25:23 -070092 FXJS_Error(isolate, JSFormatErrorString(class_name_string, prop_name_string,
93 sError));
Tom Sepeza1160452015-02-19 10:00:55 -080094 return;
95 }
Jochen Eisingerdfa2c992015-05-19 00:38:00 +020096 info.GetReturnValue().Set((v8::Local<v8::Value>)value);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070097}
98
Nico Weber9d8ec5a2015-08-04 13:00:21 -070099template <class C,
Tom Sepezba038bc2015-10-08 12:03:00 -0700100 FX_BOOL (C::*M)(IJS_Context*, CJS_PropValue&, CFX_WideString&)>
Tom Sepeza1160452015-02-19 10:00:55 -0800101void JSPropSetter(const char* prop_name_string,
102 const char* class_name_string,
103 v8::Local<v8::String> property,
104 v8::Local<v8::Value> value,
105 const v8::PropertyCallbackInfo<void>& info) {
106 v8::Isolate* isolate = info.GetIsolate();
Tom Sepez67fd5df2015-10-08 12:24:19 -0700107 CJS_Runtime* pRuntime =
108 static_cast<CJS_Runtime*>(FXJS_GetRuntimeFromIsolate(isolate));
Tom Sepezbd7fabf2015-09-28 10:31:27 -0700109 if (!pRuntime)
Tom Sepeza25fd092015-09-28 09:06:03 -0700110 return;
Tom Sepezba038bc2015-10-08 12:03:00 -0700111 IJS_Context* pRuntimeContext = pRuntime->GetCurrentContext();
Tom Sepez39bfe122015-09-17 15:25:23 -0700112 CJS_Object* pJSObj = (CJS_Object*)FXJS_GetPrivate(isolate, info.Holder());
Tom Sepeza1160452015-02-19 10:00:55 -0800113 C* pObj = reinterpret_cast<C*>(pJSObj->GetEmbedObject());
Tom Sepez3a832662015-03-02 12:59:05 -0800114 CFX_WideString sError;
Tom Sepez67fd5df2015-10-08 12:24:19 -0700115 CJS_PropValue propValue(CJS_Value(pRuntime, value, CJS_Value::VT_unknown));
Tom Sepeza25fd092015-09-28 09:06:03 -0700116 propValue.StartSetting();
Tom Sepeza1160452015-02-19 10:00:55 -0800117 if (!(pObj->*M)(pRuntimeContext, propValue, sError)) {
Tom Sepez39bfe122015-09-17 15:25:23 -0700118 FXJS_Error(isolate, JSFormatErrorString(class_name_string, prop_name_string,
119 sError));
Tom Sepeza1160452015-02-19 10:00:55 -0800120 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700121}
122
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700123#define JS_STATIC_PROP(prop_name, class_name) \
124 static void get_##prop_name##_static( \
125 v8::Local<v8::String> property, \
126 const v8::PropertyCallbackInfo<v8::Value>& info) { \
127 JSPropGetter<class_name, &class_name::prop_name>(#prop_name, #class_name, \
128 property, info); \
129 } \
130 static void set_##prop_name##_static( \
131 v8::Local<v8::String> property, v8::Local<v8::Value> value, \
132 const v8::PropertyCallbackInfo<void>& info) { \
133 JSPropSetter<class_name, &class_name::prop_name>(#prop_name, #class_name, \
134 property, value, info); \
Tom Sepeza1160452015-02-19 10:00:55 -0800135 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700136
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700137template <class C,
Tom Sepezba038bc2015-10-08 12:03:00 -0700138 FX_BOOL (C::*M)(IJS_Context*,
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700139 const CJS_Parameters&,
140 CJS_Value&,
141 CFX_WideString&)>
Tom Sepeza1160452015-02-19 10:00:55 -0800142void JSMethod(const char* method_name_string,
143 const char* class_name_string,
144 const v8::FunctionCallbackInfo<v8::Value>& info) {
145 v8::Isolate* isolate = info.GetIsolate();
Tom Sepez67fd5df2015-10-08 12:24:19 -0700146 CJS_Runtime* pRuntime =
147 static_cast<CJS_Runtime*>(FXJS_GetRuntimeFromIsolate(isolate));
Tom Sepezbd7fabf2015-09-28 10:31:27 -0700148 if (!pRuntime)
Tom Sepeza25fd092015-09-28 09:06:03 -0700149 return;
Tom Sepezba038bc2015-10-08 12:03:00 -0700150 IJS_Context* pRuntimeContext = pRuntime->GetCurrentContext();
Tom Sepeza1160452015-02-19 10:00:55 -0800151 CJS_Parameters parameters;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700152 for (unsigned int i = 0; i < (unsigned int)info.Length(); i++) {
Tom Sepez67fd5df2015-10-08 12:24:19 -0700153 parameters.push_back(CJS_Value(pRuntime, info[i], CJS_Value::VT_unknown));
Tom Sepeza1160452015-02-19 10:00:55 -0800154 }
Tom Sepez67fd5df2015-10-08 12:24:19 -0700155 CJS_Value valueRes(pRuntime);
Tom Sepez39bfe122015-09-17 15:25:23 -0700156 CJS_Object* pJSObj = (CJS_Object*)FXJS_GetPrivate(isolate, info.Holder());
Tom Sepeza1160452015-02-19 10:00:55 -0800157 C* pObj = reinterpret_cast<C*>(pJSObj->GetEmbedObject());
Tom Sepez3a832662015-03-02 12:59:05 -0800158 CFX_WideString sError;
Tom Sepeza1160452015-02-19 10:00:55 -0800159 if (!(pObj->*M)(pRuntimeContext, parameters, valueRes, sError)) {
Tom Sepez39bfe122015-09-17 15:25:23 -0700160 FXJS_Error(isolate, JSFormatErrorString(class_name_string,
161 method_name_string, sError));
Tom Sepeza1160452015-02-19 10:00:55 -0800162 return;
163 }
Tom Sepezf4ef3f92015-04-23 11:31:31 -0700164 info.GetReturnValue().Set(valueRes.ToV8Value());
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700165}
166
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700167#define JS_STATIC_METHOD(method_name, class_name) \
168 static void method_name##_static( \
169 const v8::FunctionCallbackInfo<v8::Value>& info) { \
170 JSMethod<class_name, &class_name::method_name>(#method_name, #class_name, \
171 info); \
Tom Sepeza1160452015-02-19 10:00:55 -0800172 }
173
174#define JS_SPECIAL_STATIC_METHOD(method_name, class_alternate, class_name) \
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700175 static void method_name##_static( \
176 const v8::FunctionCallbackInfo<v8::Value>& info) { \
177 JSMethod<class_alternate, &class_alternate::method_name>( \
178 #method_name, #class_name, info); \
Tom Sepeza1160452015-02-19 10:00:55 -0800179 }
180
Tom Sepezcd56a7d2015-10-06 11:45:28 -0700181// All JS classes have a name, an object defintion ID, and the ability to
182// register themselves with FXJS_V8. We never make a BASE class on its own
183// because it can't really do anything.
184#define DECLARE_JS_CLASS_BASE_PART() \
185 static const wchar_t* g_pClassName; \
186 static int g_nObjDefnID; \
187 static void DefineJSObjects(v8::Isolate* pIsolate, FXJSOBJTYPE eObjType);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700188
Tom Sepezcd56a7d2015-10-06 11:45:28 -0700189#define IMPLEMENT_JS_CLASS_BASE_PART(js_class_name, class_name) \
190 const wchar_t* js_class_name::g_pClassName = JS_WIDESTRING(class_name); \
191 int js_class_name::g_nObjDefnID = -1;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700192
Tom Sepezcd56a7d2015-10-06 11:45:28 -0700193// CONST classes provide constants, but not constructors, methods, or props.
194#define DECLARE_JS_CLASS_CONST() \
195 DECLARE_JS_CLASS_BASE_PART() \
196 DECLARE_JS_CLASS_CONST_PART()
197
198#define IMPLEMENT_JS_CLASS_CONST(js_class_name, class_name) \
199 IMPLEMENT_JS_CLASS_BASE_PART(js_class_name, class_name) \
200 IMPLEMENT_JS_CLASS_CONST_PART(js_class_name, class_name) \
201 void js_class_name::DefineJSObjects(v8::Isolate* pIsolate, \
202 FXJSOBJTYPE eObjType) { \
203 g_nObjDefnID = FXJS_DefineObj(pIsolate, js_class_name::g_pClassName, \
204 eObjType, nullptr, nullptr); \
205 DefineConsts(pIsolate); \
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700206 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700207
Tom Sepezcd56a7d2015-10-06 11:45:28 -0700208#define DECLARE_JS_CLASS_CONST_PART() \
209 static JSConstSpec JS_Class_Consts[]; \
210 static void DefineConsts(v8::Isolate* pIsolate);
211
212#define IMPLEMENT_JS_CLASS_CONST_PART(js_class_name, class_name) \
213 void js_class_name::DefineConsts(v8::Isolate* pIsolate) { \
214 for (size_t i = 0; i < FX_ArraySize(JS_Class_Consts) - 1; ++i) { \
215 FXJS_DefineObjConst( \
216 pIsolate, g_nObjDefnID, JS_Class_Consts[i].pName, \
217 JS_Class_Consts[i].t == 0 \
218 ? FXJS_NewNumber(pIsolate, JS_Class_Consts[i].number) \
219 : FXJS_NewString(pIsolate, JS_Class_Consts[i].string)); \
220 } \
221 }
222
223// Convenience macros for declaring classes without an alternate.
224#define DECLARE_JS_CLASS() DECLARE_JS_CLASS_RICH()
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700225#define IMPLEMENT_JS_CLASS(js_class_name, class_name) \
226 IMPLEMENT_JS_CLASS_RICH(js_class_name, class_name, class_name)
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700227
Tom Sepezcd56a7d2015-10-06 11:45:28 -0700228// Rich JS classes provide constants, methods, properties, and the ability
229// to construct native object state.
230#define DECLARE_JS_CLASS_RICH() \
231 DECLARE_JS_CLASS_BASE_PART() \
232 DECLARE_JS_CLASS_CONST_PART() \
233 DECLARE_JS_CLASS_RICH_PART()
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700234
Tom Sepezcd56a7d2015-10-06 11:45:28 -0700235#define IMPLEMENT_JS_CLASS_RICH(js_class_name, class_alternate, class_name) \
236 IMPLEMENT_JS_CLASS_BASE_PART(js_class_name, class_name) \
237 IMPLEMENT_JS_CLASS_CONST_PART(js_class_name, class_name) \
238 IMPLEMENT_JS_CLASS_RICH_PART(js_class_name, class_alternate, class_name) \
239 void js_class_name::DefineJSObjects(v8::Isolate* pIsolate, \
240 FXJSOBJTYPE eObjType) { \
241 g_nObjDefnID = FXJS_DefineObj(pIsolate, js_class_name::g_pClassName, \
242 eObjType, JSConstructor, JSDestructor); \
243 DefineConsts(pIsolate); \
244 DefineProps(pIsolate); \
245 DefineMethods(pIsolate); \
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700246 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700247
Tom Sepez33420902015-10-13 15:00:10 -0700248#define DECLARE_JS_CLASS_RICH_PART() \
249 static void JSConstructor(IJS_Runtime* pRuntime, v8::Local<v8::Object> obj); \
250 static void JSDestructor(v8::Local<v8::Object> obj); \
251 static void DefineProps(v8::Isolate* pIsoalte); \
252 static void DefineMethods(v8::Isolate* pIsoalte); \
253 static JSPropertySpec JS_Class_Properties[]; \
Tom Sepezcd56a7d2015-10-06 11:45:28 -0700254 static JSMethodSpec JS_Class_Methods[];
255
256#define IMPLEMENT_JS_CLASS_RICH_PART(js_class_name, class_alternate, \
257 class_name) \
Tom Sepez33420902015-10-13 15:00:10 -0700258 void js_class_name::JSConstructor(IJS_Runtime* pIRuntime, \
Tom Sepez7fed2e72015-10-07 13:09:38 -0700259 v8::Local<v8::Object> obj) { \
Tom Sepezcd56a7d2015-10-06 11:45:28 -0700260 CJS_Object* pObj = new js_class_name(obj); \
261 pObj->SetEmbedObject(new class_alternate(pObj)); \
262 FXJS_SetPrivate(nullptr, obj, (void*)pObj); \
Tom Sepez33420902015-10-13 15:00:10 -0700263 pObj->InitInstance(pIRuntime); \
Tom Sepezcd56a7d2015-10-06 11:45:28 -0700264 } \
265 void js_class_name::JSDestructor(v8::Local<v8::Object> obj) { \
266 js_class_name* pObj = (js_class_name*)FXJS_GetPrivate(nullptr, obj); \
267 pObj->ExitInstance(); \
268 delete pObj; \
269 } \
270 void js_class_name::DefineProps(v8::Isolate* pIsolate) { \
271 for (size_t i = 0; i < FX_ArraySize(JS_Class_Properties) - 1; ++i) { \
272 FXJS_DefineObjProperty( \
273 pIsolate, g_nObjDefnID, JS_Class_Properties[i].pName, \
274 JS_Class_Properties[i].pPropGet, JS_Class_Properties[i].pPropPut); \
275 } \
276 } \
277 void js_class_name::DefineMethods(v8::Isolate* pIsolate) { \
278 for (size_t i = 0; i < FX_ArraySize(JS_Class_Methods) - 1; ++i) { \
279 FXJS_DefineObjMethod(pIsolate, g_nObjDefnID, JS_Class_Methods[i].pName, \
280 JS_Class_Methods[i].pMethodCall); \
281 } \
282 }
283
284// Special JS classes implement methods, props, and queries, but not consts.
285#define DECLARE_SPECIAL_JS_CLASS() \
286 DECLARE_JS_CLASS_BASE_PART() \
287 DECLARE_JS_CLASS_CONST_PART() \
288 DECLARE_JS_CLASS_RICH_PART() \
289 DECLARE_SPECIAL_JS_CLASS_PART()
290
291#define IMPLEMENT_SPECIAL_JS_CLASS(js_class_name, class_alternate, class_name) \
292 IMPLEMENT_JS_CLASS_BASE_PART(js_class_name, class_name) \
293 IMPLEMENT_JS_CLASS_CONST_PART(js_class_name, class_name) \
294 IMPLEMENT_JS_CLASS_RICH_PART(js_class_name, class_alternate, class_name) \
295 IMPLEMENT_SPECIAL_JS_CLASS_PART(js_class_name, class_alternate, class_name) \
296 void js_class_name::DefineJSObjects(v8::Isolate* pIsolate, \
297 FXJSOBJTYPE eObjType) { \
298 g_nObjDefnID = FXJS_DefineObj(pIsolate, js_class_name::g_pClassName, \
299 eObjType, JSConstructor, JSDestructor); \
300 DefineConsts(pIsolate); \
301 DefineProps(pIsolate); \
302 DefineMethods(pIsolate); \
303 DefineAllProperties(pIsolate); \
304 }
305
306#define DECLARE_SPECIAL_JS_CLASS_PART() \
307 static void queryprop_static( \
308 v8::Local<v8::String> property, \
309 const v8::PropertyCallbackInfo<v8::Integer>& info); \
310 static void getprop_static(v8::Local<v8::String> property, \
311 const v8::PropertyCallbackInfo<v8::Value>& info); \
312 static void putprop_static(v8::Local<v8::String> property, \
313 v8::Local<v8::Value> value, \
314 const v8::PropertyCallbackInfo<v8::Value>& info); \
315 static void delprop_static( \
316 v8::Local<v8::String> property, \
317 const v8::PropertyCallbackInfo<v8::Boolean>& info); \
318 static void DefineAllProperties(v8::Isolate* pIsolate);
319
320#define IMPLEMENT_SPECIAL_JS_CLASS_PART(js_class_name, class_alternate, \
321 class_name) \
322 void js_class_name::queryprop_static( \
323 v8::Local<v8::String> property, \
324 const v8::PropertyCallbackInfo<v8::Integer>& info) { \
325 JSSpecialPropQuery<class_alternate>(#class_name, property, info); \
326 } \
327 void js_class_name::getprop_static( \
328 v8::Local<v8::String> property, \
329 const v8::PropertyCallbackInfo<v8::Value>& info) { \
330 JSSpecialPropGet<class_alternate>(#class_name, property, info); \
331 } \
332 void js_class_name::putprop_static( \
333 v8::Local<v8::String> property, v8::Local<v8::Value> value, \
334 const v8::PropertyCallbackInfo<v8::Value>& info) { \
335 JSSpecialPropPut<class_alternate>(#class_name, property, value, info); \
336 } \
337 void js_class_name::delprop_static( \
338 v8::Local<v8::String> property, \
339 const v8::PropertyCallbackInfo<v8::Boolean>& info) { \
340 JSSpecialPropDel<class_alternate>(#class_name, property, info); \
341 } \
342 void js_class_name::DefineAllProperties(v8::Isolate* pIsolate) { \
343 FXJS_DefineObjAllProperties( \
344 pIsolate, g_nObjDefnID, js_class_name::queryprop_static, \
345 js_class_name::getprop_static, js_class_name::putprop_static, \
346 js_class_name::delprop_static); \
347 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700348
Tom Sepez2311b782015-02-23 10:22:51 -0800349template <class Alt>
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700350void JSSpecialPropQuery(const char*,
351 v8::Local<v8::String> property,
352 const v8::PropertyCallbackInfo<v8::Integer>& info) {
Tom Sepez2311b782015-02-23 10:22:51 -0800353 v8::Isolate* isolate = info.GetIsolate();
354 v8::String::Utf8Value utf8_value(property);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700355 CFX_WideString propname =
356 CFX_WideString::FromUTF8(*utf8_value, utf8_value.length());
357 CJS_Object* pJSObj =
Tom Sepez39bfe122015-09-17 15:25:23 -0700358 reinterpret_cast<CJS_Object*>(FXJS_GetPrivate(isolate, info.Holder()));
Tom Sepez2311b782015-02-23 10:22:51 -0800359 Alt* pObj = reinterpret_cast<Alt*>(pJSObj->GetEmbedObject());
360 FX_BOOL bRet = pObj->QueryProperty(propname.c_str());
361 info.GetReturnValue().Set(bRet ? 4 : 0);
362}
363
364template <class Alt>
365void JSSpecialPropGet(const char* class_name,
366 v8::Local<v8::String> property,
367 const v8::PropertyCallbackInfo<v8::Value>& info) {
368 v8::Isolate* isolate = info.GetIsolate();
Tom Sepez67fd5df2015-10-08 12:24:19 -0700369 CJS_Runtime* pRuntime =
370 static_cast<CJS_Runtime*>(FXJS_GetRuntimeFromIsolate(isolate));
Tom Sepezbd7fabf2015-09-28 10:31:27 -0700371 if (!pRuntime)
Tom Sepeza25fd092015-09-28 09:06:03 -0700372 return;
Tom Sepezba038bc2015-10-08 12:03:00 -0700373 IJS_Context* pRuntimeContext = pRuntime->GetCurrentContext();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700374 CJS_Object* pJSObj =
Tom Sepez39bfe122015-09-17 15:25:23 -0700375 reinterpret_cast<CJS_Object*>(FXJS_GetPrivate(isolate, info.Holder()));
Tom Sepez2311b782015-02-23 10:22:51 -0800376 Alt* pObj = reinterpret_cast<Alt*>(pJSObj->GetEmbedObject());
377 v8::String::Utf8Value utf8_value(property);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700378 CFX_WideString propname =
379 CFX_WideString::FromUTF8(*utf8_value, utf8_value.length());
Tom Sepez3a832662015-03-02 12:59:05 -0800380 CFX_WideString sError;
Tom Sepez67fd5df2015-10-08 12:24:19 -0700381 CJS_PropValue value(pRuntime);
Tom Sepez2311b782015-02-23 10:22:51 -0800382 value.StartGetting();
383 if (!pObj->DoProperty(pRuntimeContext, propname.c_str(), value, sError)) {
Tom Sepez39bfe122015-09-17 15:25:23 -0700384 FXJS_Error(isolate, JSFormatErrorString(class_name, "GetProperty", sError));
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700385 return;
Tom Sepez2311b782015-02-23 10:22:51 -0800386 }
Jochen Eisingerdfa2c992015-05-19 00:38:00 +0200387 info.GetReturnValue().Set((v8::Local<v8::Value>)value);
Tom Sepez2311b782015-02-23 10:22:51 -0800388}
389
390template <class Alt>
391void JSSpecialPropPut(const char* class_name,
392 v8::Local<v8::String> property,
393 v8::Local<v8::Value> value,
394 const v8::PropertyCallbackInfo<v8::Value>& info) {
395 v8::Isolate* isolate = info.GetIsolate();
Tom Sepez67fd5df2015-10-08 12:24:19 -0700396 CJS_Runtime* pRuntime =
397 static_cast<CJS_Runtime*>(FXJS_GetRuntimeFromIsolate(isolate));
Tom Sepezbd7fabf2015-09-28 10:31:27 -0700398 if (!pRuntime)
Tom Sepeza25fd092015-09-28 09:06:03 -0700399 return;
Tom Sepezba038bc2015-10-08 12:03:00 -0700400 IJS_Context* pRuntimeContext = pRuntime->GetCurrentContext();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700401 CJS_Object* pJSObj =
Tom Sepez39bfe122015-09-17 15:25:23 -0700402 reinterpret_cast<CJS_Object*>(FXJS_GetPrivate(isolate, info.Holder()));
Tom Sepez2311b782015-02-23 10:22:51 -0800403 Alt* pObj = reinterpret_cast<Alt*>(pJSObj->GetEmbedObject());
404 v8::String::Utf8Value utf8_value(property);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700405 CFX_WideString propname =
406 CFX_WideString::FromUTF8(*utf8_value, utf8_value.length());
Tom Sepez3a832662015-03-02 12:59:05 -0800407 CFX_WideString sError;
Tom Sepez67fd5df2015-10-08 12:24:19 -0700408 CJS_PropValue PropValue(CJS_Value(pRuntime, value, CJS_Value::VT_unknown));
Tom Sepez2311b782015-02-23 10:22:51 -0800409 PropValue.StartSetting();
410 if (!pObj->DoProperty(pRuntimeContext, propname.c_str(), PropValue, sError)) {
Tom Sepez39bfe122015-09-17 15:25:23 -0700411 FXJS_Error(isolate, JSFormatErrorString(class_name, "PutProperty", sError));
Tom Sepez2311b782015-02-23 10:22:51 -0800412 }
413}
414
415template <class Alt>
416void JSSpecialPropDel(const char* class_name,
417 v8::Local<v8::String> property,
418 const v8::PropertyCallbackInfo<v8::Boolean>& info) {
419 v8::Isolate* isolate = info.GetIsolate();
Tom Sepezba038bc2015-10-08 12:03:00 -0700420 IJS_Runtime* pRuntime = FXJS_GetRuntimeFromIsolate(isolate);
Tom Sepezbd7fabf2015-09-28 10:31:27 -0700421 if (!pRuntime)
Tom Sepeza25fd092015-09-28 09:06:03 -0700422 return;
Tom Sepezba038bc2015-10-08 12:03:00 -0700423 IJS_Context* pRuntimeContext = pRuntime->GetCurrentContext();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700424 CJS_Object* pJSObj =
Tom Sepez39bfe122015-09-17 15:25:23 -0700425 reinterpret_cast<CJS_Object*>(FXJS_GetPrivate(isolate, info.Holder()));
Tom Sepez2311b782015-02-23 10:22:51 -0800426 Alt* pObj = reinterpret_cast<Alt*>(pJSObj->GetEmbedObject());
427 v8::String::Utf8Value utf8_value(property);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700428 CFX_WideString propname =
429 CFX_WideString::FromUTF8(*utf8_value, utf8_value.length());
Tom Sepez3a832662015-03-02 12:59:05 -0800430 CFX_WideString sError;
Tom Sepez2311b782015-02-23 10:22:51 -0800431 if (!pObj->DelProperty(pRuntimeContext, propname.c_str(), sError)) {
432 CFX_ByteString cbName;
433 cbName.Format("%s.%s", class_name, "DelProperty");
Tom Sepez39bfe122015-09-17 15:25:23 -0700434 // Probably a missing call to JSFX_Error().
Tom Sepez2311b782015-02-23 10:22:51 -0800435 }
436}
437
Tom Sepezba038bc2015-10-08 12:03:00 -0700438template <FX_BOOL (*F)(IJS_Context* cc,
Tom Sepezcd56a7d2015-10-06 11:45:28 -0700439 const CJS_Parameters& params,
440 CJS_Value& vRet,
441 CFX_WideString& sError)>
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700442void JSGlobalFunc(const char* func_name_string,
Tom Sepeza1160452015-02-19 10:00:55 -0800443 const v8::FunctionCallbackInfo<v8::Value>& info) {
Tom Sepez67fd5df2015-10-08 12:24:19 -0700444 CJS_Runtime* pRuntime =
445 static_cast<CJS_Runtime*>(FXJS_GetRuntimeFromIsolate(info.GetIsolate()));
Tom Sepezbd7fabf2015-09-28 10:31:27 -0700446 if (!pRuntime)
Tom Sepeza25fd092015-09-28 09:06:03 -0700447 return;
Tom Sepezba038bc2015-10-08 12:03:00 -0700448 IJS_Context* pRuntimeContext = pRuntime->GetCurrentContext();
Tom Sepeza1160452015-02-19 10:00:55 -0800449 CJS_Parameters parameters;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700450 for (unsigned int i = 0; i < (unsigned int)info.Length(); i++) {
Tom Sepez67fd5df2015-10-08 12:24:19 -0700451 parameters.push_back(CJS_Value(pRuntime, info[i], CJS_Value::VT_unknown));
Tom Sepeza1160452015-02-19 10:00:55 -0800452 }
Tom Sepez67fd5df2015-10-08 12:24:19 -0700453 CJS_Value valueRes(pRuntime);
Tom Sepez3a832662015-03-02 12:59:05 -0800454 CFX_WideString sError;
455 if (!(*F)(pRuntimeContext, parameters, valueRes, sError)) {
Tom Sepez67fd5df2015-10-08 12:24:19 -0700456 FXJS_Error(pRuntime->GetIsolate(),
457 JSFormatErrorString(func_name_string, nullptr, sError));
Tom Sepeza1160452015-02-19 10:00:55 -0800458 return;
459 }
Tom Sepezf4ef3f92015-04-23 11:31:31 -0700460 info.GetReturnValue().Set(valueRes.ToV8Value());
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700461}
462
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700463#define JS_STATIC_GLOBAL_FUN(fun_name) \
464 static void fun_name##_static( \
465 const v8::FunctionCallbackInfo<v8::Value>& info) { \
466 JSGlobalFunc<fun_name>(#fun_name, info); \
Tom Sepeza1160452015-02-19 10:00:55 -0800467 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700468
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700469#define JS_STATIC_DECLARE_GLOBAL_FUN() \
470 static JSMethodSpec global_methods[]; \
Tom Sepez142165e2015-09-11 13:21:50 -0700471 static void DefineJSObjects(v8::Isolate* pIsolate)
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700472
473#define BEGIN_JS_STATIC_GLOBAL_FUN(js_class_name) \
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700474 JSMethodSpec js_class_name::global_methods[] = {
475#define JS_STATIC_GLOBAL_FUN_ENTRY(method_name) \
476 JS_STATIC_METHOD_ENTRY(method_name)
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700477
478#define END_JS_STATIC_GLOBAL_FUN() END_JS_STATIC_METHOD()
479
Tom Sepez39bfe122015-09-17 15:25:23 -0700480#define IMPLEMENT_JS_STATIC_GLOBAL_FUN(js_class_name) \
481 void js_class_name::DefineJSObjects(v8::Isolate* pIsolate) { \
Tom Sepezcd56a7d2015-10-06 11:45:28 -0700482 for (size_t i = 0; i < FX_ArraySize(global_methods) - 1; ++i) { \
Tom Sepez39bfe122015-09-17 15:25:23 -0700483 FXJS_DefineGlobalMethod(pIsolate, \
484 js_class_name::global_methods[i].pName, \
485 js_class_name::global_methods[i].pMethodCall); \
486 } \
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700487 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700488
Tom Sepez39bfe122015-09-17 15:25:23 -0700489CJS_Value::Type GET_VALUE_TYPE(v8::Local<v8::Value> p);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700490
Tom Sepez37458412015-10-06 11:33:46 -0700491#endif // FPDFSDK_SRC_JAVASCRIPT_JS_DEFINE_H_