blob: adf69ec0e9efd36c8475b7d91619e35fbd4d37fc [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();
Tom Sepeza25fd092015-09-28 09:06:03 -070082 v8::Local<v8::Context> context = isolate->GetCurrentContext();
83 v8::Local<v8::Value> v = context->GetEmbedderData(1);
84 if (v.IsEmpty())
85 return;
86 v8::Local<v8::External> field = v8::Local<v8::External>::Cast(v);
87 IFXJS_Runtime* pRuntime = (IFXJS_Runtime*)field->Value();
88 IFXJS_Context* pRuntimeContext = pRuntime->GetCurrentContext();
Tom Sepez39bfe122015-09-17 15:25:23 -070089 CJS_Object* pJSObj = (CJS_Object*)FXJS_GetPrivate(isolate, info.Holder());
Tom Sepeza1160452015-02-19 10:00:55 -080090 C* pObj = reinterpret_cast<C*>(pJSObj->GetEmbedObject());
Tom Sepez3a832662015-03-02 12:59:05 -080091 CFX_WideString sError;
Tom Sepeza25fd092015-09-28 09:06:03 -070092 CJS_PropValue value(isolate);
93 value.StartGetting();
Tom Sepeza1160452015-02-19 10:00:55 -080094 if (!(pObj->*M)(pRuntimeContext, value, sError)) {
Tom Sepez39bfe122015-09-17 15:25:23 -070095 FXJS_Error(isolate, JSFormatErrorString(class_name_string, prop_name_string,
96 sError));
Tom Sepeza1160452015-02-19 10:00:55 -080097 return;
98 }
Jochen Eisingerdfa2c992015-05-19 00:38:00 +020099 info.GetReturnValue().Set((v8::Local<v8::Value>)value);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700100}
101
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700102template <class C,
103 FX_BOOL (C::*M)(IFXJS_Context*, CJS_PropValue&, CFX_WideString&)>
Tom Sepeza1160452015-02-19 10:00:55 -0800104void JSPropSetter(const char* prop_name_string,
105 const char* class_name_string,
106 v8::Local<v8::String> property,
107 v8::Local<v8::Value> value,
108 const v8::PropertyCallbackInfo<void>& info) {
109 v8::Isolate* isolate = info.GetIsolate();
Tom Sepeza25fd092015-09-28 09:06:03 -0700110 v8::Local<v8::Context> context = isolate->GetCurrentContext();
111 v8::Local<v8::Value> v = context->GetEmbedderData(1);
112 if (v.IsEmpty())
113 return;
114 v8::Local<v8::External> field = v8::Local<v8::External>::Cast(v);
115 IFXJS_Runtime* pRuntime = (IFXJS_Runtime*)field->Value();
116 IFXJS_Context* pRuntimeContext = pRuntime->GetCurrentContext();
Tom Sepez39bfe122015-09-17 15:25:23 -0700117 CJS_Object* pJSObj = (CJS_Object*)FXJS_GetPrivate(isolate, info.Holder());
Tom Sepeza1160452015-02-19 10:00:55 -0800118 C* pObj = reinterpret_cast<C*>(pJSObj->GetEmbedObject());
Tom Sepez3a832662015-03-02 12:59:05 -0800119 CFX_WideString sError;
Tom Sepeza25fd092015-09-28 09:06:03 -0700120 CJS_PropValue propValue(CJS_Value(isolate, value, CJS_Value::VT_unknown));
121 propValue.StartSetting();
Tom Sepeza1160452015-02-19 10:00:55 -0800122 if (!(pObj->*M)(pRuntimeContext, propValue, sError)) {
Tom Sepez39bfe122015-09-17 15:25:23 -0700123 FXJS_Error(isolate, JSFormatErrorString(class_name_string, prop_name_string,
124 sError));
Tom Sepeza1160452015-02-19 10:00:55 -0800125 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700126}
127
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700128#define JS_STATIC_PROP(prop_name, class_name) \
129 static void get_##prop_name##_static( \
130 v8::Local<v8::String> property, \
131 const v8::PropertyCallbackInfo<v8::Value>& info) { \
132 JSPropGetter<class_name, &class_name::prop_name>(#prop_name, #class_name, \
133 property, info); \
134 } \
135 static void set_##prop_name##_static( \
136 v8::Local<v8::String> property, v8::Local<v8::Value> value, \
137 const v8::PropertyCallbackInfo<void>& info) { \
138 JSPropSetter<class_name, &class_name::prop_name>(#prop_name, #class_name, \
139 property, value, info); \
Tom Sepeza1160452015-02-19 10:00:55 -0800140 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700141
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700142/* ========================================= METHOD CALLBACK
143 * =========================================== */
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700144
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700145template <class C,
146 FX_BOOL (C::*M)(IFXJS_Context*,
147 const CJS_Parameters&,
148 CJS_Value&,
149 CFX_WideString&)>
Tom Sepeza1160452015-02-19 10:00:55 -0800150void JSMethod(const char* method_name_string,
151 const char* class_name_string,
152 const v8::FunctionCallbackInfo<v8::Value>& info) {
153 v8::Isolate* isolate = info.GetIsolate();
Tom Sepeza25fd092015-09-28 09:06:03 -0700154 v8::Local<v8::Context> context = isolate->GetCurrentContext();
155 v8::Local<v8::Value> v = context->GetEmbedderData(1);
156 if (v.IsEmpty())
157 return;
158 v8::Local<v8::External> field = v8::Local<v8::External>::Cast(v);
159 IFXJS_Runtime* pRuntime = (IFXJS_Runtime*)field->Value();
160 IFXJS_Context* pRuntimeContext = pRuntime->GetCurrentContext();
Tom Sepeza1160452015-02-19 10:00:55 -0800161 CJS_Parameters parameters;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700162 for (unsigned int i = 0; i < (unsigned int)info.Length(); i++) {
Tom Sepez39bfe122015-09-17 15:25:23 -0700163 parameters.push_back(CJS_Value(isolate, info[i], CJS_Value::VT_unknown));
Tom Sepeza1160452015-02-19 10:00:55 -0800164 }
165 CJS_Value valueRes(isolate);
Tom Sepez39bfe122015-09-17 15:25:23 -0700166 CJS_Object* pJSObj = (CJS_Object*)FXJS_GetPrivate(isolate, info.Holder());
Tom Sepeza1160452015-02-19 10:00:55 -0800167 C* pObj = reinterpret_cast<C*>(pJSObj->GetEmbedObject());
Tom Sepez3a832662015-03-02 12:59:05 -0800168 CFX_WideString sError;
Tom Sepeza1160452015-02-19 10:00:55 -0800169 if (!(pObj->*M)(pRuntimeContext, parameters, valueRes, sError)) {
Tom Sepez39bfe122015-09-17 15:25:23 -0700170 FXJS_Error(isolate, JSFormatErrorString(class_name_string,
171 method_name_string, sError));
Tom Sepeza1160452015-02-19 10:00:55 -0800172 return;
173 }
Tom Sepezf4ef3f92015-04-23 11:31:31 -0700174 info.GetReturnValue().Set(valueRes.ToV8Value());
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700175}
176
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700177#define JS_STATIC_METHOD(method_name, class_name) \
178 static void method_name##_static( \
179 const v8::FunctionCallbackInfo<v8::Value>& info) { \
180 JSMethod<class_name, &class_name::method_name>(#method_name, #class_name, \
181 info); \
Tom Sepeza1160452015-02-19 10:00:55 -0800182 }
183
184#define JS_SPECIAL_STATIC_METHOD(method_name, class_alternate, class_name) \
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700185 static void method_name##_static( \
186 const v8::FunctionCallbackInfo<v8::Value>& info) { \
187 JSMethod<class_alternate, &class_alternate::method_name>( \
188 #method_name, #class_name, info); \
Tom Sepeza1160452015-02-19 10:00:55 -0800189 }
190
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700191/* ===================================== JS CLASS
192 * =============================================== */
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700193
Tom Sepez142165e2015-09-11 13:21:50 -0700194#define DECLARE_JS_CLASS(js_class_name) \
195 static void JSConstructor(IFXJS_Context* cc, v8::Local<v8::Object> obj, \
196 v8::Local<v8::Object> global); \
197 static void JSDestructor(v8::Local<v8::Object> obj); \
198 static void DefineJSObjects(v8::Isolate* pIsolate, FXJSOBJTYPE eObjType); \
199 static JSConstSpec JS_Class_Consts[]; \
200 static JSPropertySpec JS_Class_Properties[]; \
201 static JSMethodSpec JS_Class_Methods[]; \
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700202 static const wchar_t* m_pClassName
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700203
Tom Sepez39bfe122015-09-17 15:25:23 -0700204#define IMPLEMENT_JS_CLASS_RICH(js_class_name, class_alternate, class_name) \
205 const wchar_t* js_class_name::m_pClassName = JS_WIDESTRING(class_name); \
206 void js_class_name::JSConstructor(IFXJS_Context* cc, \
207 v8::Local<v8::Object> obj, \
208 v8::Local<v8::Object> global) { \
209 CJS_Object* pObj = new js_class_name(obj); \
210 pObj->SetEmbedObject(new class_alternate(pObj)); \
211 FXJS_SetPrivate(NULL, obj, (void*)pObj); \
212 pObj->InitInstance(cc); \
213 } \
214 \
215 void js_class_name::JSDestructor(v8::Local<v8::Object> obj) { \
216 js_class_name* pObj = (js_class_name*)FXJS_GetPrivate(NULL, obj); \
217 pObj->ExitInstance(); \
218 delete pObj; \
219 } \
220 \
221 void js_class_name::DefineJSObjects(v8::Isolate* pIsolate, \
222 FXJSOBJTYPE eObjType) { \
223 int nObjDefnID = FXJS_DefineObj(pIsolate, js_class_name::m_pClassName, \
224 eObjType, JSConstructor, JSDestructor); \
225 for (int i = 0; i < FX_ArraySize(JS_Class_Properties) - 1; ++i) { \
226 FXJS_DefineObjProperty( \
227 pIsolate, nObjDefnID, JS_Class_Properties[i].pName, \
228 JS_Class_Properties[i].pPropGet, JS_Class_Properties[i].pPropPut); \
229 } \
230 for (int i = 0; i < FX_ArraySize(JS_Class_Methods) - 1; ++i) { \
231 FXJS_DefineObjMethod(pIsolate, nObjDefnID, JS_Class_Methods[i].pName, \
232 JS_Class_Methods[i].pMethodCall); \
233 } \
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700234 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700235
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700236#define IMPLEMENT_JS_CLASS(js_class_name, class_name) \
237 IMPLEMENT_JS_CLASS_RICH(js_class_name, class_name, class_name)
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700238
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700239/* ======================================== CONST CLASS
240 * ============================================ */
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700241
Tom Sepez142165e2015-09-11 13:21:50 -0700242#define DECLARE_JS_CLASS_CONST() \
243 static void DefineJSObjects(v8::Isolate* pIsolate, FXJSOBJTYPE eObjType); \
244 static JSConstSpec JS_Class_Consts[]; \
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700245 static const wchar_t* m_pClassName
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700246
Tom Sepez39bfe122015-09-17 15:25:23 -0700247#define IMPLEMENT_JS_CLASS_CONST(js_class_name, class_name) \
248 const wchar_t* js_class_name::m_pClassName = JS_WIDESTRING(class_name); \
249 void js_class_name::DefineJSObjects(v8::Isolate* pIsolate, \
250 FXJSOBJTYPE eObjType) { \
251 int nObjDefnID = FXJS_DefineObj(pIsolate, js_class_name::m_pClassName, \
252 eObjType, NULL, NULL); \
253 for (int i = 0; i < FX_ArraySize(JS_Class_Consts) - 1; ++i) { \
254 FXJS_DefineObjConst( \
255 pIsolate, nObjDefnID, JS_Class_Consts[i].pName, \
256 JS_Class_Consts[i].t == 0 \
257 ? FXJS_NewNumber(pIsolate, JS_Class_Consts[i].number) \
258 : FXJS_NewString(pIsolate, JS_Class_Consts[i].string)); \
259 } \
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700260 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700261
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700262/* ===================================== SPECIAL JS CLASS
263 * =============================================== */
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700264
Tom Sepez2311b782015-02-23 10:22:51 -0800265template <class Alt>
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700266void JSSpecialPropQuery(const char*,
267 v8::Local<v8::String> property,
268 const v8::PropertyCallbackInfo<v8::Integer>& info) {
Tom Sepez2311b782015-02-23 10:22:51 -0800269 v8::Isolate* isolate = info.GetIsolate();
270 v8::String::Utf8Value utf8_value(property);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700271 CFX_WideString propname =
272 CFX_WideString::FromUTF8(*utf8_value, utf8_value.length());
273 CJS_Object* pJSObj =
Tom Sepez39bfe122015-09-17 15:25:23 -0700274 reinterpret_cast<CJS_Object*>(FXJS_GetPrivate(isolate, info.Holder()));
Tom Sepez2311b782015-02-23 10:22:51 -0800275 Alt* pObj = reinterpret_cast<Alt*>(pJSObj->GetEmbedObject());
276 FX_BOOL bRet = pObj->QueryProperty(propname.c_str());
277 info.GetReturnValue().Set(bRet ? 4 : 0);
278}
279
280template <class Alt>
281void JSSpecialPropGet(const char* class_name,
282 v8::Local<v8::String> property,
283 const v8::PropertyCallbackInfo<v8::Value>& info) {
284 v8::Isolate* isolate = info.GetIsolate();
285 v8::Local<v8::Context> context = isolate->GetCurrentContext();
Tom Sepeza25fd092015-09-28 09:06:03 -0700286 v8::Local<v8::Value> v = context->GetEmbedderData(1);
287 if (v.IsEmpty())
288 return;
289 v8::Local<v8::External> field = v8::Local<v8::External>::Cast(v);
290 IFXJS_Runtime* pRuntime = (IFXJS_Runtime*)field->Value();
291 IFXJS_Context* pRuntimeContext = pRuntime->GetCurrentContext();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700292 CJS_Object* pJSObj =
Tom Sepez39bfe122015-09-17 15:25:23 -0700293 reinterpret_cast<CJS_Object*>(FXJS_GetPrivate(isolate, info.Holder()));
Tom Sepez2311b782015-02-23 10:22:51 -0800294 Alt* pObj = reinterpret_cast<Alt*>(pJSObj->GetEmbedObject());
295 v8::String::Utf8Value utf8_value(property);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700296 CFX_WideString propname =
297 CFX_WideString::FromUTF8(*utf8_value, utf8_value.length());
Tom Sepez3a832662015-03-02 12:59:05 -0800298 CFX_WideString sError;
Tom Sepez2311b782015-02-23 10:22:51 -0800299 CJS_PropValue value(isolate);
300 value.StartGetting();
301 if (!pObj->DoProperty(pRuntimeContext, propname.c_str(), value, sError)) {
Tom Sepez39bfe122015-09-17 15:25:23 -0700302 FXJS_Error(isolate, JSFormatErrorString(class_name, "GetProperty", sError));
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700303 return;
Tom Sepez2311b782015-02-23 10:22:51 -0800304 }
Jochen Eisingerdfa2c992015-05-19 00:38:00 +0200305 info.GetReturnValue().Set((v8::Local<v8::Value>)value);
Tom Sepez2311b782015-02-23 10:22:51 -0800306}
307
308template <class Alt>
309void JSSpecialPropPut(const char* class_name,
310 v8::Local<v8::String> property,
311 v8::Local<v8::Value> value,
312 const v8::PropertyCallbackInfo<v8::Value>& info) {
313 v8::Isolate* isolate = info.GetIsolate();
314 v8::Local<v8::Context> context = isolate->GetCurrentContext();
Tom Sepeza25fd092015-09-28 09:06:03 -0700315 v8::Local<v8::Value> v = context->GetEmbedderData(1);
316 if (v.IsEmpty())
317 return;
318 v8::Local<v8::External> field = v8::Local<v8::External>::Cast(v);
319 IFXJS_Runtime* pRuntime = (IFXJS_Runtime*)field->Value();
320 IFXJS_Context* pRuntimeContext = pRuntime->GetCurrentContext();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700321 CJS_Object* pJSObj =
Tom Sepez39bfe122015-09-17 15:25:23 -0700322 reinterpret_cast<CJS_Object*>(FXJS_GetPrivate(isolate, info.Holder()));
Tom Sepez2311b782015-02-23 10:22:51 -0800323 Alt* pObj = reinterpret_cast<Alt*>(pJSObj->GetEmbedObject());
324 v8::String::Utf8Value utf8_value(property);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700325 CFX_WideString propname =
326 CFX_WideString::FromUTF8(*utf8_value, utf8_value.length());
Tom Sepez3a832662015-03-02 12:59:05 -0800327 CFX_WideString sError;
Tom Sepez39bfe122015-09-17 15:25:23 -0700328 CJS_PropValue PropValue(CJS_Value(isolate, value, CJS_Value::VT_unknown));
Tom Sepez2311b782015-02-23 10:22:51 -0800329 PropValue.StartSetting();
330 if (!pObj->DoProperty(pRuntimeContext, propname.c_str(), PropValue, sError)) {
Tom Sepez39bfe122015-09-17 15:25:23 -0700331 FXJS_Error(isolate, JSFormatErrorString(class_name, "PutProperty", sError));
Tom Sepez2311b782015-02-23 10:22:51 -0800332 }
333}
334
335template <class Alt>
336void JSSpecialPropDel(const char* class_name,
337 v8::Local<v8::String> property,
338 const v8::PropertyCallbackInfo<v8::Boolean>& info) {
339 v8::Isolate* isolate = info.GetIsolate();
340 v8::Local<v8::Context> context = isolate->GetCurrentContext();
Tom Sepeza25fd092015-09-28 09:06:03 -0700341 v8::Local<v8::Value> v = context->GetEmbedderData(1);
342 if (v.IsEmpty())
343 return;
344 v8::Local<v8::External> field = v8::Local<v8::External>::Cast(v);
345 IFXJS_Runtime* pRuntime = (IFXJS_Runtime*)field->Value();
346 IFXJS_Context* pRuntimeContext = pRuntime->GetCurrentContext();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700347 CJS_Object* pJSObj =
Tom Sepez39bfe122015-09-17 15:25:23 -0700348 reinterpret_cast<CJS_Object*>(FXJS_GetPrivate(isolate, info.Holder()));
Tom Sepez2311b782015-02-23 10:22:51 -0800349 Alt* pObj = reinterpret_cast<Alt*>(pJSObj->GetEmbedObject());
350 v8::String::Utf8Value utf8_value(property);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700351 CFX_WideString propname =
352 CFX_WideString::FromUTF8(*utf8_value, utf8_value.length());
Tom Sepez3a832662015-03-02 12:59:05 -0800353 CFX_WideString sError;
Tom Sepez2311b782015-02-23 10:22:51 -0800354 if (!pObj->DelProperty(pRuntimeContext, propname.c_str(), sError)) {
355 CFX_ByteString cbName;
356 cbName.Format("%s.%s", class_name, "DelProperty");
Tom Sepez39bfe122015-09-17 15:25:23 -0700357 // Probably a missing call to JSFX_Error().
Tom Sepez2311b782015-02-23 10:22:51 -0800358 }
359}
360
Tom Sepez142165e2015-09-11 13:21:50 -0700361#define DECLARE_SPECIAL_JS_CLASS(js_class_name) \
362 static void JSConstructor(IFXJS_Context* cc, v8::Local<v8::Object> obj, \
363 v8::Local<v8::Object> global); \
364 static void JSDestructor(v8::Local<v8::Object> obj); \
365 static JSConstSpec JS_Class_Consts[]; \
366 static JSPropertySpec JS_Class_Properties[]; \
367 static JSMethodSpec JS_Class_Methods[]; \
368 static void DefineJSObjects(v8::Isolate* pIsolate, FXJSOBJTYPE eObjType); \
369 static const wchar_t* m_pClassName; \
370 static void queryprop_##js_class_name##_static( \
371 v8::Local<v8::String> property, \
372 const v8::PropertyCallbackInfo<v8::Integer>& info); \
373 static void getprop_##js_class_name##_static( \
374 v8::Local<v8::String> property, \
375 const v8::PropertyCallbackInfo<v8::Value>& info); \
376 static void putprop_##js_class_name##_static( \
377 v8::Local<v8::String> property, v8::Local<v8::Value> value, \
378 const v8::PropertyCallbackInfo<v8::Value>& info); \
379 static void delprop_##js_class_name##_static( \
380 v8::Local<v8::String> property, \
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700381 const v8::PropertyCallbackInfo<v8::Boolean>& info)
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700382
383#define IMPLEMENT_SPECIAL_JS_CLASS(js_class_name, class_alternate, class_name) \
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700384 const wchar_t* js_class_name::m_pClassName = JS_WIDESTRING(class_name); \
385 void js_class_name::queryprop_##js_class_name##_static( \
386 v8::Local<v8::String> property, \
387 const v8::PropertyCallbackInfo<v8::Integer>& info) { \
388 JSSpecialPropQuery<class_alternate>(#class_name, property, info); \
389 } \
390 void js_class_name::getprop_##js_class_name##_static( \
391 v8::Local<v8::String> property, \
392 const v8::PropertyCallbackInfo<v8::Value>& info) { \
393 JSSpecialPropGet<class_alternate>(#class_name, property, info); \
394 } \
395 void js_class_name::putprop_##js_class_name##_static( \
396 v8::Local<v8::String> property, v8::Local<v8::Value> value, \
397 const v8::PropertyCallbackInfo<v8::Value>& info) { \
398 JSSpecialPropPut<class_alternate>(#class_name, property, value, info); \
399 } \
400 void js_class_name::delprop_##js_class_name##_static( \
401 v8::Local<v8::String> property, \
402 const v8::PropertyCallbackInfo<v8::Boolean>& info) { \
403 JSSpecialPropDel<class_alternate>(#class_name, property, info); \
404 } \
Tom Sepez808a99e2015-09-10 12:28:37 -0700405 void js_class_name::JSConstructor(IFXJS_Context* cc, \
406 v8::Local<v8::Object> obj, \
407 v8::Local<v8::Object> global) { \
Nico Weber077f1a32015-08-06 15:08:57 -0700408 CJS_Object* pObj = new js_class_name(obj); \
409 pObj->SetEmbedObject(new class_alternate(pObj)); \
Tom Sepez39bfe122015-09-17 15:25:23 -0700410 FXJS_SetPrivate(NULL, obj, (void*)pObj); \
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700411 pObj->InitInstance(cc); \
412 } \
413 \
Tom Sepez808a99e2015-09-10 12:28:37 -0700414 void js_class_name::JSDestructor(v8::Local<v8::Object> obj) { \
Tom Sepez39bfe122015-09-17 15:25:23 -0700415 js_class_name* pObj = (js_class_name*)FXJS_GetPrivate(NULL, obj); \
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700416 ASSERT(pObj != NULL); \
417 pObj->ExitInstance(); \
418 delete pObj; \
419 } \
420 \
Tom Sepez142165e2015-09-11 13:21:50 -0700421 void js_class_name::DefineJSObjects(v8::Isolate* pIsolate, \
422 FXJSOBJTYPE eObjType) { \
Tom Sepez39bfe122015-09-17 15:25:23 -0700423 int nObjDefnID = FXJS_DefineObj(pIsolate, js_class_name::m_pClassName, \
424 eObjType, JSConstructor, JSDestructor); \
Tom Sepez570875c2015-09-11 08:35:03 -0700425 for (int i = 0; i < FX_ArraySize(JS_Class_Properties) - 1; ++i) { \
Tom Sepez39bfe122015-09-17 15:25:23 -0700426 FXJS_DefineObjProperty( \
427 pIsolate, nObjDefnID, JS_Class_Properties[i].pName, \
428 JS_Class_Properties[i].pPropGet, JS_Class_Properties[i].pPropPut); \
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700429 } \
430 \
Tom Sepez570875c2015-09-11 08:35:03 -0700431 for (int i = 0; i < FX_ArraySize(JS_Class_Methods) - 1; ++i) { \
Tom Sepez39bfe122015-09-17 15:25:23 -0700432 FXJS_DefineObjMethod(pIsolate, nObjDefnID, JS_Class_Methods[i].pName, \
433 JS_Class_Methods[i].pMethodCall); \
Tom Sepez570875c2015-09-11 08:35:03 -0700434 } \
Tom Sepez39bfe122015-09-17 15:25:23 -0700435 FXJS_DefineObjAllProperties( \
Tom Sepez142165e2015-09-11 13:21:50 -0700436 pIsolate, nObjDefnID, \
437 js_class_name::queryprop_##js_class_name##_static, \
438 js_class_name::getprop_##js_class_name##_static, \
439 js_class_name::putprop_##js_class_name##_static, \
440 js_class_name::delprop_##js_class_name##_static); \
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700441 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700442
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700443/* ======================================== GLOBAL METHODS
444 * ============================================ */
Tom Sepeza1160452015-02-19 10:00:55 -0800445
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700446template <FX_BOOL (
447 *F)(IFXJS_Context*, const CJS_Parameters&, CJS_Value&, CFX_WideString&)>
448void JSGlobalFunc(const char* func_name_string,
Tom Sepeza1160452015-02-19 10:00:55 -0800449 const v8::FunctionCallbackInfo<v8::Value>& info) {
450 v8::Isolate* isolate = info.GetIsolate();
Tom Sepeza25fd092015-09-28 09:06:03 -0700451 v8::Local<v8::Context> context = isolate->GetCurrentContext();
452 v8::Local<v8::Value> v = context->GetEmbedderData(1);
453 if (v.IsEmpty())
454 return;
455 v8::Local<v8::External> field = v8::Local<v8::External>::Cast(v);
456 IFXJS_Runtime* pRuntime = (IFXJS_Runtime*)field->Value();
457 IFXJS_Context* pRuntimeContext = pRuntime->GetCurrentContext();
Tom Sepeza1160452015-02-19 10:00:55 -0800458 CJS_Parameters parameters;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700459 for (unsigned int i = 0; i < (unsigned int)info.Length(); i++) {
Tom Sepez39bfe122015-09-17 15:25:23 -0700460 parameters.push_back(CJS_Value(isolate, info[i], CJS_Value::VT_unknown));
Tom Sepeza1160452015-02-19 10:00:55 -0800461 }
462 CJS_Value valueRes(isolate);
Tom Sepez3a832662015-03-02 12:59:05 -0800463 CFX_WideString sError;
464 if (!(*F)(pRuntimeContext, parameters, valueRes, sError)) {
Tom Sepez39bfe122015-09-17 15:25:23 -0700465 FXJS_Error(isolate, JSFormatErrorString(func_name_string, nullptr, sError));
Tom Sepeza1160452015-02-19 10:00:55 -0800466 return;
467 }
Tom Sepezf4ef3f92015-04-23 11:31:31 -0700468 info.GetReturnValue().Set(valueRes.ToV8Value());
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700469}
470
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700471#define JS_STATIC_GLOBAL_FUN(fun_name) \
472 static void fun_name##_static( \
473 const v8::FunctionCallbackInfo<v8::Value>& info) { \
474 JSGlobalFunc<fun_name>(#fun_name, info); \
Tom Sepeza1160452015-02-19 10:00:55 -0800475 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700476
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700477#define JS_STATIC_DECLARE_GLOBAL_FUN() \
478 static JSMethodSpec global_methods[]; \
Tom Sepez142165e2015-09-11 13:21:50 -0700479 static void DefineJSObjects(v8::Isolate* pIsolate)
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700480
481#define BEGIN_JS_STATIC_GLOBAL_FUN(js_class_name) \
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700482 JSMethodSpec js_class_name::global_methods[] = {
483#define JS_STATIC_GLOBAL_FUN_ENTRY(method_name) \
484 JS_STATIC_METHOD_ENTRY(method_name)
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700485
486#define END_JS_STATIC_GLOBAL_FUN() END_JS_STATIC_METHOD()
487
Tom Sepez39bfe122015-09-17 15:25:23 -0700488#define IMPLEMENT_JS_STATIC_GLOBAL_FUN(js_class_name) \
489 void js_class_name::DefineJSObjects(v8::Isolate* pIsolate) { \
490 for (int i = 0; i < FX_ArraySize(global_methods) - 1; ++i) { \
491 FXJS_DefineGlobalMethod(pIsolate, \
492 js_class_name::global_methods[i].pName, \
493 js_class_name::global_methods[i].pMethodCall); \
494 } \
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700495 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700496
Tom Sepez39bfe122015-09-17 15:25:23 -0700497CJS_Value::Type GET_VALUE_TYPE(v8::Local<v8::Value> p);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700498
Tom Sepez19922bb2015-05-28 13:23:12 -0700499#endif // FPDFSDK_INCLUDE_JAVASCRIPT_JS_DEFINE_H_