Error reporting for JS Vector and Entity methods.

git-svn-id: http://svn.berlios.de/svnroot/repos/oolite-linux/trunk@911 127b21dd-08f5-0310-b4b7-95ae10353056
This commit is contained in:
Jens Ayton 2007-04-06 17:35:42 +00:00
parent 67138687af
commit ca593a0a1e
7 changed files with 187 additions and 25 deletions

View File

@ -215,6 +215,7 @@ script.javaScript.call.badSelector = $scriptError;
script.javaScript.error = $scriptError;
script.javaScript.exception = $scriptError;
script.javaScript.warning = $scriptError;
script.javaScript.badParameter = $scriptError;
script.load = no;
script.load.badName = $scriptError;

View File

@ -272,6 +272,8 @@
<string>inherit</string>
<key>script.debug.testCondition.testValues</key>
<string>inherit</string>
<key>script.javaScript.badParameter</key>
<string>$scriptError</string>
<key>script.javaScript.call.badSelector</key>
<string>$scriptError</string>
<key>script.javaScript.error</key>

View File

@ -41,6 +41,8 @@ static JSBool EntityEquality(JSContext *context, JSObject *this, jsval value, JS
// Methods
static JSBool EntitySetPosition(JSContext *context, JSObject *this, uintN argc, jsval *argv, jsval *outResult);
// static JSBool EntitySetOrientation(JSContext *context, JSObject *this, uintN argc, jsval *argv, jsval *outResult);
static JSBool EntityValid(JSContext *context, JSObject *this, uintN argc, jsval *argv, jsval *outResult);
static JSExtendedClass sEntityClass =
@ -108,6 +110,7 @@ static JSFunctionSpec sEntityMethods[] =
// JS name Function min args
{ "setPosition", EntitySetPosition, 1, },
// { "setOrientation", EntitySetOrientation, 1, },
{ "valid", EntityValid, 0, },
{ 0 }
};
@ -279,8 +282,14 @@ static JSBool EntityConvert(JSContext *context, JSObject *this, JSType type, jsv
case JSTYPE_VOID: // Used for string concatenation.
case JSTYPE_STRING:
// Return description of vector
if (!JSEntityGetEntity(context, this, &entity)) return NO;
*outValue = [[entity description] javaScriptValueInContext:context];
if (JSEntityGetEntity(context, this, &entity))
{
*outValue = [[entity description] javaScriptValueInContext:context];
}
else
{
*outValue = STRING_TO_JSVAL(JS_InternString(context, "[stale Entity]"));
}
return YES;
default:
@ -300,11 +309,11 @@ static JSBool EntityEquality(JSContext *context, JSObject *this, jsval value, JS
{
Entity *thisEnt, *thatEnt;
if (!JSVAL_IS_OBJECT(value)) return NO;
if (!JSEntityGetEntity(context, this, &thisEnt)) return NO;
if (!JSEntityGetEntity(context, JSVAL_TO_OBJECT(value), &thatEnt)) return NO;
// No failures or diagnostic messages.
JSEntityGetEntity(context, this, &thisEnt);
JSEntityGetEntity(context, JSVAL_TO_OBJECT(value), &thatEnt);
*outEqual = [thisEnt isEqual:thatEnt];
*outEqual = [thisEnt isEqual:thatEnt]; // Note ![nil isEqual:nil], so two stale entity refs will not be equal.
return YES;
}
@ -314,9 +323,22 @@ static JSBool EntitySetPosition(JSContext *context, JSObject *this, uintN argc,
Entity *thisEnt;
Vector vector;
if (!JSEntityGetEntity(context, this, &thisEnt)) return NO;
if (!VectorFromArgumentList(context, argc, argv, &vector, NULL)) return NO;
if (!JSEntityGetEntity(context, this, &thisEnt)) return YES; // stale reference, no-op.
if (!VectorFromArgumentList(context, argc, argv, &vector, NULL))
{
ReportVectorParamConversionFailure(context, @"Entity", @"setPosition", argc, argv);
return YES;
}
[thisEnt setPosition:vector];
return YES;
}
static JSBool EntityValid(JSContext *context, JSObject *this, uintN argc, jsval *argv, jsval *outResult)
{
Entity *thisEnt;
*outResult = BOOLEAN_TO_JSVAL(JSEntityGetEntity(context, this, &thisEnt));
return YES;
}

View File

@ -46,3 +46,7 @@ BOOL JSVectorSetVector(JSContext *context, JSObject *vectorObj, Vector vector);
// Construct a vector from an argument list which is either a (JS) vector, a (JS) entity, or three things that can be considered numbers. The optional outConsumed argument can be used to find out how many parameters were used (currently, this will be 0 on failure, otherwise 1 or 3). If it fails (and returns NO) the vector will be unaltered.
BOOL VectorFromArgumentList(JSContext *context, uintN argc, jsval *argv, Vector *outVector, uintN *outConsumed);
// Standard error reporter for VectorFromArgumentList() failure.
void ReportVectorParamConversionFailure(JSContext *context, NSString *scriptClass, NSString *function, uintN argc, jsval *argv);

View File

@ -247,6 +247,12 @@ BOOL VectorFromArgumentList(JSContext *context, uintN argc, jsval *argv, Vector
}
void ReportVectorParamConversionFailure(JSContext *context, NSString *scriptClass, NSString *function, uintN argc, jsval *argv)
{
OOReportJavaScriptWarning(context, @"%@.%@(): could not construct vector from parameters %@.", scriptClass, function, [NSString stringWithJavaScriptParameters:argv count:argc inContext:context]);
}
static JSBool VectorGetProperty(JSContext *context, JSObject *this, jsval name, jsval *outValue)
{
Vector vector;
@ -269,7 +275,7 @@ static JSBool VectorGetProperty(JSContext *context, JSObject *this, jsval name,
break;
default:
return NO;
return YES;
}
return YES;
@ -300,7 +306,7 @@ static JSBool VectorSetProperty(JSContext *context, JSObject *this, jsval name,
break;
default:
return NO;
return YES;
}
return JSVectorSetVector(context, this, vector);
@ -372,9 +378,10 @@ static JSBool VectorEquality(JSContext *context, JSObject *this, jsval value, JS
{
Vector thisv, thatv;
if (!JSVAL_IS_OBJECT(value)) return NO;
*outEqual = NO;
if (!JSVectorGetVector(context, this, &thisv)) return NO;
if (!JSVectorGetVector(context, JSVAL_TO_OBJECT(value), &thatv)) return NO;
if (!JSVAL_IS_OBJECT(value)) return YES;
if (!JSVectorGetVector(context, JSVAL_TO_OBJECT(value), &thatv)) return YES;
*outEqual = vector_equal(thisv, thatv);
return YES;
@ -386,7 +393,11 @@ static JSBool VectorAdd(JSContext *context, JSObject *this, uintN argc, jsval *a
Vector thisv, thatv, result;
if (!JSVectorGetVector(context, this, &thisv)) return NO;
if (!VectorFromArgumentList(context, argc, argv, &thatv, NULL)) return NO;
if (!VectorFromArgumentList(context, argc, argv, &thatv, NULL))
{
ReportVectorParamConversionFailure(context, @"Vector", @"add", argc, argv);
return YES;
}
result = vector_add(thisv, thatv);
@ -399,7 +410,11 @@ static JSBool VectorSubtract(JSContext *context, JSObject *this, uintN argc, jsv
Vector thisv, thatv, result;
if (!JSVectorGetVector(context, this, &thisv)) return NO;
if (!VectorFromArgumentList(context, argc, argv, &thatv, NULL)) return NO;
if (!VectorFromArgumentList(context, argc, argv, &thatv, NULL))
{
ReportVectorParamConversionFailure(context, @"Vector", @"subtract", argc, argv);
return YES;
}
result = vector_subtract(thisv, thatv);
@ -413,7 +428,11 @@ static JSBool VectorDistanceTo(JSContext *context, JSObject *this, uintN argc, j
GLfloat result;
if (!JSVectorGetVector(context, this, &thisv)) return NO;
if (!VectorFromArgumentList(context, argc, argv, &thatv, NULL)) return NO;
if (!VectorFromArgumentList(context, argc, argv, &thatv, NULL))
{
ReportVectorParamConversionFailure(context, @"Vector", @"distanceTo", argc, argv);
return YES;
}
result = distance(thisv, thatv);
@ -427,7 +446,11 @@ static JSBool VectorSquaredDistanceTo(JSContext *context, JSObject *this, uintN
GLfloat result;
if (!JSVectorGetVector(context, this, &thisv)) return NO;
if (!VectorFromArgumentList(context, argc, argv, &thatv, NULL)) return NO;
if (!VectorFromArgumentList(context, argc, argv, &thatv, NULL))
{
ReportVectorParamConversionFailure(context, @"Vector", @"squaredDistanceTo", argc, argv);
return YES;
}
result = distance2(thisv, thatv);
@ -441,7 +464,11 @@ static JSBool VectorMultiply(JSContext *context, JSObject *this, uintN argc, jsv
double scalar;
if (!JSVectorGetVector(context, this, &thisv)) return NO;
if (!JS_ValueToNumber(context, argv[0], &scalar)) return NO;
if (!JS_ValueToNumber(context, argv[0], &scalar))
{
OOLog(@"script.javaScript.badParameter.vector.multiply", @"--- JavaScript: Vector.multiply(): expected number, got %@.", [NSString stringWithJavaScriptValue:argv[0] inContext:context]);
return YES;
}
result = vector_multiply_scalar(thisv, scalar);
@ -455,7 +482,11 @@ static JSBool VectorDot(JSContext *context, JSObject *this, uintN argc, jsval *a
GLfloat result;
if (!JSVectorGetVector(context, this, &thisv)) return NO;
if (!VectorFromArgumentList(context, argc, argv, &thatv, NULL)) return NO;
if (!VectorFromArgumentList(context, argc, argv, &thatv, NULL))
{
ReportVectorParamConversionFailure(context, @"Vector", @"dot", argc, argv);
return YES;
}
result = dot_product(thisv, thatv);
@ -469,7 +500,11 @@ static JSBool VectorAngleTo(JSContext *context, JSObject *this, uintN argc, jsva
GLfloat result;
if (!JSVectorGetVector(context, this, &thisv)) return NO;
if (!VectorFromArgumentList(context, argc, argv, &thatv, NULL)) return NO;
if (!VectorFromArgumentList(context, argc, argv, &thatv, NULL))
{
ReportVectorParamConversionFailure(context, @"Vector", @"angleTo", argc, argv);
return YES;
}
result = acosf(dot_product(vector_normal(thisv), vector_normal(thatv)));
@ -482,7 +517,11 @@ static JSBool VectorCross(JSContext *context, JSObject *this, uintN argc, jsval
Vector thisv, thatv, result;
if (!JSVectorGetVector(context, this, &thisv)) return NO;
if (!VectorFromArgumentList(context, argc, argv, &thatv, NULL)) return NO;
if (!VectorFromArgumentList(context, argc, argv, &thatv, NULL))
{
ReportVectorParamConversionFailure(context, @"Vector", @"cross", argc, argv);
return YES;
}
result = true_cross_product(thisv, thatv);
@ -497,8 +536,16 @@ static JSBool VectorTripleProduct(JSContext *context, JSObject *this, uintN argc
uintN consumed;
if (!JSVectorGetVector(context, this, &thisv)) return NO;
if (!VectorFromArgumentList(context, argc, argv, &thatv, &consumed)) return NO;
if (!VectorFromArgumentList(context, argc + consumed, argv, &theotherv, NULL)) return NO;
if (!VectorFromArgumentList(context, argc, argv, &thatv, &consumed))
{
ReportVectorParamConversionFailure(context, @"Vector", @"tripleProduct", argc, argv);
return YES;
}
if (!VectorFromArgumentList(context, argc + consumed, argv + consumed, &theotherv, NULL))
{
ReportVectorParamConversionFailure(context, @"Vector", @"tripleProduct", argc + consumed, argv + consumed);
return YES;
}
result = triple_product(thisv, thatv, theotherv);

View File

@ -44,6 +44,12 @@ MA 02110-1301, USA.
@end
void OOReportJavaScriptError(JSContext *context, NSString *format, ...);
void OOReportJavaScriptErrorWithArguments(JSContext *context, NSString *format, va_list args);
void OOReportJavaScriptWarning(JSContext *context, NSString *format, ...);
void OOReportJavaScriptWarningWithArguments(JSContext *context, NSString *format, va_list args);
@protocol OOJavaScriptConversion <NSObject>
- (jsval)javaScriptValueInContext:(JSContext *)context;
@ -59,6 +65,9 @@ MA 02110-1301, USA.
// Convert an arbitrary JS object to an NSString, using JS_ValueToString.
+ (id)stringWithJavaScriptValue:(jsval)value inContext:(JSContext *)context;
// For diagnostic messages; produces things like @"(42, true, "a string", an object description)".
+ (id)stringWithJavaScriptParameters:(jsval *)params count:(uintN)count inContext:(JSContext *)context;
// Concatenate sequence of arbitrary JS objects into string.
+ (id)concatenationOfStringsFromJavaScriptValues:(jsval *)values count:(size_t)count separator:(NSString *)separator inContext:(JSContext *)context;

View File

@ -1175,14 +1175,19 @@ static void ReportJSError(JSContext *cx, const char *message, JSErrorReport *rep
NSString *messageText = nil;
NSString *lineBuf = nil;
NSString *messageClass = nil;
NSString *highlight = @"*****";
// Type of problem: error, warning or exception? (Strict flag wilfully ignored.)
if (report->flags & JSREPORT_EXCEPTION) severity = @"exception";
else if (report->flags & JSREPORT_WARNING) severity = @"warning";
else if (report->flags & JSREPORT_WARNING)
{
severity = @"warning";
highlight = @"-----";
}
else severity = @"error";
// The error message itself
messageText = [NSString stringWithUTF16String:report->ucmessage];
messageText = [NSString stringWithUTF8String:message];
// Get offending line, if present, and trim trailing line breaks
lineBuf = [NSString stringWithUTF16String:report->uclinebuf];
@ -1192,7 +1197,7 @@ static void ReportJSError(JSContext *cx, const char *message, JSErrorReport *rep
messageClass = [NSString stringWithFormat:@"script.javaScript.%@.%u", severity, report->errorNumber];
// First line: problem description
OOLog(messageClass, @"***** JavaScript %@: %@", severity, messageText);
OOLog(messageClass, @"%@ JavaScript %@: %@", highlight, severity, messageText);
// Second line: where error occured, and line if provided. (The line is only provided for compile-time errors, not run-time errors.)
if ([lineBuf length] != 0)
@ -1242,6 +1247,7 @@ static void ReportJSError(JSContext *cx, const char *message, JSErrorReport *rep
/* create a context and associate it with the JS run time */
cx = JS_NewContext(rt, 8192);
JS_SetOptions(cx, JSOPTION_VAROBJFIX | JSOPTION_STRICT | JSOPTION_NATIVE_BRANCH_CALLBACK);
/* if cx does not have a value, end the program here */
if (!cx)
@ -1302,6 +1308,46 @@ static void ReportJSError(JSContext *cx, const char *message, JSErrorReport *rep
@end
void OOReportJavaScriptError(JSContext *context, NSString *format, ...)
{
va_list args;
va_start(args, format);
OOReportJavaScriptErrorWithArguments(context, format, args);
va_end(args);
}
void OOReportJavaScriptErrorWithArguments(JSContext *context, NSString *format, va_list args)
{
NSString *msg = nil;
msg = [[NSString alloc] initWithFormat:format arguments:args];
JS_ReportWarning(context, "%s", [msg UTF8String]);
[msg release];
}
void OOReportJavaScriptWarning(JSContext *context, NSString *format, ...)
{
va_list args;
va_start(args, format);
OOReportJavaScriptWarningWithArguments(context, format, args);
va_end(args);
}
void OOReportJavaScriptWarningWithArguments(JSContext *context, NSString *format, va_list args)
{
NSString *msg = nil;
msg = [[NSString alloc] initWithFormat:format arguments:args];
JS_ReportWarning(context, "%s", [msg UTF8String]);
[msg release];
}
@implementation NSString (OOJavaScriptExtensions)
// Convert a JSString to an NSString.
@ -1326,6 +1372,37 @@ static void ReportJSError(JSContext *cx, const char *message, JSErrorReport *rep
}
+ (id)stringWithJavaScriptParameters:(jsval *)params count:(uintN)count inContext:(JSContext *)context
{
if (params == nil && count != 0) return nil;
uintN i;
jsval val;
NSMutableString *result = [NSMutableString string];
NSString *valString = nil;
for (i = 0; i != count; ++i)
{
if (i != 0) [result appendString:@", "];
else [result appendString:@"("];
val = params[i];
valString = [self stringWithJavaScriptValue:val inContext:context];
if (JSVAL_IS_STRING(val))
{
[result appendFormat:@"\"%@\"", valString];
}
else
{
[result appendString:valString];
}
}
[result appendString:@")"];
return result;
}
- (jsval)javaScriptValueInContext:(JSContext *)context
{
size_t length;