Use stdint.h types throughout PDFium.
[pdfium.git] / fpdfsdk / src / javascript / global.cpp
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 "../../include/javascript/IJavaScript.h"
8 #include "../../include/javascript/JS_Context.h"
9 #include "../../include/javascript/JS_Define.h"
10 #include "../../include/javascript/JS_EventHandler.h"
11 #include "../../include/javascript/JS_GlobalData.h"
12 #include "../../include/javascript/JS_Object.h"
13 #include "../../include/javascript/JS_Value.h"
14 #include "../../include/javascript/JavaScript.h"
15 #include "../../include/javascript/global.h"
16 #include "../../include/javascript/resource.h"
17
18 /* ---------------------------- global ---------------------------- */
19
20 // Helper class for compile-time calculation of hash values in order to
21 // avoid having global object initializers.
22 template <unsigned ACC, wchar_t... Ns>
23 struct CHash;
24
25 // Only needed to hash single-character strings.
26 template <wchar_t N>
27 struct CHash<N> {
28   static const unsigned value = N;
29 };
30
31 template <unsigned ACC, wchar_t N>
32 struct CHash<ACC, N> {
33   static const unsigned value = (ACC * 1313LLU + N) & 0xFFFFFFFF;
34 };
35
36 template <unsigned ACC, wchar_t N, wchar_t... Ns>
37 struct CHash<ACC, N, Ns...> {
38   static const unsigned value = CHash<CHash<ACC, N>::value, Ns...>::value;
39 };
40
41 extern const unsigned int JSCONST_nStringHash =
42   CHash<'s','t','r','i','n','g'>::value;
43 extern const unsigned int JSCONST_nNumberHash =
44   CHash<'n','u','m','b','e','r'>::value;
45 extern const unsigned int JSCONST_nBoolHash =
46   CHash<'b','o','o','l','e','a','n'>::value;
47 extern const unsigned int JSCONST_nDateHash =
48   CHash<'d','a','t','e'>::value;
49 extern const unsigned int JSCONST_nObjectHash =
50   CHash<'o','b','j','e','c','t'>::value;
51 extern const unsigned int JSCONST_nFXobjHash =
52   CHash<'f','x','o','b','j'>::value;
53 extern const unsigned int JSCONST_nNullHash =
54   CHash<'n','u','l','l'>::value;
55 extern const unsigned int JSCONST_nUndefHash =
56   CHash<'u','n','d','e','f','i','n','e','d'>::value;
57
58 #ifdef _DEBUG
59 class HashVerify
60 {
61 public:
62   HashVerify();
63 } g_hashVerify;
64
65 HashVerify::HashVerify()
66 {
67   ASSERT(JSCONST_nStringHash ==
68     JS_CalcHash(VALUE_NAME_STRING,wcslen(VALUE_NAME_STRING)));
69   ASSERT(JSCONST_nNumberHash ==
70     JS_CalcHash(VALUE_NAME_NUMBER,wcslen(VALUE_NAME_NUMBER)));
71   ASSERT(JSCONST_nBoolHash ==
72     JS_CalcHash(VALUE_NAME_BOOLEAN,wcslen(VALUE_NAME_BOOLEAN)));
73   ASSERT(JSCONST_nDateHash ==
74     JS_CalcHash(VALUE_NAME_DATE,wcslen(VALUE_NAME_DATE)));
75   ASSERT(JSCONST_nObjectHash ==
76     JS_CalcHash(VALUE_NAME_OBJECT,wcslen(VALUE_NAME_OBJECT)));
77   ASSERT(JSCONST_nFXobjHash ==
78     JS_CalcHash(VALUE_NAME_FXOBJ,wcslen(VALUE_NAME_FXOBJ)));
79   ASSERT(JSCONST_nNullHash ==
80     JS_CalcHash(VALUE_NAME_NULL,wcslen(VALUE_NAME_NULL)));
81   ASSERT(JSCONST_nUndefHash ==
82     JS_CalcHash(VALUE_NAME_UNDEFINED,wcslen(VALUE_NAME_UNDEFINED)));
83 }
84 #endif
85
86
87 BEGIN_JS_STATIC_CONST(CJS_Global)
88 END_JS_STATIC_CONST()
89
90 BEGIN_JS_STATIC_PROP(CJS_Global)
91 END_JS_STATIC_PROP()
92
93 BEGIN_JS_STATIC_METHOD(CJS_Global)
94         JS_STATIC_METHOD_ENTRY(setPersistent)
95 END_JS_STATIC_METHOD()
96
97 IMPLEMENT_SPECIAL_JS_CLASS(CJS_Global, global_alternate, global);
98
99 FX_BOOL CJS_Global::InitInstance(IFXJS_Context* cc)
100 {
101         CJS_Context* pContext = (CJS_Context*)cc;
102         ASSERT(pContext != NULL);
103
104         global_alternate* pGlobal = (global_alternate*)GetEmbedObject();
105         ASSERT(pGlobal != NULL);
106         
107         pGlobal->Initial(pContext->GetReaderApp());
108         
109         return TRUE;
110 };
111
112 global_alternate::global_alternate(CJS_Object* pJSObject)
113         : CJS_EmbedObj(pJSObject),
114         m_pApp(NULL)
115 {
116 }
117
118 global_alternate::~global_alternate(void)
119 {
120         ASSERT(m_pApp != NULL);
121
122 //      CommitGlobalPersisitentVariables();
123         DestroyGlobalPersisitentVariables();
124
125         CJS_RuntimeFactory* pFactory = m_pApp->m_pJSRuntimeFactory;
126         ASSERT(pFactory);
127
128         pFactory->ReleaseGlobalData();
129 }
130   
131 void global_alternate::Initial(CPDFDoc_Environment* pApp)
132 {
133         m_pApp = pApp;
134
135         CJS_RuntimeFactory* pFactory = pApp->m_pJSRuntimeFactory;
136         ASSERT(pFactory);
137         m_pGlobalData = pFactory->NewGlobalData(pApp);
138         UpdateGlobalPersistentVariables();
139 }
140
141 FX_BOOL global_alternate::QueryProperty(FX_LPCWSTR propname)
142 {
143         return CFX_WideString(propname) != L"setPersistent";
144 }
145
146 FX_BOOL global_alternate::DelProperty(IFXJS_Context* cc, FX_LPCWSTR propname, CFX_WideString& sError)
147 {
148         js_global_data* pData = NULL;
149         CFX_ByteString sPropName = CFX_ByteString::FromUnicode(propname);
150
151         if (m_mapGlobal.Lookup(sPropName, (FX_LPVOID&)pData))
152         {
153                 pData->bDeleted = TRUE;
154                 return TRUE;
155         }
156
157         return FALSE;
158 }
159
160 FX_BOOL global_alternate::DoProperty(IFXJS_Context* cc, FX_LPCWSTR propname, CJS_PropValue& vp, CFX_WideString& sError)
161 {
162         if (vp.IsSetting())
163         {
164                 CFX_ByteString sPropName = CFX_ByteString::FromUnicode(propname);
165                 switch (vp.GetType())
166                 {
167                 case VT_number:
168                         {
169                                 double dData;
170                                 vp >> dData;
171                                 return SetGlobalVariables(sPropName, JS_GLOBALDATA_TYPE_NUMBER, dData, false, "", v8::Local<v8::Object>(), FALSE);
172                         }
173                 case VT_boolean:
174                         {
175                                 bool bData;
176                                 vp >> bData;
177                                 return SetGlobalVariables(sPropName, JS_GLOBALDATA_TYPE_BOOLEAN, 0, bData, "", v8::Local<v8::Object>(), FALSE);
178                         }
179                 case VT_string:
180                         {
181                                 CFX_ByteString sData;
182                                 vp >> sData;
183                                 return SetGlobalVariables(sPropName, JS_GLOBALDATA_TYPE_STRING, 0, false, sData, v8::Local<v8::Object>(), FALSE);
184                         }
185                 case VT_object:
186                         {
187                                 JSObject pData;
188                                 vp >> pData;
189                                 return SetGlobalVariables(sPropName, JS_GLOBALDATA_TYPE_OBJECT, 0, false, "", pData, FALSE);
190                         }
191                 case VT_null:
192                         {
193                                 return SetGlobalVariables(sPropName, JS_GLOBALDATA_TYPE_NULL, 0, false, "", v8::Local<v8::Object>(), FALSE);
194                         }
195                 case VT_undefined:
196                         {
197                                 DelProperty(cc, propname, sError);
198                                 return TRUE;
199                         }
200                 default:
201                         return FALSE;
202                 }
203         }
204         else
205         {
206                 js_global_data* pData = NULL;
207                 CFX_ByteString sPropName = CFX_ByteString::FromUnicode(propname);
208
209                 if (m_mapGlobal.Lookup(sPropName, (FX_LPVOID&)pData))
210                 {
211                         if (pData)
212                         {
213                                 if (!pData->bDeleted)
214                                 {
215                                         switch (pData->nType)
216                                         {
217                                         case JS_GLOBALDATA_TYPE_NUMBER:
218                                                 vp << pData->dData;
219                                                 break;
220                                         case JS_GLOBALDATA_TYPE_BOOLEAN:
221                                                 vp << pData->bData;
222                                                 break;
223                                         case JS_GLOBALDATA_TYPE_STRING:
224                                                 vp << pData->sData;
225                                                 break;
226                                         case JS_GLOBALDATA_TYPE_OBJECT:
227                                                 {
228                                                         v8::Local<v8::Object> obj = v8::Local<v8::Object>::New(vp.GetIsolate(),pData->pData);
229                                                         vp << obj;
230                                                         break;
231                                                 }
232                                         case JS_GLOBALDATA_TYPE_NULL:
233                                                 vp.SetNull();
234                                                 break;
235                                         default:
236                                                 return FALSE;
237                                         }
238                                         return TRUE;
239                                 }
240                                 else
241                                 {
242                                         return TRUE;
243                                 }
244                         }
245                         else
246                         {
247                                 vp.SetNull();
248                                 return TRUE;
249                         }
250                 }
251                 else
252                 {
253                         vp.SetNull();
254                         return TRUE;
255                 }
256         }
257
258         return FALSE;
259 }
260
261 FX_BOOL global_alternate::setPersistent(IFXJS_Context* cc, const CJS_Parameters& params, CJS_Value& vRet, CFX_WideString& sError)
262 {
263         CJS_Context* pContext = static_cast<CJS_Context*>(cc);
264         if (params.size() != 2)
265         {
266                 sError = JSGetStringFromID(pContext, IDS_STRING_JSPARAMERROR);
267                 return FALSE;
268         }
269
270         CFX_ByteString sName = params[0].ToCFXByteString();
271
272         js_global_data* pData = NULL;
273         if (m_mapGlobal.Lookup(sName, (FX_LPVOID&)pData))
274         {
275                 if (pData && !pData->bDeleted)
276                 {
277                         pData->bPersistent = params[1].ToBool();
278                         return TRUE;
279                 }
280         }
281
282         sError = JSGetStringFromID(pContext, IDS_STRING_JSNOGLOBAL);
283         return FALSE;
284 }
285
286 void global_alternate::UpdateGlobalPersistentVariables()
287 {
288         ASSERT(m_pGlobalData != NULL);
289
290         for (int i=0,sz=m_pGlobalData->GetSize(); i<sz; i++)
291         {
292                 CJS_GlobalData_Element* pData = m_pGlobalData->GetAt(i);
293                 ASSERT(pData != NULL);
294
295                 switch (pData->data.nType)
296                 {
297                 case JS_GLOBALDATA_TYPE_NUMBER:
298                         this->SetGlobalVariables(pData->data.sKey, JS_GLOBALDATA_TYPE_NUMBER, pData->data.dData, false, "", v8::Local<v8::Object>(), pData->bPersistent == 1);
299                         JS_PutObjectNumber(NULL,(JSFXObject)(*m_pJSObject),
300                                                            pData->data.sKey.UTF8Decode().c_str(), pData->data.dData);
301                         break;
302                 case JS_GLOBALDATA_TYPE_BOOLEAN:
303                         this->SetGlobalVariables(pData->data.sKey, JS_GLOBALDATA_TYPE_BOOLEAN, 0, (bool)(pData->data.bData == 1), "", v8::Local<v8::Object>(), pData->bPersistent == 1);
304                         JS_PutObjectBoolean(NULL,(JSFXObject)(*m_pJSObject),
305                                                                 pData->data.sKey.UTF8Decode().c_str(), (bool)(pData->data.bData == 1));
306                         break;
307                 case JS_GLOBALDATA_TYPE_STRING:
308                         this->SetGlobalVariables(pData->data.sKey, JS_GLOBALDATA_TYPE_STRING, 0, false, pData->data.sData, v8::Local<v8::Object>(), pData->bPersistent == 1);
309                         JS_PutObjectString(NULL, (JSFXObject)(*m_pJSObject),
310                                                            pData->data.sKey.UTF8Decode().c_str(),
311                                                            pData->data.sData.UTF8Decode().c_str());
312                         break;
313                 case JS_GLOBALDATA_TYPE_OBJECT:
314                         {
315                                 IJS_Runtime* pRuntime = JS_GetRuntime((JSFXObject)(*m_pJSObject));
316                                 v8::Local<v8::Object> pObj = JS_NewFxDynamicObj(pRuntime, NULL, -1);
317
318                                 PutObjectProperty(pObj, &pData->data);
319
320                                 this->SetGlobalVariables(pData->data.sKey, JS_GLOBALDATA_TYPE_OBJECT, 0, false, "", 
321                                         (JSObject)pObj, pData->bPersistent == 1);
322                                 JS_PutObjectObject(NULL,(JSFXObject)(*m_pJSObject),
323                                                                    pData->data.sKey.UTF8Decode().c_str(), (JSObject)pObj);
324                         }
325                         break;
326                 case JS_GLOBALDATA_TYPE_NULL:
327                         this->SetGlobalVariables(pData->data.sKey, JS_GLOBALDATA_TYPE_NULL, 0, false, "", v8::Local<v8::Object>(), pData->bPersistent == 1);
328                         JS_PutObjectNull(NULL,(JSFXObject)(*m_pJSObject),
329                                                          pData->data.sKey.UTF8Decode().c_str());
330                         break;
331                 }
332         }
333 }
334
335 void global_alternate::CommitGlobalPersisitentVariables()
336 {
337         ASSERT(m_pGlobalData != NULL);
338
339         FX_POSITION      pos = m_mapGlobal.GetStartPosition();
340         while (pos)
341         {
342                 CFX_ByteString name; 
343                 js_global_data* pData = NULL;
344                 m_mapGlobal.GetNextAssoc(pos, name, (FX_LPVOID&)pData);
345                 
346                 if (pData)
347                 {
348                         if (pData->bDeleted)
349                         {
350                                 m_pGlobalData->DeleteGlobalVariable(name);
351                         }
352                         else
353                         {
354                                 switch (pData->nType)
355                                 {
356                                 case JS_GLOBALDATA_TYPE_NUMBER:
357                                         m_pGlobalData->SetGlobalVariableNumber(name, pData->dData);
358                                         m_pGlobalData->SetGlobalVariablePersistent(name, pData->bPersistent);
359                                         break;
360                                 case JS_GLOBALDATA_TYPE_BOOLEAN:
361                                         m_pGlobalData->SetGlobalVariableBoolean(name, pData->bData);
362                                         m_pGlobalData->SetGlobalVariablePersistent(name, pData->bPersistent);
363                                         break;
364                                 case JS_GLOBALDATA_TYPE_STRING:
365                                         m_pGlobalData->SetGlobalVariableString(name, pData->sData);
366                                         m_pGlobalData->SetGlobalVariablePersistent(name, pData->bPersistent);
367                                         break;
368                                 case JS_GLOBALDATA_TYPE_OBJECT:
369                                         //if (pData->pData)
370                                         {
371                                                 CJS_GlobalVariableArray array;
372                                                 v8::Local<v8::Object> obj = v8::Local<v8::Object>::New(GetJSObject()->GetIsolate(),pData->pData);
373                                                 ObjectToArray(obj, array);
374                                                 m_pGlobalData->SetGlobalVariableObject(name, array);
375                                                 m_pGlobalData->SetGlobalVariablePersistent(name, pData->bPersistent);
376                                         }
377                                         break;
378                                 case JS_GLOBALDATA_TYPE_NULL:
379                                         m_pGlobalData->SetGlobalVariableNull(name);
380                                         m_pGlobalData->SetGlobalVariablePersistent(name, pData->bPersistent);
381                                         break;
382                                 }
383                         }
384                 }
385         }
386 }
387
388 void global_alternate::ObjectToArray(v8::Local<v8::Object> pObj, CJS_GlobalVariableArray& array)
389 {
390         v8::Local<v8::Context> context = pObj->CreationContext();
391         v8::Isolate* isolate = context->GetIsolate();
392         v8::Local<v8::Array> pKeyList = JS_GetObjectElementNames(isolate, pObj);
393         int     nObjElements = pKeyList->Length();
394
395         for (int i=0; i<nObjElements; i++)
396         {
397                 
398                 CFX_WideString ws = JS_ToString(isolate, JS_GetArrayElement(isolate, pKeyList, i));
399                 CFX_ByteString sKey = ws.UTF8Encode();
400
401                 v8::Local<v8::Value> v = JS_GetObjectElement(isolate, pObj, ws.c_str());
402                 FXJSVALUETYPE vt = GET_VALUE_TYPE(v);
403                 switch (vt)
404                 {
405                 case VT_number:
406                         {
407                                 CJS_KeyValue* pObjElement = new CJS_KeyValue;
408                                 pObjElement->nType = JS_GLOBALDATA_TYPE_NUMBER;
409                                 pObjElement->sKey = sKey;
410                                 pObjElement->dData = JS_ToNumber(isolate, v);
411                                 array.Add(pObjElement);
412                         }
413                         break;
414                 case VT_boolean:
415                         {
416                                 CJS_KeyValue* pObjElement = new CJS_KeyValue;
417                                 pObjElement->nType = JS_GLOBALDATA_TYPE_BOOLEAN;
418                                 pObjElement->sKey = sKey;
419                                 pObjElement->dData = JS_ToBoolean(isolate, v);
420                                 array.Add(pObjElement);
421                         }
422                         break;
423                 case VT_string:
424                         {
425                                 CFX_ByteString sValue = CJS_Value(isolate, v, VT_string).ToCFXByteString();
426                                 CJS_KeyValue* pObjElement = new CJS_KeyValue;
427                                 pObjElement->nType = JS_GLOBALDATA_TYPE_STRING;
428                                 pObjElement->sKey = sKey;
429                                 pObjElement->sData = sValue;
430                                 array.Add(pObjElement);
431                         }
432                         break;
433                 case VT_object:
434                         {
435                                 CJS_KeyValue* pObjElement = new CJS_KeyValue;
436                                 pObjElement->nType = JS_GLOBALDATA_TYPE_OBJECT;
437                                 pObjElement->sKey = sKey;
438                                 ObjectToArray(JS_ToObject(isolate, v), pObjElement->objData);
439                                 array.Add(pObjElement);
440                         }
441                         break;
442                 case VT_null:
443                         {
444                                 CJS_KeyValue* pObjElement = new CJS_KeyValue;
445                                 pObjElement->nType = JS_GLOBALDATA_TYPE_NULL;
446                                 pObjElement->sKey = sKey;
447                                 array.Add(pObjElement);
448                         }
449                         break;
450                 default:
451                         break;
452                 }
453         }
454 }
455
456 void global_alternate::PutObjectProperty(v8::Local<v8::Object> pObj, CJS_KeyValue* pData)
457 {
458         ASSERT(pData != NULL);
459
460         for (int i=0,sz=pData->objData.Count(); i<sz; i++)
461         {
462                 CJS_KeyValue* pObjData = pData->objData.GetAt(i);
463                 ASSERT(pObjData != NULL);
464
465                 switch (pObjData->nType)
466                 {
467                 case JS_GLOBALDATA_TYPE_NUMBER:
468                         JS_PutObjectNumber(NULL,(JSObject)pObj, pObjData->sKey.UTF8Decode().c_str(), pObjData->dData);
469                         break;
470                 case JS_GLOBALDATA_TYPE_BOOLEAN:
471                         JS_PutObjectBoolean(NULL,(JSObject)pObj, pObjData->sKey.UTF8Decode().c_str(), (bool)(pObjData->bData == 1));
472                         break;
473                 case JS_GLOBALDATA_TYPE_STRING:
474                         JS_PutObjectString(NULL,(JSObject)pObj, pObjData->sKey.UTF8Decode().c_str(), pObjData->sData.UTF8Decode().c_str());
475                         break;
476                 case JS_GLOBALDATA_TYPE_OBJECT:
477                         {
478                                 IJS_Runtime* pRuntime = JS_GetRuntime((JSFXObject)(*m_pJSObject));
479                                 v8::Local<v8::Object> pNewObj = JS_NewFxDynamicObj(pRuntime, NULL, -1);
480                                 PutObjectProperty(pNewObj, pObjData);
481                                 JS_PutObjectObject(NULL, (JSObject)pObj, pObjData->sKey.UTF8Decode().c_str(), (JSObject)pNewObj);
482                         }
483                         break;
484                 case JS_GLOBALDATA_TYPE_NULL:
485                         JS_PutObjectNull(NULL,(JSObject)pObj, pObjData->sKey.UTF8Decode().c_str());
486                         break;
487                 }
488         }
489 }
490
491 void global_alternate::DestroyGlobalPersisitentVariables()
492 {
493         FX_POSITION      pos = m_mapGlobal.GetStartPosition();
494         while (pos)
495         {
496                 CFX_ByteString name; 
497                 js_global_data* pData = NULL;
498                 m_mapGlobal.GetNextAssoc(pos, name, (FX_LPVOID&)pData);
499                 delete pData;
500         }
501
502         m_mapGlobal.RemoveAll();
503 }
504
505
506 FX_BOOL global_alternate::SetGlobalVariables(FX_LPCSTR propname, int nType, 
507                                 double dData, bool bData, const CFX_ByteString& sData, JSObject pData, bool bDefaultPersistent)
508 {
509         if (propname == NULL) return FALSE;
510
511         js_global_data* pTemp = NULL;
512         m_mapGlobal.Lookup(propname, (FX_LPVOID&)pTemp);
513
514         if (pTemp)
515         {
516                 if (pTemp->bDeleted || pTemp->nType != nType)
517                 {
518                         pTemp->dData = 0;
519                         pTemp->bData = 0;
520                         pTemp->sData = "";
521                         pTemp->nType = nType;
522                 }
523
524                 pTemp->bDeleted = FALSE;
525
526                 switch (nType)
527                 {
528                 case JS_GLOBALDATA_TYPE_NUMBER:
529                         {
530                                 pTemp->dData = dData;
531                         }
532                         break;
533                 case JS_GLOBALDATA_TYPE_BOOLEAN:
534                         {
535                                 pTemp->bData = bData;
536                         }
537                         break;
538                 case JS_GLOBALDATA_TYPE_STRING:
539                         {
540                                 pTemp->sData = sData;
541                         }
542                         break;
543                 case JS_GLOBALDATA_TYPE_OBJECT:
544                         {
545                                 pTemp->pData.Reset(JS_GetRuntime(pData), pData);
546                         }
547                         break;
548                 case JS_GLOBALDATA_TYPE_NULL:
549                         break;
550                 default:
551                         return FALSE;
552                 }       
553
554                 return TRUE;
555         }
556
557         js_global_data* pNewData = NULL;
558
559         switch (nType)
560         {
561         case JS_GLOBALDATA_TYPE_NUMBER:
562                 {
563                         pNewData = new js_global_data;
564                         pNewData->nType = JS_GLOBALDATA_TYPE_NUMBER;
565                         pNewData->dData = dData;
566                         pNewData->bPersistent = bDefaultPersistent;
567                 }
568                 break;
569         case JS_GLOBALDATA_TYPE_BOOLEAN:
570                 {
571                         pNewData = new js_global_data;
572                         pNewData->nType = JS_GLOBALDATA_TYPE_BOOLEAN;
573                         pNewData->bData = bData;
574                         pNewData->bPersistent = bDefaultPersistent;
575                 }
576                 break;
577         case JS_GLOBALDATA_TYPE_STRING:
578                 {
579                         pNewData = new js_global_data;
580                         pNewData->nType = JS_GLOBALDATA_TYPE_STRING;
581                         pNewData->sData = sData;
582                         pNewData->bPersistent = bDefaultPersistent;
583                 }
584                 break;
585         case JS_GLOBALDATA_TYPE_OBJECT:
586                 {
587                         pNewData = new js_global_data;
588                         pNewData->nType = JS_GLOBALDATA_TYPE_OBJECT;
589                         pNewData->pData.Reset(JS_GetRuntime(pData), pData);
590                         pNewData->bPersistent = bDefaultPersistent;
591                 }
592                 break;
593         case JS_GLOBALDATA_TYPE_NULL:
594                 {
595                         pNewData = new js_global_data;
596                         pNewData->nType = JS_GLOBALDATA_TYPE_NULL;
597                         pNewData->bPersistent = bDefaultPersistent;
598                 }
599                 break;
600         default:
601                 return FALSE;
602         }       
603
604         m_mapGlobal.SetAt(propname, (FX_LPVOID)pNewData);
605
606         return TRUE;
607 }
608
609 FXJSVALUETYPE GET_VALUE_TYPE(v8::Local<v8::Value> p)
610 {
611   const unsigned int nHash = JS_CalcHash(JS_GetTypeof(p));
612
613   if (nHash == JSCONST_nUndefHash)
614     return VT_undefined;
615   if (nHash == JSCONST_nNullHash)
616     return VT_null;
617   if (nHash == JSCONST_nStringHash)
618     return VT_string;
619   if (nHash == JSCONST_nNumberHash)
620     return VT_number;
621   if (nHash == JSCONST_nBoolHash)
622     return VT_boolean;
623   if (nHash == JSCONST_nDateHash)
624     return VT_date;
625   if (nHash == JSCONST_nObjectHash)
626     return VT_object;
627   if (nHash == JSCONST_nFXobjHash)
628     return VT_fxobject;
629
630   return VT_unknown;
631 }
632