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