blob: 17bf7b132cf89e2f2f0715a00db59d80edcd5e55 [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
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700179#define DECLARE_JS_CLASS(js_class_name) \
180 static void JSConstructor(IFXJS_Context* cc, JSFXObject obj, \
181 JSFXObject global); \
182 static void JSDestructor(JSFXObject obj); \
183 static int Init(IJS_Runtime* pRuntime, FXJSOBJTYPE eObjType); \
184 static JSConstSpec JS_Class_Consts[]; \
185 static JSPropertySpec JS_Class_Properties[]; \
186 static JSMethodSpec JS_Class_Methods[]; \
187 static const wchar_t* m_pClassName
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700188
Nico Weber9d8ec5a2015-08-04 13:00:21 -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, JSFXObject obj, \
192 JSFXObject global) { \
Nico Weber077f1a32015-08-06 15:08:57 -0700193 CJS_Object* pObj = new js_class_name(obj); \
194 pObj->SetEmbedObject(new class_alternate(pObj)); \
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700195 JS_SetPrivate(NULL, obj, (void*)pObj); \
196 pObj->InitInstance(cc); \
197 } \
198 \
199 void js_class_name::JSDestructor(JSFXObject obj) { \
200 js_class_name* pObj = (js_class_name*)JS_GetPrivate(NULL, obj); \
201 ASSERT(pObj != NULL); \
202 pObj->ExitInstance(); \
203 delete pObj; \
204 } \
205 \
206 int js_class_name::Init(IJS_Runtime* pRuntime, FXJSOBJTYPE eObjType) { \
207 int nObjDefnID = JS_DefineObj(pRuntime, js_class_name::m_pClassName, \
208 eObjType, JSConstructor, JSDestructor); \
209 if (nObjDefnID >= 0) { \
210 for (int j = 0, \
211 szj = sizeof(JS_Class_Properties) / sizeof(JSPropertySpec) - 1; \
212 j < szj; j++) { \
213 if (JS_DefineObjProperty(pRuntime, nObjDefnID, \
214 JS_Class_Properties[j].pName, \
215 JS_Class_Properties[j].pPropGet, \
216 JS_Class_Properties[j].pPropPut) < 0) \
217 return -1; \
218 } \
219 for (int k = 0, \
220 szk = sizeof(JS_Class_Methods) / sizeof(JSMethodSpec) - 1; \
221 k < szk; k++) { \
222 if (JS_DefineObjMethod(pRuntime, nObjDefnID, \
223 JS_Class_Methods[k].pName, \
224 JS_Class_Methods[k].pMethodCall) < 0) \
225 return -1; \
226 } \
227 return nObjDefnID; \
228 } \
229 return -1; \
230 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700231
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700232#define IMPLEMENT_JS_CLASS(js_class_name, class_name) \
233 IMPLEMENT_JS_CLASS_RICH(js_class_name, class_name, class_name)
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700234
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700235/* ======================================== CONST CLASS
236 * ============================================ */
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700237
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700238#define DECLARE_JS_CLASS_CONST() \
239 static int Init(IJS_Runtime* pRuntime, FXJSOBJTYPE eObjType); \
240 static JSConstSpec JS_Class_Consts[]; \
241 static const wchar_t* m_pClassName
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700242
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700243#define IMPLEMENT_JS_CLASS_CONST(js_class_name, class_name) \
244 const wchar_t* js_class_name::m_pClassName = JS_WIDESTRING(class_name); \
245 int js_class_name::Init(IJS_Runtime* pRuntime, FXJSOBJTYPE eObjType) { \
246 int nObjDefnID = JS_DefineObj(pRuntime, js_class_name::m_pClassName, \
247 eObjType, NULL, NULL); \
248 if (nObjDefnID >= 0) { \
249 for (int i = 0, sz = sizeof(JS_Class_Consts) / sizeof(JSConstSpec) - 1; \
250 i < sz; i++) { \
251 if (JS_Class_Consts[i].t == 0) { \
252 if (JS_DefineObjConst( \
253 pRuntime, nObjDefnID, JS_Class_Consts[i].pName, \
254 JS_NewNumber(pRuntime, JS_Class_Consts[i].number)) < 0) \
255 return -1; \
256 } else { \
257 if (JS_DefineObjConst( \
258 pRuntime, nObjDefnID, JS_Class_Consts[i].pName, \
259 JS_NewString(pRuntime, JS_Class_Consts[i].string)) < 0) \
260 return -1; \
261 } \
262 } \
263 return nObjDefnID; \
264 } \
265 return -1; \
266 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700267
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700268/* ===================================== SPECIAL JS CLASS
269 * =============================================== */
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700270
Tom Sepez2311b782015-02-23 10:22:51 -0800271template <class Alt>
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700272void JSSpecialPropQuery(const char*,
273 v8::Local<v8::String> property,
274 const v8::PropertyCallbackInfo<v8::Integer>& info) {
Tom Sepez2311b782015-02-23 10:22:51 -0800275 v8::Isolate* isolate = info.GetIsolate();
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());
279 CJS_Object* pJSObj =
280 reinterpret_cast<CJS_Object*>(JS_GetPrivate(isolate, info.Holder()));
Tom Sepez2311b782015-02-23 10:22:51 -0800281 Alt* pObj = reinterpret_cast<Alt*>(pJSObj->GetEmbedObject());
282 FX_BOOL bRet = pObj->QueryProperty(propname.c_str());
283 info.GetReturnValue().Set(bRet ? 4 : 0);
284}
285
286template <class Alt>
287void JSSpecialPropGet(const char* class_name,
288 v8::Local<v8::String> property,
289 const v8::PropertyCallbackInfo<v8::Value>& info) {
290 v8::Isolate* isolate = info.GetIsolate();
291 v8::Local<v8::Context> context = isolate->GetCurrentContext();
292 IFXJS_Runtime* pRuntime = (IFXJS_Runtime*)isolate->GetData(2);
293 IFXJS_Context* pRuntimeContext = pRuntime->GetCurrentContext();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700294 CJS_Object* pJSObj =
295 reinterpret_cast<CJS_Object*>(JS_GetPrivate(isolate, info.Holder()));
Tom Sepez2311b782015-02-23 10:22:51 -0800296 Alt* pObj = reinterpret_cast<Alt*>(pJSObj->GetEmbedObject());
297 v8::String::Utf8Value utf8_value(property);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700298 CFX_WideString propname =
299 CFX_WideString::FromUTF8(*utf8_value, utf8_value.length());
Tom Sepez3a832662015-03-02 12:59:05 -0800300 CFX_WideString sError;
Tom Sepez2311b782015-02-23 10:22:51 -0800301 CJS_PropValue value(isolate);
302 value.StartGetting();
303 if (!pObj->DoProperty(pRuntimeContext, propname.c_str(), value, sError)) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700304 JS_Error(isolate, JSFormatErrorString(class_name, "GetProperty", sError));
305 return;
Tom Sepez2311b782015-02-23 10:22:51 -0800306 }
Jochen Eisingerdfa2c992015-05-19 00:38:00 +0200307 info.GetReturnValue().Set((v8::Local<v8::Value>)value);
Tom Sepez2311b782015-02-23 10:22:51 -0800308}
309
310template <class Alt>
311void JSSpecialPropPut(const char* class_name,
312 v8::Local<v8::String> property,
313 v8::Local<v8::Value> value,
314 const v8::PropertyCallbackInfo<v8::Value>& info) {
315 v8::Isolate* isolate = info.GetIsolate();
316 v8::Local<v8::Context> context = isolate->GetCurrentContext();
317 IFXJS_Runtime* pRuntime = (IFXJS_Runtime*)isolate->GetData(2);
318 IFXJS_Context* pRuntimeContext = pRuntime->GetCurrentContext();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700319 CJS_Object* pJSObj =
320 reinterpret_cast<CJS_Object*>(JS_GetPrivate(isolate, info.Holder()));
Tom Sepez2311b782015-02-23 10:22:51 -0800321 Alt* pObj = reinterpret_cast<Alt*>(pJSObj->GetEmbedObject());
322 v8::String::Utf8Value utf8_value(property);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700323 CFX_WideString propname =
324 CFX_WideString::FromUTF8(*utf8_value, utf8_value.length());
Tom Sepez3a832662015-03-02 12:59:05 -0800325 CFX_WideString sError;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700326 CJS_PropValue PropValue(CJS_Value(isolate, value, VT_unknown));
Tom Sepez2311b782015-02-23 10:22:51 -0800327 PropValue.StartSetting();
328 if (!pObj->DoProperty(pRuntimeContext, propname.c_str(), PropValue, sError)) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700329 JS_Error(isolate, JSFormatErrorString(class_name, "PutProperty", sError));
Tom Sepez2311b782015-02-23 10:22:51 -0800330 }
331}
332
333template <class Alt>
334void JSSpecialPropDel(const char* class_name,
335 v8::Local<v8::String> property,
336 const v8::PropertyCallbackInfo<v8::Boolean>& info) {
337 v8::Isolate* isolate = info.GetIsolate();
338 v8::Local<v8::Context> context = isolate->GetCurrentContext();
339 IFXJS_Runtime* pRuntime = (IFXJS_Runtime*)isolate->GetData(2);
340 IFXJS_Context* pRuntimeContext = pRuntime->GetCurrentContext();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700341 CJS_Object* pJSObj =
342 reinterpret_cast<CJS_Object*>(JS_GetPrivate(isolate, info.Holder()));
Tom Sepez2311b782015-02-23 10:22:51 -0800343 Alt* pObj = reinterpret_cast<Alt*>(pJSObj->GetEmbedObject());
344 v8::String::Utf8Value utf8_value(property);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700345 CFX_WideString propname =
346 CFX_WideString::FromUTF8(*utf8_value, utf8_value.length());
Tom Sepez3a832662015-03-02 12:59:05 -0800347 CFX_WideString sError;
Tom Sepez2311b782015-02-23 10:22:51 -0800348 if (!pObj->DelProperty(pRuntimeContext, propname.c_str(), sError)) {
349 CFX_ByteString cbName;
350 cbName.Format("%s.%s", class_name, "DelProperty");
351 // Probably a missing call to JS_Error().
352 }
353}
354
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700355#define DECLARE_SPECIAL_JS_CLASS(js_class_name) \
356 static void JSConstructor(IFXJS_Context* cc, JSFXObject obj, \
357 JSFXObject global); \
358 static void JSDestructor(JSFXObject obj); \
359 static JSConstSpec JS_Class_Consts[]; \
360 static JSPropertySpec JS_Class_Properties[]; \
361 static JSMethodSpec JS_Class_Methods[]; \
362 static int Init(IJS_Runtime* pRuntime, FXJSOBJTYPE eObjType); \
363 static const wchar_t* m_pClassName; \
364 static void queryprop_##js_class_name##_static( \
365 v8::Local<v8::String> property, \
366 const v8::PropertyCallbackInfo<v8::Integer>& info); \
367 static void getprop_##js_class_name##_static( \
368 v8::Local<v8::String> property, \
369 const v8::PropertyCallbackInfo<v8::Value>& info); \
370 static void putprop_##js_class_name##_static( \
371 v8::Local<v8::String> property, v8::Local<v8::Value> value, \
372 const v8::PropertyCallbackInfo<v8::Value>& info); \
373 static void delprop_##js_class_name##_static( \
374 v8::Local<v8::String> property, \
375 const v8::PropertyCallbackInfo<v8::Boolean>& info)
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700376
377#define IMPLEMENT_SPECIAL_JS_CLASS(js_class_name, class_alternate, class_name) \
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700378 const wchar_t* js_class_name::m_pClassName = JS_WIDESTRING(class_name); \
379 void js_class_name::queryprop_##js_class_name##_static( \
380 v8::Local<v8::String> property, \
381 const v8::PropertyCallbackInfo<v8::Integer>& info) { \
382 JSSpecialPropQuery<class_alternate>(#class_name, property, info); \
383 } \
384 void js_class_name::getprop_##js_class_name##_static( \
385 v8::Local<v8::String> property, \
386 const v8::PropertyCallbackInfo<v8::Value>& info) { \
387 JSSpecialPropGet<class_alternate>(#class_name, property, info); \
388 } \
389 void js_class_name::putprop_##js_class_name##_static( \
390 v8::Local<v8::String> property, v8::Local<v8::Value> value, \
391 const v8::PropertyCallbackInfo<v8::Value>& info) { \
392 JSSpecialPropPut<class_alternate>(#class_name, property, value, info); \
393 } \
394 void js_class_name::delprop_##js_class_name##_static( \
395 v8::Local<v8::String> property, \
396 const v8::PropertyCallbackInfo<v8::Boolean>& info) { \
397 JSSpecialPropDel<class_alternate>(#class_name, property, info); \
398 } \
399 void js_class_name::JSConstructor(IFXJS_Context* cc, JSFXObject obj, \
400 JSFXObject global) { \
Nico Weber077f1a32015-08-06 15:08:57 -0700401 CJS_Object* pObj = new js_class_name(obj); \
402 pObj->SetEmbedObject(new class_alternate(pObj)); \
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700403 JS_SetPrivate(NULL, obj, (void*)pObj); \
404 pObj->InitInstance(cc); \
405 } \
406 \
407 void js_class_name::JSDestructor(JSFXObject obj) { \
408 js_class_name* pObj = (js_class_name*)JS_GetPrivate(NULL, obj); \
409 ASSERT(pObj != NULL); \
410 pObj->ExitInstance(); \
411 delete pObj; \
412 } \
413 \
414 int js_class_name::Init(IJS_Runtime* pRuntime, FXJSOBJTYPE eObjType) { \
415 int nObjDefnID = JS_DefineObj(pRuntime, js_class_name::m_pClassName, \
416 eObjType, JSConstructor, JSDestructor); \
417 \
418 if (nObjDefnID >= 0) { \
419 for (int j = 0, \
420 szj = sizeof(JS_Class_Properties) / sizeof(JSPropertySpec) - 1; \
421 j < szj; j++) { \
422 if (JS_DefineObjProperty(pRuntime, nObjDefnID, \
423 JS_Class_Properties[j].pName, \
424 JS_Class_Properties[j].pPropGet, \
425 JS_Class_Properties[j].pPropPut) < 0) \
426 return -1; \
427 } \
428 \
429 for (int k = 0, \
430 szk = sizeof(JS_Class_Methods) / sizeof(JSMethodSpec) - 1; \
431 k < szk; k++) { \
432 if (JS_DefineObjMethod(pRuntime, nObjDefnID, \
433 JS_Class_Methods[k].pName, \
434 JS_Class_Methods[k].pMethodCall) < 0) \
435 return -1; \
436 } \
437 if (JS_DefineObjAllProperties( \
438 pRuntime, nObjDefnID, \
439 js_class_name::queryprop_##js_class_name##_static, \
440 js_class_name::getprop_##js_class_name##_static, \
441 js_class_name::putprop_##js_class_name##_static, \
442 js_class_name::delprop_##js_class_name##_static) < 0) \
443 return -1; \
444 \
445 return nObjDefnID; \
446 } \
447 \
448 return -1; \
449 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700450
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700451/* ======================================== GLOBAL METHODS
452 * ============================================ */
Tom Sepeza1160452015-02-19 10:00:55 -0800453
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700454template <FX_BOOL (
455 *F)(IFXJS_Context*, const CJS_Parameters&, CJS_Value&, CFX_WideString&)>
456void JSGlobalFunc(const char* func_name_string,
Tom Sepeza1160452015-02-19 10:00:55 -0800457 const v8::FunctionCallbackInfo<v8::Value>& info) {
458 v8::Isolate* isolate = info.GetIsolate();
459 IFXJS_Runtime* pRuntime = (IFXJS_Runtime*)isolate->GetData(2);
460 IFXJS_Context* pRuntimeContext = pRuntime->GetCurrentContext();
461 CJS_Parameters parameters;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700462 for (unsigned int i = 0; i < (unsigned int)info.Length(); i++) {
Tom Sepeza1160452015-02-19 10:00:55 -0800463 parameters.push_back(CJS_Value(isolate, info[i], VT_unknown));
464 }
465 CJS_Value valueRes(isolate);
Tom Sepez3a832662015-03-02 12:59:05 -0800466 CFX_WideString sError;
467 if (!(*F)(pRuntimeContext, parameters, valueRes, sError)) {
468 JS_Error(isolate, JSFormatErrorString(func_name_string, nullptr, sError));
Tom Sepeza1160452015-02-19 10:00:55 -0800469 return;
470 }
Tom Sepezf4ef3f92015-04-23 11:31:31 -0700471 info.GetReturnValue().Set(valueRes.ToV8Value());
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700472}
473
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700474#define JS_STATIC_GLOBAL_FUN(fun_name) \
475 static void fun_name##_static( \
476 const v8::FunctionCallbackInfo<v8::Value>& info) { \
477 JSGlobalFunc<fun_name>(#fun_name, info); \
Tom Sepeza1160452015-02-19 10:00:55 -0800478 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700479
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700480#define JS_STATIC_DECLARE_GLOBAL_FUN() \
481 static JSMethodSpec global_methods[]; \
482 static int Init(IJS_Runtime* pRuntime)
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700483
484#define BEGIN_JS_STATIC_GLOBAL_FUN(js_class_name) \
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700485 JSMethodSpec js_class_name::global_methods[] = {
486#define JS_STATIC_GLOBAL_FUN_ENTRY(method_name) \
487 JS_STATIC_METHOD_ENTRY(method_name)
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700488
489#define END_JS_STATIC_GLOBAL_FUN() END_JS_STATIC_METHOD()
490
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700491#define IMPLEMENT_JS_STATIC_GLOBAL_FUN(js_class_name) \
492 int js_class_name::Init(IJS_Runtime* pRuntime) { \
493 for (int i = 0, sz = sizeof(js_class_name::global_methods) / \
494 sizeof(JSMethodSpec) - \
495 1; \
496 i < sz; i++) { \
497 if (JS_DefineGlobalMethod( \
498 pRuntime, js_class_name::global_methods[i].pName, \
499 js_class_name::global_methods[i].pMethodCall) < 0) \
500 return -1; \
501 } \
502 return 0; \
503 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700504
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700505/* ======================================== GLOBAL CONSTS
506 * ============================================ */
507#define DEFINE_GLOBAL_CONST(pRuntime, const_name, const_value) \
508 if (JS_DefineGlobalConst( \
509 pRuntime, JS_WIDESTRING(const_name), \
510 JS_NewString(pRuntime, JS_WIDESTRING(const_value)))) \
511 return -1
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700512
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700513/* ======================================== GLOBAL ARRAYS
514 * ============================================ */
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700515
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700516#define DEFINE_GLOBAL_ARRAY(pRuntime) \
517 int size = FX_ArraySize(ArrayContent); \
518 \
519 CJS_Array array(pRuntime); \
520 for (int i = 0; i < size; i++) \
521 array.SetElement(i, CJS_Value(pRuntime, ArrayContent[i])); \
522 \
523 CJS_PropValue prop(pRuntime); \
524 prop << array; \
525 if (JS_DefineGlobalConst(pRuntime, (const wchar_t*)ArrayName, \
526 prop.ToV8Value()) < 0) \
527 return -1
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700528
529/* ============================================================ */
530
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700531#define VALUE_NAME_STRING L"string"
532#define VALUE_NAME_NUMBER L"number"
533#define VALUE_NAME_BOOLEAN L"boolean"
534#define VALUE_NAME_DATE L"date"
535#define VALUE_NAME_OBJECT L"object"
536#define VALUE_NAME_FXOBJ L"fxobj"
537#define VALUE_NAME_NULL L"null"
538#define VALUE_NAME_UNDEFINED L"undefined"
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700539
Jochen Eisingerdfa2c992015-05-19 00:38:00 +0200540FXJSVALUETYPE GET_VALUE_TYPE(v8::Local<v8::Value> p);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700541
Tom Sepez19922bb2015-05-28 13:23:12 -0700542#endif // FPDFSDK_INCLUDE_JAVASCRIPT_JS_DEFINE_H_