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"
FXJSE_Value_IsUndefined(FXJSE_HVALUE hValue)13 FX_BOOL FXJSE_Value_IsUndefined(FXJSE_HVALUE hValue) {
14   CFXJSE_Value* lpValue = reinterpret_cast<CFXJSE_Value*>(hValue);
15   return lpValue && lpValue->IsUndefined();
16 }
FXJSE_Value_IsNull(FXJSE_HVALUE hValue)17 FX_BOOL FXJSE_Value_IsNull(FXJSE_HVALUE hValue) {
18   CFXJSE_Value* lpValue = reinterpret_cast<CFXJSE_Value*>(hValue);
19   return lpValue && lpValue->IsNull();
20 }
FXJSE_Value_IsBoolean(FXJSE_HVALUE hValue)21 FX_BOOL FXJSE_Value_IsBoolean(FXJSE_HVALUE hValue) {
22   CFXJSE_Value* lpValue = reinterpret_cast<CFXJSE_Value*>(hValue);
23   return lpValue && lpValue->IsBoolean();
24 }
FXJSE_Value_IsUTF8String(FXJSE_HVALUE hValue)25 FX_BOOL FXJSE_Value_IsUTF8String(FXJSE_HVALUE hValue) {
26   CFXJSE_Value* lpValue = reinterpret_cast<CFXJSE_Value*>(hValue);
27   return lpValue && lpValue->IsString();
28 }
FXJSE_Value_IsNumber(FXJSE_HVALUE hValue)29 FX_BOOL FXJSE_Value_IsNumber(FXJSE_HVALUE hValue) {
30   CFXJSE_Value* lpValue = reinterpret_cast<CFXJSE_Value*>(hValue);
31   return lpValue && lpValue->IsNumber();
32 }
FXJSE_Value_IsInteger(FXJSE_HVALUE hValue)33 FX_BOOL FXJSE_Value_IsInteger(FXJSE_HVALUE hValue) {
34   CFXJSE_Value* lpValue = reinterpret_cast<CFXJSE_Value*>(hValue);
35   return lpValue && lpValue->IsInteger();
36 }
FXJSE_Value_IsObject(FXJSE_HVALUE hValue)37 FX_BOOL FXJSE_Value_IsObject(FXJSE_HVALUE hValue) {
38   CFXJSE_Value* lpValue = reinterpret_cast<CFXJSE_Value*>(hValue);
39   return lpValue && lpValue->IsObject();
40 }
FXJSE_Value_IsArray(FXJSE_HVALUE hValue)41 FX_BOOL FXJSE_Value_IsArray(FXJSE_HVALUE hValue) {
42   CFXJSE_Value* lpValue = reinterpret_cast<CFXJSE_Value*>(hValue);
43   return lpValue && lpValue->IsArray();
44 }
FXJSE_Value_IsFunction(FXJSE_HVALUE hValue)45 FX_BOOL FXJSE_Value_IsFunction(FXJSE_HVALUE hValue) {
46   CFXJSE_Value* lpValue = reinterpret_cast<CFXJSE_Value*>(hValue);
47   return lpValue && lpValue->IsFunction();
48 }
FXJSE_Value_IsDate(FXJSE_HVALUE hValue)49 FX_BOOL FXJSE_Value_IsDate(FXJSE_HVALUE hValue) {
50   CFXJSE_Value* lpValue = reinterpret_cast<CFXJSE_Value*>(hValue);
51   return lpValue && lpValue->IsDate();
52 }
FXJSE_Value_ToBoolean(FXJSE_HVALUE hValue)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 }
FXJSE_Value_ToFloat(FXJSE_HVALUE hValue)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 }
FXJSE_Value_ToDouble(FXJSE_HVALUE hValue)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 }
FXJSE_Value_ToUTF8String(FXJSE_HVALUE hValue,CFX_ByteString & szStrOutput)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 }
FXJSE_Value_ToInteger(FXJSE_HVALUE hValue)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 }
FXJSE_Value_ToObject(FXJSE_HVALUE hValue,FXJSE_HCLASS hClass)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 }
FXJSE_Value_SetUndefined(FXJSE_HVALUE hValue)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 }
FXJSE_Value_SetNull(FXJSE_HVALUE hValue)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 }
FXJSE_Value_SetBoolean(FXJSE_HVALUE hValue,FX_BOOL bBoolean)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 }
FXJSE_Value_SetUTF8String(FXJSE_HVALUE hValue,const CFX_ByteStringC & szString)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 }
FXJSE_Value_SetInteger(FXJSE_HVALUE hValue,int32_t nInteger)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 }
FXJSE_Value_SetFloat(FXJSE_HVALUE hValue,FX_FLOAT fFloat)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 }
FXJSE_Value_SetDouble(FXJSE_HVALUE hValue,FXJSE_DOUBLE dDouble)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 }
FXJSE_Value_SetObject(FXJSE_HVALUE hValue,void * lpObject,FXJSE_HCLASS hClass)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 }
FXJSE_Value_SetArray(FXJSE_HVALUE hValue,uint32_t uValueCount,FXJSE_HVALUE * rgValues)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 }
FXJSE_Value_SetDate(FXJSE_HVALUE hValue,FXJSE_DOUBLE dDouble)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 }
FXJSE_Value_Set(FXJSE_HVALUE hValue,FXJSE_HVALUE hOriginalValue)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 }
FXJSE_Value_GetObjectProp(FXJSE_HVALUE hValue,const CFX_ByteStringC & szPropName,FXJSE_HVALUE hPropValue)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 }
FXJSE_Value_SetObjectProp(FXJSE_HVALUE hValue,const CFX_ByteStringC & szPropName,FXJSE_HVALUE hPropValue)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 }
FXJSE_Value_GetObjectPropByIdx(FXJSE_HVALUE hValue,uint32_t uPropIdx,FXJSE_HVALUE hPropValue)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 }
FXJSE_Value_SetObjectPropByIdx(FXJSE_HVALUE hValue,uint32_t uPropIdx,FXJSE_HVALUE hPropValue)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 }
FXJSE_Value_DeleteObjectProp(FXJSE_HVALUE hValue,const CFX_ByteStringC & szPropName)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 }
FXJSE_Value_ObjectHasOwnProp(FXJSE_HVALUE hValue,const CFX_ByteStringC & szPropName,FX_BOOL bUseTypeGetter)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 }
FXJSE_Value_SetObjectOwnProp(FXJSE_HVALUE hValue,const CFX_ByteStringC & szPropName,FXJSE_HVALUE hPropValue)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 }
FXJSE_Value_SetFunctionBind(FXJSE_HVALUE hValue,FXJSE_HVALUE hOldFunction,FXJSE_HVALUE hNewThis)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 }
FXJSE_Value_CallFunction(FXJSE_HVALUE hFunction,FXJSE_HVALUE hThis,FXJSE_HVALUE hRetValue,uint32_t nArgCount,FXJSE_HVALUE * lpArgs)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 }
FXJSE_Value_Create(FXJSE_HRUNTIME hRuntime)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 }
FXJSE_Value_Release(FXJSE_HVALUE hValue)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 }
FXJSE_Value_GetRuntime(FXJSE_HVALUE hValue)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 }
FXJSE_ThrowMessage(const CFX_ByteStringC & utf8Name,const CFX_ByteStringC & utf8Message)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 }
Create(v8::Isolate * pIsolate)270 CFXJSE_Value* CFXJSE_Value::Create(v8::Isolate* pIsolate) {
271   return new CFXJSE_Value(pIsolate);
272 }
ToObject(CFXJSE_Class * lpClass) const273 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 }
FXJSE_ftod(FX_FLOAT fNumber)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 }
SetFloat(FX_FLOAT fFloat)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 }
SetHostObject(void * lpObject,CFXJSE_Class * lpClass)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 }
SetArray(uint32_t uValueCount,CFXJSE_Value ** rgValues)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 }
SetDate(FXJSE_DOUBLE dDouble)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 }
SetObjectProperty(const CFX_ByteStringC & szPropName,CFXJSE_Value * lpPropValue)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 }
GetObjectProperty(const CFX_ByteStringC & szPropName,CFXJSE_Value * lpPropValue)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 }
SetObjectProperty(uint32_t uPropIdx,CFXJSE_Value * lpPropValue)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 }
GetObjectProperty(uint32_t uPropIdx,CFXJSE_Value * lpPropValue)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 }
DeleteObjectProperty(const CFX_ByteStringC & szPropName)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 }
HasObjectOwnProperty(const CFX_ByteStringC & szPropName,FX_BOOL bUseTypeGetter)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 }
SetObjectOwnProperty(const CFX_ByteStringC & szPropName,CFXJSE_Value * lpPropValue)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 }
SetFunctionBind(CFXJSE_Value * lpOldFunction,CFXJSE_Value * lpNewThis)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)
Call(CFXJSE_Value * lpReceiver,CFXJSE_Value * lpRetValue,uint32_t nArgCount,FXJSE_HVALUE * lpArgs)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