COOPY » Guide  version 0.6.5
/home/paulfitz/cvs/coopy_scm/coopy/src/libjs/JsWrap.cpp
Go to the documentation of this file.
00001 #include "jsapi.h"
00002 
00003 #include <coopy/JsWrap.h>
00004 
00005 using namespace coopy::js;
00006 using namespace std;
00007 
00008 static JSClass global_class = {
00009   "global", JSCLASS_GLOBAL_FLAGS,
00010   JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_StrictPropertyStub,
00011   JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub,
00012   JSCLASS_NO_OPTIONAL_MEMBERS
00013 };
00014 
00015 void reportError(JSContext *cx, const char *message, JSErrorReport *report) {
00016   fprintf(stderr, "%s:%u:%s\n",
00017           report->filename ? report->filename : "<no filename=\"filename\">",
00018           (unsigned int) report->lineno,
00019           message);
00020 }
00021 
00022 
00023 namespace coopy {
00024   namespace js {
00025     class JsWrapGlobal;
00026   }
00027 }
00028 
00029 class coopy::js::JsWrapGlobal {
00030 public:
00031   JSRuntime *rt;
00032   JSContext *cx;
00033   JSObject  *global;
00034   int id;
00035   int cid;
00036 
00037 
00038   bool init();
00039   bool fini();
00040   
00041 public:
00042   JsWrapGlobal() {
00043     rt = 0/*NULL*/;
00044     cx = 0/*NULL*/;
00045     global = 0/*NULL*/;
00046     id = 0;
00047     cid = -1;
00048     init();
00049   }
00050 
00051   virtual ~JsWrapGlobal() {
00052     fini();
00053   }
00054 
00055   std::string apply(const std::string& string);
00056 
00057   bool send(const std::string& function_name,
00058             const std::string& str);
00059 
00060   bool send(const std::string& function_name,
00061             jsval *val);
00062 
00063   int getId() {
00064     int r = id;
00065     id++;
00066     return id;
00067   }
00068 
00069   void setCurrentId(int i) {
00070     cid = i;
00071   }
00072 
00073   bool isCurrentId(int i) {
00074     return cid==i;
00075   }
00076 };
00077 
00078 
00079 
00080 bool JsWrapGlobal::init() {
00081   if (rt) return false;
00082 
00083   rt = JS_NewRuntime(8 * 1024 * 1024);
00084   if (!rt) return false;
00085 
00086   cx = JS_NewContext(rt, 8192);
00087   if (!cx) {
00088     JS_DestroyRuntime(rt);
00089     rt = NULL;
00090     return false;
00091   }
00092 
00093   JS_SetOptions(cx, JSOPTION_VAROBJFIX | JSOPTION_JIT | JSOPTION_METHODJIT);
00094   JS_SetVersion(cx, JSVERSION_LATEST);
00095   JS_SetErrorReporter(cx, reportError);
00096 
00097   global = JS_NewCompartmentAndGlobalObject(cx, &global_class, NULL);
00098   if (!global) {
00099     JS_DestroyContext(cx);
00100     cx = NULL;
00101     JS_DestroyRuntime(rt);
00102     rt = NULL;
00103     return false;
00104   }
00105 
00106   if (!JS_InitStandardClasses(cx, global)) {
00107     fini();
00108     return false;
00109   }
00110 
00111   return true;
00112 }
00113 
00114 bool JsWrapGlobal::fini() {
00115   if (!rt) return false;
00116   JS_DestroyContext(cx);
00117   cx = NULL;
00118   JS_DestroyRuntime(rt);
00119   rt = NULL;
00120   JS_ShutDown();
00121   global = NULL;
00122   return true;
00123 }
00124 
00125 
00126 string JsWrapGlobal::apply(const string& script) {
00127   jsval rval;
00128   JSString *str;
00129   JSBool ok;
00130   const char *filename = "noname";
00131   uintN lineno = 0;
00132 
00133   ok = JS_EvaluateScript(cx, global, script.c_str(), script.length(),
00134                          filename, lineno, &rval);
00135 
00136   if (!ok) return "";
00137   
00138   str = JS_ValueToString(cx, rval);
00139   return JS_EncodeString(cx, str);
00140 }
00141 
00142 bool JsWrapGlobal::send(const std::string& function_name, 
00143                         const std::string& str) {
00144   //dbg_printf("js: %s\n", function_name.c_str());
00145   JSBool ok;
00146   jsval rval;
00147   jsval lval;
00148 
00149   lval = STRING_TO_JSVAL(JS_NewStringCopyZ(cx,str.c_str()));
00150   ok = JS_CallFunctionName(cx, global, function_name.c_str(), 
00151                            1,&lval,&rval);
00152   return ok;
00153 }
00154 
00155 bool JsWrapGlobal::send(const std::string& function_name,
00156                         jsval *val) {
00157   //dbg_printf("js: %s\n", function_name.c_str());
00158   JSBool ok;
00159   jsval rval;
00160 
00161   ok = JS_CallFunctionName(cx, global, function_name.c_str(), 
00162                            1,val,&rval);
00163   return ok;
00164 }
00165 
00166 
00167 static int js_instance_count = 0;
00168 static JsWrapGlobal *js_global = NULL;
00169 
00170 JsWrap::JsWrap() {
00171   if (!js_global) js_global = new JsWrapGlobal();
00172   js_instance_count++;
00173 }
00174 
00175 JsWrap::~JsWrap() {
00176   js_instance_count--;
00177   if (js_instance_count==0&&js_global) {
00178     delete js_global;
00179     js_global = NULL;
00180   }
00181 }
00182 
00183 std::string JsWrap::apply(const std::string& str) {
00184   if (!js_global) return "";
00185   return js_global->apply(str);
00186 }
00187 
00188 bool JsWrap::send(const std::string& function_name, const std::string& str) {
00189   if (!js_global) return false;
00190   return js_global->send(function_name,str);
00191 }
00192 
00193 bool JsWrap::send(const std::string& function_name, jsval *val) {
00194   if (!js_global) return false;
00195   return js_global->send(function_name,val);
00196 }
00197 
00198 JSContext *JsWrap::context() const { 
00199   if (!js_global) return NULL;
00200   return js_global->cx;
00201 }
00202 
00203 JSObject *JsWrap::global() const {
00204   if (!js_global) return NULL;
00205   return js_global->global;
00206 }
00207 
00208 
00209 int JsWrap::getId() const {
00210   if (!js_global) return -1;
00211   return js_global->getId();
00212 }
00213 
00214 void JsWrap::setCurrentId(int i) const {
00215   if (!js_global) return;
00216   js_global->setCurrentId(i);
00217 }
00218 
00219 bool JsWrap::isCurrentId(int i) const {
00220   if (!js_global) return false;
00221   return js_global->isCurrentId(i);
00222 }
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines