📄 jsicontext.cpp
字号:
*value = (VXIValue *) VXIBooleanCreate ((JSVAL_TO_BOOLEAN (val) ? TRUE : FALSE)); else if ( JSVAL_IS_NULL (val) ) // JavaScript null rc = VXIjsi_RESULT_FAILURE; else if ( JSVAL_IS_OBJECT (val) ) { JSObject *obj = JSVAL_TO_OBJECT(val); if ( JS_IsArrayObject (context, obj) ) { // Array, create a VXIVector jsuint elements = 0; VXIVector *vec = NULL; if ( ! JS_GetArrayLength (context, obj, &elements) ) { rc = VXIjsi_RESULT_FATAL_ERROR; } else if ( (vec = VXIVectorCreate( )) == NULL ) { rc = VXIjsi_RESULT_OUT_OF_MEMORY; } else { // Traverse through the elements in the vector (could be empty, // in which case we want to return an empty VXIVector) for (jsuint i = 0; (( rc == VXIjsi_RESULT_SUCCESS ) && ( i < elements )); i++) { // Convert the element to a VXIValue, then insert jsval elVal = JSVAL_VOID; if ( JS_GetElement (context, obj, i, &elVal) ) { VXIValue *elValue; rc = JsvalToVXIValue (context, elVal, &elValue); if (( rc == VXIjsi_RESULT_SUCCESS ) && ( VXIVectorAddElement (vec, elValue) != VXIvalue_RESULT_SUCCESS )) { rc = VXIjsi_RESULT_OUT_OF_MEMORY; VXIValueDestroy (&elValue); } } else { rc = VXIjsi_RESULT_FATAL_ERROR; } } if ( rc == VXIjsi_RESULT_SUCCESS ) *value = (VXIValue *) vec; else VXIVectorDestroy (&vec); } } else if ( JS_InstanceOf (context, obj, &CONTENT_CLASS, NULL) ) { // Content object, retrieve the VXIContent *value = (VXIValue *) JS_GetPrivate (context, obj); if ( *value == NULL ) rc = VXIjsi_RESULT_FATAL_ERROR; else *value = VXIValueClone (*value); } else { // Regular object, create a VXIMap JSIdArray *props = JS_Enumerate (context, obj); VXIMap *vmap = NULL; if ( ! props ) { rc = VXIjsi_RESULT_FATAL_ERROR; } else if ( (vmap = VXIMapCreate( )) == NULL ) { rc = VXIjsi_RESULT_OUT_OF_MEMORY; } else { // Traverse through the properties in the object (could be empty, // in which case we want to return an empty VXIMap) jsint i = 0; for (i = 0; (( rc == VXIjsi_RESULT_SUCCESS ) && ( i < props->length )); i++) { // Get the property name, looks funky but this was // recommended by one of the SpiderMonkey contributors in a // newsgroup thread jsval prName = JSVAL_VOID, prVal = JSVAL_VOID; if ( JS_IdToValue (context, props->vector[i], &prName) ) { const jschar *name = NULL; size_t namelen = 0; if ( JSVAL_IS_STRING (prName) ) { name = JS_GetStringChars (JSVAL_TO_STRING (prName)); namelen = JS_GetStringLength (JSVAL_TO_STRING (prName)); } else if ( JSVAL_IS_INT (prName) ) { JSString *str = JS_ValueToString (context, prName); name = JS_GetStringChars (str); namelen = JS_GetStringLength (str); } // Lookup the property, convert to a value, then add to the map if (( name ) && ( JS_GetUCProperty (context, obj, name, namelen, &prVal) )) { VXIValue *prValue = NULL; GET_VXICHAR_FROM_JSCHAR(tmpname, name); rc = JsvalToVXIValue (context, prVal, &prValue); if (( rc == VXIjsi_RESULT_SUCCESS ) && ( VXIMapSetProperty (vmap, tmpname, prValue) != VXIvalue_RESULT_SUCCESS )) { rc = VXIjsi_RESULT_OUT_OF_MEMORY; VXIValueDestroy (&prValue); } if( rc == VXIjsi_RESULT_NON_FATAL_ERROR ) rc = VXIjsi_RESULT_SUCCESS; } else { rc = VXIjsi_RESULT_FATAL_ERROR; } } else { rc = VXIjsi_RESULT_FATAL_ERROR; } } if ( rc == VXIjsi_RESULT_SUCCESS ) *value = (VXIValue *) vmap; else VXIMapDestroy (&vmap); } // Free the ID array if ( props ) JS_DestroyIdArray (context, props); } } else // JavaScript undefined (VOID) rc = VXIjsi_RESULT_NON_FATAL_ERROR; // Check for out of memory during VXIValue type create if (( rc == VXIjsi_RESULT_SUCCESS ) && ( *value == NULL )) rc = VXIjsi_RESULT_OUT_OF_MEMORY; return rc; } // Convert VXIValue types to JS values VXIjsiResult JsiContext::VXIValueToJsval (JSContext *context, const VXIValue *value, JsiProtectedJsval *val) { VXIjsiResult rc = VXIjsi_RESULT_SUCCESS; if (( value == NULL ) || ( val == NULL )) return VXIjsi_RESULT_INVALID_ARGUMENT; switch ( VXIValueGetType (value) ) { case VALUE_BOOLEAN: { VXIbool i = VXIBooleanValue ((const VXIBoolean *) value); rc = val->Set (BOOLEAN_TO_JSVAL(i)); } break; case VALUE_INTEGER: { VXIint32 i = VXIIntegerValue ((const VXIInteger *) value); if ( INT_FITS_IN_JSVAL(i) ) rc = val->Set (INT_TO_JSVAL(i)); else rc = VXIjsi_RESULT_NON_FATAL_ERROR; } break; case VALUE_FLOAT: { jsdouble *d = JS_NewDouble (context, (double) VXIFloatValue ((const VXIFloat *) value)); if ( d ) rc = val->Set (DOUBLE_TO_JSVAL(d)); else rc = VXIjsi_RESULT_OUT_OF_MEMORY; } break; case VALUE_STRING: { GET_JSCHAR_FROM_VXICHAR(tmpvalue, tmpvaluelen, VXIStringCStr ((const VXIString *) value)); JSString *s = JS_NewUCStringCopyZ (context, tmpvalue); if ( s ) rc = val->Set (STRING_TO_JSVAL(s)); else rc = VXIjsi_RESULT_OUT_OF_MEMORY; } break; case VALUE_PTR: // Not supported in JavaScript rc = VXIjsi_RESULT_NON_FATAL_ERROR; break; case VALUE_CONTENT: { // Create an object for the content, attach the passed content as // private data. We set the return value prior to setting the // private data to avoid getting garbage collected in the // meantime. VXIValue *c = NULL; JSObject *content = JS_NewObject (context, &CONTENT_CLASS, NULL, NULL); if (( ! content ) || ( val->Set (OBJECT_TO_JSVAL(content)) != VXIjsi_RESULT_SUCCESS ) || ( (c = VXIValueClone (value)) == NULL )) { val->Clear( ); rc = VXIjsi_RESULT_OUT_OF_MEMORY; // JS object gets garbage collected } else if ( ! JS_SetPrivate (context, content, c) ) { val->Clear( ); rc = VXIjsi_RESULT_FATAL_ERROR; } } break; case VALUE_MAP: { // Create an object for the map, temporarily root it so the data // added underneath is not garbage collected on us JSObject *mapObj = JS_NewObject (context, &MAP_CLASS, NULL, NULL); if ( ! mapObj ) { rc = VXIjsi_RESULT_OUT_OF_MEMORY; } else if ( (rc = val->Set (OBJECT_TO_JSVAL (mapObj))) == VXIjsi_RESULT_SUCCESS ) { // Walk the map and add object properties, the map may be empty const VXIchar *prop; const VXIValue *propValue; VXIMapIterator *it = VXIMapGetFirstProperty ((const VXIMap *) value, &prop, &propValue); while (( it ) && ( rc == VXIjsi_RESULT_SUCCESS )) { JsiProtectedJsval propVal (context); rc = VXIValueToJsval (context, propValue, &propVal); if ( rc == VXIjsi_RESULT_SUCCESS ) { GET_JSCHAR_FROM_VXICHAR(tmpprop, tmpproplen, prop); if ( ! JS_DefineUCProperty (context, mapObj, tmpprop, tmpproplen, propVal.Get( ), NULL, NULL, JSPROP_ENUMERATE) ) rc = VXIjsi_RESULT_OUT_OF_MEMORY; } if ( VXIMapGetNextProperty (it, &prop, &propValue) != VXIvalue_RESULT_SUCCESS ) { VXIMapIteratorDestroy (&it); it = NULL; } } if ( it ) VXIMapIteratorDestroy (&it); } } break; case VALUE_VECTOR: { // Create a vector for the map, temporarily root it so the data // added underneath is not garbage collected on us JSObject *vecObj = JS_NewArrayObject (context, 0, NULL); if ( ! vecObj ) { rc = VXIjsi_RESULT_OUT_OF_MEMORY; } else if ( (rc = val->Set (OBJECT_TO_JSVAL (vecObj))) == VXIjsi_RESULT_SUCCESS ) { // Walk the map and add object properties, the map may be empty const VXIVector *vec = (const VXIVector *) value; VXIunsigned i = 0; const VXIValue *elValue; while (( rc == VXIjsi_RESULT_SUCCESS ) && ( (elValue = VXIVectorGetElement (vec, i)) != NULL )) { JsiProtectedJsval elVal (context); rc = VXIValueToJsval (context, elValue, &elVal); if (( rc == VXIjsi_RESULT_SUCCESS ) && ( ! JS_DefineElement (context, vecObj, i, elVal.Get( ), NULL, NULL, JSPROP_ENUMERATE) )) rc = VXIjsi_RESULT_OUT_OF_MEMORY; i++; } } } break; default: rc = VXIjsi_RESULT_UNSUPPORTED; } if ( rc != VXIjsi_RESULT_SUCCESS ) val->Clear( ); return rc; } // Static callback for finalizing scopes void JS_DLL_CALLBACK JsiContext::ScopeFinalize (JSContext *context, JSObject *obj) { // Get this for logging the destruction JsiContext *pThis = (JsiContext *) JS_GetContextPrivate (context); // Get the scope node from the private data and delete it JsiScopeChainNode *scopeNode = (JsiScopeChainNode *) JS_GetPrivate (context, obj); if ( scopeNode ) { if ( pThis ) pThis->Diag (SBJSI_LOG_SCOPE, L"JsiContext::ScopeFinalize", L"scope garbage collected %s (0x%p), context 0x%p", scopeNode->GetName( ).c_str( ), obj, context); delete scopeNode; } } // Static callback for finalizing content objects void JS_DLL_CALLBACK JsiContext::ContentFinalize (JSContext *cx, JSObject *obj) { // Get the scope name from the private data and delete it VXIContent *content = (VXIContent *) JS_GetPrivate (cx, obj); if ( content ) { VXIValue *tmp = (VXIValue *) content; VXIValueDestroy (&tmp); } } // Static callback for enforcing maxBranches JSBool JS_DLL_CALLBACK JsiContext::BranchCallback (JSContext *context, JSScript *script) { if ( ! context ) return JS_FALSE; // Get ourself from our private data JsiContext *pThis = (JsiContext *) JS_GetContextPrivate (context); if ( ! pThis ) { // Severe error return JS_FALSE; } pThis->numBranches++; JSBool rc = JS_TRUE; if ( pThis->numBranches > pThis->maxBranches ) { rc = JS_FALSE; pThis->Error (JSI_WARN_MAX_BRANCHES_EXCEEDED, L"%s%ld", L"maxBranches", pThis->maxBranches); } return rc; } // Static callback for reporting JavaScript errors void JS_DLL_CALLBACK JsiContext::ErrorReporter (JSContext *context, const char *message, JSErrorReport *report) { if ( ! context ) return; // Get ourself from our private data JsiContext *pThis = (JsiContext *) JS_GetContextPrivate (context); if ( ! pThis ) return; // Severe error // Save exception information, ownership of the value is passed jsval ex = JSVAL_VOID; VXIValue *exception = NULL; if (( JS_IsExceptionPending (context) ) && ( JS_GetPendingException (context, &ex) ) && ( JsvalToVXIValue (context, ex, &exception) == VXIjsi_RESULT_SUCCESS )) { if ( pThis->exception ) VXIValueDestroy (&pThis->exception); pThis->exception = exception; } if ( pThis->logEnabled ) { // Convert the ASCII string to wide characters wchar_t wmessage[1024]; size_t len = strlen (message); if ( len > 1023 ) len = 1023; for (size_t i = 0; i < len; i++) wmessage[i] = (wchar_t) message[i]; wmessage[len] = 0; // Determine the error number to log unsigned int errNum; if ( JSREPORT_IS_WARNING (report->flags) ) errNum = JSI_WARN_SM_SCRIPT_WARNING; else if ( JSREPORT_IS_EXCEPTION (report->flags) ) errNum = JSI_ERROR_SM_SCRIPT_EXCEPTION; else if ( JSREPORT_IS_STRICT (report->flags) ) errNum = JSI_WARN_SM_SCRIPT_STRICT; else errNum = JSI_ERROR_SM_SCRIPT_ERROR; // Log the error GET_VXICHAR_FROM_JSCHAR(tmpuclinebuf, report->uclinebuf); GET_VXICHAR_FROM_JSCHAR(tmpuctokenptr, report->uctokenptr); pThis->Error (errNum, L"%s%s%s%ld%s%s%s%s", L"errmsg", wmessage, L"line", report->lineno, L"linetxt", (tmpuclinebuf ? tmpuclinebuf : L""), L"tokentxt", (tmpuctokenptr ? tmpuctokenptr : L"")); } } // Check if the variable name is valid at declaration bool JsiContext::IsValidVarName(JSContext *context, JSObject *obj, const VXIchar* vname) { bool ret = true; SBjsiString tscript(L"var "); tscript += vname; GET_JSCHAR_FROM_VXICHAR(tmpscript, tmpscriptlen, tscript.c_str()); // check if the variable name is valid JSScript *jsScript = JS_CompileUCScript (context, obj, tmpscript, tmpscriptlen, NULL, 1); if( !jsScript ) ret = false; else JS_DestroyScript (context, jsScript); return ret; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -