blob: c7872599bf8f54baa815dae3792e0548043769b7 [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"
dsinclair89bdd082016-04-06 10:47:54 -070015#include "fpdfsdk/jsapi/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;
Dan Sinclair3ebd1212016-03-09 09:59:23 -050020 const wchar_t* string; // NOLINT
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[] = {
Dan Sinclairf766ad22016-03-14 13:51:24 -040053#define JS_STATIC_PROP_ENTRY(prop_name) \
54 { \
Tom Sepez37458412015-10-06 11:33:46 -070055 JS_WIDESTRING(prop_name), get_##prop_name##_static, \
Dan Sinclairf766ad22016-03-14 13:51:24 -040056 set_##prop_name##_static \
57 } \
Nico Weber9d8ec5a2015-08-04 13:00:21 -070058 ,
Tom Sepezcd56a7d2015-10-06 11:45:28 -070059
Nico Weber9d8ec5a2015-08-04 13:00:21 -070060#define END_JS_STATIC_PROP() \
61 { 0, 0, 0 } \
62 } \
Dan Sinclair50cce602016-02-24 09:51:16 -050063 ; // NOLINT
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070064
Nico Weber9d8ec5a2015-08-04 13:00:21 -070065#define BEGIN_JS_STATIC_METHOD(js_class_name) \
66 JSMethodSpec js_class_name::JS_Class_Methods[] = {
67#define JS_STATIC_METHOD_ENTRY(method_name) \
68 { JS_WIDESTRING(method_name), method_name##_static } \
69 ,
Tom Sepezcd56a7d2015-10-06 11:45:28 -070070
Nico Weber9d8ec5a2015-08-04 13:00:21 -070071#define END_JS_STATIC_METHOD() \
72 { 0, 0 } \
73 } \
Dan Sinclair50cce602016-02-24 09:51:16 -050074 ; // NOLINT
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070075
Nico Weber9d8ec5a2015-08-04 13:00:21 -070076template <class C,
Tom Sepezba038bc2015-10-08 12:03:00 -070077 FX_BOOL (C::*M)(IJS_Context*, CJS_PropValue&, CFX_WideString&)>
Tom Sepeza1160452015-02-19 10:00:55 -080078void JSPropGetter(const char* prop_name_string,
79 const char* class_name_string,
80 v8::Local<v8::String> property,
81 const v8::PropertyCallbackInfo<v8::Value>& info) {
82 v8::Isolate* isolate = info.GetIsolate();
Tom Sepezb8ec0a32015-11-20 14:23:02 -080083 CJS_Runtime* pRuntime =
84 static_cast<CJS_Runtime*>(FXJS_GetRuntimeFromIsolate(isolate));
Tom Sepezbd7fabf2015-09-28 10:31:27 -070085 if (!pRuntime)
Tom Sepeza25fd092015-09-28 09:06:03 -070086 return;
Tom Sepezdfbf8e72015-10-14 14:17:26 -070087 IJS_Context* pContext = pRuntime->GetCurrentContext();
Tom Sepez39bfe122015-09-17 15:25:23 -070088 CJS_Object* pJSObj = (CJS_Object*)FXJS_GetPrivate(isolate, info.Holder());
Tom Sepeza1160452015-02-19 10:00:55 -080089 C* pObj = reinterpret_cast<C*>(pJSObj->GetEmbedObject());
Tom Sepez3a832662015-03-02 12:59:05 -080090 CFX_WideString sError;
Tom Sepez67fd5df2015-10-08 12:24:19 -070091 CJS_PropValue value(pRuntime);
Tom Sepeza25fd092015-09-28 09:06:03 -070092 value.StartGetting();
Tom Sepezdfbf8e72015-10-14 14:17:26 -070093 if (!(pObj->*M)(pContext, value, sError)) {
Tom Sepez39bfe122015-09-17 15:25:23 -070094 FXJS_Error(isolate, JSFormatErrorString(class_name_string, prop_name_string,
95 sError));
Tom Sepeza1160452015-02-19 10:00:55 -080096 return;
97 }
Jochen Eisingerdfa2c992015-05-19 00:38:00 +020098 info.GetReturnValue().Set((v8::Local<v8::Value>)value);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070099}
100
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700101template <class C,
Tom Sepezba038bc2015-10-08 12:03:00 -0700102 FX_BOOL (C::*M)(IJS_Context*, CJS_PropValue&, CFX_WideString&)>
Tom Sepeza1160452015-02-19 10:00:55 -0800103void JSPropSetter(const char* prop_name_string,
104 const char* class_name_string,
105 v8::Local<v8::String> property,
106 v8::Local<v8::Value> value,
107 const v8::PropertyCallbackInfo<void>& info) {
108 v8::Isolate* isolate = info.GetIsolate();
Tom Sepezb8ec0a32015-11-20 14:23:02 -0800109 CJS_Runtime* pRuntime =
110 static_cast<CJS_Runtime*>(FXJS_GetRuntimeFromIsolate(isolate));
Tom Sepezbd7fabf2015-09-28 10:31:27 -0700111 if (!pRuntime)
Tom Sepeza25fd092015-09-28 09:06:03 -0700112 return;
Tom Sepezdfbf8e72015-10-14 14:17:26 -0700113 IJS_Context* pContext = pRuntime->GetCurrentContext();
Tom Sepez39bfe122015-09-17 15:25:23 -0700114 CJS_Object* pJSObj = (CJS_Object*)FXJS_GetPrivate(isolate, info.Holder());
Tom Sepeza1160452015-02-19 10:00:55 -0800115 C* pObj = reinterpret_cast<C*>(pJSObj->GetEmbedObject());
Tom Sepez3a832662015-03-02 12:59:05 -0800116 CFX_WideString sError;
Tom Sepez67fd5df2015-10-08 12:24:19 -0700117 CJS_PropValue propValue(CJS_Value(pRuntime, value, CJS_Value::VT_unknown));
Tom Sepeza25fd092015-09-28 09:06:03 -0700118 propValue.StartSetting();
Tom Sepezdfbf8e72015-10-14 14:17:26 -0700119 if (!(pObj->*M)(pContext, propValue, sError)) {
Tom Sepez39bfe122015-09-17 15:25:23 -0700120 FXJS_Error(isolate, JSFormatErrorString(class_name_string, prop_name_string,
121 sError));
Tom Sepeza1160452015-02-19 10:00:55 -0800122 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700123}
124
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700125#define JS_STATIC_PROP(prop_name, class_name) \
126 static void get_##prop_name##_static( \
127 v8::Local<v8::String> property, \
128 const v8::PropertyCallbackInfo<v8::Value>& info) { \
129 JSPropGetter<class_name, &class_name::prop_name>(#prop_name, #class_name, \
130 property, info); \
131 } \
132 static void set_##prop_name##_static( \
133 v8::Local<v8::String> property, v8::Local<v8::Value> value, \
134 const v8::PropertyCallbackInfo<void>& info) { \
135 JSPropSetter<class_name, &class_name::prop_name>(#prop_name, #class_name, \
136 property, value, info); \
Tom Sepeza1160452015-02-19 10:00:55 -0800137 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700138
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700139template <class C,
Tom Sepezba038bc2015-10-08 12:03:00 -0700140 FX_BOOL (C::*M)(IJS_Context*,
Lei Zhang945fdb72015-11-11 10:18:16 -0800141 const std::vector<CJS_Value>&,
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700142 CJS_Value&,
143 CFX_WideString&)>
Tom Sepeza1160452015-02-19 10:00:55 -0800144void JSMethod(const char* method_name_string,
145 const char* class_name_string,
146 const v8::FunctionCallbackInfo<v8::Value>& info) {
147 v8::Isolate* isolate = info.GetIsolate();
Tom Sepezb8ec0a32015-11-20 14:23:02 -0800148 CJS_Runtime* pRuntime =
149 static_cast<CJS_Runtime*>(FXJS_GetRuntimeFromIsolate(isolate));
Tom Sepezbd7fabf2015-09-28 10:31:27 -0700150 if (!pRuntime)
Tom Sepeza25fd092015-09-28 09:06:03 -0700151 return;
Tom Sepezdfbf8e72015-10-14 14:17:26 -0700152 IJS_Context* pContext = pRuntime->GetCurrentContext();
Lei Zhang945fdb72015-11-11 10:18:16 -0800153 std::vector<CJS_Value> parameters;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700154 for (unsigned int i = 0; i < (unsigned int)info.Length(); i++) {
Tom Sepez67fd5df2015-10-08 12:24:19 -0700155 parameters.push_back(CJS_Value(pRuntime, info[i], CJS_Value::VT_unknown));
Tom Sepeza1160452015-02-19 10:00:55 -0800156 }
Tom Sepez67fd5df2015-10-08 12:24:19 -0700157 CJS_Value valueRes(pRuntime);
Tom Sepez39bfe122015-09-17 15:25:23 -0700158 CJS_Object* pJSObj = (CJS_Object*)FXJS_GetPrivate(isolate, info.Holder());
Tom Sepeza1160452015-02-19 10:00:55 -0800159 C* pObj = reinterpret_cast<C*>(pJSObj->GetEmbedObject());
Tom Sepez3a832662015-03-02 12:59:05 -0800160 CFX_WideString sError;
Tom Sepezdfbf8e72015-10-14 14:17:26 -0700161 if (!(pObj->*M)(pContext, parameters, valueRes, sError)) {
Tom Sepez39bfe122015-09-17 15:25:23 -0700162 FXJS_Error(isolate, JSFormatErrorString(class_name_string,
163 method_name_string, sError));
Tom Sepeza1160452015-02-19 10:00:55 -0800164 return;
165 }
Tom Sepezf4ef3f92015-04-23 11:31:31 -0700166 info.GetReturnValue().Set(valueRes.ToV8Value());
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700167}
168
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700169#define JS_STATIC_METHOD(method_name, class_name) \
170 static void method_name##_static( \
171 const v8::FunctionCallbackInfo<v8::Value>& info) { \
172 JSMethod<class_name, &class_name::method_name>(#method_name, #class_name, \
173 info); \
Tom Sepeza1160452015-02-19 10:00:55 -0800174 }
175
176#define JS_SPECIAL_STATIC_METHOD(method_name, class_alternate, class_name) \
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700177 static void method_name##_static( \
178 const v8::FunctionCallbackInfo<v8::Value>& info) { \
179 JSMethod<class_alternate, &class_alternate::method_name>( \
180 #method_name, #class_name, info); \
Tom Sepeza1160452015-02-19 10:00:55 -0800181 }
182
Tom Sepezcd56a7d2015-10-06 11:45:28 -0700183// All JS classes have a name, an object defintion ID, and the ability to
184// register themselves with FXJS_V8. We never make a BASE class on its own
185// because it can't really do anything.
186#define DECLARE_JS_CLASS_BASE_PART() \
187 static const wchar_t* g_pClassName; \
188 static int g_nObjDefnID; \
189 static void DefineJSObjects(v8::Isolate* pIsolate, FXJSOBJTYPE eObjType);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700190
Tom Sepezcd56a7d2015-10-06 11:45:28 -0700191#define IMPLEMENT_JS_CLASS_BASE_PART(js_class_name, class_name) \
192 const wchar_t* js_class_name::g_pClassName = JS_WIDESTRING(class_name); \
193 int js_class_name::g_nObjDefnID = -1;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700194
Tom Sepezcd56a7d2015-10-06 11:45:28 -0700195// CONST classes provide constants, but not constructors, methods, or props.
196#define DECLARE_JS_CLASS_CONST() \
197 DECLARE_JS_CLASS_BASE_PART() \
198 DECLARE_JS_CLASS_CONST_PART()
199
200#define IMPLEMENT_JS_CLASS_CONST(js_class_name, class_name) \
201 IMPLEMENT_JS_CLASS_BASE_PART(js_class_name, class_name) \
202 IMPLEMENT_JS_CLASS_CONST_PART(js_class_name, class_name) \
203 void js_class_name::DefineJSObjects(v8::Isolate* pIsolate, \
204 FXJSOBJTYPE eObjType) { \
205 g_nObjDefnID = FXJS_DefineObj(pIsolate, js_class_name::g_pClassName, \
206 eObjType, nullptr, nullptr); \
207 DefineConsts(pIsolate); \
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700208 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700209
Tom Sepezcd56a7d2015-10-06 11:45:28 -0700210#define DECLARE_JS_CLASS_CONST_PART() \
211 static JSConstSpec JS_Class_Consts[]; \
212 static void DefineConsts(v8::Isolate* pIsolate);
213
214#define IMPLEMENT_JS_CLASS_CONST_PART(js_class_name, class_name) \
215 void js_class_name::DefineConsts(v8::Isolate* pIsolate) { \
216 for (size_t i = 0; i < FX_ArraySize(JS_Class_Consts) - 1; ++i) { \
217 FXJS_DefineObjConst( \
218 pIsolate, g_nObjDefnID, JS_Class_Consts[i].pName, \
219 JS_Class_Consts[i].t == 0 \
220 ? FXJS_NewNumber(pIsolate, JS_Class_Consts[i].number) \
221 : FXJS_NewString(pIsolate, JS_Class_Consts[i].string)); \
222 } \
223 }
224
225// Convenience macros for declaring classes without an alternate.
226#define DECLARE_JS_CLASS() DECLARE_JS_CLASS_RICH()
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700227#define IMPLEMENT_JS_CLASS(js_class_name, class_name) \
228 IMPLEMENT_JS_CLASS_RICH(js_class_name, class_name, class_name)
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700229
Tom Sepezcd56a7d2015-10-06 11:45:28 -0700230// Rich JS classes provide constants, methods, properties, and the ability
231// to construct native object state.
232#define DECLARE_JS_CLASS_RICH() \
233 DECLARE_JS_CLASS_BASE_PART() \
234 DECLARE_JS_CLASS_CONST_PART() \
235 DECLARE_JS_CLASS_RICH_PART()
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700236
Tom Sepezcd56a7d2015-10-06 11:45:28 -0700237#define IMPLEMENT_JS_CLASS_RICH(js_class_name, class_alternate, class_name) \
238 IMPLEMENT_JS_CLASS_BASE_PART(js_class_name, class_name) \
239 IMPLEMENT_JS_CLASS_CONST_PART(js_class_name, class_name) \
240 IMPLEMENT_JS_CLASS_RICH_PART(js_class_name, class_alternate, class_name) \
241 void js_class_name::DefineJSObjects(v8::Isolate* pIsolate, \
242 FXJSOBJTYPE eObjType) { \
243 g_nObjDefnID = FXJS_DefineObj(pIsolate, js_class_name::g_pClassName, \
244 eObjType, JSConstructor, JSDestructor); \
245 DefineConsts(pIsolate); \
246 DefineProps(pIsolate); \
247 DefineMethods(pIsolate); \
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700248 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700249
Tom Sepez33420902015-10-13 15:00:10 -0700250#define DECLARE_JS_CLASS_RICH_PART() \
251 static void JSConstructor(IJS_Runtime* pRuntime, v8::Local<v8::Object> obj); \
252 static void JSDestructor(v8::Local<v8::Object> obj); \
253 static void DefineProps(v8::Isolate* pIsoalte); \
254 static void DefineMethods(v8::Isolate* pIsoalte); \
255 static JSPropertySpec JS_Class_Properties[]; \
Tom Sepezcd56a7d2015-10-06 11:45:28 -0700256 static JSMethodSpec JS_Class_Methods[];
257
258#define IMPLEMENT_JS_CLASS_RICH_PART(js_class_name, class_alternate, \
259 class_name) \
Tom Sepez33420902015-10-13 15:00:10 -0700260 void js_class_name::JSConstructor(IJS_Runtime* pIRuntime, \
Tom Sepez7fed2e72015-10-07 13:09:38 -0700261 v8::Local<v8::Object> obj) { \
Tom Sepezcd56a7d2015-10-06 11:45:28 -0700262 CJS_Object* pObj = new js_class_name(obj); \
263 pObj->SetEmbedObject(new class_alternate(pObj)); \
264 FXJS_SetPrivate(nullptr, obj, (void*)pObj); \
Tom Sepez33420902015-10-13 15:00:10 -0700265 pObj->InitInstance(pIRuntime); \
Tom Sepezcd56a7d2015-10-06 11:45:28 -0700266 } \
267 void js_class_name::JSDestructor(v8::Local<v8::Object> obj) { \
268 js_class_name* pObj = (js_class_name*)FXJS_GetPrivate(nullptr, obj); \
269 pObj->ExitInstance(); \
270 delete pObj; \
271 } \
272 void js_class_name::DefineProps(v8::Isolate* pIsolate) { \
273 for (size_t i = 0; i < FX_ArraySize(JS_Class_Properties) - 1; ++i) { \
274 FXJS_DefineObjProperty( \
275 pIsolate, g_nObjDefnID, JS_Class_Properties[i].pName, \
276 JS_Class_Properties[i].pPropGet, JS_Class_Properties[i].pPropPut); \
277 } \
278 } \
279 void js_class_name::DefineMethods(v8::Isolate* pIsolate) { \
280 for (size_t i = 0; i < FX_ArraySize(JS_Class_Methods) - 1; ++i) { \
281 FXJS_DefineObjMethod(pIsolate, g_nObjDefnID, JS_Class_Methods[i].pName, \
282 JS_Class_Methods[i].pMethodCall); \
283 } \
284 }
285
286// Special JS classes implement methods, props, and queries, but not consts.
287#define DECLARE_SPECIAL_JS_CLASS() \
288 DECLARE_JS_CLASS_BASE_PART() \
289 DECLARE_JS_CLASS_CONST_PART() \
290 DECLARE_JS_CLASS_RICH_PART() \
291 DECLARE_SPECIAL_JS_CLASS_PART()
292
293#define IMPLEMENT_SPECIAL_JS_CLASS(js_class_name, class_alternate, class_name) \
294 IMPLEMENT_JS_CLASS_BASE_PART(js_class_name, class_name) \
295 IMPLEMENT_JS_CLASS_CONST_PART(js_class_name, class_name) \
296 IMPLEMENT_JS_CLASS_RICH_PART(js_class_name, class_alternate, class_name) \
297 IMPLEMENT_SPECIAL_JS_CLASS_PART(js_class_name, class_alternate, class_name) \
298 void js_class_name::DefineJSObjects(v8::Isolate* pIsolate, \
299 FXJSOBJTYPE eObjType) { \
300 g_nObjDefnID = FXJS_DefineObj(pIsolate, js_class_name::g_pClassName, \
301 eObjType, JSConstructor, JSDestructor); \
302 DefineConsts(pIsolate); \
303 DefineProps(pIsolate); \
304 DefineMethods(pIsolate); \
305 DefineAllProperties(pIsolate); \
306 }
307
308#define DECLARE_SPECIAL_JS_CLASS_PART() \
309 static void queryprop_static( \
310 v8::Local<v8::String> property, \
311 const v8::PropertyCallbackInfo<v8::Integer>& info); \
312 static void getprop_static(v8::Local<v8::String> property, \
313 const v8::PropertyCallbackInfo<v8::Value>& info); \
314 static void putprop_static(v8::Local<v8::String> property, \
315 v8::Local<v8::Value> value, \
316 const v8::PropertyCallbackInfo<v8::Value>& info); \
317 static void delprop_static( \
318 v8::Local<v8::String> property, \
319 const v8::PropertyCallbackInfo<v8::Boolean>& info); \
320 static void DefineAllProperties(v8::Isolate* pIsolate);
321
322#define IMPLEMENT_SPECIAL_JS_CLASS_PART(js_class_name, class_alternate, \
323 class_name) \
324 void js_class_name::queryprop_static( \
325 v8::Local<v8::String> property, \
326 const v8::PropertyCallbackInfo<v8::Integer>& info) { \
327 JSSpecialPropQuery<class_alternate>(#class_name, property, info); \
328 } \
329 void js_class_name::getprop_static( \
330 v8::Local<v8::String> property, \
331 const v8::PropertyCallbackInfo<v8::Value>& info) { \
332 JSSpecialPropGet<class_alternate>(#class_name, property, info); \
333 } \
334 void js_class_name::putprop_static( \
335 v8::Local<v8::String> property, v8::Local<v8::Value> value, \
336 const v8::PropertyCallbackInfo<v8::Value>& info) { \
337 JSSpecialPropPut<class_alternate>(#class_name, property, value, info); \
338 } \
339 void js_class_name::delprop_static( \
340 v8::Local<v8::String> property, \
341 const v8::PropertyCallbackInfo<v8::Boolean>& info) { \
342 JSSpecialPropDel<class_alternate>(#class_name, property, info); \
343 } \
344 void js_class_name::DefineAllProperties(v8::Isolate* pIsolate) { \
345 FXJS_DefineObjAllProperties( \
346 pIsolate, g_nObjDefnID, js_class_name::queryprop_static, \
347 js_class_name::getprop_static, js_class_name::putprop_static, \
348 js_class_name::delprop_static); \
349 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700350
Tom Sepez2311b782015-02-23 10:22:51 -0800351template <class Alt>
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700352void JSSpecialPropQuery(const char*,
353 v8::Local<v8::String> property,
354 const v8::PropertyCallbackInfo<v8::Integer>& info) {
Tom Sepez2311b782015-02-23 10:22:51 -0800355 v8::Isolate* isolate = info.GetIsolate();
356 v8::String::Utf8Value utf8_value(property);
tsepez6fe7d212016-04-06 10:51:14 -0700357 CFX_WideString propname = CFX_WideString::FromUTF8(
358 CFX_ByteStringC(*utf8_value, utf8_value.length()));
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700359 CJS_Object* pJSObj =
Tom Sepez39bfe122015-09-17 15:25:23 -0700360 reinterpret_cast<CJS_Object*>(FXJS_GetPrivate(isolate, info.Holder()));
Tom Sepez2311b782015-02-23 10:22:51 -0800361 Alt* pObj = reinterpret_cast<Alt*>(pJSObj->GetEmbedObject());
362 FX_BOOL bRet = pObj->QueryProperty(propname.c_str());
363 info.GetReturnValue().Set(bRet ? 4 : 0);
364}
365
366template <class Alt>
367void JSSpecialPropGet(const char* class_name,
368 v8::Local<v8::String> property,
369 const v8::PropertyCallbackInfo<v8::Value>& info) {
370 v8::Isolate* isolate = info.GetIsolate();
Tom Sepezb8ec0a32015-11-20 14:23:02 -0800371 CJS_Runtime* pRuntime =
372 static_cast<CJS_Runtime*>(FXJS_GetRuntimeFromIsolate(isolate));
Tom Sepezbd7fabf2015-09-28 10:31:27 -0700373 if (!pRuntime)
Tom Sepeza25fd092015-09-28 09:06:03 -0700374 return;
Tom Sepezdfbf8e72015-10-14 14:17:26 -0700375 IJS_Context* pContext = pRuntime->GetCurrentContext();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700376 CJS_Object* pJSObj =
Tom Sepez39bfe122015-09-17 15:25:23 -0700377 reinterpret_cast<CJS_Object*>(FXJS_GetPrivate(isolate, info.Holder()));
Tom Sepez2311b782015-02-23 10:22:51 -0800378 Alt* pObj = reinterpret_cast<Alt*>(pJSObj->GetEmbedObject());
379 v8::String::Utf8Value utf8_value(property);
tsepez6fe7d212016-04-06 10:51:14 -0700380 CFX_WideString propname = CFX_WideString::FromUTF8(
381 CFX_ByteStringC(*utf8_value, utf8_value.length()));
Tom Sepez3a832662015-03-02 12:59:05 -0800382 CFX_WideString sError;
Tom Sepez67fd5df2015-10-08 12:24:19 -0700383 CJS_PropValue value(pRuntime);
Tom Sepez2311b782015-02-23 10:22:51 -0800384 value.StartGetting();
Tom Sepezdfbf8e72015-10-14 14:17:26 -0700385 if (!pObj->DoProperty(pContext, propname.c_str(), value, sError)) {
Tom Sepez39bfe122015-09-17 15:25:23 -0700386 FXJS_Error(isolate, JSFormatErrorString(class_name, "GetProperty", sError));
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700387 return;
Tom Sepez2311b782015-02-23 10:22:51 -0800388 }
Jochen Eisingerdfa2c992015-05-19 00:38:00 +0200389 info.GetReturnValue().Set((v8::Local<v8::Value>)value);
Tom Sepez2311b782015-02-23 10:22:51 -0800390}
391
392template <class Alt>
393void JSSpecialPropPut(const char* class_name,
394 v8::Local<v8::String> property,
395 v8::Local<v8::Value> value,
396 const v8::PropertyCallbackInfo<v8::Value>& info) {
397 v8::Isolate* isolate = info.GetIsolate();
Tom Sepezb8ec0a32015-11-20 14:23:02 -0800398 CJS_Runtime* pRuntime =
399 static_cast<CJS_Runtime*>(FXJS_GetRuntimeFromIsolate(isolate));
Tom Sepezbd7fabf2015-09-28 10:31:27 -0700400 if (!pRuntime)
Tom Sepeza25fd092015-09-28 09:06:03 -0700401 return;
Tom Sepezdfbf8e72015-10-14 14:17:26 -0700402 IJS_Context* pContext = pRuntime->GetCurrentContext();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700403 CJS_Object* pJSObj =
Tom Sepez39bfe122015-09-17 15:25:23 -0700404 reinterpret_cast<CJS_Object*>(FXJS_GetPrivate(isolate, info.Holder()));
Tom Sepez2311b782015-02-23 10:22:51 -0800405 Alt* pObj = reinterpret_cast<Alt*>(pJSObj->GetEmbedObject());
406 v8::String::Utf8Value utf8_value(property);
tsepez6fe7d212016-04-06 10:51:14 -0700407 CFX_WideString propname = CFX_WideString::FromUTF8(
408 CFX_ByteStringC(*utf8_value, utf8_value.length()));
Tom Sepez3a832662015-03-02 12:59:05 -0800409 CFX_WideString sError;
Tom Sepez67fd5df2015-10-08 12:24:19 -0700410 CJS_PropValue PropValue(CJS_Value(pRuntime, value, CJS_Value::VT_unknown));
Tom Sepez2311b782015-02-23 10:22:51 -0800411 PropValue.StartSetting();
Tom Sepezdfbf8e72015-10-14 14:17:26 -0700412 if (!pObj->DoProperty(pContext, propname.c_str(), PropValue, sError)) {
Tom Sepez39bfe122015-09-17 15:25:23 -0700413 FXJS_Error(isolate, JSFormatErrorString(class_name, "PutProperty", sError));
Tom Sepez2311b782015-02-23 10:22:51 -0800414 }
415}
416
417template <class Alt>
418void JSSpecialPropDel(const char* class_name,
419 v8::Local<v8::String> property,
420 const v8::PropertyCallbackInfo<v8::Boolean>& info) {
421 v8::Isolate* isolate = info.GetIsolate();
Tom Sepezb8ec0a32015-11-20 14:23:02 -0800422 IJS_Runtime* pRuntime = FXJS_GetRuntimeFromIsolate(isolate);
Tom Sepezbd7fabf2015-09-28 10:31:27 -0700423 if (!pRuntime)
Tom Sepeza25fd092015-09-28 09:06:03 -0700424 return;
Tom Sepezdfbf8e72015-10-14 14:17:26 -0700425 IJS_Context* pContext = pRuntime->GetCurrentContext();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700426 CJS_Object* pJSObj =
Tom Sepez39bfe122015-09-17 15:25:23 -0700427 reinterpret_cast<CJS_Object*>(FXJS_GetPrivate(isolate, info.Holder()));
Tom Sepez2311b782015-02-23 10:22:51 -0800428 Alt* pObj = reinterpret_cast<Alt*>(pJSObj->GetEmbedObject());
429 v8::String::Utf8Value utf8_value(property);
tsepez6fe7d212016-04-06 10:51:14 -0700430 CFX_WideString propname = CFX_WideString::FromUTF8(
431 CFX_ByteStringC(*utf8_value, utf8_value.length()));
Tom Sepez3a832662015-03-02 12:59:05 -0800432 CFX_WideString sError;
Tom Sepezdfbf8e72015-10-14 14:17:26 -0700433 if (!pObj->DelProperty(pContext, propname.c_str(), sError)) {
Tom Sepez2311b782015-02-23 10:22:51 -0800434 CFX_ByteString cbName;
435 cbName.Format("%s.%s", class_name, "DelProperty");
Tom Sepez39bfe122015-09-17 15:25:23 -0700436 // Probably a missing call to JSFX_Error().
Tom Sepez2311b782015-02-23 10:22:51 -0800437 }
438}
439
Lei Zhang945fdb72015-11-11 10:18:16 -0800440template <FX_BOOL (*F)(IJS_Context*,
441 const std::vector<CJS_Value>&,
442 CJS_Value&,
443 CFX_WideString&)>
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700444void JSGlobalFunc(const char* func_name_string,
Tom Sepeza1160452015-02-19 10:00:55 -0800445 const v8::FunctionCallbackInfo<v8::Value>& info) {
Tom Sepezb8ec0a32015-11-20 14:23:02 -0800446 CJS_Runtime* pRuntime =
447 static_cast<CJS_Runtime*>(FXJS_GetRuntimeFromIsolate(info.GetIsolate()));
Tom Sepezbd7fabf2015-09-28 10:31:27 -0700448 if (!pRuntime)
Tom Sepeza25fd092015-09-28 09:06:03 -0700449 return;
Tom Sepezdfbf8e72015-10-14 14:17:26 -0700450 IJS_Context* pContext = pRuntime->GetCurrentContext();
Lei Zhang945fdb72015-11-11 10:18:16 -0800451 std::vector<CJS_Value> parameters;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700452 for (unsigned int i = 0; i < (unsigned int)info.Length(); i++) {
Tom Sepez67fd5df2015-10-08 12:24:19 -0700453 parameters.push_back(CJS_Value(pRuntime, info[i], CJS_Value::VT_unknown));
Tom Sepeza1160452015-02-19 10:00:55 -0800454 }
Tom Sepez67fd5df2015-10-08 12:24:19 -0700455 CJS_Value valueRes(pRuntime);
Tom Sepez3a832662015-03-02 12:59:05 -0800456 CFX_WideString sError;
Tom Sepezdfbf8e72015-10-14 14:17:26 -0700457 if (!(*F)(pContext, parameters, valueRes, sError)) {
Tom Sepez67fd5df2015-10-08 12:24:19 -0700458 FXJS_Error(pRuntime->GetIsolate(),
459 JSFormatErrorString(func_name_string, nullptr, sError));
Tom Sepeza1160452015-02-19 10:00:55 -0800460 return;
461 }
Tom Sepezf4ef3f92015-04-23 11:31:31 -0700462 info.GetReturnValue().Set(valueRes.ToV8Value());
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700463}
464
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700465#define JS_STATIC_GLOBAL_FUN(fun_name) \
466 static void fun_name##_static( \
467 const v8::FunctionCallbackInfo<v8::Value>& info) { \
468 JSGlobalFunc<fun_name>(#fun_name, info); \
Tom Sepeza1160452015-02-19 10:00:55 -0800469 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700470
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700471#define JS_STATIC_DECLARE_GLOBAL_FUN() \
472 static JSMethodSpec global_methods[]; \
Tom Sepez142165e2015-09-11 13:21:50 -0700473 static void DefineJSObjects(v8::Isolate* pIsolate)
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700474
475#define BEGIN_JS_STATIC_GLOBAL_FUN(js_class_name) \
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700476 JSMethodSpec js_class_name::global_methods[] = {
477#define JS_STATIC_GLOBAL_FUN_ENTRY(method_name) \
478 JS_STATIC_METHOD_ENTRY(method_name)
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700479
480#define END_JS_STATIC_GLOBAL_FUN() END_JS_STATIC_METHOD()
481
Tom Sepez39bfe122015-09-17 15:25:23 -0700482#define IMPLEMENT_JS_STATIC_GLOBAL_FUN(js_class_name) \
483 void js_class_name::DefineJSObjects(v8::Isolate* pIsolate) { \
Tom Sepezcd56a7d2015-10-06 11:45:28 -0700484 for (size_t i = 0; i < FX_ArraySize(global_methods) - 1; ++i) { \
Tom Sepez39bfe122015-09-17 15:25:23 -0700485 FXJS_DefineGlobalMethod(pIsolate, \
486 js_class_name::global_methods[i].pName, \
487 js_class_name::global_methods[i].pMethodCall); \
488 } \
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700489 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700490
Tom Sepez39bfe122015-09-17 15:25:23 -0700491CJS_Value::Type GET_VALUE_TYPE(v8::Local<v8::Value> p);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700492
Dan Sinclairf766ad22016-03-14 13:51:24 -0400493#endif // FPDFSDK_JAVASCRIPT_JS_DEFINE_H_