Home | History | Annotate | Download | only in fxjs
      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 
     14 CJS_V8::CJS_V8(v8::Isolate* isolate) : m_isolate(isolate) {}
     15 
     16 CJS_V8::~CJS_V8() {
     17   m_V8PersistentContext.Reset();
     18 }
     19 
     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 
     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 
     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 
     61 v8::Local<v8::Array> CJS_V8::NewArray() {
     62   return v8::Array::New(m_isolate);
     63 }
     64 
     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 
     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 
     85 unsigned CJS_V8::GetArrayLength(v8::Local<v8::Array> pArray) {
     86   if (pArray.IsEmpty())
     87     return 0;
     88   return pArray->Length();
     89 }
     90 
     91 v8::Local<v8::Context> CJS_V8::NewLocalContext() {
     92   return v8::Local<v8::Context>::New(m_isolate, m_V8PersistentContext);
     93 }
     94 
     95 v8::Local<v8::Context> CJS_V8::GetPersistentContext() {
     96   return m_V8PersistentContext.Get(m_isolate);
     97 }
     98 
     99 v8::Local<v8::Number> CJS_V8::NewNumber(int number) {
    100   return v8::Int32::New(m_isolate, number);
    101 }
    102 
    103 v8::Local<v8::Number> CJS_V8::NewNumber(double number) {
    104   return v8::Number::New(m_isolate, number);
    105 }
    106 
    107 v8::Local<v8::Number> CJS_V8::NewNumber(float number) {
    108   return v8::Number::New(m_isolate, (float)number);
    109 }
    110 
    111 v8::Local<v8::Boolean> CJS_V8::NewBoolean(bool b) {
    112   return v8::Boolean::New(m_isolate, b);
    113 }
    114 
    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 
    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 
    129 v8::Local<v8::Value> CJS_V8::NewNull() {
    130   return v8::Null(m_isolate);
    131 }
    132 
    133 v8::Local<v8::Value> CJS_V8::NewUndefined() {
    134   return v8::Undefined(m_isolate);
    135 }
    136 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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
    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 
    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