1
0
forked from 0ad/0ad

Console: changed things so declaring variables while an entity is selected will no longer define a new property in that entity. Kind of broke the ability to access properties of the selected object without typing selection[0], due to other bugs.

ScriptableComplex: added evil hack so iteration through properties works
with the new SpiderMonkey, which fixes the GUI scripts.

This was SVN commit r5185.
This commit is contained in:
Ykkrosh 2007-06-16 22:07:40 +00:00
parent 63732eda21
commit 73884c1f09
5 changed files with 49 additions and 26 deletions

View File

@ -63,7 +63,7 @@ JSClass GUIClass = {
//------------------------------------------------------------------- //-------------------------------------------------------------------
InReaction gui_handler(const SDL_Event_* ev) InReaction gui_handler(const SDL_Event_* ev)
{ {
PROFILE(" GUI event handler "); PROFILE( "GUI event handler" );
return g_GUI.HandleEvent(ev); return g_GUI.HandleEvent(ev);
} }

View File

@ -280,7 +280,7 @@ private:
* @throws PS_RESULT Depends on what pFunc might throw. PS_RESULT is standard. * @throws PS_RESULT Depends on what pFunc might throw. PS_RESULT is standard.
* Itself doesn't throw anything. * Itself doesn't throw anything.
*/ */
static void RecurseObject(const int RR, IGUIObject *pObject, void_Object_pFunction_argT pFunc, const T &Argument) static void RecurseObject(int RR, IGUIObject *pObject, void_Object_pFunction_argT pFunc, const T &Argument)
{ {
// TODO Gee: Don't run this for the base object. // TODO Gee: Don't run this for the base object.
if (CheckIfRestricted(RR, pObject)) if (CheckIfRestricted(RR, pObject))
@ -301,7 +301,7 @@ private:
* *
* @see RecurseObject() * @see RecurseObject()
*/ */
static void RecurseObject(const int RR, IGUIObject *pObject, void_Object_pFunction_argRefT pFunc, T &Argument) static void RecurseObject(int RR, IGUIObject *pObject, void_Object_pFunction_argRefT pFunc, T &Argument)
{ {
if (CheckIfRestricted(RR, pObject)) if (CheckIfRestricted(RR, pObject))
return; return;
@ -321,7 +321,7 @@ private:
* *
* @see RecurseObject() * @see RecurseObject()
*/ */
static void RecurseObject(const int RR, IGUIObject *pObject, void_Object_pFunction pFunc) static void RecurseObject(int RR, IGUIObject *pObject, void_Object_pFunction pFunc)
{ {
if (CheckIfRestricted(RR, pObject)) if (CheckIfRestricted(RR, pObject))
return; return;
@ -347,7 +347,7 @@ private:
* @param pObject Object * @param pObject Object
* @return true if restricted * @return true if restricted
*/ */
static bool CheckIfRestricted(const int RR, IGUIObject *pObject) static bool CheckIfRestricted(int RR, IGUIObject *pObject)
{ {
if (RR & GUIRR_HIDDEN) if (RR & GUIRR_HIDDEN)
{ {

View File

@ -41,6 +41,8 @@ CConsole::CConsole()
m_iMsgHistPos = 1; m_iMsgHistPos = 1;
m_charsPerPage=0; m_charsPerPage=0;
m_ScriptObject = NULL; // scripting host isn't initialised yet - we'll set this later
InsertMessage(L"[ 0 A.D. Console v0.12 ] type \"\\info\" for help"); InsertMessage(L"[ 0 A.D. Console v0.12 ] type \"\\info\" for help");
InsertMessage(L""); InsertMessage(L"");
@ -72,6 +74,9 @@ CConsole::~CConsole()
m_deqMsgHistory.clear(); m_deqMsgHistory.clear();
m_deqBufHistory.clear(); m_deqBufHistory.clear();
delete[] m_szBuffer; delete[] m_szBuffer;
if (m_ScriptObject)
JS_RemoveRoot(g_ScriptingHost.GetContext(), &m_ScriptObject);
} }
@ -666,29 +671,28 @@ void CConsole::ProcessBuffer(const wchar_t* szLine)
Iter->second(); Iter->second();
} }
} }
else if (szLine[0] == ':') else if (szLine[0] == ':' || szLine[0] == '?')
{ {
// Process it as JavaScript // Process it as JavaScript
// (Cheating) run it as the first selected entity, if there is one. // Run the script inside the first selected entity, if there is one.
JSObject* RunAs = NULL; // (Actually do it by using a separate object with the entity as its parent, so the script
if( g_Selection.m_selected.size() ) // can read the entities variables but will define new variables in a private scope)
RunAs = g_Selection.m_selected[0]->GetScript(); // (NOTE: this doesn't actually work, because the entities don't really have properties
// since they aren't sufficiently like real JS objects, which makes them get ignored in
// this situation. But this code is here so that it will work when the entities get fixed.)
if (! m_ScriptObject)
{
m_ScriptObject = JS_NewObject(g_ScriptingHost.GetContext(), NULL, NULL, NULL);
JS_AddRoot(g_ScriptingHost.GetContext(), &m_ScriptObject); // gets unrooted in ~CConsole
}
if (! g_Selection.m_selected.empty())
{
JS_SetParent(g_ScriptingHost.GetContext(), m_ScriptObject, g_Selection.m_selected[0]->GetScript());
}
g_ScriptingHost.ExecuteScript( CStrW( szLine + 1 ), L"Console", RunAs ); jsval rval = g_ScriptingHost.ExecuteScript( CStrW( szLine + 1 ), L"Console", m_ScriptObject );
if (szLine[0] == '?' && rval)
}
else if (szLine[0] == '?')
{
// Process it as JavaScript and display the result
// (Cheating) run it as the first selected entity, if there is one.
JSObject* RunAs = NULL;
if( g_Selection.m_selected.size() )
RunAs = g_Selection.m_selected[0]->GetScript();
jsval rval = g_ScriptingHost.ExecuteScript( CStrW( szLine + 1 ), L"Console", RunAs );
if (rval)
{ {
try { try {
InsertMessage( L"%ls", g_ScriptingHost.ValueToUCString( rval ).c_str() ); InsertMessage( L"%ls", g_ScriptingHost.ValueToUCString( rval ).c_str() );
@ -696,9 +700,13 @@ void CConsole::ProcessBuffer(const wchar_t* szLine)
InsertMessage( L"%hs", "<error converting return value to string>" ); InsertMessage( L"%hs", "<error converting return value to string>" );
} }
} }
JS_SetParent(g_ScriptingHost.GetContext(), m_ScriptObject, NULL); // so the previous one can get garbage-collected
} }
else else
{
SendChatMessage(szLine); SendChatMessage(szLine);
}
} }
void CConsole::LoadHistory() void CConsole::LoadHistory()

View File

@ -21,6 +21,8 @@
#define CONSOLE_BUFFER_SIZE 1024 // for text being typed into the console #define CONSOLE_BUFFER_SIZE 1024 // for text being typed into the console
#define CONSOLE_MESSAGE_SIZE 1024 // for messages being printed into the console #define CONSOLE_MESSAGE_SIZE 1024 // for messages being printed into the console
struct JSObject;
typedef void(*fptr)(void); typedef void(*fptr)(void);
class CConsole class CConsole
@ -77,6 +79,8 @@ private:
void LoadHistory(); void LoadHistory();
void SaveHistory(); void SaveHistory();
JSObject* m_ScriptObject; // to run scripts in, so they can define variables that are retained between commands
public: public:
CConsole(); CConsole();

View File

@ -160,9 +160,17 @@ public:
} }
// I think this is what I'm supposed to do... (cheers, Philip) // I think this is what I'm supposed to do... (cheers, Philip)
if( !JS_ValueToId( g_ScriptingHost.GetContext(), ToJSVal<CStrW>( *( it->second ) ), idp ) ) if( !JS_ValueToId( cx, ToJSVal<CStrW>( *( it->second ) ), idp ) )
return( JS_FALSE ); return( JS_FALSE );
// EVIL HACK: since https://bugzilla.mozilla.org/show_bug.cgi?id=261887 (which is in
// the SpiderMonkey 1.6 release, and not in 1.5), you can't enumerate properties that
// don't actually exist on the object. This should probably be fixed by defining a custom
// Resolve function to make them look like they exist, but for now we just define the
// property on the object here so that it will exist by the time the JS iteration code
// does its checks.
JS_DefineProperty(cx, obj, CStr(*it->second).c_str(), JSVAL_VOID, NULL, NULL, 0);
(it->second)++; (it->second)++;
*statep = PRIVATE_TO_JSVAL( it ); *statep = PRIVATE_TO_JSVAL( it );
@ -604,9 +612,12 @@ JSBool CJSComplex<T, ReadOnly>::JSEnumerate( JSContext* cx, JSObject* obj, JSIte
} }
// I think this is what I'm supposed to do... (cheers, Philip) // I think this is what I'm supposed to do... (cheers, Philip)
if( !JS_ValueToId( g_ScriptingHost.GetContext(), ToJSVal<CStrW>( *( it->second ) ), idp ) ) if( !JS_ValueToId( cx, ToJSVal<CStrW>( *( it->second ) ), idp ) )
return( JS_FALSE ); return( JS_FALSE );
// EVIL HACK: see the comment in the other JSEnumerate
JS_DefineProperty(cx, obj, CStr(*it->second).c_str(), JSVAL_VOID, NULL, NULL, 0);
(it->second)++; (it->second)++;
*statep = PRIVATE_TO_JSVAL( it ); *statep = PRIVATE_TO_JSVAL( it );