• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2014 The PDFium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6 
7 #ifndef FXJS_JS_DEFINE_H_
8 #define FXJS_JS_DEFINE_H_
9 
10 #include <memory>
11 #include <vector>
12 
13 #include "core/fxcrt/unowned_ptr.h"
14 #include "fxjs/cfxjs_engine.h"
15 #include "fxjs/cjs_result.h"
16 #include "fxjs/cjs_runtime.h"
17 #include "fxjs/js_resources.h"
18 
19 class CJS_Object;
20 
21 double JS_DateParse(v8::Isolate* pIsolate, const WideString& str);
22 
23 // Some JS methods have the bizarre convention that they may also be called
24 // with a single argument which is an object containing the actual arguments
25 // as its properties. The varying arguments to this method are the property
26 // names as wchar_t string literals corresponding to each positional argument.
27 // The result will always contain |nKeywords| value, check for the unspecified
28 // ones in the result using IsExpandedParamKnown() below.
29 std::vector<v8::Local<v8::Value>> ExpandKeywordParams(
30     CJS_Runtime* pRuntime,
31     const std::vector<v8::Local<v8::Value>>& originals,
32     size_t nKeywords,
33     ...);
34 
35 bool IsExpandedParamKnown(v8::Local<v8::Value> value);
36 
37 // All JS classes have a name, an object defintion ID, and the ability to
38 // register themselves with FXJS_V8. We never make a BASE class on its own
39 // because it can't really do anything.
40 
41 // Rich JS classes provide constants, methods, properties, and the ability
42 // to construct native object state.
43 
44 template <class T>
JSConstructor(CFXJS_Engine * pEngine,v8::Local<v8::Object> obj,v8::Local<v8::Object> proxy)45 static void JSConstructor(CFXJS_Engine* pEngine,
46                           v8::Local<v8::Object> obj,
47                           v8::Local<v8::Object> proxy) {
48   pEngine->SetObjectPrivate(
49       obj, std::make_unique<T>(proxy, static_cast<CJS_Runtime*>(pEngine)));
50 }
51 
52 // CJS_Object has virtual dtor, template not required.
53 void JSDestructor(v8::Local<v8::Object> obj);
54 
55 template <class C>
JSGetObject(v8::Isolate * isolate,v8::Local<v8::Object> obj)56 UnownedPtr<C> JSGetObject(v8::Isolate* isolate, v8::Local<v8::Object> obj) {
57   if (CFXJS_Engine::GetObjDefnID(obj) != C::GetObjDefnID())
58     return nullptr;
59 
60   CJS_Object* pJSObj = CFXJS_Engine::GetObjectPrivate(isolate, obj);
61   if (!pJSObj)
62     return nullptr;
63 
64   return UnownedPtr<C>(static_cast<C*>(pJSObj));
65 }
66 
67 template <class C, CJS_Result (C::*M)(CJS_Runtime*)>
JSPropGetter(const char * prop_name_string,const char * class_name_string,v8::Local<v8::String> property,const v8::PropertyCallbackInfo<v8::Value> & info)68 void JSPropGetter(const char* prop_name_string,
69                   const char* class_name_string,
70                   v8::Local<v8::String> property,
71                   const v8::PropertyCallbackInfo<v8::Value>& info) {
72   auto pObj = JSGetObject<C>(info.GetIsolate(), info.Holder());
73   if (!pObj)
74     return;
75 
76   CJS_Runtime* pRuntime = pObj->GetRuntime();
77   if (!pRuntime)
78     return;
79 
80   CJS_Result result = (pObj.get()->*M)(pRuntime);
81   if (result.HasError()) {
82     pRuntime->Error(JSFormatErrorString(class_name_string, prop_name_string,
83                                         result.Error()));
84     return;
85   }
86 
87   if (result.HasReturn())
88     info.GetReturnValue().Set(result.Return());
89 }
90 
91 template <class C, CJS_Result (C::*M)(CJS_Runtime*, v8::Local<v8::Value>)>
JSPropSetter(const char * prop_name_string,const char * class_name_string,v8::Local<v8::String> property,v8::Local<v8::Value> value,const v8::PropertyCallbackInfo<void> & info)92 void JSPropSetter(const char* prop_name_string,
93                   const char* class_name_string,
94                   v8::Local<v8::String> property,
95                   v8::Local<v8::Value> value,
96                   const v8::PropertyCallbackInfo<void>& info) {
97   auto pObj = JSGetObject<C>(info.GetIsolate(), info.Holder());
98   if (!pObj)
99     return;
100 
101   CJS_Runtime* pRuntime = pObj->GetRuntime();
102   if (!pRuntime)
103     return;
104 
105   CJS_Result result = (pObj.get()->*M)(pRuntime, value);
106   if (result.HasError()) {
107     pRuntime->Error(JSFormatErrorString(class_name_string, prop_name_string,
108                                         result.Error()));
109   }
110 }
111 
112 template <class C,
113           CJS_Result (C::*M)(CJS_Runtime*,
114                              const std::vector<v8::Local<v8::Value>>&)>
JSMethod(const char * method_name_string,const char * class_name_string,const v8::FunctionCallbackInfo<v8::Value> & info)115 void JSMethod(const char* method_name_string,
116               const char* class_name_string,
117               const v8::FunctionCallbackInfo<v8::Value>& info) {
118   auto pObj = JSGetObject<C>(info.GetIsolate(), info.Holder());
119   if (!pObj)
120     return;
121 
122   CJS_Runtime* pRuntime = pObj->GetRuntime();
123   if (!pRuntime)
124     return;
125 
126   std::vector<v8::Local<v8::Value>> parameters;
127   for (unsigned int i = 0; i < (unsigned int)info.Length(); i++)
128     parameters.push_back(info[i]);
129 
130   CJS_Result result = (pObj.get()->*M)(pRuntime, parameters);
131   if (result.HasError()) {
132     pRuntime->Error(JSFormatErrorString(class_name_string, method_name_string,
133                                         result.Error()));
134     return;
135   }
136 
137   if (result.HasReturn())
138     info.GetReturnValue().Set(result.Return());
139 }
140 
141 #define JS_STATIC_PROP(err_name, prop_name, class_name)           \
142   static void get_##prop_name##_static(                           \
143       v8::Local<v8::String> property,                             \
144       const v8::PropertyCallbackInfo<v8::Value>& info) {          \
145     JSPropGetter<class_name, &class_name::get_##prop_name>(       \
146         #err_name, class_name::kName, property, info);            \
147   }                                                               \
148   static void set_##prop_name##_static(                           \
149       v8::Local<v8::String> property, v8::Local<v8::Value> value, \
150       const v8::PropertyCallbackInfo<void>& info) {               \
151     JSPropSetter<class_name, &class_name::set_##prop_name>(       \
152         #err_name, class_name::kName, property, value, info);     \
153   }
154 
155 #define JS_STATIC_METHOD(method_name, class_name)                            \
156   static void method_name##_static(                                          \
157       const v8::FunctionCallbackInfo<v8::Value>& info) {                     \
158     JSMethod<class_name, &class_name::method_name>(#method_name,             \
159                                                    class_name::kName, info); \
160   }
161 
162 #endif  // FXJS_JS_DEFINE_H_
163