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
HashVerify()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
InitInstance(IFXJS_Context * cc)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
global_alternate(CJS_Object * pJSObject)112 global_alternate::global_alternate(CJS_Object* pJSObject)
113 : CJS_EmbedObj(pJSObject),
114 m_pApp(NULL)
115 {
116 }
117
~global_alternate(void)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
Initial(CPDFDoc_Environment * pApp)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
QueryProperty(FX_LPCWSTR propname)141 FX_BOOL global_alternate::QueryProperty(FX_LPCWSTR propname)
142 {
143 return CFX_WideString(propname) != L"setPersistent";
144 }
145
DelProperty(IFXJS_Context * cc,FX_LPCWSTR propname,CFX_WideString & sError)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
DoProperty(IFXJS_Context * cc,FX_LPCWSTR propname,CJS_PropValue & vp,CFX_WideString & sError)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
setPersistent(IFXJS_Context * cc,const CJS_Parameters & params,CJS_Value & vRet,CFX_WideString & sError)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
UpdateGlobalPersistentVariables()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
CommitGlobalPersisitentVariables()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
ObjectToArray(v8::Local<v8::Object> pObj,CJS_GlobalVariableArray & array)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
PutObjectProperty(v8::Local<v8::Object> pObj,CJS_KeyValue * pData)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
DestroyGlobalPersisitentVariables()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
SetGlobalVariables(FX_LPCSTR propname,int nType,double dData,bool bData,const CFX_ByteString & sData,JSObject pData,bool bDefaultPersistent)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
GET_VALUE_TYPE(v8::Local<v8::Value> p)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
633