diff --git a/binaries/data/mods/_test.sim/simulation/components/test-entityid.js b/binaries/data/mods/_test.sim/simulation/components/test-entityid.js
index e0541699d9..b6cf0da9e8 100644
--- a/binaries/data/mods/_test.sim/simulation/components/test-entityid.js
+++ b/binaries/data/mods/_test.sim/simulation/components/test-entityid.js
@@ -2,8 +2,14 @@ function TestScript1A() {}
TestScript1A.prototype.GetX = function() {
// Test that .entity is readonly
- delete this.entity;
- this.entity = -1;
+ try {
+ delete this.entity;
+ Engine.TS_FAIL("Missed exception");
+ } catch (e) { }
+ try {
+ this.entity = -1;
+ Engine.TS_FAIL("Missed exception");
+ } catch (e) { }
// and return the value
return this.entity;
diff --git a/binaries/data/mods/_test.sim/simulation/components/test-serialize.js b/binaries/data/mods/_test.sim/simulation/components/test-serialize.js
index be8cba461d..9893d6d794 100644
--- a/binaries/data/mods/_test.sim/simulation/components/test-serialize.js
+++ b/binaries/data/mods/_test.sim/simulation/components/test-serialize.js
@@ -19,8 +19,14 @@ function TestScript1_entity() {}
TestScript1_entity.prototype.GetX = function() {
// Test that .entity is readonly
- delete this.entity;
- this.entity = -1;
+ try {
+ delete this.entity;
+ Engine.TS_FAIL("Missed exception");
+ } catch (e) { }
+ try {
+ this.entity = -1;
+ Engine.TS_FAIL("Missed exception");
+ } catch (e) { }
// and return the value
return this.entity;
diff --git a/binaries/data/tools/atlas/scripts/section/terrain.js b/binaries/data/tools/atlas/scripts/section/terrain.js
index 7b852f0ea0..8978390e7b 100644
--- a/binaries/data/tools/atlas/scripts/section/terrain.js
+++ b/binaries/data/tools/atlas/scripts/section/terrain.js
@@ -76,6 +76,7 @@ function TerrainPreviewPage(panel, name)
this.previewReloadTimer = null;
}
+
TerrainPreviewPage.prototype = {
reloadPreviews: function() {
this.panel.freeze();
@@ -108,7 +109,6 @@ TerrainPreviewPage.prototype = {
imgSizer.add(label, 1, wxAlignment.CENTRE);
this.itemSizer.add(imgSizer, 0, wxAlignment.CENTRE | wxStretch.EXPAND);
}
-
this.itemSizer.layout();
this.panel.layout();
this.panel.thaw();
@@ -143,8 +143,9 @@ TerrainPreviewPage.prototype = {
scrolled.sizer = itemSizer;
// Adjust the number of columns to fit in the available area
+ var w = this.w;
scrolled.onSize = function (evt) {
- var numCols = Math.max(1, Math.floor(evt.size.width / (this.w+16)));
+ var numCols = Math.max(1, Math.floor(evt.size.width / (w+16)));
if (itemSizer.cols != numCols)
itemSizer.cols = numCols;
};
diff --git a/source/graphics/GameView.cpp b/source/graphics/GameView.cpp
index 6c2d36fe01..838bdfec5b 100644
--- a/source/graphics/GameView.cpp
+++ b/source/graphics/GameView.cpp
@@ -676,7 +676,7 @@ void CGameView::Update(float DeltaTime)
cmpPosition->GetInterpolatedPosition2D(frameOffset, x, z, angle);
float height = 4.f;
m->ViewCamera.m_Orientation.SetIdentity();
- m->ViewCamera.m_Orientation.RotateX(M_PI/24.f);
+ m->ViewCamera.m_Orientation.RotateX((float)M_PI/24.f);
m->ViewCamera.m_Orientation.RotateY(angle);
m->ViewCamera.m_Orientation.Translate(pos.X, pos.Y + height, pos.Z);
diff --git a/source/graphics/scripting/JSInterface_Camera.cpp b/source/graphics/scripting/JSInterface_Camera.cpp
deleted file mode 100644
index 6a3c2adc3c..0000000000
--- a/source/graphics/scripting/JSInterface_Camera.cpp
+++ /dev/null
@@ -1,310 +0,0 @@
-/* Copyright (C) 2009 Wildfire Games.
- * This file is part of 0 A.D.
- *
- * 0 A.D. is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 2 of the License, or
- * (at your option) any later version.
- *
- * 0 A.D. is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with 0 A.D. If not, see .
- */
-
-#include "precompiled.h"
-
-#include "JSInterface_Camera.h"
-
-#include "scripting/JSConversions.h"
-#include "maths/scripting/JSInterface_Vector3D.h"
-#include "graphics/Camera.h"
-#include "maths/Vector3D.h"
-#include "maths/Matrix3D.h"
-#include "maths/MathUtil.h"
-#include "graphics/Terrain.h"
-#include "ps/Game.h"
-#include "graphics/GameView.h"
-
-
-JSClass JSI_Camera::JSI_class = {
- "Camera", JSCLASS_HAS_PRIVATE,
- JS_PropertyStub, JS_PropertyStub,
- JSI_Camera::getProperty, JSI_Camera::setProperty,
- JS_EnumerateStub, JS_ResolveStub,
- JS_ConvertStub, JSI_Camera::finalize,
- NULL, NULL, NULL, NULL
-};
-
-JSPropertySpec JSI_Camera::JSI_props[] =
-{
- { "position", JSI_Camera::vector_position, JSPROP_ENUMERATE },
- { "orientation", JSI_Camera::vector_orientation, JSPROP_ENUMERATE },
- { "up", JSI_Camera::vector_up, JSPROP_ENUMERATE },
- { 0 },
-};
-
-JSFunctionSpec JSI_Camera::JSI_methods[] =
-{
- { "lookAt", JSI_Camera::lookAt, 2, 0, 0 },
- { "getFocus", JSI_Camera::getFocus, 0, 0, 0 },
- { 0 }
-};
-
-void JSI_Camera::init()
-{
- g_ScriptingHost.DefineCustomObjectType( &JSI_class, JSI_Camera::construct, 0, JSI_props, JSI_methods, NULL, NULL );
-}
-
-JSI_Camera::Camera_Info::Camera_Info()
-{
- Initialise();
-}
-
-JSI_Camera::Camera_Info::Camera_Info( const CVector3D& Position )
-{
- CMatrix3D Orient;
- Orient.SetXRotation( DEGTORAD( 30 ) );
- Orient.RotateY( DEGTORAD( -45 ) );
- Orient.Translate( Position );
-
- Initialise( (const CMatrix3D&)Orient );
-}
-
-JSI_Camera::Camera_Info::Camera_Info( const CVector3D& Position, const CVector3D& Orientation )
-{
- Initialise();
- m_Data->LookAlong( Position, Orientation, CVector3D( 0.0f, 1.0f, 0.0f ) );
-}
-
-JSI_Camera::Camera_Info::Camera_Info( const CVector3D& Position, const CVector3D& Orientation, const CVector3D& Up )
-{
- Initialise();
- m_Data->LookAlong( Position, Orientation, Up );
-}
-
-JSI_Camera::Camera_Info::Camera_Info( const CMatrix3D& Orientation )
-{
- Initialise( Orientation );
-}
-
-JSI_Camera::Camera_Info::Camera_Info( CCamera* Reference )
-{
- m_Data = Reference;
- m_EngineOwned = true;
-}
-
-JSI_Camera::Camera_Info::~Camera_Info()
-{
- if( !m_EngineOwned )
- delete( m_Data );
-}
-
-void JSI_Camera::Camera_Info::Initialise()
-{
- CMatrix3D Orient;
- Orient.SetXRotation( DEGTORAD( 30 ) );
- Orient.RotateY( DEGTORAD( -45 ) );
- Orient.Translate( 100, 150, -100 );
-
- Initialise( (const CMatrix3D&)Orient );
-}
-
-void JSI_Camera::Camera_Info::Initialise( const CMatrix3D& Orientation )
-{
- m_Data = new CCamera();
- m_EngineOwned = false;
-
- m_Data->LookAlong( Orientation.GetTranslation(), Orientation.GetIn(), Orientation.GetUp() );
-}
-
-void JSI_Camera::Camera_Info::Freshen()
-{
- m_sv_Position = m_Data->m_Orientation.GetTranslation();
- m_sv_Orientation = m_Data->m_Orientation.GetIn();
- m_sv_Up = m_Data->m_Orientation.GetUp();
-}
-
-void JSI_Camera::Camera_Info::Update()
-{
- m_Data->LookAlong( m_sv_Position, m_sv_Orientation, m_sv_Up );
-}
-
-void JSI_Camera::Camera_Info::FreshenTarget()
-{
- m_sv_Target = m_Data->GetFocus();
-}
-
-JSBool JSI_Camera::getCamera( JSContext* cx, JSObject* UNUSED(obj), jsval UNUSED(id), jsval* vp )
-{
- if( g_Game && g_Game->GetView()->GetCamera() )
- {
- JSObject* camera = JS_NewObject( cx, &JSI_Camera::JSI_class, NULL, NULL );
- JS_SetPrivate( cx, camera, new Camera_Info( g_Game->GetView()->GetCamera() ) );
- *vp = OBJECT_TO_JSVAL( camera );
- }
- else
- {
- *vp = JSVAL_NULL;
- }
- return( JS_TRUE );
-}
-
-JSBool JSI_Camera::setCamera( JSContext* cx, JSObject* UNUSED(obj), jsval UNUSED(id), jsval* vp )
-{
- JSObject* camera = JSVAL_TO_OBJECT( *vp );
- Camera_Info* cameraInfo;
- if( !JSVAL_IS_OBJECT( *vp ) || NULL == ( cameraInfo = (Camera_Info*)JS_GetInstancePrivate( cx, camera, &JSI_Camera::JSI_class, NULL ) ) )
- {
- JS_ReportError( cx, "[Camera] Invalid object" );
- }
- else
- {
- g_Game->GetView()->GetCamera()->m_Orientation = cameraInfo->m_Data->m_Orientation;
- }
- return( JS_TRUE );
-}
-
-JSBool JSI_Camera::getProperty( JSContext* cx, JSObject* obj, jsval id, jsval* vp )
-{
- if( !JSVAL_IS_INT( id ) )
- return( JS_TRUE );
-
- Camera_Info* cameraInfo = (Camera_Info*)JS_GetPrivate( cx, obj );
- if( !cameraInfo )
- {
- JS_ReportError( cx, "[Camera] Invalid Reference" );
- return( JS_TRUE );
- }
-
- CVector3D* d;
-
- switch( ToPrimitive( id ) )
- {
- case vector_position: d = &cameraInfo->m_sv_Position; break;
- case vector_orientation: d = &cameraInfo->m_sv_Orientation; break;
- case vector_up: d = &cameraInfo->m_sv_Up; break;
- default: return( JS_TRUE );
- }
-
- JSObject* vector3d = JS_NewObject( g_ScriptingHost.getContext(), &JSI_Vector3D::JSI_class, NULL, NULL );
- JS_SetPrivate( g_ScriptingHost.getContext(), vector3d, new JSI_Vector3D::Vector3D_Info( d, cameraInfo, ( void( IPropertyOwner::* )() )&Camera_Info::Update, ( void( IPropertyOwner::* )() )&Camera_Info::Freshen ) );
- *vp = OBJECT_TO_JSVAL( vector3d );
- return( JS_TRUE );
-}
-
-JSBool JSI_Camera::setProperty( JSContext* cx, JSObject* obj, jsval id, jsval* vp )
-{
- if( !JSVAL_IS_INT( id ) )
- return( JS_TRUE );
-
- Camera_Info* cameraInfo = (Camera_Info*)JS_GetPrivate( cx, obj );
- if( !cameraInfo )
- {
- JS_ReportError( cx, "[Camera] Invalid reference" );
- return( JS_TRUE );
- }
-
- JSObject* vector3d = JSVAL_TO_OBJECT( *vp );
- JSI_Vector3D::Vector3D_Info* v = NULL;
-
- if( JSVAL_IS_OBJECT( *vp ) && NULL != ( v = (JSI_Vector3D::Vector3D_Info*)JS_GetInstancePrivate( g_ScriptingHost.getContext(), vector3d, &JSI_Vector3D::JSI_class, NULL ) ) )
- {
- cameraInfo->Freshen();
-
- switch( ToPrimitive( id ) )
- {
- case vector_position: cameraInfo->m_sv_Position = *( v->vector ); break;
- case vector_orientation: cameraInfo->m_sv_Orientation = *( v->vector ); break;
- case vector_up: cameraInfo->m_sv_Up = *( v->vector ); break;
- }
-
- cameraInfo->Update();
- }
-
- return( JS_TRUE );
-}
-
-#define GETVECTOR( jv ) ( ( JSVAL_IS_OBJECT( jv ) && NULL != ( v = (JSI_Vector3D::Vector3D_Info*)JS_GetInstancePrivate( g_ScriptingHost.getContext(), JSVAL_TO_OBJECT( jv ), &JSI_Vector3D::JSI_class, NULL ) ) ) ? *(v->vector) : CVector3D() )
-
-
-JSBool JSI_Camera::lookAt( JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval )
-{
- JSI_Vector3D::Vector3D_Info* v = NULL;
- Camera_Info* cameraInfo = (Camera_Info*)JS_GetPrivate( cx, obj );
-
- JSU_REQUIRE_PARAM_RANGE(2, 3);
-
- cameraInfo->m_sv_Position = GETVECTOR( argv[0] );
- cameraInfo->m_sv_Orientation = GETVECTOR( argv[1] ) - cameraInfo->m_sv_Position;
- cameraInfo->m_sv_Orientation.Normalize();
-
- if( argc == 2 )
- {
- cameraInfo->m_sv_Up = CVector3D( 0.0f, 1.0f, 0.0f );
- }
- else if( argc == 3 )
- {
- cameraInfo->m_sv_Up = GETVECTOR( argv[2] );
- }
-
- cameraInfo->Update();
-
- *rval = JSVAL_TRUE;
- return( JS_TRUE );
-}
-
-JSBool JSI_Camera::getFocus( JSContext* cx, JSObject* obj,
- uintN UNUSED(argc), jsval* UNUSED(argv), jsval* rval )
-{
- // Largely copied from the equivalent method in CCamera
-
- Camera_Info* cameraInfo = (Camera_Info*)JS_GetPrivate( cx, obj );
-
- JSObject* vector3d = JS_NewObject( g_ScriptingHost.getContext(), &JSI_Vector3D::JSI_class, NULL, NULL );
- JS_SetPrivate( g_ScriptingHost.getContext(), vector3d, new JSI_Vector3D::Vector3D_Info( &( cameraInfo->m_sv_Target ), cameraInfo, NULL, ( void( IPropertyOwner::* )() )&Camera_Info::FreshenTarget ) );
- *rval = OBJECT_TO_JSVAL( vector3d );
- return( JS_TRUE );
-}
-
-JSBool JSI_Camera::construct( JSContext* cx, JSObject* UNUSED(obj),
- uintN argc, jsval* argv, jsval* rval )
-{
- JSI_Vector3D::Vector3D_Info* v = NULL;
-
- JSObject* camera = JS_NewObject( cx, &JSI_Camera::JSI_class, NULL, NULL );
-
- JSU_REQUIRE_MAX_PARAMS(3);
- Camera_Info* camera_info = 0;
- switch(argc)
- {
- 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 );
-}
-
-void JSI_Camera::finalize( JSContext* cx, JSObject* obj )
-{
- delete( (Camera_Info*)JS_GetPrivate( cx, obj ) );
-}
-
diff --git a/source/graphics/scripting/JSInterface_Camera.h b/source/graphics/scripting/JSInterface_Camera.h
deleted file mode 100644
index f7ded003fb..0000000000
--- a/source/graphics/scripting/JSInterface_Camera.h
+++ /dev/null
@@ -1,101 +0,0 @@
-/* Copyright (C) 2009 Wildfire Games.
- * This file is part of 0 A.D.
- *
- * 0 A.D. is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 2 of the License, or
- * (at your option) any later version.
- *
- * 0 A.D. is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with 0 A.D. If not, see .
- */
-
-// JSInterface_Camera.h
-//
-// A JavaScript wrapper around a camera object.
-//
-// Usage: When manipulating objects of type 'Camera' in JavaScript
-
-#include "scripting/ScriptingHost.h"
-
-#include "maths/Vector3D.h"
-#include "graphics/Camera.h"
-#include "graphics/HFTracer.h"
-
-#ifndef INCLUDED_JSI_CAMERA
-#define INCLUDED_JSI_CAMERA
-
-namespace JSI_Camera
-{
- enum
- {
- vector_position,
- vector_orientation,
- vector_up
- };
-
- enum
- {
- lookat
- };
-
- struct Camera_Info : public IPropertyOwner
- {
- CCamera* m_Data;
- bool m_EngineOwned;
- CVector3D m_sv_Position;
- CVector3D m_sv_Orientation;
- CVector3D m_sv_Up;
- CVector3D m_sv_Target;
-
- Camera_Info(); // Create a camera set to the initial view
-
- Camera_Info( const CVector3D& Position );
- Camera_Info( const CVector3D& Position, const CVector3D& Orientation );
- Camera_Info( const CVector3D& Position, const CVector3D& Orientation, const CVector3D& Up );
- Camera_Info( const CMatrix3D& Orientation );
- Camera_Info( CCamera* copy );
-
- void Initialise();
- void Initialise( const CMatrix3D& Orientation );
-
- void Freshen();
- void Update();
- void FreshenTarget();
-
- ~Camera_Info();
-/*
-
- Camera_Info( const CVector3D& _position );
- Camera_Info( const CVector3D& _position, const CVector3D& _orientation );
- Camera_Info( const CVector3D& _position, const CVector3D& _orientation, const CVector3D& _up );
- Camera_Info( CCamera* _copy );
- void update();
-
-*/
- };
- extern JSClass JSI_class;
- extern JSPropertySpec JSI_props[];
- extern JSFunctionSpec JSI_methods[];
-
- JSBool getProperty( JSContext* cx, JSObject* obj, jsval id, jsval* vp );
- JSBool setProperty( JSContext* cx, JSObject* obj, jsval id, jsval* vp );
-
- JSBool getCamera( JSContext* cx, JSObject* obj, jsval id, jsval* vp );
- JSBool setCamera( JSContext* cx, JSObject* obj, jsval id, jsval* vp );
-
- JSBool construct( JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval );
- void finalize( JSContext* cx, JSObject* obj );
-
- JSBool lookAt( JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval );
- JSBool getFocus( JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval );
-
- void init();
-}
-
-#endif
diff --git a/source/graphics/scripting/JSInterface_LightEnv.cpp b/source/graphics/scripting/JSInterface_LightEnv.cpp
deleted file mode 100644
index ac17ec8132..0000000000
--- a/source/graphics/scripting/JSInterface_LightEnv.cpp
+++ /dev/null
@@ -1,250 +0,0 @@
-/* Copyright (C) 2009 Wildfire Games.
- * This file is part of 0 A.D.
- *
- * 0 A.D. is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 2 of the License, or
- * (at your option) any later version.
- *
- * 0 A.D. is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with 0 A.D. If not, see .
- */
-
-/*
- * Provide the LightEnv object type for JavaScript
- */
-
-#include "precompiled.h"
-
-#include "maths/scripting/JSInterface_Vector3D.h"
-
-#include "graphics/scripting/JSInterface_LightEnv.h"
-#include "graphics/LightEnv.h"
-
-#include "ps/World.h"
-
-#include "scripting/JSConversions.h"
-
-
-namespace JSI_LightEnv {
-
-namespace {
-
-extern JSClass JSI_class;
-
-/**
- * This enumeration is used to index properties with the JavaScript implementation.
- */
-enum
-{
- lightenv_elevation,
- lightenv_rotation,
- lightenv_terrainShadowTransparency,
- lightenv_sun,
- lightenv_terrainAmbient,
- lightenv_unitsAmbient
-};
-
-///////////////////////////////////////////////////////////////////////////////////////////////
-// LightEnv_Info, the private structure that holds data for individual LightEnv objects
-
-struct LightEnv_Info : public IPropertyOwner
-{
- CLightEnv* m_Data;
- bool m_EngineOwned;
-
- // Create a new LightEnv that will only be used by JavaScript
- LightEnv_Info()
- {
- m_Data = new CLightEnv;
- m_EngineOwned = false;
- }
-
- // Use the given CLightEnv from the engine. The caller must guarantee that
- // the copy object will not be deleted.
- LightEnv_Info(CLightEnv* copy)
- {
- m_Data = copy;
- m_EngineOwned = true;
- }
-
- ~LightEnv_Info()
- {
- if (!m_EngineOwned)
- delete m_Data;
- }
-};
-
-
-///////////////////////////////////////////////////////////////////////////////////////////////
-// Construction and finalization of LightEnvs
-
-/**
- * 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* argv, jsval* rval)
-{
- JSObject* lightenv = JS_NewObject(cx, &JSI_class, NULL, NULL);
-
- JSU_REQUIRE_NO_PARAMS();
-
- JS_SetPrivate(cx, lightenv, new LightEnv_Info);
- *rval = OBJECT_TO_JSVAL(lightenv);
- return JS_TRUE;
-}
-
-/**
- * finalize: callback from the JS engine to indicate we should free our private data
- */
-void finalize(JSContext* cx, JSObject* obj)
-{
- delete (LightEnv_Info*)JS_GetPrivate(cx, obj);
-}
-
-
-///////////////////////////////////////////////////////////////////////////////////////////////
-// Accessing properties of a LightEnv object
-
-// Can't use ToJSVal here because we need live updates from the vectors
-JSBool getVectorProperty(JSContext* cx, LightEnv_Info* lightenvInfo, CVector3D* vec, jsval* vp)
-{
- JSObject* vector3d = JS_NewObject(cx, &JSI_Vector3D::JSI_class, NULL, NULL);
- JS_SetPrivate(cx, vector3d, new JSI_Vector3D::Vector3D_Info(vec, lightenvInfo));
- *vp = OBJECT_TO_JSVAL(vector3d);
- return JS_TRUE;
-}
-
-
-JSBool getProperty(JSContext* cx, JSObject* obj, jsval id, jsval* vp)
-{
- if (!JSVAL_IS_INT(id))
- return JS_TRUE ;
-
- LightEnv_Info* lightenvInfo = (LightEnv_Info*)JS_GetPrivate(cx, obj);
- if (!lightenvInfo)
- {
- JS_ReportError(cx, "[LightEnv] Invalid Reference");
- return JS_TRUE;
- }
-
- CLightEnv* lightenv = lightenvInfo->m_Data;
-
- switch(ToPrimitive(id)) {
- case lightenv_elevation: *vp = ToJSVal(lightenv->GetElevation()); break;
- case lightenv_rotation: *vp = ToJSVal(lightenv->GetRotation()); break;
- case lightenv_terrainShadowTransparency: *vp = ToJSVal(lightenv->GetTerrainShadowTransparency()); break;
- case lightenv_sun: return getVectorProperty(cx, lightenvInfo, &lightenv->m_SunColor, vp);
- case lightenv_terrainAmbient: return getVectorProperty(cx, lightenvInfo, &lightenv->m_TerrainAmbientColor, vp);
- case lightenv_unitsAmbient: return getVectorProperty(cx, lightenvInfo, &lightenv->m_UnitsAmbientColor, vp);
- default: break;
- }
-
- return JS_TRUE;
-}
-
-
-JSBool setProperty(JSContext* cx, JSObject* obj, jsval id, jsval* vp)
-{
- if (!JSVAL_IS_INT(id))
- return( JS_TRUE );
-
- LightEnv_Info* lightenvInfo = (LightEnv_Info*)JS_GetPrivate(cx, obj);
- if (!lightenvInfo)
- {
- JS_ReportError(cx, "[LightEnv] Invalid reference");
- return JS_TRUE;
- }
-
- CLightEnv* lightenv = lightenvInfo->m_Data;
-
- switch(ToPrimitive(id)) {
- case lightenv_elevation: lightenv->SetElevation(ToPrimitive(*vp)); break;
- case lightenv_rotation: lightenv->SetRotation(ToPrimitive(*vp)); break;
- case lightenv_terrainShadowTransparency: lightenv->SetTerrainShadowTransparency(ToPrimitive(*vp)); break;
- case lightenv_sun: lightenv->m_SunColor = ToPrimitive(*vp); break;
- case lightenv_terrainAmbient: lightenv->m_TerrainAmbientColor = ToPrimitive(*vp); break;
- case lightenv_unitsAmbient: lightenv->m_UnitsAmbientColor = ToPrimitive(*vp); break;
- default: break;
- }
-
- return JS_TRUE;
-}
-
-
-
-///////////////////////////////////////////////////////////////////////////////////////////////
-// Registration of LightEnv class with JavaScript
-
-JSClass JSI_class = {
- "LightEnv", JSCLASS_HAS_PRIVATE,
- JS_PropertyStub, JS_PropertyStub,
- getProperty, setProperty,
- JS_EnumerateStub, JS_ResolveStub,
- JS_ConvertStub, finalize,
- NULL, NULL, NULL, NULL
-};
-
-JSPropertySpec JSI_props[] =
-{
- { "elevation", lightenv_elevation, JSPROP_ENUMERATE },
- { "rotation", lightenv_rotation, JSPROP_ENUMERATE },
- { "terrainShadowTransparency", lightenv_terrainShadowTransparency, JSPROP_ENUMERATE },
- { "sun", lightenv_sun, JSPROP_ENUMERATE },
- { "terrainAmbient", lightenv_terrainAmbient, JSPROP_ENUMERATE },
- { "unitsAmbient", lightenv_unitsAmbient, JSPROP_ENUMERATE },
- { 0 },
-};
-
-JSFunctionSpec JSI_methods[] =
-{
- { 0 }
-};
-
-} // anonymous namespace
-
-/**
- * init: called by GameSetup to register the LightEnv class with the JS engine.
- */
-void init()
-{
- g_ScriptingHost.DefineCustomObjectType( &JSI_class, construct, 0, JSI_props, JSI_methods, NULL, NULL );
-}
-
-
-///////////////////////////////////////////////////////////////////////////////////////////////
-// Accessing the global lightenv
-
-JSBool getLightEnv(JSContext* cx, JSObject* UNUSED(obj), jsval UNUSED(id), jsval* vp)
-{
- JSObject* lightenv = JS_NewObject(cx, &JSI_class, NULL, NULL);
- JS_SetPrivate(cx, lightenv, new LightEnv_Info(&g_LightEnv));
- *vp = OBJECT_TO_JSVAL(lightenv);
- return JS_TRUE;
-}
-
-JSBool setLightEnv(JSContext* cx, JSObject* UNUSED(obj), jsval UNUSED(id), jsval* vp)
-{
- JSObject* lightenv = JSVAL_TO_OBJECT(*vp);
- LightEnv_Info* lightenvInfo;
-
- if (!JSVAL_IS_OBJECT(*vp) || NULL == (lightenvInfo = (LightEnv_Info*)JS_GetInstancePrivate(cx, lightenv, &JSI_class, NULL)))
- {
- JS_ReportError( cx, "[LightEnv] Invalid object" );
- }
- else
- {
- g_LightEnv = *lightenvInfo->m_Data;
- }
-
- return JS_TRUE;
-}
-
-} // namespace JSI_LightEnv
-
-
diff --git a/source/graphics/scripting/JSInterface_LightEnv.h b/source/graphics/scripting/JSInterface_LightEnv.h
deleted file mode 100644
index c2da76c229..0000000000
--- a/source/graphics/scripting/JSInterface_LightEnv.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/* Copyright (C) 2009 Wildfire Games.
- * This file is part of 0 A.D.
- *
- * 0 A.D. is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 2 of the License, or
- * (at your option) any later version.
- *
- * 0 A.D. is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with 0 A.D. If not, see .
- */
-
-/*
- * Provide the LightEnv object type for JavaScript
- */
-
-#ifndef INCLUDED_JSI_LIGHTENV
-#define INCLUDED_JSI_LIGHTENV
-
-#include "scripting/ScriptingHost.h"
-
-namespace JSI_LightEnv
-{
- void init();
- JSBool getLightEnv( JSContext* cx, JSObject* obj, jsval id, jsval* vp );
- JSBool setLightEnv( JSContext* cx, JSObject* obj, jsval id, jsval* vp );
-}
-
-#endif
diff --git a/source/gui/CGUI.cpp b/source/gui/CGUI.cpp
index cd67124206..b51947b4ed 100644
--- a/source/gui/CGUI.cpp
+++ b/source/gui/CGUI.cpp
@@ -1,4 +1,4 @@
-/* Copyright (C) 2009 Wildfire Games.
+/* Copyright (C) 2010 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@@ -57,6 +57,7 @@ CGUI
#include "ps/Profile.h"
#include "scripting/ScriptingHost.h"
+#include "scriptinterface/ScriptInterface.h"
#include "ps/Hotkey.h"
#include "ps/Globals.h"
#include "ps/Filesystem.h"
@@ -347,10 +348,15 @@ CGUI::CGUI() : m_MouseButtons(0), m_FocusedObject(NULL), m_InternalNameNumber(0)
m_BaseObject = new CGUIDummyObject;
m_BaseObject->SetGUI(this);
- // Construct the parent object for all GUI JavaScript things
- m_ScriptObject = JS_NewObject(g_ScriptingHost.getContext(), NULL, g_ScriptingHost.GetGlobalObject(), NULL);
- debug_assert(m_ScriptObject != NULL); // How should it handle errors?
- JS_AddRoot(g_ScriptingHost.getContext(), &m_ScriptObject);
+ // Construct the root object for all GUI JavaScript things.
+ // (We need an object with no parent, so functions defined by scripts get
+ // put onto this object and not its parent. In the current version of SpiderMonkey
+ // that means it must be a global object. Then we adjust its prototype so it
+ // can still read standard properties from the context's standard global object.)
+ m_ScriptObject = JS_NewGlobalObject(g_ScriptingHost.getContext(), g_ScriptingHost.GetScriptInterface().GetGlobalClass());
+ JS_AddObjectRoot(g_ScriptingHost.getContext(), &m_ScriptObject);
+
+ JS_SetPrototype(g_ScriptingHost.getContext(), m_ScriptObject, g_ScriptingHost.GetGlobalObject());
}
CGUI::~CGUI()
@@ -363,7 +369,7 @@ CGUI::~CGUI()
if (m_ScriptObject)
{
// Let it be garbage-collected
- JS_RemoveRoot(g_ScriptingHost.getContext(), &m_ScriptObject);
+ JS_RemoveObjectRoot(g_ScriptingHost.getContext(), &m_ScriptObject);
}
}
diff --git a/source/gui/GUIManager.cpp b/source/gui/GUIManager.cpp
index 5c0423817b..5db258443a 100644
--- a/source/gui/GUIManager.cpp
+++ b/source/gui/GUIManager.cpp
@@ -48,22 +48,6 @@ InReaction gui_handler(const SDL_Event_* ev)
return g_GUI->HandleEvent(ev);
}
-CGUIManager::SGUIPage::SGUIPage()
-{
- JS_AddNamedRoot(g_ScriptingHost.GetContext(), &initData, "SGUIPage initData");
-}
-
-CGUIManager::SGUIPage::SGUIPage(const SGUIPage& page)
-{
- *this = page;
- JS_AddNamedRoot(g_ScriptingHost.GetContext(), &initData, "SGUIPage initData copy");
-}
-
-CGUIManager::SGUIPage::~SGUIPage()
-{
- JS_RemoveRoot(g_ScriptingHost.GetContext(), &initData);
-}
-
CGUIManager::CGUIManager(ScriptInterface& scriptInterface) :
m_ScriptInterface(scriptInterface)
{
@@ -90,7 +74,7 @@ void CGUIManager::PushPage(const CStrW& pageName, CScriptVal initData)
{
m_PageStack.push_back(SGUIPage());
m_PageStack.back().name = pageName;
- m_PageStack.back().initData = initData;
+ m_PageStack.back().initData = CScriptValRooted(m_ScriptInterface.GetContext(), initData);
LoadPage(m_PageStack.back());
}
diff --git a/source/gui/GUIManager.h b/source/gui/GUIManager.h
index d6b456e2f6..4957e621e4 100644
--- a/source/gui/GUIManager.h
+++ b/source/gui/GUIManager.h
@@ -135,15 +135,11 @@ public:
private:
struct SGUIPage
{
- SGUIPage();
- SGUIPage(const SGUIPage&);
- ~SGUIPage();
-
CStrW name;
std::set inputs; // for hotloading
JSContext* cx;
- CScriptVal initData; // data to be passed to the init() function
+ CScriptValRooted initData; // data to be passed to the init() function
shared_ptr gui; // the actual GUI page
};
diff --git a/source/gui/IGUIObject.cpp b/source/gui/IGUIObject.cpp
index 5ef7752533..cabf002e91 100644
--- a/source/gui/IGUIObject.cpp
+++ b/source/gui/IGUIObject.cpp
@@ -90,13 +90,13 @@ IGUIObject::~IGUIObject()
std::map::iterator it;
for (it = m_ScriptHandlers.begin(); it != m_ScriptHandlers.end(); ++it)
{
- JS_RemoveRoot(g_ScriptingHost.getContext(), it->second);
+ JS_RemoveObjectRoot(g_ScriptingHost.getContext(), it->second);
delete it->second;
}
}
if (m_JSObject)
- JS_RemoveRoot(g_ScriptingHost.getContext(), &m_JSObject);
+ JS_RemoveObjectRoot(g_ScriptingHost.getContext(), &m_JSObject);
}
//-------------------------------------------------------------------
@@ -488,11 +488,11 @@ void IGUIObject::SetScriptHandler(const CStr& Action, JSObject* Function)
{
JSObject** obj = new JSObject*;
*obj = Function;
- JS_AddRoot(g_ScriptingHost.getContext(), obj);
+ JS_AddObjectRoot(g_ScriptingHost.getContext(), obj);
if (m_ScriptHandlers[Action])
{
- JS_RemoveRoot(g_ScriptingHost.getContext(), m_ScriptHandlers[Action]);
+ JS_RemoveObjectRoot(g_ScriptingHost.getContext(), m_ScriptHandlers[Action]);
delete m_ScriptHandlers[Action];
}
m_ScriptHandlers[Action] = obj;
@@ -504,10 +504,6 @@ void IGUIObject::ScriptEvent(const CStr& Action)
if (it == m_ScriptHandlers.end())
return;
- // PRIVATE_TO_JSVAL assumes two-byte alignment,
- // so make sure that's always true
- debug_assert(! ((jsval)this & JSVAL_INT));
-
// The IGUIObject needs to be stored inside the script's object
jsval guiObject = PRIVATE_TO_JSVAL(this);
@@ -517,9 +513,6 @@ void IGUIObject::ScriptEvent(const CStr& Action)
// TODO: why don't we use GetJSObject here?
- // Prevent it from being garbage-collected before it's passed into the function
- JS_AddRoot(g_ScriptingHost.getContext(), &jsGuiObject);
-
// Set up the 'mouse' parameter
jsval mouseParams[3];
mouseParams[0] = INT_TO_JSVAL(m_pGUI->m_MousePos.x);
@@ -528,9 +521,6 @@ void IGUIObject::ScriptEvent(const CStr& Action)
JSObject* mouseObj = JS_ConstructObjectWithArguments(g_ScriptingHost.getContext(), &JSI_GUIMouse::JSI_class, m_pGUI->m_ScriptObject, NULL, 3, mouseParams);
debug_assert(mouseObj); // TODO: Handle errors
- // Don't garbage collect the mouse
- JS_AddRoot(g_ScriptingHost.getContext(), &mouseObj);
-
jsval paramData[] = { OBJECT_TO_JSVAL(mouseObj) };
jsval result;
@@ -539,10 +529,6 @@ void IGUIObject::ScriptEvent(const CStr& Action)
{
JS_ReportError(g_ScriptingHost.getContext(), "Errors executing script action \"%s\"", Action.c_str());
}
-
- // Allow the temporary parameters to be garbage-collected
- JS_RemoveRoot(g_ScriptingHost.getContext(), &mouseObj);
- JS_RemoveRoot(g_ScriptingHost.getContext(), &jsGuiObject);
}
void IGUIObject::ScriptEvent(const CStr& Action, const CScriptValRooted& Argument)
@@ -571,7 +557,7 @@ JSObject* IGUIObject::GetJSObject()
if (! m_JSObject)
{
m_JSObject = JS_NewObject(g_ScriptingHost.getContext(), &JSI_IGUIObject::JSI_class, NULL, NULL);
- JS_AddRoot(g_ScriptingHost.getContext(), &m_JSObject);
+ JS_AddObjectRoot(g_ScriptingHost.getContext(), &m_JSObject);
JS_SetPrivate(g_ScriptingHost.getContext(), m_JSObject, this);
}
return m_JSObject;
diff --git a/source/gui/IGUIObject.h b/source/gui/IGUIObject.h
index 2e6e8292f2..24ce4afabf 100644
--- a/source/gui/IGUIObject.h
+++ b/source/gui/IGUIObject.h
@@ -145,8 +145,8 @@ class IGUIObject
friend class GUITooltip;
// Allow getProperty to access things like GetParent()
- friend JSBool JSI_IGUIObject::getProperty(JSContext* cx, JSObject* obj, jsval id, jsval* vp);
- friend JSBool JSI_IGUIObject::setProperty(JSContext* cx, JSObject* obj, jsval id, jsval* vp);
+ friend JSBool JSI_IGUIObject::getProperty(JSContext* cx, JSObject* obj, jsid id, jsval* vp);
+ friend JSBool JSI_IGUIObject::setProperty(JSContext* cx, JSObject* obj, jsid id, jsval* vp);
public:
IGUIObject();
diff --git a/source/gui/scripting/GuiScriptConversions.cpp b/source/gui/scripting/GuiScriptConversions.cpp
index be30568833..c77e39749a 100644
--- a/source/gui/scripting/GuiScriptConversions.cpp
+++ b/source/gui/scripting/GuiScriptConversions.cpp
@@ -46,10 +46,6 @@ template<> jsval ScriptInterface::ToJSVal(JSContext* cx, SDL_Event_
default: typeName = "(unknown)"; break;
}
- ScriptInterface::LocalRootScope scope(cx);
- if (! scope.OK())
- return JSVAL_VOID;
-
JSObject* obj = JS_NewObject(cx, NULL, NULL, NULL);
if (! obj)
return JSVAL_VOID;
@@ -123,7 +119,6 @@ template<> jsval ScriptInterface::ToJSVal(JSContext* cx, SDL_Event_
jsval rval = OBJECT_TO_JSVAL(obj);
- scope.LeaveWithResult(rval);
return rval;
}
diff --git a/source/gui/scripting/JSInterface_GUITypes.cpp b/source/gui/scripting/JSInterface_GUITypes.cpp
index 0d09e6937a..b197ace95c 100644
--- a/source/gui/scripting/JSInterface_GUITypes.cpp
+++ b/source/gui/scripting/JSInterface_GUITypes.cpp
@@ -45,30 +45,32 @@ JSPropertySpec JSI_GUISize::JSI_props[] =
JSFunctionSpec JSI_GUISize::JSI_methods[] =
{
- { "toString", JSI_GUISize::toString, 0, 0, 0 },
+ { "toString", JSI_GUISize::toString, 0, 0 },
{ 0 }
};
-JSBool JSI_GUISize::construct(JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* UNUSED(rval))
+JSBool JSI_GUISize::construct(JSContext* cx, uintN argc, jsval* vp)
{
+ JSObject* obj = JS_NewObject(cx, &JSI_GUISize::JSI_class, NULL, NULL);
+
if (argc == 8)
{
- JS_SetProperty(cx, obj, "left", &argv[0]);
- JS_SetProperty(cx, obj, "top", &argv[1]);
- JS_SetProperty(cx, obj, "right", &argv[2]);
- JS_SetProperty(cx, obj, "bottom", &argv[3]);
- JS_SetProperty(cx, obj, "rleft", &argv[4]);
- JS_SetProperty(cx, obj, "rtop", &argv[5]);
- JS_SetProperty(cx, obj, "rright", &argv[6]);
- JS_SetProperty(cx, obj, "rbottom", &argv[7]);
+ JS_SetProperty(cx, obj, "left", &JS_ARGV(cx, vp)[0]);
+ JS_SetProperty(cx, obj, "top", &JS_ARGV(cx, vp)[1]);
+ JS_SetProperty(cx, obj, "right", &JS_ARGV(cx, vp)[2]);
+ JS_SetProperty(cx, obj, "bottom", &JS_ARGV(cx, vp)[3]);
+ JS_SetProperty(cx, obj, "rleft", &JS_ARGV(cx, vp)[4]);
+ JS_SetProperty(cx, obj, "rtop", &JS_ARGV(cx, vp)[5]);
+ JS_SetProperty(cx, obj, "rright", &JS_ARGV(cx, vp)[6]);
+ JS_SetProperty(cx, obj, "rbottom", &JS_ARGV(cx, vp)[7]);
}
else if (argc == 4)
{
jsval zero = JSVAL_ZERO;
- JS_SetProperty(cx, obj, "left", &argv[0]);
- JS_SetProperty(cx, obj, "top", &argv[1]);
- JS_SetProperty(cx, obj, "right", &argv[2]);
- JS_SetProperty(cx, obj, "bottom", &argv[3]);
+ JS_SetProperty(cx, obj, "left", &JS_ARGV(cx, vp)[0]);
+ JS_SetProperty(cx, obj, "top", &JS_ARGV(cx, vp)[1]);
+ JS_SetProperty(cx, obj, "right", &JS_ARGV(cx, vp)[2]);
+ JS_SetProperty(cx, obj, "bottom", &JS_ARGV(cx, vp)[3]);
JS_SetProperty(cx, obj, "rleft", &zero);
JS_SetProperty(cx, obj, "rtop", &zero);
JS_SetProperty(cx, obj, "rright", &zero);
@@ -87,6 +89,7 @@ JSBool JSI_GUISize::construct(JSContext* cx, JSObject* obj, uintN argc, jsval* a
JS_SetProperty(cx, obj, "rbottom", &zero);
}
+ JS_SET_RVAL(cx, vp, OBJECT_TO_JSVAL(obj));
return JS_TRUE;
}
@@ -99,13 +102,15 @@ CStr ToPercentString(double pix, double per)
return CStr(per)+CStr("%")+( pix == 0.0 ? CStr() : pix > 0.0 ? CStr("+")+CStr(pix) : CStr(pix) );
}
-JSBool JSI_GUISize::toString(JSContext* cx, JSObject* obj, uintN UNUSED(argc), jsval* UNUSED(argv), jsval* rval)
+JSBool JSI_GUISize::toString(JSContext* cx, uintN argc, jsval* vp)
{
+ UNUSED2(argc);
+
CStr buffer;
try
{
-#define SIDE(side) buffer += ToPercentString(g_ScriptingHost.GetObjectProperty_Double(obj, #side), g_ScriptingHost.GetObjectProperty_Double(obj, "r"#side));
+#define SIDE(side) buffer += ToPercentString(g_ScriptingHost.GetObjectProperty_Double(JS_THIS_OBJECT(cx, vp), #side), g_ScriptingHost.GetObjectProperty_Double(JS_THIS_OBJECT(cx, vp), "r"#side));
SIDE(left);
buffer += " ";
SIDE(top);
@@ -117,11 +122,11 @@ JSBool JSI_GUISize::toString(JSContext* cx, JSObject* obj, uintN UNUSED(argc), j
}
catch (PSERROR_Scripting_ConversionFailed)
{
- *rval = STRING_TO_JSVAL(JS_NewStringCopyZ(cx, ""));
+ JS_SET_RVAL(cx, vp, STRING_TO_JSVAL(JS_NewStringCopyZ(cx, "")));
return JS_TRUE;
}
- *rval = STRING_TO_JSVAL(JS_NewStringCopyZ(cx, buffer.c_str()));
+ JS_SET_RVAL(cx, vp, STRING_TO_JSVAL(JS_NewStringCopyZ(cx, buffer.c_str())));
return JS_TRUE;
}
@@ -149,45 +154,57 @@ JSPropertySpec JSI_GUIColor::JSI_props[] =
JSFunctionSpec JSI_GUIColor::JSI_methods[] =
{
- { "toString", JSI_GUIColor::toString, 0, 0, 0 },
+ { "toString", JSI_GUIColor::toString, 0, 0 },
{ 0 }
};
-JSBool JSI_GUIColor::construct(JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* UNUSED(rval))
+JSBool JSI_GUIColor::construct(JSContext* cx, uintN argc, jsval* vp)
{
+ JSObject* obj = JS_NewObject(cx, &JSI_GUIColor::JSI_class, NULL, NULL);
+
if (argc == 4)
{
- JS_SetProperty(cx, obj, "r", &argv[0]);
- JS_SetProperty(cx, obj, "g", &argv[1]);
- JS_SetProperty(cx, obj, "b", &argv[2]);
- JS_SetProperty(cx, obj, "a", &argv[3]);
+ JS_SetProperty(cx, obj, "r", &JS_ARGV(cx, vp)[0]);
+ JS_SetProperty(cx, obj, "g", &JS_ARGV(cx, vp)[1]);
+ JS_SetProperty(cx, obj, "b", &JS_ARGV(cx, vp)[2]);
+ JS_SetProperty(cx, obj, "a", &JS_ARGV(cx, vp)[3]);
}
else
{
// Nice magenta:
- jsval r = DOUBLE_TO_JSVAL(JS_NewDouble(cx, 1.0));
- JS_SetProperty(cx, obj, "r", &r);
- jsval g = DOUBLE_TO_JSVAL(JS_NewDouble(cx, 0.0));
- JS_SetProperty(cx, obj, "g", &g);
- jsval b = DOUBLE_TO_JSVAL(JS_NewDouble(cx, 1.0));
- JS_SetProperty(cx, obj, "b", &b);
- jsval a = DOUBLE_TO_JSVAL(JS_NewDouble(cx, 1.0));
- JS_SetProperty(cx, obj, "a", &a);
+ jsval c;
+ if (!JS_NewNumberValue(cx, 1.0, &c))
+ return JS_FALSE;
+ JS_SetProperty(cx, obj, "r", &c);
+ JS_SetProperty(cx, obj, "b", &c);
+ JS_SetProperty(cx, obj, "a", &c);
+ if (!JS_NewNumberValue(cx, 0.0, &c))
+ return JS_FALSE;
+ JS_SetProperty(cx, obj, "g", &c);
}
+
+ JS_SET_RVAL(cx, vp, OBJECT_TO_JSVAL(obj));
return JS_TRUE;
}
-JSBool JSI_GUIColor::toString(JSContext* cx, JSObject* obj,
- uintN UNUSED(argc), jsval* UNUSED(argv), jsval* rval)
+JSBool JSI_GUIColor::toString(JSContext* cx, uintN argc, jsval* vp)
{
+ UNUSED2(argc);
+
+ jsdouble r, g, b, a;
+ if (!JS_ValueToNumber(cx, g_ScriptingHost.GetObjectProperty(JS_THIS_OBJECT(cx, vp), "r"), &r)) return JS_FALSE;
+ if (!JS_ValueToNumber(cx, g_ScriptingHost.GetObjectProperty(JS_THIS_OBJECT(cx, vp), "g"), &g)) return JS_FALSE;
+ if (!JS_ValueToNumber(cx, g_ScriptingHost.GetObjectProperty(JS_THIS_OBJECT(cx, vp), "b"), &b)) return JS_FALSE;
+ if (!JS_ValueToNumber(cx, g_ScriptingHost.GetObjectProperty(JS_THIS_OBJECT(cx, vp), "a"), &a)) return JS_FALSE;
+
char buffer[256];
// Convert to integers, to be compatible with the GUI's string SetSetting
snprintf(buffer, 256, "%d %d %d %d",
- (int)( 255.0 * *JSVAL_TO_DOUBLE(g_ScriptingHost.GetObjectProperty(obj, "r")) ),
- (int)( 255.0 * *JSVAL_TO_DOUBLE(g_ScriptingHost.GetObjectProperty(obj, "g")) ),
- (int)( 255.0 * *JSVAL_TO_DOUBLE(g_ScriptingHost.GetObjectProperty(obj, "b")) ),
- (int)( 255.0 * *JSVAL_TO_DOUBLE(g_ScriptingHost.GetObjectProperty(obj, "a")) ));
- *rval = STRING_TO_JSVAL(JS_NewStringCopyZ(cx, buffer));
+ (int)(255.0 * r),
+ (int)(255.0 * g),
+ (int)(255.0 * b),
+ (int)(255.0 * a));
+ JS_SET_RVAL(cx, vp, STRING_TO_JSVAL(JS_NewStringCopyZ(cx, buffer)));
return JS_TRUE;
}
@@ -213,17 +230,19 @@ JSPropertySpec JSI_GUIMouse::JSI_props[] =
JSFunctionSpec JSI_GUIMouse::JSI_methods[] =
{
- { "toString", JSI_GUIMouse::toString, 0, 0, 0 },
+ { "toString", JSI_GUIMouse::toString, 0, 0 },
{ 0 }
};
-JSBool JSI_GUIMouse::construct(JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* UNUSED(rval))
+JSBool JSI_GUIMouse::construct(JSContext* cx, uintN argc, jsval* vp)
{
+ JSObject* obj = JS_NewObject(cx, &JSI_GUIMouse::JSI_class, NULL, NULL);
+
if (argc == 3)
{
- JS_SetProperty(cx, obj, "x", &argv[0]);
- JS_SetProperty(cx, obj, "y", &argv[1]);
- JS_SetProperty(cx, obj, "buttons", &argv[2]);
+ JS_SetProperty(cx, obj, "x", &JS_ARGV(cx, vp)[0]);
+ JS_SetProperty(cx, obj, "y", &JS_ARGV(cx, vp)[1]);
+ JS_SetProperty(cx, obj, "buttons", &JS_ARGV(cx, vp)[2]);
}
else
{
@@ -232,17 +251,23 @@ JSBool JSI_GUIMouse::construct(JSContext* cx, JSObject* obj, uintN argc, jsval*
JS_SetProperty(cx, obj, "y", &zero);
JS_SetProperty(cx, obj, "buttons", &zero);
}
+
+ JS_SET_RVAL(cx, vp, OBJECT_TO_JSVAL(obj));
return JS_TRUE;
}
-JSBool JSI_GUIMouse::toString(JSContext* cx, JSObject* obj, uintN UNUSED(argc), jsval* UNUSED(argv), jsval* rval)
+JSBool JSI_GUIMouse::toString(JSContext* cx, uintN argc, jsval* vp)
{
+ UNUSED2(argc);
+
+ int32 x, y, buttons;
+ if (!JS_ValueToECMAInt32(cx, g_ScriptingHost.GetObjectProperty(JS_THIS_OBJECT(cx, vp), "x"), &x)) return JS_FALSE;
+ if (!JS_ValueToECMAInt32(cx, g_ScriptingHost.GetObjectProperty(JS_THIS_OBJECT(cx, vp), "y"), &y)) return JS_FALSE;
+ if (!JS_ValueToECMAInt32(cx, g_ScriptingHost.GetObjectProperty(JS_THIS_OBJECT(cx, vp), "buttons"), &buttons)) return JS_FALSE;
+
char buffer[256];
- snprintf(buffer, 256, "%d %d %d",
- JSVAL_TO_INT(g_ScriptingHost.GetObjectProperty(obj, "x")),
- JSVAL_TO_INT(g_ScriptingHost.GetObjectProperty(obj, "y")),
- JSVAL_TO_INT(g_ScriptingHost.GetObjectProperty(obj, "buttons")) );
- *rval = STRING_TO_JSVAL(JS_NewStringCopyZ(cx, buffer));
+ snprintf(buffer, 256, "%d %d %d", x, y, buttons);
+ JS_SET_RVAL(cx, vp, STRING_TO_JSVAL(JS_NewStringCopyZ(cx, buffer)));
return JS_TRUE;
}
diff --git a/source/gui/scripting/JSInterface_GUITypes.h b/source/gui/scripting/JSInterface_GUITypes.h
index 7dbbe4e0f1..c8e74c1524 100644
--- a/source/gui/scripting/JSInterface_GUITypes.h
+++ b/source/gui/scripting/JSInterface_GUITypes.h
@@ -26,8 +26,8 @@
extern JSClass JSI_class; \
extern JSPropertySpec JSI_props[]; \
extern JSFunctionSpec JSI_methods[]; \
- JSBool construct( JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval ); \
- JSBool toString( JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval ); \
+ JSBool construct(JSContext* cx, uintN argc, jsval* vp); \
+ JSBool toString(JSContext* cx, uintN argc, jsval* vp); \
}
GUISTDTYPE(Size)
diff --git a/source/gui/scripting/JSInterface_IGUIObject.cpp b/source/gui/scripting/JSInterface_IGUIObject.cpp
index 4205af01be..da0b72ee57 100644
--- a/source/gui/scripting/JSInterface_IGUIObject.cpp
+++ b/source/gui/scripting/JSInterface_IGUIObject.cpp
@@ -1,4 +1,4 @@
-/* Copyright (C) 2009 Wildfire Games.
+/* Copyright (C) 2010 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@@ -28,7 +28,7 @@
#include "ps/CLogger.h"
-#include "ps/StringConvert.h"
+#include "scriptinterface/ScriptInterface.h"
JSClass JSI_IGUIObject::JSI_class = {
"GUIObject", JSCLASS_HAS_PRIVATE,
@@ -46,15 +46,25 @@ JSPropertySpec JSI_IGUIObject::JSI_props[] =
JSFunctionSpec JSI_IGUIObject::JSI_methods[] =
{
- { "toString", JSI_IGUIObject::toString, 0, 0, 0 },
- { "focus", JSI_IGUIObject::focus, 0, 0, 0 },
- { "blur", JSI_IGUIObject::blur, 0, 0, 0 },
+ { "toString", JSI_IGUIObject::toString, 0, 0 },
+ { "focus", JSI_IGUIObject::focus, 0, 0 },
+ { "blur", JSI_IGUIObject::blur, 0, 0 },
{ 0 }
};
-JSBool JSI_IGUIObject::getProperty(JSContext* cx, JSObject* obj, jsval id, jsval* vp)
+JSBool JSI_IGUIObject::getProperty(JSContext* cx, JSObject* obj, jsid id, jsval* vp)
{
- CStr propName = JS_GetStringBytes(JS_ValueToString(cx, id));
+ IGUIObject* e = (IGUIObject*)JS_GetInstancePrivate(cx, obj, &JSI_IGUIObject::JSI_class, NULL);
+ if (!e)
+ return JS_FALSE;
+
+ jsval idval;
+ if (!JS_IdToValue(cx, id, &idval))
+ return JS_FALSE;
+
+ std::string propName;
+ if (!ScriptInterface::FromJSVal(cx, idval, propName))
+ return JS_FALSE;
// Skip some things which are known to be functions rather than properties.
// ("constructor" *must* be here, else it'll try to GetSettingType before
@@ -69,10 +79,8 @@ JSBool JSI_IGUIObject::getProperty(JSContext* cx, JSObject* obj, jsval id, jsval
)
return JS_TRUE;
- IGUIObject* e = (IGUIObject*)JS_GetPrivate(cx, obj);
-
// Use onWhatever to access event handlers
- if (propName.Left(2) == "on")
+ if (propName.substr(0, 2) == "on")
{
CStr eventName (CStr(propName.substr(2)).LowerCase());
std::map::iterator it = e->m_ScriptHandlers.find(eventName);
@@ -143,8 +151,7 @@ JSBool JSI_IGUIObject::getProperty(JSContext* cx, JSObject* obj, jsval id, jsval
float value;
GUI::GetSetting(e, propName, value);
// Create a garbage-collectable double
- *vp = DOUBLE_TO_JSVAL(JS_NewDouble(cx, value) );
- break;
+ return JS_NewNumberValue(cx, value, vp);
}
case GUIST_CColor:
@@ -154,8 +161,9 @@ JSBool JSI_IGUIObject::getProperty(JSContext* cx, JSObject* obj, jsval id, jsval
JSObject* obj = JS_NewObject(cx, &JSI_GUIColor::JSI_class, NULL, NULL);
*vp = OBJECT_TO_JSVAL(obj); // root it
+ jsval c;
// Attempt to minimise ugliness through macrosity
- #define P(x) jsval x = DOUBLE_TO_JSVAL(JS_NewDouble(cx, colour.x)); JS_SetProperty(cx, obj, #x, &x)
+ #define P(x) if (!JS_NewNumberValue(cx, colour.x, &c)) return JS_FALSE; JS_SetProperty(cx, obj, #x, &c)
P(r);
P(g);
P(b);
@@ -197,8 +205,7 @@ JSBool JSI_IGUIObject::getProperty(JSContext* cx, JSObject* obj, jsval id, jsval
{
CGUIString value;
GUI::GetSetting(e, propName, value);
- JSString* s = StringConvert::wchars_to_jsstring(cx, value.GetRawString().c_str());
- *vp = STRING_TO_JSVAL(s);
+ *vp = ScriptInterface::ToJSVal(cx, value.GetRawString());
break;
}
@@ -206,7 +213,7 @@ JSBool JSI_IGUIObject::getProperty(JSContext* cx, JSObject* obj, jsval id, jsval
{
CStr value;
GUI::GetSetting(e, propName, value);
- *vp = STRING_TO_JSVAL(JS_NewStringCopyZ(cx, value));
+ *vp = ScriptInterface::ToJSVal(cx, value);
break;
}
@@ -214,7 +221,7 @@ JSBool JSI_IGUIObject::getProperty(JSContext* cx, JSObject* obj, jsval id, jsval
{
CStrW value;
GUI::GetSetting(e, propName, value);
- *vp = STRING_TO_JSVAL(JS_NewUCStringCopyZ(cx, value.utf16().c_str()));
+ *vp = ScriptInterface::ToJSVal(cx, value);
break;
}
@@ -222,7 +229,7 @@ JSBool JSI_IGUIObject::getProperty(JSContext* cx, JSObject* obj, jsval id, jsval
{
CGUISpriteInstance *value;
GUI::GetSettingPointer(e, propName, value);
- *vp = STRING_TO_JSVAL(JS_NewStringCopyZ(cx, value->GetName()));
+ *vp = ScriptInterface::ToJSVal(cx, value->GetName());
break;
}
@@ -238,7 +245,7 @@ JSBool JSI_IGUIObject::getProperty(JSContext* cx, JSObject* obj, jsval id, jsval
case EAlign_Center: word = "center"; break;
default: debug_warn(L"Invalid EAlign!"); word = "error"; break;
}
- *vp = STRING_TO_JSVAL(JS_NewStringCopyZ(cx, word));
+ *vp = ScriptInterface::ToJSVal(cx, word);
break;
}
@@ -254,7 +261,7 @@ JSBool JSI_IGUIObject::getProperty(JSContext* cx, JSObject* obj, jsval id, jsval
case EVAlign_Center: word = "center"; break;
default: debug_warn(L"Invalid EVAlign!"); word = "error"; break;
}
- *vp = STRING_TO_JSVAL(JS_NewStringCopyZ(cx, word));
+ *vp = ScriptInterface::ToJSVal(cx, word);
break;
}
@@ -268,8 +275,7 @@ JSBool JSI_IGUIObject::getProperty(JSContext* cx, JSObject* obj, jsval id, jsval
for (size_t i = 0; i < value.m_Items.size(); ++i)
{
- JSString* s = StringConvert::wchars_to_jsstring(cx, value.m_Items[i].GetRawString().c_str());
- jsval val = STRING_TO_JSVAL(s);
+ jsval val = ScriptInterface::ToJSVal(cx, value.m_Items[i].GetRawString());
JS_SetElement(cx, obj, (jsint)i, &val);
}
@@ -286,20 +292,31 @@ JSBool JSI_IGUIObject::getProperty(JSContext* cx, JSObject* obj, jsval id, jsval
}
}
-JSBool JSI_IGUIObject::setProperty(JSContext* cx, JSObject* obj, jsval id, jsval* vp)
+JSBool JSI_IGUIObject::setProperty(JSContext* cx, JSObject* obj, jsid id, jsval* vp)
{
- IGUIObject* e = (IGUIObject*)JS_GetPrivate(cx, obj);
- CStr propName = g_ScriptingHost.ValueToString(id);
+ IGUIObject* e = (IGUIObject*)JS_GetInstancePrivate(cx, obj, &JSI_IGUIObject::JSI_class, NULL);
+ if (!e)
+ return JS_FALSE;
+
+ jsval idval;
+ if (!JS_IdToValue(cx, id, &idval))
+ return JS_FALSE;
+
+ std::string propName;
+ if (!ScriptInterface::FromJSVal(cx, idval, propName))
+ return JS_FALSE;
+
if (propName == "name")
{
- CStr propValue = JS_GetStringBytes(JS_ValueToString(cx, *vp));
- e->SetName(propValue);
-
+ std::string value;
+ if (!ScriptInterface::FromJSVal(cx, *vp, value))
+ return JS_FALSE;
+ e->SetName(value);
return JS_TRUE;
}
// Use onWhatever to set event handlers
- if (propName.Left(2) == "on")
+ if (propName.substr(0, 2) == "on")
{
if (!JSVAL_IS_OBJECT(*vp) || !JS_ObjectIsFunction(cx, JSVAL_TO_OBJECT(*vp)))
{
@@ -326,29 +343,39 @@ JSBool JSI_IGUIObject::setProperty(JSContext* cx, JSObject* obj, jsval id, jsval
case GUIST_CStr:
{
- CStr value (JS_GetStringBytes(JS_ValueToString(cx, *vp)));
+ std::string value;
+ if (!ScriptInterface::FromJSVal(cx, *vp, value))
+ return JS_FALSE;
+
GUI::SetSetting(e, propName, value);
break;
}
case GUIST_CStrW:
{
- utf16string value (JS_GetStringChars(JS_ValueToString(cx, *vp)));
+ std::wstring value;
+ if (!ScriptInterface::FromJSVal(cx, *vp, value))
+ return JS_FALSE;
+
GUI::SetSetting(e, propName, value);
break;
}
case GUIST_CGUISpriteInstance:
{
- CStr value (JS_GetStringBytes(JS_ValueToString(cx, *vp)));
- GUI::SetSetting(e, propName, value);
+ std::string value;
+ if (!ScriptInterface::FromJSVal(cx, *vp, value))
+ return JS_FALSE;
+
+ GUI::SetSetting(e, propName, CGUISpriteInstance(value));
break;
}
case GUIST_CGUIString:
{
std::wstring value;
- StringConvert::jsstring_to_wstring(JS_ValueToString(cx, *vp), value);
+ if (!ScriptInterface::FromJSVal(cx, *vp, value))
+ return JS_FALSE;
CGUIString str;
str.SetValue(value);
@@ -358,7 +385,10 @@ JSBool JSI_IGUIObject::setProperty(JSContext* cx, JSObject* obj, jsval id, jsval
case GUIST_EAlign:
{
- CStr value (JS_GetStringBytes(JS_ValueToString(cx, *vp)));
+ std::string value;
+ if (!ScriptInterface::FromJSVal(cx, *vp, value))
+ return JS_FALSE;
+
EAlign a;
if (value == "left") a = EAlign_Left;
else if (value == "right") a = EAlign_Right;
@@ -374,7 +404,10 @@ JSBool JSI_IGUIObject::setProperty(JSContext* cx, JSObject* obj, jsval id, jsval
case GUIST_EVAlign:
{
- CStr value (JS_GetStringBytes(JS_ValueToString(cx, *vp)));
+ std::string value;
+ if (!ScriptInterface::FromJSVal(cx, *vp, value))
+ return JS_FALSE;
+
EVAlign a;
if (value == "top") a = EVAlign_Top;
else if (value == "bottom") a = EVAlign_Bottom;
@@ -432,7 +465,8 @@ JSBool JSI_IGUIObject::setProperty(JSContext* cx, JSObject* obj, jsval id, jsval
if (JSVAL_IS_STRING(*vp))
{
std::wstring value;
- StringConvert::jsstring_to_wstring(JS_ValueToString(cx, *vp), value);
+ if (!ScriptInterface::FromJSVal(cx, *vp, value))
+ return JS_FALSE;
if (e->SetSetting(propName, value) != PSRETURN_OK)
{
@@ -472,7 +506,8 @@ JSBool JSI_IGUIObject::setProperty(JSContext* cx, JSObject* obj, jsval id, jsval
if (JSVAL_IS_STRING(*vp))
{
std::wstring value;
- StringConvert::jsstring_to_wstring(JS_ValueToString(cx, *vp), value);
+ if (!ScriptInterface::FromJSVal(cx, *vp, value))
+ return JS_FALSE;
if (e->SetSetting(propName, value) != PSRETURN_OK)
{
@@ -519,8 +554,8 @@ JSBool JSI_IGUIObject::setProperty(JSContext* cx, JSObject* obj, jsval id, jsval
}
std::wstring value;
- JSString* string = JS_ValueToString(cx, element);
- StringConvert::jsstring_to_wstring(string, value);
+ if (!ScriptInterface::FromJSVal(cx, element, value))
+ return JS_FALSE;
CGUIString str;
str.SetValue(value);
@@ -549,7 +584,7 @@ JSBool JSI_IGUIObject::setProperty(JSContext* cx, JSObject* obj, jsval id, jsval
}
-JSBool JSI_IGUIObject::construct(JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* UNUSED(rval))
+JSBool JSI_IGUIObject::construct(JSContext* cx, uintN argc, jsval* vp)
{
if (argc == 0)
{
@@ -557,12 +592,13 @@ JSBool JSI_IGUIObject::construct(JSContext* cx, JSObject* obj, uintN argc, jsval
return JS_FALSE;
}
- debug_assert(argc == 1);
+ JSObject* obj = JS_NewObject(cx, &JSI_IGUIObject::JSI_class, NULL, NULL);
// Store the IGUIObject in the JS object's 'private' area
- IGUIObject* guiObject = (IGUIObject*)JSVAL_TO_PRIVATE(argv[0]);
+ IGUIObject* guiObject = (IGUIObject*)JSVAL_TO_PRIVATE(JS_ARGV(cx, vp)[0]);
JS_SetPrivate(cx, obj, guiObject);
+ JS_SET_RVAL(cx, vp, OBJECT_TO_JSVAL(obj));
return JS_TRUE;
}
@@ -571,29 +607,45 @@ void JSI_IGUIObject::init()
g_ScriptingHost.DefineCustomObjectType(&JSI_class, construct, 1, JSI_props, JSI_methods, NULL, NULL);
}
-JSBool JSI_IGUIObject::toString(JSContext* cx, JSObject* obj, uintN UNUSED(argc), jsval* UNUSED(argv), jsval* rval)
+JSBool JSI_IGUIObject::toString(JSContext* cx, uintN argc, jsval* vp)
{
- IGUIObject* e = (IGUIObject*)JS_GetPrivate( cx, obj );
+ UNUSED2(argc);
+
+ IGUIObject* e = (IGUIObject*)JS_GetInstancePrivate(cx, JS_THIS_OBJECT(cx, vp), &JSI_IGUIObject::JSI_class, NULL);
+ if (!e)
+ return JS_FALSE;
char buffer[256];
snprintf(buffer, 256, "[GUIObject: %s]", e->GetName().c_str());
buffer[255] = 0;
- *rval = STRING_TO_JSVAL(JS_NewStringCopyZ(cx, buffer));
+ JS_SET_RVAL(cx, vp, STRING_TO_JSVAL(JS_NewStringCopyZ(cx, buffer)));
return JS_TRUE;
}
-JSBool JSI_IGUIObject::focus(JSContext* cx, JSObject* obj, uintN UNUSED(argc), jsval* UNUSED(argv), jsval* UNUSED(rval))
+JSBool JSI_IGUIObject::focus(JSContext* cx, uintN argc, jsval* vp)
{
- IGUIObject* e = (IGUIObject*)JS_GetPrivate( cx, obj );
+ UNUSED2(argc);
+
+ IGUIObject* e = (IGUIObject*)JS_GetInstancePrivate(cx, JS_THIS_OBJECT(cx, vp), &JSI_IGUIObject::JSI_class, NULL);
+ if (!e)
+ return JS_FALSE;
e->GetGUI()->SetFocusedObject(e);
+
+ JS_SET_RVAL(cx, vp, JSVAL_VOID);
return JS_TRUE;
}
-JSBool JSI_IGUIObject::blur(JSContext* cx, JSObject* obj, uintN UNUSED(argc), jsval* UNUSED(argv), jsval* UNUSED(rval))
+JSBool JSI_IGUIObject::blur(JSContext* cx, uintN argc, jsval* vp)
{
- IGUIObject* e = (IGUIObject*)JS_GetPrivate( cx, obj );
+ UNUSED2(argc);
+
+ IGUIObject* e = (IGUIObject*)JS_GetInstancePrivate(cx, JS_THIS_OBJECT(cx, vp), &JSI_IGUIObject::JSI_class, NULL);
+ if (!e)
+ return JS_FALSE;
e->GetGUI()->SetFocusedObject(NULL);
+
+ JS_SET_RVAL(cx, vp, JSVAL_VOID);
return JS_TRUE;
}
diff --git a/source/gui/scripting/JSInterface_IGUIObject.h b/source/gui/scripting/JSInterface_IGUIObject.h
index 28ae20e051..d971bb158b 100644
--- a/source/gui/scripting/JSInterface_IGUIObject.h
+++ b/source/gui/scripting/JSInterface_IGUIObject.h
@@ -25,14 +25,12 @@ namespace JSI_IGUIObject
extern JSClass JSI_class;
extern JSPropertySpec JSI_props[];
extern JSFunctionSpec JSI_methods[];
- JSBool addProperty(JSContext* cx, JSObject* obj, jsval id, jsval* vp);
- JSBool delProperty(JSContext* cx, JSObject* obj, jsval id, jsval* vp);
- JSBool getProperty(JSContext* cx, JSObject* obj, jsval id, jsval* vp);
- JSBool setProperty(JSContext* cx, JSObject* obj, jsval id, jsval* vp);
- JSBool construct(JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval);
- JSBool toString(JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval);
- JSBool focus(JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval);
- JSBool blur(JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval);
+ JSBool getProperty(JSContext* cx, JSObject* obj, jsid id, jsval* vp);
+ JSBool setProperty(JSContext* cx, JSObject* obj, jsid id, jsval* vp);
+ JSBool construct(JSContext* cx, uintN argc, jsval* vp);
+ JSBool toString(JSContext* cx, uintN argc, jsval* vp);
+ JSBool focus(JSContext* cx, uintN argc, jsval* vp);
+ JSBool blur(JSContext* cx, uintN argc, jsval* vp);
void init();
}
diff --git a/source/lib/sysdep/os/win/wposix/wposix_types.h b/source/lib/sysdep/os/win/wposix/wposix_types.h
index 3b52051dd9..58afcd6c0e 100644
--- a/source/lib/sysdep/os/win/wposix/wposix_types.h
+++ b/source/lib/sysdep/os/win/wposix/wposix_types.h
@@ -34,7 +34,7 @@
//
//
-typedef signed char int8_t;
+typedef __int8 int8_t;
typedef short int16_t;
// already defined by MinGW
diff --git a/source/maths/scripting/JSInterface_Vector3D.cpp b/source/maths/scripting/JSInterface_Vector3D.cpp
index d7e8569502..2d17e838e9 100644
--- a/source/maths/scripting/JSInterface_Vector3D.cpp
+++ b/source/maths/scripting/JSInterface_Vector3D.cpp
@@ -21,11 +21,6 @@
#include "scripting/JSConversions.h"
#include "scripting/ScriptingHost.h"
-namespace JSI_Vector3D
-{
- static CVector3D* GetVector( JSContext* cx, JSObject* obj );
-}
-
JSClass JSI_Vector3D::JSI_class = {
"Vector3D", JSCLASS_HAS_PRIVATE,
JS_PropertyStub, JS_PropertyStub,
@@ -45,24 +40,13 @@ JSPropertySpec JSI_Vector3D::JSI_props[] =
JSFunctionSpec JSI_Vector3D::JSI_methods[] =
{
- { "toString", JSI_Vector3D::toString, 0, 0, 0 },
- { "add", JSI_Vector3D::add, 1, 0, 0 },
- { "subtract", JSI_Vector3D::subtract, 1, 0, 0 },
- { "minus", JSI_Vector3D::subtract, 1, 0, 0 },
- { "negate", JSI_Vector3D::negate, 1, 0, 0 },
- { "scale", JSI_Vector3D::scale, 1, 0, 0 },
- { "multiply", JSI_Vector3D::scale, 1, 0, 0 },
- { "divide", JSI_Vector3D::divide, 1, 0, 0 },
- { "dot", JSI_Vector3D::dot, 1, 0, 0 },
- { "cross", JSI_Vector3D::cross, 1, 0, 0 },
- { "length", JSI_Vector3D::length, 0, 0, 0 },
- { "normalize", JSI_Vector3D::normalize, 0, 0, 0 },
+ { "toString", JSI_Vector3D::toString, 0, 0 },
{ 0 }
};
void JSI_Vector3D::init()
{
- g_ScriptingHost.DefineCustomObjectType( &JSI_class, JSI_Vector3D::construct, 0, JSI_props, JSI_methods, NULL, NULL );
+ g_ScriptingHost.DefineCustomObjectType(&JSI_class, JSI_Vector3D::construct, 0, JSI_props, JSI_methods, NULL, NULL);
}
JSI_Vector3D::Vector3D_Info::Vector3D_Info()
@@ -71,19 +55,19 @@ JSI_Vector3D::Vector3D_Info::Vector3D_Info()
vector = new CVector3D();
}
-JSI_Vector3D::Vector3D_Info::Vector3D_Info( float x, float y, float z )
+JSI_Vector3D::Vector3D_Info::Vector3D_Info(float x, float y, float z)
{
owner = NULL;
- vector = new CVector3D( x, y, z );
+ vector = new CVector3D(x, y, z);
}
-JSI_Vector3D::Vector3D_Info::Vector3D_Info( const CVector3D& copy )
+JSI_Vector3D::Vector3D_Info::Vector3D_Info(const CVector3D& copy)
{
owner = NULL;
- vector = new CVector3D( copy.X, copy.Y, copy.Z );
+ vector = new CVector3D(copy.X, copy.Y, copy.Z);
}
-JSI_Vector3D::Vector3D_Info::Vector3D_Info( CVector3D* attach, IPropertyOwner* _owner )
+JSI_Vector3D::Vector3D_Info::Vector3D_Info(CVector3D* attach, IPropertyOwner* _owner)
{
owner = _owner;
updateFn = NULL;
@@ -91,7 +75,7 @@ JSI_Vector3D::Vector3D_Info::Vector3D_Info( CVector3D* attach, IPropertyOwner* _
vector = attach;
}
-JSI_Vector3D::Vector3D_Info::Vector3D_Info( CVector3D* attach, IPropertyOwner* _owner, void( IPropertyOwner::*_updateFn )(void) )
+JSI_Vector3D::Vector3D_Info::Vector3D_Info(CVector3D* attach, IPropertyOwner* _owner, void(IPropertyOwner::*_updateFn)(void))
{
owner = _owner;
updateFn = _updateFn;
@@ -99,7 +83,8 @@ JSI_Vector3D::Vector3D_Info::Vector3D_Info( CVector3D* attach, IPropertyOwner* _
vector = attach;
}
-JSI_Vector3D::Vector3D_Info::Vector3D_Info( CVector3D* attach, IPropertyOwner* _owner, void( IPropertyOwner::*_updateFn )(void), void( IPropertyOwner::*_freshenFn )(void) )
+JSI_Vector3D::Vector3D_Info::Vector3D_Info(CVector3D* attach, IPropertyOwner* _owner, void(IPropertyOwner::*_updateFn)(void),
+ void(IPropertyOwner::*_freshenFn)(void))
{
owner = _owner;
updateFn = _updateFn;
@@ -109,245 +94,116 @@ JSI_Vector3D::Vector3D_Info::Vector3D_Info( CVector3D* attach, IPropertyOwner* _
JSI_Vector3D::Vector3D_Info::~Vector3D_Info()
{
- if( !owner ) delete( vector );
+ if (!owner)
+ delete (vector);
}
-JSBool JSI_Vector3D::getProperty( JSContext* cx, JSObject* obj, jsval id, jsval* vp )
+JSBool JSI_Vector3D::getProperty(JSContext* cx, JSObject* obj, jsid id, jsval* vp)
{
- if( !JSVAL_IS_INT( id ) )
- return( JS_TRUE );
+ if (!JSID_IS_INT(id))
+ return JS_TRUE;
- Vector3D_Info* vectorInfo = (Vector3D_Info*)JS_GetPrivate( cx, obj );
- if( !vectorInfo )
- {
- JS_ReportError( cx, "[Vector3D] Invalid reference" );
- return( JS_TRUE );
- }
+ Vector3D_Info* vectorInfo = (Vector3D_Info*)JS_GetInstancePrivate(cx, obj, &JSI_Vector3D::JSI_class, NULL);
+ if (!vectorInfo)
+ return JS_FALSE;
- CVector3D* vectorData = vectorInfo->vector;
-
- if( vectorInfo->owner && vectorInfo->freshenFn ) ( (vectorInfo->owner)->*(vectorInfo->freshenFn) )();
-
- switch( ToPrimitive( id ) )
- {
- case component_x: *vp = DOUBLE_TO_JSVAL( JS_NewDouble( cx, vectorData->X ) ); return( JS_TRUE );
- case component_y: *vp = DOUBLE_TO_JSVAL( JS_NewDouble( cx, vectorData->Y ) ); return( JS_TRUE );
- case component_z: *vp = DOUBLE_TO_JSVAL( JS_NewDouble( cx, vectorData->Z ) ); return( JS_TRUE );
- }
-
- return( JS_FALSE );
-}
-
-JSBool JSI_Vector3D::setProperty( JSContext* cx, JSObject* obj, jsval id, jsval* vp )
-{
- if( !JSVAL_IS_INT( id ) )
- return( JS_TRUE );
-
- Vector3D_Info* vectorInfo = (Vector3D_Info*)JS_GetPrivate( cx, obj );
- if( !vectorInfo )
- {
- JS_ReportError( cx, "[Vector3D] Invalid reference" );
- return( JS_TRUE );
- }
CVector3D* vectorData = vectorInfo->vector;
- if( vectorInfo->owner && vectorInfo->freshenFn ) ( (vectorInfo->owner)->*(vectorInfo->freshenFn) )();
+ if (vectorInfo->owner && vectorInfo->freshenFn)
+ ((vectorInfo->owner)->*(vectorInfo->freshenFn))();
- switch( ToPrimitive( id ) )
+ switch (JSID_TO_INT(id))
{
- case component_x: vectorData->X = ToPrimitive( *vp ); break;
- case component_y: vectorData->Y = ToPrimitive( *vp ); break;
- case component_z: vectorData->Z = ToPrimitive( *vp ); break;
+ case component_x:
+ return JS_NewNumberValue(cx, vectorData->X, vp);
+ case component_y:
+ return JS_NewNumberValue(cx, vectorData->Y, vp);
+ case component_z:
+ return JS_NewNumberValue(cx, vectorData->Z, vp);
}
-
- if( vectorInfo->owner && vectorInfo->updateFn ) ( (vectorInfo->owner)->*(vectorInfo->updateFn) )();
-
- return( JS_TRUE );
+ return JS_FALSE;
}
-JSBool JSI_Vector3D::construct( JSContext* cx, JSObject* UNUSED(obj), uintN argc, jsval* argv, jsval* rval )
+JSBool JSI_Vector3D::setProperty(JSContext* cx, JSObject* obj, jsid id, jsval* vp)
{
- JSObject* vector = JS_NewObject( cx, &JSI_Vector3D::JSI_class, NULL, NULL );
-
- if( argc == 0 )
+ if (!JSID_IS_INT(id))
+ return JS_TRUE;
+
+ Vector3D_Info* vectorInfo = (Vector3D_Info*)JS_GetInstancePrivate(cx, obj, &JSI_Vector3D::JSI_class, NULL);
+ if (!vectorInfo)
+ return JS_FALSE;
+
+ CVector3D* vectorData = vectorInfo->vector;
+
+ if (vectorInfo->owner && vectorInfo->freshenFn)
+ ((vectorInfo->owner)->*(vectorInfo->freshenFn))();
+
+ switch (JSID_TO_INT(id))
{
- JS_SetPrivate( cx, vector, new Vector3D_Info() );
- *rval = OBJECT_TO_JSVAL( vector );
- return( JS_TRUE );
+ case component_x:
+ vectorData->X = ToPrimitive (*vp);
+ break;
+ case component_y:
+ vectorData->Y = ToPrimitive (*vp);
+ break;
+ case component_z:
+ vectorData->Z = ToPrimitive (*vp);
+ break;
+ }
+
+ if (vectorInfo->owner && vectorInfo->updateFn)
+ ((vectorInfo->owner)->*(vectorInfo->updateFn))();
+
+ return JS_TRUE;
+}
+
+JSBool JSI_Vector3D::construct(JSContext* cx, uintN argc, jsval* vp)
+{
+ JSObject* vector = JS_NewObject(cx, &JSI_Vector3D::JSI_class, NULL, NULL);
+
+ if (argc == 0)
+ {
+ JS_SetPrivate(cx, vector, new Vector3D_Info());
+ JS_SET_RVAL(cx, vp, OBJECT_TO_JSVAL(vector));
+ return JS_TRUE;
}
JSU_REQUIRE_PARAMS(3);
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 );
+ float x = ToPrimitive (JS_ARGV(cx, vp)[0]);
+ float y = ToPrimitive (JS_ARGV(cx, vp)[1]);
+ float z = ToPrimitive (JS_ARGV(cx, vp)[2]);
+ JS_SetPrivate(cx, vector, new Vector3D_Info(x, y, z));
+ JS_SET_RVAL(cx, vp, 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 );
+ JS_ReportError(cx, "Invalid parameters to Vector3D constructor");
+ return JS_FALSE;
}
}
-void JSI_Vector3D::finalize( JSContext* cx, JSObject* obj )
+void JSI_Vector3D::finalize(JSContext* cx, JSObject* obj)
{
- delete( (Vector3D_Info*)JS_GetPrivate( cx, obj ) );
+ delete ((Vector3D_Info*)JS_GetPrivate(cx, obj));
}
-JSBool JSI_Vector3D::toString( JSContext* cx, JSObject* obj,
- uintN UNUSED(argc), jsval* UNUSED(argv), jsval* rval )
+JSBool JSI_Vector3D::toString(JSContext* cx, uintN UNUSED(argc), jsval* vp)
{
char buffer[256];
- Vector3D_Info* vectorInfo = (Vector3D_Info*)JS_GetPrivate( cx, obj );
+ Vector3D_Info* vectorInfo = (Vector3D_Info*)JS_GetInstancePrivate(cx, JS_THIS_OBJECT(cx, vp), &JSI_Vector3D::JSI_class, NULL);
+ if (!vectorInfo)
+ return JS_FALSE;
- if( !vectorInfo ) return( JS_TRUE );
+ if (vectorInfo->owner && vectorInfo->freshenFn)
+ ((vectorInfo->owner)->*(vectorInfo->freshenFn))();
- if( vectorInfo->owner && vectorInfo->freshenFn ) ( (vectorInfo->owner)->*(vectorInfo->freshenFn) )();
-
- CVector3D* vectorData = vectorInfo->vector;
- sprintf_s( buffer, ARRAY_SIZE(buffer), "[object Vector3D: ( %f, %f, %f )]", vectorData->X, vectorData->Y, vectorData->Z );
- *rval = STRING_TO_JSVAL( JS_NewStringCopyZ( cx, buffer ) );
- return( JS_TRUE );
-}
-
-CVector3D* JSI_Vector3D::GetVector( JSContext* cx, JSObject* obj )
-{
- Vector3D_Info* vectorInfo = (Vector3D_Info*)JS_GetInstancePrivate( cx, obj, &JSI_class, NULL );
- if( !vectorInfo )
- {
- JS_ReportError( cx, "[Vector3D] Invalid reference" );
- return( NULL );
- }
- if( vectorInfo->owner && vectorInfo->freshenFn ) ( (vectorInfo->owner)->*(vectorInfo->freshenFn) )();
- return( vectorInfo->vector );
-}
-
-#define GET_VECTORS\
- CVector3D* a = GetVector( cx, obj );\
- if(!a)\
- return( JS_TRUE );\
- if( ( argc == 0 ) || !JSVAL_IS_OBJECT( argv[0] ) )\
- {\
-invalid_param:\
- JS_ReportError( cx, "[Vector3D] Invalid parameter" );\
- return( JS_TRUE );\
- }\
- CVector3D* b = GetVector( cx, JSVAL_TO_OBJECT( argv[0] ) );\
- if(!b)\
- goto invalid_param;
-
-#define GET_VECTOR_AND_FLOAT\
- CVector3D* v = GetVector( cx, obj );\
- if(!v)\
- return( JS_TRUE );\
- float f;\
- if( ( argc == 0 ) || !ToPrimitive( cx, argv[0], f ) )\
- {\
- JS_ReportError( cx, "Invalid parameter" );\
- return( JS_TRUE );\
- }
-
-
-JSBool JSI_Vector3D::add( JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval )
-{
- GET_VECTORS;
-
- JSObject* vector3d = JS_NewObject( g_ScriptingHost.getContext(), &JSI_Vector3D::JSI_class, NULL, NULL );
- JS_SetPrivate( g_ScriptingHost.getContext(), vector3d, new JSI_Vector3D::Vector3D_Info( *a + *b ) );
- *rval = OBJECT_TO_JSVAL( vector3d );
-
- return( JS_TRUE );
-}
-
-JSBool JSI_Vector3D::subtract( JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval )
-{
- GET_VECTORS;
-
- JSObject* vector3d = JS_NewObject( g_ScriptingHost.getContext(), &JSI_Vector3D::JSI_class, NULL, NULL );
- JS_SetPrivate( g_ScriptingHost.getContext(), vector3d, new JSI_Vector3D::Vector3D_Info( *a - *b ) );
- *rval = OBJECT_TO_JSVAL( vector3d );
-
- return( JS_TRUE );
-}
-
-JSBool JSI_Vector3D::negate( JSContext* cx, JSObject* obj,
- uintN UNUSED(argc), jsval* UNUSED(argv), jsval* rval )
-{
- CVector3D* v = GetVector( cx, obj );
- if(!v)
- return( JS_TRUE );
-
- *rval = ToJSVal( -( *v ) );
-
- return( JS_TRUE );
-}
-
-JSBool JSI_Vector3D::scale( JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval )
-{
- GET_VECTOR_AND_FLOAT;
-
- JSObject* vector3d = JS_NewObject( g_ScriptingHost.getContext(), &JSI_Vector3D::JSI_class, NULL, NULL );
- JS_SetPrivate( g_ScriptingHost.getContext(), vector3d, new JSI_Vector3D::Vector3D_Info( *v * f ) );
- *rval = OBJECT_TO_JSVAL( vector3d );
-
- return( JS_TRUE );
-}
-
-JSBool JSI_Vector3D::divide( JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval )
-{
- GET_VECTOR_AND_FLOAT;
-
- JSObject* vector3d = JS_NewObject( g_ScriptingHost.getContext(), &JSI_Vector3D::JSI_class, NULL, NULL );
- JS_SetPrivate( g_ScriptingHost.getContext(), vector3d, new JSI_Vector3D::Vector3D_Info( *v * ( 1.0f / f ) ) );
- *rval = OBJECT_TO_JSVAL( vector3d );
-
- return( JS_TRUE );
-}
-
-JSBool JSI_Vector3D::dot( JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval )
-{
- GET_VECTORS;
-
- *rval = ToJSVal( a->Dot( *b ) );
- return( JS_TRUE );
-}
-
-JSBool JSI_Vector3D::cross( JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval )
-{
- GET_VECTORS;
-
- *rval = ToJSVal( a->Cross( *b ) );
- return( JS_TRUE );
-}
-
-JSBool JSI_Vector3D::length( JSContext* cx, JSObject* obj,
- uintN UNUSED(argc), jsval* UNUSED(argv), jsval* rval )
-{
- CVector3D* v = GetVector( cx, obj );
- if(!v)
- return( JS_TRUE );
-
- *rval = ToJSVal( v->Length() );
- return( JS_TRUE );
-}
-
-JSBool JSI_Vector3D::normalize( JSContext* cx, JSObject* obj,
- uintN UNUSED(argc), jsval* UNUSED(argv), jsval* rval )
-{
- CVector3D* v = GetVector( cx, obj );
- if(!v)
- return( JS_TRUE );
-
- CVector3D r( v->X, v->Y, v->Z );
- r.Normalize();
-
- *rval = ToJSVal( r );
- return( JS_TRUE );
+ CVector3D* vectorData = vectorInfo->vector;
+ sprintf_s(buffer, ARRAY_SIZE(buffer), "[object Vector3D: ( %f, %f, %f )]", vectorData->X, vectorData->Y, vectorData->Z);
+ JS_SET_RVAL(cx, vp, STRING_TO_JSVAL(JS_NewStringCopyZ(cx, buffer)));
+ return JS_TRUE;
}
diff --git a/source/maths/scripting/JSInterface_Vector3D.h b/source/maths/scripting/JSInterface_Vector3D.h
index f2486bacae..ab08ec9adf 100644
--- a/source/maths/scripting/JSInterface_Vector3D.h
+++ b/source/maths/scripting/JSInterface_Vector3D.h
@@ -36,42 +36,31 @@ namespace JSI_Vector3D
component_y,
component_z
};
- JSBool toString( JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval );
- JSBool add( JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval );
- JSBool subtract( JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval );
- JSBool negate( JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval );
- JSBool scale( JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval );
- JSBool divide( JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval );
- JSBool dot( JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval );
- JSBool cross( JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval );
- JSBool length( JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval );
- JSBool normalize( JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval );
+ JSBool toString(JSContext* cx, uintN argc, jsval* vp);
struct Vector3D_Info
{
IPropertyOwner* owner;
- void ( IPropertyOwner::*updateFn )();
- void ( IPropertyOwner::*freshenFn )();
+ void (IPropertyOwner::*updateFn)();
+ void (IPropertyOwner::*freshenFn)();
CVector3D* vector;
Vector3D_Info();
- Vector3D_Info( float x, float y, float z );
- Vector3D_Info( const CVector3D& copy );
- Vector3D_Info( CVector3D* attach, IPropertyOwner* _owner );
- Vector3D_Info( CVector3D* attach, IPropertyOwner* _owner, void (IPropertyOwner::*_updateFn)(void) );
- Vector3D_Info( CVector3D* attach, IPropertyOwner* _owner, void (IPropertyOwner::*_updateFn)(void), void (IPropertyOwner::*_freshenFn)(void) );
+ Vector3D_Info(float x, float y, float z);
+ Vector3D_Info(const CVector3D& copy);
+ Vector3D_Info(CVector3D* attach, IPropertyOwner* _owner);
+ Vector3D_Info(CVector3D* attach, IPropertyOwner* _owner, void(IPropertyOwner::*_updateFn)(void));
+ Vector3D_Info(CVector3D* attach, IPropertyOwner* _owner, void(IPropertyOwner::*_updateFn)(void), void(IPropertyOwner::*_freshenFn)(void));
~Vector3D_Info();
};
extern JSClass JSI_class;
extern JSPropertySpec JSI_props[];
extern JSFunctionSpec JSI_methods[];
- JSBool getProperty( JSContext* cx, JSObject* obj, jsval id, jsval* vp );
- JSBool setProperty( JSContext* cx, JSObject* obj, jsval id, jsval* vp );
- void finalize( JSContext* cx, JSObject* obj );
- JSBool construct( JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval );
- void init();
+ JSBool getProperty(JSContext* cx, JSObject* obj, jsid id, jsval* vp);
+ JSBool setProperty(JSContext* cx, JSObject* obj, jsid id, jsval* vp);
+ void finalize(JSContext* cx, JSObject* obj);
+ JSBool construct(JSContext* cx, uintN argc, jsval* vp);
+ void init();
}
#endif
-
-
diff --git a/source/ps/ConfigDB.cpp b/source/ps/ConfigDB.cpp
index 88876750b5..8091d6de7e 100644
--- a/source/ps/ConfigDB.cpp
+++ b/source/ps/ConfigDB.cpp
@@ -24,6 +24,8 @@
#include "Filesystem.h"
#include "scripting/ScriptingHost.h"
+#include "scriptinterface/ScriptInterface.h"
+
#include
typedef std::map TConfigMap;
@@ -35,38 +37,49 @@ bool CConfigDB::m_UseVFS[CFG_LAST];
namespace ConfigNamespace_JS
{
- JSBool GetProperty( JSContext* cx, JSObject* obj, jsval id, jsval* vp )
+ JSBool GetProperty(JSContext* cx, JSObject* obj, jsid id, jsval* vp)
{
EConfigNamespace cfgNs = GET_NS_PRIVATE(cx, obj);
if (cfgNs < 0 || cfgNs >= CFG_LAST)
return JS_FALSE;
- CStr propName = g_ScriptingHost.ValueToString(id);
- CConfigValue *val=g_ConfigDB.GetValue(cfgNs, propName);
+ jsval idval;
+ if (!JS_IdToValue(cx, id, &idval))
+ return JS_FALSE;
+
+ std::string propName;
+ if (!ScriptInterface::FromJSVal(cx, idval, propName))
+ return JS_FALSE;
+
+ CConfigValue *val = g_ConfigDB.GetValue(cfgNs, propName);
if (val)
{
- JSString *js_str=JS_NewStringCopyN(cx, val->m_String.c_str(), val->m_String.size());
+ JSString *js_str = JS_NewStringCopyN(cx, val->m_String.c_str(), val->m_String.size());
*vp = STRING_TO_JSVAL(js_str);
}
return JS_TRUE;
}
- JSBool SetProperty( JSContext* cx, JSObject* obj, jsval id, jsval* vp )
+ JSBool SetProperty(JSContext* cx, JSObject* obj, jsid id, jsval* vp)
{
EConfigNamespace cfgNs = GET_NS_PRIVATE(cx, obj);
if (cfgNs < 0 || cfgNs >= CFG_LAST)
return JS_FALSE;
- CStr propName = g_ScriptingHost.ValueToString(id);
- CConfigValue *val=g_ConfigDB.CreateValue(cfgNs, propName);
- char *str;
- if (JS_ConvertArguments(cx, 1, vp, "s", &str))
- {
- val->m_String=str;
- return JS_TRUE;
- }
- else
+ jsval idval;
+ if (!JS_IdToValue(cx, id, &idval))
return JS_FALSE;
+
+ std::string propName;
+ if (!ScriptInterface::FromJSVal(cx, idval, propName))
+ return JS_FALSE;
+
+ CConfigValue *val = g_ConfigDB.CreateValue(cfgNs, propName);
+
+ if (!ScriptInterface::FromJSVal(cx, *vp, val->m_String))
+ return JS_FALSE;
+
+ return JS_TRUE;
}
JSClass Class = {
@@ -77,13 +90,12 @@ namespace ConfigNamespace_JS
JS_ConvertStub, JS_FinalizeStub
};
- JSBool Construct( JSContext* cx, JSObject* obj, uintN argc, jsval* UNUSED(argv), jsval* rval )
+ JSBool Construct(JSContext* cx, uintN argc, jsval* vp)
{
- if (argc != 0)
- return JS_FALSE;
+ UNUSED2(argc);
- JSObject *newObj=JS_NewObject(cx, &Class, NULL, obj);
- *rval=OBJECT_TO_JSVAL(newObj);
+ JSObject *newObj = JS_NewObject(cx, &Class, NULL, NULL);
+ JS_SET_RVAL(cx, vp, OBJECT_TO_JSVAL(newObj));
return JS_TRUE;
}
@@ -92,65 +104,70 @@ namespace ConfigNamespace_JS
JS_SetPrivate(cx, obj, (void *)((uintptr_t)cfgNs << 1)); // JS requires bottom bit = 0
}
- JSBool WriteFile( JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval )
+ JSBool WriteFile(JSContext* cx, uintN argc, jsval* vp)
{
- EConfigNamespace cfgNs = GET_NS_PRIVATE(cx, obj);
+ EConfigNamespace cfgNs = GET_NS_PRIVATE(cx, JS_THIS_OBJECT(cx, vp));
if (cfgNs < 0 || cfgNs >= CFG_LAST)
return JS_FALSE;
if (argc != 2)
return JS_FALSE;
- JSBool useVFS;
- char *path;
- if (JS_ConvertArguments(cx, 2, argv, "bs", &useVFS, &path))
- {
- JSBool res=g_ConfigDB.WriteFile(cfgNs, useVFS?true:false, CStrW(path));
- *rval = BOOLEAN_TO_JSVAL(res);
- return JS_TRUE;
- }
- else
- return JS_FALSE;
- }
-
- JSBool Reload( JSContext* cx, JSObject* obj, uintN argc, jsval* UNUSED(argv), jsval* rval )
- {
- if (argc != 0)
+ bool useVFS;
+ if (!ScriptInterface::FromJSVal(cx, JS_ARGV(cx, vp)[0], useVFS))
return JS_FALSE;
- EConfigNamespace cfgNs = GET_NS_PRIVATE(cx, obj);
- if (cfgNs < 0 || cfgNs >= CFG_LAST)
+ std::wstring path;
+ if (!ScriptInterface::FromJSVal(cx, JS_ARGV(cx, vp)[1], path))
return JS_FALSE;
- JSBool ret=g_ConfigDB.Reload(cfgNs);
- *rval = BOOLEAN_TO_JSVAL(ret);
+ bool res = g_ConfigDB.WriteFile(cfgNs, useVFS, path);
+
+ JS_SET_RVAL(cx, vp, BOOLEAN_TO_JSVAL(res));
return JS_TRUE;
}
- JSBool SetFile( JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* UNUSED(rval) )
+ JSBool Reload(JSContext* cx, uintN argc, jsval* vp)
{
if (argc != 0)
return JS_FALSE;
- EConfigNamespace cfgNs = GET_NS_PRIVATE(cx, obj);
+ EConfigNamespace cfgNs = GET_NS_PRIVATE(cx, JS_THIS_OBJECT(cx, vp));
if (cfgNs < 0 || cfgNs >= CFG_LAST)
return JS_FALSE;
- JSBool useVFS;
- char *path;
- if (JS_ConvertArguments(cx, 2, argv, "bs", &useVFS, &path))
- {
- g_ConfigDB.SetConfigFile(cfgNs, useVFS?true:false, CStrW(path));
- return JS_TRUE;
- }
- else
+ JSBool ret = g_ConfigDB.Reload(cfgNs);
+ JS_SET_RVAL(cx, vp, BOOLEAN_TO_JSVAL(ret));
+ return JS_TRUE;
+ }
+
+ JSBool SetFile(JSContext* cx, uintN argc, jsval* vp)
+ {
+ EConfigNamespace cfgNs = GET_NS_PRIVATE(cx, JS_THIS_OBJECT(cx, vp));
+ if (cfgNs < 0 || cfgNs >= CFG_LAST)
return JS_FALSE;
+
+ if (argc != 2)
+ return JS_FALSE;
+
+ bool useVFS;
+ if (!ScriptInterface::FromJSVal(cx, JS_ARGV(cx, vp)[0], useVFS))
+ return JS_FALSE;
+
+ std::wstring path;
+ if (!ScriptInterface::FromJSVal(cx, JS_ARGV(cx, vp)[1], path))
+ return JS_FALSE;
+
+ g_ConfigDB.SetConfigFile(cfgNs, useVFS, path);
+
+ JS_SET_RVAL(cx, vp, JSVAL_VOID);
+ return JS_TRUE;
}
JSFunctionSpec Funcs[] = {
- { "writeFile", WriteFile, 2, 0, 0},
- { "reload", Reload, 0, 0, 0},
- { "setFile", SetFile, 2, 0, 0},
+ { "writeFile", WriteFile, 2, 0 },
+ { "reload", Reload, 0, 0 },
+ { "setFile", SetFile, 2, 0 },
{0}
};
};
@@ -173,13 +190,12 @@ namespace ConfigDB_JS
{0}
};
- JSBool Construct( JSContext* cx, JSObject* obj, uintN argc, jsval* UNUSED(argv), jsval* rval )
+ JSBool Construct(JSContext* cx, uintN argc, jsval* vp)
{
- if (argc != 0)
- return JS_FALSE;
+ UNUSED2(argc);
- JSObject *newObj=JS_NewObject(cx, &Class, NULL, obj);
- *rval=OBJECT_TO_JSVAL(newObj);
+ JSObject *newObj = JS_NewObject(cx, &Class, NULL, NULL);
+ JS_SET_RVAL(cx, vp, OBJECT_TO_JSVAL(newObj));
int flags=JSPROP_ENUMERATE|JSPROP_READONLY|JSPROP_PERMANENT;
#define cfg_ns(_propname, _enum) STMT (\
@@ -204,15 +220,16 @@ CConfigDB::CConfigDB()
{
g_ScriptingHost.DefineCustomObjectType(&ConfigDB_JS::Class, ConfigDB_JS::Construct, 0, ConfigDB_JS::Props, ConfigDB_JS::Funcs, NULL, NULL);
g_ScriptingHost.DefineCustomObjectType(&ConfigNamespace_JS::Class, ConfigNamespace_JS::Construct, 0, NULL, ConfigNamespace_JS::Funcs, NULL, NULL);
- JSObject *js_ConfigDB=g_ScriptingHost.CreateCustomObject("ConfigDB");
+ JSObject *js_ConfigDB = g_ScriptingHost.CreateCustomObject("ConfigDB");
g_ScriptingHost.SetGlobal("g_ConfigDB", OBJECT_TO_JSVAL(js_ConfigDB));
}
CConfigValue *CConfigDB::GetValue(EConfigNamespace ns, const CStr& name)
{
- CConfigValueSet* values = GetValues( ns, name );
- if( !values ) return( NULL );
- return &( (*values)[0] );
+ CConfigValueSet* values = GetValues(ns, name);
+ if (!values)
+ return (NULL);
+ return &((*values)[0]);
}
CConfigValueSet *CConfigDB::GetValues(EConfigNamespace ns, const CStr& name)
@@ -223,18 +240,18 @@ CConfigValueSet *CConfigDB::GetValues(EConfigNamespace ns, const CStr& name)
return NULL;
}
- TConfigMap::iterator it = m_Map[CFG_COMMAND].find( name );
- if( it != m_Map[CFG_COMMAND].end() )
- return &( it->second );
+ TConfigMap::iterator it = m_Map[CFG_COMMAND].find(name);
+ if (it != m_Map[CFG_COMMAND].end())
+ return &(it->second);
- for( int search_ns = ns; search_ns >= 0; search_ns-- )
+ for (int search_ns = ns; search_ns >= 0; search_ns--)
{
TConfigMap::iterator it = m_Map[search_ns].find(name);
if (it != m_Map[search_ns].end())
- return &( it->second );
+ return &(it->second);
}
- return( NULL );
+ return NULL;
}
std::vector > CConfigDB::GetValuesWithPrefix(EConfigNamespace ns, const CStr& prefix)
diff --git a/source/ps/GameSetup/GameSetup.cpp b/source/ps/GameSetup/GameSetup.cpp
index cf89b40aeb..695e2ff2d7 100644
--- a/source/ps/GameSetup/GameSetup.cpp
+++ b/source/ps/GameSetup/GameSetup.cpp
@@ -48,7 +48,6 @@
#include "ps/Overlay.h"
#include "ps/Profile.h"
#include "ps/ProfileViewer.h"
-#include "ps/StringConvert.h"
#include "ps/Util.h"
#include "ps/VideoMode.h"
#include "ps/World.h"
@@ -76,9 +75,6 @@
#include "maths/scripting/JSInterface_Vector3D.h"
-#include "graphics/scripting/JSInterface_Camera.h"
-#include "graphics/scripting/JSInterface_LightEnv.h"
-
#include "ps/scripting/JSInterface_Console.h"
#include "gui/GUI.h"
@@ -184,9 +180,8 @@ retry:
// display progress / description in loading screen
void GUI_DisplayLoadProgress(int percent, const wchar_t* pending_task)
{
- JSString* js_desc = StringConvert::wstring_to_jsstring(g_ScriptingHost.getContext(), pending_task);
- g_ScriptingHost.SetGlobal("g_Progress", INT_TO_JSVAL(percent));
- g_ScriptingHost.SetGlobal("g_LoadDescription", STRING_TO_JSVAL(js_desc));
+ g_ScriptingHost.GetScriptInterface().SetGlobal("g_Progress", percent, true);
+ g_ScriptingHost.GetScriptInterface().SetGlobal("g_LoadDescription", pending_task, true);
g_GUI->SendEventToAll("progress");
}
@@ -306,8 +301,6 @@ static void RegisterJavascriptInterfaces()
JSI_Vector3D::init();
// graphics
- JSI_Camera::init();
- JSI_LightEnv::init();
CGameView::ScriptingInit();
// renderer
diff --git a/source/ps/StringConvert.cpp b/source/ps/StringConvert.cpp
deleted file mode 100644
index a859de777d..0000000000
--- a/source/ps/StringConvert.cpp
+++ /dev/null
@@ -1,83 +0,0 @@
-/* Copyright (C) 2009 Wildfire Games.
- * This file is part of 0 A.D.
- *
- * 0 A.D. is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 2 of the License, or
- * (at your option) any later version.
- *
- * 0 A.D. is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with 0 A.D. If not, see .
- */
-
-#include "precompiled.h"
-
-#include "StringConvert.h"
-#include "lib/external_libraries/sdl.h"
-#include "scripting/SpiderMonkey.h"
-
-#if SDL_BYTEORDER == SDL_BIG_ENDIAN
-#define ucs2le_to_wchart(ptr) (wchar_t)( (u16) ((u8*)ptr)[0] | (u16) ( ((u8*)ptr)[1] << 8) )
-#else
-#define ucs2le_to_wchart(ptr) (wchar_t)(*ptr);
-#endif
-
-
-JSString* StringConvert::wchars_to_jsstring(JSContext* cx, const wchar_t* chars, size_t len)
-{
- if (len == 0)
- return JSVAL_TO_STRING(JS_GetEmptyStringValue(cx));
-
- jschar* data = (jschar*)JS_malloc(cx, len*sizeof(jschar));
-
- if (!data)
- return NULL;
-
- // Copy the string data, doing wchar_t->jschar conversion (since they're not equal in GCC)
- for (size_t i=0; i.
- */
-
-#ifndef INCLUDED_STRINGCONVERT
-#define INCLUDED_STRINGCONVERT
-
-typedef unsigned short jschar;
-typedef unsigned short ucs2char;
-
-struct JSString;
-struct JSContext;
-
-#include
-
-namespace StringConvert
-{
- // A random collection of conversion functions:
-
- JSString* wstring_to_jsstring(JSContext* cx, const std::wstring& str);
- JSString* wchars_to_jsstring(JSContext* cx, const wchar_t* chars);
- JSString* wchars_to_jsstring(JSContext* cx, const wchar_t* chars, size_t len);
-
- void jsstring_to_wstring(JSString* str, std::wstring& result);
- void jschars_to_wstring(const jschar* chars, size_t len, std::wstring& result);
- void ucs2le_to_wstring(const char* start, const char* end, std::wstring& result);
-
-}
-
-#endif // INCLUDED_STRINGCONVERT
diff --git a/source/ps/scripting/JSInterface_Console.cpp b/source/ps/scripting/JSInterface_Console.cpp
index 31541d5441..79b3005ece 100644
--- a/source/ps/scripting/JSInterface_Console.cpp
+++ b/source/ps/scripting/JSInterface_Console.cpp
@@ -1,4 +1,4 @@
-/* Copyright (C) 2009 Wildfire Games.
+/* Copyright (C) 2010 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@@ -40,81 +40,85 @@ JSPropertySpec JSI_Console::JSI_props[] =
JSFunctionSpec JSI_Console::JSI_methods[] =
{
- { "write", JSI_Console::writeConsole, 1, 0, 0 },
+ { "write", JSI_Console::writeConsole, 1, 0 },
{ 0 },
};
-JSBool JSI_Console::getProperty( JSContext* UNUSED(cx), JSObject* UNUSED(obj), jsval id, jsval* vp )
+JSBool JSI_Console::getProperty(JSContext* UNUSED(cx), JSObject* UNUSED(obj), jsid id, jsval* vp)
{
- if( !JSVAL_IS_INT( id ) )
- return( JS_TRUE );
+ if (!JSID_IS_INT(id))
+ return JS_TRUE;
- int i = JSVAL_TO_INT( id );
+ int i = JSID_TO_INT(id);
- switch( i )
+ switch (i)
{
case console_visible:
- *vp = BOOLEAN_TO_JSVAL( g_Console->IsActive() ); return( JS_TRUE );
+ *vp = BOOLEAN_TO_JSVAL(g_Console->IsActive());
+ return JS_TRUE;
default:
- *vp = JSVAL_NULL; return( JS_TRUE );
- }
+ *vp = JSVAL_NULL;
+ return JS_TRUE;
+ }
}
-JSBool JSI_Console::setProperty( JSContext* UNUSED(cx), JSObject* UNUSED(obj), jsval id, jsval* vp )
+JSBool JSI_Console::setProperty(JSContext* UNUSED(cx), JSObject* UNUSED(obj), jsid id, jsval* vp)
{
- if( !JSVAL_IS_INT( id ) )
- return( JS_TRUE );
+ if (!JSID_IS_INT(id))
+ return JS_TRUE;
- int i = JSVAL_TO_INT( id );
+ int i = JSID_TO_INT(id);
- switch( i )
+ switch (i)
{
case console_visible:
try
{
- g_Console->SetVisible( ToPrimitive( *vp ) );
- return( JS_TRUE );
+ g_Console->SetVisible(ToPrimitive (*vp));
+ return JS_TRUE;
}
- catch( PSERROR_Scripting_ConversionFailed )
+ catch (PSERROR_Scripting_ConversionFailed)
{
- return( JS_TRUE );
+ return JS_TRUE;
}
default:
- return( JS_TRUE );
- }
+ return JS_TRUE;
+ }
}
void JSI_Console::init()
{
- g_ScriptingHost.DefineCustomObjectType( &JSI_class, NULL, 0, JSI_props, JSI_methods, NULL, NULL );
+ g_ScriptingHost.DefineCustomObjectType(&JSI_class, NULL, 0, JSI_props, JSI_methods, NULL, NULL);
}
-JSBool JSI_Console::getConsole( JSContext* cx, JSObject* UNUSED(obj), jsval UNUSED(id), jsval* vp )
+JSBool JSI_Console::getConsole(JSContext* cx, JSObject* UNUSED(obj), jsid UNUSED(id), jsval* vp)
{
- JSObject* console = JS_NewObject( cx, &JSI_Console::JSI_class, NULL, NULL );
- *vp = OBJECT_TO_JSVAL( console );
- return( JS_TRUE );
+ JSObject* console = JS_NewObject(cx, &JSI_Console::JSI_class, NULL, NULL);
+ *vp = OBJECT_TO_JSVAL(console);
+ return JS_TRUE;
}
-JSBool JSI_Console::writeConsole( JSContext* UNUSED(context), JSObject* UNUSED(globalObject), uintN argc, jsval* argv, jsval* UNUSED(rval) )
+JSBool JSI_Console::writeConsole(JSContext* cx, uintN argc, jsval* vp)
{
- debug_assert( argc >= 1 );
+ UNUSED2(cx);
+
CStrW output;
- for( unsigned int i = 0; i < argc; i++ )
+ for (uintN i = 0; i < argc; i++)
{
try
{
- CStrW arg = g_ScriptingHost.ValueToUCString( argv[i] );
+ CStrW arg = g_ScriptingHost.ValueToUCString(JS_ARGV(cx, vp)[i]);
output += arg;
}
- catch( PSERROR_Scripting_ConversionFailed )
+ catch (PSERROR_Scripting_ConversionFailed)
{
}
}
// TODO: What if the console has been destroyed already?
if (g_Console)
- g_Console->InsertMessage( L"%ls", output.c_str() );
+ g_Console->InsertMessage(L"%ls", output.c_str());
- return( JS_TRUE );
+ JS_SET_RVAL(cx, vp, JSVAL_VOID);
+ return JS_TRUE;
}
diff --git a/source/ps/scripting/JSInterface_Console.h b/source/ps/scripting/JSInterface_Console.h
index ae99c05581..2512bcb63e 100644
--- a/source/ps/scripting/JSInterface_Console.h
+++ b/source/ps/scripting/JSInterface_Console.h
@@ -34,14 +34,14 @@ namespace JSI_Console
extern JSPropertySpec JSI_props[];
extern JSFunctionSpec JSI_methods[];
- JSBool getProperty( JSContext* cx, JSObject* obj, jsval id, jsval* vp );
- JSBool setProperty( JSContext* cx, JSObject* obj, jsval id, jsval* vp );
+ JSBool getProperty(JSContext* cx, JSObject* obj, jsid id, jsval* vp);
+ JSBool setProperty(JSContext* cx, JSObject* obj, jsid id, jsval* vp);
- JSBool getConsole( JSContext* context, JSObject* obj, jsval id, jsval* vp );
+ JSBool getConsole(JSContext* context, JSObject* obj, jsid id, jsval* vp);
void init();
- JSBool writeConsole( JSContext* context, JSObject* obj, uintN argc, jsval* argv, jsval* rval );
+ JSBool writeConsole(JSContext* cx, uintN argc, jsval* vp);
}
#endif
diff --git a/source/ps/scripting/JSInterface_VFS.cpp b/source/ps/scripting/JSInterface_VFS.cpp
index 9ed49f3fbe..0176e9eb93 100644
--- a/source/ps/scripting/JSInterface_VFS.cpp
+++ b/source/ps/scripting/JSInterface_VFS.cpp
@@ -29,15 +29,15 @@
// shared error handling code
#define JS_CHECK_FILE_ERR(err)\
/* this is liable to happen often, so don't complain */\
- if(err == ERR::VFS_FILE_NOT_FOUND)\
+ if (err == ERR::VFS_FILE_NOT_FOUND)\
{\
- *rval = JSVAL_NULL;\
- return( JS_TRUE );\
+ JS_SET_RVAL(cx, vp, JSVAL_NULL);\
+ return JS_TRUE;\
}\
/* unknown failure. we return an error (akin to an exception in JS) that
stops the script to make sure this error is noticed. */\
- else if(err < 0)\
- return( JS_FALSE );\
+ else if (err < 0)\
+ return JS_FALSE;\
/* else: success */
@@ -54,13 +54,13 @@ struct BuildDirEntListState
: cx(cx_)
{
filename_array = JS_NewArrayObject(cx, 0, NULL);
- JS_AddRoot(cx, &filename_array);
+ JS_AddObjectRoot(cx, &filename_array);
cur_idx = 0;
}
~BuildDirEntListState()
{
- JS_RemoveRoot(cx, &filename_array);
+ JS_RemoveObjectRoot(cx, &filename_array);
}
};
@@ -85,44 +85,45 @@ static LibError BuildDirEntListCB(const VfsPath& pathname, const FileInfo& UNUSE
//
// note: full pathnames of each file/subdirectory are returned,
// ready for use as a "filename" for the other functions.
-JSBool JSI_VFS::BuildDirEntList( JSContext* cx, JSObject* UNUSED(obj), uintN argc, jsval* argv, jsval* rval )
+JSBool JSI_VFS::BuildDirEntList(JSContext* cx, uintN argc, jsval* vp)
{
//
// get arguments
//
- debug_assert( argc >= 1 );
+ JSU_REQUIRE_MIN_PARAMS(1);
+
CStr path;
- if( !ToPrimitive( cx, argv[0], path ) )
- return( JS_FALSE );
+ if (!ToPrimitive (cx, JS_ARGV(cx, vp)[0], path))
+ return JS_FALSE;
CStrW filter_str = L"";
- if(argc >= 2)
+ if (argc >= 2)
{
- if( !ToPrimitive( cx, argv[1], filter_str ) )
- return( JS_FALSE );
+ if (!ToPrimitive (cx, JS_ARGV(cx, vp)[1], filter_str))
+ return JS_FALSE;
}
// convert to const wchar_t*; if there's no filter, pass 0 for speed
// (interpreted as: "accept all files without comparing").
const wchar_t* filter = 0;
- if(!filter_str.empty())
+ if (!filter_str.empty())
filter = filter_str.c_str();
bool recursive = false;
- if(argc >= 3)
+ if (argc >= 3)
{
- if( !ToPrimitive( cx, argv[2], recursive ) )
- return( JS_FALSE );
+ if (!ToPrimitive (cx, JS_ARGV(cx, vp)[2], recursive))
+ return JS_FALSE;
}
- int flags = recursive? fs_util::DIR_RECURSIVE : 0;
+ int flags = recursive ? fs_util::DIR_RECURSIVE : 0;
// build array in the callback function
BuildDirEntListState state(cx);
fs_util::ForEachFile(g_VFS, CStrW(path), BuildDirEntListCB, (uintptr_t)&state, filter, flags);
- *rval = OBJECT_TO_JSVAL( state.filename_array );
- return( JS_TRUE );
+ JS_SET_RVAL(cx, vp, OBJECT_TO_JSVAL(state.filename_array));
+ return JS_TRUE;
}
@@ -130,19 +131,20 @@ JSBool JSI_VFS::BuildDirEntList( JSContext* cx, JSObject* UNUSED(obj), uintN arg
//
// mtime = getFileMTime(filename);
// filename: VFS filename (may include path)
-JSBool JSI_VFS::GetFileMTime( JSContext* cx, JSObject* UNUSED(obj), uintN argc, jsval* argv, jsval* rval )
+JSBool JSI_VFS::GetFileMTime(JSContext* cx, uintN argc, jsval* vp)
{
- debug_assert( argc >= 1 );
+ JSU_REQUIRE_MIN_PARAMS(1);
+
CStr filename;
- if( !ToPrimitive( cx, argv[0], filename ) )
- return( JS_FALSE );
+ if (!ToPrimitive (cx, JS_ARGV(cx, vp)[0], filename))
+ return JS_FALSE;
FileInfo fileInfo;
LibError err = g_VFS->GetFileInfo(CStrW(filename), &fileInfo);
- JS_CHECK_FILE_ERR( err );
+ JS_CHECK_FILE_ERR(err);
- *rval = ToJSVal( (double)fileInfo.MTime() );
- return( JS_TRUE );
+ JS_SET_RVAL(cx, vp, ToJSVal((double)fileInfo.MTime()));
+ return JS_TRUE;
}
@@ -150,19 +152,20 @@ JSBool JSI_VFS::GetFileMTime( JSContext* cx, JSObject* UNUSED(obj), uintN argc,
//
// size = getFileSize(filename);
// filename: VFS filename (may include path)
-JSBool JSI_VFS::GetFileSize( JSContext* cx, JSObject* UNUSED(obj), uintN argc, jsval* argv, jsval* rval )
+JSBool JSI_VFS::GetFileSize(JSContext* cx, uintN argc, jsval* vp)
{
- debug_assert( argc >= 1 );
+ JSU_REQUIRE_MIN_PARAMS(1);
+
CStr filename;
- if( !ToPrimitive( cx, argv[0], filename ) )
- return( JS_FALSE );
+ if (!ToPrimitive (cx, JS_ARGV(cx, vp)[0], filename))
+ return JS_FALSE;
FileInfo fileInfo;
LibError err = g_VFS->GetFileInfo(CStrW(filename), &fileInfo);
JS_CHECK_FILE_ERR(err);
- *rval = ToJSVal( (unsigned)fileInfo.Size() );
- return( JS_TRUE );
+ JS_SET_RVAL(cx, vp, ToJSVal( (unsigned)fileInfo.Size() ));
+ return JS_TRUE;
}
@@ -170,25 +173,27 @@ JSBool JSI_VFS::GetFileSize( JSContext* cx, JSObject* UNUSED(obj), uintN argc, j
//
// contents = readFile(filename);
// filename: VFS filename (may include path)
-JSBool JSI_VFS::ReadFile( JSContext* cx, JSObject* UNUSED(obj), uintN argc, jsval* argv, jsval* rval )
+JSBool JSI_VFS::ReadFile(JSContext* cx, uintN argc, jsval* vp)
{
- debug_assert( argc >= 1 );
- CStr filename;
- if( !ToPrimitive( cx, argv[0], filename ) )
- return( JS_FALSE );
+ JSU_REQUIRE_MIN_PARAMS(1);
- shared_ptr buf; size_t size;
- LibError err = g_VFS->LoadFile( CStrW(filename), buf, size );
+ CStr filename;
+ if (!ToPrimitive (cx, JS_ARGV(cx, vp)[0], filename))
+ return JS_FALSE;
+
+ shared_ptr buf;
+ size_t size;
+ LibError err = g_VFS->LoadFile(CStrW(filename), buf, size);
JS_CHECK_FILE_ERR( err );
- CStr contents( (const char*)buf.get(), size );
+ CStr contents((const char*)buf.get(), size);
// Fix CRLF line endings. (This function will only ever be used on text files.)
contents.Replace("\r\n", "\n");
// Decode as UTF-8
- *rval = ToJSVal( contents.FromUTF8() );
- return( JS_TRUE );
+ JS_SET_RVAL(cx, vp, ToJSVal( contents.FromUTF8() ));
+ return JS_TRUE;
}
@@ -196,22 +201,24 @@ JSBool JSI_VFS::ReadFile( JSContext* cx, JSObject* UNUSED(obj), uintN argc, jsva
//
// lines = readFileLines(filename);
// filename: VFS filename (may include path)
-JSBool JSI_VFS::ReadFileLines( JSContext* cx, JSObject* UNUSED(obj), uintN argc, jsval* argv, jsval* rval )
+JSBool JSI_VFS::ReadFileLines(JSContext* cx, uintN argc, jsval* vp)
{
- debug_assert( argc >= 1 );
+ JSU_REQUIRE_MIN_PARAMS(1);
+
CStr filename;
- if( !ToPrimitive( cx, argv[0], filename ) )
- return( JS_FALSE );
+ if (!ToPrimitive (cx, JS_ARGV(cx, vp)[0], filename))
+ return (JS_FALSE);
//
// read file
//
- shared_ptr buf; size_t size;
- LibError err = g_VFS->LoadFile( CStrW(filename), buf, size );
+ shared_ptr buf;
+ size_t size;
+ LibError err = g_VFS->LoadFile(CStrW(filename), buf, size);
JS_CHECK_FILE_ERR( err );
- CStr contents( (const char*)buf.get(), size );
+ CStr contents((const char*)buf.get(), size);
// Fix CRLF line endings. (This function will only ever be used on text files.)
contents.Replace("\r\n", "\n");
@@ -220,32 +227,33 @@ JSBool JSI_VFS::ReadFileLines( JSContext* cx, JSObject* UNUSED(obj), uintN argc,
// split into array of strings (one per line)
//
- std::stringstream ss( contents );
+ std::stringstream ss(contents);
- JSObject* line_array = JS_NewArrayObject( cx, 0, NULL );
- JS_AddRoot(cx, &line_array);
+ JSObject* line_array = JS_NewArrayObject(cx, 0, NULL);
std::string line;
int cur_line = 0;
- while( std::getline( ss, line ) )
+ while (std::getline(ss, line))
{
// Decode each line as UTF-8
- jsval val = ToJSVal( CStr( line ).FromUTF8() );
- JS_SetElement( cx, line_array, cur_line++, &val );
+ jsval val = ToJSVal(CStr(line).FromUTF8());
+ JS_SetElement(cx, line_array, cur_line++, &val);
}
- JS_RemoveRoot(cx, &line_array);
-
- *rval = OBJECT_TO_JSVAL( line_array );
- return( JS_TRUE );
+ JS_SET_RVAL(cx, vp, OBJECT_TO_JSVAL( line_array ));
+ return JS_TRUE ;
}
// vfs_optimizer
-JSBool JSI_VFS::ArchiveBuilderCancel(JSContext* UNUSED(cx), JSObject* UNUSED(obj), uintN argc, jsval* UNUSED(argv), jsval* UNUSED(rval) )
+JSBool JSI_VFS::ArchiveBuilderCancel(JSContext* cx, uintN argc, jsval* vp)
{
- debug_assert( argc == 0 );
+ UNUSED2(cx);
+ UNUSED2(argc);
+
// vfs_opt_auto_build_cancel();
- return( JS_TRUE );
+
+ JS_SET_RVAL(cx, vp, JSVAL_VOID);
+ return JS_TRUE;
}
diff --git a/source/ps/scripting/JSInterface_VFS.h b/source/ps/scripting/JSInterface_VFS.h
index 1e8fe8e0b0..603622198b 100644
--- a/source/ps/scripting/JSInterface_VFS.h
+++ b/source/ps/scripting/JSInterface_VFS.h
@@ -38,36 +38,36 @@ namespace JSI_VFS
//
// note: full pathnames of each file/subdirectory are returned,
// ready for use as a "filename" for the other functions.
- JSBool BuildDirEntList( JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval );
+ JSBool BuildDirEntList(JSContext* cx, uintN argc, jsval* vp);
// Return time [seconds since 1970] of the last modification to the specified file.
//
// mtime = getFileMTime(filename);
// filename: VFS filename (may include path)
- JSBool GetFileMTime( JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval );
+ JSBool GetFileMTime(JSContext* cx, uintN argc, jsval* vp);
// Return current size of file.
//
// size = getFileSize(filename);
// filename: VFS filename (may include path)
- JSBool GetFileSize( JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval );
+ JSBool GetFileSize(JSContext* cx, uintN argc, jsval* vp);
// Return file contents in a string.
//
// contents = readFile(filename);
// filename: VFS filename (may include path)
- JSBool ReadFile( JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval );
+ JSBool ReadFile(JSContext* cx, uintN argc, jsval* vp);
// Return file contents as an array of lines.
//
// lines = readFileLines(filename);
// filename: VFS filename (may include path)
- JSBool ReadFileLines( JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval );
+ JSBool ReadFileLines(JSContext* cx, uintN argc, jsval* vp);
// Abort the current archive build operation (no-op if not currently active).
//
// archiveBuilderCancel();
- JSBool ArchiveBuilderCancel(JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval );
+ JSBool ArchiveBuilderCancel(JSContext* cx, uintN argc, jsval* vp);
}
#endif
diff --git a/source/scripting/JSConversions.cpp b/source/scripting/JSConversions.cpp
index b9bfb602bf..856e39ec33 100644
--- a/source/scripting/JSConversions.cpp
+++ b/source/scripting/JSConversions.cpp
@@ -1,4 +1,4 @@
-/* Copyright (C) 2009 Wildfire Games.
+/* Copyright (C) 2010 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@@ -22,6 +22,7 @@
#include "maths/scripting/JSInterface_Vector3D.h"
#include "ps/Parser.h"
#include "lib/sysdep/sysdep.h" // isfinite
+#include "scriptinterface/ScriptInterface.h"
#include
#include
@@ -180,12 +181,16 @@ template<> bool ToPrimitive( JSContext* cx, jsval v, ssize_t& Storage )
template<> jsval ToJSVal( const double& Native )
{
- return( DOUBLE_TO_JSVAL( JS_NewDouble( g_ScriptingHost.getContext(), Native ) ) );
+ jsval val = JSVAL_VOID;
+ JS_NewNumberValue( g_ScriptingHost.getContext(), Native, &val );
+ return val;
}
template<> jsval ToJSVal( double& Native )
{
- return( DOUBLE_TO_JSVAL( JS_NewDouble( g_ScriptingHost.getContext(), Native ) ) );
+ jsval val = JSVAL_VOID;
+ JS_NewNumberValue( g_ScriptingHost.getContext(), Native, &val );
+ return val;
}
template<> bool ToPrimitive( JSContext* cx, jsval v, double& Storage )
@@ -200,12 +205,16 @@ template<> bool ToPrimitive( JSContext* cx, jsval v, double& Storage )
template<> jsval ToJSVal( const float& Native )
{
- return( DOUBLE_TO_JSVAL( JS_NewDouble( g_ScriptingHost.getContext(), Native ) ) );
+ jsval val = JSVAL_VOID;
+ JS_NewNumberValue( g_ScriptingHost.getContext(), Native, &val );
+ return val;
}
template<> jsval ToJSVal( float& Native )
{
- return( DOUBLE_TO_JSVAL( JS_NewDouble( g_ScriptingHost.getContext(), Native ) ) );
+ jsval val = JSVAL_VOID;
+ JS_NewNumberValue( g_ScriptingHost.getContext(), Native, &val );
+ return val;
}
template<> bool ToPrimitive( JSContext* cx, jsval v, float& Storage )
@@ -256,27 +265,23 @@ template<> bool ToPrimitive( JSContext* UNUSED(cx), jsval v, CStrW& Stora
template<> jsval ToJSVal( const CStrW& Native )
{
- return( STRING_TO_JSVAL( JS_NewUCStringCopyZ( g_ScriptingHost.GetContext(), Native.utf16().c_str() ) ) );
+ return( STRING_TO_JSVAL( JS_NewUCStringCopyZ( g_ScriptingHost.GetContext(), reinterpret_cast(Native.utf16().c_str()) ) ) );
}
template<> jsval ToJSVal( CStrW& Native )
{
- return( STRING_TO_JSVAL( JS_NewUCStringCopyZ( g_ScriptingHost.GetContext(), Native.utf16().c_str() ) ) );
+ return( STRING_TO_JSVAL( JS_NewUCStringCopyZ( g_ScriptingHost.GetContext(), reinterpret_cast(Native.utf16().c_str()) ) ) );
}
// CStr/CStr8
-template<> bool ToPrimitive( JSContext* UNUSED(cx), jsval v, CStr8& Storage )
+template<> bool ToPrimitive( JSContext* cx, jsval v, CStr8& Storage )
{
- try
- {
- Storage = g_ScriptingHost.ValueToString( v );
- }
- catch( PSERROR_Scripting_ConversionFailed )
- {
- return( false );
- }
- return( true );
+ std::string str;
+ if (!ScriptInterface::FromJSVal(cx, v, str))
+ return false;
+ Storage = str;
+ return true;
}
template<> jsval ToJSVal( const CStr8& Native )
@@ -304,18 +309,12 @@ jsval JSParseString( const CStrW& Native )
stringParser.InputTaskType( "string", "_$value_" );
CParserLine result;
result.ParseString( stringParser, CStr(Native) );
- bool boolResult; int intResult; float floatResult;
+ bool boolResult;
+ float floatResult;
if( result.GetArgFloat( 0, floatResult ) )
- {
- if( floatResult == floor( floatResult ) )
- {
- intResult = (int)floatResult;
- if( INT_FITS_IN_JSVAL( intResult ) )
- return( ToJSVal( intResult ) );
- }
return( ToJSVal( floatResult ) );
- }
+
if( result.GetArgBool( 0, boolResult ) )
return( BOOLEAN_TO_JSVAL( boolResult ) );
diff --git a/source/scripting/JSUtil.cpp b/source/scripting/JSUtil.cpp
index 4061a9fe67..bc7fb75d09 100644
--- a/source/scripting/JSUtil.cpp
+++ b/source/scripting/JSUtil.cpp
@@ -19,12 +19,12 @@
#include "SpiderMonkey.h"
-jsval jsu_report_param_error(JSContext* cx, jsval* rval)
+JSBool jsu_report_param_error(JSContext* cx, jsval* vp)
{
JS_ReportError(cx, "Invalid parameter(s) or count");
- if(rval)
- *rval = JSVAL_NULL;
+ if (vp)
+ JS_SET_RVAL(cx, vp, JSVAL_NULL);
// yes, we had an error, but returning JS_FALSE would cause SpiderMonkey
// to abort. that would be hard to debug.
diff --git a/source/scripting/JSUtil.h b/source/scripting/JSUtil.h
index 3cc3f2ee1c..574b9a2f6f 100644
--- a/source/scripting/JSUtil.h
+++ b/source/scripting/JSUtil.h
@@ -17,7 +17,7 @@
// included from SpiderMonkey.h
-extern jsval jsu_report_param_error(JSContext* cx, jsval* rval);
+extern JSBool jsu_report_param_error(JSContext* cx, jsval* vp);
// consistent argc checking for normal function wrappers: reports an
@@ -25,24 +25,23 @@ extern jsval jsu_report_param_error(JSContext* cx, jsval* rval);
// .. require exact number (most common case)
#define JSU_REQUIRE_PARAMS(exact_number)\
if(argc != exact_number)\
- return jsu_report_param_error(cx, rval);
+ return jsu_report_param_error(cx, vp);
// .. 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);
+ return jsu_report_param_error(cx, vp);
// .. 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);
+ return jsu_report_param_error(cx, vp);
// .. require at most a certain count
#define JSU_REQUIRE_MAX_PARAMS(max_number)\
if(argc > max_number)\
- return jsu_report_param_error(cx, rval);
+ return jsu_report_param_error(cx, vp);
// .. 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);
+ return jsu_report_param_error(cx, vp);
// same as JSU_REQUIRE_PARAMS, but used from C++ functions that are
// a bit further removed from SpiderMonkey, i.e. return a
diff --git a/source/scripting/ScriptGlue.cpp b/source/scripting/ScriptGlue.cpp
index 430d40bdb4..e0185836b5 100644
--- a/source/scripting/ScriptGlue.cpp
+++ b/source/scripting/ScriptGlue.cpp
@@ -31,8 +31,6 @@
#include "graphics/MapWriter.h"
#include "graphics/Unit.h"
#include "graphics/UnitManager.h"
-#include "graphics/scripting/JSInterface_Camera.h"
-#include "graphics/scripting/JSInterface_LightEnv.h"
#include "gui/GUIManager.h"
#include "gui/IGUIObject.h"
#include "lib/frequency_filter.h"
@@ -109,24 +107,26 @@ static void InitJsTimers()
js_timer_clients[0].sum.SetToZero();
}
-JSBool StartJsTimer(JSContext* cx, JSObject*, uintN argc, jsval* argv, jsval* rval)
+JSBool StartJsTimer(JSContext* cx, uintN argc, jsval* vp)
{
ONCE(InitJsTimers());
JSU_REQUIRE_PARAMS(1);
- size_t slot = ToPrimitive(argv[0]);
+ size_t slot = ToPrimitive(JS_ARGV(cx, vp)[0]);
if (slot >= MAX_JS_TIMERS)
return JS_FALSE;
js_start_times[slot].SetFromTimer();
+
+ JS_SET_RVAL(cx, vp, JSVAL_VOID);
return JS_TRUE;
}
-JSBool StopJsTimer(JSContext* cx, JSObject*, uintN argc, jsval* argv, jsval* rval)
+JSBool StopJsTimer(JSContext* cx, uintN argc, jsval* vp)
{
JSU_REQUIRE_PARAMS(1);
- size_t slot = ToPrimitive(argv[0]);
+ size_t slot = ToPrimitive(JS_ARGV(cx, vp)[0]);
if (slot >= MAX_JS_TIMERS)
return JS_FALSE;
@@ -135,6 +135,8 @@ JSBool StopJsTimer(JSContext* cx, JSObject*, uintN argc, jsval* argv, jsval* rva
now.Subtract(js_timer_overhead);
BillingPolicy_Default()(&js_timer_clients[slot], js_start_times[slot], now);
js_start_times[slot].SetToZero();
+
+ JS_SET_RVAL(cx, vp, JSVAL_VOID);
return JS_TRUE;
}
@@ -146,11 +148,13 @@ JSBool StopJsTimer(JSContext* cx, JSObject*, uintN argc, jsval* argv, jsval* rva
// Immediately ends the current game (if any).
// params:
// returns:
-JSBool EndGame(JSContext* cx, JSObject*, uintN argc, jsval* argv, jsval* rval)
+JSBool EndGame(JSContext* cx, uintN argc, jsval* vp)
{
JSU_REQUIRE_NO_PARAMS();
EndGame();
+
+ JS_SET_RVAL(cx, vp, JSVAL_VOID);
return JS_TRUE;
}
@@ -164,13 +168,13 @@ JSBool EndGame(JSContext* cx, JSObject*, uintN argc, jsval* argv, jsval* rval)
// notes:
// - This value is recalculated once a frame. We take special care to
// filter it, so it is both accurate and free of jitter.
-JSBool GetFps( JSContext* cx, JSObject*, uintN argc, jsval* argv, jsval* rval )
+JSBool GetFps(JSContext* cx, uintN argc, jsval* vp)
{
JSU_REQUIRE_NO_PARAMS();
int freq = 0;
if (g_frequencyFilter)
freq = g_frequencyFilter->StableFrequency();
- *rval = INT_TO_JSVAL(freq);
+ JS_SET_RVAL(cx, vp, INT_TO_JSVAL(freq));
return JS_TRUE;
}
@@ -181,28 +185,13 @@ JSBool GetFps( JSContext* cx, JSObject*, uintN 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*, uintN argc, jsval* argv, jsval* rval )
+JSBool ExitProgram(JSContext* cx, uintN argc, jsval* vp)
{
JSU_REQUIRE_NO_PARAMS();
kill_mainloop();
- return JS_TRUE;
-}
-
-// Write an indication of total video RAM to console.
-// params:
-// returns:
-// notes:
-// - May not be supported on all platforms.
-// - Only a rough approximation; do not base low-level decisions
-// ("should I allocate one more texture?") on this.
-JSBool WriteVideoMemToConsole( JSContext* cx, JSObject*, uintN argc, jsval* argv, jsval* rval )
-{
- JSU_REQUIRE_NO_PARAMS();
-
- const SDL_VideoInfo* videoInfo = SDL_GetVideoInfo();
- g_Console->InsertMessage(L"VRAM: total %d", videoInfo->video_mem);
+ JS_SET_RVAL(cx, vp, JSVAL_VOID);
return JS_TRUE;
}
@@ -212,38 +201,27 @@ JSBool WriteVideoMemToConsole( JSContext* cx, JSObject*, uintN argc, jsval* argv
// returns:
// notes:
// - Cursors are stored in "art\textures\cursors"
-JSBool SetCursor( JSContext* cx, JSObject*, uintN argc, jsval* argv, jsval* rval )
+JSBool SetCursor(JSContext* cx, uintN argc, jsval* vp)
{
JSU_REQUIRE_PARAMS(1);
- g_CursorName = g_ScriptingHost.ValueToUCString(argv[0]);
+ g_CursorName = g_ScriptingHost.ValueToUCString(JS_ARGV(cx, vp)[0]);
+
+ JS_SET_RVAL(cx, vp, JSVAL_VOID);
return JS_TRUE;
}
-// Change the LOD bias.
-// params: LOD bias [float]
-// returns:
-// 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*, uintN argc, jsval* argv, jsval* rval )
+JSBool GetGUIObjectByName(JSContext* cx, uintN argc, jsval* vp)
{
JSU_REQUIRE_PARAMS(1);
- g_Renderer.SetOptionFloat(CRenderer::OPT_LODBIAS, ToPrimitive(argv[0]));
- return JS_TRUE;
-}
-
-
-JSBool GetGUIObjectByName(JSContext* cx, JSObject* UNUSED(obj), uintN UNUSED(argc), jsval* argv, jsval* rval)
-{
try
{
- CStr name = ToPrimitive(cx, argv[0]);
+ CStr name = ToPrimitive(cx, JS_ARGV(cx, vp)[0]);
IGUIObject* guiObj = g_GUI->FindObjectByName(name);
if (guiObj)
- *rval = OBJECT_TO_JSVAL(guiObj->GetJSObject());
+ JS_SET_RVAL(cx, vp, OBJECT_TO_JSVAL(guiObj->GetJSObject()));
else
- *rval = JSVAL_NULL;
+ JS_SET_RVAL(cx, vp, JSVAL_NULL);
return JS_TRUE;
}
catch (PSERROR_Scripting&)
@@ -270,14 +248,14 @@ JSBool GetGUIObjectByName(JSContext* cx, JSObject* UNUSED(obj), uintN UNUSED(arg
// lib/svn_revision.cpp. it is useful to know when attempting to
// reproduce bugs (the main EXE and PDB should be temporarily reverted to
// that revision so that they match user-submitted crashdumps).
-JSBool GetBuildTimestamp( JSContext* cx, JSObject*, uintN argc, jsval* argv, jsval* rval )
+JSBool GetBuildTimestamp(JSContext* cx, uintN argc, jsval* vp)
{
JSU_REQUIRE_MAX_PARAMS(1);
char buf[200];
// see function documentation
- const int mode = argc? JSVAL_TO_INT(argv[0]) : -1;
+ const int mode = argc? JSVAL_TO_INT(JS_ARGV(cx, vp)[0]) : -1;
switch(mode)
{
case -1:
@@ -294,7 +272,7 @@ JSBool GetBuildTimestamp( JSContext* cx, JSObject*, uintN argc, jsval* argv, jsv
break;
}
- *rval = STRING_TO_JSVAL(JS_NewStringCopyZ(cx, buf));
+ JS_SET_RVAL(cx, vp, STRING_TO_JSVAL(JS_NewStringCopyZ(cx, buf)));
return JS_TRUE;
}
@@ -311,8 +289,11 @@ void DumpHeap(const char* name, int idx, JSContext* cx)
}
#endif
-JSBool DumpHeaps(JSContext* UNUSED(cx), JSObject* UNUSED(globalObject), uintN UNUSED(argc), jsval* UNUSED(argv), jsval* UNUSED(rval) )
+JSBool DumpHeaps(JSContext* cx, uintN argc, jsval* vp)
{
+ UNUSED2(cx);
+ UNUSED2(argc);
+
#ifdef DEBUG
static int i = 0;
@@ -325,47 +306,50 @@ JSBool DumpHeaps(JSContext* UNUSED(cx), JSObject* UNUSED(globalObject), uintN UN
#else
debug_warn(L"DumpHeaps only available in DEBUG mode");
#endif
+
+ JS_SET_RVAL(cx, vp, JSVAL_VOID);
return JS_TRUE;
}
//-----------------------------------------------------------------------------
// Is the game paused?
-JSBool IsPaused( JSContext* cx, JSObject* UNUSED(globalObject), uintN argc, jsval* argv, jsval* rval )
+JSBool IsPaused(JSContext* cx, uintN argc, jsval* vp)
{
JSU_REQUIRE_NO_PARAMS();
- if( !g_Game )
+ if (!g_Game)
{
- JS_ReportError( cx, "Game is not started" );
+ JS_ReportError(cx, "Game is not started");
return JS_FALSE;
}
- *rval = g_Game->m_Paused ? JSVAL_TRUE : JSVAL_FALSE;
- return JS_TRUE ;
+ JS_SET_RVAL(cx, vp, g_Game->m_Paused ? JSVAL_TRUE : JSVAL_FALSE);
+ return JS_TRUE;
}
// Pause/unpause the game
-JSBool SetPaused( JSContext* cx, JSObject* UNUSED(globalObject), uintN argc, jsval* argv, jsval* rval )
+JSBool SetPaused(JSContext* cx, uintN argc, jsval* vp)
{
JSU_REQUIRE_PARAMS( 1 );
- if( !g_Game )
+ if (!g_Game)
{
- JS_ReportError( cx, "Game is not started" );
+ JS_ReportError(cx, "Game is not started");
return JS_FALSE;
}
try
{
- g_Game->m_Paused = ToPrimitive( argv[0] );
+ g_Game->m_Paused = ToPrimitive (JS_ARGV(cx, vp)[0]);
}
- catch( PSERROR_Scripting_ConversionFailed )
+ catch (PSERROR_Scripting_ConversionFailed)
{
- JS_ReportError( cx, "Invalid parameter to SetPaused" );
+ JS_ReportError(cx, "Invalid parameter to SetPaused");
}
- return JS_TRUE;
+ JS_SET_RVAL(cx, vp, JSVAL_VOID);
+ return JS_TRUE;
}
@@ -381,7 +365,7 @@ JSBool SetPaused( JSContext* cx, JSObject* UNUSED(globalObject), uintN argc, jsv
// - Extra (reserved for future use, always zero)
//
// we simplify this a bit with a macro:
-#define JS_FUNC(script_name, cpp_function, min_params) { script_name, cpp_function, min_params, 0, 0 },
+#define JS_FUNC(script_name, cpp_function, min_params) { script_name, cpp_function, min_params, 0 },
JSFunctionSpec ScriptFunctionTable[] =
{
@@ -404,8 +388,6 @@ JSFunctionSpec ScriptFunctionTable[] =
JS_FUNC("exit", ExitProgram, 0)
JS_FUNC("isPaused", IsPaused, 0)
JS_FUNC("setPaused", SetPaused, 1)
- JS_FUNC("vmem", WriteVideoMemToConsole, 0)
- JS_FUNC("_lodBias", _LodBias, 0)
JS_FUNC("setCursor", SetCursor, 1)
JS_FUNC("getFPS", GetFps, 0)
JS_FUNC("getGUIObjectByName", GetGUIObjectByName, 1)
@@ -415,7 +397,7 @@ JSFunctionSpec ScriptFunctionTable[] =
JS_FUNC("dumpHeaps", DumpHeaps, 0)
// end of table marker
- {0, 0, 0, 0, 0}
+ {0}
};
#undef JS_FUNC
@@ -424,23 +406,22 @@ JSFunctionSpec ScriptFunctionTable[] =
// property accessors
//-----------------------------------------------------------------------------
-JSBool GetGameView( JSContext* UNUSED(cx), JSObject* UNUSED(obj), jsval UNUSED(id), jsval* vp )
+JSBool GetGameView(JSContext* UNUSED(cx), JSObject* UNUSED(obj), jsid UNUSED(id), jsval* vp)
{
if (g_Game)
- *vp = OBJECT_TO_JSVAL( g_Game->GetView()->GetScript() );
+ *vp = OBJECT_TO_JSVAL(g_Game->GetView()->GetScript());
else
*vp = JSVAL_NULL;
- return( JS_TRUE );
+ return JS_TRUE;
}
-
-JSBool GetRenderer( JSContext* UNUSED(cx), JSObject* UNUSED(obj), jsval UNUSED(id), jsval* vp )
+JSBool GetRenderer(JSContext* UNUSED(cx), JSObject* UNUSED(obj), jsid UNUSED(id), jsval* vp)
{
if (CRenderer::IsInitialised())
- *vp = OBJECT_TO_JSVAL( g_Renderer.GetScript() );
+ *vp = OBJECT_TO_JSVAL(g_Renderer.GetScript());
else
*vp = JSVAL_NULL;
- return( JS_TRUE );
+ return JS_TRUE;
}
@@ -455,9 +436,7 @@ enum ScriptGlobalTinyIDs
JSPropertySpec ScriptGlobalTable[] =
{
- { "camera" , GLOBAL_CAMERA, JSPROP_PERMANENT, JSI_Camera::getCamera, JSI_Camera::setCamera },
{ "console" , GLOBAL_CONSOLE, JSPROP_PERMANENT|JSPROP_READONLY, JSI_Console::getConsole, 0 },
- { "lightenv" , GLOBAL_LIGHTENV, JSPROP_PERMANENT, JSI_LightEnv::getLightEnv, JSI_LightEnv::setLightEnv },
{ "gameView" , 0, JSPROP_PERMANENT|JSPROP_READONLY, GetGameView, 0 },
{ "renderer" , 0, JSPROP_PERMANENT|JSPROP_READONLY, GetRenderer, 0 },
diff --git a/source/scripting/ScriptableObject.h b/source/scripting/ScriptableObject.h
index c1347bbf74..bebd790587 100644
--- a/source/scripting/ScriptableObject.h
+++ b/source/scripting/ScriptableObject.h
@@ -155,12 +155,12 @@ public:
void Root()
{
if( JSVAL_IS_GCTHING( m_Data ) )
- JS_AddNamedRoot( g_ScriptingHost.GetContext(), (void*)&m_Data, "ScriptableObjectProperty" );
+ JS_AddNamedValueRoot( g_ScriptingHost.GetContext(), &m_Data, "ScriptableObjectProperty" );
}
void Uproot()
{
if( JSVAL_IS_GCTHING( m_Data ))
- JS_RemoveRoot( g_ScriptingHost.GetContext(), (void*)&m_Data );
+ JS_RemoveValueRoot( g_ScriptingHost.GetContext(), &m_Data );
}
jsval Get( JSContext* UNUSED(cx), IJSObject* UNUSED(object))
{
@@ -179,14 +179,14 @@ public:
template class CNativeFunction
{
public:
- static JSBool JSFunction( JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval )
+ static JSBool JSFunction( JSContext* cx, uintN argc, jsval* vp )
{
- T* Native = ToNative( cx, obj );
+ T* Native = ToNative( cx, JS_THIS_OBJECT( cx, vp ) );
if( !Native )
- return( JS_TRUE );
-
- *rval = ToJSVal( (Native->*NativeFunction)( cx, argc, argv ) );
+ return( JS_FALSE );
+ jsval rval = ToJSVal( (Native->*NativeFunction)( cx, argc, JS_ARGV(cx, vp) ) );
+ JS_SET_RVAL( cx, vp, rval );
return( JS_TRUE );
}
};
@@ -196,14 +196,15 @@ template
{
public:
- static JSBool JSFunction( JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* UNUSED(rval) )
+ static JSBool JSFunction( JSContext* cx, uintN argc, jsval* vp )
{
- T* Native = ToNative( cx, obj );
+ T* Native = ToNative( cx, JS_THIS_OBJECT( cx, vp ) );
if( !Native )
- return( JS_TRUE );
+ return( JS_FALSE );
- (Native->*NativeFunction)( cx, argc, argv );
+ (Native->*NativeFunction)( cx, argc, JS_ARGV(cx, vp) );
+ JS_SET_RVAL( cx, vp, JSVAL_VOID );
return( JS_TRUE );
}
};
@@ -328,7 +329,7 @@ public:
template
static void AddMethod( const char* Name, uintN MinArgs )
{
- JSFunctionSpec FnInfo = { Name, CNativeFunction::JSFunction, (uint8)MinArgs, 0, 0 };
+ JSFunctionSpec FnInfo = { Name, CNativeFunction::JSFunction, (uint8)MinArgs, 0 };
m_Methods.push_back( FnInfo );
}
template static void AddProperty( const CStrW& PropertyName, PropType T::*Native, bool PropReadOnly = ReadOnly )
@@ -373,7 +374,7 @@ public:
{
m_JS = JS_NewObject( g_ScriptingHost.GetContext(), &JSI_class, NULL, NULL );
if( m_EngineOwned )
- JS_AddNamedRoot( g_ScriptingHost.GetContext(), (void*)&m_JS, JSI_class.name );
+ JS_AddNamedObjectRoot( g_ScriptingHost.GetContext(), &m_JS, JSI_class.name );
JS_SetPrivate( g_ScriptingHost.GetContext(), m_JS, (T*)this );
}
@@ -384,7 +385,7 @@ public:
{
JS_SetPrivate( g_ScriptingHost.GetContext(), m_JS, NULL );
if( m_EngineOwned )
- JS_RemoveRoot( g_ScriptingHost.GetContext(), &m_JS );
+ JS_RemoveObjectRoot( g_ScriptingHost.GetContext(), &m_JS );
m_JS = NULL;
}
}
@@ -393,26 +394,34 @@ public:
// Functions and data that must be provided to JavaScript
//
private:
- static JSBool JSGetProperty( JSContext* cx, JSObject* obj, jsval id, jsval* vp )
+ static JSBool JSGetProperty( JSContext* cx, JSObject* obj, jsid id, jsval* vp )
{
T* Instance = ToNative( cx, obj );
if( !Instance )
return( JS_TRUE );
- CStrW PropName = g_ScriptingHost.ValueToUCString( id );
+ jsval idval;
+ if( !JS_IdToValue( cx, id, &idval ) )
+ return( JS_FALSE );
+
+ CStrW PropName = g_ScriptingHost.ValueToUCString( idval );
if( !Instance->GetProperty( cx, PropName, vp ) )
return( JS_TRUE );
return( JS_TRUE );
}
- static JSBool JSSetProperty( JSContext* cx, JSObject* obj, jsval id, jsval* vp )
+ static JSBool JSSetProperty( JSContext* cx, JSObject* obj, jsid id, jsval* vp )
{
T* Instance = ToNative( cx, obj );
if( !Instance )
return( JS_TRUE );
- CStrW PropName = g_ScriptingHost.ValueToUCString( id );
+ jsval idval;
+ if( !JS_IdToValue( cx, id, &idval ) )
+ return( JS_FALSE );
+
+ CStrW PropName = g_ScriptingHost.ValueToUCString( idval );
Instance->SetProperty( cx, PropName, vp );
diff --git a/source/scripting/ScriptingHost.cpp b/source/scripting/ScriptingHost.cpp
index 4a835415cf..36b961e88e 100644
--- a/source/scripting/ScriptingHost.cpp
+++ b/source/scripting/ScriptingHost.cpp
@@ -94,7 +94,9 @@ void ScriptingHost::RunScript(const VfsPath& pathname, JSObject* globalObject)
utf16string script(scriptw.begin(), scriptw.end());
jsval rval;
- JSBool ok = JS_EvaluateUCScript(m_Context, globalObject, script.c_str(), (uintN)script.size(), CStr(pathname.string()).c_str(), 1, &rval);
+ JSBool ok = JS_EvaluateUCScript(m_Context, globalObject,
+ reinterpret_cast(script.c_str()), (uintN)script.size(),
+ CStr(pathname.string()).c_str(), 1, &rval);
if (ok == JS_FALSE)
throw PSERROR_Scripting_LoadFile_EvalErrors();
@@ -105,7 +107,8 @@ jsval ScriptingHost::ExecuteScript(const CStrW& script, const CStrW& calledFrom,
jsval rval;
JSBool ok = JS_EvaluateUCScript(m_Context, contextObject ? contextObject : m_GlobalObject,
- script.utf16().c_str(), (int)script.length(), CStr(calledFrom), 1, &rval);
+ reinterpret_cast(script.utf16().c_str()), (int)script.length(),
+ CStr(calledFrom), 1, &rval);
if (!ok) return JSVAL_NULL;
@@ -168,12 +171,10 @@ jsval ScriptingHost::GetObjectProperty( JSObject* object, const std::string& pro
void ScriptingHost::SetObjectProperty_Double(JSObject* object, const char* propertyName, double value)
{
- jsdouble* d = JS_NewDouble(m_Context, value);
- if (! d)
+ jsval v;
+ if (! JS_NewNumberValue(m_Context, value, &v))
throw PSERROR_Scripting_ConversionFailed();
- jsval v = DOUBLE_TO_JSVAL(d);
-
if (! JS_SetProperty(m_Context, object, propertyName, &v))
throw PSERROR_Scripting_ConversionFailed();
}
@@ -203,15 +204,6 @@ void ScriptingHost::SetGlobal(const std::string &globalName, jsval value)
// conversions
//----------------------------------------------------------------------------
-std::string ScriptingHost::ValueToString(const jsval value)
-{
- JSString* string = JS_ValueToString(m_Context, value);
- if (string == NULL)
- throw PSERROR_Scripting_ConversionFailed();
-
- return std::string(JS_GetStringBytes(string), JS_GetStringLength(string));
-}
-
CStrW ScriptingHost::ValueToUCString( const jsval value )
{
JSString* string = JS_ValueToString(m_Context, value);
diff --git a/source/scripting/ScriptingHost.h b/source/scripting/ScriptingHost.h
index 1327c8a8dc..732c464a66 100644
--- a/source/scripting/ScriptingHost.h
+++ b/source/scripting/ScriptingHost.h
@@ -111,7 +111,6 @@ public:
void SetGlobal(const std::string& globalName, jsval value);
- std::string ValueToString(const jsval value);
CStrW ValueToUCString(const jsval value);
};
diff --git a/source/scripting/SpiderMonkey.h b/source/scripting/SpiderMonkey.h
index f3563dc482..ed9a0e839f 100644
--- a/source/scripting/SpiderMonkey.h
+++ b/source/scripting/SpiderMonkey.h
@@ -30,27 +30,10 @@
// (notably precompiled.h and i18n/ScriptInterface.cpp) want only these
// definitions without pulling in the whole of ScriptingHost.
-// jstypes.h (included via jsapi.h) requires we define
-// "one of XP_BEOS, XP_MAC, XP_OS2, XP_WIN or XP_UNIX".
-#include "lib/config.h"
-#if OS_WIN
-# define XP_WIN
-#elif OS_MAC
-# define XP_MAC
-#elif OS_BEOS
-# define XP_BEOS
-#else
-# define XP_UNIX
-#endif
+// (Actually that XP_* stuff is handled by the newer scriptinterface
+// code instead; this file no longer does anything interesting)
-#include
-
-#ifndef NDEBUG
-// Used by ScriptingHost::jshook_{script,function}
-# include
-#endif
-
-// include any further required headers here
+#include "scriptinterface/ScriptTypes.h"
#include "JSUtil.h"
diff --git a/source/scriptinterface/AutoRooters.cpp b/source/scriptinterface/AutoRooters.cpp
index a6047d5547..7b7097c88e 100644
--- a/source/scriptinterface/AutoRooters.cpp
+++ b/source/scriptinterface/AutoRooters.cpp
@@ -47,4 +47,15 @@ void AutoGCRooter::Trace(JSTracer* trc)
{
JS_CALL_VALUE_TRACER(trc, m_Vals[i], "AutoGCRooter val");
}
+
+ for (size_t i = 0; i < m_IdArrays.size(); ++i)
+ {
+ for (jsint j = 0; j < m_IdArrays[i]->length; ++j)
+ {
+ jsval val = JSVAL_VOID;
+ JS_IdToValue(m_ScriptInterface.GetContext(), m_IdArrays[i]->vector[j], &val);
+ JS_CALL_VALUE_TRACER(trc, val, "AutoGCRooter id array");
+ }
+ }
+
}
diff --git a/source/scriptinterface/AutoRooters.h b/source/scriptinterface/AutoRooters.h
index acdf8740b5..3cf94ad256 100644
--- a/source/scriptinterface/AutoRooters.h
+++ b/source/scriptinterface/AutoRooters.h
@@ -22,30 +22,6 @@
#include "js/jsapi.h"
-// Exception-safety and GC-safety wrapper for JSIdArray
-// (TODO: it'd be nicer to use the existing js::AutoIdArray but currently that
-// requires a load of semi-private SpiderMonkey headers that cause a load of compile warnings)
-class IdArrayWrapper
-{
- JSContext* m_cx;
- JSIdArray* m_ida;
-public:
- IdArrayWrapper(JSContext* cx, JSIdArray* ida) :
- m_cx(cx), m_ida(ida)
- {
- for (jsint i = 0; i < m_ida->length; ++i)
- if (!JS_AddRoot(m_cx, &m_ida->vector[i]))
- debug_warn(L"JS_AddRoot failed");
- }
- ~IdArrayWrapper()
- {
- for (jsint i = 0; i < m_ida->length; ++i)
- if (!JS_RemoveRoot(m_cx, &m_ida->vector[i]))
- debug_warn(L"JS_RemoveRoot failed");
- JS_DestroyIdArray(m_cx, m_ida);
- }
-};
-
/**
* Helper for rooting large groups of script values.
* Construct this object, push values into it, and they will all be rooted until this
@@ -61,6 +37,7 @@ public:
void Push(JSObject* obj) { m_Objects.push_back(obj); }
void Push(jsval val) { m_Vals.push_back(val); }
+ void Push(JSIdArray* ida) { m_IdArrays.push_back(ida); }
void Trace(JSTracer* trc);
private:
@@ -69,6 +46,7 @@ private:
std::vector m_Objects;
std::vector m_Vals;
+ std::vector m_IdArrays;
// TODO: add vectors of other value types
};
diff --git a/source/scriptinterface/ScriptConversions.cpp b/source/scriptinterface/ScriptConversions.cpp
index d2ec1df494..66e86a5a8f 100644
--- a/source/scriptinterface/ScriptConversions.cpp
+++ b/source/scriptinterface/ScriptConversions.cpp
@@ -21,18 +21,19 @@
#include "ps/utf16string.h"
#include "ps/CLogger.h"
+#include "ps/CStr.h"
#include "js/jsapi.h"
#define FAIL(msg) STMT(JS_ReportError(cx, msg); return false)
// Implicit type conversions often hide bugs, so warn about them
-#define WARN_IF_NOT(c) STMT(if (!(c)) { JS_ReportWarning(cx, "Script value conversion check failed: %s", #c); })
+#define WARN_IF_NOT(c, v) STMT(if (!(c)) { JS_ReportWarning(cx, "Script value conversion check failed: %s (got type %s)", #c, JS_GetTypeName(cx, JS_TypeOfValue(cx, v))); })
template<> bool ScriptInterface::FromJSVal(JSContext* cx, jsval v, bool& out)
{
JSBool ret;
- WARN_IF_NOT(JSVAL_IS_BOOLEAN(v));
+ WARN_IF_NOT(JSVAL_IS_BOOLEAN(v), v);
if (!JS_ValueToBoolean(cx, v, &ret))
return false;
out = (ret ? true : false);
@@ -42,7 +43,7 @@ template<> bool ScriptInterface::FromJSVal(JSContext* cx, jsval v, bool& o
template<> bool ScriptInterface::FromJSVal(JSContext* cx, jsval v, float& out)
{
jsdouble ret;
- WARN_IF_NOT(JSVAL_IS_NUMBER(v));
+ WARN_IF_NOT(JSVAL_IS_NUMBER(v), v);
if (!JS_ValueToNumber(cx, v, &ret))
return false;
out = ret;
@@ -52,7 +53,7 @@ template<> bool ScriptInterface::FromJSVal(JSContext* cx, jsval v, float&
template<> bool ScriptInterface::FromJSVal(JSContext* cx, jsval v, double& out)
{
jsdouble ret;
- WARN_IF_NOT(JSVAL_IS_NUMBER(v));
+ WARN_IF_NOT(JSVAL_IS_NUMBER(v), v);
if (!JS_ValueToNumber(cx, v, &ret))
return false;
out = ret;
@@ -62,7 +63,7 @@ template<> bool ScriptInterface::FromJSVal(JSContext* cx, jsval v, doubl
template<> bool ScriptInterface::FromJSVal(JSContext* cx, jsval v, i32& out)
{
int32 ret;
- WARN_IF_NOT(JSVAL_IS_INT(v));
+ WARN_IF_NOT(JSVAL_IS_NUMBER(v), v);
if (!JS_ValueToECMAInt32(cx, v, &ret))
return false;
out = ret;
@@ -72,7 +73,7 @@ template<> bool ScriptInterface::FromJSVal(JSContext* cx, jsval v, i32& out
template<> bool ScriptInterface::FromJSVal(JSContext* cx, jsval v, u32& out)
{
uint32 ret;
- WARN_IF_NOT(JSVAL_IS_INT(v));
+ WARN_IF_NOT(JSVAL_IS_NUMBER(v), v);
if (!JS_ValueToECMAUint32(cx, v, &ret))
return false;
out = ret;
@@ -94,7 +95,7 @@ template<> bool ScriptInterface::FromJSVal(JSContext* cx, jsva
template<> bool ScriptInterface::FromJSVal(JSContext* cx, jsval v, std::wstring& out)
{
- WARN_IF_NOT(JSVAL_IS_STRING(v));
+ WARN_IF_NOT(JSVAL_IS_STRING(v) || JSVAL_IS_NUMBER(v), v); // allow implicit number conversions
JSString* ret = JS_ValueToString(cx, v);
if (!ret)
FAIL("Argument must be convertible to a string");
@@ -105,15 +106,15 @@ template<> bool ScriptInterface::FromJSVal(JSContext* cx, jsval v,
template<> bool ScriptInterface::FromJSVal(JSContext* cx, jsval v, std::string& out)
{
- WARN_IF_NOT(JSVAL_IS_STRING(v));
+ WARN_IF_NOT(JSVAL_IS_STRING(v) || JSVAL_IS_NUMBER(v), v); // allow implicit number conversions
JSString* ret = JS_ValueToString(cx, v);
if (!ret)
FAIL("Argument must be convertible to a string");
- char* ch = JS_GetStringBytes(ret);
+ char* ch = JS_EncodeString(cx, ret); // chops off high byte of each jschar
+ if (!ch)
+ FAIL("JS_EncodeString failed"); // out of memory
out = std::string(ch, ch + JS_GetStringLength(ret));
- // TODO: if JS_GetStringBytes fails it'll return a zero-length string
- // and we'll overflow its bounds by using JS_GetStringLength - should
- // use one of the new SpiderMonkey 1.8 functions instead
+ JS_free(cx, ch);
return true;
}
@@ -139,13 +140,10 @@ template<> jsval ScriptInterface::ToJSVal(JSContext* cx, const double& v
return rval;
}
-template<> jsval ScriptInterface::ToJSVal(JSContext* cx, const i32& val)
+template<> jsval ScriptInterface::ToJSVal(JSContext* UNUSED(cx), const i32& val)
{
- if (INT_FITS_IN_JSVAL(val))
- return INT_TO_JSVAL(val);
- jsval rval = JSVAL_VOID;
- JS_NewNumberValue(cx, val, &rval); // ignore return value
- return rval;
+ cassert(JSVAL_INT_BITS == 32);
+ return INT_TO_JSVAL(val);
}
template<> jsval ScriptInterface::ToJSVal(JSContext* cx, const u32& val)
@@ -185,6 +183,11 @@ template<> jsval ScriptInterface::ToJSVal(JSContext* cx, const std:
return JSVAL_VOID;
}
+template<> jsval ScriptInterface::ToJSVal(JSContext* cx, const wchar_t* const& val)
+{
+ return ToJSVal(cx, std::wstring(val));
+}
+
template<> jsval ScriptInterface::ToJSVal(JSContext* cx, const char* const& val)
{
JSString* str = JS_NewStringCopyZ(cx, val);
@@ -193,6 +196,16 @@ template<> jsval ScriptInterface::ToJSVal(JSContext* cx, const char
return JSVAL_VOID;
}
+template<> jsval ScriptInterface::ToJSVal(JSContext* cx, const CStrW& val)
+{
+ return ToJSVal(cx, static_cast(val));
+}
+
+template<> jsval ScriptInterface::ToJSVal(JSContext* cx, const CStr8& val)
+{
+ return ToJSVal(cx, static_cast(val));
+}
+
////////////////////////////////////////////////////////////////
// Compound types:
@@ -201,13 +214,11 @@ template static jsval ToJSVal_vector(JSContext* cx, const std::vecto
JSObject* obj = JS_NewArrayObject(cx, 0, NULL);
if (!obj)
return JSVAL_VOID;
- JS_AddRoot(cx, &obj);
for (size_t i = 0; i < val.size(); ++i)
{
jsval el = ScriptInterface::ToJSVal(cx, val[i]);
JS_SetElement(cx, obj, (jsint)i, &el);
}
- JS_RemoveRoot(cx, &obj);
return OBJECT_TO_JSVAL(obj);
}
diff --git a/source/scriptinterface/ScriptInterface.cpp b/source/scriptinterface/ScriptInterface.cpp
index 416de46c4c..25e9c6a5b8 100644
--- a/source/scriptinterface/ScriptInterface.cpp
+++ b/source/scriptinterface/ScriptInterface.cpp
@@ -40,7 +40,9 @@ const int RUNTIME_SIZE = 16 * 1024 * 1024; // TODO: how much memory is needed?
const int STACK_CHUNK_SIZE = 8192;
#if ENABLE_SCRIPT_PROFILING
-#include "js/jsdbgapi.h"
+# define signbit std::signbit
+# include "js/jsdbgapi.h"
+# undef signbit
#endif
////////////////////////////////////////////////////////////////
@@ -49,7 +51,7 @@ struct ScriptInterface_impl
{
ScriptInterface_impl(const char* nativeScopeName, JSContext* cx);
~ScriptInterface_impl();
- void Register(const char* name, JSFastNative fptr, uintN nargs);
+ void Register(const char* name, JSNative fptr, uintN nargs);
JSRuntime* m_rt; // NULL if m_cx is shared; non-NULL if we own m_cx
JSContext* m_cx;
@@ -109,7 +111,7 @@ void ErrorReporter(JSContext* cx, const char* message, JSErrorReport* report)
LOGERROR(L"%hs", msg.str().c_str());
// When running under Valgrind, print more information in the error message
- VALGRIND_PRINTF_BACKTRACE("->");
+// VALGRIND_PRINTF_BACKTRACE("->");
}
// Functions in the global namespace:
@@ -276,7 +278,11 @@ ScriptInterface_impl::ScriptInterface_impl(const char* nativeScopeName, JSContex
JS_SetOptions(m_cx, JSOPTION_STRICT // "warn on dubious practice"
| JSOPTION_XML // "ECMAScript for XML support: parse as a token"
| JSOPTION_VAROBJFIX // "recommended" (fixes variable scoping)
+
+ // Enable all the JIT features:
// | JSOPTION_JIT
+// | JSOPTION_METHODJIT
+// | JSOPTION_PROFILING
);
JS_SetVersion(m_cx, JSVERSION_LATEST);
@@ -286,7 +292,7 @@ ScriptInterface_impl::ScriptInterface_impl(const char* nativeScopeName, JSContex
// Threadsafe SpiderMonkey requires that we have a request before doing anything much
JS_BeginRequest(m_cx);
- m_glob = JS_NewObject(m_cx, &global_class, NULL, NULL);
+ m_glob = JS_NewGlobalObject(m_cx, &global_class);
ok = JS_InitStandardClasses(m_cx, m_glob);
JS_DefineProperty(m_cx, m_glob, "global", OBJECT_TO_JSVAL(m_glob), NULL, NULL, JSPROP_ENUMERATE | JSPROP_READONLY
@@ -296,10 +302,10 @@ ScriptInterface_impl::ScriptInterface_impl(const char* nativeScopeName, JSContex
m_nativeScope = JS_DefineObject(m_cx, m_glob, nativeScopeName, NULL, NULL, JSPROP_ENUMERATE | JSPROP_READONLY
| JSPROP_PERMANENT);
- JS_DefineFunction(m_cx, m_glob, "print", (JSNative)::print, 0, JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT | JSFUN_FAST_NATIVE);
- JS_DefineFunction(m_cx, m_glob, "log", (JSNative)::logmsg, 1, JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT | JSFUN_FAST_NATIVE);
- JS_DefineFunction(m_cx, m_glob, "warn", (JSNative)::warn, 1, JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT | JSFUN_FAST_NATIVE);
- JS_DefineFunction(m_cx, m_glob, "error", (JSNative)::error, 1, JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT | JSFUN_FAST_NATIVE);
+ JS_DefineFunction(m_cx, m_glob, "print", ::print, 0, JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT);
+ JS_DefineFunction(m_cx, m_glob, "log", ::logmsg, 1, JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT);
+ JS_DefineFunction(m_cx, m_glob, "warn", ::warn, 1, JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT);
+ JS_DefineFunction(m_cx, m_glob, "error", ::error, 1, JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT);
}
ScriptInterface_impl::~ScriptInterface_impl()
@@ -312,9 +318,9 @@ ScriptInterface_impl::~ScriptInterface_impl()
}
}
-void ScriptInterface_impl::Register(const char* name, JSFastNative fptr, uintN nargs)
+void ScriptInterface_impl::Register(const char* name, JSNative fptr, uintN nargs)
{
- JS_DefineFunction(m_cx, m_nativeScope, name, reinterpret_cast(fptr), nargs, JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT | JSFUN_FAST_NATIVE);
+ JS_DefineFunction(m_cx, m_nativeScope, name, fptr, nargs, JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT);
}
ScriptInterface::ScriptInterface(const char* nativeScopeName, const char* debugName) :
@@ -361,8 +367,8 @@ void ScriptInterface::ReplaceNondeterministicFunctions(boost::rand48& rng)
return;
}
- JSFunction* random = JS_DefineFunction(m->m_cx, JSVAL_TO_OBJECT(math), "random", (JSNative)Math_random, 0,
- JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT | JSFUN_FAST_NATIVE);
+ JSFunction* random = JS_DefineFunction(m->m_cx, JSVAL_TO_OBJECT(math), "random", Math_random, 0,
+ JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT);
if (!random)
{
LOGERROR(L"ReplaceNondeterministicFunctions: failed to replace Math.random");
@@ -372,7 +378,7 @@ void ScriptInterface::ReplaceNondeterministicFunctions(boost::rand48& rng)
JS_SetReservedSlot(m->m_cx, JS_GetFunctionObject(random), 0, PRIVATE_TO_JSVAL(&rng));
}
-void ScriptInterface::Register(const char* name, JSFastNative fptr, size_t nargs)
+void ScriptInterface::Register(const char* name, JSNative fptr, size_t nargs)
{
m->Register(name, fptr, (uintN)nargs);
}
@@ -387,16 +393,6 @@ JSRuntime* ScriptInterface::GetRuntime() const
return m->m_rt;
}
-bool ScriptInterface::AddRoot(void* ptr, const char* name)
-{
- return JS_AddNamedRoot(m->m_cx, ptr, name) ? true : false;
-}
-
-bool ScriptInterface::RemoveRoot(void* ptr)
-{
- return JS_RemoveRoot(m->m_cx, ptr) ? true : false;
-}
-
AutoGCRooter* ScriptInterface::ReplaceAutoGCRooter(AutoGCRooter* rooter)
{
debug_assert(m->m_rt); // this class must own the runtime, else the rooter won't work
@@ -405,30 +401,6 @@ AutoGCRooter* ScriptInterface::ReplaceAutoGCRooter(AutoGCRooter* rooter)
return ret;
}
-ScriptInterface::LocalRootScope::LocalRootScope(JSContext* cx) :
- m_cx(cx)
-{
- m_OK = JS_EnterLocalRootScope(m_cx) ? true : false;
-}
-
-ScriptInterface::LocalRootScope::~LocalRootScope()
-{
- if (m_OK)
- JS_LeaveLocalRootScope(m_cx);
-}
-
-bool ScriptInterface::LocalRootScope::OK()
-{
- return m_OK;
-}
-
-void ScriptInterface::LocalRootScope::LeaveWithResult(jsval val)
-{
- if (m_OK)
- JS_LeaveLocalRootScopeWithResult(m_cx, val);
- m_OK = false;
-}
-
jsval ScriptInterface::CallConstructor(jsval ctor)
{
@@ -494,19 +466,14 @@ bool ScriptInterface::CallFunction_(jsval val, const char* name, size_t argc, js
JSObject* obj;
if (!JS_ValueToObject(m->m_cx, val, &obj) || obj == NULL)
return false;
- JS_AddRoot(m->m_cx, &obj);
// Check that the named function actually exists, to avoid ugly JS error reports
// when calling an undefined value
JSBool found;
if (!JS_HasProperty(m->m_cx, obj, name, &found) || !found)
- {
- JS_RemoveRoot(m->m_cx, &obj);
return false;
- }
JSBool ok = JS_CallFunctionName(m->m_cx, obj, name, (uintN)argc, argv, &ret);
- JS_RemoveRoot(m->m_cx, &obj);
return ok ? true : false;
}
@@ -516,6 +483,11 @@ jsval ScriptInterface::GetGlobalObject()
return OBJECT_TO_JSVAL(JS_GetGlobalObject(m->m_cx));
}
+JSClass* ScriptInterface::GetGlobalClass()
+{
+ return &global_class;
+}
+
bool ScriptInterface::SetGlobal_(const char* name, jsval value, bool replace)
{
if (!replace)
@@ -577,8 +549,6 @@ bool ScriptInterface::HasProperty(jsval obj, const char* name)
bool ScriptInterface::EnumeratePropertyNamesWithPrefix(jsval obj, const char* prefix, std::vector& out)
{
- LOCAL_ROOT_SCOPE;
-
utf16string prefix16 (prefix, prefix+strlen(prefix));
if (! JSVAL_IS_OBJECT(obj))
@@ -638,10 +608,8 @@ bool ScriptInterface::LoadScript(const std::wstring& filename, const std::wstrin
if (!func)
return false;
- JS_AddRoot(m->m_cx, &func); // TODO: do we need to root this?
jsval scriptRval;
JSBool ok = JS_CallFunction(m->m_cx, NULL, func, 0, NULL, &scriptRval);
- JS_RemoveRoot(m->m_cx, &func);
return ok ? true : false;
}
@@ -687,7 +655,7 @@ CScriptValRooted ScriptInterface::ParseJSON(const utf16string& string)
return CScriptValRooted();
}
- if (!JS_ConsumeJSONText(m->m_cx, parser, string.c_str(), (uint32)string.size()))
+ if (!JS_ConsumeJSONText(m->m_cx, parser, reinterpret_cast(string.c_str()), (uint32)string.size()))
{
LOGERROR(L"ParseJSON failed to consume");
return CScriptValRooted();
@@ -786,7 +754,7 @@ class ValueCloner
{
public:
ValueCloner(ScriptInterface& from, ScriptInterface& to) :
- cxFrom(from.GetContext()), cxTo(to.GetContext()), m_RooterFrom(from), m_RooterTo(to)
+ scriptInterfaceFrom(from), cxFrom(from.GetContext()), cxTo(to.GetContext()), m_RooterFrom(from), m_RooterTo(to)
{
}
@@ -796,7 +764,7 @@ public:
if (!JSVAL_IS_GCTHING(val) || JSVAL_IS_NULL(val))
return val;
- std::map::iterator it = m_Mapping.find(val);
+ std::map::iterator it = m_Mapping.find(JSVAL_TO_GCTHING(val));
if (it != m_Mapping.end())
return it->second;
@@ -815,8 +783,7 @@ private:
if (JSVAL_IS_DOUBLE(val))
{
jsval rval;
- CLONE_REQUIRE(JS_NewNumberValue(cxTo, *JSVAL_TO_DOUBLE(val), &rval), L"JS_NewNumberValue");
- m_Mapping[val] = rval;
+ CLONE_REQUIRE(JS_NewNumberValue(cxTo, JSVAL_TO_DOUBLE(val), &rval), L"JS_NewNumberValue");
m_RooterTo.Push(rval);
return rval;
}
@@ -826,7 +793,7 @@ private:
JSString* str = JS_NewUCStringCopyN(cxTo, JS_GetStringChars(JSVAL_TO_STRING(val)), JS_GetStringLength(JSVAL_TO_STRING(val)));
CLONE_REQUIRE(str, L"JS_NewUCStringCopyN");
jsval rval = STRING_TO_JSVAL(str);
- m_Mapping[val] = rval;
+ m_Mapping[JSVAL_TO_GCTHING(val)] = rval;
m_RooterTo.Push(rval);
return rval;
}
@@ -847,17 +814,18 @@ private:
CLONE_REQUIRE(newObj, L"JS_NewObject");
}
- m_Mapping[val] = OBJECT_TO_JSVAL(newObj);
+ m_Mapping[JSVAL_TO_GCTHING(val)] = OBJECT_TO_JSVAL(newObj);
m_RooterTo.Push(newObj);
- JSIdArray* ida = JS_Enumerate(cxFrom, JSVAL_TO_OBJECT(val));
- CLONE_REQUIRE(ida, L"JS_Enumerate");
+ AutoJSIdArray ida (cxFrom, JS_Enumerate(cxFrom, JSVAL_TO_OBJECT(val)));
+ CLONE_REQUIRE(ida.get(), L"JS_Enumerate");
- IdArrayWrapper idaWrapper(cxFrom, ida);
+ AutoGCRooter idaRooter(scriptInterfaceFrom);
+ idaRooter.Push(ida.get());
- for (jsint i = 0; i < ida->length; ++i)
+ for (size_t i = 0; i < ida.length(); ++i)
{
- jsid id = ida->vector[i];
+ jsid id = ida[i];
jsval idval, propval;
CLONE_REQUIRE(JS_IdToValue(cxFrom, id, &idval), L"JS_IdToValue");
CLONE_REQUIRE(JS_GetPropertyById(cxFrom, JSVAL_TO_OBJECT(val), id, &propval), L"JS_GetPropertyById");
@@ -884,9 +852,10 @@ private:
return OBJECT_TO_JSVAL(newObj);
}
+ ScriptInterface& scriptInterfaceFrom;
JSContext* cxFrom;
JSContext* cxTo;
- std::map m_Mapping;
+ std::map m_Mapping;
AutoGCRooter m_RooterFrom;
AutoGCRooter m_RooterTo;
};
diff --git a/source/scriptinterface/ScriptInterface.h b/source/scriptinterface/ScriptInterface.h
index bcc24b0f18..fb99a61459 100644
--- a/source/scriptinterface/ScriptInterface.h
+++ b/source/scriptinterface/ScriptInterface.h
@@ -18,10 +18,6 @@
#ifndef INCLUDED_SCRIPTINTERFACE
#define INCLUDED_SCRIPTINTERFACE
-// XXX: This is largely copied from tools/atlas/AtlasScript
-// Duplication is bad - they should use a shared version of the common code,
-// and just add their own extensions individually
-
#include
#include
#include
@@ -144,6 +140,8 @@ public:
jsval GetGlobalObject();
+ JSClass* GetGlobalClass();
+
/**
* Set the named property on the global object.
* If @p replace is true, an existing property will be overwritten; otherwise attempts
@@ -223,9 +221,6 @@ public:
*/
template static jsval ToJSVal(JSContext* cx, T const& val);
- bool AddRoot(void* ptr, const char* name);
- bool RemoveRoot(void* ptr);
-
AutoGCRooter* ReplaceAutoGCRooter(AutoGCRooter* rooter);
/**
@@ -233,26 +228,6 @@ public:
*/
void DumpHeap();
- // Helper class for automatically rooting values
- class LocalRootScope
- {
- JSContext* m_cx;
- bool m_OK;
- public:
- // Tries to enter local root scope, so newly created
- // values won't be GCed. This might fail, so check OK()
- LocalRootScope(JSContext* cx);
- // Returns true if the local root scope was successfully entered
- bool OK();
- // Leaves the local root scope, but keeps the given return value rooted
- void LeaveWithResult(jsval val);
- // Leaves the local root scope
- ~LocalRootScope();
- private:
- LocalRootScope& operator=(const LocalRootScope&);
- };
-#define LOCAL_ROOT_SCOPE LocalRootScope scope(GetContext()); if (! scope.OK()) return false
-
void MaybeGC();
private:
@@ -266,7 +241,7 @@ private:
static JSClass* GetClass(JSContext* cx, JSObject* obj);
static void* GetPrivate(JSContext* cx, JSObject* obj);
- void Register(const char* name, JSFastNative fptr, size_t nargs);
+ void Register(const char* name, JSNative fptr, size_t nargs);
std::auto_ptr m;
// The nasty macro/template bits are split into a separate file so you don't have to look at them
@@ -278,10 +253,10 @@ public:
// void RegisterFunction(const char* functionName);
//
// template
- // static JSFastNative call;
+ // static JSNative call;
//
// template
- // static JSFastNative callMethod;
+ // static JSNative callMethod;
//
// template
// static size_t nargs();
@@ -293,7 +268,6 @@ public:
template
bool ScriptInterface::CallFunction(jsval val, const char* name, R& ret)
{
- LOCAL_ROOT_SCOPE;
jsval jsRet;
bool ok = CallFunction_(val, name, 0, NULL, jsRet);
if (!ok)
@@ -304,7 +278,6 @@ bool ScriptInterface::CallFunction(jsval val, const char* name, R& ret)
template
bool ScriptInterface::CallFunctionVoid(jsval val, const char* name, const T0& a0)
{
- LOCAL_ROOT_SCOPE;
jsval jsRet;
jsval argv[1];
argv[0] = ToJSVal(GetContext(), a0);
@@ -314,7 +287,6 @@ bool ScriptInterface::CallFunctionVoid(jsval val, const char* name, const T0& a0
template
bool ScriptInterface::CallFunctionVoid(jsval val, const char* name, const T0& a0, const T1& a1)
{
- LOCAL_ROOT_SCOPE;
jsval jsRet;
jsval argv[2];
argv[0] = ToJSVal(GetContext(), a0);
@@ -325,7 +297,6 @@ bool ScriptInterface::CallFunctionVoid(jsval val, const char* name, const T0& a0
template
bool ScriptInterface::CallFunctionVoid(jsval val, const char* name, const T0& a0, const T1& a1, const T2& a2)
{
- LOCAL_ROOT_SCOPE;
jsval jsRet;
jsval argv[3];
argv[0] = ToJSVal(GetContext(), a0);
@@ -337,7 +308,6 @@ bool ScriptInterface::CallFunctionVoid(jsval val, const char* name, const T0& a0
template
bool ScriptInterface::CallFunction(jsval val, const char* name, const T0& a0, R& ret)
{
- LOCAL_ROOT_SCOPE;
jsval jsRet;
jsval argv[1];
argv[0] = ToJSVal(GetContext(), a0);
@@ -350,7 +320,6 @@ bool ScriptInterface::CallFunction(jsval val, const char* name, const T0& a0, R&
template
bool ScriptInterface::CallFunction(jsval val, const char* name, const T0& a0, const T1& a1, R& ret)
{
- LOCAL_ROOT_SCOPE;
jsval jsRet;
jsval argv[2];
argv[0] = ToJSVal(GetContext(), a0);
@@ -364,7 +333,6 @@ bool ScriptInterface::CallFunction(jsval val, const char* name, const T0& a0, co
template
bool ScriptInterface::CallFunction(jsval val, const char* name, const T0& a0, const T1& a1, const T2& a2, R& ret)
{
- LOCAL_ROOT_SCOPE;
jsval jsRet;
jsval argv[3];
argv[0] = ToJSVal(GetContext(), a0);
@@ -379,14 +347,12 @@ bool ScriptInterface::CallFunction(jsval val, const char* name, const T0& a0, co
template
bool ScriptInterface::SetGlobal(const char* name, const T& value, bool replace)
{
- LOCAL_ROOT_SCOPE;
return SetGlobal_(name, ToJSVal(GetContext(), value), replace);
}
template
bool ScriptInterface::SetProperty(jsval obj, const char* name, const T& value, bool readonly)
{
- LOCAL_ROOT_SCOPE;
return SetProperty_(obj, name, ToJSVal(GetContext(), value), readonly);
}
diff --git a/source/scriptinterface/ScriptTypes.h b/source/scriptinterface/ScriptTypes.h
index e29ce40087..c73f8a9119 100644
--- a/source/scriptinterface/ScriptTypes.h
+++ b/source/scriptinterface/ScriptTypes.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2009 Wildfire Games.
+/* Copyright (C) 2010 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@@ -20,13 +20,19 @@
#ifdef _WIN32
# define XP_WIN
+# define WIN32 // SpiderMonkey expects this
+
+// The jsval struct type causes crashes due to weird miscompilation
+// issues in (at least) VC2008, so force it to be the less-type-safe
+// non-struct type instead
+# define JS_NO_JSVAL_JSID_STRUCT_TYPES
+
#else
# define XP_UNIX
#endif
// (we don't support XP_OS2 or XP_BEOS)
-#include "js/jspubtd.h"
-#include "js/jsversion.h"
+#include "js/jsapi.h"
#if JS_VERSION != 185
#error Your compiler is trying to use an incorrect version of the SpiderMonkey library.
diff --git a/source/scriptinterface/ScriptVal.cpp b/source/scriptinterface/ScriptVal.cpp
index b62ce51a75..00fa704395 100644
--- a/source/scriptinterface/ScriptVal.cpp
+++ b/source/scriptinterface/ScriptVal.cpp
@@ -1,4 +1,4 @@
-/* Copyright (C) 2009 Wildfire Games.
+/* Copyright (C) 2010 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@@ -24,21 +24,21 @@
struct Unrooter
{
Unrooter(JSContext* cx) : cx(cx) { }
- void operator()(jsval* p) { JS_RemoveRoot(cx, p); delete p; }
+ void operator()(jsval* p) { JS_RemoveValueRoot(cx, p); delete p; }
JSContext* cx;
};
CScriptValRooted::CScriptValRooted(JSContext* cx, jsval val)
{
jsval* p = new jsval(val);
- JS_AddNamedRoot(cx, p, "CScriptValRooted");
+ JS_AddNamedValueRoot(cx, p, "CScriptValRooted");
m_Val = boost::shared_ptr(p, Unrooter(cx));
}
CScriptValRooted::CScriptValRooted(JSContext* cx, CScriptVal val)
{
jsval* p = new jsval(val.get());
- JS_AddNamedRoot(cx, p, "CScriptValRooted");
+ JS_AddNamedValueRoot(cx, p, "CScriptValRooted");
m_Val = boost::shared_ptr(p, Unrooter(cx));
}
@@ -49,12 +49,47 @@ jsval CScriptValRooted::get() const
return *m_Val;
}
+jsval& CScriptValRooted::getRef() const
+{
+ debug_assert(m_Val);
+ return *m_Val;
+}
+
bool CScriptValRooted::undefined() const
{
- return (!m_Val || *m_Val == JSVAL_VOID);
+ return (!m_Val || JSVAL_IS_VOID(*m_Val));
}
bool CScriptValRooted::uninitialised() const
{
return !m_Val;
}
+
+AutoJSIdArray::AutoJSIdArray(JSContext* cx, JSIdArray* ida) :
+ m_Context(cx), m_IdArray(ida)
+{
+}
+
+AutoJSIdArray::~AutoJSIdArray()
+{
+ if (m_IdArray)
+ JS_DestroyIdArray(m_Context, m_IdArray);
+}
+
+JSIdArray* AutoJSIdArray::get() const
+{
+ return m_IdArray;
+}
+
+size_t AutoJSIdArray::length() const
+{
+ debug_assert(m_IdArray);
+ return m_IdArray->length;
+}
+
+jsid AutoJSIdArray::operator[](size_t i) const
+{
+ debug_assert(m_IdArray);
+ debug_assert(i < (size_t)m_IdArray->length);
+ return m_IdArray->vector[i];
+}
diff --git a/source/scriptinterface/ScriptVal.h b/source/scriptinterface/ScriptVal.h
index 8a7c3b8222..5ac1e452c3 100644
--- a/source/scriptinterface/ScriptVal.h
+++ b/source/scriptinterface/ScriptVal.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2009 Wildfire Games.
+/* Copyright (C) 2010 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@@ -29,10 +29,10 @@
class CScriptVal
{
public:
- CScriptVal() : m_Val(0) { }
+ CScriptVal() : m_Val(JSVAL_VOID) { }
CScriptVal(jsval val) : m_Val(val) { }
- jsval get() const { return m_Val; }
+ const jsval& get() const { return m_Val; }
private:
jsval m_Val;
@@ -45,14 +45,48 @@ public:
CScriptValRooted(JSContext* cx, jsval val);
CScriptValRooted(JSContext* cx, CScriptVal val);
+ /**
+ * Returns the current value (or JSVAL_VOID if uninitialised).
+ */
jsval get() const;
+ /**
+ * Returns reference to the current value.
+ * Fails if the value is not yet initialised.
+ */
+ jsval& getRef() const;
+
+ /**
+ * Returns whether the value is uninitialised or is JSVAL_VOID.
+ */
bool undefined() const;
+ /**
+ * Returns whether the value is uninitialised.
+ */
bool uninitialised() const;
private:
boost::shared_ptr m_Val;
};
+/**
+ * RAII wrapper for JSIdArray*
+ */
+class AutoJSIdArray
+{
+ NONCOPYABLE(AutoJSIdArray);
+public:
+ AutoJSIdArray(JSContext* cx, JSIdArray* ida);
+ ~AutoJSIdArray();
+
+ JSIdArray* get() const;
+ size_t length() const;
+ jsid operator[](size_t i) const;
+
+private:
+ JSContext* m_Context;
+ JSIdArray* m_IdArray;
+};
+
#endif // INCLUDED_SCRIPTVAL
diff --git a/source/scriptinterface/tests/test_ScriptConversions.h b/source/scriptinterface/tests/test_ScriptConversions.h
index a9154f9e45..3d2827d8a0 100644
--- a/source/scriptinterface/tests/test_ScriptConversions.h
+++ b/source/scriptinterface/tests/test_ScriptConversions.h
@@ -34,7 +34,6 @@ class TestScriptConversions : public CxxTest::TestSuite
JSContext* cx = script.GetContext();
jsval v1 = ScriptInterface::ToJSVal(cx, value);
- JS_AddRoot(cx, &v1);
// We want to convert values to strings, but can't just call toSource() on them
// since they might not be objects. So just use uneval.
@@ -42,8 +41,6 @@ class TestScriptConversions : public CxxTest::TestSuite
TS_ASSERT(script.CallFunction(OBJECT_TO_JSVAL(JS_GetGlobalObject(cx)), "uneval", CScriptVal(v1), source));
TS_ASSERT_STR_EQUALS(source, expected);
-
- JS_RemoveRoot(cx, &v1);
}
template
@@ -53,7 +50,6 @@ class TestScriptConversions : public CxxTest::TestSuite
JSContext* cx = script.GetContext();
jsval v1 = ScriptInterface::ToJSVal(cx, value);
- JS_AddRoot(cx, &v1);
std::string source;
TS_ASSERT(script.CallFunction(OBJECT_TO_JSVAL(JS_GetGlobalObject(cx)), "uneval", CScriptVal(v1), source));
@@ -64,8 +60,6 @@ class TestScriptConversions : public CxxTest::TestSuite
T v2 = T();
TS_ASSERT(ScriptInterface::FromJSVal(script.GetContext(), v1, v2));
TS_ASSERT_EQUALS(value, v2);
-
- JS_RemoveRoot(cx, &v1);
}
public:
@@ -132,18 +126,16 @@ public:
TS_ASSERT(JSVAL_IS_INT(ScriptInterface::ToJSVal(cx, 0)));
- TS_ASSERT(JSVAL_IS_INT(ScriptInterface::ToJSVal(cx, 1073741822))); // JSVAL_INT_MAX-1
- TS_ASSERT(JSVAL_IS_INT(ScriptInterface::ToJSVal(cx, 1073741823))); // JSVAL_INT_MAX
- TS_ASSERT(JSVAL_IS_DOUBLE(ScriptInterface::ToJSVal(cx, 1073741824))); // JSVAL_INT_MAX+1
- TS_ASSERT(JSVAL_IS_INT(ScriptInterface::ToJSVal(cx, -1073741823))); // JSVAL_INT_MIN+1
- TS_ASSERT(JSVAL_IS_INT(ScriptInterface::ToJSVal(cx, -1073741824))); // JSVAL_INT_MIN
- TS_ASSERT(JSVAL_IS_DOUBLE(ScriptInterface::ToJSVal(cx, -1073741825))); // JSVAL_INT_MIN-1
+ TS_ASSERT(JSVAL_IS_INT(ScriptInterface::ToJSVal(cx, 2147483646))); // JSVAL_INT_MAX-1
+ TS_ASSERT(JSVAL_IS_INT(ScriptInterface::ToJSVal(cx, 2147483647))); // JSVAL_INT_MAX
+ TS_ASSERT(JSVAL_IS_INT(ScriptInterface::ToJSVal(cx, -2147483647))); // JSVAL_INT_MIN+1
+ TS_ASSERT(JSVAL_IS_INT(ScriptInterface::ToJSVal(cx, -(i64)2147483648))); // JSVAL_INT_MIN
TS_ASSERT(JSVAL_IS_INT(ScriptInterface::ToJSVal(cx, 0)));
- TS_ASSERT(JSVAL_IS_INT(ScriptInterface::ToJSVal(cx, 1073741822))); // JSVAL_INT_MAX-1
- TS_ASSERT(JSVAL_IS_INT(ScriptInterface::ToJSVal(cx, 1073741823))); // JSVAL_INT_MAX
- TS_ASSERT(JSVAL_IS_DOUBLE(ScriptInterface::ToJSVal(cx, 1073741824))); // JSVAL_INT_MAX+1
+ TS_ASSERT(JSVAL_IS_INT(ScriptInterface::ToJSVal(cx, 2147483646))); // JSVAL_INT_MAX-1
+ TS_ASSERT(JSVAL_IS_INT(ScriptInterface::ToJSVal(cx, 2147483647))); // JSVAL_INT_MAX
+ TS_ASSERT(JSVAL_IS_DOUBLE(ScriptInterface::ToJSVal(cx, 2147483648))); // JSVAL_INT_MAX+1
}
void test_nonfinite()
diff --git a/source/scriptinterface/tests/test_ScriptInterface.h b/source/scriptinterface/tests/test_ScriptInterface.h
index ff8b71f9ce..4008631390 100644
--- a/source/scriptinterface/tests/test_ScriptInterface.h
+++ b/source/scriptinterface/tests/test_ScriptInterface.h
@@ -136,7 +136,7 @@ public:
TS_ASSERT(script.Eval(input.c_str(), val));
std::string stringified = script.StringifyJSON(val.get());
- TS_ASSERT_STR_EQUALS(stringified, "{\n \"x\":1,\n \"z\":[2,\n \"3\xE2\x98\xBA\xEF\xBF\xBD\"\n ],\n \"y\":true\n}");
+ TS_ASSERT_STR_EQUALS(stringified, "{\n \"x\": 1,\n \"z\": [\n 2,\n \"3\xE2\x98\xBA\xEF\xBF\xBD\"\n ],\n \"y\": true\n}");
val = script.ParseJSON(stringified);
TS_ASSERT_WSTR_EQUALS(script.ToString(val.get()), L"({x:1, z:[2, \"3\\u263A\\uFFFD\"], y:true})");
diff --git a/source/simulation2/components/ICmpFootprint.cpp b/source/simulation2/components/ICmpFootprint.cpp
index 9e09dbe860..056c810965 100644
--- a/source/simulation2/components/ICmpFootprint.cpp
+++ b/source/simulation2/components/ICmpFootprint.cpp
@@ -32,10 +32,6 @@ CScriptVal ICmpFootprint::GetShape_wrapper()
JSContext* cx = GetSimContext().GetScriptInterface().GetContext();
- ScriptInterface::LocalRootScope scope(cx);
- if (!scope.OK())
- return JSVAL_VOID;
-
JSObject* obj = JS_NewObject(cx, NULL, NULL, NULL);
if (!obj)
return JSVAL_VOID;
diff --git a/source/simulation2/scripting/EngineScriptConversions.cpp b/source/simulation2/scripting/EngineScriptConversions.cpp
index f06db98b34..3d523e82b1 100644
--- a/source/simulation2/scripting/EngineScriptConversions.cpp
+++ b/source/simulation2/scripting/EngineScriptConversions.cpp
@@ -37,7 +37,7 @@ template<> jsval ScriptInterface::ToJSVal(JSContext* cx, IComponent
// If this is a scripted component, just return the JS object directly
jsval instance = val->GetJSInstance();
- if (instance)
+ if (!JSVAL_IS_NULL(instance))
return instance;
// Otherwise we need to construct a wrapper object
@@ -72,7 +72,7 @@ static jsval ConvertCParamNode(JSContext* cx, CParamNode const& val)
// Just a string
utf16string text(val.ToString().begin(), val.ToString().end());
- JSString* str = JS_InternUCStringN(cx, text.data(), text.length());
+ JSString* str = JS_InternUCStringN(cx, reinterpret_cast(text.data()), text.length());
if (str)
return STRING_TO_JSVAL(str);
// TODO: report error
@@ -97,7 +97,7 @@ static jsval ConvertCParamNode(JSContext* cx, CParamNode const& val)
if (!val.ToString().empty())
{
utf16string text(val.ToString().begin(), val.ToString().end());
- JSString* str = JS_InternUCStringN(cx, text.data(), text.length());
+ JSString* str = JS_InternUCStringN(cx, reinterpret_cast(text.data()), text.length());
if (!str)
return JSVAL_VOID; // TODO: report error
jsval childVal = STRING_TO_JSVAL(str);
@@ -135,10 +135,6 @@ template<> jsval ScriptInterface::ToJSVal(JSContext* cx, cons
template<> bool ScriptInterface::FromJSVal(JSContext* cx, jsval v, CColor& out)
{
- ScriptInterface::LocalRootScope scope(cx);
- if (!scope.OK())
- return false;
-
if (!JSVAL_IS_OBJECT(v))
return false; // TODO: report type error
JSObject* obj = JSVAL_TO_OBJECT(v);
@@ -160,10 +156,6 @@ template<> bool ScriptInterface::FromJSVal(JSContext* cx, jsval v, CColo
template<> jsval ScriptInterface::ToJSVal(JSContext* cx, CColor const& val)
{
- ScriptInterface::LocalRootScope scope(cx);
- if (!scope.OK())
- return JSVAL_VOID;
-
JSObject* obj = JS_NewObject(cx, NULL, NULL, NULL);
if (!obj)
return JSVAL_VOID;
@@ -201,10 +193,6 @@ template<> jsval ScriptInterface::ToJSVal(JSContext* cx, const fixed& val
template<> bool ScriptInterface::FromJSVal(JSContext* cx, jsval v, CFixedVector3D& out)
{
- ScriptInterface::LocalRootScope scope(cx);
- if (!scope.OK())
- return false;
-
if (!JSVAL_IS_OBJECT(v))
return false; // TODO: report type error
JSObject* obj = JSVAL_TO_OBJECT(v);
@@ -225,10 +213,6 @@ template<> bool ScriptInterface::FromJSVal(JSContext* cx, jsval
template<> jsval ScriptInterface::ToJSVal(JSContext* cx, const CFixedVector3D& val)
{
- ScriptInterface::LocalRootScope scope(cx);
- if (!scope.OK())
- return JSVAL_VOID;
-
JSObject* obj = JS_NewObject(cx, NULL, NULL, NULL);
if (!obj)
return JSVAL_VOID;
@@ -246,10 +230,6 @@ template<> jsval ScriptInterface::ToJSVal(JSContext* cx, const C
template<> bool ScriptInterface::FromJSVal(JSContext* cx, jsval v, CFixedVector2D& out)
{
- ScriptInterface::LocalRootScope scope(cx);
- if (!scope.OK())
- return false;
-
if (!JSVAL_IS_OBJECT(v))
return false; // TODO: report type error
JSObject* obj = JSVAL_TO_OBJECT(v);
diff --git a/source/simulation2/scripting/MessageTypeConversions.cpp b/source/simulation2/scripting/MessageTypeConversions.cpp
index e9f31d650c..8491ceb34d 100644
--- a/source/simulation2/scripting/MessageTypeConversions.cpp
+++ b/source/simulation2/scripting/MessageTypeConversions.cpp
@@ -23,9 +23,6 @@
#include "js/jsapi.h"
#define TOJSVAL_SETUP() \
- ScriptInterface::LocalRootScope scope(scriptInterface.GetContext()); \
- if (! scope.OK()) \
- return JSVAL_VOID; \
JSObject* obj = JS_NewObject(scriptInterface.GetContext(), NULL, NULL, NULL); \
if (! obj) \
return JSVAL_VOID
diff --git a/source/simulation2/scripting/ScriptComponent.cpp b/source/simulation2/scripting/ScriptComponent.cpp
index fe957a40a3..246a42acc5 100644
--- a/source/simulation2/scripting/ScriptComponent.cpp
+++ b/source/simulation2/scripting/ScriptComponent.cpp
@@ -23,30 +23,22 @@
#include "simulation2/serialization/IDeserializer.h"
CComponentTypeScript::CComponentTypeScript(ScriptInterface& scriptInterface, jsval instance) :
- m_ScriptInterface(scriptInterface), m_Instance(instance)
+ m_ScriptInterface(scriptInterface), m_Instance(CScriptValRooted(scriptInterface.GetContext(), instance))
{
- debug_assert(instance);
- m_ScriptInterface.AddRoot(&m_Instance, "CComponentTypeScript.m_Instance");
-
// Cache the property detection for efficiency
- m_HasCustomSerialize = m_ScriptInterface.HasProperty(m_Instance, "Serialize");
-}
-
-CComponentTypeScript::~CComponentTypeScript()
-{
- m_ScriptInterface.RemoveRoot(&m_Instance);
+ m_HasCustomSerialize = m_ScriptInterface.HasProperty(m_Instance.get(), "Serialize");
}
void CComponentTypeScript::Init(const CSimContext& UNUSED(context), const CParamNode& paramNode, entity_id_t ent)
{
- m_ScriptInterface.SetProperty(m_Instance, "entity", (int)ent, true);
- m_ScriptInterface.SetProperty(m_Instance, "template", paramNode, true);
- m_ScriptInterface.CallFunctionVoid(m_Instance, "Init");
+ m_ScriptInterface.SetProperty(m_Instance.get(), "entity", (int)ent, true);
+ m_ScriptInterface.SetProperty(m_Instance.get(), "template", paramNode, true);
+ m_ScriptInterface.CallFunctionVoid(m_Instance.get(), "Init");
}
void CComponentTypeScript::Deinit(const CSimContext& UNUSED(context))
{
- m_ScriptInterface.CallFunctionVoid(m_Instance, "Deinit");
+ m_ScriptInterface.CallFunctionVoid(m_Instance.get(), "Deinit");
}
void CComponentTypeScript::HandleMessage(const CSimContext& UNUSED(context), const CMessage& msg, bool global)
@@ -55,7 +47,7 @@ void CComponentTypeScript::HandleMessage(const CSimContext& UNUSED(context), con
CScriptVal msgVal = msg.ToJSValCached(m_ScriptInterface);
- if (!m_ScriptInterface.CallFunctionVoid(m_Instance, name, msgVal))
+ if (!m_ScriptInterface.CallFunctionVoid(m_Instance.get(), name, msgVal))
LOGERROR(L"Script message handler %hs failed", name);
}
@@ -66,13 +58,13 @@ void CComponentTypeScript::Serialize(ISerializer& serialize)
if (m_HasCustomSerialize)
{
CScriptValRooted val;
- if (!m_ScriptInterface.CallFunction(m_Instance, "Serialize", val))
+ if (!m_ScriptInterface.CallFunction(m_Instance.get(), "Serialize", val))
LOGERROR(L"Script Serialize call failed");
serialize.ScriptVal("object", val);
}
else
{
- serialize.ScriptVal("object", m_Instance);
+ serialize.ScriptVal("object", m_Instance.get());
}
}
@@ -82,8 +74,8 @@ void CComponentTypeScript::Deserialize(const CSimContext& UNUSED(context), const
// Use ScriptObjectAppend so we don't lose the carefully-constructed
// prototype/parent of this object
- deserialize.ScriptObjectAppend("object", m_Instance);
+ deserialize.ScriptObjectAppend("object", m_Instance.getRef());
- m_ScriptInterface.SetProperty(m_Instance, "entity", (int)ent, true);
- m_ScriptInterface.SetProperty(m_Instance, "template", paramNode, true);
+ m_ScriptInterface.SetProperty(m_Instance.get(), "entity", (int)ent, true);
+ m_ScriptInterface.SetProperty(m_Instance.get(), "template", paramNode, true);
}
diff --git a/source/simulation2/scripting/ScriptComponent.h b/source/simulation2/scripting/ScriptComponent.h
index 4ebac2affd..e7e45f1ec8 100644
--- a/source/simulation2/scripting/ScriptComponent.h
+++ b/source/simulation2/scripting/ScriptComponent.h
@@ -35,9 +35,8 @@ class CComponentTypeScript
{
public:
CComponentTypeScript(ScriptInterface& scriptInterface, jsval instance);
- ~CComponentTypeScript();
- jsval GetInstance() const { return m_Instance; }
+ jsval GetInstance() const { return m_Instance.get(); }
void Init(const CSimContext& context, const CParamNode& paramNode, entity_id_t ent);
void Deinit(const CSimContext& context);
@@ -58,7 +57,7 @@ public:
R Call(const char* funcname BOOST_PP_ENUM_TRAILING_BINARY_PARAMS(i, const T, &a)) \
{ \
R ret; \
- if (m_ScriptInterface.CallFunction(m_Instance, funcname BOOST_PP_ENUM_TRAILING_PARAMS(i, a), ret)) \
+ if (m_ScriptInterface.CallFunction(m_Instance.get(), funcname BOOST_PP_ENUM_TRAILING_PARAMS(i, a), ret)) \
return ret; \
LOGERROR(L"Error calling component script function %hs", funcname); \
return R(); \
@@ -66,7 +65,7 @@ public:
BOOST_PP_IF(i, template<, ) BOOST_PP_ENUM_PARAMS(i, typename T) BOOST_PP_IF(i, >, ) \
void CallVoid(const char* funcname BOOST_PP_ENUM_TRAILING_BINARY_PARAMS(i, const T, &a)) \
{ \
- if (m_ScriptInterface.CallFunctionVoid(m_Instance, funcname BOOST_PP_ENUM_TRAILING_PARAMS(i, a))) \
+ if (m_ScriptInterface.CallFunctionVoid(m_Instance.get(), funcname BOOST_PP_ENUM_TRAILING_PARAMS(i, a))) \
return; \
LOGERROR(L"Error calling component script function %hs", funcname); \
}
@@ -75,7 +74,7 @@ BOOST_PP_REPEAT(SCRIPT_INTERFACE_MAX_ARGS, OVERLOADS, ~)
private:
ScriptInterface& m_ScriptInterface;
- jsval m_Instance;
+ CScriptValRooted m_Instance;
bool m_HasCustomSerialize;
NONCOPYABLE(CComponentTypeScript);
diff --git a/source/simulation2/serialization/BinarySerializer.cpp b/source/simulation2/serialization/BinarySerializer.cpp
index 1a2426f62a..62921d63b3 100644
--- a/source/simulation2/serialization/BinarySerializer.cpp
+++ b/source/simulation2/serialization/BinarySerializer.cpp
@@ -25,18 +25,9 @@
#include "scriptinterface/ScriptInterface.h"
-// Shut up some warnings triggered by jsobj.h
-#if MSC_VERSION
-# pragma warning(push)
-# pragma warning(disable:4512) // assignment operator could not be generated
-# pragma warning(disable:4800) // forcing value to bool 'true' or 'false' (performance warning)
-#endif
-
-#include "js/jsobj.h"
-
-#if MSC_VERSION
-# pragma warning(pop)
-#endif
+#define signbit std::signbit
+#include "js/jsvalue.h" // for JSDOUBLE_IS_INT32
+#undef signbit
CBinarySerializerScriptImpl::CBinarySerializerScriptImpl(ScriptInterface& scriptInterface, ISerializer& serializer) :
m_ScriptInterface(scriptInterface), m_Serializer(serializer), m_Rooter(m_ScriptInterface),
@@ -100,43 +91,18 @@ void CBinarySerializerScriptImpl::HandleScriptVal(jsval val)
// Find all properties (ordered by insertion time)
- // JS_Enumerate is a bit slow (lots of memory allocation), so do the enumeration manually
- // (based on the code from JS_Enumerate, using the probably less stable JSObject API):
- //
- // Correction: Actually array_enumerate returns an incorrect num_properties so we can't
- // trust it and have to iterate over all ids before we know how many there are, so
- // actually this probably isn't any faster than JS_Enumerate. Also it's less compatible
- // with future JSAPI updates. This probably wasn't a great idea.
-
// (Note that we don't do any rooting, because we assume nothing is going to trigger GC.
// I'm not absolute certain that's necessarily a valid assumption.)
- jsval iter_state, num_properties;
- if (!obj->enumerate(cx, JSENUMERATE_INIT, &iter_state, &num_properties))
- throw PSERROR_Serialize_ScriptError("enumerate INIT failed");
- debug_assert(JSVAL_IS_INT(num_properties));
- debug_assert(JSVAL_TO_INT(num_properties) >= 0);
+ AutoJSIdArray ida (cx, JS_Enumerate(cx, obj));
+ if (!ida.get())
+ throw PSERROR_Serialize_ScriptError("JS_Enumerate failed");
- std::vector ids;
- ids.reserve(JSVAL_TO_INT(num_properties));
+ m_Serializer.NumberU32_Unbounded("num props", (uint32_t)ida.length());
- while (true)
+ for (size_t i = 0; i < ida.length(); ++i)
{
- jsval id;
- if (!obj->enumerate(cx, JSENUMERATE_NEXT, &iter_state, &id))
- throw PSERROR_Serialize_ScriptError("enumerate NEXT failed");
-
- if (JSVAL_IS_NULL(iter_state))
- break;
-
- ids.push_back(id);
- }
-
- m_Serializer.NumberU32_Unbounded("num props", (uint32_t)ids.size());
-
- for (size_t i = 0; i < ids.size(); ++i)
- {
- jsval id = ids[i];
+ jsid id = ida[i];
jsval idval, propval;
@@ -176,15 +142,26 @@ void CBinarySerializerScriptImpl::HandleScriptVal(jsval val)
if (JSVAL_IS_INT(val))
{
m_Serializer.NumberU8_Unbounded("type", SCRIPT_TYPE_INT);
- // jsvals are limited to JSVAL_INT_BITS == 31 bits, even on 64-bit platforms
- m_Serializer.NumberI32("value", (int32_t)JSVAL_TO_INT(val), JSVAL_INT_MIN, JSVAL_INT_MAX);
+ m_Serializer.NumberI32_Unbounded("value", (int32_t)JSVAL_TO_INT(val));
}
else
{
debug_assert(JSVAL_IS_DOUBLE(val));
- m_Serializer.NumberU8_Unbounded("type", SCRIPT_TYPE_DOUBLE);
- jsdouble* dbl = JSVAL_TO_DOUBLE(val);
- m_Serializer.NumberDouble_Unbounded("value", *dbl);
+
+ // If the value fits in an int, serialise as an int
+ jsdouble d = JSVAL_TO_DOUBLE(val);
+ int32_t i;
+ if (JSDOUBLE_IS_INT32(d, &i))
+ {
+ m_Serializer.NumberU8_Unbounded("type", SCRIPT_TYPE_INT);
+ m_Serializer.NumberI32_Unbounded("value", i);
+ }
+ // Otherwise serialise as a double
+ else
+ {
+ m_Serializer.NumberU8_Unbounded("type", SCRIPT_TYPE_DOUBLE);
+ m_Serializer.NumberDouble_Unbounded("value", d);
+ }
}
break;
}
diff --git a/source/simulation2/serialization/StdDeserializer.cpp b/source/simulation2/serialization/StdDeserializer.cpp
index 43b2844130..aafe20e5aa 100644
--- a/source/simulation2/serialization/StdDeserializer.cpp
+++ b/source/simulation2/serialization/StdDeserializer.cpp
@@ -46,7 +46,7 @@ void CStdDeserializer::AddScriptBackref(JSObject* obj)
{
std::pair::iterator, bool> it = m_ScriptBackrefs.insert(std::make_pair((u32)m_ScriptBackrefs.size()+1, obj));
debug_assert(it.second);
- if (!JS_AddRoot(m_ScriptInterface.GetContext(), (void*)&it.first->second))
+ if (!JS_AddObjectRoot(m_ScriptInterface.GetContext(), &it.first->second))
throw PSERROR_Deserialize_ScriptError("JS_AddRoot failed");
}
@@ -63,7 +63,7 @@ void CStdDeserializer::FreeScriptBackrefs()
std::map::iterator it = m_ScriptBackrefs.begin();
for (; it != m_ScriptBackrefs.end(); ++it)
{
- if (!JS_RemoveRoot(m_ScriptInterface.GetContext(), (void*)&it->second))
+ if (!JS_RemoveObjectRoot(m_ScriptInterface.GetContext(), &it->second))
throw PSERROR_Deserialize_ScriptError("JS_RemoveRoot failed");
}
m_ScriptBackrefs.clear();
diff --git a/source/simulation2/system/ComponentManager.cpp b/source/simulation2/system/ComponentManager.cpp
index c677bd9313..3ce162f52e 100644
--- a/source/simulation2/system/ComponentManager.cpp
+++ b/source/simulation2/system/ComponentManager.cpp
@@ -100,12 +100,6 @@ CComponentManager::CComponentManager(CSimContext& context, bool skipScriptFuncti
CComponentManager::~CComponentManager()
{
ResetState();
-
- // Release GC roots
- std::map::iterator it = m_ComponentTypesById.begin();
- for (; it != m_ComponentTypesById.end(); ++it)
- if (it->second.type == CT_Script)
- m_ScriptInterface.RemoveRoot(&it->second.ctor);
}
void CComponentManager::LoadComponentTypes()
@@ -194,10 +188,7 @@ void CComponentManager::Script_RegisterComponentType(void* cbdata, int iid, std:
}
}
- // Clean up the old component type
- componentManager->m_ScriptInterface.RemoveRoot(&componentManager->m_ComponentTypesById[cid].ctor);
-
- // Remove its old message subscriptions
+ // Remove the old component type's message subscriptions
std::map >::iterator it;
for (it = componentManager->m_LocalMessageSubscriptions.begin(); it != componentManager->m_LocalMessageSubscriptions.end(); ++it)
{
@@ -228,15 +219,19 @@ void CComponentManager::Script_RegisterComponentType(void* cbdata, int iid, std:
}
// Construct a new ComponentType, using the wrapper's alloc functions
- ComponentType ct = { CT_Script, iid, ctWrapper.alloc, ctWrapper.dealloc, cname, schema, ctor.get() };
+ ComponentType ct = {
+ CT_Script,
+ iid,
+ ctWrapper.alloc,
+ ctWrapper.dealloc,
+ cname,
+ schema,
+ CScriptValRooted(componentManager->m_ScriptInterface.GetContext(), ctor)
+ };
componentManager->m_ComponentTypesById[cid] = ct;
componentManager->m_CurrentComponent = cid; // needed by Subscribe
- // Stop the ctor getting GCed
- componentManager->m_ScriptInterface.AddRoot(&componentManager->m_ComponentTypesById[cid].ctor, "ComponentType ctor");
- // TODO: check carefully that roots will never get leaked etc
-
// Find all the ctor prototype's On* methods, and subscribe to the appropriate messages:
@@ -285,7 +280,7 @@ void CComponentManager::Script_RegisterComponentType(void* cbdata, int iid, std:
for (; eit != comps.end(); ++eit)
{
jsval instance = eit->second->GetJSInstance();
- if (instance)
+ if (!JSVAL_IS_NULL(instance))
componentManager->m_ScriptInterface.SetPrototype(instance, proto.get());
}
}
@@ -458,7 +453,7 @@ void CComponentManager::ResetState()
void CComponentManager::RegisterComponentType(InterfaceId iid, ComponentTypeId cid, AllocFunc alloc, DeallocFunc dealloc,
const char* name, const std::string& schema)
{
- ComponentType c = { CT_Native, iid, alloc, dealloc, name, schema, 0 };
+ ComponentType c = { CT_Native, iid, alloc, dealloc, name, schema, CScriptValRooted() };
m_ComponentTypesById.insert(std::make_pair(cid, c));
m_ComponentTypeIdsByName[name] = cid;
}
@@ -466,7 +461,7 @@ void CComponentManager::RegisterComponentType(InterfaceId iid, ComponentTypeId c
void CComponentManager::RegisterComponentTypeScriptWrapper(InterfaceId iid, ComponentTypeId cid, AllocFunc alloc,
DeallocFunc dealloc, const char* name, const std::string& schema)
{
- ComponentType c = { CT_ScriptWrapper, iid, alloc, dealloc, name, schema, 0 };
+ ComponentType c = { CT_ScriptWrapper, iid, alloc, dealloc, name, schema, CScriptValRooted() };
m_ComponentTypesById.insert(std::make_pair(cid, c));
m_ComponentTypeIdsByName[name] = cid;
// TODO: merge with RegisterComponentType
@@ -584,11 +579,11 @@ IComponent* CComponentManager::ConstructComponent(entity_id_t ent, ComponentType
std::map& emap2 = m_ComponentsByTypeId[cid];
// If this is a scripted component, construct the appropriate JS object first
- jsval obj = 0;
+ jsval obj = JSVAL_NULL;
if (ct.type == CT_Script)
{
- obj = m_ScriptInterface.CallConstructor(ct.ctor);
- if (!obj)
+ obj = m_ScriptInterface.CallConstructor(ct.ctor.get());
+ if (JSVAL_IS_VOID(obj))
{
LOGERROR(L"Script component constructor failed");
return NULL;
diff --git a/source/simulation2/system/ComponentManager.h b/source/simulation2/system/ComponentManager.h
index 88059cf191..4609991e77 100644
--- a/source/simulation2/system/ComponentManager.h
+++ b/source/simulation2/system/ComponentManager.h
@@ -66,7 +66,7 @@ private:
DeallocFunc dealloc;
std::string name;
std::string schema; // RelaxNG fragment
- jsval ctor; // only valid if type == CT_Script
+ CScriptValRooted ctor; // only valid if type == CT_Script
};
public:
diff --git a/source/simulation2/system/IComponent.cpp b/source/simulation2/system/IComponent.cpp
index 195b6982b2..67ce2de6fc 100644
--- a/source/simulation2/system/IComponent.cpp
+++ b/source/simulation2/system/IComponent.cpp
@@ -40,5 +40,5 @@ JSClass* IComponent::GetJSClass() const
jsval IComponent::GetJSInstance() const
{
- return 0;
+ return JSVAL_NULL;
}
diff --git a/source/simulation2/system/InterfaceScripted.h b/source/simulation2/system/InterfaceScripted.h
index 9554b9731a..4731c286be 100644
--- a/source/simulation2/system/InterfaceScripted.h
+++ b/source/simulation2/system/InterfaceScripted.h
@@ -45,38 +45,38 @@
#define DEFINE_INTERFACE_METHOD_0(scriptname, rettype, classname, methodname) \
{ scriptname, \
- reinterpret_cast(static_cast(ScriptInterface::callMethod)), \
+ ScriptInterface::callMethod, \
0, \
- JSPROP_ENUMERATE|JSPROP_READONLY|JSPROP_PERMANENT|JSFUN_FAST_NATIVE, 0 },
+ JSPROP_ENUMERATE|JSPROP_READONLY|JSPROP_PERMANENT },
#define DEFINE_INTERFACE_METHOD_1(scriptname, rettype, classname, methodname, arg1) \
{ scriptname, \
- reinterpret_cast(static_cast(ScriptInterface::callMethod)), \
+ ScriptInterface::callMethod, \
1, \
- JSPROP_ENUMERATE|JSPROP_READONLY|JSPROP_PERMANENT|JSFUN_FAST_NATIVE, 0 },
+ JSPROP_ENUMERATE|JSPROP_READONLY|JSPROP_PERMANENT },
#define DEFINE_INTERFACE_METHOD_2(scriptname, rettype, classname, methodname, arg1, arg2) \
{ scriptname, \
- reinterpret_cast(static_cast(ScriptInterface::callMethod)), \
+ ScriptInterface::callMethod, \
2, \
- JSPROP_ENUMERATE|JSPROP_READONLY|JSPROP_PERMANENT|JSFUN_FAST_NATIVE, 0 },
+ JSPROP_ENUMERATE|JSPROP_READONLY|JSPROP_PERMANENT },
#define DEFINE_INTERFACE_METHOD_3(scriptname, rettype, classname, methodname, arg1, arg2, arg3) \
{ scriptname, \
- reinterpret_cast(static_cast(ScriptInterface::callMethod)), \
+ ScriptInterface::callMethod, \
3, \
- JSPROP_ENUMERATE|JSPROP_READONLY|JSPROP_PERMANENT|JSFUN_FAST_NATIVE, 0 },
+ JSPROP_ENUMERATE|JSPROP_READONLY|JSPROP_PERMANENT },
#define DEFINE_INTERFACE_METHOD_4(scriptname, rettype, classname, methodname, arg1, arg2, arg3, arg4) \
{ scriptname, \
- reinterpret_cast(static_cast(ScriptInterface::callMethod)), \
+ ScriptInterface::callMethod, \
4, \
- JSPROP_ENUMERATE|JSPROP_READONLY|JSPROP_PERMANENT|JSFUN_FAST_NATIVE, 0 },
+ JSPROP_ENUMERATE|JSPROP_READONLY|JSPROP_PERMANENT },
#define DEFINE_INTERFACE_METHOD_5(scriptname, rettype, classname, methodname, arg1, arg2, arg3, arg4, arg5) \
{ scriptname, \
- reinterpret_cast(static_cast(ScriptInterface::callMethod)), \
+ ScriptInterface::callMethod, \
5, \
- JSPROP_ENUMERATE|JSPROP_READONLY|JSPROP_PERMANENT|JSFUN_FAST_NATIVE, 0 },
+ JSPROP_ENUMERATE|JSPROP_READONLY|JSPROP_PERMANENT },
#endif // INCLUDED_INTERFACE_SCRIPTED
diff --git a/source/simulation2/tests/test_ComponentManager.h b/source/simulation2/tests/test_ComponentManager.h
index 662b833fe5..fabaea0251 100644
--- a/source/simulation2/tests/test_ComponentManager.h
+++ b/source/simulation2/tests/test_ComponentManager.h
@@ -325,6 +325,7 @@ public:
{
CSimContext context;
CComponentManager man(context);
+ ScriptTestSetup(man.m_ScriptInterface);
man.LoadComponentTypes();
TS_ASSERT(man.LoadScript(L"simulation/components/test-entityid.js"));
@@ -334,10 +335,8 @@ public:
man.AddComponent(ent1, man.LookupCID("TestScript1A"), noParam);
man.AddComponent(ent2, man.LookupCID("TestScript1A"), noParam);
- TestLogger log;
TS_ASSERT_EQUALS(static_cast (man.QueryInterface(ent1, IID_Test1))->GetX(), (int)ent1);
TS_ASSERT_EQUALS(static_cast (man.QueryInterface(ent2, IID_Test1))->GetX(), (int)ent2);
- TS_ASSERT_WSTR_CONTAINS(log.GetOutput(), L"this.entity is read-only");
}
void test_script_QueryInterface()
@@ -632,6 +631,7 @@ public:
{
CSimContext context;
CComponentManager man(context);
+ ScriptTestSetup(man.m_ScriptInterface);
man.LoadComponentTypes();
TS_ASSERT(man.LoadScript(L"simulation/components/test-serialize.js"));
diff --git a/source/simulation2/tests/test_Serializer.h b/source/simulation2/tests/test_Serializer.h
index 96c2d58ae3..a7e2593995 100644
--- a/source/simulation2/tests/test_Serializer.h
+++ b/source/simulation2/tests/test_Serializer.h
@@ -372,17 +372,17 @@ public:
const char stream[] = "\x02" // SCRIPT_TYPE_ARRAY
"\x04\0\0\0" // num props
"\x01\0\0\0" "0\0" // "0"
- "\x05" "\x00\0\0\xC0" // SCRIPT_TYPE_INT -1073741824 (JS_INT_MIN)
+ "\x05" "\0\0\0\x80" // SCRIPT_TYPE_INT -2147483648 (JS_INT_MIN)
"\x01\0\0\0" "1\0" // "1"
- "\x06" "\0\0\x40\0\0\0\xD0\xC1" // SCRIPT_TYPE_DOUBLE -1073741825 (JS_INT_MIN-1)
+ "\x06" "\0\0\x20\0\0\0\xE0\xC1" // SCRIPT_TYPE_DOUBLE -2147483649 (JS_INT_MIN-1)
"\x01\0\0\0" "2\0" // "2"
- "\x05" "\xFF\xFF\xFF\x3F" // SCRIPT_TYPE_INT 1073741823
+ "\x05" "\xFF\xFF\xFF\x7F" // SCRIPT_TYPE_INT 2147483647 (JS_INT_MAX)
"\x01\0\0\0" "3\0" // "3"
- "\x06" "\0\0\0\0\0\0\xD0\x41" // SCRIPT_TYPE_DOUBLE 1073741824
+ "\x06" "\0\0\0\0\0\0\xE0\x41" // SCRIPT_TYPE_DOUBLE 2147483648 (JS_INT_MAX+1)
;
- helper_script_roundtrip("numbers", "[-1073741824, -1073741825, 1.073741823e+9, 1073741824]",
- "[-1073741824, -1073741825, 1073741823, 1073741824]", sizeof(stream) - 1, stream);
+ helper_script_roundtrip("numbers", "[-2147483648, -2147483649, 2.147483647e+9, 2147483648]",
+ "[-2147483648, -2147483649, 2147483647, 2147483648]", sizeof(stream) - 1, stream);
}
void test_script_exceptions()
diff --git a/source/sound/JSI_Sound.cpp b/source/sound/JSI_Sound.cpp
index a527394bd9..a1141f28c0 100644
--- a/source/sound/JSI_Sound.cpp
+++ b/source/sound/JSI_Sound.cpp
@@ -28,21 +28,14 @@ JSI_Sound::JSI_Sound(const VfsPath& pathname)
{
m_Handle = snd_open(g_VFS, pathname);
- // special-case to avoid throwing exceptions if quickstart has
- // disabled sound: set a flag queried by Construct; the object will
- // then immediately be freed.
- if (m_Handle == ERR::AGAIN)
+ // if open failed, we still have to return a valid non-null object to
+ // the script, so just reset the handle to 0 so all subsequent method
+ // calls will do nothing
+ if (m_Handle < 0)
{
- m_SoundDisabled = true;
+ m_Handle = 0;
return;
}
- m_SoundDisabled = false;
-
- // if open failed, raise an exception - it's the only way to
- // report errors, since we're in the ctor and don't want to move
- // the open call elsewhere (by requiring an explicit open() call).
- if (m_Handle < 0)
- throw std::exception(); // caught by JSI_Sound::Construct.
(void)snd_set_pos(m_Handle, 0,0,0, true);
}
@@ -190,35 +183,17 @@ CStr JSI_Sound::ToString(JSContext* UNUSED(cx), uintN UNUSED(argc), jsval* UNUSE
return "[object Sound: " + CStr(h_filename(m_Handle).string()) + "]";
}
-JSBool JSI_Sound::Construct(JSContext* cx, JSObject* UNUSED(obj), uintN argc, jsval* argv, jsval* rval)
+JSBool JSI_Sound::Construct(JSContext* cx, uintN argc, jsval* vp)
{
- debug_assert(argc >= 1); // FIXME
+ JSU_REQUIRE_MIN_PARAMS(1);
+
CStrW filename;
- if (! ToPrimitive(cx, argv[0], filename))
+ if (! ToPrimitive(cx, JS_ARGV(cx, vp)[0], filename))
return JS_FALSE;
- try
- {
- JSI_Sound* newObject = new JSI_Sound(filename);
-
- // somewhat of a hack to avoid throwing exceptions if
- // sound was disabled due to quickstart. see JSI_Sound().
- if (newObject->m_SoundDisabled)
- {
- delete newObject;
- *rval = JSVAL_NULL;
- return JS_TRUE;
- }
-
- newObject->m_EngineOwned = false;
- *rval = OBJECT_TO_JSVAL(newObject->GetScript());
- }
- catch (std::exception)
- {
- // failed, but this can happen easily enough that we don't want to
- // return JS_FALSE (since that stops the script).
- *rval = JSVAL_NULL;
- }
+ JSI_Sound* newObject = new JSI_Sound(filename);
+ newObject->m_EngineOwned = false;
+ JS_SET_RVAL(cx, vp, OBJECT_TO_JSVAL(newObject->GetScript()));
return JS_TRUE;
}
diff --git a/source/sound/JSI_Sound.h b/source/sound/JSI_Sound.h
index 2b6c3ca2ec..17739805bb 100644
--- a/source/sound/JSI_Sound.h
+++ b/source/sound/JSI_Sound.h
@@ -48,34 +48,31 @@ public:
// Script-bound functions
- CStr ToString( JSContext* cx, uintN argc, jsval* argv );
+ CStr ToString(JSContext* cx, uintN argc, jsval* argv);
// start playing the sound (one-shot).
// it will automatically be freed when done.
- bool Play( JSContext* cx, uintN argc, jsval* argv );
+ bool Play(JSContext* cx, uintN argc, jsval* argv);
// request the sound be played until free() is called. returns immediately.
- bool Loop( JSContext* cx, uintN argc, jsval* argv );
+ bool Loop(JSContext* cx, uintN argc, jsval* argv);
// stop sound if currently playing and free resources.
// doesn't need to be called unless played via loop() -
// sounds are freed automatically when done playing.
- bool Free( JSContext* cx, uintN argc, jsval* argv );
+ bool Free(JSContext* cx, uintN argc, jsval* argv);
- bool SetGain( JSContext* cx, uintN argc, jsval* argv );
+ bool SetGain(JSContext* cx, uintN argc, jsval* argv);
- bool SetPitch( JSContext* cx, uintN argc, jsval* argv );
+ bool SetPitch(JSContext* cx, uintN argc, jsval* argv);
- bool SetPosition( JSContext* cx, uintN argc, jsval* argv );
+ bool SetPosition(JSContext* cx, uintN argc, jsval* argv);
- bool Fade ( JSContext* cx, uintN argc, jsval* argv );
+ bool Fade(JSContext* cx, uintN argc, jsval* argv);
- static JSBool Construct( JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval );
+ static JSBool Construct(JSContext* cx, uintN argc, jsval* vp);
static void ScriptingInit();
-
-private:
- bool m_SoundDisabled; // see constructor and JSI_Sound::Construct
};
#endif // #ifndef INCLUDED_JSI_SOUND
diff --git a/source/tools/atlas/AtlasScript/NativeWrapper.inl b/source/tools/atlas/AtlasScript/NativeWrapper.inl
index 00df75f072..148c98cc5e 100644
--- a/source/tools/atlas/AtlasScript/NativeWrapper.inl
+++ b/source/tools/atlas/AtlasScript/NativeWrapper.inl
@@ -29,7 +29,7 @@ public:
#define NUMBERED_LIST_BALANCED(z, i, data) BOOST_PP_COMMA_IF(i) data##i
// Some other things
#define TYPED_ARGS(z, i, data) , T##i a##i
- #define CONVERT_ARG(z, i, data) T##i a##i; if (! ScriptInterface::FromJSVal(cx, argv[i], a##i)) return JS_FALSE;
+ #define CONVERT_ARG(z, i, data) T##i a##i; if (! ScriptInterface::FromJSVal(cx, i < argc ? JS_ARGV(cx, vp)[i] : JSVAL_VOID, a##i)) return JS_FALSE;
// List-generating macros, named roughly after their first list item
#define TYPENAME_T0_HEAD(z, i) BOOST_PP_REPEAT_##z (i, NUMBERED_LIST_HEAD, typename T)
@@ -56,7 +56,7 @@ private:
// (Definition comes later, since it depends on some things we haven't defined yet)
#define OVERLOADS(z, i, data) \
template \
- static JSBool call(JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval);
+ static JSBool call(JSContext* cx, uintN argc, jsval* vp);
BOOST_PP_REPEAT(MAX_ARGS, OVERLOADS, ~)
#undef OVERLOADS
@@ -102,10 +102,12 @@ struct ScriptInterface_NativeWrapper {
// JSNative-compatible function that wraps the function identified in the template argument list
#define OVERLOADS(z, i, data) \
template \
- JSBool ScriptInterface::call(JSContext* cx, JSObject* /*obj*/, uintN /*argc*/, jsval* argv, jsval* rval) { \
- (void)argv; /* avoid 'unused parameter' warnings */ \
+ JSBool ScriptInterface::call(JSContext* cx, uintN argc, jsval* vp) { \
+ (void)cx; (void)argc; /* avoid 'unused parameter' warnings */ \
BOOST_PP_REPEAT_##z (i, CONVERT_ARG, ~) \
- ScriptInterface_NativeWrapper::call(cx, *rval, fptr A0_TAIL(z,i)); \
+ jsval rval = JSVAL_VOID; \
+ ScriptInterface_NativeWrapper
::call(cx, rval, fptr A0_TAIL(z,i)); \
+ JS_SET_RVAL(cx, vp, rval); \
return JS_TRUE; \
}
BOOST_PP_REPEAT(MAX_ARGS, OVERLOADS, ~)
diff --git a/source/tools/atlas/AtlasScript/ScriptInterface.cpp b/source/tools/atlas/AtlasScript/ScriptInterface.cpp
index a31c99231b..a98b42efbe 100644
--- a/source/tools/atlas/AtlasScript/ScriptInterface.cpp
+++ b/source/tools/atlas/AtlasScript/ScriptInterface.cpp
@@ -166,8 +166,11 @@ namespace
JSString* ret = JS_ValueToString(cx, v);
if (! ret)
FAIL("Argument must be convertible to a string");
- char* ch = JS_GetStringBytes(ret);
- out = std::string(ch);
+ char* ch = JS_EncodeString(cx, ret); // chops off high byte of each jschar
+ if (! ch)
+ FAIL("JS_EncodeString failed"); // out of memory
+ out = std::string(ch, ch + JS_GetStringLength(ret));
+ JS_free(cx, ch);
return true;
}
};
@@ -241,7 +244,7 @@ namespace
static jsval Convert(JSContext* cx, const float& val)
{
jsval rval = JSVAL_VOID;
- JS_NewDoubleValue(cx, val, &rval); // ignore return value
+ JS_NewNumberValue(cx, val, &rval); // ignore return value
return rval;
}
};
@@ -326,13 +329,11 @@ namespace
{
JSObject* obj = JS_NewArrayObject(cx, 0, NULL);
if (! obj) return JSVAL_VOID;
- JS_AddRoot(cx, &obj);
for (size_t i = 0; i < val.size(); ++i)
{
jsval el = ToJSVal::Convert(cx, val[i]);
JS_SetElement(cx, obj, (jsint)i, &el);
}
- JS_RemoveRoot(cx, &obj);
return OBJECT_TO_JSVAL(obj);
}
};
@@ -382,7 +383,6 @@ namespace
{
JSObject* obj = JS_NewObject(cx, NULL, NULL, NULL);
if (! obj) return JSVAL_VOID;
- JS_AddRoot(cx, &obj);
JS_DefineProperty(cx, obj, "name", ToJSVal::Convert(cx, *val.name), NULL, NULL, JSPROP_ENUMERATE);
@@ -393,8 +393,6 @@ namespace
jsval bmp = wxjs::gui::Bitmap::CreateObject(cx, new wxBitmap (wxImage(val.imagewidth, val.imageheight, buf)));
JS_DefineProperty(cx, obj, "imagedata", bmp, NULL, NULL, JSPROP_ENUMERATE);
- JS_RemoveRoot(cx, &obj);
-
return OBJECT_TO_JSVAL(obj);
}
};
@@ -405,11 +403,9 @@ namespace
{
JSObject* obj = JS_NewObject(cx, NULL, NULL, NULL);
if (! obj) return JSVAL_VOID;
- JS_AddRoot(cx, &obj);
JS_DefineProperty(cx, obj, "id", ToJSVal::Convert(cx, *val.id), NULL, NULL, JSPROP_ENUMERATE);
JS_DefineProperty(cx, obj, "name", ToJSVal::Convert(cx, *val.name), NULL, NULL, JSPROP_ENUMERATE);
JS_DefineProperty(cx, obj, "type", ToJSVal::Convert(cx, val.type), NULL, NULL, JSPROP_ENUMERATE);
- JS_RemoveRoot(cx, &obj);
return OBJECT_TO_JSVAL(obj);
}
};
@@ -420,11 +416,9 @@ namespace
{
JSObject* obj = JS_NewObject(cx, NULL, NULL, NULL);
if (! obj) return JSVAL_VOID;
- JS_AddRoot(cx, &obj);
JS_DefineProperty(cx, obj, "player", ToJSVal::Convert(cx, val.player), NULL, NULL, JSPROP_ENUMERATE);
JS_DefineProperty(cx, obj, "selections", ToJSVal >::Convert(cx, *val.selections), NULL, NULL, JSPROP_ENUMERATE);
JS_DefineProperty(cx, obj, "variantgroups", ToJSVal > >::Convert(cx, *val.variantgroups), NULL, NULL, JSPROP_ENUMERATE);
- JS_RemoveRoot(cx, &obj);
return OBJECT_TO_JSVAL(obj);
}
};
@@ -531,37 +525,47 @@ namespace
// Functions in the Atlas.* namespace:
- JSBool ForceGC(JSContext* cx, JSObject* WXUNUSED(obj), uintN WXUNUSED(argc), jsval* WXUNUSED(argv), jsval* WXUNUSED(rval))
+ JSBool ForceGC(JSContext* cx, uintN WXUNUSED(argc), jsval* vp)
{
JS_GC(cx);
+ JS_SET_RVAL(cx, vp, JSVAL_VOID);
return JS_TRUE;
}
- JSBool LoadScript(JSContext* cx, JSObject* WXUNUSED(obj), uintN WXUNUSED(argc), jsval* argv, jsval* rval)
+ JSBool LoadScript(JSContext* cx, uintN argc, jsval* vp)
{
- if (! ( JSVAL_IS_STRING(argv[0]) && JSVAL_IS_STRING(argv[1]) ))
+ if (argc < 2 || !JSVAL_IS_STRING(JS_ARGV(cx, vp)[0]) || !JSVAL_IS_STRING(JS_ARGV(cx, vp)[1]))
return JS_FALSE;
- JSString* name = JSVAL_TO_STRING(argv[0]);
- JSString* code = JSVAL_TO_STRING(argv[1]);
+ std::string name;
+ if (!ScriptInterface::FromJSVal(cx, JS_ARGV(cx, vp)[0], name))
+ return JS_FALSE;
+
+ JSString* code = JSVAL_TO_STRING(JS_ARGV(cx, vp)[1]);
- return ScriptInterface_impl::LoadScript(cx,
+ jsval rval = JSVAL_VOID;
+ if (!ScriptInterface_impl::LoadScript(cx,
JS_GetStringChars(code), (uintN)JS_GetStringLength(code),
- JS_GetStringBytes(name), rval);
+ name.c_str(), &rval))
+ return JS_FALSE;
+
+ JS_SET_RVAL(cx, vp, rval);
+ return JS_TRUE;
}
// Functions in the global namespace:
- JSBool print(JSContext* cx, JSObject* WXUNUSED(obj), uintN argc, jsval* argv, jsval* WXUNUSED(rval))
+ JSBool print(JSContext* cx, uintN argc, jsval* vp)
{
for (uintN i = 0; i < argc; ++i)
{
std::string str;
- if (! ScriptInterface::FromJSVal(cx, argv[i], str))
+ if (! ScriptInterface::FromJSVal(cx, JS_ARGV(cx, vp)[i], str))
return JS_FALSE;
printf("%s", str.c_str());
}
fflush(stdout);
+ JS_SET_RVAL(cx, vp, JSVAL_VOID);
return JS_TRUE;
}
}
@@ -588,7 +592,7 @@ ScriptInterface_impl::ScriptInterface_impl()
| JSOPTION_XML // "ECMAScript for XML support: parse as a token"
);
- m_glob = JS_NewObject(m_cx, &global_class, NULL, NULL);
+ m_glob = JS_NewGlobalObject(m_cx, &global_class);
ok = JS_InitStandardClasses(m_cx, m_glob);
JS_DefineProperty(m_cx, m_glob, "global", OBJECT_TO_JSVAL(m_glob), NULL, NULL, JSPROP_ENUMERATE|JSPROP_READONLY|JSPROP_PERMANENT);
@@ -666,31 +670,14 @@ JSContext* ScriptInterface::GetContext()
return m->m_cx;
}
-bool ScriptInterface::AddRoot(void* ptr)
+bool ScriptInterface::AddRoot(jsval* ptr)
{
- return JS_AddRoot(m->m_cx, ptr) ? true : false;
+ return JS_AddValueRoot(m->m_cx, ptr) ? true : false;
}
-bool ScriptInterface::RemoveRoot(void* ptr)
+bool ScriptInterface::RemoveRoot(jsval* ptr)
{
- return JS_RemoveRoot(m->m_cx, ptr) ? true : false;
-}
-
-ScriptInterface::LocalRootScope::LocalRootScope(ScriptInterface& scriptInterface)
- : m_ScriptInterface(scriptInterface)
-{
- m_OK = JS_EnterLocalRootScope(m_ScriptInterface.m->m_cx) ? true : false;
-}
-
-ScriptInterface::LocalRootScope::~LocalRootScope()
-{
- if (m_OK)
- JS_LeaveLocalRootScope(m_ScriptInterface.m->m_cx);
-}
-
-bool ScriptInterface::LocalRootScope::OK()
-{
- return m_OK;
+ return JS_RemoveValueRoot(m->m_cx, ptr) ? true : false;
}
@@ -813,7 +800,7 @@ std::pair ScriptInterface::LoadScriptAsSidebar(const wxStrin
#define CONVERT_ARGS(r, data, i, elem) \
TYPE(elem) a##i; \
- if (! ScriptInterface::FromJSVal< TYPE(elem) >(cx, argv[i], a##i)) \
+ if (! ScriptInterface::FromJSVal< TYPE(elem) >(cx, i < argc ? JS_ARGV(cx, vp)[i] : JSVAL_VOID, a##i)) \
return JS_FALSE;
#define CONVERT_OUTPUTS(r, data, i, elem) \
@@ -823,33 +810,35 @@ std::pair ScriptInterface::LoadScriptAsSidebar(const wxStrin
#define ARG_LIST(r, data, i, elem) BOOST_PP_COMMA_IF(i) a##i
#define MESSAGE(name, vals) \
- JSBool call_##name(JSContext* cx, JSObject* WXUNUSED(obj), uintN WXUNUSED(argc), jsval* argv, jsval* WXUNUSED(rval)) \
+ JSBool call_##name(JSContext* cx, uintN argc, jsval* vp) \
{ \
- (void)cx; (void)argv; /* avoid 'unused parameter' warnings */ \
+ (void)cx; (void)argc; /* avoid 'unused parameter' warnings */ \
BOOST_PP_SEQ_FOR_EACH_I(CONVERT_ARGS, ~, vals) \
g_MessagePasser->Add(SHAREABLE_NEW(m##name, ( BOOST_PP_SEQ_FOR_EACH_I(ARG_LIST, ~, vals) ))); \
+ JS_SET_RVAL(cx, vp, JSVAL_VOID); \
return JS_TRUE; \
}
#define COMMAND(name, merge, vals) \
- JSBool call_##name(JSContext* cx, JSObject* WXUNUSED(obj), uintN WXUNUSED(argc), jsval* argv, jsval* WXUNUSED(rval)) \
+ JSBool call_##name(JSContext* cx, uintN argc, jsval* vp) \
{ \
- (void)cx; (void)argv; /* avoid 'unused parameter' warnings */ \
+ (void)cx; (void)argc; /* avoid 'unused parameter' warnings */ \
BOOST_PP_SEQ_FOR_EACH_I(CONVERT_ARGS, ~, vals) \
g_SubmitCommand(new AtlasMessage::m##name (AtlasMessage::d##name ( BOOST_PP_SEQ_FOR_EACH_I(ARG_LIST, ~, vals) ))); \
+ JS_SET_RVAL(cx, vp, JSVAL_VOID); \
return JS_TRUE; \
}
#define QUERY(name, in_vals, out_vals) \
- JSBool call_##name(JSContext* cx, JSObject* WXUNUSED(obj), uintN WXUNUSED(argc), jsval* argv, jsval* rval) \
+ JSBool call_##name(JSContext* cx, uintN argc, jsval* vp) \
{ \
- (void)argv; /* avoid 'unused parameter' warnings */ \
+ (void)cx; (void)argc; /* avoid 'unused parameter' warnings */ \
BOOST_PP_SEQ_FOR_EACH_I(CONVERT_ARGS, ~, in_vals) \
q##name q = q##name( BOOST_PP_SEQ_FOR_EACH_I(ARG_LIST, ~, in_vals) ); \
q.Post(); \
JSObject* ret = JS_NewObject(cx, NULL, NULL, NULL); \
if (! ret) return JS_FALSE; \
- *rval = OBJECT_TO_JSVAL(ret); \
+ JS_SET_RVAL(cx, vp, OBJECT_TO_JSVAL(ret)); \
BOOST_PP_SEQ_FOR_EACH_I(CONVERT_OUTPUTS, ~, out_vals) \
return JS_TRUE; \
}
@@ -898,4 +887,3 @@ void ScriptInterface_impl::RegisterMessages(JSObject* parent)
#undef COMMAND
#undef QUERY
}
-
diff --git a/source/tools/atlas/AtlasScript/ScriptInterface.h b/source/tools/atlas/AtlasScript/ScriptInterface.h
index d2f2237d72..9e7d2e8401 100644
--- a/source/tools/atlas/AtlasScript/ScriptInterface.h
+++ b/source/tools/atlas/AtlasScript/ScriptInterface.h
@@ -20,11 +20,18 @@
#ifdef _WIN32
# define XP_WIN
+# define WIN32 // SpiderMonkey expects this
+
+// The jsval struct type causes crashes due to weird miscompilation
+// issues in (at least) VC2008, so force it to be the less-type-safe
+// non-struct type instead
+# define JS_NO_JSVAL_JSID_STRUCT_TYPES
+
#else
# define XP_UNIX
#endif // (we don't support XP_OS2 or XP_BEOS)
-#include "js/jspubtd.h"
+#include "js/jsapi.h"
class wxWindow;
class wxString;
@@ -70,26 +77,8 @@ public:
// value must be rooted if you don't want it to be collected.)
template static jsval ToJSVal(JSContext* cx, const T& val);
- bool AddRoot(void* ptr);
- bool RemoveRoot(void* ptr);
-
- // Helper class for automatically rooting values
- class LocalRootScope
- {
- ScriptInterface& m_ScriptInterface;
- bool m_OK;
- public:
- // Tries to enter local root scope, so newly created
- // values won't be GCed. This might fail, so check OK()
- LocalRootScope(ScriptInterface& scriptInterface);
- // Returns true if the local root scope was successfully entered
- bool OK();
- // Leaves the local root scope
- ~LocalRootScope();
- private:
- LocalRootScope& operator=(const LocalRootScope&);
- };
- #define LOCAL_ROOT_SCOPE LocalRootScope scope(*this); if (! scope.OK()) return false
+ bool AddRoot(jsval* ptr);
+ bool RemoveRoot(jsval* ptr);
private:
JSContext* GetContext();
@@ -113,7 +102,6 @@ bool ScriptInterface::SetValue(const wxString& name, const T& val)
template
bool ScriptInterface::GetValue(const wxString& name, T& ret)
{
- LOCAL_ROOT_SCOPE;
jsval jsRet;
if (! GetValue_(name, jsRet)) return false;
return FromJSVal(GetContext(), jsRet, ret);
@@ -122,7 +110,6 @@ bool ScriptInterface::GetValue(const wxString& name, T& ret)
template
bool ScriptInterface::CallFunction(jsval val, const char* name, const T& a, R& ret)
{
- LOCAL_ROOT_SCOPE;
jsval jsRet;
std::vector argv;
argv.push_back(ToJSVal(GetContext(), a));
@@ -134,7 +121,6 @@ bool ScriptInterface::CallFunction(jsval val, const char* name, const T& a, R& r
template