blob: 7cade587b5cf89248114a3c0504afd286f46c610 [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 Sepez19922bb2015-05-28 13:23:12 -07007#ifndef FPDFSDK_INCLUDE_JAVASCRIPT_JS_DEFINE_H_
8#define FPDFSDK_INCLUDE_JAVASCRIPT_JS_DEFINE_H_
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07009
Tom Sepez3a832662015-03-02 12:59:05 -080010#include "../jsapi/fxjs_v8.h"
11#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/* ====================================== PUBLIC DEFINE SPEC
34 * ============================================== */
35#define JS_WIDESTRING(widestring) L## #widestring
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070036
Nico Weber9d8ec5a2015-08-04 13:00:21 -070037#define BEGIN_JS_STATIC_CONST(js_class_name) \
38 JSConstSpec js_class_name::JS_Class_Consts[] = {
39#define JS_STATIC_CONST_ENTRY_NUMBER(const_name, pValue) \
Nico Weber077f1a32015-08-06 15:08:57 -070040 { const_name, pValue, L"", 0 } \
Nico Weber9d8ec5a2015-08-04 13:00:21 -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 ,
45#define END_JS_STATIC_CONST() \
46 { 0, 0, 0, 0 } \
47 } \
48 ;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070049
Nico Weber9d8ec5a2015-08-04 13:00:21 -070050#define BEGIN_JS_STATIC_PROP(js_class_name) \
51 JSPropertySpec js_class_name::JS_Class_Properties[] = {
52#define JS_STATIC_PROP_ENTRY(prop_name) \
53 { \
54 JS_WIDESTRING(prop_name), get_##prop_name##_static, set_##prop_name##_static \
55 } \
56 ,
57#define END_JS_STATIC_PROP() \
58 { 0, 0, 0 } \
59 } \
60 ;
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 ,
67#define END_JS_STATIC_METHOD() \
68 { 0, 0 } \
69 } \
70 ;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070071
Nico Weber9d8ec5a2015-08-04 13:00:21 -070072/* ======================================== PROP CALLBACK
73 * ============================================ */
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070074
Nico Weber9d8ec5a2015-08-04 13:00:21 -070075template <class C,
76 FX_BOOL (C::*M)(IFXJS_Context*, CJS_PropValue&, CFX_WideString&)>
Tom Sepeza1160452015-02-19 10:00:55 -080077void JSPropGetter(const char* prop_name_string,
78 const char* class_name_string,
79 v8::Local<v8::String> property,
80 const v8::PropertyCallbackInfo<v8::Value>& info) {
81 v8::Isolate* isolate = info.GetIsolate();
82 IFXJS_Runtime* pRuntime = (IFXJS_Runtime*)isolate->GetData(2);
83 IFXJS_Context* pRuntimeContext = pRuntime->GetCurrentContext();
84 CJS_PropValue value(isolate);
85 value.StartGetting();
Nico Weber9d8ec5a2015-08-04 13:00:21 -070086 CJS_Object* pJSObj = (CJS_Object*)JS_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 Sepeza1160452015-02-19 10:00:55 -080089 if (!(pObj->*M)(pRuntimeContext, value, sError)) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -070090 JS_Error(isolate,
91 JSFormatErrorString(class_name_string, prop_name_string, sError));
Tom Sepeza1160452015-02-19 10:00:55 -080092 return;
93 }
Jochen Eisingerdfa2c992015-05-19 00:38:00 +020094 info.GetReturnValue().Set((v8::Local<v8::Value>)value);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070095}
96
Nico Weber9d8ec5a2015-08-04 13:00:21 -070097template <class C,
98 FX_BOOL (C::*M)(IFXJS_Context*, CJS_PropValue&, CFX_WideString&)>
Tom Sepeza1160452015-02-19 10:00:55 -080099void JSPropSetter(const char* prop_name_string,
100 const char* class_name_string,
101 v8::Local<v8::String> property,
102 v8::Local<v8::Value> value,
103 const v8::PropertyCallbackInfo<void>& info) {
104 v8::Isolate* isolate = info.GetIsolate();
105 IFXJS_Runtime* pRuntime = (IFXJS_Runtime*)isolate->GetData(2);
106 IFXJS_Context* pRuntimeContext = pRuntime->GetCurrentContext();
107 CJS_PropValue propValue(CJS_Value(isolate, value, VT_unknown));
108 propValue.StartSetting();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700109 CJS_Object* pJSObj = (CJS_Object*)JS_GetPrivate(isolate, info.Holder());
Tom Sepeza1160452015-02-19 10:00:55 -0800110 C* pObj = reinterpret_cast<C*>(pJSObj->GetEmbedObject());
Tom Sepez3a832662015-03-02 12:59:05 -0800111 CFX_WideString sError;
Tom Sepeza1160452015-02-19 10:00:55 -0800112 if (!(pObj->*M)(pRuntimeContext, propValue, sError)) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700113 JS_Error(isolate,
114 JSFormatErrorString(class_name_string, prop_name_string, sError));
Tom Sepeza1160452015-02-19 10:00:55 -0800115 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700116}
117
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700118#define JS_STATIC_PROP(prop_name, class_name) \
119 static void get_##prop_name##_static( \
120 v8::Local<v8::String> property, \
121 const v8::PropertyCallbackInfo<v8::Value>& info) { \
122 JSPropGetter<class_name, &class_name::prop_name>(#prop_name, #class_name, \
123 property, info); \
124 } \
125 static void set_##prop_name##_static( \
126 v8::Local<v8::String> property, v8::Local<v8::Value> value, \
127 const v8::PropertyCallbackInfo<void>& info) { \
128 JSPropSetter<class_name, &class_name::prop_name>(#prop_name, #class_name, \
129 property, value, info); \
Tom Sepeza1160452015-02-19 10:00:55 -0800130 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700131
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700132/* ========================================= METHOD CALLBACK
133 * =========================================== */
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();
144 IFXJS_Runtime* pRuntime = (IFXJS_Runtime*)isolate->GetData(2);
145 IFXJS_Context* pRuntimeContext = pRuntime->GetCurrentContext();
146 CJS_Parameters parameters;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700147 for (unsigned int i = 0; i < (unsigned int)info.Length(); i++) {
Tom Sepeza1160452015-02-19 10:00:55 -0800148 parameters.push_back(CJS_Value(isolate, info[i], VT_unknown));
149 }
150 CJS_Value valueRes(isolate);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700151 CJS_Object* pJSObj = (CJS_Object*)JS_GetPrivate(isolate, info.Holder());
Tom Sepeza1160452015-02-19 10:00:55 -0800152 C* pObj = reinterpret_cast<C*>(pJSObj->GetEmbedObject());
Tom Sepez3a832662015-03-02 12:59:05 -0800153 CFX_WideString sError;
Tom Sepeza1160452015-02-19 10:00:55 -0800154 if (!(pObj->*M)(pRuntimeContext, parameters, valueRes, sError)) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700155 JS_Error(isolate, JSFormatErrorString(class_name_string, method_name_string,
156 sError));
Tom Sepeza1160452015-02-19 10:00:55 -0800157 return;
158 }
Tom Sepezf4ef3f92015-04-23 11:31:31 -0700159 info.GetReturnValue().Set(valueRes.ToV8Value());
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700160}
161
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700162#define JS_STATIC_METHOD(method_name, class_name) \
163 static void method_name##_static( \
164 const v8::FunctionCallbackInfo<v8::Value>& info) { \
165 JSMethod<class_name, &class_name::method_name>(#method_name, #class_name, \
166 info); \
Tom Sepeza1160452015-02-19 10:00:55 -0800167 }
168
169#define JS_SPECIAL_STATIC_METHOD(method_name, class_alternate, class_name) \
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700170 static void method_name##_static( \
171 const v8::FunctionCallbackInfo<v8::Value>& info) { \
172 JSMethod<class_alternate, &class_alternate::method_name>( \
173 #method_name, #class_name, info); \
Tom Sepeza1160452015-02-19 10:00:55 -0800174 }
175
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700176/* ===================================== JS CLASS
177 * =============================================== */
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700178
Tom Sepez142165e2015-09-11 13:21:50 -0700179#define DECLARE_JS_CLASS(js_class_name) \
180 static void JSConstructor(IFXJS_Context* cc, v8::Local<v8::Object> obj, \
181 v8::Local<v8::Object> global); \
182 static void JSDestructor(v8::Local<v8::Object> obj); \
183 static void DefineJSObjects(v8::Isolate* pIsolate, FXJSOBJTYPE eObjType); \
184 static JSConstSpec JS_Class_Consts[]; \
185 static JSPropertySpec JS_Class_Properties[]; \
186 static JSMethodSpec JS_Class_Methods[]; \
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700187 static const wchar_t* m_pClassName
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700188
Tom Sepez142165e2015-09-11 13:21:50 -0700189#define IMPLEMENT_JS_CLASS_RICH(js_class_name, class_alternate, class_name) \
190 const wchar_t* js_class_name::m_pClassName = JS_WIDESTRING(class_name); \
191 void js_class_name::JSConstructor(IFXJS_Context* cc, \
192 v8::Local<v8::Object> obj, \
193 v8::Local<v8::Object> global) { \
194 CJS_Object* pObj = new js_class_name(obj); \
195 pObj->SetEmbedObject(new class_alternate(pObj)); \
196 JS_SetPrivate(NULL, obj, (void*)pObj); \
197 pObj->InitInstance(cc); \
198 } \
199 \
200 void js_class_name::JSDestructor(v8::Local<v8::Object> obj) { \
201 js_class_name* pObj = (js_class_name*)JS_GetPrivate(NULL, obj); \
202 pObj->ExitInstance(); \
203 delete pObj; \
204 } \
205 \
206 void js_class_name::DefineJSObjects(v8::Isolate* pIsolate, \
207 FXJSOBJTYPE eObjType) { \
208 int nObjDefnID = JS_DefineObj(pIsolate, js_class_name::m_pClassName, \
209 eObjType, JSConstructor, JSDestructor); \
210 for (int i = 0; i < FX_ArraySize(JS_Class_Properties) - 1; ++i) { \
211 JS_DefineObjProperty(pIsolate, nObjDefnID, JS_Class_Properties[i].pName, \
212 JS_Class_Properties[i].pPropGet, \
213 JS_Class_Properties[i].pPropPut); \
214 } \
215 for (int i = 0; i < FX_ArraySize(JS_Class_Methods) - 1; ++i) { \
216 JS_DefineObjMethod(pIsolate, nObjDefnID, JS_Class_Methods[i].pName, \
217 JS_Class_Methods[i].pMethodCall); \
218 } \
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700219 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700220
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700221#define IMPLEMENT_JS_CLASS(js_class_name, class_name) \
222 IMPLEMENT_JS_CLASS_RICH(js_class_name, class_name, class_name)
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700223
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700224/* ======================================== CONST CLASS
225 * ============================================ */
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700226
Tom Sepez142165e2015-09-11 13:21:50 -0700227#define DECLARE_JS_CLASS_CONST() \
228 static void DefineJSObjects(v8::Isolate* pIsolate, FXJSOBJTYPE eObjType); \
229 static JSConstSpec JS_Class_Consts[]; \
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700230 static const wchar_t* m_pClassName
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700231
Tom Sepez142165e2015-09-11 13:21:50 -0700232#define IMPLEMENT_JS_CLASS_CONST(js_class_name, class_name) \
233 const wchar_t* js_class_name::m_pClassName = JS_WIDESTRING(class_name); \
234 void js_class_name::DefineJSObjects(v8::Isolate* pIsolate, \
235 FXJSOBJTYPE eObjType) { \
236 int nObjDefnID = JS_DefineObj(pIsolate, js_class_name::m_pClassName, \
237 eObjType, NULL, NULL); \
238 for (int i = 0; i < FX_ArraySize(JS_Class_Consts) - 1; ++i) { \
239 JS_DefineObjConst( \
240 pIsolate, nObjDefnID, JS_Class_Consts[i].pName, \
241 JS_Class_Consts[i].t == 0 \
242 ? JS_NewNumber(pIsolate, JS_Class_Consts[i].number) \
243 : JS_NewString(pIsolate, JS_Class_Consts[i].string)); \
244 } \
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700245 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700246
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700247/* ===================================== SPECIAL JS CLASS
248 * =============================================== */
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700249
Tom Sepez2311b782015-02-23 10:22:51 -0800250template <class Alt>
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700251void JSSpecialPropQuery(const char*,
252 v8::Local<v8::String> property,
253 const v8::PropertyCallbackInfo<v8::Integer>& info) {
Tom Sepez2311b782015-02-23 10:22:51 -0800254 v8::Isolate* isolate = info.GetIsolate();
255 v8::String::Utf8Value utf8_value(property);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700256 CFX_WideString propname =
257 CFX_WideString::FromUTF8(*utf8_value, utf8_value.length());
258 CJS_Object* pJSObj =
259 reinterpret_cast<CJS_Object*>(JS_GetPrivate(isolate, info.Holder()));
Tom Sepez2311b782015-02-23 10:22:51 -0800260 Alt* pObj = reinterpret_cast<Alt*>(pJSObj->GetEmbedObject());
261 FX_BOOL bRet = pObj->QueryProperty(propname.c_str());
262 info.GetReturnValue().Set(bRet ? 4 : 0);
263}
264
265template <class Alt>
266void JSSpecialPropGet(const char* class_name,
267 v8::Local<v8::String> property,
268 const v8::PropertyCallbackInfo<v8::Value>& info) {
269 v8::Isolate* isolate = info.GetIsolate();
270 v8::Local<v8::Context> context = isolate->GetCurrentContext();
271 IFXJS_Runtime* pRuntime = (IFXJS_Runtime*)isolate->GetData(2);
272 IFXJS_Context* pRuntimeContext = pRuntime->GetCurrentContext();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700273 CJS_Object* pJSObj =
274 reinterpret_cast<CJS_Object*>(JS_GetPrivate(isolate, info.Holder()));
Tom Sepez2311b782015-02-23 10:22:51 -0800275 Alt* pObj = reinterpret_cast<Alt*>(pJSObj->GetEmbedObject());
276 v8::String::Utf8Value utf8_value(property);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700277 CFX_WideString propname =
278 CFX_WideString::FromUTF8(*utf8_value, utf8_value.length());
Tom Sepez3a832662015-03-02 12:59:05 -0800279 CFX_WideString sError;
Tom Sepez2311b782015-02-23 10:22:51 -0800280 CJS_PropValue value(isolate);
281 value.StartGetting();
282 if (!pObj->DoProperty(pRuntimeContext, propname.c_str(), value, sError)) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700283 JS_Error(isolate, JSFormatErrorString(class_name, "GetProperty", sError));
284 return;
Tom Sepez2311b782015-02-23 10:22:51 -0800285 }
Jochen Eisingerdfa2c992015-05-19 00:38:00 +0200286 info.GetReturnValue().Set((v8::Local<v8::Value>)value);
Tom Sepez2311b782015-02-23 10:22:51 -0800287}
288
289template <class Alt>
290void JSSpecialPropPut(const char* class_name,
291 v8::Local<v8::String> property,
292 v8::Local<v8::Value> value,
293 const v8::PropertyCallbackInfo<v8::Value>& info) {
294 v8::Isolate* isolate = info.GetIsolate();
295 v8::Local<v8::Context> context = isolate->GetCurrentContext();
296 IFXJS_Runtime* pRuntime = (IFXJS_Runtime*)isolate->GetData(2);
297 IFXJS_Context* pRuntimeContext = pRuntime->GetCurrentContext();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700298 CJS_Object* pJSObj =
299 reinterpret_cast<CJS_Object*>(JS_GetPrivate(isolate, info.Holder()));
Tom Sepez2311b782015-02-23 10:22:51 -0800300 Alt* pObj = reinterpret_cast<Alt*>(pJSObj->GetEmbedObject());
301 v8::String::Utf8Value utf8_value(property);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700302 CFX_WideString propname =
303 CFX_WideString::FromUTF8(*utf8_value, utf8_value.length());
Tom Sepez3a832662015-03-02 12:59:05 -0800304 CFX_WideString sError;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700305 CJS_PropValue PropValue(CJS_Value(isolate, value, VT_unknown));
Tom Sepez2311b782015-02-23 10:22:51 -0800306 PropValue.StartSetting();
307 if (!pObj->DoProperty(pRuntimeContext, propname.c_str(), PropValue, sError)) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700308 JS_Error(isolate, JSFormatErrorString(class_name, "PutProperty", sError));
Tom Sepez2311b782015-02-23 10:22:51 -0800309 }
310}
311
312template <class Alt>
313void JSSpecialPropDel(const char* class_name,
314 v8::Local<v8::String> property,
315 const v8::PropertyCallbackInfo<v8::Boolean>& info) {
316 v8::Isolate* isolate = info.GetIsolate();
317 v8::Local<v8::Context> context = isolate->GetCurrentContext();
318 IFXJS_Runtime* pRuntime = (IFXJS_Runtime*)isolate->GetData(2);
319 IFXJS_Context* pRuntimeContext = pRuntime->GetCurrentContext();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700320 CJS_Object* pJSObj =
321 reinterpret_cast<CJS_Object*>(JS_GetPrivate(isolate, info.Holder()));
Tom Sepez2311b782015-02-23 10:22:51 -0800322 Alt* pObj = reinterpret_cast<Alt*>(pJSObj->GetEmbedObject());
323 v8::String::Utf8Value utf8_value(property);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700324 CFX_WideString propname =
325 CFX_WideString::FromUTF8(*utf8_value, utf8_value.length());
Tom Sepez3a832662015-03-02 12:59:05 -0800326 CFX_WideString sError;
Tom Sepez2311b782015-02-23 10:22:51 -0800327 if (!pObj->DelProperty(pRuntimeContext, propname.c_str(), sError)) {
328 CFX_ByteString cbName;
329 cbName.Format("%s.%s", class_name, "DelProperty");
330 // Probably a missing call to JS_Error().
331 }
332}
333
Tom Sepez142165e2015-09-11 13:21:50 -0700334#define DECLARE_SPECIAL_JS_CLASS(js_class_name) \
335 static void JSConstructor(IFXJS_Context* cc, v8::Local<v8::Object> obj, \
336 v8::Local<v8::Object> global); \
337 static void JSDestructor(v8::Local<v8::Object> obj); \
338 static JSConstSpec JS_Class_Consts[]; \
339 static JSPropertySpec JS_Class_Properties[]; \
340 static JSMethodSpec JS_Class_Methods[]; \
341 static void DefineJSObjects(v8::Isolate* pIsolate, FXJSOBJTYPE eObjType); \
342 static const wchar_t* m_pClassName; \
343 static void queryprop_##js_class_name##_static( \
344 v8::Local<v8::String> property, \
345 const v8::PropertyCallbackInfo<v8::Integer>& info); \
346 static void getprop_##js_class_name##_static( \
347 v8::Local<v8::String> property, \
348 const v8::PropertyCallbackInfo<v8::Value>& info); \
349 static void putprop_##js_class_name##_static( \
350 v8::Local<v8::String> property, v8::Local<v8::Value> value, \
351 const v8::PropertyCallbackInfo<v8::Value>& info); \
352 static void delprop_##js_class_name##_static( \
353 v8::Local<v8::String> property, \
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700354 const v8::PropertyCallbackInfo<v8::Boolean>& info)
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700355
356#define IMPLEMENT_SPECIAL_JS_CLASS(js_class_name, class_alternate, class_name) \
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700357 const wchar_t* js_class_name::m_pClassName = JS_WIDESTRING(class_name); \
358 void js_class_name::queryprop_##js_class_name##_static( \
359 v8::Local<v8::String> property, \
360 const v8::PropertyCallbackInfo<v8::Integer>& info) { \
361 JSSpecialPropQuery<class_alternate>(#class_name, property, info); \
362 } \
363 void js_class_name::getprop_##js_class_name##_static( \
364 v8::Local<v8::String> property, \
365 const v8::PropertyCallbackInfo<v8::Value>& info) { \
366 JSSpecialPropGet<class_alternate>(#class_name, property, info); \
367 } \
368 void js_class_name::putprop_##js_class_name##_static( \
369 v8::Local<v8::String> property, v8::Local<v8::Value> value, \
370 const v8::PropertyCallbackInfo<v8::Value>& info) { \
371 JSSpecialPropPut<class_alternate>(#class_name, property, value, info); \
372 } \
373 void js_class_name::delprop_##js_class_name##_static( \
374 v8::Local<v8::String> property, \
375 const v8::PropertyCallbackInfo<v8::Boolean>& info) { \
376 JSSpecialPropDel<class_alternate>(#class_name, property, info); \
377 } \
Tom Sepez808a99e2015-09-10 12:28:37 -0700378 void js_class_name::JSConstructor(IFXJS_Context* cc, \
379 v8::Local<v8::Object> obj, \
380 v8::Local<v8::Object> global) { \
Nico Weber077f1a32015-08-06 15:08:57 -0700381 CJS_Object* pObj = new js_class_name(obj); \
382 pObj->SetEmbedObject(new class_alternate(pObj)); \
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700383 JS_SetPrivate(NULL, obj, (void*)pObj); \
384 pObj->InitInstance(cc); \
385 } \
386 \
Tom Sepez808a99e2015-09-10 12:28:37 -0700387 void js_class_name::JSDestructor(v8::Local<v8::Object> obj) { \
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700388 js_class_name* pObj = (js_class_name*)JS_GetPrivate(NULL, obj); \
389 ASSERT(pObj != NULL); \
390 pObj->ExitInstance(); \
391 delete pObj; \
392 } \
393 \
Tom Sepez142165e2015-09-11 13:21:50 -0700394 void js_class_name::DefineJSObjects(v8::Isolate* pIsolate, \
395 FXJSOBJTYPE eObjType) { \
Tom Sepez808a99e2015-09-10 12:28:37 -0700396 int nObjDefnID = JS_DefineObj(pIsolate, js_class_name::m_pClassName, \
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700397 eObjType, JSConstructor, JSDestructor); \
Tom Sepez570875c2015-09-11 08:35:03 -0700398 for (int i = 0; i < FX_ArraySize(JS_Class_Properties) - 1; ++i) { \
Tom Sepez142165e2015-09-11 13:21:50 -0700399 JS_DefineObjProperty(pIsolate, nObjDefnID, JS_Class_Properties[i].pName, \
400 JS_Class_Properties[i].pPropGet, \
401 JS_Class_Properties[i].pPropPut); \
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700402 } \
403 \
Tom Sepez570875c2015-09-11 08:35:03 -0700404 for (int i = 0; i < FX_ArraySize(JS_Class_Methods) - 1; ++i) { \
Tom Sepez142165e2015-09-11 13:21:50 -0700405 JS_DefineObjMethod(pIsolate, nObjDefnID, JS_Class_Methods[i].pName, \
406 JS_Class_Methods[i].pMethodCall); \
Tom Sepez570875c2015-09-11 08:35:03 -0700407 } \
Tom Sepez142165e2015-09-11 13:21:50 -0700408 JS_DefineObjAllProperties( \
409 pIsolate, nObjDefnID, \
410 js_class_name::queryprop_##js_class_name##_static, \
411 js_class_name::getprop_##js_class_name##_static, \
412 js_class_name::putprop_##js_class_name##_static, \
413 js_class_name::delprop_##js_class_name##_static); \
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700414 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700415
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700416/* ======================================== GLOBAL METHODS
417 * ============================================ */
Tom Sepeza1160452015-02-19 10:00:55 -0800418
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700419template <FX_BOOL (
420 *F)(IFXJS_Context*, const CJS_Parameters&, CJS_Value&, CFX_WideString&)>
421void JSGlobalFunc(const char* func_name_string,
Tom Sepeza1160452015-02-19 10:00:55 -0800422 const v8::FunctionCallbackInfo<v8::Value>& info) {
423 v8::Isolate* isolate = info.GetIsolate();
424 IFXJS_Runtime* pRuntime = (IFXJS_Runtime*)isolate->GetData(2);
425 IFXJS_Context* pRuntimeContext = pRuntime->GetCurrentContext();
426 CJS_Parameters parameters;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700427 for (unsigned int i = 0; i < (unsigned int)info.Length(); i++) {
Tom Sepeza1160452015-02-19 10:00:55 -0800428 parameters.push_back(CJS_Value(isolate, info[i], VT_unknown));
429 }
430 CJS_Value valueRes(isolate);
Tom Sepez3a832662015-03-02 12:59:05 -0800431 CFX_WideString sError;
432 if (!(*F)(pRuntimeContext, parameters, valueRes, sError)) {
433 JS_Error(isolate, JSFormatErrorString(func_name_string, nullptr, sError));
Tom Sepeza1160452015-02-19 10:00:55 -0800434 return;
435 }
Tom Sepezf4ef3f92015-04-23 11:31:31 -0700436 info.GetReturnValue().Set(valueRes.ToV8Value());
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700437}
438
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700439#define JS_STATIC_GLOBAL_FUN(fun_name) \
440 static void fun_name##_static( \
441 const v8::FunctionCallbackInfo<v8::Value>& info) { \
442 JSGlobalFunc<fun_name>(#fun_name, info); \
Tom Sepeza1160452015-02-19 10:00:55 -0800443 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700444
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700445#define JS_STATIC_DECLARE_GLOBAL_FUN() \
446 static JSMethodSpec global_methods[]; \
Tom Sepez142165e2015-09-11 13:21:50 -0700447 static void DefineJSObjects(v8::Isolate* pIsolate)
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700448
449#define BEGIN_JS_STATIC_GLOBAL_FUN(js_class_name) \
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700450 JSMethodSpec js_class_name::global_methods[] = {
451#define JS_STATIC_GLOBAL_FUN_ENTRY(method_name) \
452 JS_STATIC_METHOD_ENTRY(method_name)
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700453
454#define END_JS_STATIC_GLOBAL_FUN() END_JS_STATIC_METHOD()
455
Tom Sepez142165e2015-09-11 13:21:50 -0700456#define IMPLEMENT_JS_STATIC_GLOBAL_FUN(js_class_name) \
457 void js_class_name::DefineJSObjects(v8::Isolate* pIsolate) { \
458 for (int i = 0; i < FX_ArraySize(global_methods) - 1; ++i) { \
459 JS_DefineGlobalMethod(pIsolate, js_class_name::global_methods[i].pName, \
460 js_class_name::global_methods[i].pMethodCall); \
461 } \
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700462 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700463
Jochen Eisingerdfa2c992015-05-19 00:38:00 +0200464FXJSVALUETYPE GET_VALUE_TYPE(v8::Local<v8::Value> p);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700465
Tom Sepez19922bb2015-05-28 13:23:12 -0700466#endif // FPDFSDK_INCLUDE_JAVASCRIPT_JS_DEFINE_H_