[dss-commits] r8808 - in dss/trunk: core core/scripting core/sim tests

dss-commits at forum.digitalstrom.org dss-commits at forum.digitalstrom.org
Tue Sep 29 16:08:06 CEST 2009


Author: pstaehlin
Date: 2009-09-29 16:08:06 +0200 (Tue, 29 Sep 2009)
New Revision: 8808

Modified:
   dss/trunk/core/eventinterpreterplugins.cpp
   dss/trunk/core/jshandler.cpp
   dss/trunk/core/jshandler.h
   dss/trunk/core/scripting/modeljs.cpp
   dss/trunk/core/scripting/modeljs.h
   dss/trunk/core/sim/dsid_js.cpp
   dss/trunk/tests/jshandlertests.cpp
   dss/trunk/tests/modeljstests.cpp
   dss/trunk/tests/scriptstest.cpp
Log:
Work on javascript integration:
* Fixed crash in PropertyListener => JS code
* Made evaluate execute a JS string and evaluateScript execute a script w/o precompiling it
* Raise simulated dSLinkInterrupt from own thread
* Store JS-PropertyListeners on the context to ensure they will be removed if the context gets invalid


Modified: dss/trunk/core/eventinterpreterplugins.cpp
===================================================================
--- dss/trunk/core/eventinterpreterplugins.cpp	2009-09-29 13:57:47 UTC (rev 8807)
+++ dss/trunk/core/eventinterpreterplugins.cpp	2009-09-29 14:08:06 UTC (rev 8808)
@@ -107,8 +107,7 @@
           raisedEvent.setProperty("subscription", &subscriptionObj);
           subscriptionObj.setProperty<const std::string&>("name", _subscription.getEventName());
           
-          ctx->loadFromFile(scriptName);
-          ctx->evaluate<void>();
+          ctx->evaluateScript<void>(scriptName);
 
           if(ctx->getKeepContext()) {
             m_KeptContexts.push_back(ctx);

Modified: dss/trunk/core/jshandler.cpp
===================================================================
--- dss/trunk/core/jshandler.cpp	2009-09-29 13:57:47 UTC (rev 8807)
+++ dss/trunk/core/jshandler.cpp	2009-09-29 14:08:06 UTC (rev 8808)
@@ -23,6 +23,8 @@
 
 #include <cstring>
 #include <sstream>
+#include <fstream>
+#include <iostream>
 
 #include "core/logger.h"
 
@@ -60,7 +62,6 @@
     JSContext* context = JS_NewContext(m_pRuntime, 8192);
 
     ScriptContext* pResult = new ScriptContext(*this, context);
-    JS_SetContextPrivate(context, pResult);
     for(boost::ptr_vector<ScriptExtension>::iterator ipExtension = m_Extensions.begin(); ipExtension != m_Extensions.end(); ++ipExtension) {
       ipExtension->extendContext(*pResult);
     }
@@ -103,8 +104,7 @@
       line = (char*)malloc(len);
       strncpy(line, er->linebuf, len);
       line[len-1] = '\0';
-    }
-    else {
+    } else {
       len=0;
       pointer = (char*)malloc(1);
       line = (char*)malloc(1);
@@ -167,8 +167,7 @@
   };
 
   ScriptContext::ScriptContext(ScriptEnvironment& _env, JSContext* _pContext)
-  : m_pScriptToExecute(NULL),
-    m_Environment(_env),
+  : m_Environment(_env),
     m_pContext(_pContext),
     m_KeepContext(false)
   {
@@ -190,54 +189,33 @@
       throw ScriptException("InitStandardClasses failed");
     }
 
+    JS_SetContextPrivate(m_pContext, this);
   } // ctor
 
   ScriptContext::~ScriptContext() {
+    scrubVector(m_AttachedObjects);
     JS_SetContextPrivate(m_pContext, NULL);
-//    JS_RemoveRoot(m_pContext, m_pSourceObject);
-    if(m_pScriptToExecute != NULL) {
-      JS_DestroyScript(m_pContext, m_pScriptToExecute);
-    }
     JS_DestroyContext(m_pContext);
+    m_pContext = NULL;
   } // dtor
 
-  void ScriptContext::loadFromFile(const std::string& _fileName) {
-    if(m_pScriptToExecute != NULL) {
-      JS_DestroyScript(m_pContext, m_pScriptToExecute);
-    }
-    m_FileName = _fileName;
-    if(!fileExists(_fileName)) {
-      throw ScriptException(std::string("File \"") + _fileName + "\" not found");
-    }
+  void ScriptContext::attachObject(ScriptContextAttachedObject* _pObject) {
+    m_AttachedObjects.push_back(_pObject);
+  } // attachObject
 
-    m_pScriptToExecute = JS_CompileFile(m_pContext, m_pRootObject, _fileName.c_str());
-    if(m_pScriptToExecute == NULL) {
-      throw ScriptException(std::string("Could not parse file \"") + _fileName + "\"");
+  void ScriptContext::removeAttachedObject(ScriptContextAttachedObject* _pObject) {
+    std::vector<ScriptContextAttachedObject*>::iterator it =
+       std::find(m_AttachedObjects.begin(), m_AttachedObjects.end(), _pObject);
+    if(it != m_AttachedObjects.end()) {
+      m_AttachedObjects.erase(it);
+      delete _pObject;
     }
-    /*
-    // protect newly allocated script from garbage-collection
-    m_pSourceObject = JS_NewScriptObject(m_pContext, m_pScriptToExecute);
-    if (m_pSourceObject == NULL
-        || !JS_AddNamedRoot(m_pContext, &m_pSourceObject, "scrobj")) {
-      throw ScriptException("Could not add named root for script");
-    }
-    */
-  } // loadFromFile
+  } // removeAttachedObject
 
-  void ScriptContext::loadFromMemory(const char* _script) {
-    if(m_pScriptToExecute != NULL) {
-      JS_DestroyScript(m_pContext, m_pScriptToExecute);
-    }
-    m_pScriptToExecute = JS_CompileScript(m_pContext, m_pRootObject, _script, strlen(_script), "memory", 1);
-    if(m_pScriptToExecute == NULL) {
-      throw ScriptException(std::string("Could not parse in-memory script"));
-    }
-  } // loadFromMemory
-  
   template<>
   jsval ScriptContext::convertTo(const jsval& _val) {
     return _val;
-  }
+  } // convertTo<jsval>
  
   template<>
   int ScriptContext::convertTo(const jsval& _val) {
@@ -298,48 +276,58 @@
     }
     return false;
   } // raisePendingExceptions
-      
+
   template <>
-  jsval ScriptContext::evaluate() {
+  jsval ScriptContext::evaluateScript(const std::string& _fileName) {
     AssertLocked(this);
+
+    std::ifstream in(_fileName.c_str());
+    std::string line;
+    std::stringstream sstream;
+    while(std::getline(in,line)) {
+      sstream << line << "\n";
+    }
     jsval rval;
-    JSBool ok = JS_ExecuteScript(m_pContext, m_pRootObject, m_pScriptToExecute, &rval);
+    std::string script = sstream.str();
+    JSBool ok = JS_EvaluateScript(m_pContext, m_pRootObject, script.c_str(), script.size(),
+                       _fileName.c_str(), 0, &rval);
     if(ok) {
       return rval;
     } else {
       raisePendingExceptions();
       throw ScriptException("Error executing script");
     }
-  } // evaluate<jsval>
-  
+  } // evaluateScript
+
   template <>
-  void ScriptContext::evaluate() {
-    evaluate<jsval>();
-  } // evaluate<void>
-  
+  void ScriptContext::evaluateScript(const std::string& _script) {
+    evaluateScript<jsval>(_script);
+  } // evaluateScript<void>
+
   template <>
-  double ScriptContext::evaluate() {
-    return convertTo<double>(evaluate<jsval>());
-  } // evaluate<double>
+  int ScriptContext::evaluateScript(const std::string& _script) {
+    return convertTo<int>(evaluateScript<jsval>(_script));
+  } // evaluateScript<int>
 
   template <>
-  int ScriptContext::evaluate() {
-    return convertTo<int>(evaluate<jsval>());
-  } // evaluate<int>
+  double ScriptContext::evaluateScript(const std::string& _script) {
+    return convertTo<double>(evaluateScript<jsval>(_script));
+  } // evaluateScript<double>
 
   template <>
-  bool ScriptContext::evaluate() {
-    return convertTo<bool>(evaluate<jsval>());
-  } // evaluate<bool>
+  std::string ScriptContext::evaluateScript(const std::string& _script) {
+    return convertTo<std::string>(evaluateScript<jsval>(_script));
+  } // evaluateScript<std::string>
 
   template <>
-  std::string ScriptContext::evaluate() {
-    return convertTo<std::string>(evaluate<jsval>());
-  } // evaluate<string>
+  bool ScriptContext::evaluateScript(const std::string& _script) {
+    return convertTo<bool>(evaluateScript<jsval>(_script));
+  } // evaluateScript<bool>
 
   template <>
-  jsval ScriptContext::evaluateScript(const std::string& _script) {
+  jsval ScriptContext::evaluate(const std::string& _script) {
     AssertLocked(this);
+
     const char* filename = "temporary_script";
     jsval rval;
     JSBool ok = JS_EvaluateScript(m_pContext, m_pRootObject, _script.c_str(), _script.size(),
@@ -350,32 +338,32 @@
       raisePendingExceptions();
       throw ScriptException("Error executing script");
     }
-  } // evaluateScript
+  } // evaluate
   
   template <>
-  void ScriptContext::evaluateScript(const std::string& _script) {
-    evaluateScript<jsval>(_script);
-  } // evaluateScript<void>
+  void ScriptContext::evaluate(const std::string& _script) {
+    evaluate<jsval>(_script);
+  } // evaluate<void>
 
   template <>
-  int ScriptContext::evaluateScript(const std::string& _script) {
-    return convertTo<int>(evaluateScript<jsval>(_script));
-  } // evaluateScript<int>
+  int ScriptContext::evaluate(const std::string& _script) {
+    return convertTo<int>(evaluate<jsval>(_script));
+  } // evaluate<int>
 
   template <>
-  double ScriptContext::evaluateScript(const std::string& _script) {
-    return convertTo<double>(evaluateScript<jsval>(_script));
-  } // evaluateScript<double>
+  double ScriptContext::evaluate(const std::string& _script) {
+    return convertTo<double>(evaluate<jsval>(_script));
+  } // evaluate<double>
 
   template <>
-  std::string ScriptContext::evaluateScript(const std::string& _script) {
-    return convertTo<std::string>(evaluateScript<jsval>(_script));
-  } // evaluateScript<std::string>
+  std::string ScriptContext::evaluate(const std::string& _script) {
+    return convertTo<std::string>(evaluate<jsval>(_script));
+  } // evaluate<std::string>
 
   template <>
-  bool ScriptContext::evaluateScript(const std::string& _script) {
-    return convertTo<bool>(evaluateScript<jsval>(_script));
-  } // evaluateScript<bool>
+  bool ScriptContext::evaluate(const std::string& _script) {
+    return convertTo<bool>(evaluate<jsval>(_script));
+  } // evaluate<bool>
 
 
   //================================================== ScriptExtension

Modified: dss/trunk/core/jshandler.h
===================================================================
--- dss/trunk/core/jshandler.h	2009-09-29 13:57:47 UTC (rev 8807)
+++ dss/trunk/core/jshandler.h	2009-09-29 14:08:06 UTC (rev 8808)
@@ -26,6 +26,10 @@
 #include "config.h"
 #endif
 
+#include <iostream>
+
+#define JS_THREADSAFE
+
 #ifdef HAVE_MOZJS_JSAPI_H
 #include <mozjs/jsapi.h>
 #else
@@ -43,6 +47,7 @@
   class ScriptContext;
   class ScriptExtension;
   class ScriptObject;
+  class ScriptContextAttachedObject;
 
   /** Wrapper for a script runtime environment. The ScriptEnvironment
     * is also responsible for creating Contexts and enhancing them with
@@ -76,40 +81,25 @@
     * a std::string contained in memory. */
   class ScriptContext : public LockableObject {
   private:
-    JSScript* m_pScriptToExecute;
     std::string m_FileName;
     JSObject* m_pRootObject;
     boost::scoped_ptr<ScriptObject> m_RootObject;
-    JSObject* m_pSourceObject;
     ScriptEnvironment& m_Environment;
     JSContext* m_pContext;
     bool m_KeepContext;
+    std::vector<ScriptContextAttachedObject*> m_AttachedObjects;
     static void jsErrorHandler(JSContext *ctx, const char *msg, JSErrorReport *er);
   public:
     ScriptContext(ScriptEnvironment& _env, JSContext* _pContext);
     virtual ~ScriptContext();
 
-    /** Loads the script from File
-      * @throw runtime_error if _fileName does not exist
-      * @throw ScriptException if there is something wrong with the script
-      */
-    void loadFromFile(const std::string& _fileName);
-    /** Loads the script from Memory.
-      * @throw ScriptException if there is something wrong with the script
-      */
-    void loadFromMemory(const char* _script);
-
-    /** Evaluates the previously loaded script. The result of the script
-      * will be casted to typeof t.
-      * @throw ScriptRuntimeException if the script raised an exception
-      * @throw SciptException
-      */
+    /** Evaluates the given script */  
     template <class t>
-    t evaluate();
+    t evaluate(const std::string& _script);
 
-    /** Evaluates the given script */  
+    /** Evaluates the given file */
     template <class t>
-    t evaluateScript(const std::string& _script);
+    t evaluateScript(const std::string& _fileName);
 
     /** Returns a pointer to the JSContext */
     JSContext* getJSContext() { return m_pContext; }
@@ -120,12 +110,15 @@
     bool raisePendingExceptions();
     bool getKeepContext() { return m_KeepContext; };
     void setKeepContext(bool _value) { m_KeepContext = _value; }
+
+    void attachObject(ScriptContextAttachedObject* _pObject);
+    void removeAttachedObject(ScriptContextAttachedObject* _pObject);
   public:
 
     /** Helper function to convert a jsval to a t. */
     template<class t>
     t convertTo(const jsval& _val);
-  };
+  }; // ScriptContext
 
   /** Exception class that will be raised if anything out of the
     * ordinary should happen. */
@@ -222,8 +215,15 @@
 
     template<class t>
     t callFunctionByReference(jsval _function, ScriptFunctionParameterList& _parameter);
-}; // ScriptObject
+  }; // ScriptObject
 
+  class ScriptContextAttachedObject {
+  public:
+    ~ScriptContextAttachedObject() {
+      std::cout << "destroying attached object" << std::endl;
+    }
+  }; // ScriptContextAttachedObject
+
 } // namespace dss
 
 #endif

Modified: dss/trunk/core/scripting/modeljs.cpp
===================================================================
--- dss/trunk/core/scripting/modeljs.cpp	2009-09-29 13:57:47 UTC (rev 8807)
+++ dss/trunk/core/scripting/modeljs.cpp	2009-09-29 14:08:06 UTC (rev 8808)
@@ -985,6 +985,8 @@
             new PropertyScriptListener(ext, ctx, obj, argv[1], ident);
         ext->addListener(listener);
         node->addListener(listener);
+        ctx->attachObject(listener);
+
         JSString* str = JS_NewStringCopyZ(cx, ident.c_str());
         *rval = STRING_TO_JSVAL(str);
       }
@@ -1034,14 +1036,15 @@
   } // addListener
 
   void PropertyScriptExtension::removeListener(const std::string& _identifier) {
-    for(boost::ptr_vector<PropertyScriptListener>::iterator it = m_Listeners.begin(), e = m_Listeners.end();
+    for(std::vector<PropertyScriptListener*>::iterator it = m_Listeners.begin(), e = m_Listeners.end();
         it != e; ++it) {
-      if(it->getIdentifier() == _identifier) {
-        it->unsubscribe();
+      if((*it)->getIdentifier() == _identifier) {
+        (*it)->unsubscribe();
+        m_Listeners.erase(it);
         return;
       }
     }
-  }
+  } // removeListener
 
 
   //================================================== PropertyScriptListener
@@ -1056,8 +1059,15 @@
     m_pFunctionObject(_functionObj),
     m_Function(_function),
     m_Identifier(_identifier)
-  { } // ctor
+  {
+    JS_AddRoot(_pContext->getJSContext(), &m_Function);
+  } // ctor
 
+  PropertyScriptListener::~PropertyScriptListener() {
+    m_pExtension->removeListener(m_Identifier);
+    JS_RemoveRoot(m_pContext->getJSContext(), &m_Function);
+  } // dtor
+
   void PropertyScriptListener::createScriptObject() {
     if(m_pScriptObject == NULL) {
       m_pScriptObject.reset(new ScriptObject(m_pFunctionObject, *m_pContext));
@@ -1076,10 +1086,15 @@
   } // propertyAdded
 
   void PropertyScriptListener::doOnChange(PropertyNodePtr _changedNode) {
+    AssertLocked locked(m_pContext);
     createScriptObject();
     ScriptFunctionParameterList list(*m_pContext);
     list.add(_changedNode->getDisplayName());
-    m_pScriptObject->callFunctionByReference<void>(m_Function, list);
+    try {
+      m_pScriptObject->callFunctionByReference<void>(m_Function, list);
+    } catch(ScriptRuntimeException& e) {
+      Logger::getInstance()->log("PropertyScriptListener::doOnChange: Caught exception while calling handler: " + std::string(e.what()), lsFatal);
+    }
   } // doOnChange
 
 } // namespace

Modified: dss/trunk/core/scripting/modeljs.h
===================================================================
--- dss/trunk/core/scripting/modeljs.h	2009-09-29 13:57:47 UTC (rev 8807)
+++ dss/trunk/core/scripting/modeljs.h	2009-09-29 14:08:06 UTC (rev 8808)
@@ -91,9 +91,11 @@
   class PropertyNode;
   class PropertyScriptExtension;
   
-  class PropertyScriptListener : public PropertyListener {
+  class PropertyScriptListener : public PropertyListener,
+                                 public ScriptContextAttachedObject {
   public:
     PropertyScriptListener(PropertyScriptExtension* _pExtension, ScriptContext* _pContext, JSObject* _functionObj, jsval _function, const std::string& _identifier);
+    virtual ~PropertyScriptListener();
 
     virtual void propertyChanged(PropertyNodePtr _changedNode);
     virtual void propertyRemoved(PropertyNodePtr _parent, PropertyNodePtr _child);
@@ -127,7 +129,7 @@
     void removeListener(const std::string& _identifier);
   private:
     PropertySystem& m_PropertySystem;
-    boost::ptr_vector<PropertyScriptListener> m_Listeners;
+    std::vector<PropertyScriptListener*> m_Listeners;
     int m_NextListenerID;
   }; // PropertyScriptExtension
 

Modified: dss/trunk/core/sim/dsid_js.cpp
===================================================================
--- dss/trunk/core/sim/dsid_js.cpp	2009-09-29 13:57:47 UTC (rev 8807)
+++ dss/trunk/core/sim/dsid_js.cpp	2009-09-29 14:08:06 UTC (rev 8808)
@@ -23,22 +23,25 @@
 #include "core/jshandler.h"
 #include "core/scripting/modeljs.h"
 #include "core/dss.h"
+#include "core/thread.h"
 
 namespace dss {
 
   class DSIDJS : public DSIDInterface {
   public:
     DSIDJS(const DSModulatorSim& _simulator, dsid_t _dsid,
-           devid_t _shortAddress, boost::shared_ptr<ScriptContext> _pContext)
+           devid_t _shortAddress, boost::shared_ptr<ScriptContext> _pContext,
+           const std::string& _fileName)
     : DSIDInterface(_simulator, _dsid, _shortAddress),
-      m_pContext(_pContext)
+      m_pContext(_pContext),
+      m_FileName(_fileName)
     {}
 
     virtual ~DSIDJS() {}
 
     virtual void initialize() {
       try {
-        jsval res = m_pContext->evaluate<jsval>();
+        jsval res = m_pContext->evaluateScript<jsval>(m_FileName);
         if(JSVAL_IS_OBJECT(res)) {
           m_pJSThis = JSVAL_TO_OBJECT(res);
           m_pSelf.reset(new ScriptObject(m_pJSThis, *m_pContext));
@@ -253,6 +256,7 @@
     boost::shared_ptr<ScriptContext> m_pContext;
     JSObject* m_pJSThis;
     boost::shared_ptr<ScriptObject> m_pSelf;
+    std::string m_FileName;
   }; // DSIDJS
 
 
@@ -282,6 +286,23 @@
     DSSim& m_Simulation;
   }; // PropertyScriptExtension
 
+  class DSLinkInterrupSender : public Thread {
+  public:
+    DSLinkInterrupSender(dsid_t _dsid, DSIDScriptExtension* _ext)
+    : Thread("DSLinkInterruptSender"),
+      m_DSID(_dsid), m_Ext(_ext)
+    {
+      setFreeAtTermination(true);
+    }
+    virtual void execute() {
+      sleepMS(rand() % 3000);
+      m_Ext->dSLinkInterrupt(m_DSID);
+    }
+  private:
+    dsid_t m_DSID;
+    DSIDScriptExtension* m_Ext;
+  };
+
   JSBool global_dsid_dSLinkInterrupt(JSContext* cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) {
     if(argc < 1) {
       Logger::getInstance()->log("JS: glogal_dsid_dSLinkInterrupt: need argument dsid", lsError);
@@ -293,7 +314,8 @@
 
       try {
         dsid_t dsid = dsid_t::fromString(dsidString);
-        ext->dSLinkInterrupt(dsid);
+        DSLinkInterrupSender* sender = new DSLinkInterrupSender(dsid, ext);
+        sender->run();
       } catch(std::runtime_error&) {
         Logger::getInstance()->log("Could not parse DSID");
       }
@@ -329,12 +351,7 @@
 
   DSIDInterface* DSIDJSCreator::createDSID(const dsid_t _dsid, const devid_t _shortAddress, const DSModulatorSim& _modulator) {
     boost::shared_ptr<ScriptContext> pContext(m_pScriptEnvironment->getContext());
-    try {
-      pContext->loadFromFile(m_FileName);
-    } catch(ScriptException& e) {
-      Logger::getInstance()->log("DSIDJSCreator: Could not parse file: " + m_FileName + "(" + e.what() + ")", lsError);
-    }
-    DSIDJS* result = new DSIDJS(_modulator, _dsid, _shortAddress, pContext);
+    DSIDJS* result = new DSIDJS(_modulator, _dsid, _shortAddress, pContext, m_FileName);
     return result;
   } // createDSID
 

Modified: dss/trunk/tests/jshandlertests.cpp
===================================================================
--- dss/trunk/tests/jshandlertests.cpp	2009-09-29 13:57:47 UTC (rev 8807)
+++ dss/trunk/tests/jshandlertests.cpp	2009-09-29 14:08:06 UTC (rev 8808)
@@ -42,13 +42,13 @@
   BOOST_CHECK_EQUAL(obj.getProperty<int>("testing"), 1);
   ctx->getRootObject().setProperty("obj", &obj);
 
-  BOOST_CHECK_EQUAL(ctx->evaluateScript<int>("obj.testing"), 1);
+  BOOST_CHECK_EQUAL(ctx->evaluate<int>("obj.testing"), 1);
   obj.setProperty("testing", 0);
-  BOOST_CHECK_EQUAL(ctx->evaluateScript<int>("obj.testing"), 0);
+  BOOST_CHECK_EQUAL(ctx->evaluate<int>("obj.testing"), 0);
 
   obj.setProperty("testing2", "test");
   BOOST_CHECK_EQUAL(obj.getProperty<std::string>("testing2"), "test");
-  BOOST_CHECK_EQUAL(ctx->evaluateScript<std::string>("obj.testing2"), "test");
+  BOOST_CHECK_EQUAL(ctx->evaluate<std::string>("obj.testing2"), "test");
 } // testSimpleObject
 
 BOOST_AUTO_TEST_CASE(testCallingFunctions) {
@@ -56,7 +56,7 @@
   env->initialize();
 
   boost::scoped_ptr<ScriptContext> ctx(env->getContext());
-  jsval res = ctx->evaluateScript<jsval>("dev = { func: function(a,b,c) { return { e: a, f: b, g: c }; } }; dev");
+  jsval res = ctx->evaluate<jsval>("dev = { func: function(a,b,c) { return { e: a, f: b, g: c }; } }; dev");
 
   BOOST_ASSERT(JSVAL_IS_OBJECT(res));
 

Modified: dss/trunk/tests/modeljstests.cpp
===================================================================
--- dss/trunk/tests/modeljstests.cpp	2009-09-29 13:57:47 UTC (rev 8807)
+++ dss/trunk/tests/modeljstests.cpp	2009-09-29 14:08:06 UTC (rev 8808)
@@ -47,17 +47,12 @@
   env->addExtension(ext);
 
   boost::scoped_ptr<ScriptContext> ctx(env->getContext());
-  ctx->loadFromMemory("getName()");
-  string name = ctx->evaluate<string>();
+  string name = ctx->evaluate<string>("getName()");
 
   BOOST_CHECK_EQUAL(apt.getName(), name);
 
-  ctx.reset(env->getContext());
-  ctx->loadFromMemory("setName('hello'); getName()");
+  name = ctx->evaluate<string>("setName('hello'); getName()");
 
-  name = ctx->evaluate<string>();
-  ctx.reset();
-
   BOOST_CHECK_EQUAL(string("hello"), name);
   BOOST_CHECK_EQUAL(string("hello"), apt.getName());
 } // testBasics
@@ -77,14 +72,11 @@
   env->addExtension(ext);
 
   boost::scoped_ptr<ScriptContext> ctx(env->getContext());
-  ctx->loadFromMemory("var devs = getDevices(); devs.length()");
-  int length = ctx->evaluate<int>();
+  int length = ctx->evaluate<int>("var devs = getDevices(); devs.length()");
 
   BOOST_CHECK_EQUAL(2, length);
 
-  ctx.reset(env->getContext());
-  ctx->loadFromMemory("var devs = getDevices(); var devs2 = getDevices(); devs.combine(devs2)");
-  ctx->evaluate<void>();
+  ctx->evaluate<void>("var devs = getDevices(); var devs2 = getDevices(); devs.combine(devs2)");
 } // testSets
 
 BOOST_AUTO_TEST_CASE(testDevices) {
@@ -104,10 +96,9 @@
   env->addExtension(ext);
 
   boost::scoped_ptr<ScriptContext> ctx(env->getContext());
-  ctx->loadFromMemory("var devs = getDevices();\n"
+  ctx->evaluate<void>("var devs = getDevices();\n"
                       "var f = function(dev) { print(dev.name); }\n"
                       "devs.perform(f)\n");
-  ctx->evaluate<void>();
 } // testDevices
 
 BOOST_AUTO_TEST_CASE(testEvents) {
@@ -139,10 +130,10 @@
   BOOST_CHECK_EQUAL(interpreter.getNumberOfSubscriptions(), 0);
 
   boost::scoped_ptr<ScriptContext> ctx(env->getContext());
-  ctx->loadFromMemory("var evt = new event('test');\n"
+  ctx->evaluate<void>("var evt = new event('test');\n"
                       "evt.raise()\n"
                       "\n");
-  ctx->evaluate<void>();
+  // TODO: add subscription to confirm the event actually got raised
 } // testEvents
 
 BOOST_AUTO_TEST_CASE(testSubscriptions) {
@@ -174,10 +165,9 @@
   BOOST_CHECK_EQUAL(interpreter.getNumberOfSubscriptions(), 0);
 
   boost::scoped_ptr<ScriptContext> ctx(env->getContext());
-  ctx->loadFromMemory("var s = new subscription('test', 'test', { 'param1': 1, 'param2': 2, 'string': 'string'} );\n"
+  ctx->evaluate<void>("var s = new subscription('test', 'test', { 'param1': 1, 'param2': 2, 'string': 'string'} );\n"
                       "s.subscribe();\n"
                       "\n");
-  ctx->evaluate<void>();
 
   BOOST_CHECK_EQUAL(interpreter.getNumberOfSubscriptions(), 1);
 } // testSubscriptions
@@ -190,12 +180,12 @@
   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);
+  ctx->evaluate<void>("setProperty('/testing', 1)");
+  BOOST_CHECK_EQUAL(ctx->evaluate<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_CHECK_EQUAL(ctx->evaluate<int>("getProperty('/testing')"), 2);
 }
 
 BOOST_AUTO_TEST_CASE(testPropertyListener) {
@@ -206,8 +196,8 @@
   env->addExtension(ext);
 
   boost::scoped_ptr<ScriptContext> ctx(env->getContext());
-  ctx->evaluateScript<void>("setProperty('/testing', 1); setProperty('/triggered', false); "
-                            "listener_ident = setListener('/testing', function(changedNode) { setProperty('/triggered', true); }); "
+  ctx->evaluate<void>("setProperty('/testing', 1); setProperty('/triggered', false); "
+                      "listener_ident = setListener('/testing', function(changedNode) { setProperty('/triggered', true); }); "
       );
 
   BOOST_CHECK_EQUAL(propSys.getBoolValue("/triggered"), false);
@@ -219,7 +209,7 @@
   BOOST_CHECK_EQUAL(propSys.getIntValue("/testing"), 2);
 
   // check that removing works
-  ctx->evaluateScript<void>("removeListener(listener_ident);");
+  ctx->evaluate<void>("removeListener(listener_ident);");
 
   propSys.setBoolValue("/triggered", false);
   BOOST_CHECK_EQUAL(propSys.getBoolValue("/triggered"), false);
@@ -230,8 +220,8 @@
   BOOST_CHECK_EQUAL(propSys.getIntValue("/testing"), 2);
 
   // check that closures are working as expected
-  ctx->evaluateScript<void>("setProperty('/triggered', false); "
-                            "var ident = setListener('/testing', function(changedNode) { setProperty('/triggered', true); removeListener(ident); }); "
+  ctx->evaluate<void>("setProperty('/triggered', false); "
+                      "var ident = setListener('/testing', function(changedNode) { setProperty('/triggered', true); removeListener(ident); }); "
       );
 
   BOOST_CHECK_EQUAL(propSys.getBoolValue("/triggered"), false);
@@ -258,14 +248,21 @@
   env->addExtension(ext);
 
   boost::scoped_ptr<ScriptContext> ctx(env->getContext());
-  ctx->evaluateScript<void>("setProperty('/testing', 1); setProperty('/triggered', false); "
-                            "setListener('/triggered', function() { setProperty('/itWorks', true); } ); "
+  ctx->evaluate<void>("setProperty('/testing', 1); setProperty('/triggered', false); "
+                            "other_ident = setListener('/triggered', function() { setProperty('/itWorks', true); } ); "
                             "listener_ident = setListener('/testing', function(changedNode) { setProperty('/triggered', true); }); "
       );
       
   propSys.setBoolValue("/testing", true);
   
   BOOST_CHECK_EQUAL(propSys.getBoolValue("/itWorks"), true);
+
+  // TODO: find out why it crashes w/o those lines
+  ctx->evaluate<void>("removeListener(other_ident); "
+                      "removeListener(listener_ident); "
+      );
+
+  ctx.reset();
 } // testReentrancy
 
 class TestThreadingThread : public Thread {
@@ -294,9 +291,9 @@
   env->addExtension(ext);
 
   boost::scoped_ptr<ScriptContext> ctx(env->getContext());
-  ctx->evaluateScript<void>("var func = setProperty('/testing1', 1); setProperty('/testing2', 1); "
-                            "setListener('/testing1', function() { setProperty('/itWorks', true); } ); "
-                            "setListener('/testing2', function() { setProperty('/itWorks', true); } ); "
+  ctx->evaluate<void>("var func = setProperty('/testing1', 1); setProperty('/testing2', 1); "
+                      "l1 = setListener('/testing1', function() { setProperty('/itWorks', true); } ); "
+                      "l2 = setListener('/testing2', function() { setProperty('/itWorks', true); } ); "
       );
       
   PropertyNodePtr node1 = propSys.getProperty("/testing1");
@@ -329,6 +326,9 @@
     t2.terminate();
     sleepMS(500);
   }
+
+  // TODO: find out why it crashes w/o those lines
+  ctx->evaluate<void>("removeListener(l1); removeListener(l2);");
 } // testThreading
 
 BOOST_AUTO_TEST_SUITE_END()

Modified: dss/trunk/tests/scriptstest.cpp
===================================================================
--- dss/trunk/tests/scriptstest.cpp	2009-09-29 13:57:47 UTC (rev 8807)
+++ dss/trunk/tests/scriptstest.cpp	2009-09-29 14:08:06 UTC (rev 8808)
@@ -35,34 +35,26 @@
 BOOST_AUTO_TEST_CASE(testSimpleScripts) {
   ScriptEnvironment env;
   env.initialize();
-  ScriptContext* ctx = env.getContext();
-  ctx->loadFromMemory("x = 10; print(x); x = x * x;");
-  double result = ctx->evaluate<double>();
+  boost::scoped_ptr<ScriptContext> ctx(env.getContext());
+  double result = ctx->evaluate<double>("x = 10; print(x); x = x * x;");
   BOOST_CHECK_EQUAL(result, 100.0);
-  delete ctx;
 
-  ctx = env.getContext();
-  ctx->loadFromFile("data/test.js");
-  result = ctx->evaluate<double>();
+  ctx.reset(env.getContext());
+  result = ctx->evaluateScript<double>("data/test.js");
   BOOST_CHECK_EQUAL(result, 100.0);
-  delete ctx;
 
-  ctx = env.getContext();
-  ctx->loadFromMemory("x = 'bla'; x = x + 'bla';");
-  string sres = ctx->evaluate<string>();
+  ctx.reset(env.getContext());
+  string sres = ctx->evaluate<string>("x = 'bla'; x = x + 'bla';");
   BOOST_CHECK_EQUAL(sres, string("blabla"));
-  delete ctx;
 } // testSimpleScripts
 
 BOOST_AUTO_TEST_CASE(testMultipleIterations) {
   ScriptEnvironment env;
   env.initialize();
   for(int i = 0; i < 100; i++) {
-    ScriptContext* ctx = env.getContext();
-    ctx->loadFromFile("data/test3.js");
-    ctx->evaluate<void>();
+    boost::scoped_ptr<ScriptContext> ctx(env.getContext());
+    ctx->evaluateScript<void>("data/test3.js");
     cout << ".";
-    delete ctx;
   }
   cout << endl;
 } // testMultipleIterations
@@ -71,9 +63,8 @@
   ScriptEnvironment* env = new ScriptEnvironment();
   env->initialize();
   ScriptContext* ctx = env->getContext();
-  ctx->loadFromMemory("x = {}; x.what = 'bla'; x.toString = function() { return 'bla'; }; throw x; x = 10;");
   try {
-    ctx->evaluate<double>();
+    ctx->evaluate<double>("x = {}; x.what = 'bla'; x.toString = function() { return 'bla'; }; throw x; x = 10;");
     BOOST_CHECK(false);
   } catch(ScriptRuntimeException& _ex) {
     BOOST_CHECK_EQUAL(_ex.getExceptionMessage(), string("bla"));



More information about the dss-commits mailing list