• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2017 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 #include "fxjs/cjs_v8.h"
8 
9 #ifdef PDF_ENABLE_XFA
10 #include "fxjs/cfxjse_context.h"
11 #include "xfa/fxfa/parser/cxfa_object.h"
12 #endif  // PDF_ENABLE_XFA
13 
CJS_V8(v8::Isolate * isolate)14 CJS_V8::CJS_V8(v8::Isolate* isolate) : m_isolate(isolate) {}
15 
~CJS_V8()16 CJS_V8::~CJS_V8() {
17   m_V8PersistentContext.Reset();
18 }
19 
GetObjectProperty(v8::Local<v8::Object> pObj,const WideString & wsPropertyName)20 v8::Local<v8::Value> CJS_V8::GetObjectProperty(
21     v8::Local<v8::Object> pObj,
22     const WideString& wsPropertyName) {
23   if (pObj.IsEmpty())
24     return v8::Local<v8::Value>();
25   v8::Local<v8::Value> val;
26   if (!pObj->Get(m_isolate->GetCurrentContext(),
27                  NewString(wsPropertyName.AsStringView()))
28            .ToLocal(&val))
29     return v8::Local<v8::Value>();
30   return val;
31 }
32 
GetObjectPropertyNames(v8::Local<v8::Object> pObj)33 std::vector<WideString> CJS_V8::GetObjectPropertyNames(
34     v8::Local<v8::Object> pObj) {
35   if (pObj.IsEmpty())
36     return std::vector<WideString>();
37 
38   v8::Local<v8::Array> val;
39   v8::Local<v8::Context> context = m_isolate->GetCurrentContext();
40   if (!pObj->GetPropertyNames(context).ToLocal(&val))
41     return std::vector<WideString>();
42 
43   std::vector<WideString> result;
44   for (uint32_t i = 0; i < val->Length(); ++i) {
45     result.push_back(ToWideString(val->Get(context, i).ToLocalChecked()));
46   }
47 
48   return result;
49 }
50 
PutObjectProperty(v8::Local<v8::Object> pObj,const WideString & wsPropertyName,v8::Local<v8::Value> pPut)51 void CJS_V8::PutObjectProperty(v8::Local<v8::Object> pObj,
52                                const WideString& wsPropertyName,
53                                v8::Local<v8::Value> pPut) {
54   if (pObj.IsEmpty())
55     return;
56   pObj->Set(m_isolate->GetCurrentContext(),
57             NewString(wsPropertyName.AsStringView()), pPut)
58       .FromJust();
59 }
60 
NewArray()61 v8::Local<v8::Array> CJS_V8::NewArray() {
62   return v8::Array::New(m_isolate);
63 }
64 
PutArrayElement(v8::Local<v8::Array> pArray,unsigned index,v8::Local<v8::Value> pValue)65 unsigned CJS_V8::PutArrayElement(v8::Local<v8::Array> pArray,
66                                  unsigned index,
67                                  v8::Local<v8::Value> pValue) {
68   if (pArray.IsEmpty())
69     return 0;
70   if (pArray->Set(m_isolate->GetCurrentContext(), index, pValue).IsNothing())
71     return 0;
72   return 1;
73 }
74 
GetArrayElement(v8::Local<v8::Array> pArray,unsigned index)75 v8::Local<v8::Value> CJS_V8::GetArrayElement(v8::Local<v8::Array> pArray,
76                                              unsigned index) {
77   if (pArray.IsEmpty())
78     return v8::Local<v8::Value>();
79   v8::Local<v8::Value> val;
80   if (!pArray->Get(m_isolate->GetCurrentContext(), index).ToLocal(&val))
81     return v8::Local<v8::Value>();
82   return val;
83 }
84 
GetArrayLength(v8::Local<v8::Array> pArray)85 unsigned CJS_V8::GetArrayLength(v8::Local<v8::Array> pArray) {
86   if (pArray.IsEmpty())
87     return 0;
88   return pArray->Length();
89 }
90 
NewLocalContext()91 v8::Local<v8::Context> CJS_V8::NewLocalContext() {
92   return v8::Local<v8::Context>::New(m_isolate, m_V8PersistentContext);
93 }
94 
GetPersistentContext()95 v8::Local<v8::Context> CJS_V8::GetPersistentContext() {
96   return m_V8PersistentContext.Get(m_isolate);
97 }
98 
NewNumber(int number)99 v8::Local<v8::Number> CJS_V8::NewNumber(int number) {
100   return v8::Int32::New(m_isolate, number);
101 }
102 
NewNumber(double number)103 v8::Local<v8::Number> CJS_V8::NewNumber(double number) {
104   return v8::Number::New(m_isolate, number);
105 }
106 
NewNumber(float number)107 v8::Local<v8::Number> CJS_V8::NewNumber(float number) {
108   return v8::Number::New(m_isolate, (float)number);
109 }
110 
NewBoolean(bool b)111 v8::Local<v8::Boolean> CJS_V8::NewBoolean(bool b) {
112   return v8::Boolean::New(m_isolate, b);
113 }
114 
NewString(const ByteStringView & str)115 v8::Local<v8::String> CJS_V8::NewString(const ByteStringView& str) {
116   v8::Isolate* pIsolate = m_isolate ? m_isolate : v8::Isolate::GetCurrent();
117   return v8::String::NewFromUtf8(pIsolate, str.unterminated_c_str(),
118                                  v8::NewStringType::kNormal, str.GetLength())
119       .ToLocalChecked();
120 }
121 
NewString(const WideStringView & str)122 v8::Local<v8::String> CJS_V8::NewString(const WideStringView& str) {
123   // Conversion from pdfium's wchar_t wide-strings to v8's uint16_t
124   // wide-strings isn't handled by v8, so use UTF8 as a common
125   // intermediate format.
126   return NewString(FX_UTF8Encode(str).AsStringView());
127 }
128 
NewNull()129 v8::Local<v8::Value> CJS_V8::NewNull() {
130   return v8::Null(m_isolate);
131 }
132 
NewUndefined()133 v8::Local<v8::Value> CJS_V8::NewUndefined() {
134   return v8::Undefined(m_isolate);
135 }
136 
NewDate(double d)137 v8::Local<v8::Date> CJS_V8::NewDate(double d) {
138   return v8::Date::New(m_isolate->GetCurrentContext(), d)
139       .ToLocalChecked()
140       .As<v8::Date>();
141 }
142 
ToInt32(v8::Local<v8::Value> pValue)143 int CJS_V8::ToInt32(v8::Local<v8::Value> pValue) {
144   if (pValue.IsEmpty())
145     return 0;
146   v8::Local<v8::Context> context = m_isolate->GetCurrentContext();
147   v8::MaybeLocal<v8::Int32> maybe_int32 = pValue->ToInt32(context);
148   if (maybe_int32.IsEmpty())
149     return 0;
150   return maybe_int32.ToLocalChecked()->Value();
151 }
152 
ToBoolean(v8::Local<v8::Value> pValue)153 bool CJS_V8::ToBoolean(v8::Local<v8::Value> pValue) {
154   if (pValue.IsEmpty())
155     return false;
156   v8::Local<v8::Context> context = m_isolate->GetCurrentContext();
157   v8::MaybeLocal<v8::Boolean> maybe_boolean = pValue->ToBoolean(context);
158   if (maybe_boolean.IsEmpty())
159     return false;
160   return maybe_boolean.ToLocalChecked()->Value();
161 }
162 
ToDouble(v8::Local<v8::Value> pValue)163 double CJS_V8::ToDouble(v8::Local<v8::Value> pValue) {
164   if (pValue.IsEmpty())
165     return 0.0;
166   v8::Local<v8::Context> context = m_isolate->GetCurrentContext();
167   v8::MaybeLocal<v8::Number> maybe_number = pValue->ToNumber(context);
168   if (maybe_number.IsEmpty())
169     return 0.0;
170   return maybe_number.ToLocalChecked()->Value();
171 }
172 
ToWideString(v8::Local<v8::Value> pValue)173 WideString CJS_V8::ToWideString(v8::Local<v8::Value> pValue) {
174   if (pValue.IsEmpty())
175     return WideString();
176   v8::Local<v8::Context> context = m_isolate->GetCurrentContext();
177   v8::MaybeLocal<v8::String> maybe_string = pValue->ToString(context);
178   if (maybe_string.IsEmpty())
179     return WideString();
180   v8::String::Utf8Value s(m_isolate, maybe_string.ToLocalChecked());
181   return WideString::FromUTF8(ByteStringView(*s, s.length()));
182 }
183 
ToByteString(v8::Local<v8::Value> pValue)184 ByteString CJS_V8::ToByteString(v8::Local<v8::Value> pValue) {
185   if (pValue.IsEmpty())
186     return ByteString();
187   v8::Local<v8::Context> context = m_isolate->GetCurrentContext();
188   v8::MaybeLocal<v8::String> maybe_string = pValue->ToString(context);
189   if (maybe_string.IsEmpty())
190     return ByteString();
191   v8::String::Utf8Value s(m_isolate, maybe_string.ToLocalChecked());
192   return ByteString(*s);
193 }
194 
ToObject(v8::Local<v8::Value> pValue)195 v8::Local<v8::Object> CJS_V8::ToObject(v8::Local<v8::Value> pValue) {
196   if (pValue.IsEmpty() || !pValue->IsObject())
197     return v8::Local<v8::Object>();
198   v8::Local<v8::Context> context = m_isolate->GetCurrentContext();
199   return pValue->ToObject(context).ToLocalChecked();
200 }
201 
ToArray(v8::Local<v8::Value> pValue)202 v8::Local<v8::Array> CJS_V8::ToArray(v8::Local<v8::Value> pValue) {
203   if (pValue.IsEmpty() || !pValue->IsArray())
204     return v8::Local<v8::Array>();
205   v8::Local<v8::Context> context = m_isolate->GetCurrentContext();
206   return v8::Local<v8::Array>::Cast(pValue->ToObject(context).ToLocalChecked());
207 }
208 
SetConstArray(const WideString & name,v8::Local<v8::Array> array)209 void CJS_V8::SetConstArray(const WideString& name, v8::Local<v8::Array> array) {
210   m_ConstArrays[name] = v8::Global<v8::Array>(GetIsolate(), array);
211 }
212 
GetConstArray(const WideString & name)213 v8::Local<v8::Array> CJS_V8::GetConstArray(const WideString& name) {
214   return v8::Local<v8::Array>::New(GetIsolate(), m_ConstArrays[name]);
215 }
216 
217 #ifdef PDF_ENABLE_XFA
ToXFAObject(v8::Local<v8::Value> obj)218 CXFA_Object* CJS_V8::ToXFAObject(v8::Local<v8::Value> obj) {
219   ASSERT(!obj.IsEmpty());
220 
221   if (!obj->IsObject())
222     return nullptr;
223 
224   CFXJSE_HostObject* hostObj =
225       FXJSE_RetrieveObjectBinding(obj.As<v8::Object>(), nullptr);
226   if (!hostObj || hostObj->type() != CFXJSE_HostObject::kXFA)
227     return nullptr;
228   return static_cast<CXFA_Object*>(hostObj);
229 }
230 
NewXFAObject(CXFA_Object * obj,v8::Global<v8::FunctionTemplate> & tmpl)231 v8::Local<v8::Value> CJS_V8::NewXFAObject(
232     CXFA_Object* obj,
233     v8::Global<v8::FunctionTemplate>& tmpl) {
234   v8::EscapableHandleScope scope(m_isolate);
235   v8::Local<v8::FunctionTemplate> klass =
236       v8::Local<v8::FunctionTemplate>::New(m_isolate, tmpl);
237   v8::Local<v8::Object> object = klass->InstanceTemplate()->NewInstance();
238   FXJSE_UpdateObjectBinding(object, obj);
239   return scope.Escape(object);
240 }
241 #endif  // PDF_ENABLE_XFA
242