[dss-commits] r8761 - in dss/trunk: core core/scripting tests
dss-commits at forum.digitalstrom.org
dss-commits at forum.digitalstrom.org
Mon Sep 14 19:59:44 CEST 2009
Author: pstaehlin
Date: 2009-09-14 19:59:43 +0200 (Mon, 14 Sep 2009)
New Revision: 8761
Modified:
dss/trunk/core/jshandler.cpp
dss/trunk/core/jshandler.h
dss/trunk/core/scripting/modeljs.cpp
dss/trunk/core/scripting/modeljs.h
dss/trunk/tests/jshandlertests.cpp
dss/trunk/tests/modeljstests.cpp
Log:
Support for getting/setting properties including tests
References #129
Modified: dss/trunk/core/jshandler.cpp
===================================================================
--- dss/trunk/core/jshandler.cpp 2009-09-14 08:39:28 UTC (rev 8760)
+++ dss/trunk/core/jshandler.cpp 2009-09-14 17:59:43 UTC (rev 8761)
@@ -220,8 +220,13 @@
throw ScriptException(std::string("Could not parse in-memory script"));
}
} // loadFromMemory
-
+
template<>
+ jsval ScriptContext::convertTo(const jsval& _val) {
+ return _val;
+ }
+
+ template<>
int ScriptContext::convertTo(const jsval& _val) {
if(JSVAL_IS_NUMBER(_val)) {
int result;
@@ -264,54 +269,99 @@
}
throw ScriptException("Value is not of type double");
}
-
+
+ bool ScriptContext::raisePendingExceptions() {
+ if(JS_IsExceptionPending(m_pContext)) {
+ jsval exval;
+ if(JS_GetPendingException(m_pContext, &exval)) {
+ JS_ClearPendingException(m_pContext);
+ JSString* errstr = JS_ValueToString(m_pContext, exval);
+ if(errstr != NULL) {
+ const char* errmsgBytes = JS_GetStringBytes(errstr);
+ throw ScriptRuntimeException(std::string("Caught Exception while executing script: ") + errmsgBytes, std::string(errmsgBytes));
+ }
+ }
+ throw ScriptException("Exception was pending after script execution, but couldnt get it from the vm");
+ }
+ return false;
+ } // raisePendingExceptions
+
template <>
jsval ScriptContext::evaluate() {
jsval rval;
JSBool ok = JS_ExecuteScript(m_pContext, m_pRootObject, m_pScriptToExecute, &rval);
if(ok) {
- //JS_GC(m_pContext);
return rval;
} else {
- if(JS_IsExceptionPending(m_pContext)) {
- jsval exval;
- if(JS_GetPendingException(m_pContext, &exval)) {
- JS_ClearPendingException(m_pContext);
- JSString* errstr = JS_ValueToString(m_pContext, exval);
- if(errstr != NULL) {
- const char* errmsgBytes = JS_GetStringBytes(errstr);
- throw ScriptRuntimeException(std::string("Caught Exception while executing script: ") + errmsgBytes, std::string(errmsgBytes));
- }
- }
- throw ScriptException("Exception was pending after script execution, but couldnt get it from the vm");
- } else {
- throw ScriptException("Error executing script");
- }
+ raisePendingExceptions();
+ throw ScriptException("Error executing script");
}
} // evaluate<jsval>
-
+
template <>
+ void ScriptContext::evaluate() {
+ evaluate<jsval>();
+ } // evaluate<void>
+
+ template <>
double ScriptContext::evaluate() {
return convertTo<double>(evaluate<jsval>());
} // evaluate<double>
-
template <>
int ScriptContext::evaluate() {
return convertTo<int>(evaluate<jsval>());
} // evaluate<int>
-
template <>
- void ScriptContext::evaluate() {
- evaluate<jsval>();
- } // evaluate<void>
+ bool ScriptContext::evaluate() {
+ return convertTo<bool>(evaluate<jsval>());
+ } // evaluate<bool>
template <>
std::string ScriptContext::evaluate() {
return convertTo<std::string>(evaluate<jsval>());
} // evaluate<string>
+ template <>
+ jsval ScriptContext::evaluateScript(const std::string& _script) {
+ const char* filename = "temporary_script";
+ jsval rval;
+ JSBool ok = JS_EvaluateScript(m_pContext, m_pRootObject, _script.c_str(), _script.size(),
+ filename, 0, &rval);
+ if(ok) {
+ return rval;
+ } else {
+ raisePendingExceptions();
+ throw ScriptException("Error executing script");
+ }
+ } // evaluateScript
+
+ template <>
+ void ScriptContext::evaluateScript(const std::string& _script) {
+ evaluateScript<jsval>(_script);
+ } // evaluateScript<void>
+
+ template <>
+ int ScriptContext::evaluateScript(const std::string& _script) {
+ return convertTo<int>(evaluateScript<jsval>(_script));
+ } // evaluateScript<int>
+
+ template <>
+ double ScriptContext::evaluateScript(const std::string& _script) {
+ return convertTo<double>(evaluateScript<jsval>(_script));
+ } // evaluateScript<double>
+
+ template <>
+ std::string ScriptContext::evaluateScript(const std::string& _script) {
+ return convertTo<std::string>(evaluateScript<jsval>(_script));
+ } // evaluateScript<std::string>
+
+ template <>
+ bool ScriptContext::evaluateScript(const std::string& _script) {
+ return convertTo<bool>(evaluateScript<jsval>(_script));
+ } // evaluateScript<bool>
+
//================================================== ScriptExtension
//================================================== ScriptObject
Modified: dss/trunk/core/jshandler.h
===================================================================
--- dss/trunk/core/jshandler.h 2009-09-14 08:39:28 UTC (rev 8760)
+++ dss/trunk/core/jshandler.h 2009-09-14 17:59:43 UTC (rev 8761)
@@ -83,6 +83,7 @@
ScriptEnvironment& m_Environment;
JSContext* m_pContext;
static void jsErrorHandler(JSContext *ctx, const char *msg, JSErrorReport *er);
+ bool raisePendingExceptions();
public:
ScriptContext(ScriptEnvironment& _env, JSContext* _pContext);
virtual ~ScriptContext();
@@ -105,6 +106,10 @@
template <class t>
t evaluate();
+ /** Evaluates the given script */
+ template <class t>
+ t evaluateScript(const std::string& _script);
+
/** Returns a pointer to the JSContext */
JSContext* getJSContext() { return m_pContext; }
/** Returns a const reference to the ScriptEnvironment */
Modified: dss/trunk/core/scripting/modeljs.cpp
===================================================================
--- dss/trunk/core/scripting/modeljs.cpp 2009-09-14 08:39:28 UTC (rev 8760)
+++ dss/trunk/core/scripting/modeljs.cpp 2009-09-14 17:59:43 UTC (rev 8761)
@@ -20,12 +20,14 @@
*/
#include "modeljs.h"
-#include "core/dss.h"
-#include "core/logger.h"
#include <sstream>
#include <boost/scoped_ptr.hpp>
+#include "core/dss.h"
+#include "core/logger.h"
+#include "core/propertysystem.h"
+
namespace dss {
const std::string ModelScriptcontextExtensionName = "modelextension";
@@ -884,4 +886,93 @@
return result;
}
+ //================================================== PropertyScriptExtension
+
+ const std::string PropertyScriptExtensionName = "propertyextension";
+
+ PropertyScriptExtension::PropertyScriptExtension(PropertySystem& _propertySystem)
+ : ScriptExtension(PropertyScriptExtensionName),
+ m_PropertySystem(_propertySystem)
+ { } // ctor
+
+ JSBool global_prop_setProperty(JSContext* cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) {
+ if(argc > 2) {
+ Logger::getInstance()->log("JS: global_prop_setProperty: need two arguments: property-path & value", lsError);
+ } else {
+ ScriptContext* ctx = static_cast<ScriptContext*>(JS_GetContextPrivate(cx));
+
+ PropertyScriptExtension* ext = dynamic_cast<PropertyScriptExtension*>(ctx->getEnvironment().getExtension(PropertyScriptExtensionName));
+ std::string propName = ctx->convertTo<std::string>(argv[0]);
+
+ PropertyNodePtr node = ext->getPropertySystem().createProperty(propName);
+ try {
+ if(JSVAL_IS_STRING(argv[1])) {
+ node->setStringValue(ctx->convertTo<std::string>(argv[1]));
+ } else if(JSVAL_IS_BOOLEAN(argv[1])) {
+ node->setBooleanValue(ctx->convertTo<bool>(argv[1]));
+ } else if(JSVAL_IS_INT(argv[1])) {
+ node->setIntegerValue(ctx->convertTo<int>(argv[1]));
+ } else {
+ Logger::getInstance()->log("JS: global_prop_setProperty: unknown type of argument 2", lsError);
+ }
+ *rval = JSVAL_TRUE;
+ return JS_TRUE;
+ } catch(PropertyTypeMismatch&) {
+ Logger::getInstance()->log("Error setting value of " + propName, lsFatal);
+ }
+ }
+ return JS_FALSE;
+ } // global_prop_setProperty
+
+ JSBool global_prop_getProperty(JSContext* cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) {
+ if(argc > 1) {
+ Logger::getInstance()->log("JS: global_prop_getProperty: need one argument: property-path", lsError);
+ } else {
+ ScriptContext* ctx = static_cast<ScriptContext*>(JS_GetContextPrivate(cx));
+
+ PropertyScriptExtension* ext = dynamic_cast<PropertyScriptExtension*>(ctx->getEnvironment().getExtension(PropertyScriptExtensionName));
+ std::string propName = ctx->convertTo<std::string>(argv[0]);
+
+ PropertyNodePtr node = ext->getPropertySystem().getProperty(propName);
+ if(node == NULL) {
+ *rval = JSVAL_NULL;
+ } else {
+ switch(node->getValueType()) {
+ case vTypeInteger:
+ *rval = INT_TO_JSVAL(node->getIntegerValue());
+ break;
+ case vTypeString: {
+ std::string val = node->getStringValue();
+ *rval = STRING_TO_JSVAL(JS_NewStringCopyZ(cx, val.c_str()));
+ }
+ break;
+ case vTypeBoolean:
+ *rval = BOOLEAN_TO_JSVAL(node->getBoolValue());
+ break;
+ case vTypeNone:
+ *rval = JSVAL_VOID;
+ default:
+ assert(false);
+ }
+ }
+ return JS_TRUE;
+ }
+ return JS_FALSE;
+ } // global_prop_getProperty
+
+ JSFunctionSpec prop_global_methods[] = {
+ {"setProperty", global_prop_setProperty, 2, 0, 0},
+ {"getProperty", global_prop_getProperty, 1, 0, 0},
+ {NULL},
+ };
+
+ void PropertyScriptExtension::extendContext(ScriptContext& _context) {
+ JS_DefineFunctions(_context.getJSContext(), JS_GetGlobalObject(_context.getJSContext()), prop_global_methods);
+ } // extendContext
+
+ JSObject* PropertyScriptExtension::createJSProperty(ScriptContext& _ctx, boost::shared_ptr<PropertyNode> _node) {
+ return NULL;
+ } // createJSProperty
+
+
} // namespace
Modified: dss/trunk/core/scripting/modeljs.h
===================================================================
--- dss/trunk/core/scripting/modeljs.h 2009-09-14 08:39:28 UTC (rev 8760)
+++ dss/trunk/core/scripting/modeljs.h 2009-09-14 17:59:43 UTC (rev 8761)
@@ -82,7 +82,24 @@
JSObject* createJSEvent(ScriptContext& _ctx, boost::shared_ptr<Event> _event);
JSObject* createJSSubscription(ScriptContext& _ctx, boost::shared_ptr<EventSubscription> _subscription);
- };
+ }; // EventScriptExtension
+
+ class PropertySystem;
+ class PropertyNode;
+
+ class PropertyScriptExtension : public ScriptExtension {
+ public:
+ PropertyScriptExtension(PropertySystem& _propertySystem);
+ virtual ~PropertyScriptExtension() {}
+
+ virtual void extendContext(ScriptContext& _context);
+
+ PropertySystem& getPropertySystem() { return m_PropertySystem; }
+
+ JSObject* createJSProperty(ScriptContext& _ctx, boost::shared_ptr<PropertyNode> _node);
+ private:
+ PropertySystem& m_PropertySystem;
+ }; // PropertyScriptExtension
}
Modified: dss/trunk/tests/jshandlertests.cpp
===================================================================
--- dss/trunk/tests/jshandlertests.cpp 2009-09-14 08:39:28 UTC (rev 8760)
+++ dss/trunk/tests/jshandlertests.cpp 2009-09-14 17:59:43 UTC (rev 8761)
@@ -42,14 +42,13 @@
BOOST_CHECK_EQUAL(obj.getProperty<int>("testing"), 1);
ctx->getRootObject().setProperty("obj", &obj);
- ctx->loadFromMemory("obj.testing");
- BOOST_CHECK_EQUAL(ctx->evaluate<int>(), 1);
+ BOOST_CHECK_EQUAL(ctx->evaluateScript<int>("obj.testing"), 1);
obj.setProperty("testing", 0);
- BOOST_CHECK_EQUAL(ctx->evaluate<int>(), 0);
+ BOOST_CHECK_EQUAL(ctx->evaluateScript<int>("obj.testing"), 0);
- obj.setProperty("testing", "test");
- BOOST_CHECK_EQUAL(obj.getProperty<std::string>("testing"), "test");
- BOOST_CHECK_EQUAL(ctx->evaluate<std::string>(), "test");
+ obj.setProperty("testing2", "test");
+ BOOST_CHECK_EQUAL(obj.getProperty<std::string>("testing2"), "test");
+ BOOST_CHECK_EQUAL(ctx->evaluateScript<std::string>("obj.testing2"), "test");
} // testSimpleObject
BOOST_AUTO_TEST_SUITE_END()
Modified: dss/trunk/tests/modeljstests.cpp
===================================================================
--- dss/trunk/tests/modeljstests.cpp 2009-09-14 08:39:28 UTC (rev 8760)
+++ dss/trunk/tests/modeljstests.cpp 2009-09-14 17:59:43 UTC (rev 8761)
@@ -23,9 +23,10 @@
#define BOOST_TEST_DYN_LINK
#include <boost/test/unit_test.hpp>
-#include "../core/scripting/modeljs.h"
-#include "../core/event.h"
-#include "../core/eventinterpreterplugins.h"
+#include "core/scripting/modeljs.h"
+#include "core/event.h"
+#include "core/eventinterpreterplugins.h"
+#include "core/propertysystem.h"
#include <boost/scoped_ptr.hpp>
#include <memory>
@@ -181,4 +182,20 @@
BOOST_CHECK_EQUAL(interpreter.getNumberOfSubscriptions(), 1);
} // testSubscriptions
+BOOST_AUTO_TEST_CASE(testProperties) {
+ PropertySystem propSys;
+ boost::scoped_ptr<ScriptEnvironment> env(new ScriptEnvironment());
+ env->initialize();
+ ScriptExtension* ext = new PropertyScriptExtension(propSys);
+ env->addExtension(ext);
+
+ boost::scoped_ptr<ScriptContext> ctx(env->getContext());
+ ctx->evaluateScript<void>("setProperty('/testing', 1)");
+ BOOST_CHECK_EQUAL(ctx->evaluateScript<int>("getProperty('/testing')"), 1);
+ BOOST_CHECK_EQUAL(propSys.getIntValue("/testing"), 1);
+
+ propSys.setIntValue("/testing", 2);
+ BOOST_CHECK_EQUAL(ctx->evaluateScript<int>("getProperty('/testing')"), 2);
+}
+
BOOST_AUTO_TEST_SUITE_END()
More information about the dss-commits
mailing list