blob: e120758c60f91bf666846da03cbbf7cdb2ae354a [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
Dan Sinclairf766ad22016-03-14 13:51:24 -04007#ifndef FPDFSDK_JAVASCRIPT_JS_DEFINE_H_
8#define FPDFSDK_JAVASCRIPT_JS_DEFINE_H_
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07009
Dan Sinclair3ebd1212016-03-09 09:59:23 -050010#include <vector>
11
Dan Sinclairf766ad22016-03-14 13:51:24 -040012#include "fpdfsdk/javascript/JS_Object.h"
13#include "fpdfsdk/javascript/JS_Value.h"
14#include "fpdfsdk/javascript/resource.h"
dsinclairb3f24672016-07-12 10:42:14 -070015#include "fxjs/include/fxjs_v8.h"
Tom Sepeza1160452015-02-19 10:00:55 -080016
Nico Weber9d8ec5a2015-08-04 13:00:21 -070017struct JSConstSpec {
18 const wchar_t* pName;
19 double number;
thestigfbe14b92016-05-02 13:31:10 -070020 const wchar_t* str;
Dan Sinclairf766ad22016-03-14 13:51:24 -040021 uint8_t t; // 0:double 1:str
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070022};
23
Nico Weber9d8ec5a2015-08-04 13:00:21 -070024struct JSPropertySpec {
25 const wchar_t* pName;
26 v8::AccessorGetterCallback pPropGet;
27 v8::AccessorSetterCallback pPropPut;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070028};
29
Nico Weber9d8ec5a2015-08-04 13:00:21 -070030struct JSMethodSpec {
31 const wchar_t* pName;
32 v8::FunctionCallback pMethodCall;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070033};
34
Nico Weber9d8ec5a2015-08-04 13:00:21 -070035#define JS_WIDESTRING(widestring) L## #widestring
Nico Weber9d8ec5a2015-08-04 13:00:21 -070036#define BEGIN_JS_STATIC_CONST(js_class_name) \
37 JSConstSpec js_class_name::JS_Class_Consts[] = {
38#define JS_STATIC_CONST_ENTRY_NUMBER(const_name, pValue) \
Nico Weber077f1a32015-08-06 15:08:57 -070039 { const_name, pValue, L"", 0 } \
Nico Weber9d8ec5a2015-08-04 13:00:21 -070040 ,
Tom Sepezcd56a7d2015-10-06 11:45:28 -070041
Nico Weber077f1a32015-08-06 15:08:57 -070042#define JS_STATIC_CONST_ENTRY_STRING(const_name, pValue) \
43 { const_name, 0, pValue, 1 } \
Nico Weber9d8ec5a2015-08-04 13:00:21 -070044 ,
Tom Sepezcd56a7d2015-10-06 11:45:28 -070045
Nico Weber9d8ec5a2015-08-04 13:00:21 -070046#define END_JS_STATIC_CONST() \
47 { 0, 0, 0, 0 } \
48 } \
Dan Sinclair50cce602016-02-24 09:51:16 -050049 ; // NOLINT
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070050
Nico Weber9d8ec5a2015-08-04 13:00:21 -070051#define BEGIN_JS_STATIC_PROP(js_class_name) \
52 JSPropertySpec js_class_name::JS_Class_Properties[] = {
thestigfbe14b92016-05-02 13:31:10 -070053#define JS_STATIC_PROP_ENTRY(prop_name) \
54 {JS_WIDESTRING(prop_name), get_##prop_name##_static, \
55 set_##prop_name##_static}, // NOLINT
Tom Sepezcd56a7d2015-10-06 11:45:28 -070056
Nico Weber9d8ec5a2015-08-04 13:00:21 -070057#define END_JS_STATIC_PROP() \
58 { 0, 0, 0 } \
59 } \
Dan Sinclair50cce602016-02-24 09:51:16 -050060 ; // NOLINT
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070061
Nico Weber9d8ec5a2015-08-04 13:00:21 -070062#define BEGIN_JS_STATIC_METHOD(js_class_name) \
63 JSMethodSpec js_class_name::JS_Class_Methods[] = {
64#define JS_STATIC_METHOD_ENTRY(method_name) \
65 { JS_WIDESTRING(method_name), method_name##_static } \
66 ,
Tom Sepezcd56a7d2015-10-06 11:45:28 -070067
Nico Weber9d8ec5a2015-08-04 13:00:21 -070068#define END_JS_STATIC_METHOD() \
69 { 0, 0 } \
70 } \
Dan Sinclair50cce602016-02-24 09:51:16 -050071 ; // NOLINT
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070072
Nico Weber9d8ec5a2015-08-04 13:00:21 -070073template <class C,
Tom Sepezba038bc2015-10-08 12:03:00 -070074 FX_BOOL (C::*M)(IJS_Context*, CJS_PropValue&, CFX_WideString&)>
Tom Sepeza1160452015-02-19 10:00:55 -080075void JSPropGetter(const char* prop_name_string,
76 const char* class_name_string,
77 v8::Local<v8::String> property,
78 const v8::PropertyCallbackInfo<v8::Value>& info) {
79 v8::Isolate* isolate = info.GetIsolate();
Tom Sepezb8ec0a32015-11-20 14:23:02 -080080 CJS_Runtime* pRuntime =
81 static_cast<CJS_Runtime*>(FXJS_GetRuntimeFromIsolate(isolate));
Tom Sepezbd7fabf2015-09-28 10:31:27 -070082 if (!pRuntime)
Tom Sepeza25fd092015-09-28 09:06:03 -070083 return;
Tom Sepezdfbf8e72015-10-14 14:17:26 -070084 IJS_Context* pContext = 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 Sepez67fd5df2015-10-08 12:24:19 -070088 CJS_PropValue value(pRuntime);
Tom Sepeza25fd092015-09-28 09:06:03 -070089 value.StartGetting();
Tom Sepezdfbf8e72015-10-14 14:17:26 -070090 if (!(pObj->*M)(pContext, 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 }
tsepezfbf52c22016-07-25 11:17:07 -070095 info.GetReturnValue().Set(value.ToV8Value());
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070096}
97
Nico Weber9d8ec5a2015-08-04 13:00:21 -070098template <class C,
Tom Sepezba038bc2015-10-08 12:03:00 -070099 FX_BOOL (C::*M)(IJS_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 Sepezb8ec0a32015-11-20 14:23:02 -0800106 CJS_Runtime* pRuntime =
107 static_cast<CJS_Runtime*>(FXJS_GetRuntimeFromIsolate(isolate));
Tom Sepezbd7fabf2015-09-28 10:31:27 -0700108 if (!pRuntime)
Tom Sepeza25fd092015-09-28 09:06:03 -0700109 return;
Tom Sepezdfbf8e72015-10-14 14:17:26 -0700110 IJS_Context* pContext = pRuntime->GetCurrentContext();
Tom Sepez39bfe122015-09-17 15:25:23 -0700111 CJS_Object* pJSObj = (CJS_Object*)FXJS_GetPrivate(isolate, info.Holder());
Tom Sepeza1160452015-02-19 10:00:55 -0800112 C* pObj = reinterpret_cast<C*>(pJSObj->GetEmbedObject());
Tom Sepez3a832662015-03-02 12:59:05 -0800113 CFX_WideString sError;
tsepez40faa792016-07-15 17:58:02 -0700114 CJS_PropValue propValue(CJS_Value(pRuntime, value));
Tom Sepeza25fd092015-09-28 09:06:03 -0700115 propValue.StartSetting();
Tom Sepezdfbf8e72015-10-14 14:17:26 -0700116 if (!(pObj->*M)(pContext, propValue, sError)) {
Tom Sepez39bfe122015-09-17 15:25:23 -0700117 FXJS_Error(isolate, JSFormatErrorString(class_name_string, prop_name_string,
118 sError));
Tom Sepeza1160452015-02-19 10:00:55 -0800119 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700120}
121
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700122#define JS_STATIC_PROP(prop_name, class_name) \
123 static void get_##prop_name##_static( \
124 v8::Local<v8::String> property, \
125 const v8::PropertyCallbackInfo<v8::Value>& info) { \
126 JSPropGetter<class_name, &class_name::prop_name>(#prop_name, #class_name, \
127 property, info); \
128 } \
129 static void set_##prop_name##_static( \
130 v8::Local<v8::String> property, v8::Local<v8::Value> value, \
131 const v8::PropertyCallbackInfo<void>& info) { \
132 JSPropSetter<class_name, &class_name::prop_name>(#prop_name, #class_name, \
133 property, value, info); \
Tom Sepeza1160452015-02-19 10:00:55 -0800134 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700135
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700136template <class C,
Tom Sepezba038bc2015-10-08 12:03:00 -0700137 FX_BOOL (C::*M)(IJS_Context*,
Lei Zhang945fdb72015-11-11 10:18:16 -0800138 const std::vector<CJS_Value>&,
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700139 CJS_Value&,
140 CFX_WideString&)>
Tom Sepeza1160452015-02-19 10:00:55 -0800141void JSMethod(const char* method_name_string,
142 const char* class_name_string,
143 const v8::FunctionCallbackInfo<v8::Value>& info) {
144 v8::Isolate* isolate = info.GetIsolate();
Tom Sepezb8ec0a32015-11-20 14:23:02 -0800145 CJS_Runtime* pRuntime =
146 static_cast<CJS_Runtime*>(FXJS_GetRuntimeFromIsolate(isolate));
Tom Sepezbd7fabf2015-09-28 10:31:27 -0700147 if (!pRuntime)
Tom Sepeza25fd092015-09-28 09:06:03 -0700148 return;
Tom Sepezdfbf8e72015-10-14 14:17:26 -0700149 IJS_Context* pContext = pRuntime->GetCurrentContext();
Lei Zhang945fdb72015-11-11 10:18:16 -0800150 std::vector<CJS_Value> parameters;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700151 for (unsigned int i = 0; i < (unsigned int)info.Length(); i++) {
tsepez40faa792016-07-15 17:58:02 -0700152 parameters.push_back(CJS_Value(pRuntime, info[i]));
Tom Sepeza1160452015-02-19 10:00:55 -0800153 }
Tom Sepez67fd5df2015-10-08 12:24:19 -0700154 CJS_Value valueRes(pRuntime);
Tom Sepez39bfe122015-09-17 15:25:23 -0700155 CJS_Object* pJSObj = (CJS_Object*)FXJS_GetPrivate(isolate, info.Holder());
Tom Sepeza1160452015-02-19 10:00:55 -0800156 C* pObj = reinterpret_cast<C*>(pJSObj->GetEmbedObject());
Tom Sepez3a832662015-03-02 12:59:05 -0800157 CFX_WideString sError;
Tom Sepezdfbf8e72015-10-14 14:17:26 -0700158 if (!(pObj->*M)(pContext, parameters, valueRes, sError)) {
Tom Sepez39bfe122015-09-17 15:25:23 -0700159 FXJS_Error(isolate, JSFormatErrorString(class_name_string,
160 method_name_string, sError));
Tom Sepeza1160452015-02-19 10:00:55 -0800161 return;
162 }
Tom Sepezf4ef3f92015-04-23 11:31:31 -0700163 info.GetReturnValue().Set(valueRes.ToV8Value());
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700164}
165
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700166#define JS_STATIC_METHOD(method_name, class_name) \
167 static void method_name##_static( \
168 const v8::FunctionCallbackInfo<v8::Value>& info) { \
169 JSMethod<class_name, &class_name::method_name>(#method_name, #class_name, \
170 info); \
Tom Sepeza1160452015-02-19 10:00:55 -0800171 }
172
173#define JS_SPECIAL_STATIC_METHOD(method_name, class_alternate, class_name) \
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700174 static void method_name##_static( \
175 const v8::FunctionCallbackInfo<v8::Value>& info) { \
176 JSMethod<class_alternate, &class_alternate::method_name>( \
177 #method_name, #class_name, info); \
Tom Sepeza1160452015-02-19 10:00:55 -0800178 }
179
Tom Sepezcd56a7d2015-10-06 11:45:28 -0700180// All JS classes have a name, an object defintion ID, and the ability to
181// register themselves with FXJS_V8. We never make a BASE class on its own
182// because it can't really do anything.
183#define DECLARE_JS_CLASS_BASE_PART() \
184 static const wchar_t* g_pClassName; \
185 static int g_nObjDefnID; \
186 static void DefineJSObjects(v8::Isolate* pIsolate, FXJSOBJTYPE eObjType);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700187
Tom Sepezcd56a7d2015-10-06 11:45:28 -0700188#define IMPLEMENT_JS_CLASS_BASE_PART(js_class_name, class_name) \
189 const wchar_t* js_class_name::g_pClassName = JS_WIDESTRING(class_name); \
190 int js_class_name::g_nObjDefnID = -1;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700191
Tom Sepezcd56a7d2015-10-06 11:45:28 -0700192// CONST classes provide constants, but not constructors, methods, or props.
193#define DECLARE_JS_CLASS_CONST() \
194 DECLARE_JS_CLASS_BASE_PART() \
195 DECLARE_JS_CLASS_CONST_PART()
196
197#define IMPLEMENT_JS_CLASS_CONST(js_class_name, class_name) \
198 IMPLEMENT_JS_CLASS_BASE_PART(js_class_name, class_name) \
199 IMPLEMENT_JS_CLASS_CONST_PART(js_class_name, class_name) \
200 void js_class_name::DefineJSObjects(v8::Isolate* pIsolate, \
201 FXJSOBJTYPE eObjType) { \
202 g_nObjDefnID = FXJS_DefineObj(pIsolate, js_class_name::g_pClassName, \
203 eObjType, nullptr, nullptr); \
204 DefineConsts(pIsolate); \
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700205 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700206
Tom Sepezcd56a7d2015-10-06 11:45:28 -0700207#define DECLARE_JS_CLASS_CONST_PART() \
208 static JSConstSpec JS_Class_Consts[]; \
209 static void DefineConsts(v8::Isolate* pIsolate);
210
thestigfbe14b92016-05-02 13:31:10 -0700211#define IMPLEMENT_JS_CLASS_CONST_PART(js_class_name, class_name) \
212 void js_class_name::DefineConsts(v8::Isolate* pIsolate) { \
213 for (size_t i = 0; i < FX_ArraySize(JS_Class_Consts) - 1; ++i) { \
214 FXJS_DefineObjConst( \
215 pIsolate, g_nObjDefnID, JS_Class_Consts[i].pName, \
216 JS_Class_Consts[i].t == 0 \
217 ? FXJS_NewNumber(pIsolate, JS_Class_Consts[i].number) \
218 : FXJS_NewString(pIsolate, JS_Class_Consts[i].str)); \
219 } \
Tom Sepezcd56a7d2015-10-06 11:45:28 -0700220 }
221
222// Convenience macros for declaring classes without an alternate.
223#define DECLARE_JS_CLASS() DECLARE_JS_CLASS_RICH()
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700224#define IMPLEMENT_JS_CLASS(js_class_name, class_name) \
225 IMPLEMENT_JS_CLASS_RICH(js_class_name, class_name, class_name)
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700226
Tom Sepezcd56a7d2015-10-06 11:45:28 -0700227// Rich JS classes provide constants, methods, properties, and the ability
228// to construct native object state.
229#define DECLARE_JS_CLASS_RICH() \
230 DECLARE_JS_CLASS_BASE_PART() \
231 DECLARE_JS_CLASS_CONST_PART() \
232 DECLARE_JS_CLASS_RICH_PART()
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700233
Tom Sepezcd56a7d2015-10-06 11:45:28 -0700234#define IMPLEMENT_JS_CLASS_RICH(js_class_name, class_alternate, class_name) \
235 IMPLEMENT_JS_CLASS_BASE_PART(js_class_name, class_name) \
236 IMPLEMENT_JS_CLASS_CONST_PART(js_class_name, class_name) \
237 IMPLEMENT_JS_CLASS_RICH_PART(js_class_name, class_alternate, class_name) \
238 void js_class_name::DefineJSObjects(v8::Isolate* pIsolate, \
239 FXJSOBJTYPE eObjType) { \
240 g_nObjDefnID = FXJS_DefineObj(pIsolate, js_class_name::g_pClassName, \
241 eObjType, JSConstructor, JSDestructor); \
242 DefineConsts(pIsolate); \
243 DefineProps(pIsolate); \
244 DefineMethods(pIsolate); \
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700245 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700246
Tom Sepez33420902015-10-13 15:00:10 -0700247#define DECLARE_JS_CLASS_RICH_PART() \
248 static void JSConstructor(IJS_Runtime* pRuntime, v8::Local<v8::Object> obj); \
249 static void JSDestructor(v8::Local<v8::Object> obj); \
250 static void DefineProps(v8::Isolate* pIsoalte); \
251 static void DefineMethods(v8::Isolate* pIsoalte); \
252 static JSPropertySpec JS_Class_Properties[]; \
Tom Sepezcd56a7d2015-10-06 11:45:28 -0700253 static JSMethodSpec JS_Class_Methods[];
254
255#define IMPLEMENT_JS_CLASS_RICH_PART(js_class_name, class_alternate, \
256 class_name) \
Tom Sepez33420902015-10-13 15:00:10 -0700257 void js_class_name::JSConstructor(IJS_Runtime* pIRuntime, \
Tom Sepez7fed2e72015-10-07 13:09:38 -0700258 v8::Local<v8::Object> obj) { \
Tom Sepezcd56a7d2015-10-06 11:45:28 -0700259 CJS_Object* pObj = new js_class_name(obj); \
260 pObj->SetEmbedObject(new class_alternate(pObj)); \
261 FXJS_SetPrivate(nullptr, obj, (void*)pObj); \
Tom Sepez33420902015-10-13 15:00:10 -0700262 pObj->InitInstance(pIRuntime); \
Tom Sepezcd56a7d2015-10-06 11:45:28 -0700263 } \
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);
tsepez6fe7d212016-04-06 10:51:14 -0700354 CFX_WideString propname = CFX_WideString::FromUTF8(
355 CFX_ByteStringC(*utf8_value, utf8_value.length()));
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700356 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 Sepezb8ec0a32015-11-20 14:23:02 -0800368 CJS_Runtime* pRuntime =
369 static_cast<CJS_Runtime*>(FXJS_GetRuntimeFromIsolate(isolate));
Tom Sepezbd7fabf2015-09-28 10:31:27 -0700370 if (!pRuntime)
Tom Sepeza25fd092015-09-28 09:06:03 -0700371 return;
Tom Sepezdfbf8e72015-10-14 14:17:26 -0700372 IJS_Context* pContext = pRuntime->GetCurrentContext();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700373 CJS_Object* pJSObj =
Tom Sepez39bfe122015-09-17 15:25:23 -0700374 reinterpret_cast<CJS_Object*>(FXJS_GetPrivate(isolate, info.Holder()));
Tom Sepez2311b782015-02-23 10:22:51 -0800375 Alt* pObj = reinterpret_cast<Alt*>(pJSObj->GetEmbedObject());
376 v8::String::Utf8Value utf8_value(property);
tsepez6fe7d212016-04-06 10:51:14 -0700377 CFX_WideString propname = CFX_WideString::FromUTF8(
378 CFX_ByteStringC(*utf8_value, utf8_value.length()));
Tom Sepez3a832662015-03-02 12:59:05 -0800379 CFX_WideString sError;
Tom Sepez67fd5df2015-10-08 12:24:19 -0700380 CJS_PropValue value(pRuntime);
Tom Sepez2311b782015-02-23 10:22:51 -0800381 value.StartGetting();
Tom Sepezdfbf8e72015-10-14 14:17:26 -0700382 if (!pObj->DoProperty(pContext, propname.c_str(), value, sError)) {
Tom Sepez39bfe122015-09-17 15:25:23 -0700383 FXJS_Error(isolate, JSFormatErrorString(class_name, "GetProperty", sError));
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700384 return;
Tom Sepez2311b782015-02-23 10:22:51 -0800385 }
tsepezfbf52c22016-07-25 11:17:07 -0700386 info.GetReturnValue().Set(value.ToV8Value());
Tom Sepez2311b782015-02-23 10:22:51 -0800387}
388
389template <class Alt>
390void JSSpecialPropPut(const char* class_name,
391 v8::Local<v8::String> property,
392 v8::Local<v8::Value> value,
393 const v8::PropertyCallbackInfo<v8::Value>& info) {
394 v8::Isolate* isolate = info.GetIsolate();
Tom Sepezb8ec0a32015-11-20 14:23:02 -0800395 CJS_Runtime* pRuntime =
396 static_cast<CJS_Runtime*>(FXJS_GetRuntimeFromIsolate(isolate));
Tom Sepezbd7fabf2015-09-28 10:31:27 -0700397 if (!pRuntime)
Tom Sepeza25fd092015-09-28 09:06:03 -0700398 return;
Tom Sepezdfbf8e72015-10-14 14:17:26 -0700399 IJS_Context* pContext = pRuntime->GetCurrentContext();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700400 CJS_Object* pJSObj =
Tom Sepez39bfe122015-09-17 15:25:23 -0700401 reinterpret_cast<CJS_Object*>(FXJS_GetPrivate(isolate, info.Holder()));
Tom Sepez2311b782015-02-23 10:22:51 -0800402 Alt* pObj = reinterpret_cast<Alt*>(pJSObj->GetEmbedObject());
403 v8::String::Utf8Value utf8_value(property);
tsepez6fe7d212016-04-06 10:51:14 -0700404 CFX_WideString propname = CFX_WideString::FromUTF8(
405 CFX_ByteStringC(*utf8_value, utf8_value.length()));
Tom Sepez3a832662015-03-02 12:59:05 -0800406 CFX_WideString sError;
tsepez40faa792016-07-15 17:58:02 -0700407 CJS_PropValue PropValue(CJS_Value(pRuntime, value));
Tom Sepez2311b782015-02-23 10:22:51 -0800408 PropValue.StartSetting();
Tom Sepezdfbf8e72015-10-14 14:17:26 -0700409 if (!pObj->DoProperty(pContext, propname.c_str(), PropValue, sError)) {
Tom Sepez39bfe122015-09-17 15:25:23 -0700410 FXJS_Error(isolate, JSFormatErrorString(class_name, "PutProperty", sError));
Tom Sepez2311b782015-02-23 10:22:51 -0800411 }
412}
413
414template <class Alt>
415void JSSpecialPropDel(const char* class_name,
416 v8::Local<v8::String> property,
417 const v8::PropertyCallbackInfo<v8::Boolean>& info) {
418 v8::Isolate* isolate = info.GetIsolate();
Tom Sepezb8ec0a32015-11-20 14:23:02 -0800419 IJS_Runtime* pRuntime = FXJS_GetRuntimeFromIsolate(isolate);
Tom Sepezbd7fabf2015-09-28 10:31:27 -0700420 if (!pRuntime)
Tom Sepeza25fd092015-09-28 09:06:03 -0700421 return;
Tom Sepezdfbf8e72015-10-14 14:17:26 -0700422 IJS_Context* pContext = pRuntime->GetCurrentContext();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700423 CJS_Object* pJSObj =
Tom Sepez39bfe122015-09-17 15:25:23 -0700424 reinterpret_cast<CJS_Object*>(FXJS_GetPrivate(isolate, info.Holder()));
Tom Sepez2311b782015-02-23 10:22:51 -0800425 Alt* pObj = reinterpret_cast<Alt*>(pJSObj->GetEmbedObject());
426 v8::String::Utf8Value utf8_value(property);
tsepez6fe7d212016-04-06 10:51:14 -0700427 CFX_WideString propname = CFX_WideString::FromUTF8(
428 CFX_ByteStringC(*utf8_value, utf8_value.length()));
Tom Sepez3a832662015-03-02 12:59:05 -0800429 CFX_WideString sError;
Tom Sepezdfbf8e72015-10-14 14:17:26 -0700430 if (!pObj->DelProperty(pContext, propname.c_str(), sError)) {
Tom Sepez2311b782015-02-23 10:22:51 -0800431 CFX_ByteString cbName;
432 cbName.Format("%s.%s", class_name, "DelProperty");
Tom Sepez39bfe122015-09-17 15:25:23 -0700433 // Probably a missing call to JSFX_Error().
Tom Sepez2311b782015-02-23 10:22:51 -0800434 }
435}
436
Lei Zhang945fdb72015-11-11 10:18:16 -0800437template <FX_BOOL (*F)(IJS_Context*,
438 const std::vector<CJS_Value>&,
439 CJS_Value&,
440 CFX_WideString&)>
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700441void JSGlobalFunc(const char* func_name_string,
Tom Sepeza1160452015-02-19 10:00:55 -0800442 const v8::FunctionCallbackInfo<v8::Value>& info) {
Tom Sepezb8ec0a32015-11-20 14:23:02 -0800443 CJS_Runtime* pRuntime =
444 static_cast<CJS_Runtime*>(FXJS_GetRuntimeFromIsolate(info.GetIsolate()));
Tom Sepezbd7fabf2015-09-28 10:31:27 -0700445 if (!pRuntime)
Tom Sepeza25fd092015-09-28 09:06:03 -0700446 return;
Tom Sepezdfbf8e72015-10-14 14:17:26 -0700447 IJS_Context* pContext = pRuntime->GetCurrentContext();
Lei Zhang945fdb72015-11-11 10:18:16 -0800448 std::vector<CJS_Value> parameters;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700449 for (unsigned int i = 0; i < (unsigned int)info.Length(); i++) {
tsepez40faa792016-07-15 17:58:02 -0700450 parameters.push_back(CJS_Value(pRuntime, info[i]));
Tom Sepeza1160452015-02-19 10:00:55 -0800451 }
Tom Sepez67fd5df2015-10-08 12:24:19 -0700452 CJS_Value valueRes(pRuntime);
Tom Sepez3a832662015-03-02 12:59:05 -0800453 CFX_WideString sError;
Tom Sepezdfbf8e72015-10-14 14:17:26 -0700454 if (!(*F)(pContext, parameters, valueRes, sError)) {
Tom Sepez67fd5df2015-10-08 12:24:19 -0700455 FXJS_Error(pRuntime->GetIsolate(),
456 JSFormatErrorString(func_name_string, nullptr, sError));
Tom Sepeza1160452015-02-19 10:00:55 -0800457 return;
458 }
Tom Sepezf4ef3f92015-04-23 11:31:31 -0700459 info.GetReturnValue().Set(valueRes.ToV8Value());
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700460}
461
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700462#define JS_STATIC_GLOBAL_FUN(fun_name) \
463 static void fun_name##_static( \
464 const v8::FunctionCallbackInfo<v8::Value>& info) { \
465 JSGlobalFunc<fun_name>(#fun_name, info); \
Tom Sepeza1160452015-02-19 10:00:55 -0800466 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700467
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700468#define JS_STATIC_DECLARE_GLOBAL_FUN() \
469 static JSMethodSpec global_methods[]; \
Tom Sepez142165e2015-09-11 13:21:50 -0700470 static void DefineJSObjects(v8::Isolate* pIsolate)
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700471
472#define BEGIN_JS_STATIC_GLOBAL_FUN(js_class_name) \
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700473 JSMethodSpec js_class_name::global_methods[] = {
474#define JS_STATIC_GLOBAL_FUN_ENTRY(method_name) \
475 JS_STATIC_METHOD_ENTRY(method_name)
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700476
477#define END_JS_STATIC_GLOBAL_FUN() END_JS_STATIC_METHOD()
478
Tom Sepez39bfe122015-09-17 15:25:23 -0700479#define IMPLEMENT_JS_STATIC_GLOBAL_FUN(js_class_name) \
480 void js_class_name::DefineJSObjects(v8::Isolate* pIsolate) { \
Tom Sepezcd56a7d2015-10-06 11:45:28 -0700481 for (size_t i = 0; i < FX_ArraySize(global_methods) - 1; ++i) { \
Tom Sepez39bfe122015-09-17 15:25:23 -0700482 FXJS_DefineGlobalMethod(pIsolate, \
483 js_class_name::global_methods[i].pName, \
484 js_class_name::global_methods[i].pMethodCall); \
485 } \
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700486 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700487
Dan Sinclairf766ad22016-03-14 13:51:24 -0400488#endif // FPDFSDK_JAVASCRIPT_JS_DEFINE_H_