2 // Tizen Web Device API
3 // Copyright (c) 2013 Samsung Electronics Co., Ltd.
5 // Licensed under the Apache License, Version 2.0 (the License);
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
9 // http://www.apache.org/licenses/LICENSE-2.0
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
20 #include <JavaScriptCore/JavaScript.h>
21 #include "StandaloneConsole.h"
22 #include "JSConsole.h"
24 #include <GlobalContextManager.h>
29 #define LOG_TAG "TIZEN_DEVICEAPI"
32 using namespace DeviceAPI::Common;
40 StandaloneConsole *mConsole;
41 pthread_mutex_t *mLock;
42 _Command(const char * cmd, StandaloneConsole *console, pthread_mutex_t* lock){
51 mConsole->RunLine(mLine);
52 pthread_mutex_unlock(mLock);
59 StandaloneConsole *console;
62 static Eina_Bool tick(void *data){
66 static Eina_Bool commandDispath(void *data){
67 _Command *cmd = (_Command*)data;
73 Eina_Bool StandaloneConsole::timerCb(void *data){
74 CallbackData *callback = (CallbackData*)data;
75 StandaloneConsole *console = callback->console;
76 map<int,int>::iterator itr;
77 itr = console->mTimerMap.find(callback->id);
78 if( itr == console->mTimerMap.end() ){
79 JSValueUnprotect(console->getGlobalContext(), callback->callback);
83 if( itr->second == 0){
84 console->mTimerMap.erase(itr);
85 JSValueUnprotect(console->getGlobalContext(), callback->callback);
89 if( callback->callback != NULL){
90 JSObjectCallAsFunction(console->getGlobalContext(), callback->callback, NULL, 0, 0, NULL);
93 if( itr->second == 2 ){
94 console->mTimerMap.erase(itr);
95 JSValueUnprotect(console->getGlobalContext(), callback->callback);
104 JSValueRef StandaloneConsole::alert(JSContextRef ctx, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception){
105 if( argumentCount < 1 )
106 return JSValueMakeUndefined(ctx);
109 //JSContextRef globalCtx = GlobalContextManager::getInstance()->getGlobalContext(ctx);
110 //printf(" local : %p, global : %p \n", ctx, globalCtx);
112 JSStringRef str = JSValueToStringCopy(ctx, arguments[0], NULL);
114 return JSValueMakeUndefined(ctx);
116 int n = JSStringGetLength(str);
119 JSStringGetUTF8CString(str, cstr,n+1);
120 printf("<alert>%s\n", cstr);
122 return JSValueMakeUndefined(ctx);
125 JSValueRef StandaloneConsole::setInterval(JSContextRef ctx, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception){
127 StandaloneConsole *console = static_cast<StandaloneConsole*>(JSObjectGetPrivate(thisObject));
128 if( argumentCount < 2 ){
129 if( exception != NULL){
132 return JSValueMakeUndefined(ctx);
135 double interval = JSValueToNumber(ctx, arguments[1], NULL);
136 interval = interval/1000;
138 console->mTimerMap.insert(pair<int,int>(handleid, 1));
139 CallbackData *data = new CallbackData();
140 JSValueProtect(console->getGlobalContext(), arguments[0]);
141 data->callback = JSValueToObject(ctx, arguments[0], NULL);
143 data->console = console;
145 ecore_timer_add( interval, StandaloneConsole::timerCb , data);
146 return JSValueMakeNumber(ctx, handleid);
150 JSValueRef StandaloneConsole::setTimeout(JSContextRef ctx, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception){
152 StandaloneConsole *console = static_cast<StandaloneConsole*>(JSObjectGetPrivate(thisObject));
154 if( argumentCount < 2 ){
155 if( exception != NULL){
158 return JSValueMakeUndefined(ctx);
161 double interval = JSValueToNumber(ctx, arguments[1], NULL);
162 interval = interval/1000;
164 console->mTimerMap.insert(pair<int,int>(handleid, 2));
165 CallbackData *data = new CallbackData();
166 JSValueProtect(console->getGlobalContext(), arguments[0]);
167 data->callback = JSValueToObject(ctx, arguments[0], NULL);
169 data->console = console;
171 ecore_timer_add( interval, StandaloneConsole::timerCb , data);
172 return JSValueMakeNumber(ctx, handleid);
177 JSValueRef StandaloneConsole::clearInterval(JSContextRef ctx, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception){
178 StandaloneConsole *console = static_cast<StandaloneConsole*>(JSObjectGetPrivate(thisObject));
179 if(console == NULL) return JSValueMakeUndefined(ctx);
180 if( argumentCount < 1 ){
181 printf("error clearInterval\n");
182 if( exception != NULL){
185 return JSValueMakeUndefined(ctx);
188 int handleid = JSValueToNumber(ctx, arguments[0], NULL);
189 map<int,int>::iterator it;
190 it = console->mTimerMap.find(handleid);
191 if( it != console->mTimerMap.end())
192 console->mTimerMap[handleid] = 0;
193 return JSValueMakeUndefined(ctx);
197 static JSValueRef test(JSContextRef ctx, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception){
198 return JSValueMakeUndefined(ctx);
202 static void setProperty(JSContextRef ctx , JSObjectRef object, const char *name, JSValueRef value, JSPropertyAttributes attributes)
204 JSStringRef propertyName = JSStringCreateWithUTF8CString(name);
205 JSObjectSetProperty(ctx, object, propertyName, value,attributes, NULL );
206 JSStringRelease(propertyName);
209 static JSValueRef getProperty(JSContextRef ctx , JSObjectRef object, const char *name){
211 JSStringRef propertyName = JSStringCreateWithUTF8CString(name);
212 value = JSObjectGetProperty(ctx, object, propertyName, NULL);
213 JSStringRelease(propertyName);
217 static char * toString(JSContextRef ctx , JSValueRef jsV){
218 JSValueRef exception = NULL;
219 JSStringRef jsStr = JSValueToStringCopy(ctx, jsV, &exception);
220 if( exception != NULL )
222 int n = JSStringGetMaximumUTF8CStringSize(jsStr);
223 char *buf = new char[n+1];
224 JSStringGetUTF8CString(jsStr, buf, n+1);
225 JSStringRelease(jsStr);
229 StandaloneConsole::StandaloneConsole():mGlobalContext(NULL),mGlobalObject(NULL){
232 StandaloneConsole::~StandaloneConsole(){
235 void StandaloneConsole::initialize(){
237 JSStaticFunction functions[] = {
238 { "alert", StandaloneConsole::alert , kJSPropertyAttributeNone },
239 { "setInterval", StandaloneConsole::setInterval , kJSPropertyAttributeNone },
240 { "setTimeout", StandaloneConsole::setTimeout , kJSPropertyAttributeNone },
241 { "clearInterval", StandaloneConsole::clearInterval , kJSPropertyAttributeNone },
242 { "clearTimeout", StandaloneConsole::clearInterval , kJSPropertyAttributeNone },
243 { "test", test, kJSPropertyAttributeNone },
248 JSClassDefinition def = {
249 0, // current (and only) version is 0
250 kJSClassAttributeNone, //attributes
251 "global", //class name
252 NULL, // parent class
253 NULL, //static values
254 functions, // static functions
260 NULL, //deleteProperty
261 NULL, //getPropertyNames
262 NULL, // callAsConstructor
265 NULL // convertToType
268 JSClassRef globalClass = JSClassCreate(&def);
270 mGlobalContext = JSGlobalContextCreate(globalClass);
271 mGlobalObject = JSContextGetGlobalObject(mGlobalContext);
272 JSObjectSetPrivate(mGlobalObject, this);
273 JSObjectRef console = JSConsole::createJSObject(mGlobalContext);
274 setProperty(mGlobalContext, mGlobalObject, "console", console, kJSPropertyAttributeReadOnly);
277 //is it ecore bug? event was not invoke, it was added in another thread
278 ecore_timer_add(0.001, tick, NULL);
282 JSObjectRef StandaloneConsole::getGlobalObject(){
283 return mGlobalObject;
286 JSContextRef StandaloneConsole::getGlobalContext(){
287 return mGlobalContext;
291 JSValueRef StandaloneConsole::RunLineEx(const char* line, JSValueRef *exception){
292 JSStringRef jsScript = JSStringCreateWithUTF8CString(line);
293 JSValueRef ret = JSEvaluateScript(mGlobalContext, jsScript, NULL, NULL, 0, exception);
294 JSStringRelease(jsScript);
298 JSValueRef StandaloneConsole::RunScriptEx(const char* path, JSValueRef *exception){
300 FILE* f = fopen(path, "r");
305 fseek(f, 0, SEEK_END);
306 int length = ftell(f);
307 fseek(f, 0, SEEK_SET);
312 memset(buff, 0, length);
313 int r = fread(buff, 1, length, f);
317 printf("error read\n");
318 return JSValueMakeUndefined(mGlobalContext);
320 return RunLineEx(buff, exception);
323 return JSValueMakeUndefined(mGlobalContext);
326 void StandaloneConsole::RunLine(const char * line){
327 JSValueRef exception = NULL;
328 JSValueRef v = RunLineEx(line, &exception);
329 reportingResult(v,exception);
332 void StandaloneConsole::RunScript(const char * path){
333 JSValueRef exception = NULL;
334 JSValueRef v = RunScriptEx(path, &exception);
335 reportingResult(v,exception);
338 void StandaloneConsole::GarbageCollect(){
339 printf("GarbageCollect\n");
340 JSGarbageCollect(mGlobalContext);
342 void StandaloneConsole::reportingResult(JSValueRef v, JSValueRef exception){
343 if( exception != NULL ){
344 char *errStr = toString(mGlobalContext, exception);
345 if( errStr != NULL ){
346 printf("< error - %s\n", errStr);
349 JSObjectRef errObj = JSValueToObject(mGlobalContext, exception, NULL);
350 if( errObj != NULL ){
351 JSValueRef stack = getProperty(mGlobalContext, errObj, "stack");
352 char *stackStr = NULL;
353 if( !JSValueIsUndefined(mGlobalContext, stack) && (stackStr = toString(mGlobalContext, stack )) != NULL){
354 printf("stack:%s\n", stackStr);
359 char *resultStr = toString(mGlobalContext, v);
360 if( resultStr != NULL ){
361 printf("< %s\n", resultStr);
367 JSObjectRef StandaloneConsole::registModule(const char * name, JSClassRef module, void * priv){
368 JSObjectRef obj = JSObjectMake(mGlobalContext, module, priv);
369 setProperty(mGlobalContext, mGlobalObject, name, obj, kJSPropertyAttributeReadOnly);
373 void StandaloneConsole::appendModule(const char * name, JSObjectRef module){
374 setProperty(mGlobalContext, mGlobalObject, name, module, kJSPropertyAttributeReadOnly);
377 void StandaloneConsole::commandline(StandaloneConsole* console){
378 pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
379 pthread_mutex_lock(&lock);
380 printf("command line mode ( \"quit\" for exit )\n");
384 if( gets(line) == NULL )
386 if( strcmp(line, "quit") == 0 )
388 if( strcmp(line, "gc") == 0 ){
389 console->GarbageCollect();
392 if( strcmp(line, "") == 0 )
394 _Command *cmd = new _Command(line, console, &lock);
396 ecore_idler_add(commandDispath, cmd);
397 pthread_mutex_lock(&lock);