Home | History | Annotate | Download | only in src
      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 #include "xfa/src/foxitlib.h"
      8 #include "fxv8.h"
      9 #include "value.h"
     10 #include "class.h"
     11 #include <math.h>
     12 #include "util_inline.h"
     13 FX_BOOL FXJSE_Value_IsUndefined(FXJSE_HVALUE hValue) {
     14   CFXJSE_Value* lpValue = reinterpret_cast<CFXJSE_Value*>(hValue);
     15   return lpValue && lpValue->IsUndefined();
     16 }
     17 FX_BOOL FXJSE_Value_IsNull(FXJSE_HVALUE hValue) {
     18   CFXJSE_Value* lpValue = reinterpret_cast<CFXJSE_Value*>(hValue);
     19   return lpValue && lpValue->IsNull();
     20 }
     21 FX_BOOL FXJSE_Value_IsBoolean(FXJSE_HVALUE hValue) {
     22   CFXJSE_Value* lpValue = reinterpret_cast<CFXJSE_Value*>(hValue);
     23   return lpValue && lpValue->IsBoolean();
     24 }
     25 FX_BOOL FXJSE_Value_IsUTF8String(FXJSE_HVALUE hValue) {
     26   CFXJSE_Value* lpValue = reinterpret_cast<CFXJSE_Value*>(hValue);
     27   return lpValue && lpValue->IsString();
     28 }
     29 FX_BOOL FXJSE_Value_IsNumber(FXJSE_HVALUE hValue) {
     30   CFXJSE_Value* lpValue = reinterpret_cast<CFXJSE_Value*>(hValue);
     31   return lpValue && lpValue->IsNumber();
     32 }
     33 FX_BOOL FXJSE_Value_IsInteger(FXJSE_HVALUE hValue) {
     34   CFXJSE_Value* lpValue = reinterpret_cast<CFXJSE_Value*>(hValue);
     35   return lpValue && lpValue->IsInteger();
     36 }
     37 FX_BOOL FXJSE_Value_IsObject(FXJSE_HVALUE hValue) {
     38   CFXJSE_Value* lpValue = reinterpret_cast<CFXJSE_Value*>(hValue);
     39   return lpValue && lpValue->IsObject();
     40 }
     41 FX_BOOL FXJSE_Value_IsArray(FXJSE_HVALUE hValue) {
     42   CFXJSE_Value* lpValue = reinterpret_cast<CFXJSE_Value*>(hValue);
     43   return lpValue && lpValue->IsArray();
     44 }
     45 FX_BOOL FXJSE_Value_IsFunction(FXJSE_HVALUE hValue) {
     46   CFXJSE_Value* lpValue = reinterpret_cast<CFXJSE_Value*>(hValue);
     47   return lpValue && lpValue->IsFunction();
     48 }
     49 FX_BOOL FXJSE_Value_IsDate(FXJSE_HVALUE hValue) {
     50   CFXJSE_Value* lpValue = reinterpret_cast<CFXJSE_Value*>(hValue);
     51   return lpValue && lpValue->IsDate();
     52 }
     53 FX_BOOL FXJSE_Value_ToBoolean(FXJSE_HVALUE hValue) {
     54   CFXJSE_Value* lpValue = reinterpret_cast<CFXJSE_Value*>(hValue);
     55   ASSERT(lpValue);
     56   return lpValue->ToBoolean();
     57 }
     58 FX_FLOAT FXJSE_Value_ToFloat(FXJSE_HVALUE hValue) {
     59   CFXJSE_Value* lpValue = reinterpret_cast<CFXJSE_Value*>(hValue);
     60   ASSERT(lpValue);
     61   return lpValue->ToFloat();
     62 }
     63 FXJSE_DOUBLE FXJSE_Value_ToDouble(FXJSE_HVALUE hValue) {
     64   CFXJSE_Value* lpValue = reinterpret_cast<CFXJSE_Value*>(hValue);
     65   ASSERT(lpValue);
     66   return lpValue->ToDouble();
     67 }
     68 void FXJSE_Value_ToUTF8String(FXJSE_HVALUE hValue,
     69                               CFX_ByteString& szStrOutput) {
     70   CFXJSE_Value* lpValue = reinterpret_cast<CFXJSE_Value*>(hValue);
     71   ASSERT(lpValue);
     72   return lpValue->ToString(szStrOutput);
     73 }
     74 int32_t FXJSE_Value_ToInteger(FXJSE_HVALUE hValue) {
     75   CFXJSE_Value* lpValue = reinterpret_cast<CFXJSE_Value*>(hValue);
     76   ASSERT(lpValue);
     77   return lpValue->ToInteger();
     78 }
     79 void* FXJSE_Value_ToObject(FXJSE_HVALUE hValue, FXJSE_HCLASS hClass) {
     80   CFXJSE_Value* lpValue = reinterpret_cast<CFXJSE_Value*>(hValue);
     81   CFXJSE_Class* lpClass = reinterpret_cast<CFXJSE_Class*>(hClass);
     82   ASSERT(lpValue);
     83   return lpValue->ToObject(lpClass);
     84 }
     85 void FXJSE_Value_SetUndefined(FXJSE_HVALUE hValue) {
     86   CFXJSE_Value* lpValue = reinterpret_cast<CFXJSE_Value*>(hValue);
     87   ASSERT(lpValue);
     88   return lpValue->SetUndefined();
     89 }
     90 void FXJSE_Value_SetNull(FXJSE_HVALUE hValue) {
     91   CFXJSE_Value* lpValue = reinterpret_cast<CFXJSE_Value*>(hValue);
     92   ASSERT(lpValue);
     93   return lpValue->SetNull();
     94 }
     95 void FXJSE_Value_SetBoolean(FXJSE_HVALUE hValue, FX_BOOL bBoolean) {
     96   CFXJSE_Value* lpValue = reinterpret_cast<CFXJSE_Value*>(hValue);
     97   ASSERT(lpValue);
     98   return lpValue->SetBoolean(bBoolean);
     99 }
    100 void FXJSE_Value_SetUTF8String(FXJSE_HVALUE hValue,
    101                                const CFX_ByteStringC& szString) {
    102   CFXJSE_Value* lpValue = reinterpret_cast<CFXJSE_Value*>(hValue);
    103   ASSERT(lpValue);
    104   return lpValue->SetString(szString);
    105 }
    106 void FXJSE_Value_SetInteger(FXJSE_HVALUE hValue, int32_t nInteger) {
    107   CFXJSE_Value* lpValue = reinterpret_cast<CFXJSE_Value*>(hValue);
    108   ASSERT(lpValue);
    109   return lpValue->SetInteger(nInteger);
    110 }
    111 void FXJSE_Value_SetFloat(FXJSE_HVALUE hValue, FX_FLOAT fFloat) {
    112   CFXJSE_Value* lpValue = reinterpret_cast<CFXJSE_Value*>(hValue);
    113   ASSERT(lpValue);
    114   return lpValue->SetFloat(fFloat);
    115 }
    116 void FXJSE_Value_SetDouble(FXJSE_HVALUE hValue, FXJSE_DOUBLE dDouble) {
    117   CFXJSE_Value* lpValue = reinterpret_cast<CFXJSE_Value*>(hValue);
    118   ASSERT(lpValue);
    119   return lpValue->SetDouble(dDouble);
    120 }
    121 void FXJSE_Value_SetObject(FXJSE_HVALUE hValue,
    122                            void* lpObject,
    123                            FXJSE_HCLASS hClass) {
    124   CFXJSE_Value* lpValue = reinterpret_cast<CFXJSE_Value*>(hValue);
    125   CFXJSE_Class* lpClass = reinterpret_cast<CFXJSE_Class*>(hClass);
    126   if (lpClass == NULL) {
    127     ASSERT(lpObject == NULL);
    128     lpValue->SetJSObject();
    129   } else if (lpClass != NULL) {
    130     lpValue->SetHostObject(lpObject, lpClass);
    131   }
    132 }
    133 void FXJSE_Value_SetArray(FXJSE_HVALUE hValue,
    134                           uint32_t uValueCount,
    135                           FXJSE_HVALUE* rgValues) {
    136   CFXJSE_Value* lpValue = reinterpret_cast<CFXJSE_Value*>(hValue);
    137   return lpValue->SetArray(uValueCount,
    138                            reinterpret_cast<CFXJSE_Value**>(rgValues));
    139 }
    140 void FXJSE_Value_SetDate(FXJSE_HVALUE hValue, FXJSE_DOUBLE dDouble) {
    141   CFXJSE_Value* lpValue = reinterpret_cast<CFXJSE_Value*>(hValue);
    142   return lpValue->SetDate(dDouble);
    143 }
    144 void FXJSE_Value_Set(FXJSE_HVALUE hValue, FXJSE_HVALUE hOriginalValue) {
    145   CFXJSE_Value* lpValue = reinterpret_cast<CFXJSE_Value*>(hValue);
    146   CFXJSE_Value* lpOriginalValue =
    147       reinterpret_cast<CFXJSE_Value*>(hOriginalValue);
    148   ASSERT(lpValue && lpOriginalValue);
    149   return lpValue->Assign(lpOriginalValue);
    150 }
    151 FX_BOOL FXJSE_Value_GetObjectProp(FXJSE_HVALUE hValue,
    152                                   const CFX_ByteStringC& szPropName,
    153                                   FXJSE_HVALUE hPropValue) {
    154   CFXJSE_Value* lpValue = reinterpret_cast<CFXJSE_Value*>(hValue);
    155   CFXJSE_Value* lpPropValue = reinterpret_cast<CFXJSE_Value*>(hPropValue);
    156   ASSERT(lpValue && lpPropValue);
    157   return lpValue->GetObjectProperty(szPropName, lpPropValue);
    158 }
    159 FX_BOOL FXJSE_Value_SetObjectProp(FXJSE_HVALUE hValue,
    160                                   const CFX_ByteStringC& szPropName,
    161                                   FXJSE_HVALUE hPropValue) {
    162   CFXJSE_Value* lpValue = reinterpret_cast<CFXJSE_Value*>(hValue);
    163   CFXJSE_Value* lpPropValue = reinterpret_cast<CFXJSE_Value*>(hPropValue);
    164   ASSERT(lpValue && lpPropValue);
    165   return lpValue->SetObjectProperty(szPropName, lpPropValue);
    166 }
    167 FX_BOOL FXJSE_Value_GetObjectPropByIdx(FXJSE_HVALUE hValue,
    168                                        uint32_t uPropIdx,
    169                                        FXJSE_HVALUE hPropValue) {
    170   CFXJSE_Value* lpValue = reinterpret_cast<CFXJSE_Value*>(hValue);
    171   CFXJSE_Value* lpPropValue = reinterpret_cast<CFXJSE_Value*>(hPropValue);
    172   ASSERT(lpValue && lpPropValue);
    173   return lpValue->GetObjectProperty(uPropIdx, lpPropValue);
    174 }
    175 FX_BOOL FXJSE_Value_SetObjectPropByIdx(FXJSE_HVALUE hValue,
    176                                        uint32_t uPropIdx,
    177                                        FXJSE_HVALUE hPropValue) {
    178   CFXJSE_Value* lpValue = reinterpret_cast<CFXJSE_Value*>(hValue);
    179   CFXJSE_Value* lpPropValue = reinterpret_cast<CFXJSE_Value*>(hPropValue);
    180   ASSERT(lpValue && lpPropValue);
    181   return lpValue->SetObjectProperty(uPropIdx, lpPropValue);
    182 }
    183 FX_BOOL FXJSE_Value_DeleteObjectProp(FXJSE_HVALUE hValue,
    184                                      const CFX_ByteStringC& szPropName) {
    185   CFXJSE_Value* lpValue = reinterpret_cast<CFXJSE_Value*>(hValue);
    186   ASSERT(lpValue);
    187   return lpValue->DeleteObjectProperty(szPropName);
    188 }
    189 FX_BOOL FXJSE_Value_ObjectHasOwnProp(FXJSE_HVALUE hValue,
    190                                      const CFX_ByteStringC& szPropName,
    191                                      FX_BOOL bUseTypeGetter) {
    192   CFXJSE_Value* lpValue = reinterpret_cast<CFXJSE_Value*>(hValue);
    193   ASSERT(lpValue);
    194   return lpValue->HasObjectOwnProperty(szPropName, bUseTypeGetter);
    195 }
    196 FX_BOOL FXJSE_Value_SetObjectOwnProp(FXJSE_HVALUE hValue,
    197                                      const CFX_ByteStringC& szPropName,
    198                                      FXJSE_HVALUE hPropValue) {
    199   CFXJSE_Value* lpValue = reinterpret_cast<CFXJSE_Value*>(hValue);
    200   CFXJSE_Value* lpPropValue = reinterpret_cast<CFXJSE_Value*>(hPropValue);
    201   ASSERT(lpValue && lpPropValue);
    202   return lpValue->SetObjectOwnProperty(szPropName, lpPropValue);
    203 }
    204 FX_BOOL FXJSE_Value_SetFunctionBind(FXJSE_HVALUE hValue,
    205                                     FXJSE_HVALUE hOldFunction,
    206                                     FXJSE_HVALUE hNewThis) {
    207   CFXJSE_Value* lpValue = reinterpret_cast<CFXJSE_Value*>(hValue);
    208   CFXJSE_Value* lpOldFunction = reinterpret_cast<CFXJSE_Value*>(hOldFunction);
    209   CFXJSE_Value* lpNewThis = reinterpret_cast<CFXJSE_Value*>(hNewThis);
    210   ASSERT(lpValue && lpOldFunction && lpNewThis);
    211   return lpValue->SetFunctionBind(lpOldFunction, lpNewThis);
    212 }
    213 FX_BOOL FXJSE_Value_CallFunction(FXJSE_HVALUE hFunction,
    214                                  FXJSE_HVALUE hThis,
    215                                  FXJSE_HVALUE hRetValue,
    216                                  uint32_t nArgCount,
    217                                  FXJSE_HVALUE* lpArgs) {
    218   CFXJSE_Value* lpFunction = reinterpret_cast<CFXJSE_Value*>(hFunction);
    219   CFXJSE_Value* lpThis = reinterpret_cast<CFXJSE_Value*>(hThis);
    220   CFXJSE_Value* lpRetValue = reinterpret_cast<CFXJSE_Value*>(hRetValue);
    221   ASSERT(lpFunction);
    222   return lpFunction->Call(lpThis, lpRetValue, nArgCount, lpArgs);
    223 }
    224 FXJSE_HVALUE FXJSE_Value_Create(FXJSE_HRUNTIME hRuntime) {
    225   CFXJSE_Value* lpValue =
    226       CFXJSE_Value::Create(reinterpret_cast<v8::Isolate*>(hRuntime));
    227   ASSERT(lpValue);
    228   return reinterpret_cast<FXJSE_HVALUE>(lpValue);
    229 }
    230 void FXJSE_Value_Release(FXJSE_HVALUE hValue) {
    231   CFXJSE_Value* lpValue = reinterpret_cast<CFXJSE_Value*>(hValue);
    232   if (lpValue) {
    233     delete lpValue;
    234   }
    235 }
    236 FXJSE_HRUNTIME FXJSE_Value_GetRuntime(FXJSE_HVALUE hValue) {
    237   CFXJSE_Value* lpValue = reinterpret_cast<CFXJSE_Value*>(hValue);
    238   ASSERT(lpValue);
    239   return reinterpret_cast<FXJSE_HRUNTIME>(lpValue->GetIsolate());
    240 }
    241 void FXJSE_ThrowMessage(const CFX_ByteStringC& utf8Name,
    242                         const CFX_ByteStringC& utf8Message) {
    243   v8::Isolate* pIsolate = v8::Isolate::GetCurrent();
    244   ASSERT(pIsolate);
    245   CFXJSE_ScopeUtil_IsolateHandleRootContext scope(pIsolate);
    246   v8::Local<v8::String> hMessage = v8::String::NewFromUtf8(
    247       pIsolate, utf8Message.GetCStr(), v8::String::kNormalString,
    248       utf8Message.GetLength());
    249   v8::Local<v8::Value> hError;
    250   if (utf8Name == "RangeError") {
    251     hError = v8::Exception::RangeError(hMessage);
    252   } else if (utf8Name == "ReferenceError") {
    253     hError = v8::Exception::ReferenceError(hMessage);
    254   } else if (utf8Name == "SyntaxError") {
    255     hError = v8::Exception::SyntaxError(hMessage);
    256   } else if (utf8Name == "TypeError") {
    257     hError = v8::Exception::TypeError(hMessage);
    258   } else {
    259     hError = v8::Exception::Error(hMessage);
    260     if (utf8Name != "Error" && !utf8Name.IsEmpty()) {
    261       hError.As<v8::Object>()->Set(
    262           v8::String::NewFromUtf8(pIsolate, "name"),
    263           v8::String::NewFromUtf8(pIsolate, utf8Name.GetCStr(),
    264                                   v8::String::kNormalString,
    265                                   utf8Name.GetLength()));
    266     }
    267   }
    268   pIsolate->ThrowException(hError);
    269 }
    270 CFXJSE_Value* CFXJSE_Value::Create(v8::Isolate* pIsolate) {
    271   return new CFXJSE_Value(pIsolate);
    272 }
    273 void* CFXJSE_Value::ToObject(CFXJSE_Class* lpClass) const {
    274   ASSERT(!m_hValue.IsEmpty());
    275   CFXJSE_ScopeUtil_IsolateHandleRootContext scope(m_pIsolate);
    276   v8::Local<v8::Value> hValue = v8::Local<v8::Value>::New(m_pIsolate, m_hValue);
    277   ASSERT(!hValue.IsEmpty());
    278   if (!hValue->IsObject()) {
    279     return NULL;
    280   }
    281   return FXJSE_RetrieveObjectBinding(hValue.As<v8::Object>(), lpClass);
    282 }
    283 V8_INLINE static double FXJSE_ftod(FX_FLOAT fNumber) {
    284   if (sizeof(FX_FLOAT) != 4) {
    285     ASSERT(FALSE);
    286     return fNumber;
    287   }
    288   uint32_t nFloatBits = (uint32_t&)fNumber;
    289   uint8_t nExponent = (uint8_t)(nFloatBits >> 16 >> 7);
    290   if (nExponent == 0 || nExponent == 255) {
    291     return fNumber;
    292   }
    293   int8_t nErrExp = nExponent - 127 - 23;
    294   if (nErrExp >= 0) {
    295     return fNumber;
    296   }
    297   double dwError = pow(2.0, nErrExp), dwErrorHalf = dwError / 2;
    298   double dNumber = fNumber, dNumberAbs = fabs(fNumber);
    299   double dNumberAbsMin = dNumberAbs - dwErrorHalf,
    300          dNumberAbsMax = dNumberAbs + dwErrorHalf;
    301   int32_t iErrPos = 0;
    302   if (floor(dNumberAbsMin) == floor(dNumberAbsMax)) {
    303     dNumberAbsMin = fmod(dNumberAbsMin, 1.0);
    304     dNumberAbsMax = fmod(dNumberAbsMax, 1.0);
    305     int32_t iErrPosMin = 1, iErrPosMax = 38;
    306     do {
    307       int32_t iMid = (iErrPosMin + iErrPosMax) / 2;
    308       double dPow = pow(10.0, iMid);
    309       if (floor(dNumberAbsMin * dPow) == floor(dNumberAbsMax * dPow)) {
    310         iErrPosMin = iMid + 1;
    311       } else {
    312         iErrPosMax = iMid;
    313       }
    314     } while (iErrPosMin < iErrPosMax);
    315     iErrPos = iErrPosMax;
    316   }
    317   double dPow = pow(10.0, iErrPos);
    318   return fNumber < 0 ? ceil(dNumber * dPow - 0.5) / dPow
    319                      : floor(dNumber * dPow + 0.5) / dPow;
    320 }
    321 void CFXJSE_Value::SetFloat(FX_FLOAT fFloat) {
    322   CFXJSE_ScopeUtil_IsolateHandle scope(m_pIsolate);
    323   v8::Local<v8::Value> hValue = v8::Number::New(m_pIsolate, FXJSE_ftod(fFloat));
    324   m_hValue.Reset(m_pIsolate, hValue);
    325 }
    326 void CFXJSE_Value::SetHostObject(void* lpObject, CFXJSE_Class* lpClass) {
    327   CFXJSE_ScopeUtil_IsolateHandleRootContext scope(m_pIsolate);
    328   ASSERT(lpClass);
    329   v8::Local<v8::FunctionTemplate> hClass =
    330       v8::Local<v8::FunctionTemplate>::New(m_pIsolate, lpClass->m_hTemplate);
    331   v8::Local<v8::Object> hObject = hClass->InstanceTemplate()->NewInstance();
    332   FXJSE_UpdateObjectBinding(hObject, lpObject);
    333   m_hValue.Reset(m_pIsolate, hObject);
    334 }
    335 void CFXJSE_Value::SetArray(uint32_t uValueCount, CFXJSE_Value** rgValues) {
    336   CFXJSE_ScopeUtil_IsolateHandleRootContext scope(m_pIsolate);
    337   v8::Local<v8::Array> hArrayObject = v8::Array::New(m_pIsolate, uValueCount);
    338   if (rgValues) {
    339     for (uint32_t i = 0; i < uValueCount; i++) {
    340       if (rgValues[i]) {
    341         hArrayObject->Set(i, v8::Local<v8::Value>::New(
    342                                  m_pIsolate, rgValues[i]->DirectGetValue()));
    343       }
    344     }
    345   }
    346   m_hValue.Reset(m_pIsolate, hArrayObject);
    347 }
    348 void CFXJSE_Value::SetDate(FXJSE_DOUBLE dDouble) {
    349   CFXJSE_ScopeUtil_IsolateHandleRootContext scope(m_pIsolate);
    350   v8::Local<v8::Value> hDate = v8::Date::New(m_pIsolate, dDouble);
    351   m_hValue.Reset(m_pIsolate, hDate);
    352 }
    353 FX_BOOL CFXJSE_Value::SetObjectProperty(const CFX_ByteStringC& szPropName,
    354                                         CFXJSE_Value* lpPropValue) {
    355   CFXJSE_ScopeUtil_IsolateHandleRootContext scope(m_pIsolate);
    356   v8::Local<v8::Value> hObject =
    357       v8::Local<v8::Value>::New(m_pIsolate, m_hValue);
    358   if (!hObject->IsObject()) {
    359     return FALSE;
    360   }
    361   v8::Local<v8::Value> hPropValue =
    362       v8::Local<v8::Value>::New(m_pIsolate, lpPropValue->DirectGetValue());
    363   return (FX_BOOL)hObject.As<v8::Object>()->Set(
    364       v8::String::NewFromUtf8(m_pIsolate, szPropName.GetCStr(),
    365                               v8::String::kNormalString,
    366                               szPropName.GetLength()),
    367       hPropValue);
    368 }
    369 FX_BOOL CFXJSE_Value::GetObjectProperty(const CFX_ByteStringC& szPropName,
    370                                         CFXJSE_Value* lpPropValue) {
    371   CFXJSE_ScopeUtil_IsolateHandleRootContext scope(m_pIsolate);
    372   v8::Local<v8::Value> hObject =
    373       v8::Local<v8::Value>::New(m_pIsolate, m_hValue);
    374   if (!hObject->IsObject()) {
    375     return FALSE;
    376   }
    377   v8::Local<v8::Value> hPropValue =
    378       hObject.As<v8::Object>()->Get(v8::String::NewFromUtf8(
    379           m_pIsolate, szPropName.GetCStr(), v8::String::kNormalString,
    380           szPropName.GetLength()));
    381   lpPropValue->ForceSetValue(hPropValue);
    382   return TRUE;
    383 }
    384 FX_BOOL CFXJSE_Value::SetObjectProperty(uint32_t uPropIdx,
    385                                         CFXJSE_Value* lpPropValue) {
    386   CFXJSE_ScopeUtil_IsolateHandleRootContext scope(m_pIsolate);
    387   v8::Local<v8::Value> hObject =
    388       v8::Local<v8::Value>::New(m_pIsolate, m_hValue);
    389   if (!hObject->IsObject()) {
    390     return FALSE;
    391   }
    392   v8::Local<v8::Value> hPropValue =
    393       v8::Local<v8::Value>::New(m_pIsolate, lpPropValue->DirectGetValue());
    394   return (FX_BOOL)hObject.As<v8::Object>()->Set(uPropIdx, hPropValue);
    395 }
    396 FX_BOOL CFXJSE_Value::GetObjectProperty(uint32_t uPropIdx,
    397                                         CFXJSE_Value* lpPropValue) {
    398   CFXJSE_ScopeUtil_IsolateHandleRootContext scope(m_pIsolate);
    399   v8::Local<v8::Value> hObject =
    400       v8::Local<v8::Value>::New(m_pIsolate, m_hValue);
    401   if (!hObject->IsObject()) {
    402     return FALSE;
    403   }
    404   v8::Local<v8::Value> hPropValue = hObject.As<v8::Object>()->Get(uPropIdx);
    405   lpPropValue->ForceSetValue(hPropValue);
    406   return TRUE;
    407 }
    408 FX_BOOL CFXJSE_Value::DeleteObjectProperty(const CFX_ByteStringC& szPropName) {
    409   CFXJSE_ScopeUtil_IsolateHandleRootContext scope(m_pIsolate);
    410   v8::Local<v8::Value> hObject =
    411       v8::Local<v8::Value>::New(m_pIsolate, m_hValue);
    412   if (!hObject->IsObject()) {
    413     return FALSE;
    414   }
    415   hObject.As<v8::Object>()->Delete(v8::String::NewFromUtf8(
    416       m_pIsolate, szPropName.GetCStr(), v8::String::kNormalString,
    417       szPropName.GetLength()));
    418   return TRUE;
    419 }
    420 FX_BOOL CFXJSE_Value::HasObjectOwnProperty(const CFX_ByteStringC& szPropName,
    421                                            FX_BOOL bUseTypeGetter) {
    422   CFXJSE_ScopeUtil_IsolateHandleRootContext scope(m_pIsolate);
    423   v8::Local<v8::Value> hObject =
    424       v8::Local<v8::Value>::New(m_pIsolate, m_hValue);
    425   if (!hObject->IsObject()) {
    426     return FALSE;
    427   }
    428   v8::Local<v8::String> hKey = v8::String::NewFromUtf8(
    429       m_pIsolate, szPropName.GetCStr(), v8::String::kNormalString,
    430       szPropName.GetLength());
    431   return hObject.As<v8::Object>()->HasRealNamedProperty(hKey) ||
    432          (bUseTypeGetter && hObject.As<v8::Object>()->HasOwnProperty(hKey));
    433 }
    434 FX_BOOL CFXJSE_Value::SetObjectOwnProperty(const CFX_ByteStringC& szPropName,
    435                                            CFXJSE_Value* lpPropValue) {
    436   CFXJSE_ScopeUtil_IsolateHandleRootContext scope(m_pIsolate);
    437   v8::Local<v8::Value> hObject =
    438       v8::Local<v8::Value>::New(m_pIsolate, m_hValue);
    439   if (!hObject->IsObject()) {
    440     return FALSE;
    441   }
    442   v8::Local<v8::Value> hValue =
    443       v8::Local<v8::Value>::New(m_pIsolate, lpPropValue->m_hValue);
    444   return hObject.As<v8::Object>()->ForceSet(
    445       v8::String::NewFromUtf8(m_pIsolate, szPropName.GetCStr(),
    446                               v8::String::kNormalString,
    447                               szPropName.GetLength()),
    448       hValue);
    449 }
    450 FX_BOOL CFXJSE_Value::SetFunctionBind(CFXJSE_Value* lpOldFunction,
    451                                       CFXJSE_Value* lpNewThis) {
    452   CFXJSE_ScopeUtil_IsolateHandleRootContext scope(m_pIsolate);
    453   v8::Local<v8::Value> rgArgs[2];
    454   v8::Local<v8::Value> hOldFunction =
    455       v8::Local<v8::Value>::New(m_pIsolate, lpOldFunction->DirectGetValue());
    456   if (hOldFunction.IsEmpty() || !hOldFunction->IsFunction()) {
    457     return FALSE;
    458   }
    459   rgArgs[0] = hOldFunction;
    460   v8::Local<v8::Value> hNewThis =
    461       v8::Local<v8::Value>::New(m_pIsolate, lpNewThis->DirectGetValue());
    462   if (hNewThis.IsEmpty()) {
    463     return FALSE;
    464   }
    465   rgArgs[1] = hNewThis;
    466   v8::Local<v8::String> hBinderFuncSource =
    467       v8::String::NewFromUtf8(m_pIsolate,
    468                               "(function (oldfunction, newthis) { return "
    469                               "oldfunction.bind(newthis); })");
    470   v8::Local<v8::Function> hBinderFunc =
    471       v8::Script::Compile(hBinderFuncSource)->Run().As<v8::Function>();
    472   v8::Local<v8::Value> hBoundFunction =
    473       hBinderFunc->Call(m_pIsolate->GetCurrentContext()->Global(), 2, rgArgs);
    474   if (hBoundFunction.IsEmpty() || !hBoundFunction->IsFunction()) {
    475     return FALSE;
    476   }
    477   m_hValue.Reset(m_pIsolate, hBoundFunction);
    478   return TRUE;
    479 }
    480 #define FXJSE_INVALID_PTR ((void*)(intptr_t)-1)
    481 FX_BOOL CFXJSE_Value::Call(CFXJSE_Value* lpReceiver,
    482                            CFXJSE_Value* lpRetValue,
    483                            uint32_t nArgCount,
    484                            FXJSE_HVALUE* lpArgs) {
    485   CFXJSE_ScopeUtil_IsolateHandleRootContext scope(m_pIsolate);
    486   v8::Local<v8::Value> hFunctionValue =
    487       v8::Local<v8::Value>::New(m_pIsolate, DirectGetValue());
    488   v8::Local<v8::Object> hFunctionObject =
    489       !hFunctionValue.IsEmpty() && hFunctionValue->IsObject()
    490           ? hFunctionValue.As<v8::Object>()
    491           : v8::Local<v8::Object>();
    492   v8::TryCatch trycatch;
    493   if (hFunctionObject.IsEmpty() || !hFunctionObject->IsCallable()) {
    494     if (lpRetValue) {
    495       lpRetValue->ForceSetValue(FXJSE_CreateReturnValue(m_pIsolate, trycatch));
    496     }
    497     return FALSE;
    498   }
    499   v8::Local<v8::Value> hReturnValue;
    500   v8::Local<v8::Value>* lpLocalArgs = NULL;
    501   if (nArgCount) {
    502     lpLocalArgs = FX_Alloc(v8::Local<v8::Value>, nArgCount);
    503     for (uint32_t i = 0; i < nArgCount; i++) {
    504       new (lpLocalArgs + i) v8::Local<v8::Value>;
    505       CFXJSE_Value* lpArg = (CFXJSE_Value*)lpArgs[i];
    506       if (lpArg) {
    507         lpLocalArgs[i] =
    508             v8::Local<v8::Value>::New(m_pIsolate, lpArg->DirectGetValue());
    509       }
    510       if (lpLocalArgs[i].IsEmpty()) {
    511         lpLocalArgs[i] = v8::Undefined(m_pIsolate);
    512       }
    513     }
    514   }
    515   FX_BOOL bRetValue = TRUE;
    516   if (lpReceiver == FXJSE_INVALID_PTR) {
    517     hReturnValue = hFunctionObject->CallAsConstructor(nArgCount, lpLocalArgs);
    518   } else {
    519     v8::Local<v8::Value> hReceiver;
    520     if (lpReceiver) {
    521       hReceiver =
    522           v8::Local<v8::Value>::New(m_pIsolate, lpReceiver->DirectGetValue());
    523     }
    524     if (hReceiver.IsEmpty() || !hReceiver->IsObject()) {
    525       hReceiver = v8::Object::New(m_pIsolate);
    526     }
    527     hReturnValue =
    528         hFunctionObject->CallAsFunction(hReceiver, nArgCount, lpLocalArgs);
    529   }
    530   if (trycatch.HasCaught()) {
    531     hReturnValue = FXJSE_CreateReturnValue(m_pIsolate, trycatch);
    532     bRetValue = FALSE;
    533   }
    534   if (lpRetValue) {
    535     lpRetValue->ForceSetValue(hReturnValue);
    536   }
    537   if (lpLocalArgs) {
    538     for (uint32_t i = 0; i < nArgCount; i++) {
    539       lpLocalArgs[i].~Local();
    540     }
    541     FX_Free(lpLocalArgs);
    542   }
    543   return bRetValue;
    544 }
    545