diff --git a/source/graphics/scripting/JSInterface_Camera.cpp b/source/graphics/scripting/JSInterface_Camera.cpp index 5454ac7740..d1f5f5b90c 100644 --- a/source/graphics/scripting/JSInterface_Camera.cpp +++ b/source/graphics/scripting/JSInterface_Camera.cpp @@ -217,19 +217,12 @@ JSBool JSI_Camera::lookAt( JSContext* cx, JSObject* obj, uint argc, jsval* argv, JSI_Vector3D::Vector3D_Info* v = NULL; Camera_Info* cameraInfo = (Camera_Info*)JS_GetPrivate( cx, obj ); - if( 2 <= argc && argc <= 3 ) - { - cameraInfo->m_sv_Position = GETVECTOR( argv[0] ); - cameraInfo->m_sv_Orientation = ( GETVECTOR( argv[1] ) - GETVECTOR( argv[0] ) ); - cameraInfo->m_sv_Orientation.Normalize(); - } - else - { - JS_ReportError( cx, "[Camera] lookAt: incorrect argument count" ); - *rval = JSVAL_FALSE; - return( JS_TRUE ); - } - + JSU_REQUIRE_PARAM_RANGE(2, 3); + + cameraInfo->m_sv_Position = GETVECTOR( argv[0] ); + cameraInfo->m_sv_Orientation = ( GETVECTOR( argv[1] ) - GETVECTOR( argv[0] ) ); + cameraInfo->m_sv_Orientation.Normalize(); + if( argc == 2 ) { cameraInfo->m_sv_Up = CVector3D( 0.0f, 1.0f, 0.0f ); @@ -265,31 +258,28 @@ JSBool JSI_Camera::construct( JSContext* cx, JSObject* UNUSED(obj), JSObject* camera = JS_NewObject( cx, &JSI_Camera::JSI_class, NULL, NULL ); - if( argc == 0 ) + JSU_REQUIRE_PARAM_RANGE(0, 3); + Camera_Info* camera_info = 0; + switch(argc) { - JS_SetPrivate( cx, camera, new Camera_Info() ); - } - else if( argc == 1 ) - { - JS_SetPrivate( cx, camera, new Camera_Info( GETVECTOR( argv[0] ) ) ); - } - else if( argc == 2 ) - { - JS_SetPrivate( cx, camera, new Camera_Info( GETVECTOR( argv[0] ), GETVECTOR( argv[1] ) ) ); - } - else if( argc == 3 ) - { - JS_SetPrivate( cx, camera, new Camera_Info( GETVECTOR( argv[0] ), GETVECTOR( argv[1] ), GETVECTOR( argv[2] ) ) ); - } - else - { - JS_ReportError( cx, "[Camera] Too many arguments to constructor" ); - *rval = JSVAL_NULL; - return( JS_TRUE ); + case 0: + camera_info = new Camera_Info(); + break; + case 1: + camera_info = new Camera_Info( GETVECTOR( argv[0] ) ); + break; + case 2: + camera_info = new Camera_Info( GETVECTOR( argv[0] ), GETVECTOR( argv[1] ) ); + break; + case 3: + camera_info = new Camera_Info( GETVECTOR( argv[0] ), GETVECTOR( argv[1] ), GETVECTOR( argv[2] ) ); + break; + NODEFAULT; } #undef GET_VECTOR + JS_SetPrivate( cx, camera, camera_info ); *rval = OBJECT_TO_JSVAL( camera ); return( JS_TRUE ); } diff --git a/source/graphics/scripting/JSInterface_LightEnv.cpp b/source/graphics/scripting/JSInterface_LightEnv.cpp index 876061b8cf..f2e8721079 100644 --- a/source/graphics/scripting/JSInterface_LightEnv.cpp +++ b/source/graphics/scripting/JSInterface_LightEnv.cpp @@ -77,21 +77,13 @@ struct LightEnv_Info : public IPropertyOwner * construct: the LightEnv constructor has been called from JavaScript, so create a new * LightEnv object */ -JSBool construct(JSContext* cx, JSObject* UNUSED(obj), uintN argc, jsval* UNUSED(argv), jsval* rval) +JSBool construct(JSContext* cx, JSObject* UNUSED(obj), uintN argc, jsval* argv, jsval* rval) { JSObject* lightenv = JS_NewObject(cx, &JSI_class, NULL, NULL); - if(argc == 0) - { - JS_SetPrivate(cx, lightenv, new LightEnv_Info); - } - else - { - JS_ReportError(cx, "[LightEnv] Too many arguments to constructor"); - *rval = JSVAL_NULL; - return JS_TRUE; - } + JSU_REQUIRE_NO_PARAMS(); + JS_SetPrivate(cx, lightenv, new LightEnv_Info); *rval = OBJECT_TO_JSVAL(lightenv); return JS_TRUE; } diff --git a/source/i18n/ScriptInterface.cpp b/source/i18n/ScriptInterface.cpp index e3783dc030..8eb01d3796 100644 --- a/source/i18n/ScriptInterface.cpp +++ b/source/i18n/ScriptInterface.cpp @@ -10,8 +10,6 @@ using namespace I18n; -#define JS_ASSERT(expr, msg) if (! (expr)) { JS_ReportError(cx, msg); return JS_FALSE; } - // LookedupWord JS class: namespace JSI_LookedupWord { @@ -26,7 +24,7 @@ namespace JSI_LookedupWord { debug_assert(locale); JSString* prop = JS_ValueToString(cx, id); - JS_ASSERT(prop, "lookup() property failed to convert to string"); + JSU_ASSERT(prop, "lookup() property failed to convert to string"); jschar* prop_chars = JS_GetStringChars(prop); @@ -38,7 +36,7 @@ namespace JSI_LookedupWord { result = L"(unrecognised property)"; JSString* result_str = StringConvert::wstring_to_jsstring(cx, result); - JS_ASSERT(result_str, "lookup() property failed to create string"); + JSU_ASSERT(result_str, "lookup() property failed to create string"); *vp = STRING_TO_JSVAL(result_str); @@ -74,10 +72,10 @@ namespace JSI_i18n { /* Set *rval = { type => "Name", value => argv[0] } */ \ \ JSObject* object = JS_NewObject(cx, NULL, NULL, obj); \ - JS_ASSERT(object, "Failed to create i18n value object"); \ + JSU_ASSERT(object, "Failed to create i18n value object"); \ \ /* TODO: More error checking */ \ - JS_ASSERT(argc == 1, "Create_" #x ": not enough params"); \ + JSU_REQUIRE_PARAMS(1); \ jsval type = STRING_TO_JSVAL(JS_NewStringCopyZ(cx, #x)); \ jsval value = STRING_TO_JSVAL(JS_ValueToString(cx, argv[0])); \ JS_SetProperty(cx, object, "type", &type); \ @@ -114,12 +112,12 @@ namespace JSI_i18n { static JSBool JSFunc_LookupWord(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) { - JS_ASSERT(argc == 2, "Incorrect number of parameters to lookup(dictionary, word) function"); + JSU_REQUIRE_PARAMS(2); // Get the strings JSString* dictname = JS_ValueToString(cx, argv[0]); JSString* word = JS_ValueToString(cx, argv[1]); - JS_ASSERT(dictname && word, "lookup() failed to convert parameters to strings"); + JSU_ASSERT(dictname && word, "lookup() failed to convert parameters to strings"); // and the characters from the strings jschar* dictname_chars = JS_GetStringChars(dictname); @@ -144,7 +142,7 @@ static JSBool JSFunc_LookupWord(JSContext *cx, JSObject *obj, uintN argc, jsval // Create an object to be returned, containing enough data to access properties of the found word JSObject* wordobj = JS_NewObject(cx, &JSI_LookedupWord::JSI_class, NULL, obj); - JS_ASSERT(wordobj, "lookup() failed to create object"); + JSU_ASSERT(wordobj, "lookup() failed to create object"); // Associate the looked-up word data with the JS object JS_SetPrivate(cx, wordobj, (void*)lookedup); @@ -155,15 +153,15 @@ static JSBool JSFunc_LookupWord(JSContext *cx, JSObject *obj, uintN argc, jsval static JSBool JSFunc_Translate(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) { - JS_ASSERT(argc >= 1, "Too few parameters to translate() function"); + JSU_ASSERT(argc >= 1, "Too few parameters to translate() function"); JSString* phrase_str = JS_ValueToString(cx, argv[0]); - JS_ASSERT(phrase_str, "translate() failed to convert first parameter to string"); + JSU_ASSERT(phrase_str, "translate() failed to convert first parameter to string"); CStrW phrase (JS_GetStringChars(phrase_str)); jsval locale_objval; - JS_ASSERT(JS_GetProperty(cx, obj, "i18n", &locale_objval), "translate() failed to find i18n object in current scope"); + JSU_ASSERT(JS_GetProperty(cx, obj, "i18n", &locale_objval), "translate() failed to find i18n object in current scope"); CLocale* locale = (CLocale*)JS_GetPrivate(cx, JSVAL_TO_OBJECT(locale_objval)); StringBuffer sb = locale->Translate(phrase.c_str()); diff --git a/source/maths/scripting/JSInterface_Vector3D.cpp b/source/maths/scripting/JSInterface_Vector3D.cpp index 71559bb5b0..d44516762d 100644 --- a/source/maths/scripting/JSInterface_Vector3D.cpp +++ b/source/maths/scripting/JSInterface_Vector3D.cpp @@ -159,28 +159,21 @@ JSBool JSI_Vector3D::construct( JSContext* cx, JSObject* UNUSED(obj), uintN argc *rval = OBJECT_TO_JSVAL( vector ); return( JS_TRUE ); } - else if( argc == 3 ) + + JSU_REQUIRE_PARAMS(3); + try { - try - { - float x = ToPrimitive( argv[0] ); - float y = ToPrimitive( argv[1] ); - float z = ToPrimitive( argv[2] ); - JS_SetPrivate( cx, vector, new Vector3D_Info( x, y, z ) ); - *rval = OBJECT_TO_JSVAL( vector ); - return( JS_TRUE ); - } - catch (PSERROR_Scripting_ConversionFailed) - { - // Invalid input (i.e. can't be coerced into doubles) - fail - JS_ReportError( cx, "Invalid parameters to Vector3D constructor" ); - *rval = JSVAL_NULL; - return( JS_FALSE ); - } + float x = ToPrimitive( argv[0] ); + float y = ToPrimitive( argv[1] ); + float z = ToPrimitive( argv[2] ); + JS_SetPrivate( cx, vector, new Vector3D_Info( x, y, z ) ); + *rval = OBJECT_TO_JSVAL( vector ); + return( JS_TRUE ); } - else + catch (PSERROR_Scripting_ConversionFailed) { - JS_ReportError( cx, "Invalid number of parameters to Vector3D constructor" ); + // Invalid input (i.e. can't be coerced into doubles) - fail + JS_ReportError( cx, "Invalid parameters to Vector3D constructor" ); *rval = JSVAL_NULL; return( JS_FALSE ); } diff --git a/source/scripting/JSUtil.cpp b/source/scripting/JSUtil.cpp new file mode 100644 index 0000000000..52ccc8a68d --- /dev/null +++ b/source/scripting/JSUtil.cpp @@ -0,0 +1,15 @@ +#include "precompiled.h" + +#include "SpiderMonkey.h" + +jsval jsu_report_param_error(JSContext* cx, jsval* rval) +{ + JS_ReportError(cx, "Invalid parameter(s) or count"); + + if(rval) + *rval = JSVAL_NULL; + + // yes, we had an error, but returning JS_FALSE would cause SpiderMonkey + // to abort. that would be hard to debug. + return JS_TRUE; +} diff --git a/source/scripting/JSUtil.h b/source/scripting/JSUtil.h new file mode 100644 index 0000000000..9440339c15 --- /dev/null +++ b/source/scripting/JSUtil.h @@ -0,0 +1,44 @@ +// included from SpiderMonkey.h + +extern jsval jsu_report_param_error(JSContext* cx, jsval* rval); + + +// consistent argc checking for normal function wrappers: reports an +// error via JS and returns if number of parameters is incorrect. +// .. require exact number (most common case) +#define JSU_REQUIRE_PARAMS(exact_number)\ + if(argc != exact_number)\ + return jsu_report_param_error(cx, rval); +// .. require 0 params (avoids L4 warning "unused argv param") +#define JSU_REQUIRE_NO_PARAMS()\ + UNUSED2(argv);\ + if(argc != 0)\ + return jsu_report_param_error(cx, rval); +// .. require a certain range (e.g. due to optional params) +#define JSU_REQUIRE_PARAM_RANGE(min_number, max_number)\ + if(!(min_number <= argc && argc <= max_number))\ + return jsu_report_param_error(cx, rval); +// .. require at least a certain count (rarely needed) +#define JSU_REQUIRE_MIN_PARAMS(min_number)\ + if(argc < min_number)\ + return jsu_report_param_error(cx, rval); + +// same as JSU_REQUIRE_PARAMS, but used from C++ functions that are +// a bit further removed from SpiderMonkey, i.e. return a +// C++ bool indicating success, and not taking an rval param. +#define JSU_REQUIRE_PARAMS_CPP(exact_number)\ + if(argc != exact_number)\ + {\ + jsu_report_param_error(cx, 0);\ + return false;\ + } + + +#define JSU_ASSERT(expr, msg)\ +STMT(\ + if(!(expr))\ + {\ + JS_ReportError(cx, msg);\ + return JS_FALSE;\ + }\ +) diff --git a/source/scripting/ScriptGlue.cpp b/source/scripting/ScriptGlue.cpp index 7fe3560f8b..150e73315b 100644 --- a/source/scripting/ScriptGlue.cpp +++ b/source/scripting/ScriptGlue.cpp @@ -60,37 +60,6 @@ extern bool g_TerrainModified; // all property accessors have the following signature: // JSBool accessor(JSContext* cx, JSObject* globalObject, jsval id, jsval* vp); -// consistent argc checking for normal function wrappers: reports an -// error via JS and returns if number of parameters is incorrect. -// .. require exact number (most common case) -#define REQUIRE_PARAMS(exact_number, func_name)\ - if(argc != exact_number)\ - {\ - JS_ReportError(cx, #func_name ": number of parameters passed doesn't match expected count");\ - return JS_FALSE;\ - } -// .. require 0 params (avoids L4 warning "unused argv param") -#define REQUIRE_NO_PARAMS(func_name)\ - UNUSED2(argv);\ - if(argc != 0)\ - {\ - JS_ReportError(cx, #func_name ": number of parameters passed doesn't match expected count");\ - return JS_FALSE;\ - } -// .. accept at most N params (e.g. buildTime) -#define REQUIRE_MAX_PARAMS(max_number, func_name)\ - if(argc > max_number)\ - {\ - JS_ReportError(cx, #func_name ": too many parameters passed");\ - return JS_FALSE;\ - } -// .. accept at least N params (e.g. issueCommand) -#define REQUIRE_MIN_PARAMS(min_number, func_name)\ - if(argc < min_number)\ - {\ - JS_ReportError(cx, #func_name ": too few parameters passed");\ - return JS_FALSE;\ - } //----------------------------------------------------------------------------- // Output @@ -102,9 +71,9 @@ extern bool g_TerrainModified; // notes: // - Each argument is converted to a string and then written to the log. // - Output is in NORMAL style (see LOG). -JSBool WriteLog(JSContext* cx, JSObject*, uint argc, jsval* argv, jsval* UNUSED(rval)) +JSBool WriteLog(JSContext* cx, JSObject*, uint argc, jsval* argv, jsval* rval) { - REQUIRE_MIN_PARAMS(1, WriteLog); + JSU_REQUIRE_PARAMS(1); CStr logMessage; @@ -125,6 +94,7 @@ JSBool WriteLog(JSContext* cx, JSObject*, uint argc, jsval* argv, jsval* UNUSED( LOG( NORMAL, "script", logMessage ); + *rval = JSVAL_TRUE; return JS_TRUE; } @@ -138,7 +108,7 @@ JSBool WriteLog(JSContext* cx, JSObject*, uint argc, jsval* argv, jsval* UNUSED( // returns: entity JSBool getEntityByHandle( JSContext* cx, JSObject*, uint argc, jsval* argv, jsval* rval ) { - REQUIRE_PARAMS(1, getEntityByHandle); + JSU_REQUIRE_PARAMS(1); *rval = JSVAL_NULL; i32 handle; @@ -169,8 +139,7 @@ JSBool getEntityByHandle( JSContext* cx, JSObject*, uint argc, jsval* argv, jsva // returns: entity template object JSBool getEntityTemplate( JSContext* cx, JSObject*, uint argc, jsval* argv, jsval* rval ) { - REQUIRE_MIN_PARAMS(1, getEntityTemplate); - REQUIRE_MAX_PARAMS(2, getEntityTemplate); + JSU_REQUIRE_PARAM_RANGE(1, 2); *rval = JSVAL_NULL; CStrW templateName; @@ -237,7 +206,9 @@ void CreateFormationMessage( std::vector& msgList, CNetMessage* ms // returns: command in serialized form [string] JSBool issueCommand( JSContext* cx, JSObject*, uint argc, jsval* argv, jsval* rval ) { - REQUIRE_MIN_PARAMS(2, issueCommand); + // at least one for target object, and then 1 or more for the CommandFromJSArgs + JSU_REQUIRE_MIN_PARAMS(2); + debug_assert(JSVAL_IS_OBJECT(argv[0])); *rval = JSVAL_NULL; @@ -300,7 +271,7 @@ JSBool issueCommand( JSContext* cx, JSObject*, uint argc, jsval* argv, jsval* rv //Formation stuff JSBool createEntityFormation( JSContext* cx, JSObject* UNUSED(obj), uint argc, jsval* argv, jsval* rval ) { - REQUIRE_MIN_PARAMS(2, createEntityFormation); + JSU_REQUIRE_PARAMS(2); CEntityList entities = *EntityCollection::RetrieveSet(cx, JSVAL_TO_OBJECT(argv[0])); CStrW name = ToPrimitive( argv[1] ); @@ -311,7 +282,7 @@ JSBool createEntityFormation( JSContext* cx, JSObject* UNUSED(obj), uint argc, j } JSBool removeFromFormation( JSContext* cx, JSObject* UNUSED(obj), uint argc, jsval* argv, jsval* rval ) { - REQUIRE_MIN_PARAMS(1, removeFromFormation); + JSU_REQUIRE_PARAMS(1); CEntityList entities; if (JS_GetClass(JSVAL_TO_OBJECT(argv[0])) == &CEntity::JSI_class) @@ -324,7 +295,7 @@ JSBool removeFromFormation( JSContext* cx, JSObject* UNUSED(obj), uint argc, jsv } JSBool lockEntityFormation( JSContext* cx, JSObject* UNUSED(obj), uint argc, jsval* argv, jsval* rval ) { - REQUIRE_MIN_PARAMS(1, lockEntityFormation); + JSU_REQUIRE_PARAMS(1); CEntity* entity = ToNative( argv[0] ); entity->GetFormation()->SetLock( ToPrimitive( argv[1] ) ); @@ -333,7 +304,7 @@ JSBool lockEntityFormation( JSContext* cx, JSObject* UNUSED(obj), uint argc, jsv } JSBool isFormationLocked( JSContext* cx, JSObject* UNUSED(obj), uint argc, jsval* argv, jsval* rval ) { - REQUIRE_MIN_PARAMS(1, isFormationLocked); + JSU_REQUIRE_PARAMS(1); CEntity* entity = ToNative( argv[0] ); *rval = entity->GetFormation()->IsLocked() ? JS_TRUE : JS_FALSE; @@ -345,7 +316,7 @@ JSBool isFormationLocked( JSContext* cx, JSObject* UNUSED(obj), uint argc, jsval JSBool getTechnology( JSContext* cx, JSObject* UNUSED(obj), uint argc, jsval* argv, jsval* rval ) { - REQUIRE_MIN_PARAMS(2, getTechnology); + JSU_REQUIRE_PARAMS(2); CStrW name; CPlayer* player; @@ -381,7 +352,7 @@ JSBool getTechnology( JSContext* cx, JSObject* UNUSED(obj), uint argc, jsval* ar // returns: whether it was actually newly registered [bool] JSBool AddGlobalHandler( JSContext* cx, JSObject* UNUSED(obj), uint argc, jsval* argv, jsval* rval ) { - REQUIRE_PARAMS(2, AddGlobalHandler); + JSU_REQUIRE_PARAMS(2); *rval = BOOLEAN_TO_JSVAL( g_JSGameEvents.AddHandlerJS( cx, argc, argv ) ); return( JS_TRUE ); @@ -393,7 +364,7 @@ JSBool AddGlobalHandler( JSContext* cx, JSObject* UNUSED(obj), uint argc, jsval* // returns: whether it was successfully removed [bool] JSBool RemoveGlobalHandler( JSContext* cx, JSObject* UNUSED(obj), uint argc, jsval* argv, jsval* rval ) { - REQUIRE_PARAMS(2, RemoveGlobalHandler); + JSU_REQUIRE_PARAMS(2); *rval = BOOLEAN_TO_JSVAL( g_JSGameEvents.RemoveHandlerJS( cx, argc, argv ) ); return( JS_TRUE ); @@ -422,8 +393,7 @@ JSBool RemoveGlobalHandler( JSContext* cx, JSObject* UNUSED(obj), uint argc, jsv // 'this' reference is usually maintained) JSBool setTimeout( JSContext* cx, JSObject*, uint argc, jsval* argv, jsval* rval ) { - REQUIRE_MIN_PARAMS(2, setTimeout); - REQUIRE_MAX_PARAMS(3, setTimeout); + JSU_REQUIRE_PARAM_RANGE(2, 3); size_t delay; try @@ -482,8 +452,7 @@ JSBool setTimeout( JSContext* cx, JSObject*, uint argc, jsval* argv, jsval* rval // - setTimeout's notes apply here as well. JSBool setInterval( JSContext* cx, JSObject*, uint argc, jsval* argv, jsval* rval ) { - REQUIRE_MIN_PARAMS(2, setInterval); - REQUIRE_MAX_PARAMS(3, setInterval); + JSU_REQUIRE_PARAM_RANGE(2, 3); size_t first, interval; try @@ -536,9 +505,9 @@ JSBool setInterval( JSContext* cx, JSObject*, uint argc, jsval* argv, jsval* rva // notes: // - Execution continues until the end of the triggered function or // script fragment, but is not triggered again. -JSBool cancelInterval( JSContext* cx, JSObject*, uint argc, jsval* argv, jsval* UNUSED(rval) ) +JSBool cancelInterval( JSContext* cx, JSObject*, uint argc, jsval* argv, jsval* rval ) { - REQUIRE_NO_PARAMS(cancelInterval); + JSU_REQUIRE_NO_PARAMS(); g_Scheduler.m_abortInterval = true; return( JS_TRUE ); @@ -552,10 +521,9 @@ JSBool cancelInterval( JSContext* cx, JSObject*, uint argc, jsval* argv, jsval* // notes: // - Execution continues until the end of the triggered function or // script fragment, but is not triggered again. -JSBool cancelTimer( JSContext* cx, JSObject*, uint argc, jsval* argv, jsval* UNUSED(rval) ) +JSBool cancelTimer( JSContext* cx, JSObject*, uint argc, jsval* argv, jsval* rval ) { - REQUIRE_MIN_PARAMS(1, cancelTimer); - REQUIRE_MAX_PARAMS(1, cancelTimer); + JSU_REQUIRE_PARAMS(1); try { @@ -572,10 +540,9 @@ JSBool cancelTimer( JSContext* cx, JSObject*, uint argc, jsval* argv, jsval* UNU } //Set the simulation rate scalar-time becomes time * SimRate. //Params: rate [float] : sets SimRate -JSBool setSimRate(JSContext* cx, JSObject*, uint argc, jsval* argv, jsval* UNUSED(rval)) +JSBool setSimRate(JSContext* cx, JSObject*, uint argc, jsval* argv, jsval* rval) { - REQUIRE_MIN_PARAMS(1, setSimRate); - REQUIRE_MAX_PARAMS(1, setSimRate); + JSU_REQUIRE_PARAMS(1); g_Game->SetSimRate( ToPrimitive(argv[0]) ); return JS_TRUE; @@ -618,12 +585,11 @@ static void initXTimers() xoverhead = xclients[0].sum/4; } -JSBool startXTimer(JSContext* cx, JSObject*, uint argc, jsval* argv, jsval* UNUSED(rval)) +JSBool startXTimer(JSContext* cx, JSObject*, uint argc, jsval* argv, jsval* rval) { ONCE(initXTimers()); - REQUIRE_MIN_PARAMS(1, startXTimer); - REQUIRE_MIN_PARAMS(1, startXTimer); + JSU_REQUIRE_PARAMS(1); uint slot = ToPrimitive(argv[0]); debug_assert(slot < MAX_XTIMERS); @@ -633,10 +599,9 @@ JSBool startXTimer(JSContext* cx, JSObject*, uint argc, jsval* argv, jsval* UNUS } -JSBool stopXTimer(JSContext* cx, JSObject*, uint argc, jsval* argv, jsval* UNUSED(rval)) +JSBool stopXTimer(JSContext* cx, JSObject*, uint argc, jsval* argv, jsval* rval) { - REQUIRE_MIN_PARAMS(1, stopXTimer); - REQUIRE_MIN_PARAMS(1, stopXTimer); + JSU_REQUIRE_PARAMS(1); uint slot = ToPrimitive(argv[0]); debug_assert(slot < MAX_XTIMERS); @@ -657,7 +622,7 @@ JSBool stopXTimer(JSContext* cx, JSObject*, uint argc, jsval* argv, jsval* UNUSE // returns: net server object JSBool createServer(JSContext* cx, JSObject*, uint argc, jsval* argv, jsval* rval) { - REQUIRE_NO_PARAMS(createServer); + JSU_REQUIRE_NO_PARAMS(); if( !g_Game ) g_Game = new CGame(); @@ -674,7 +639,7 @@ JSBool createServer(JSContext* cx, JSObject*, uint argc, jsval* argv, jsval* rva // returns: net client object JSBool createClient(JSContext* cx, JSObject*, uint argc, jsval* argv, jsval* rval) { - REQUIRE_NO_PARAMS(createClient); + JSU_REQUIRE_NO_PARAMS(); if( !g_Game ) g_Game = new CGame(); @@ -697,7 +662,7 @@ JSBool createClient(JSContext* cx, JSObject*, uint argc, jsval* argv, jsval* rva // after merging CGame and CGameAttributes JSBool startGame(JSContext* cx, JSObject*, uint argc, jsval* argv, jsval* rval) { - REQUIRE_NO_PARAMS(startGame); + JSU_REQUIRE_NO_PARAMS(); *rval = BOOLEAN_TO_JSVAL(JS_TRUE); @@ -732,9 +697,9 @@ JSBool startGame(JSContext* cx, JSObject*, uint argc, jsval* argv, jsval* rval) // Immediately ends the current game (if any). // params: // returns: -JSBool endGame(JSContext* cx, JSObject*, uint argc, jsval* argv, jsval* UNUSED(rval)) +JSBool endGame(JSContext* cx, JSObject*, uint argc, jsval* argv, jsval* rval) { - REQUIRE_NO_PARAMS(endGame); + JSU_REQUIRE_NO_PARAMS(); EndGame(); return JS_TRUE; @@ -753,9 +718,9 @@ JSBool endGame(JSContext* cx, JSObject*, uint argc, jsval* argv, jsval* UNUSED(r // Replaces the current language (locale) with a new one. // params: language id [string] as in I18n::LoadLanguage // returns: -JSBool loadLanguage(JSContext* cx, JSObject*, uint argc, jsval* argv, jsval* UNUSED(rval)) +JSBool loadLanguage(JSContext* cx, JSObject*, uint argc, jsval* argv, jsval* rval) { - REQUIRE_PARAMS(1, loadLanguage); + JSU_REQUIRE_PARAMS(1); CStr lang = g_ScriptingHost.ValueToString(argv[0]); I18n::LoadLanguage(lang); @@ -769,7 +734,7 @@ JSBool loadLanguage(JSContext* cx, JSObject*, uint argc, jsval* argv, jsval* UNU // returns: language id [string] as in I18n::LoadLanguage JSBool getLanguageID(JSContext* cx, JSObject*, uint argc, jsval* argv, jsval* rval) { - REQUIRE_NO_PARAMS(getLanguageID); + JSU_REQUIRE_NO_PARAMS(); *rval = JSVAL_NULL; JSString* s = JS_NewStringCopyZ(cx, I18n::CurrentLanguageName()); @@ -794,9 +759,9 @@ JSBool getLanguageID(JSContext* cx, JSObject*, uint argc, jsval* argv, jsval* rv // notes: // - currently implemented via access violation (read of address 0) // - useful for testing the crashlog/stack trace code. -JSBool crash(JSContext* cx, JSObject*, uint argc, jsval* argv, jsval* UNUSED(rval)) +JSBool crash(JSContext* cx, JSObject*, uint argc, jsval* argv, jsval* rval) { - REQUIRE_NO_PARAMS(crash); + JSU_REQUIRE_NO_PARAMS(); MICROLOG(L"Crashing at user's request."); return *(JSBool*)0; @@ -810,7 +775,7 @@ JSBool crash(JSContext* cx, JSObject*, uint argc, jsval* argv, jsval* UNUSED(rva // - writes an indication of how long this took to the console. JSBool forceGC(JSContext* cx, JSObject* UNUSED(obj), uint argc, jsval* argv, jsval* rval) { - REQUIRE_NO_PARAMS(forceGC); + JSU_REQUIRE_NO_PARAMS(); double time = get_time(); JS_GC(cx); @@ -833,7 +798,7 @@ JSBool forceGC(JSContext* cx, JSObject* UNUSED(obj), uint argc, jsval* argv, jsv // - Useful for accessing an object from another scope. JSBool getGUIGlobal(JSContext* cx, JSObject*, uint argc, jsval* argv, jsval* rval) { - REQUIRE_NO_PARAMS(getGUIGlobal); + JSU_REQUIRE_NO_PARAMS(); *rval = OBJECT_TO_JSVAL(g_GUI.GetScriptObject()); return JS_TRUE; @@ -842,9 +807,9 @@ JSBool getGUIGlobal(JSContext* cx, JSObject*, uint argc, jsval* argv, jsval* rva // Resets the entire GUI state and reloads the XML files. // params: // returns: -JSBool resetGUI(JSContext* cx, JSObject*, uint argc, jsval* argv, jsval* UNUSED(rval)) +JSBool resetGUI(JSContext* cx, JSObject*, uint argc, jsval* argv, jsval* rval) { - REQUIRE_NO_PARAMS(resetGUI); + JSU_REQUIRE_NO_PARAMS(); // Slightly unpleasant code, because CGUI is a Singleton but we don't really // want it to be @@ -870,7 +835,7 @@ JSBool resetGUI(JSContext* cx, JSObject*, uint argc, jsval* argv, jsval* UNUSED( // filter it, so it is both accurate and free of jitter. JSBool getFPS( JSContext* cx, JSObject*, uint argc, jsval* argv, jsval* rval ) { - REQUIRE_NO_PARAMS(getFPS); + JSU_REQUIRE_NO_PARAMS(); *rval = INT_TO_JSVAL(fps); return JS_TRUE; @@ -883,9 +848,9 @@ JSBool getFPS( JSContext* cx, JSObject*, uint argc, jsval* argv, jsval* rval ) // notes: // - Exit happens after the current main loop iteration ends // (since this only sets a flag telling it to end) -JSBool exitProgram( JSContext* cx, JSObject*, uint argc, jsval* argv, jsval* UNUSED(rval) ) +JSBool exitProgram( JSContext* cx, JSObject*, uint argc, jsval* argv, jsval* rval ) { - REQUIRE_NO_PARAMS(exitProgram); + JSU_REQUIRE_NO_PARAMS(); kill_mainloop(); return JS_TRUE; @@ -899,9 +864,9 @@ JSBool exitProgram( JSContext* cx, JSObject*, uint argc, jsval* argv, jsval* UNU // - Not supported on all platforms. // - Only a rough approximation; do not base low-level decisions // ("should I allocate one more texture?") on this. -JSBool vmem( JSContext* cx, JSObject*, uint argc, jsval* argv, jsval* UNUSED(rval) ) +JSBool vmem( JSContext* cx, JSObject*, uint argc, jsval* argv, jsval* rval ) { - REQUIRE_NO_PARAMS(vmem); + JSU_REQUIRE_NO_PARAMS(); #if OS_WIN int left, total; @@ -921,9 +886,9 @@ JSBool vmem( JSContext* cx, JSObject*, uint argc, jsval* argv, jsval* UNUSED(rva // returns: // notes: // - Cursors are stored in "art\textures\cursors" -JSBool setCursor( JSContext* cx, JSObject*, uint argc, jsval* argv, jsval* UNUSED(rval) ) +JSBool setCursor( JSContext* cx, JSObject*, uint argc, jsval* argv, jsval* rval ) { - REQUIRE_PARAMS(1, setCursor); + JSU_REQUIRE_PARAMS(1); g_CursorName = g_ScriptingHost.ValueToString(argv[0]); return JS_TRUE; } @@ -938,9 +903,9 @@ JSBool getCursorName( JSContext* UNUSED(cx), JSObject*, uint UNUSED(argc), jsval // returns: // notes: // - Usefulness is unclear. If you need it, consider renaming this and updating the docs. -JSBool _rewriteMaps( JSContext* cx, JSObject*, uint argc, jsval* argv, jsval* UNUSED(rval) ) +JSBool _rewriteMaps( JSContext* cx, JSObject*, uint argc, jsval* argv, jsval* rval ) { - REQUIRE_NO_PARAMS(_rewriteMaps); + JSU_REQUIRE_NO_PARAMS(); g_Game->GetWorld()->RewriteMap(); return JS_TRUE; @@ -953,9 +918,9 @@ JSBool _rewriteMaps( JSContext* cx, JSObject*, uint argc, jsval* argv, jsval* UN // notes: // - value is as required by GL_TEXTURE_LOD_BIAS. // - useful for adjusting image "sharpness" (since it affects which mipmap level is chosen) -JSBool _lodbias( JSContext* cx, JSObject*, uint argc, jsval* argv, jsval* UNUSED(rval) ) +JSBool _lodbias( JSContext* cx, JSObject*, uint argc, jsval* argv, jsval* rval ) { - REQUIRE_PARAMS(1, _lodbias); + JSU_REQUIRE_PARAMS(1); g_Renderer.SetOptionFloat(CRenderer::OPT_LODBIAS, ToPrimitive(argv[0])); return JS_TRUE; @@ -967,7 +932,7 @@ JSBool _lodbias( JSContext* cx, JSObject*, uint argc, jsval* argv, jsval* UNUSED // returns: success [bool] JSBool setCameraTarget( JSContext* cx, JSObject* UNUSED(obj), uint argc, jsval* argv, jsval* rval ) { - REQUIRE_PARAMS(1, setCameraTarget); + JSU_REQUIRE_PARAMS(1); *rval = JSVAL_NULL; CVector3D* target = ToNative( argv[0] ); @@ -999,7 +964,7 @@ JSBool setCameraTarget( JSContext* cx, JSObject* UNUSED(obj), uint argc, jsval* // last compiled; since the auto-build does full rebuilds, that is moot. JSBool buildTime( JSContext* cx, JSObject*, uint argc, jsval* argv, jsval* rval ) { - REQUIRE_MAX_PARAMS(1, buildTime); + JSU_REQUIRE_PARAM_RANGE(0, 1); // buildTime( ) = "date time" // buildTime(0) = "date" @@ -1019,7 +984,7 @@ JSBool buildTime( JSContext* cx, JSObject*, uint argc, jsval* argv, jsval* rval // returns: Euclidean distance [float] JSBool v3dist( JSContext* cx, JSObject* UNUSED(obj), uint argc, jsval* argv, jsval* rval ) { - REQUIRE_PARAMS(2, v3dist); + JSU_REQUIRE_PARAMS(2); CVector3D* a = ToNative( argv[0] ); CVector3D* b = ToNative( argv[1] ); @@ -1036,7 +1001,7 @@ JSBool v3dist( JSContext* cx, JSObject* UNUSED(obj), uint argc, jsval* argv, jsv // - Useful for accessing an object from another scope. JSBool getGlobal( JSContext* cx, JSObject* globalObject, uint argc, jsval* argv, jsval* rval ) { - REQUIRE_NO_PARAMS(getGlobal); + JSU_REQUIRE_NO_PARAMS(); *rval = OBJECT_TO_JSVAL( globalObject ); return( JS_TRUE ); @@ -1069,7 +1034,7 @@ JSBool startPlacing( JSContext* cx, JSObject* UNUSED(globalObject), uint argc, j // Toggles drawing the sky JSBool toggleSky( JSContext* cx, JSObject* UNUSED(globalObject), uint argc, jsval* argv, jsval* rval ) { - REQUIRE_NO_PARAMS( toggleSky ); + JSU_REQUIRE_NO_PARAMS(); g_Renderer.GetSkyManager()->m_RenderSky = !g_Renderer.GetSkyManager()->m_RenderSky; *rval = JSVAL_VOID; return( JS_TRUE ); @@ -1078,7 +1043,7 @@ JSBool toggleSky( JSContext* cx, JSObject* UNUSED(globalObject), uint argc, jsva // Toggles drawing the water plane JSBool toggleWater( JSContext* cx, JSObject* UNUSED(globalObject), uint argc, jsval* argv, jsval* rval ) { - REQUIRE_NO_PARAMS( toggleWater ); + JSU_REQUIRE_NO_PARAMS(); g_Renderer.GetWaterManager()->m_RenderWater = !g_Renderer.GetWaterManager()->m_RenderWater; *rval = JSVAL_VOID; return( JS_TRUE ); @@ -1087,7 +1052,7 @@ JSBool toggleWater( JSContext* cx, JSObject* UNUSED(globalObject), uint argc, js // Sets the water plane height JSBool setWaterHeight( JSContext* cx, JSObject* UNUSED(globalObject), uint argc, jsval* argv, jsval* rval ) { - REQUIRE_PARAMS( 1, setWaterHeight ); + JSU_REQUIRE_PARAMS( 1 ); float newHeight; if(!ToPrimitive( g_ScriptingHost.GetContext(), argv[0], newHeight )) { @@ -1104,7 +1069,7 @@ JSBool setWaterHeight( JSContext* cx, JSObject* UNUSED(globalObject), uint argc, // Gets the water plane height JSBool getWaterHeight( JSContext* cx, JSObject* UNUSED(globalObject), uint argc, jsval* argv, jsval* rval ) { - REQUIRE_NO_PARAMS( getWaterHeight ); + JSU_REQUIRE_NO_PARAMS(); *rval = ToJSVal(g_Renderer.GetWaterManager()->m_WaterHeight); return( JS_TRUE ); } @@ -1112,7 +1077,7 @@ JSBool getWaterHeight( JSContext* cx, JSObject* UNUSED(globalObject), uint argc, // Sets the water color JSBool setWaterColor( JSContext* cx, JSObject* UNUSED(globalObject), uint argc, jsval* argv, jsval* rval ) { - REQUIRE_PARAMS( 3, setWaterColor ); + JSU_REQUIRE_PARAMS( 3 ); float r,g,b; if(!ToPrimitive( g_ScriptingHost.GetContext(), argv[0], r ) || !ToPrimitive( g_ScriptingHost.GetContext(), argv[1], g ) @@ -1130,7 +1095,7 @@ JSBool setWaterColor( JSContext* cx, JSObject* UNUSED(globalObject), uint argc, // Sets the water tint (used to tint reflections in fancy water) JSBool setWaterTint( JSContext* cx, JSObject* UNUSED(globalObject), uint argc, jsval* argv, jsval* rval ) { - REQUIRE_PARAMS( 3, setWaterTint ); + JSU_REQUIRE_PARAMS( 3 ); float r,g,b; if(!ToPrimitive( g_ScriptingHost.GetContext(), argv[0], r ) || !ToPrimitive( g_ScriptingHost.GetContext(), argv[1], g ) @@ -1148,7 +1113,7 @@ JSBool setWaterTint( JSContext* cx, JSObject* UNUSED(globalObject), uint argc, j // Sets the max water alpha (achieved when it is at WaterFullDepth or deeper) JSBool setWaterMaxAlpha( JSContext* cx, JSObject* UNUSED(globalObject), uint argc, jsval* argv, jsval* rval ) { - REQUIRE_PARAMS( 1, setWaterMaxAlpha ); + JSU_REQUIRE_PARAMS( 1 ); float val; if(!ToPrimitive( g_ScriptingHost.GetContext(), argv[0], val )) { @@ -1164,7 +1129,7 @@ JSBool setWaterMaxAlpha( JSContext* cx, JSObject* UNUSED(globalObject), uint arg // Sets the water full depth (when it is colored WaterMaxAlpha) JSBool setWaterFullDepth( JSContext* cx, JSObject* UNUSED(globalObject), uint argc, jsval* argv, jsval* rval ) { - REQUIRE_PARAMS( 1, setWaterFullDepth ); + JSU_REQUIRE_PARAMS( 1 ); float val; if(!ToPrimitive( g_ScriptingHost.GetContext(), argv[0], val )) { @@ -1180,7 +1145,7 @@ JSBool setWaterFullDepth( JSContext* cx, JSObject* UNUSED(globalObject), uint ar // Sets the water alpha offset (added to tweak water alpha near the shore) JSBool setWaterAlphaOffset( JSContext* cx, JSObject* UNUSED(globalObject), uint argc, jsval* argv, jsval* rval ) { - REQUIRE_PARAMS( 1, setWaterAlphaOffset ); + JSU_REQUIRE_PARAMS( 1 ); float val; if(!ToPrimitive( g_ScriptingHost.GetContext(), argv[0], val )) { @@ -1196,7 +1161,7 @@ JSBool setWaterAlphaOffset( JSContext* cx, JSObject* UNUSED(globalObject), uint // Is the game paused? JSBool isPaused( JSContext* cx, JSObject* UNUSED(globalObject), uint argc, jsval* argv, jsval* rval ) { - REQUIRE_NO_PARAMS( isPaused ); + JSU_REQUIRE_NO_PARAMS(); if( !g_Game ) { @@ -1209,9 +1174,9 @@ JSBool isPaused( JSContext* cx, JSObject* UNUSED(globalObject), uint argc, jsval } // Pause/unpause the game -JSBool setPaused( JSContext* cx, JSObject* UNUSED(globalObject), uint argc, jsval* argv, jsval* UNUSED(rval) ) +JSBool setPaused( JSContext* cx, JSObject* UNUSED(globalObject), uint argc, jsval* argv, jsval* rval ) { - REQUIRE_PARAMS( 1, setPaused ); + JSU_REQUIRE_PARAMS( 1 ); if( !g_Game ) { @@ -1234,7 +1199,7 @@ JSBool setPaused( JSContext* cx, JSObject* UNUSED(globalObject), uint argc, jsva // Get game time JSBool getGameTime( JSContext* cx, JSObject* UNUSED(globalObject), uint argc, jsval* argv, jsval* rval ) { - REQUIRE_NO_PARAMS( getGameTime ); + JSU_REQUIRE_NO_PARAMS(); if( !g_Game ) { @@ -1249,8 +1214,7 @@ JSBool getGameTime( JSContext* cx, JSObject* UNUSED(globalObject), uint argc, js // Reveal map JSBool revealMap( JSContext* cx, JSObject* UNUSED(globalObject), uint argc, jsval* argv, jsval* rval ) { - REQUIRE_MIN_PARAMS( 0, revealMap ); - REQUIRE_MAX_PARAMS( 1, revealMap ); + JSU_REQUIRE_PARAM_RANGE(0, 1); uint newValue; if(argc == 0) diff --git a/source/scripting/SpiderMonkey.h b/source/scripting/SpiderMonkey.h index 58bed35704..9fe31db855 100644 --- a/source/scripting/SpiderMonkey.h +++ b/source/scripting/SpiderMonkey.h @@ -31,6 +31,7 @@ // include any further required headers here +#include "JSUtil.h" // Make JS debugging a little easier by automatically naming GC roots // Don't simply #define NAME_ALL_GC_ROOTS, because jsapi.h is horridly broken diff --git a/source/simulation/Entity.cpp b/source/simulation/Entity.cpp index c4c0897e83..8cee5ec65e 100644 --- a/source/simulation/Entity.cpp +++ b/source/simulation/Entity.cpp @@ -1651,10 +1651,9 @@ void CEntity::JSI_SetPlayer( jsval val ) bool CEntity::Order( JSContext* cx, uintN argc, jsval* argv, bool Queued ) { // This needs to be sorted (uses Scheduler rather than network messaging) - debug_assert( argc >= 1 ); int orderCode; - + debug_assert(argc >= 1); try { orderCode = ToPrimitive( argv[0] ); @@ -1675,11 +1674,7 @@ bool CEntity::Order( JSContext* cx, uintN argc, jsval* argv, bool Queued ) case CEntityOrder::ORDER_GOTO: case CEntityOrder::ORDER_RUN: case CEntityOrder::ORDER_PATROL: - if( argc < 3 ) - { - JS_ReportError( cx, "Too few parameters" ); - return( false ); - } + JSU_REQUIRE_PARAMS_CPP(3); try { newOrder.m_data[0].location.x = ToPrimitive( argv[1] ); @@ -1703,11 +1698,7 @@ bool CEntity::Order( JSContext* cx, uintN argc, jsval* argv, bool Queued ) } break; case CEntityOrder::ORDER_GENERIC: - if( argc < 3 ) - { - JS_ReportError( cx, "Too few parameters" ); - return( false ); - } + JSU_REQUIRE_PARAMS_CPP(3); target = ToNative( argv[1] ); if( !target ) { @@ -1735,11 +1726,7 @@ bool CEntity::Order( JSContext* cx, uintN argc, jsval* argv, bool Queued ) } break; case CEntityOrder::ORDER_PRODUCE: - if( argc < 3 ) - { - JS_ReportError( cx, "Too few parameters" ); - return( false ); - } + JSU_REQUIRE_PARAMS_CPP(3); try { newOrder.m_data[0].string = ToPrimitive(argv[2]); newOrder.m_data[1].data = ToPrimitive(argv[1]); @@ -1999,11 +1986,7 @@ jsval CEntity::SetActionParams( JSContext* UNUSED(cx), uintN argc, jsval* argv ) bool CEntity::RequestNotification( JSContext* cx, uintN argc, jsval* argv ) { - if( argc < 4 ) - { - JS_ReportError( cx, "Too few parameters" ); - return( false ); - } + JSU_REQUIRE_PARAMS_CPP(4); CEntityListener notify; CEntity *target = ToNative( argv[0] ); @@ -2061,11 +2044,7 @@ int CEntity::GetCurrentRequest( JSContext* UNUSED(cx), uintN UNUSED(argc), jsval } bool CEntity::ForceCheckListeners( JSContext *cx, uintN argc, jsval* argv ) { - if( argc < 2 ) - { - JS_ReportError( cx, "Too few parameters" ); - return false; - } + JSU_REQUIRE_PARAMS_CPP(2); int type = ToPrimitive( argv[0] ); //notify code m_currentNotification = type; @@ -2137,11 +2116,7 @@ jsval CEntity::DestroyAllNotifiers( JSContext* UNUSED(cx), uintN UNUSED(argc), j } jsval CEntity::DestroyNotifier( JSContext* cx, uintN argc, jsval* argv ) { - if ( argc < 1 ) - { - JS_ReportError(cx, "too few parameters: CEntity::DestroyNotifier"); - return JS_FALSE; - } + JSU_REQUIRE_PARAMS_CPP(1); DestroyNotifier( ToNative( argv[0] ) ); return JS_TRUE; } @@ -2154,11 +2129,7 @@ jsval CEntity::TriggerRun( JSContext* UNUSED(cx), uintN UNUSED(argc), jsval* UNU jsval CEntity::SetRun( JSContext* cx, uintN argc, jsval* argv ) { - if( argc < 1 ) - { - JS_ReportError( cx, "Too few parameters" ); - return( false ); - } + JSU_REQUIRE_PARAMS_CPP(1); bool should_run = ToPrimitive ( argv[0] ); entf_set_to(ENTF_SHOULD_RUN, should_run); entf_set_to(ENTF_IS_RUNNING, should_run); @@ -2203,11 +2174,7 @@ jsval CEntity::GetFormationBonusVal( JSContext* UNUSED(cx), uintN UNUSED(argc), jsval CEntity::RegisterDamage( JSContext* cx, uintN argc, jsval* argv ) { - if ( argc < 1 ) - { - JS_ReportError( cx, "Too few parameters" ); - return( false ); - } + JSU_REQUIRE_PARAMS_CPP(1); CEntity* inflictor = ToNative( argv[0] ); CVector2D up(1.0f, 0.0f); CVector2D pos = CVector2D( inflictor->m_position.X, inflictor->m_position.Z ); @@ -2221,11 +2188,7 @@ jsval CEntity::RegisterDamage( JSContext* cx, uintN argc, jsval* argv ) } jsval CEntity::RegisterOrderChange( JSContext* cx, uintN argc, jsval* argv ) { - if ( argc < 1 ) - { - JS_ReportError( cx, "Too few parameters" ); - return( false ); - } + JSU_REQUIRE_PARAMS_CPP(1); CEntity* idleEntity = ToNative( argv[0] ); CVector2D up(1.0f, 0.0f); @@ -2251,11 +2214,7 @@ jsval CEntity::GetAttackDirections( JSContext* UNUSED(cx), uintN UNUSED(argc), j } jsval CEntity::FindSector( JSContext* cx, uintN argc, jsval* argv ) { - if ( argc < 4 ) - { - JS_ReportError( cx, "Too few parameters" ); - return( false ); - } + JSU_REQUIRE_PARAMS_CPP(4); int divs = ToPrimitive( argv[0] ); float angle = ToPrimitive( argv[1] ); float maxAngle = ToPrimitive( argv[2] );