bool JS4D::ThrowVErrorForException( ContextRef inContext, ExceptionRef inException) { bool errorThrown; if ( (inException != NULL) && !JSValueIsUndefined( inContext, inException)) { VTask::GetCurrent()->GetDebugContext().DisableUI(); bool bHasBeenAborted = false; // first throw an error for javascript VString description; if (ValueToString( inContext, inException, description, /*outException*/ NULL)) { if ( description. BeginsWith ( CVSTR ( "SyntaxError" ) ) && JSValueIsObject ( inContext, inException ) ) // Just to be super safe at the moment to avoid breaking everything { JSObjectRef jsExceptionObject = JSValueToObject ( inContext, inException, NULL ); if ( jsExceptionObject != 0 ) { JSStringRef jsLine = JSStringCreateWithUTF8CString ( "line" ); if ( JSObjectHasProperty ( inContext, jsExceptionObject, jsLine ) ) { JSValueRef jsValLine = JSObjectGetProperty ( inContext, jsExceptionObject, jsLine, NULL ); if ( jsValLine != 0 ) { double nLine = JSValueToNumber( inContext, jsValLine, NULL ); VString vstrLine ( "Error on line " ); vstrLine. AppendReal ( nLine ); vstrLine. AppendCString ( ". " ); description. Insert ( vstrLine, 1 ); } } JSStringRelease ( jsLine ); } } else if ( description. Find ( CVSTR ( "Error: Execution aborted by caller." ) ) > 0 && JSValueIsObject ( inContext, inException ) ) bHasBeenAborted = true; if ( !bHasBeenAborted ) { StThrowError<> error( MAKE_VERROR( 'JS4D', 1)); error->SetString( "error_description", description); } } VTask::GetCurrent()->GetDebugContext().EnableUI(); errorThrown = !bHasBeenAborted; } else { errorThrown = false; } return errorThrown; }
bool VJSGlobalContext::EvaluateScript( const VString& inScript, const VURL *inSource, VValueSingle **outResult, bool inJSONresult ) const { VJSContext context( fContext); Use(); VJSValue result( fContext, NULL); JS4D::ExceptionRef exception = NULL; bool ok = context.EvaluateScript( inScript, inSource, &result, &exception); // first throw an error for javascript if necessary if (JS4D::ThrowVErrorForException( fContext, exception)) { xbox_assert( !ok); // then rethrow an error to explain wat we were doing VTask::GetCurrent()->GetDebugContext().DisableUI(); { VString url; if (inSource != NULL) inSource->GetAbsoluteURL( url, false); if (!url.IsEmpty()) { StThrowError<> error( MAKE_VERROR( 'JS4D', 2)); error->SetString( "url", url); error->SetString( "error_description", CVSTR( "Error evaluating javascript {url}")); } else { StThrowError<> error( MAKE_VERROR( 'JS4D', 3)); error->SetString( "error_description", CVSTR( "Error evaluating javascript")); } } VTask::GetCurrent()->GetDebugContext().EnableUI(); if (outResult != NULL) *outResult = NULL; } else { xbox_assert( ok); if (outResult != NULL) if ( inJSONresult ) { VJSJSON stringifier( fContext ); VString* ptStr = new VString; // The "result" value's fValue is initialized to 0 when a script is aborted using the JS debugger. In this case js core crashes while stringifying, thus the if-else // The if-else can be moved directly into ::Stringify if "null" is acceptable as a generic return value if ( result. IsNull ( ) ) ptStr-> AppendCString ( "null" ); else stringifier.Stringify( result, *ptStr ); *outResult = ptStr; } else *outResult = result.CreateVValue( NULL); } Unuse(); return ok; }