fxjs_v8.h revision 4d3acf4ec42bf6e838f9060103aff98fbf170794
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// FXJS_V8 is a layer that makes it easier to define native objects in V8, but
8// has no knowledge of PDF-specific native objects. It could in theory be used
9// to implement other sets of native objects.
10
11// PDFium code should include this file rather than including V8 headers
12// directly.
13
14#ifndef FXJS_FXJS_V8_H_
15#define FXJS_FXJS_V8_H_
16
17#include <v8-util.h>
18#include <v8.h>
19
20#include <map>
21#include <memory>
22#include <vector>
23
24#include "core/fxcrt/fx_string.h"
25#ifdef PDF_ENABLE_XFA
26// Header for CFXJSE_RuntimeData. FXJS_V8 doesn't interpret this class,
27// it is just passed along to XFA.
28#include "fxjs/cfxjse_runtimedata.h"
29#endif  // PDF_ENABLE_XFA
30
31class CFXJS_Engine;
32class CFXJS_ObjDefinition;
33
34// FXJS_V8 places no restrictions on this class; it merely passes it
35// on to caller-provided methods.
36class IJS_Context;  // A description of the event that caused JS execution.
37
38enum FXJSOBJTYPE {
39  FXJSOBJTYPE_DYNAMIC = 0,  // Created by native method and returned to JS.
40  FXJSOBJTYPE_STATIC,       // Created by init and hung off of global object.
41  FXJSOBJTYPE_GLOBAL,       // The global object itself (may only appear once).
42};
43
44struct FXJSErr {
45  const wchar_t* message;
46  const wchar_t* srcline;
47  unsigned linnum;
48};
49
50// Global weak map to save dynamic objects.
51class V8TemplateMapTraits : public v8::StdMapTraits<void*, v8::Object> {
52 public:
53  typedef v8::GlobalValueMap<void*, v8::Object, V8TemplateMapTraits> MapType;
54  typedef void WeakCallbackDataType;
55
56  static WeakCallbackDataType* WeakCallbackParameter(
57      MapType* map,
58      void* key,
59      const v8::Local<v8::Object>& value) {
60    return key;
61  }
62  static MapType* MapFromWeakCallbackInfo(
63      const v8::WeakCallbackInfo<WeakCallbackDataType>&);
64
65  static void* KeyFromWeakCallbackInfo(
66      const v8::WeakCallbackInfo<WeakCallbackDataType>& data) {
67    return data.GetParameter();
68  }
69  static const v8::PersistentContainerCallbackType kCallbackType =
70      v8::kWeakWithInternalFields;
71  static void DisposeWeak(
72      const v8::WeakCallbackInfo<WeakCallbackDataType>& data) {}
73  static void OnWeakCallback(
74      const v8::WeakCallbackInfo<WeakCallbackDataType>& data) {}
75  static void Dispose(v8::Isolate* isolate,
76                      v8::Global<v8::Object> value,
77                      void* key);
78  static void DisposeCallbackData(WeakCallbackDataType* callbackData) {}
79};
80
81class V8TemplateMap {
82 public:
83  typedef v8::GlobalValueMap<void*, v8::Object, V8TemplateMapTraits> MapType;
84
85  explicit V8TemplateMap(v8::Isolate* isolate);
86  ~V8TemplateMap();
87
88  void set(void* key, v8::Local<v8::Object> handle);
89
90  friend class V8TemplateMapTraits;
91
92 private:
93  MapType m_map;
94};
95
96class FXJS_PerIsolateData {
97 public:
98  ~FXJS_PerIsolateData();
99
100  static void SetUp(v8::Isolate* pIsolate);
101  static FXJS_PerIsolateData* Get(v8::Isolate* pIsolate);
102
103  std::vector<std::unique_ptr<CFXJS_ObjDefinition>> m_ObjectDefnArray;
104#ifdef PDF_ENABLE_XFA
105  std::unique_ptr<CFXJSE_RuntimeData> m_pFXJSERuntimeData;
106#endif  // PDF_ENABLE_XFA
107  std::unique_ptr<V8TemplateMap> m_pDynamicObjsMap;
108
109 protected:
110  explicit FXJS_PerIsolateData(v8::Isolate* pIsolate);
111};
112
113class FXJS_ArrayBufferAllocator : public v8::ArrayBuffer::Allocator {
114  void* Allocate(size_t length) override;
115  void* AllocateUninitialized(size_t length) override;
116  void Free(void* data, size_t length) override;
117};
118
119void FXJS_Initialize(unsigned int embedderDataSlot, v8::Isolate* pIsolate);
120void FXJS_Release();
121
122// Gets the global isolate set by FXJS_Initialize(), or makes a new one each
123// time if there is no such isolate. Returns true if a new isolate had to be
124// created.
125bool FXJS_GetIsolate(v8::Isolate** pResultIsolate);
126
127// Get the global isolate's ref count.
128size_t FXJS_GlobalIsolateRefCount();
129
130class CFXJS_Engine {
131 public:
132  explicit CFXJS_Engine(v8::Isolate* pIsolate);
133  ~CFXJS_Engine();
134
135  using Constructor = void (*)(CFXJS_Engine* pEngine,
136                               v8::Local<v8::Object> obj);
137  using Destructor = void (*)(CFXJS_Engine* pEngine, v8::Local<v8::Object> obj);
138
139  static CFXJS_Engine* CurrentEngineFromIsolate(v8::Isolate* pIsolate);
140  static int GetObjDefnID(v8::Local<v8::Object> pObj);
141
142  v8::Isolate* GetIsolate() const { return m_isolate; }
143
144  // Always returns a valid, newly-created objDefnID.
145  int DefineObj(const wchar_t* sObjName,
146                FXJSOBJTYPE eObjType,
147                Constructor pConstructor,
148                Destructor pDestructor);
149
150  void DefineObjMethod(int nObjDefnID,
151                       const wchar_t* sMethodName,
152                       v8::FunctionCallback pMethodCall);
153  void DefineObjProperty(int nObjDefnID,
154                         const wchar_t* sPropName,
155                         v8::AccessorGetterCallback pPropGet,
156                         v8::AccessorSetterCallback pPropPut);
157  void DefineObjAllProperties(int nObjDefnID,
158                              v8::NamedPropertyQueryCallback pPropQurey,
159                              v8::NamedPropertyGetterCallback pPropGet,
160                              v8::NamedPropertySetterCallback pPropPut,
161                              v8::NamedPropertyDeleterCallback pPropDel);
162  void DefineObjConst(int nObjDefnID,
163                      const wchar_t* sConstName,
164                      v8::Local<v8::Value> pDefault);
165  void DefineGlobalMethod(const wchar_t* sMethodName,
166                          v8::FunctionCallback pMethodCall);
167  void DefineGlobalConst(const wchar_t* sConstName,
168                         v8::FunctionCallback pConstGetter);
169
170  // Called after FXJS_Define* calls made.
171  void InitializeEngine();
172  void ReleaseEngine();
173
174  // Called after FXJS_InitializeEngine call made.
175  int Execute(const CFX_WideString& script, FXJSErr* perror);
176
177  v8::Local<v8::Context> NewLocalContext();
178  v8::Local<v8::Context> GetPersistentContext();
179  v8::Local<v8::Object> GetThisObj();
180
181  v8::Local<v8::Value> NewNull();
182  v8::Local<v8::Array> NewArray();
183  v8::Local<v8::Value> NewNumber(int number);
184  v8::Local<v8::Value> NewNumber(double number);
185  v8::Local<v8::Value> NewNumber(float number);
186  v8::Local<v8::Value> NewBoolean(bool b);
187  v8::Local<v8::Value> NewString(const CFX_WideString& str);
188  v8::Local<v8::Date> NewDate(double d);
189  v8::Local<v8::Object> NewFxDynamicObj(int nObjDefnID, bool bStatic = false);
190
191  int ToInt32(v8::Local<v8::Value> pValue);
192  bool ToBoolean(v8::Local<v8::Value> pValue);
193  double ToDouble(v8::Local<v8::Value> pValue);
194  CFX_WideString ToWideString(v8::Local<v8::Value> pValue);
195  v8::Local<v8::Object> ToObject(v8::Local<v8::Value> pValue);
196  v8::Local<v8::Array> ToArray(v8::Local<v8::Value> pValue);
197
198  // Arrays.
199  unsigned GetArrayLength(v8::Local<v8::Array> pArray);
200  v8::Local<v8::Value> GetArrayElement(v8::Local<v8::Array> pArray,
201                                       unsigned index);
202  unsigned PutArrayElement(v8::Local<v8::Array> pArray,
203                           unsigned index,
204                           v8::Local<v8::Value> pValue);
205
206  // Objects.
207  std::vector<CFX_WideString> GetObjectPropertyNames(
208      v8::Local<v8::Object> pObj);
209  v8::Local<v8::Value> GetObjectProperty(v8::Local<v8::Object> pObj,
210                                         const CFX_WideString& PropertyName);
211  void PutObjectProperty(v8::Local<v8::Object> pObj,
212                         const CFX_WideString& PropertyName,
213                         v8::Local<v8::Value> pValue);
214
215  // Native object binding.
216  void SetObjectPrivate(v8::Local<v8::Object> pObj, void* p);
217  void* GetObjectPrivate(v8::Local<v8::Object> pObj);
218  static void FreeObjectPrivate(void* p);
219  static void FreeObjectPrivate(v8::Local<v8::Object> pObj);
220
221  void SetConstArray(const CFX_WideString& name, v8::Local<v8::Array> array);
222  v8::Local<v8::Array> GetConstArray(const CFX_WideString& name);
223
224  v8::Local<v8::String> WSToJSString(const CFX_WideString& wsPropertyName);
225  void Error(const CFX_WideString& message);
226
227 protected:
228  CFXJS_Engine();
229
230  void SetIsolate(v8::Isolate* pIsolate) { m_isolate = pIsolate; }
231
232 private:
233  v8::Isolate* m_isolate;
234  v8::Global<v8::Context> m_V8PersistentContext;
235  std::vector<v8::Global<v8::Object>*> m_StaticObjects;
236  std::map<CFX_WideString, v8::Global<v8::Array>> m_ConstArrays;
237};
238
239#endif  // FXJS_FXJS_V8_H_
240