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>
31 #define LOG_TAG "TIZEN_DEVICEAPI"
34 using namespace DeviceAPI::Common;
41 StandaloneConsole *mConsole;
42 pthread_mutex_t *mLock;
43 _Command(const char * cmd, StandaloneConsole *console, pthread_mutex_t* lock){
52 mConsole->RunLine(mLine);
53 pthread_mutex_unlock(mLock);
60 StandaloneConsole *console;
63 static Eina_Bool tick(void *data){
67 static Eina_Bool commandDispath(void *data){
68 _Command *cmd = (_Command*)data;
74 Eina_Bool StandaloneConsole::timerCb(void *data){
75 CallbackData *callback = (CallbackData*)data;
76 StandaloneConsole *console = callback->console;
77 map<int,int>::iterator itr;
78 itr = console->mTimerMap.find(callback->id);
79 if( itr == console->mTimerMap.end() ){
80 JSValueUnprotect(console->getGlobalContext(), callback->callback);
84 if( itr->second == 0){
85 console->mTimerMap.erase(itr);
86 JSValueUnprotect(console->getGlobalContext(), callback->callback);
90 if( callback->callback != NULL){
91 JSObjectCallAsFunction(console->getGlobalContext(), callback->callback, NULL, 0, 0, NULL);
94 if( itr->second == 2 ){
95 console->mTimerMap.erase(itr);
96 JSValueUnprotect(console->getGlobalContext(), callback->callback);
105 JSValueRef StandaloneConsole::alert(JSContextRef ctx, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception){
106 if( argumentCount < 1 )
107 return JSValueMakeUndefined(ctx);
110 //JSContextRef globalCtx = GlobalContextManager::getInstance()->getGlobalContext(ctx);
111 //printf(" local : %p, global : %p \n", ctx, globalCtx);
113 JSStringRef str = JSValueToStringCopy(ctx, arguments[0], NULL);
115 return JSValueMakeUndefined(ctx);
117 int n = JSStringGetLength(str);
120 JSStringGetUTF8CString(str, cstr,n+1);
121 printf("<alert>%s\n", cstr);
123 return JSValueMakeUndefined(ctx);
126 JSValueRef StandaloneConsole::setInterval(JSContextRef ctx, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception){
128 StandaloneConsole *console = static_cast<StandaloneConsole*>(JSObjectGetPrivate(thisObject));
129 if( argumentCount < 2 ){
130 if( exception != NULL){
133 return JSValueMakeUndefined(ctx);
136 double interval = JSValueToNumber(ctx, arguments[1], NULL);
137 interval = interval/1000;
139 console->mTimerMap.insert(pair<int,int>(handleid, 1));
140 CallbackData *data = new CallbackData();
141 JSValueProtect(console->getGlobalContext(), arguments[0]);
142 data->callback = JSValueToObject(ctx, arguments[0], NULL);
144 data->console = console;
146 ecore_timer_add( interval, StandaloneConsole::timerCb , data);
147 return JSValueMakeNumber(ctx, handleid);
151 JSValueRef StandaloneConsole::setTimeout(JSContextRef ctx, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception){
153 StandaloneConsole *console = static_cast<StandaloneConsole*>(JSObjectGetPrivate(thisObject));
155 if( argumentCount < 2 ){
156 if( exception != NULL){
159 return JSValueMakeUndefined(ctx);
162 double interval = JSValueToNumber(ctx, arguments[1], NULL);
163 interval = interval/1000;
165 console->mTimerMap.insert(pair<int,int>(handleid, 2));
166 CallbackData *data = new CallbackData();
167 JSValueProtect(console->getGlobalContext(), arguments[0]);
168 data->callback = JSValueToObject(ctx, arguments[0], NULL);
170 data->console = console;
172 ecore_timer_add( interval, StandaloneConsole::timerCb , data);
173 return JSValueMakeNumber(ctx, handleid);
178 JSValueRef StandaloneConsole::clearInterval(JSContextRef ctx, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception){
179 StandaloneConsole *console = static_cast<StandaloneConsole*>(JSObjectGetPrivate(thisObject));
180 if(console == NULL) return JSValueMakeUndefined(ctx);
181 if( argumentCount < 1 ){
182 printf("error clearInterval\n");
183 if( exception != NULL){
186 return JSValueMakeUndefined(ctx);
189 int handleid = JSValueToNumber(ctx, arguments[0], NULL);
190 map<int,int>::iterator it;
191 it = console->mTimerMap.find(handleid);
192 if( it != console->mTimerMap.end())
193 console->mTimerMap[handleid] = 0;
194 return JSValueMakeUndefined(ctx);
198 static JSValueRef test(JSContextRef ctx, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception){
199 return JSValueMakeUndefined(ctx);
203 static void setProperty(JSContextRef ctx , JSObjectRef object, const char *name, JSValueRef value, JSPropertyAttributes attributes)
205 JSStringRef propertyName = JSStringCreateWithUTF8CString(name);
206 JSObjectSetProperty(ctx, object, propertyName, value,attributes, NULL );
207 JSStringRelease(propertyName);
210 static JSValueRef getProperty(JSContextRef ctx , JSObjectRef object, const char *name){
212 JSStringRef propertyName = JSStringCreateWithUTF8CString(name);
213 value = JSObjectGetProperty(ctx, object, propertyName, NULL);
214 JSStringRelease(propertyName);
218 static char * toString(JSContextRef ctx , JSValueRef jsV){
219 JSValueRef exception = NULL;
220 JSStringRef jsStr = JSValueToStringCopy(ctx, jsV, &exception);
221 if( exception != NULL )
223 int n = JSStringGetMaximumUTF8CStringSize(jsStr);
224 char *buf = new char[n+1];
225 JSStringGetUTF8CString(jsStr, buf, n+1);
226 JSStringRelease(jsStr);
230 StandaloneConsole::StandaloneConsole():mGlobalContext(NULL),mGlobalObject(NULL){
233 StandaloneConsole::~StandaloneConsole(){
236 void StandaloneConsole::initialize(){
238 JSStaticFunction functions[] = {
239 { "alert", StandaloneConsole::alert , kJSPropertyAttributeNone },
240 { "setInterval", StandaloneConsole::setInterval , kJSPropertyAttributeNone },
241 { "setTimeout", StandaloneConsole::setTimeout , kJSPropertyAttributeNone },
242 { "clearInterval", StandaloneConsole::clearInterval , kJSPropertyAttributeNone },
243 { "clearTimeout", StandaloneConsole::clearInterval , kJSPropertyAttributeNone },
244 { "test", test, kJSPropertyAttributeNone },
249 JSClassDefinition def = {
250 0, // current (and only) version is 0
251 kJSClassAttributeNone, //attributes
252 "global", //class name
253 NULL, // parent class
254 NULL, //static values
255 functions, // static functions
261 NULL, //deleteProperty
262 NULL, //getPropertyNames
263 NULL, // callAsConstructor
266 NULL // convertToType
269 JSClassRef globalClass = JSClassCreate(&def);
271 mGlobalContext = JSGlobalContextCreate(globalClass);
272 mGlobalObject = JSContextGetGlobalObject(mGlobalContext);
273 JSObjectSetPrivate(mGlobalObject, this);
274 JSObjectRef console = JSConsole::createJSObject(mGlobalContext);
275 setProperty(mGlobalContext, mGlobalObject, "console", console, kJSPropertyAttributeReadOnly);
278 //is it ecore bug? event was not invoke, it was added in another thread
279 ecore_timer_add(0.001, tick, NULL);
283 JSObjectRef StandaloneConsole::getGlobalObject(){
284 return mGlobalObject;
287 JSContextRef StandaloneConsole::getGlobalContext(){
288 return mGlobalContext;
292 JSValueRef StandaloneConsole::RunLineEx(const char* line, JSValueRef *exception){
293 JSStringRef jsScript = JSStringCreateWithUTF8CString(line);
294 JSValueRef ret = JSEvaluateScript(mGlobalContext, jsScript, NULL, NULL, 0, exception);
295 JSStringRelease(jsScript);
299 JSValueRef StandaloneConsole::RunScriptEx(const char* path, JSValueRef *exception){
301 FILE* f = fopen(path, "r");
306 fseek(f, 0, SEEK_END);
307 int length = ftell(f);
308 fseek(f, 0, SEEK_SET);
313 memset(buff, 0, length);
314 int r = fread(buff, 1, length, f);
318 printf("error read\n");
319 return JSValueMakeUndefined(mGlobalContext);
321 return RunLineEx(buff, exception);
324 return JSValueMakeUndefined(mGlobalContext);
327 void StandaloneConsole::RunLine(const char * line){
328 JSValueRef exception = NULL;
329 JSValueRef v = RunLineEx(line, &exception);
330 reportingResult(v,exception);
333 void StandaloneConsole::RunScript(const char * path){
334 JSValueRef exception = NULL;
335 JSValueRef v = RunScriptEx(path, &exception);
336 reportingResult(v,exception);
339 void StandaloneConsole::GarbageCollect(){
340 printf("GarbageCollect\n");
341 JSGarbageCollect(mGlobalContext);
343 void StandaloneConsole::reportingResult(JSValueRef v, JSValueRef exception){
344 if( exception != NULL ){
345 char *errStr = toString(mGlobalContext, exception);
346 if( errStr != NULL ){
347 printf("< error - %s\n", errStr);
350 JSObjectRef errObj = JSValueToObject(mGlobalContext, exception, NULL);
351 if( errObj != NULL ){
352 JSValueRef stack = getProperty(mGlobalContext, errObj, "stack");
353 char *stackStr = NULL;
354 if( !JSValueIsUndefined(mGlobalContext, stack) && (stackStr = toString(mGlobalContext, stack )) != NULL){
355 printf("stack:%s\n", stackStr);
360 char *resultStr = toString(mGlobalContext, v);
361 if( resultStr != NULL ){
362 printf("< %s\n", resultStr);
368 JSObjectRef StandaloneConsole::registModule(const char * name, JSClassRef module, void * priv){
369 JSObjectRef obj = JSObjectMake(mGlobalContext, module, priv);
370 setProperty(mGlobalContext, mGlobalObject, name, obj, kJSPropertyAttributeReadOnly);
374 void StandaloneConsole::appendModule(const char * name, JSObjectRef module){
375 setProperty(mGlobalContext, mGlobalObject, name, module, kJSPropertyAttributeReadOnly);
387 buf.c_lflag &= ~(ICANON|ECHO);
390 tcsetattr(0, TCSAFLUSH, &buf);
392 tcsetattr(0, TCSAFLUSH, &save);
396 struct termios gSave;
400 tcsetattr(0, TCSAFLUSH, &gSave);
404 vector<string> mHistory;
409 LineBuffer():mHistoryIndex(0), mCurrentPos(0){
410 tcgetattr(0, &gSave);
414 tcsetattr(0, TCSAFLUSH, &gSave);
417 void backSpace( int length ){
418 for( int i =0 ; i < length ; i++){
424 void applyHistory( unsigned int index ){
425 if( mHistory.size() > index ){
426 mLine = mHistory[index];
427 mCurrentPos = mLine.size();
430 bool checkSpecialKeys(int a){
432 if( mLine.size() != 0){
434 mLine.erase(mCurrentPos);
444 if( mHistoryIndex > 0 ){
445 applyHistory(--mHistoryIndex);
450 if( (unsigned)mHistoryIndex < mHistory.size() ){
451 applyHistory(++mHistoryIndex);
473 string Prompt(const char * prompt){
474 printf("%s", prompt);
479 backSpace(mLine.size());
483 if(!checkSpecialKeys(a)){
484 mLine.insert(mCurrentPos,1, a);
490 if( mLine.size() > 0 ){
491 mHistory.push_back(mLine);
492 mHistoryIndex = mHistory.size();
501 void StandaloneConsole::commandline(StandaloneConsole* console){
502 pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
503 pthread_mutex_lock(&lock);
504 printf("command line mode ( \"quit\" for exit )\n");
507 string line = linebuff.Prompt(">");
513 console->GarbageCollect();
516 if( line.size() == 0 )
518 _Command *cmd = new _Command(line.c_str(), console, &lock);
520 ecore_idler_add(commandDispath, cmd);
521 pthread_mutex_lock(&lock);