• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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