COOPY » Guide
version 0.6.5
|
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 }