[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