1// 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.
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 <vector>
11
12#include "fxjs/cjs_object.h"
13#include "fxjs/cjs_return.h"
14#include "fxjs/fxjs_v8.h"
15#include "fxjs/js_resources.h"
16
17double JS_GetDateTime();
18int JS_GetYearFromTime(double dt);
19int JS_GetMonthFromTime(double dt);
20int JS_GetDayFromTime(double dt);
21int JS_GetHourFromTime(double dt);
22int JS_GetMinFromTime(double dt);
23int JS_GetSecFromTime(double dt);
24double JS_LocalTime(double d);
25double JS_DateParse(const WideString& str);
26double JS_MakeDay(int nYear, int nMonth, int nDay);
27double JS_MakeTime(int nHour, int nMin, int nSec, int nMs);
28double JS_MakeDate(double day, double time);
29
30// Some JS methods have the bizarre convention that they may also be called
31// with a single argument which is an object containing the actual arguments
32// as its properties. The varying arguments to this method are the property
33// names as wchar_t string literals corresponding to each positional argument.
34// The result will always contain |nKeywords| value, with unspecified ones
35// being set to type VT_unknown.
36std::vector<v8::Local<v8::Value>> ExpandKeywordParams(
37    CJS_Runtime* pRuntime,
38    const std::vector<v8::Local<v8::Value>>& originals,
39    size_t nKeywords,
40    ...);
41
42// All JS classes have a name, an object defintion ID, and the ability to
43// register themselves with FXJS_V8. We never make a BASE class on its own
44// because it can't really do anything.
45
46// Rich JS classes provide constants, methods, properties, and the ability
47// to construct native object state.
48
49template <class T, class A>
50static void JSConstructor(CFXJS_Engine* pEngine, v8::Local<v8::Object> obj) {
51  CJS_Object* pObj = new T(obj);
52  pObj->SetEmbedObject(new A(pObj));
53  pEngine->SetObjectPrivate(obj, pObj);
54  pObj->InitInstance(static_cast<CJS_Runtime*>(pEngine));
55}
56
57template <class T>
58static void JSDestructor(CFXJS_Engine* pEngine, v8::Local<v8::Object> obj) {
59  delete static_cast<T*>(pEngine->GetObjectPrivate(obj));
60}
61
62template <class C, CJS_Return (C::*M)(CJS_Runtime*)>
63void JSPropGetter(const char* prop_name_string,
64                  const char* class_name_string,
65                  v8::Local<v8::String> property,
66                  const v8::PropertyCallbackInfo<v8::Value>& info) {
67  CJS_Runtime* pRuntime =
68      CJS_Runtime::CurrentRuntimeFromIsolate(info.GetIsolate());
69  if (!pRuntime)
70    return;
71
72  CJS_Object* pJSObj =
73      static_cast<CJS_Object*>(pRuntime->GetObjectPrivate(info.Holder()));
74  if (!pJSObj)
75    return;
76
77  C* pObj = reinterpret_cast<C*>(pJSObj->GetEmbedObject());
78  CJS_Return result = (pObj->*M)(pRuntime);
79  if (result.HasError()) {
80    pRuntime->Error(JSFormatErrorString(class_name_string, prop_name_string,
81                                        result.Error()));
82    return;
83  }
84
85  if (result.HasReturn())
86    info.GetReturnValue().Set(result.Return());
87}
88
89template <class C, CJS_Return (C::*M)(CJS_Runtime*, v8::Local<v8::Value>)>
90void JSPropSetter(const char* prop_name_string,
91                  const char* class_name_string,
92                  v8::Local<v8::String> property,
93                  v8::Local<v8::Value> value,
94                  const v8::PropertyCallbackInfo<void>& info) {
95  CJS_Runtime* pRuntime =
96      CJS_Runtime::CurrentRuntimeFromIsolate(info.GetIsolate());
97  if (!pRuntime)
98    return;
99
100  CJS_Object* pJSObj =
101      static_cast<CJS_Object*>(pRuntime->GetObjectPrivate(info.Holder()));
102  if (!pJSObj)
103    return;
104
105  C* pObj = reinterpret_cast<C*>(pJSObj->GetEmbedObject());
106  CJS_Return result = (pObj->*M)(pRuntime, value);
107  if (result.HasError()) {
108    pRuntime->Error(JSFormatErrorString(class_name_string, prop_name_string,
109                                        result.Error()));
110  }
111}
112
113template <class C,
114          CJS_Return (C::*M)(CJS_Runtime*,
115                             const std::vector<v8::Local<v8::Value>>&)>
116void JSMethod(const char* method_name_string,
117              const char* class_name_string,
118              const v8::FunctionCallbackInfo<v8::Value>& info) {
119  CJS_Runtime* pRuntime =
120      CJS_Runtime::CurrentRuntimeFromIsolate(info.GetIsolate());
121  if (!pRuntime)
122    return;
123
124  CJS_Object* pJSObj =
125      static_cast<CJS_Object*>(pRuntime->GetObjectPrivate(info.Holder()));
126  if (!pJSObj)
127    return;
128
129  std::vector<v8::Local<v8::Value>> parameters;
130  for (unsigned int i = 0; i < (unsigned int)info.Length(); i++)
131    parameters.push_back(info[i]);
132
133  C* pObj = reinterpret_cast<C*>(pJSObj->GetEmbedObject());
134  CJS_Return result = (pObj->*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::String> property,                             \
148      const v8::PropertyCallbackInfo<v8::Value>& info) {          \
149    JSPropGetter<class_name, &class_name::get_##prop_name>(       \
150        #err_name, #class_name, property, info);                  \
151  }                                                               \
152  static void set_##prop_name##_static(                           \
153      v8::Local<v8::String> 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, 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, #class_name, \
163                                                   info);                     \
164  }
165
166#endif  // FXJS_JS_DEFINE_H_
167