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