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