Fix for incorrect error handling in OOJSVector and OOJSQuaternion. Only 20 pseudo-classes left to handle! Also fixed Quaternion.rotate(), this time for real.

git-svn-id: http://svn.berlios.de/svnroot/repos/oolite-linux/trunk@1646 127b21dd-08f5-0310-b4b7-95ae10353056
This commit is contained in:
Jens Ayton 2008-05-20 17:15:41 +00:00
parent 1c0a991e74
commit 3c82f379e0
10 changed files with 306 additions and 190 deletions

View File

@ -4949,15 +4949,15 @@ static int last_outfitting_index;
[gui clear];
[gui setTitle:@"Oolite"];
text = ExpandDescriptionForCurrentSystem(@"[game-copyright]");
text = DESC(@"game-copyright");
[gui setText:text forRow:17 align:GUI_ALIGN_CENTER];
[gui setColor:[OOColor whiteColor] forRow:17];
text = ExpandDescriptionForCurrentSystem(@"[theme-music-credit]");
text = DESC(@"theme-music-credit");
[gui setText:text forRow:19 align:GUI_ALIGN_CENTER];
[gui setColor:[OOColor grayColor] forRow:19];
text = ExpandDescriptionForCurrentSystem(@"[load-previous-commander]");
text = DESC(@"load-previous-commander");
[gui setText:text forRow:21 align:GUI_ALIGN_CENTER];
[gui setColor:[OOColor yellowColor] forRow:21];

View File

@ -3472,7 +3472,9 @@ NSComparisonResult planetSort(id i1, id i2, void* context)
- (OOAegisStatus) checkForAegis
{
PlanetEntity* the_planet=[self findPlanetNearestSurface];
PlanetEntity *the_planet = [self findPlanetNearestSurface];
PlanetEntity *warnedPlanet = nil;
PlanetEntity *mainPlanet = nil;
if (the_planet == nil)
{
@ -3512,6 +3514,7 @@ NSComparisonResult planetSort(id i1, id i2, void* context)
if (d2 < cr2 * 9.0f && [UNIVERSE sun] != the_planet) //to 3x radius of any planet/moon
{
result = AEGIS_CLOSE_TO_ANY_PLANET;
warnedPlanet = the_planet; // Avoid duplicate message
}
d2 = magnitude2(vector_subtract([[UNIVERSE planet] position], [self position]));
@ -3546,7 +3549,11 @@ NSComparisonResult planetSort(id i1, id i2, void* context)
// approaching..
if ((aegis_status == AEGIS_NONE)&&(result == AEGIS_CLOSE_TO_MAIN_PLANET))
{
[self doScriptEvent:@"shipEnteredPlanetaryVicinity" withArgument:[UNIVERSE planet]];
mainPlanet = [UNIVERSE planet];
if (warnedPlanet != mainPlanet)
{
[self doScriptEvent:@"shipEnteredPlanetaryVicinity" withArgument:mainPlanet];
}
[shipAI message:@"CLOSE_TO_PLANET"];
[shipAI message:@"AEGIS_CLOSE_TO_PLANET"]; //keep for compatibility with pre-1.72 AI plists
[shipAI message:@"AEGIS_CLOSE_TO_MAIN_PLANET"];

View File

@ -338,7 +338,7 @@ void quaternion_rotate_about_z(Quaternion *quat, GLfloat angle)
void quaternion_rotate_about_axis(Quaternion *quat, Vector axis, GLfloat angle)
{
Quaternion q2, result;
Quaternion q2 /*, result */;
GLfloat a = angle * 0.5f;
GLfloat w = cosf(a);
GLfloat scale = sinf(a);
@ -347,7 +347,7 @@ void quaternion_rotate_about_axis(Quaternion *quat, Vector axis, GLfloat angle)
q2.x = axis.x * scale;
q2.y = axis.y * scale;
q2.z = axis.z * scale;
#if 0
result.w = quat->w * q2.w - q2.x * quat->x - quat->y * q2.y - quat->z * q2.z;
result.x = quat->w * q2.x + quat->x * q2.w + quat->y * q2.z - quat->z * q2.y;
result.y = quat->w * q2.y + quat->y * q2.w + quat->z * q2.x - quat->x * q2.z;
@ -357,6 +357,9 @@ void quaternion_rotate_about_axis(Quaternion *quat, Vector axis, GLfloat angle)
quat->x = result.x;
quat->y = result.y;
quat->z = result.z;
#else
*quat = quaternion_multiply(*quat, q2);
#endif
}
@ -385,7 +388,7 @@ Vector quaternion_rotate_vector(Quaternion q, Vector vector)
/*
Quaternion rotation formula:
r(q, v) = q * v * q^-1, where q^-1 is the spacial inverse of q.
*/
*/
v = make_quaternion(0, vector.x, vector.y, vector.z);
@ -396,6 +399,7 @@ Vector quaternion_rotate_vector(Quaternion q, Vector vector)
return make_vector(v.x, v.y, v.z); // w will be zero
}
#else
// Same as above with some terms eliminated. Yay algebra.
Vector quaternion_rotate_vector(Quaternion q, Vector v)
{
Quaternion qv;

View File

@ -56,8 +56,13 @@ BOOL JSQuaternionSetQuaternion(JSContext *context, JSObject *quaternionObj, Quat
optional outConsumed argument can be used to find out how many parameters
were used (currently, this will be 0 on failure, otherwise 1 or 4).
On failure, it will return NO, annd the quaternion will be unaltered. If
scriptClass and function are non-nil, a warning will be reported to the
log.
On failure, it will return NO and raise an error. If the caller is a JS
callback, it must return NO to signal an error.
*/
BOOL QuaternionFromArgumentList(JSContext *context, NSString *scriptClass, NSString *function, uintN argc, jsval *argv, Quaternion *outQuaternion, uintN *outConsumed);
/* QuaternionFromArgumentList()
Like VectorFromArgumentList(), but does not report an error on failure.
*/
BOOL QuaternionFromArgumentListNoError(JSContext *context, uintN argc, jsval *argv, Quaternion *outVector, uintN *outConsumed);

View File

@ -148,7 +148,7 @@ JSObject *JSQuaternionWithQuaternion(JSContext *context, Quaternion quaternion)
Quaternion *private = NULL;
private = malloc(sizeof *private);
if (private == NULL) return NULL;
if (EXPECT_NOT(private == NULL)) return NULL;
*private = quaternion;
@ -158,7 +158,7 @@ JSObject *JSQuaternionWithQuaternion(JSContext *context, Quaternion quaternion)
if (!JS_SetPrivate(context, result, private)) result = NULL;
}
if (result == NULL) free(private);
if (EXPECT_NOT(result == NULL)) free(private);
return result;
}
@ -168,10 +168,10 @@ BOOL QuaternionToJSValue(JSContext *context, Quaternion quaternion, jsval *outVa
{
JSObject *object = NULL;
if (outValue == NULL) return NO;
if (EXPECT_NOT(outValue == NULL)) return NO;
object = JSQuaternionWithQuaternion(context, quaternion);
if (object == NULL) return NO;
if (EXPECT_NOT(object == NULL)) return NO;
*outValue = OBJECT_TO_JSVAL(object);
return YES;
@ -180,7 +180,7 @@ BOOL QuaternionToJSValue(JSContext *context, Quaternion quaternion, jsval *outVa
BOOL JSValueToQuaternion(JSContext *context, jsval value, Quaternion *outQuaternion)
{
if (!JSVAL_IS_OBJECT(value)) return NO;
if (EXPECT_NOT(!JSVAL_IS_OBJECT(value))) return NO;
return JSObjectGetQuaternion(context, JSVAL_TO_OBJECT(value), outQuaternion);
}
@ -194,7 +194,7 @@ BOOL JSObjectGetQuaternion(JSContext *context, JSObject *quaternionObj, Quaterni
jsval arrayW, arrayX, arrayY, arrayZ;
jsdouble dVal;
if (outQuaternion == NULL || quaternionObj == NULL) return NO;
if (EXPECT_NOT(outQuaternion == NULL || quaternionObj == NULL)) return NO;
private = JS_GetInstancePrivate(context, quaternionObj, &sQuaternionClass.base, NULL);
if (private != NULL) // If this is a (JS) Quaternion...
@ -243,7 +243,7 @@ BOOL JSQuaternionSetQuaternion(JSContext *context, JSObject *quaternionObj, Quat
{
Quaternion *private = NULL;
if (quaternionObj == NULL) return NO;
if (EXPECT_NOT(quaternionObj == NULL)) return NO;
private = JS_GetInstancePrivate(context, quaternionObj, &sQuaternionClass.base, NULL);
if (private != NULL) // If this is a (JS) Quaternion...
@ -257,18 +257,30 @@ BOOL JSQuaternionSetQuaternion(JSContext *context, JSObject *quaternionObj, Quat
BOOL QuaternionFromArgumentList(JSContext *context, NSString *scriptClass, NSString *function, uintN argc, jsval *argv, Quaternion *outQuaternion, uintN *outConsumed)
{
if (QuaternionFromArgumentListNoError(context, argc, argv, outQuaternion, outConsumed)) return YES;
else
{
OOReportJavaScriptBadArguments(context, scriptClass, function, argc, argv,
@"Could not construct quaternion from parameters",
@"Quaternion, Entity or four numbers");
return NO;
}
}
BOOL QuaternionFromArgumentListNoError(JSContext *context, uintN argc, jsval *argv, Quaternion *outQuaternion, uintN *outConsumed)
{
double w, x, y, z;
// Sanity checks.
if (outConsumed != NULL) *outConsumed = 0;
// Sanity checks.
if (EXPECT_NOT(argc == 0 || argv == NULL || outQuaternion == NULL))
{
OOLogGenericParameterError();
return NO;
}
// Is first object a quaternion or entity?
if (JSVAL_IS_OBJECT(argv[0]))
{
@ -280,28 +292,18 @@ BOOL QuaternionFromArgumentList(JSContext *context, NSString *scriptClass, NSStr
}
// Otherwise, look for four numbers.
if (argc < 3) goto FAIL;
if (EXPECT_NOT(!JS_ValueToNumber(context, argv[0], &w))) goto FAIL;
if (EXPECT_NOT(!JS_ValueToNumber(context, argv[1], &x))) goto FAIL;
if (EXPECT_NOT(!JS_ValueToNumber(context, argv[2], &y))) goto FAIL;
if (EXPECT_NOT(!JS_ValueToNumber(context, argv[3], &z))) goto FAIL;
if (EXPECT_NOT(argc < 4)) return NO;
// Given a string, JS_ValueToNumber() returns YES but provides a NaN number.
if (EXPECT_NOT(isnan(w) || isnan(x) || isnan(y) || isnan(z))) goto FAIL;
if (EXPECT_NOT(!JS_ValueToNumber(context, argv[0], &w) || isnan(w))) return NO;
if (EXPECT_NOT(!JS_ValueToNumber(context, argv[1], &x) || isnan(x))) return NO;
if (EXPECT_NOT(!JS_ValueToNumber(context, argv[2], &y) || isnan(y))) return NO;
if (EXPECT_NOT(!JS_ValueToNumber(context, argv[3], &z) || isnan(z))) return NO;
// We got our four numbers.
*outQuaternion = make_quaternion(w, x, y, z);
if (outConsumed != NULL) *outConsumed = 4;
return YES;
FAIL:
// Report bad parameters, if given a class and function.
if (scriptClass != nil && function != nil)
{
OOReportJavaScriptError(context, @"%@.%@(): could not construct quaternion from parameters %@ -- expected Quaternion, Entity or four numbers.", scriptClass, function, [NSString stringWithJavaScriptParameters:argv count:argc inContext:context]);
}
return NO;
}
@ -310,26 +312,27 @@ FAIL:
static JSBool QuaternionGetProperty(JSContext *context, JSObject *this, jsval name, jsval *outValue)
{
Quaternion quaternion;
GLfloat value;
if (!JSVAL_IS_INT(name)) return YES;
if (!JSObjectGetQuaternion(context, this, &quaternion)) return NO;
if (EXPECT_NOT(!JSObjectGetQuaternion(context, this, &quaternion))) return NO;
switch (JSVAL_TO_INT(name))
{
case kQuaternion_w:
JS_NewDoubleValue(context, quaternion.w, outValue);
value = quaternion.w;
break;
case kQuaternion_x:
JS_NewDoubleValue(context, quaternion.x, outValue);
value = quaternion.x;
break;
case kQuaternion_y:
JS_NewDoubleValue(context, quaternion.y, outValue);
value = quaternion.y;
break;
case kQuaternion_z:
JS_NewDoubleValue(context, quaternion.z, outValue);
value = quaternion.z;
break;
default:
@ -337,7 +340,7 @@ static JSBool QuaternionGetProperty(JSContext *context, JSObject *this, jsval na
return NO;
}
return YES;
return JS_NewDoubleValue(context, value, outValue);
}
@ -347,7 +350,7 @@ static JSBool QuaternionSetProperty(JSContext *context, JSObject *this, jsval na
jsdouble dval;
if (!JSVAL_IS_INT(name)) return YES;
if (!JSObjectGetQuaternion(context, this, &quaternion)) return NO;
if (EXPECT_NOT(!JSObjectGetQuaternion(context, this, &quaternion))) return NO;
JS_ValueToNumber(context, *value, &dval);
switch (JSVAL_TO_INT(name))
@ -395,9 +398,9 @@ static JSBool QuaternionConstruct(JSContext *context, JSObject *this, uintN argc
Quaternion *private = NULL;
private = malloc(sizeof *private);
if (private == NULL) return NO;
if (EXPECT_NOT(private == NULL)) return NO;
if (!QuaternionFromArgumentList(context, NULL, NULL, argc, argv, &quaternion, NULL)) quaternion = kIdentityQuaternion;
if (argc == 0 || !QuaternionFromArgumentList(context, NULL, NULL, argc, argv, &quaternion, NULL)) quaternion = kIdentityQuaternion;
*private = quaternion;
@ -415,10 +418,11 @@ static JSBool QuaternionEquality(JSContext *context, JSObject *this, jsval value
{
Quaternion thisq, thatq;
// Note: "return YES" means no error, not equality.
*outEqual = NO;
if (!JSObjectGetQuaternion(context, this, &thisq)) return NO;
if (!JSVAL_IS_OBJECT(value)) return YES;
if (!JSObjectGetQuaternion(context, JSVAL_TO_OBJECT(value), &thatq)) return YES;
if (EXPECT_NOT(!JSObjectGetQuaternion(context, this, &thisq))) return NO; // This is not a quaternion?
if (EXPECT_NOT(!JSVAL_IS_OBJECT(value))) return YES; // Non-object value - not equal
if (EXPECT_NOT(!JSObjectGetQuaternion(context, JSVAL_TO_OBJECT(value), &thatq))) return YES; // Non-quaternion value - not equal
*outEqual = quaternion_equal(thisq, thatq);
return YES;
@ -432,7 +436,7 @@ static JSBool QuaternionToString(JSContext *context, JSObject *this, uintN argc,
{
Quaternion thisq;
if (!JSObjectGetQuaternion(context, this, &thisq)) return NO;
if (EXPECT_NOT(!JSObjectGetQuaternion(context, this, &thisq))) return NO;
*outResult = [QuaternionDescription(thisq) javaScriptValueInContext:context];
return YES;
@ -444,8 +448,8 @@ static JSBool QuaternionMultiply(JSContext *context, JSObject *this, uintN argc,
{
Quaternion thisq, thatq, result;
if (!JSObjectGetQuaternion(context, this, &thisq)) return NO;
if (!QuaternionFromArgumentList(context, @"Quaternion", @"multiply", argc, argv, &thatq, NULL)) return YES;
if (EXPECT_NOT(!JSObjectGetQuaternion(context, this, &thisq))) return NO;
if (EXPECT_NOT(!QuaternionFromArgumentList(context, @"Quaternion", @"multiply", argc, argv, &thatq, NULL))) return NO;
result = quaternion_multiply(thisq, thatq);
@ -459,8 +463,8 @@ static JSBool QuaternionDot(JSContext *context, JSObject *this, uintN argc, jsva
Quaternion thisq, thatq;
double result;
if (!JSObjectGetQuaternion(context, this, &thisq)) return NO;
if (!QuaternionFromArgumentList(context, @"Quaternion", @"dot", argc, argv, &thatq, NULL)) return YES;
if (EXPECT_NOT(!JSObjectGetQuaternion(context, this, &thisq))) return NO;
if (EXPECT_NOT(!QuaternionFromArgumentList(context, @"Quaternion", @"dot", argc, argv, &thatq, NULL))) return NO;
result = quaternion_dot_product(thisq, thatq);
@ -471,17 +475,23 @@ static JSBool QuaternionDot(JSContext *context, JSObject *this, uintN argc, jsva
// rotate(axis : vectorExpression, angle : Number) : Quaternion
static JSBool QuaternionRotate(JSContext *context, JSObject *this, uintN argc, jsval *argv, jsval *outResult)
{
Quaternion quat;
Quaternion thisq;
Vector axis;
double angle;
uintN consumed;
if (!JSObjectGetQuaternion(context, this, &quat)) return NO;
if (!VectorFromArgumentList(context, @"Quaternion", @"rotate", argc, argv, &axis, NULL)) return YES;
if (!NumberFromArgumentList(context, @"Quaternion", @"rotate", argc, argv, &angle, NULL)) return YES;
if (EXPECT_NOT(!JSObjectGetQuaternion(context, this, &thisq))) return NO;
if (EXPECT_NOT(!VectorFromArgumentList(context, @"Quaternion", @"rotate", argc, argv, &axis, &consumed))) return NO;
argv += consumed;
argc -= consumed;
if (argc > 0)
{
if (EXPECT_NOT(!NumberFromArgumentList(context, @"Quaternion", @"rotate", argc, argv, &angle, NULL))) return NO;
quaternion_rotate_about_axis(&thisq, axis, angle);
}
// Else no angle specified, so don't rotate and pass value through unchanged.
quaternion_rotate_about_axis(&quat, axis, angle);
return QuaternionToJSValue(context, quat, outResult);
return QuaternionToJSValue(context, thisq, outResult);
}
@ -491,8 +501,8 @@ static JSBool QuaternionRotateX(JSContext *context, JSObject *this, uintN argc,
Quaternion quat;
double angle;
if (!JSObjectGetQuaternion(context, this, &quat)) return NO;
if (!NumberFromArgumentList(context, @"Quaternion", @"rotateX", argc, argv, &angle, NULL)) return YES;
if (EXPECT_NOT(!JSObjectGetQuaternion(context, this, &quat))) return NO;
if (EXPECT_NOT(!NumberFromArgumentList(context, @"Quaternion", @"rotateX", argc, argv, &angle, NULL))) return NO;
quaternion_rotate_about_x(&quat, angle);
@ -506,8 +516,8 @@ static JSBool QuaternionRotateY(JSContext *context, JSObject *this, uintN argc,
Quaternion quat;
double angle;
if (!JSObjectGetQuaternion(context, this, &quat)) return NO;
if (!NumberFromArgumentList(context, @"Quaternion", @"rotateY", argc, argv, &angle, NULL)) return YES;
if (EXPECT_NOT(!JSObjectGetQuaternion(context, this, &quat))) return NO;
if (EXPECT_NOT(!NumberFromArgumentList(context, @"Quaternion", @"rotateY", argc, argv, &angle, NULL))) return NO;
quaternion_rotate_about_y(&quat, angle);
@ -521,8 +531,8 @@ static JSBool QuaternionRotateZ(JSContext *context, JSObject *this, uintN argc,
Quaternion quat;
double angle;
if (!JSObjectGetQuaternion(context, this, &quat)) return NO;
if (!NumberFromArgumentList(context, @"Quaternion", @"rotateZ", argc, argv, &angle, NULL)) return YES;
if (EXPECT_NOT(!JSObjectGetQuaternion(context, this, &quat))) return NO;
if (EXPECT_NOT(!NumberFromArgumentList(context, @"Quaternion", @"rotateZ", argc, argv, &angle, NULL))) return NO;
quaternion_rotate_about_z(&quat, angle);
@ -535,7 +545,7 @@ static JSBool QuaternionNormalize(JSContext *context, JSObject *this, uintN argc
{
Quaternion quat;
if (!JSObjectGetQuaternion(context, this, &quat)) return NO;
if (EXPECT_NOT(!JSObjectGetQuaternion(context, this, &quat))) return NO;
quaternion_normalize(&quat);
@ -549,7 +559,7 @@ static JSBool QuaternionVectorForward(JSContext *context, JSObject *this, uintN
Quaternion thisq;
Vector result;
if (!JSObjectGetQuaternion(context, this, &thisq)) return NO;
if (EXPECT_NOT(!JSObjectGetQuaternion(context, this, &thisq))) return NO;
result = vector_forward_from_quaternion(thisq);
@ -563,7 +573,7 @@ static JSBool QuaternionVectorUp(JSContext *context, JSObject *this, uintN argc,
Quaternion thisq;
Vector result;
if (!JSObjectGetQuaternion(context, this, &thisq)) return NO;
if (EXPECT_NOT(!JSObjectGetQuaternion(context, this, &thisq))) return NO;
result = vector_up_from_quaternion(thisq);
@ -577,7 +587,7 @@ static JSBool QuaternionVectorRight(JSContext *context, JSObject *this, uintN ar
Quaternion thisq;
Vector result;
if (!JSObjectGetQuaternion(context, this, &thisq)) return NO;
if (EXPECT_NOT(!JSObjectGetQuaternion(context, this, &thisq))) return NO;
result = vector_right_from_quaternion(thisq);
@ -593,7 +603,7 @@ static JSBool QuaternionToArray(JSContext *context, JSObject *this, uintN argc,
BOOL OK = YES;
jsval nVal;
if (!JSObjectGetQuaternion(context, this, &thisq)) return NO;
if (EXPECT_NOT(!JSObjectGetQuaternion(context, this, &thisq))) return NO;
result = JS_NewArrayObject(context, 0, NULL);
if (result != NULL)

View File

@ -56,8 +56,13 @@ BOOL JSVectorSetVector(JSContext *context, JSObject *vectorObj, Vector vector);
outConsumed argument can be used to find out how many parameters were used
(currently, this will be 0 on failure, otherwise 1 or 3).
On failure, it will return NO, annd the vector will be unaltered. If
scriptClass and function are non-nil, a warning will be reported to the
log.
On failure, it will return NO and raise an error. If the caller is a JS
callback, it must return NO to signal an error.
*/
BOOL VectorFromArgumentList(JSContext *context, NSString *scriptClass, NSString *function, uintN argc, jsval *argv, Vector *outVector, uintN *outConsumed);
/* VectorFromArgumentListNoError()
Like VectorFromArgumentList(), but does not report an error on failure.
*/
BOOL VectorFromArgumentListNoError(JSContext *context, uintN argc, jsval *argv, Vector *outVector, uintN *outConsumed);

View File

@ -160,17 +160,17 @@ JSObject *JSVectorWithVector(JSContext *context, Vector vector)
Vector *private = NULL;
private = malloc(sizeof *private);
if (private == NULL) return NULL;
if (EXPECT_NOT(private == NULL)) return NULL;
*private = vector;
result = JS_NewObject(context, &sVectorClass.base, sVectorPrototype, NULL);
if (result != NULL)
{
if (!JS_SetPrivate(context, result, private)) result = NULL;
if (EXPECT_NOT(!JS_SetPrivate(context, result, private))) result = NULL;
}
if (result == NULL) free(private);
if (EXPECT_NOT(result == NULL)) free(private);
return result;
}
@ -180,10 +180,10 @@ BOOL VectorToJSValue(JSContext *context, Vector vector, jsval *outValue)
{
JSObject *object = NULL;
if (outValue == NULL) return NO;
if (EXPECT_NOT(outValue == NULL)) return NO;
object = JSVectorWithVector(context, vector);
if (object == NULL) return NO;
if (EXPECT_NOT(object == NULL)) return NO;
*outValue = OBJECT_TO_JSVAL(object);
return YES;
@ -198,7 +198,7 @@ BOOL NSPointToVectorJSValue(JSContext *context, NSPoint point, jsval *outValue)
BOOL JSValueToVector(JSContext *context, jsval value, Vector *outVector)
{
if (!JSVAL_IS_OBJECT(value)) return NO;
if (EXPECT_NOT(!JSVAL_IS_OBJECT(value))) return NO;
return JSObjectGetVector(context, JSVAL_TO_OBJECT(value), outVector);
}
@ -210,9 +210,9 @@ BOOL JSObjectGetVector(JSContext *context, JSObject *vectorObj, Vector *outVecto
Entity *entity = nil;
jsuint arrayLength;
jsval arrayX, arrayY, arrayZ;
jsdouble dVal;
jsdouble x, y, z;
if (outVector == NULL || vectorObj == NULL) return NO;
if (EXPECT_NOT(outVector == NULL || vectorObj == NULL)) return NO;
private = JS_GetInstancePrivate(context, vectorObj, &sVectorClass.base, NULL);
if (private != NULL) // If this is a (JS) Vector...
@ -239,13 +239,13 @@ BOOL JSObjectGetVector(JSContext *context, JSObject *vectorObj, Vector *outVecto
JS_LookupElement(context, vectorObj, 2, &arrayZ))
{
// ...use the three numbers as [x, y, z]
if (!JS_ValueToNumber(context, arrayX, &dVal)) return NO;
outVector->x = dVal;
if (!JS_ValueToNumber(context, arrayY, &dVal)) return NO;
outVector->y = dVal;
if (!JS_ValueToNumber(context, arrayZ, &dVal)) return NO;
outVector->z = dVal;
return YES;
if (JS_ValueToNumber(context, arrayX, &x) &&
JS_ValueToNumber(context, arrayY, &y) &&
JS_ValueToNumber(context, arrayZ, &z))
{
*outVector = make_vector(x, y, z);
return YES;
}
}
}
}
@ -258,7 +258,7 @@ BOOL JSVectorSetVector(JSContext *context, JSObject *vectorObj, Vector vector)
{
Vector *private = NULL;
if (vectorObj == NULL) return NO;
if (EXPECT_NOT(vectorObj == NULL)) return NO;
private = JS_GetInstancePrivate(context, vectorObj, &sVectorClass.base, NULL);
if (private != NULL) // If this is a (JS) Vector...
@ -272,11 +272,24 @@ BOOL JSVectorSetVector(JSContext *context, JSObject *vectorObj, Vector vector)
BOOL VectorFromArgumentList(JSContext *context, NSString *scriptClass, NSString *function, uintN argc, jsval *argv, Vector *outVector, uintN *outConsumed)
{
if (VectorFromArgumentListNoError(context, argc, argv, outVector, outConsumed)) return YES;
else
{
OOReportJavaScriptBadArguments(context, scriptClass, function, argc, argv,
@"Could not construct vector from parameters",
@"Vector, Entity or three numbers");
return NO;
}
}
BOOL VectorFromArgumentListNoError(JSContext *context, uintN argc, jsval *argv, Vector *outVector, uintN *outConsumed)
{
double x, y, z;
// Sanity checks.
if (outConsumed != NULL) *outConsumed = 0;
// Sanity checks.
if (EXPECT_NOT(argc == 0 || argv == NULL || outVector == NULL))
{
OOLogGenericParameterError();
@ -294,27 +307,17 @@ BOOL VectorFromArgumentList(JSContext *context, NSString *scriptClass, NSString
}
// Otherwise, look for three numbers.
if (argc < 3) goto FAIL;
if (EXPECT_NOT(!JS_ValueToNumber(context, argv[0], &x))) goto FAIL;
if (EXPECT_NOT(!JS_ValueToNumber(context, argv[1], &y))) goto FAIL;
if (EXPECT_NOT(!JS_ValueToNumber(context, argv[2], &z))) goto FAIL;
if (argc < 3) return NO;
// Given a string, JS_ValueToNumber() returns YES but provides a NaN number.
if (EXPECT_NOT(isnan(x) || isnan(y) || isnan(z))) goto FAIL;
if (EXPECT_NOT(!JS_ValueToNumber(context, argv[0], &x) || isnan(x))) return NO;
if (EXPECT_NOT(!JS_ValueToNumber(context, argv[1], &y) || isnan(y))) return NO;
if (EXPECT_NOT(!JS_ValueToNumber(context, argv[2], &z) || isnan(z))) return NO;
// We got our three numbers.
*outVector = make_vector(x, y, z);
if (outConsumed != NULL) *outConsumed = 3;
return YES;
FAIL:
// Report bad parameters, if given a class and function.
if (scriptClass != nil && function != nil)
{
OOReportJavaScriptError(context, @"%@.%@(): could not construct vector from parameters %@ -- expected Vector, Entity or three numbers.", scriptClass, function, [NSString stringWithJavaScriptParameters:argv count:argc inContext:context]);
}
return NO;
}
@ -323,22 +326,23 @@ FAIL:
static JSBool VectorGetProperty(JSContext *context, JSObject *this, jsval name, jsval *outValue)
{
Vector vector;
GLfloat value;
if (!JSVAL_IS_INT(name)) return YES;
if (!JSObjectGetVector(context, this, &vector)) return NO;
if (EXPECT_NOT(!JSObjectGetVector(context, this, &vector))) return NO;
switch (JSVAL_TO_INT(name))
{
case kVector_x:
JS_NewDoubleValue(context, vector.x, outValue);
value = vector.x;
break;
case kVector_y:
JS_NewDoubleValue(context, vector.y, outValue);
value = vector.y;
break;
case kVector_z:
JS_NewDoubleValue(context, vector.z, outValue);
value = vector.z;
break;
default:
@ -346,7 +350,7 @@ static JSBool VectorGetProperty(JSContext *context, JSObject *this, jsval name,
return NO;
}
return YES;
return JS_NewDoubleValue(context, value, outValue);
}
@ -356,8 +360,8 @@ static JSBool VectorSetProperty(JSContext *context, JSObject *this, jsval name,
jsdouble dval;
if (!JSVAL_IS_INT(name)) return YES;
if (!JSObjectGetVector(context, this, &vector)) return NO;
JS_ValueToNumber(context, *value, &dval);
if (EXPECT_NOT(!JSObjectGetVector(context, this, &vector))) return NO;
if (EXPECT_NOT(!JS_ValueToNumber(context, *value, &dval))) return NO;
switch (JSVAL_TO_INT(name))
{
@ -400,13 +404,13 @@ static JSBool VectorConstruct(JSContext *context, JSObject *this, uintN argc, js
Vector *private = NULL;
private = malloc(sizeof *private);
if (private == NULL) return NO;
if (EXPECT_NOT(private == NULL)) return NO;
if (argc != 0) VectorFromArgumentList(context, NULL, NULL, argc, argv, &vector, NULL);
*private = vector;
if (!JS_SetPrivate(context, this, private))
if (EXPECT_NOT(!JS_SetPrivate(context, this, private)))
{
free(private);
return NO;
@ -421,9 +425,9 @@ static JSBool VectorEquality(JSContext *context, JSObject *this, jsval value, JS
Vector thisv, thatv;
*outEqual = NO;
if (!JSObjectGetVector(context, this, &thisv)) return NO;
if (!JSVAL_IS_OBJECT(value)) return YES;
if (!JSObjectGetVector(context, JSVAL_TO_OBJECT(value), &thatv)) return YES;
if (EXPECT_NOT(!JSObjectGetVector(context, this, &thisv))) return NO;
if (EXPECT_NOT(!JSVAL_IS_OBJECT(value))) return YES;
if (EXPECT_NOT(!JSObjectGetVector(context, JSVAL_TO_OBJECT(value), &thatv))) return YES;
*outEqual = vector_equal(thisv, thatv);
return YES;
@ -432,25 +436,25 @@ static JSBool VectorEquality(JSContext *context, JSObject *this, jsval value, JS
// *** Methods ***
// string toString()
// toString() : String
static JSBool VectorToString(JSContext *context, JSObject *this, uintN argc, jsval *argv, jsval *outResult)
{
Vector thisv;
if (!JSObjectGetVector(context, this, &thisv)) return NO;
if (EXPECT_NOT(!JSObjectGetVector(context, this, &thisv))) return NO;
*outResult = [VectorDescription(thisv) javaScriptValueInContext:context];
return YES;
}
// Vector add(vectorExpression)
// add(v : vectorExpression) : Vector
static JSBool VectorAdd(JSContext *context, JSObject *this, uintN argc, jsval *argv, jsval *outResult)
{
Vector thisv, thatv, result;
if (!JSObjectGetVector(context, this, &thisv)) return NO;
if (!VectorFromArgumentList(context, @"Vector", @"add", argc, argv, &thatv, NULL)) return YES;
if (EXPECT_NOT(!JSObjectGetVector(context, this, &thisv))) return NO;
if (EXPECT_NOT(!VectorFromArgumentList(context, @"Vector", @"add", argc, argv, &thatv, NULL))) return NO;
result = vector_add(thisv, thatv);
@ -458,13 +462,13 @@ static JSBool VectorAdd(JSContext *context, JSObject *this, uintN argc, jsval *a
}
// Vector subtract(vectorExpression)
// subtract(v : vectorExpression) : Vector
static JSBool VectorSubtract(JSContext *context, JSObject *this, uintN argc, jsval *argv, jsval *outResult)
{
Vector thisv, thatv, result;
if (!JSObjectGetVector(context, this, &thisv)) return NO;
if (!VectorFromArgumentList(context, @"Vector", @"subtract", argc, argv, &thatv, NULL)) return YES;
if (EXPECT_NOT(!JSObjectGetVector(context, this, &thisv))) return NO;
if (EXPECT_NOT(!VectorFromArgumentList(context, @"Vector", @"subtract", argc, argv, &thatv, NULL))) return NO;
result = vector_subtract(thisv, thatv);
@ -472,14 +476,14 @@ static JSBool VectorSubtract(JSContext *context, JSObject *this, uintN argc, jsv
}
// Vector distanceTo(vectorExpression)
// distanceTo(v : vectorExpression) : Vector
static JSBool VectorDistanceTo(JSContext *context, JSObject *this, uintN argc, jsval *argv, jsval *outResult)
{
Vector thisv, thatv;
GLfloat result;
if (!JSObjectGetVector(context, this, &thisv)) return NO;
if (!VectorFromArgumentList(context, @"Vector", @"distanceTo", argc, argv, &thatv, NULL)) return YES;
if (EXPECT_NOT(!JSObjectGetVector(context, this, &thisv))) return NO;
if (EXPECT_NOT(!VectorFromArgumentList(context, @"Vector", @"distanceTo", argc, argv, &thatv, NULL))) return NO;
result = distance(thisv, thatv);
@ -487,14 +491,14 @@ static JSBool VectorDistanceTo(JSContext *context, JSObject *this, uintN argc, j
}
// Vector squaredDistanceTo(vectorExpression)
// squaredDistanceTo(v : vectorExpression) : Vector
static JSBool VectorSquaredDistanceTo(JSContext *context, JSObject *this, uintN argc, jsval *argv, jsval *outResult)
{
Vector thisv, thatv;
GLfloat result;
if (!JSObjectGetVector(context, this, &thisv)) return NO;
if (!VectorFromArgumentList(context, @"Vector", @"squaredDistanceTo", argc, argv, &thatv, NULL)) return YES;
if (EXPECT_NOT(!JSObjectGetVector(context, this, &thisv))) return NO;
if (EXPECT_NOT(!VectorFromArgumentList(context, @"Vector", @"squaredDistanceTo", argc, argv, &thatv, NULL))) return NO;
result = distance2(thisv, thatv);
@ -502,14 +506,14 @@ static JSBool VectorSquaredDistanceTo(JSContext *context, JSObject *this, uintN
}
// Vector multiply(double)
// multiply(n : Number) : Vector
static JSBool VectorMultiply(JSContext *context, JSObject *this, uintN argc, jsval *argv, jsval *outResult)
{
Vector thisv, result;
double scalar;
if (!JSObjectGetVector(context, this, &thisv)) return NO;
if (!NumberFromArgumentList(context, @"Vector", @"multiply", argc, argv, &scalar, NULL)) return YES;
if (EXPECT_NOT(!JSObjectGetVector(context, this, &thisv))) return NO;
if (EXPECT_NOT(!NumberFromArgumentList(context, @"Vector", @"multiply", argc, argv, &scalar, NULL))) return NO;
result = vector_multiply_scalar(thisv, scalar);
@ -517,14 +521,14 @@ static JSBool VectorMultiply(JSContext *context, JSObject *this, uintN argc, jsv
}
// Vector dot(vectorExpression)
// dot(v : vectorExpression) : Number
static JSBool VectorDot(JSContext *context, JSObject *this, uintN argc, jsval *argv, jsval *outResult)
{
Vector thisv, thatv;
GLfloat result;
if (!JSObjectGetVector(context, this, &thisv)) return NO;
if (!VectorFromArgumentList(context, @"Vector", @"dot", argc, argv, &thatv, NULL)) return YES;
if (EXPECT_NOT(!JSObjectGetVector(context, this, &thisv))) return NO;
if (EXPECT_NOT(!VectorFromArgumentList(context, @"Vector", @"dot", argc, argv, &thatv, NULL))) return NO;
result = dot_product(thisv, thatv);
@ -532,14 +536,14 @@ static JSBool VectorDot(JSContext *context, JSObject *this, uintN argc, jsval *a
}
// double angleTo(vectorExpression)
// angleTo(v : vectorExpression) : Number
static JSBool VectorAngleTo(JSContext *context, JSObject *this, uintN argc, jsval *argv, jsval *outResult)
{
Vector thisv, thatv;
GLfloat result;
if (!JSObjectGetVector(context, this, &thisv)) return NO;
if (!VectorFromArgumentList(context, @"Vector", @"angleTo", argc, argv, &thatv, NULL)) return YES;
if (EXPECT_NOT(!JSObjectGetVector(context, this, &thisv))) return NO;
if (EXPECT_NOT(!VectorFromArgumentList(context, @"Vector", @"angleTo", argc, argv, &thatv, NULL))) return NO;
result = acosf(dot_product(vector_normal(thisv), vector_normal(thatv)));
@ -547,13 +551,13 @@ static JSBool VectorAngleTo(JSContext *context, JSObject *this, uintN argc, jsva
}
// Vector cross(vectorExpression)
// cross(v : vectorExpression) : Vector
static JSBool VectorCross(JSContext *context, JSObject *this, uintN argc, jsval *argv, jsval *outResult)
{
Vector thisv, thatv, result;
if (!JSObjectGetVector(context, this, &thisv)) return NO;
if (!VectorFromArgumentList(context, @"Vector", @"cross", argc, argv, &thatv, NULL)) return YES;
if (EXPECT_NOT(!JSObjectGetVector(context, this, &thisv))) return NO;
if (EXPECT_NOT(!VectorFromArgumentList(context, @"Vector", @"cross", argc, argv, &thatv, NULL))) return NO;
result = true_cross_product(thisv, thatv);
@ -561,18 +565,18 @@ static JSBool VectorCross(JSContext *context, JSObject *this, uintN argc, jsval
}
// Vector tripleProduct(vectorExpression, vectorExpression)
// tripleProduct(v : vectorExpression) : Number
static JSBool VectorTripleProduct(JSContext *context, JSObject *this, uintN argc, jsval *argv, jsval *outResult)
{
Vector thisv, thatv, theotherv;
GLfloat result;
uintN consumed;
if (!JSObjectGetVector(context, this, &thisv)) return NO;
if (!VectorFromArgumentList(context, @"Vector", @"tripleProduct", argc, argv, &thatv, &consumed)) return YES;
if (EXPECT_NOT(!JSObjectGetVector(context, this, &thisv))) return NO;
if (EXPECT_NOT(!VectorFromArgumentList(context, @"Vector", @"tripleProduct", argc, argv, &thatv, &consumed))) return NO;
argc += consumed;
argv += consumed;
if (!VectorFromArgumentList(context, @"Vector", @"tripleProduct", argc, argv, &theotherv, NULL)) return YES;
if (EXPECT_NOT(!VectorFromArgumentList(context, @"Vector", @"tripleProduct", argc, argv, &theotherv, NULL))) return NO;
result = triple_product(thisv, thatv, theotherv);
@ -580,12 +584,12 @@ static JSBool VectorTripleProduct(JSContext *context, JSObject *this, uintN argc
}
// Vector direction()
// direction() : Vector
static JSBool VectorDirection(JSContext *context, JSObject *this, uintN argc, jsval *argv, jsval *outResult)
{
Vector thisv, result;
if (!JSObjectGetVector(context, this, &thisv)) return NO;
if (EXPECT_NOT(!JSObjectGetVector(context, this, &thisv))) return NO;
result = vector_normal(thisv);
@ -593,13 +597,13 @@ static JSBool VectorDirection(JSContext *context, JSObject *this, uintN argc, js
}
// double magnitude()
// magnitude() : Number
static JSBool VectorMagnitude(JSContext *context, JSObject *this, uintN argc, jsval *argv, jsval *outResult)
{
Vector thisv;
GLfloat result;
if (!JSObjectGetVector(context, this, &thisv)) return NO;
if (EXPECT_NOT(!JSObjectGetVector(context, this, &thisv))) return NO;
result = magnitude(thisv);
@ -607,13 +611,13 @@ static JSBool VectorMagnitude(JSContext *context, JSObject *this, uintN argc, js
}
// double squaredMagnitude()
// squaredMagnitude() : Number
static JSBool VectorSquaredMagnitude(JSContext *context, JSObject *this, uintN argc, jsval *argv, jsval *outResult)
{
Vector thisv;
GLfloat result;
if (!JSObjectGetVector(context, this, &thisv)) return NO;
if (EXPECT_NOT(!JSObjectGetVector(context, this, &thisv))) return NO;
result = magnitude2(thisv);
@ -621,7 +625,7 @@ static JSBool VectorSquaredMagnitude(JSContext *context, JSObject *this, uintN a
}
// Quaternion rotationTo(vectorExpression)
// rotationTo(v : vectorExpression [, limit : Number]) : Quaternion
static JSBool VectorRotationTo(JSContext *context, JSObject *this, uintN argc, jsval *argv, jsval *outResult)
{
Vector thisv, thatv;
@ -630,14 +634,14 @@ static JSBool VectorRotationTo(JSContext *context, JSObject *this, uintN argc, j
Quaternion result;
uintN consumed;
if (!JSObjectGetVector(context, this, &thisv)) return NO;
if (!VectorFromArgumentList(context, @"Vector", @"rotationTo", argc, argv, &thatv, &consumed)) return YES;
if (EXPECT_NOT(!JSObjectGetVector(context, this, &thisv))) return NO;
if (EXPECT_NOT(!VectorFromArgumentList(context, @"Vector", @"rotationTo", argc, argv, &thatv, &consumed))) return NO;
argc -= consumed;
argv += consumed;
if (argc != 0) // limit parameter is optional.
{
if (!NumberFromArgumentList(context, @"Vector", @"rotationTo", argc, argv, &limit, NULL)) return YES;
if (EXPECT_NOT(!NumberFromArgumentList(context, @"Vector", @"rotationTo", argc, argv, &limit, NULL))) return NO;
gotLimit = YES;
}
else gotLimit = NO;
@ -655,8 +659,8 @@ static JSBool VectorRotateBy(JSContext *context, JSObject *this, uintN argc, jsv
Vector thisv, result;
Quaternion q;
if (!JSObjectGetVector(context, this, &thisv)) return NO;
if (!QuaternionFromArgumentList(context, @"Vector", @"rotateBy", argc, argv, &q, NULL)) return YES;
if (EXPECT_NOT(!JSObjectGetVector(context, this, &thisv))) return NO;
if (EXPECT_NOT(!QuaternionFromArgumentList(context, @"Vector", @"rotateBy", argc, argv, &q, NULL))) return NO;
result = quaternion_rotate_vector(q, thisv);
@ -669,10 +673,9 @@ static JSBool VectorToArray(JSContext *context, JSObject *this, uintN argc, jsva
{
Vector thisv;
JSObject *result = NULL;
BOOL OK = YES;
jsval nVal;
if (!JSObjectGetVector(context, this, &thisv)) return NO;
if (EXPECT_NOT(!JSObjectGetVector(context, this, &thisv))) return NO;
result = JS_NewArrayObject(context, 0, NULL);
if (result != NULL)
@ -680,16 +683,17 @@ static JSBool VectorToArray(JSContext *context, JSObject *this, uintN argc, jsva
// We do this at the top because *outResult is a GC root.
*outResult = OBJECT_TO_JSVAL(result);
if (JS_NewNumberValue(context, thisv.x, &nVal)) JS_SetElement(context, result, 0, &nVal);
else OK = NO;
if (JS_NewNumberValue(context, thisv.y, &nVal)) JS_SetElement(context, result, 1, &nVal);
else OK = NO;
if (JS_NewNumberValue(context, thisv.z, &nVal)) JS_SetElement(context, result, 2, &nVal);
else OK = NO;
if (JS_NewNumberValue(context, thisv.x, &nVal) && JS_SetElement(context, result, 0, &nVal) &&
JS_NewNumberValue(context, thisv.y, &nVal) && JS_SetElement(context, result, 1, &nVal) &&
JS_NewNumberValue(context, thisv.z, &nVal) && JS_SetElement(context, result, 2, &nVal))
{
return YES;
}
// If we get here, the conversion and stuffing in the previous condition failed.
*outResult = JSVAL_VOID;
}
if (!OK) *outResult = JSVAL_VOID;
return YES;
return NO;
}
@ -700,20 +704,29 @@ static JSBool VectorStaticInterpolate(JSContext *context, JSObject *this, uintN
double interp;
Vector result;
uintN consumed;
uintN inArgc = argc;
jsval *inArgv = argv;
if (!VectorFromArgumentList(context, @"Vector", @"interpolate", argc, argv, &av, &consumed)) return YES;
if (EXPECT_NOT(argc < 3)) goto INSUFFICIENT_ARGUMENTS;
if (EXPECT_NOT(!VectorFromArgumentList(context, @"Vector", @"interpolate", argc, argv, &av, &consumed))) return NO;
argc -= consumed;
argv += consumed;
if (argc < 2) return YES;
if (!VectorFromArgumentList(context, @"Vector", @"interpolate", argc, argv, &bv, &consumed)) return YES;
if (EXPECT_NOT(argc < 2)) goto INSUFFICIENT_ARGUMENTS;
if (EXPECT_NOT(!VectorFromArgumentList(context, @"Vector", @"interpolate", argc, argv, &bv, &consumed))) return NO;
argc -= consumed;
argv += consumed;
if (argc < 1) return YES;
if (!NumberFromArgumentList(context, @"Vector", @"interpolate", argc, argv, &interp, NULL)) return YES;
if (EXPECT_NOT(argc < 1)) goto INSUFFICIENT_ARGUMENTS;
if (EXPECT_NOT(!NumberFromArgumentList(context, @"Vector", @"interpolate", argc, argv, &interp, NULL))) return NO;
result = OOVectorInterpolate(av, bv, interp);
return VectorToJSValue(context, result, outResult);
INSUFFICIENT_ARGUMENTS:
OOReportJavaScriptBadArguments(context, @"Vector", @"interpolate", inArgc, inArgv,
@"Insufficient parameters",
@"vector expression, vector expression and number");
return NO;
}
@ -722,7 +735,7 @@ static JSBool VectorStaticRandom(JSContext *context, JSObject *this, uintN argc,
{
double maxLength;
if (argc == 0 || !NumberFromArgumentList(context, @"Vector", @"random", argc, argv, &maxLength, NULL)) maxLength = 1.0;
if (argc == 0 || !NumberFromArgumentListNoError(context, argc, argv, &maxLength, NULL)) maxLength = 1.0;
return VectorToJSValue(context, OOVectorRandomSpatial(maxLength), outResult);
}
@ -733,7 +746,7 @@ static JSBool VectorStaticRandomDirection(JSContext *context, JSObject *this, ui
{
double scale;
if (argc == 0 || !NumberFromArgumentList(context, @"Vector", @"randomDirection", argc, argv, &scale, NULL)) scale = 1.0;
if (argc == 0 || !NumberFromArgumentListNoError(context, argc, argv, &scale, NULL)) scale = 1.0;
return VectorToJSValue(context, vector_multiply_scalar(OORandomUnitVector(), scale), outResult);
}
@ -744,7 +757,7 @@ static JSBool VectorStaticRandomDirectionAndLength(JSContext *context, JSObject
{
double maxLength;
if (argc == 0 || !NumberFromArgumentList(context, @"Vector", @"randomDirectionAndLength", argc, argv, &maxLength, NULL)) maxLength = 1.0;
if (argc == 0 || !NumberFromArgumentListNoError(context, argc, argv, &maxLength, NULL)) maxLength = 1.0;
return VectorToJSValue(context, OOVectorRandomSpatial(maxLength), outResult);
}

View File

@ -86,11 +86,23 @@ enum
void OOReportJavaScriptError(JSContext *context, NSString *format, ...);
void OOReportJavaScriptErrorWithArguments(JSContext *context, NSString *format, va_list args);
void OOReportJavaScriptErrorForCaller(JSContext *context, NSString *scriptClass, NSString *function, NSString *format, ...);
void OOReportJavaScriptWarning(JSContext *context, NSString *format, ...);
void OOReportJavaScriptWarningWithArguments(JSContext *context, NSString *format, va_list args);
void OOReportJavaScriptBadPropertySelector(JSContext *context, NSString *className, jsint selector);
void OOReportJavaScriptWarningForCaller(JSContext *context, NSString *scriptClass, NSString *function, NSString *format, ...);
void OOReportJavaScriptBadPropertySelector(JSContext *context, NSString *className, jsint selector);
void OOReportJavaScriptBadArguments(JSContext *context, NSString *scriptClass, NSString *function, uintN argc, jsval *argv, NSString *message, NSString *expectedArgsDescription);
/* OOSetJSWarningOrErrorStackSkip()
Indicate that the direct call site is not relevant for error handler.
Currently, if non-zero, no call site information is provided.
Ideally, we'd stack crawl instead.
*/
void OOSetJSWarningOrErrorStackSkip(unsigned skip);
void OOSetJSWarningOrErrorStackSkip(unsigned skip); // Indicate that the direct call site is not relevant for error handler. Currently, if non-zero, no call site information is provided. Ideally, we'd stack crawl instead.
/* NumberFromArgumentList()
@ -98,12 +110,17 @@ void OOSetJSWarningOrErrorStackSkip(unsigned skip); // Indicate that the direct
argument can be used to find out how many parameters were used (currently,
this will be 0 on failure, otherwise 1).
On failure, it will return NO, annd the number will be unaltered. If
scriptClass and function are non-nil, a warning will be reported to the
log.
On failure, it will return NO and raise an error. If the caller is a JS
callback, it must return NO to signal an error.
*/
BOOL NumberFromArgumentList(JSContext *context, NSString *scriptClass, NSString *function, uintN argc, jsval *argv, double *outNumber, uintN *outConsumed);
/* NumberFromArgumentListNoError()
Like NumberFromArgumentList(), but does not report an error on failure.
*/
BOOL NumberFromArgumentListNoError(JSContext *context, uintN argc, jsval *argv, double *outNumber, uintN *outConsumed);
// Typed as int rather than BOOL to work with more general expressions such as bitfield tests.
OOINLINE jsval BOOLToJSVal(int b) INLINE_CONST_FUNC;

View File

@ -436,6 +436,14 @@ static void ReportJSError(JSContext *context, const char *message, JSErrorReport
#endif
static NSString *CallerPrefix(NSString *scriptClass, NSString *function)
{
if (function == nil) return @"";
if (scriptClass == nil) return [function stringByAppendingString:@": "];
return [NSString stringWithFormat:@"%@.%@: ", scriptClass, function];
}
void OOReportJavaScriptError(JSContext *context, NSString *format, ...)
{
va_list args;
@ -446,6 +454,20 @@ void OOReportJavaScriptError(JSContext *context, NSString *format, ...)
}
void OOReportJavaScriptErrorForCaller(JSContext *context, NSString *scriptClass, NSString *function, NSString *format, ...)
{
va_list args;
NSString *msg = nil;
va_start(args, format);
msg = [[NSString alloc] initWithFormat:format arguments:args];
va_end(args);
OOReportJavaScriptError(context, @"%@%@", CallerPrefix(scriptClass, function), msg);
[msg release];
}
void OOReportJavaScriptErrorWithArguments(JSContext *context, NSString *format, va_list args)
{
NSString *msg = nil;
@ -466,6 +488,20 @@ void OOReportJavaScriptWarning(JSContext *context, NSString *format, ...)
}
void OOReportJavaScriptWarningForCaller(JSContext *context, NSString *scriptClass, NSString *function, NSString *format, ...)
{
va_list args;
NSString *msg = nil;
va_start(args, format);
msg = [[NSString alloc] initWithFormat:format arguments:args];
va_end(args);
OOReportJavaScriptWarning(context, @"%@%@", CallerPrefix(scriptClass, function), msg);
[msg release];
}
void OOReportJavaScriptWarningWithArguments(JSContext *context, NSString *format, va_list args)
{
NSString *msg = nil;
@ -482,6 +518,15 @@ void OOReportJavaScriptBadPropertySelector(JSContext *context, NSString *classNa
}
void OOReportJavaScriptBadArguments(JSContext *context, NSString *scriptClass, NSString *function, uintN argc, jsval *argv, NSString *message, NSString *expectedArgsDescription)
{
message = [NSString stringWithFormat:@"%@ %@", message, [NSString stringWithJavaScriptParameters:argv count:argc inContext:context]];
if (expectedArgsDescription != nil) message = [NSString stringWithFormat:@"%@ -- expected %@", message, expectedArgsDescription];
OOReportJavaScriptErrorForCaller(context, scriptClass, function, @"%@.", message);
}
void OOSetJSWarningOrErrorStackSkip(unsigned skip)
{
sErrorHandlerStackSkip = skip;
@ -489,6 +534,18 @@ void OOSetJSWarningOrErrorStackSkip(unsigned skip)
BOOL NumberFromArgumentList(JSContext *context, NSString *scriptClass, NSString *function, uintN argc, jsval *argv, double *outNumber, uintN *outConsumed)
{
if (NumberFromArgumentListNoError(context, argc, argv, outNumber, outConsumed)) return YES;
else
{
OOReportJavaScriptBadArguments(context, scriptClass, function, argc, argv,
@"Expected number, got", NULL);
return NO;
}
}
BOOL NumberFromArgumentListNoError(JSContext *context, uintN argc, jsval *argv, double *outNumber, uintN *outConsumed)
{
double value;
@ -503,12 +560,7 @@ BOOL NumberFromArgumentList(JSContext *context, NSString *scriptClass, NSString
// Get value, if possible.
if (EXPECT_NOT(!JS_ValueToNumber(context, argv[0], &value) || isnan(value)))
{
// Failed; report bad parameters, if given a class and function.
if (scriptClass != nil && function != nil)
{
OOReportJavaScriptError(context, @"%@.%@(): expected number, got %@.", scriptClass, function, [NSString stringWithJavaScriptParameters:argv count:1 inContext:context]);
return NO;
}
return NO;
}
// Success.
@ -878,13 +930,12 @@ static BOOL JSNewNSDictionaryValue(JSContext *context, NSDictionary *dictionary,
uintN i;
jsval val;
NSMutableString *result = [NSMutableString string];
NSMutableString *result = [NSMutableString stringWithString:@"("];
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];
@ -892,6 +943,10 @@ static BOOL JSNewNSDictionaryValue(JSContext *context, NSDictionary *dictionary,
{
[result appendFormat:@"\"%@\"", valString];
}
else if (JSVAL_IS_OBJECT(val) && JS_IsArrayObject(context, JSVAL_TO_OBJECT(val)))
{
[result appendFormat:@"[%@]", valString];
}
else
{
if (valString == nil)

View File

@ -1337,7 +1337,7 @@ GLfloat docked_light_specular[4] = { (GLfloat) 1.0, (GLfloat) 1.0, (GLfloat) 0.5
andOriginalSystem: systems[Ranrot() & 255]]]];
if (trader_ship->scanClass == CLASS_NOT_SET)
[trader_ship setScanClass: CLASS_NEUTRAL];
[trader_ship setScanClass:CLASS_NEUTRAL];
[trader_ship setPosition:launchPos];
[trader_ship setBounty:0];
[trader_ship setCargoFlag:CARGO_FLAG_FULL_SCARCE];