Home | History | Annotate | Download | only in javascript
      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 
    633