source: trunk/FACT++/src/InterpreterV8.cc@ 14545

Last change on this file since 14545 was 14540, checked in by tbretz, 13 years ago
Use State in JsState and added 'time' to the data members. Make sure there is no crash if an mpty event was received. Added 'size' to service objects.
File size: 24.0 KB
Line 
1#include "InterpreterV8.h"
2
3#ifdef HAVE_SQL
4#include "Database.h"
5#endif
6
7#include <boost/tokenizer.hpp>
8
9InterpreterV8 *InterpreterV8::This = 0;
10
11#ifdef HAVE_V8
12
13#include <v8.h>
14#include <fstream>
15#include <sstream>
16#include <iomanip>
17
18using namespace std;
19using namespace v8;
20
21bool InterpreterV8::ReportException(TryCatch* try_catch)
22{
23 const HandleScope handle_scope;
24
25 const String::Utf8Value exception(try_catch->Exception());
26
27 if (*exception && string(*exception)=="exit")
28 return true;
29
30 const Handle<Message> message = try_catch->Message();
31
32 // Print (filename):(line number): (message).
33 const String::Utf8Value filename(message->GetScriptResourceName());
34
35 ostringstream out;
36
37 if (*filename)
38 out << *filename;
39 if (!message.IsEmpty())
40 out << ": l." << message->GetLineNumber();
41 if (*exception)
42 out << ": " << *exception;
43
44 JsException(out.str());
45
46 if (message.IsEmpty())
47 return false;
48
49 // Print line of source code.
50 const String::Utf8Value sourceline(message->GetSourceLine());
51 if (*sourceline)
52 JsException(*sourceline);
53
54 // Print wavy underline (GetUnderline is deprecated).
55 const int start = message->GetStartColumn();
56 const int end = message->GetEndColumn();
57
58 out.str("");
59 if (start>0)
60 out << setfill(' ') << setw(start) << ' ';
61 out << setfill('^') << setw(end-start) << '^';
62
63 JsException(out.str());
64
65 String::Utf8Value stack_trace(try_catch->StackTrace());
66 if (stack_trace.length()<=0)
67 return false;
68
69 //if (*stack_trace)
70 // JsException(string("\n")+*stack_trace);
71
72 return false;
73}
74
75// Executes a string within the current v8 context.
76bool InterpreterV8::ExecuteStringNT(const Handle<String> &code, const Handle<Value> &file)
77{
78 if (code.IsEmpty())
79 return true;
80
81 const HandleScope handle_scope;
82
83 const Handle<Script> script = Script::Compile(code, file);
84 if (script.IsEmpty())
85 return false;
86
87 const Handle<Value> result = script->Run();
88 if (result.IsEmpty())
89 return false;
90
91 // If all went well and the result wasn't undefined then print
92 // the returned value.
93 if (!result->IsUndefined())
94 JsResult(*String::Utf8Value(result));
95
96 return true;
97}
98
99bool InterpreterV8::ExecuteCode(const Handle<String> &code, const Handle<Value> &file)
100{
101 TryCatch exception;
102
103 const bool rc = ExecuteStringNT(code, file);
104
105 if (!exception.CanContinue())
106 return false;
107
108 if (exception.HasCaught())
109 return ReportException(&exception);
110
111 return rc;
112}
113
114bool InterpreterV8::ExecuteCode(const string &code, const string &file)
115{
116 return ExecuteCode(String::New(code.c_str(), code.size()),
117 String::New(file.c_str()));
118}
119
120bool InterpreterV8::ExecuteFile(const string &name)
121{
122 ifstream fin(name.c_str());
123 if (!fin)
124 {
125 JsException("Error - Could not open file '"+name+"'");
126 return false;
127 }
128
129 string buffer;
130 if (!getline(fin, buffer, '\0'))
131 return true;
132
133 if (fin.fail())
134 {
135 JsException("Error - reading file.");
136 return false;
137 }
138
139 return ExecuteCode(buffer, name);
140}
141
142Handle<Value> InterpreterV8::FuncWait(const Arguments& args)
143{
144 if (args.Length()!=2 && args.Length()!=3)
145 return ThrowException(String::New("Number of arguments must be 2 or 3."));
146
147 if (!args[0]->IsString())
148 return ThrowException(String::New("Argument 1 not a string."));
149
150 if (!args[1]->IsInt32())
151 return ThrowException(String::New("Argument 2 not an int32."));
152
153 if (args.Length()==3 && !args[2]->IsUint32())
154 return ThrowException(String::New("Argument 3 not an uint32."));
155
156 const string server = *String::Utf8Value(args[0]);
157 const int32_t state = args[1]->Int32Value();
158 const uint32_t millisec = args.Length()==3 ? args[2]->Int32Value() : 0;
159
160 const int rc = JsWait(server, state, millisec);
161
162 if (rc==0 || rc==1)
163 return Boolean::New(rc);
164
165 return ThrowException(String::New(("Waitig for state "+to_string(state)+" of server '"+server+"' failed.").c_str()));
166}
167
168Handle<Value> InterpreterV8::FuncSend(const Arguments& args)
169{
170 if (args.Length()==0)
171 return ThrowException(String::New("Number of arguments must be at least 1."));
172
173 if (!args[0]->IsString())
174 return ThrowException(String::New("Argument 1 must be a string."));
175
176 const HandleScope handle_scope;
177
178 const String::Utf8Value str(args[0]);
179
180 string command = *str;
181
182 for (int i=1; i<args.Length(); i++)
183 {
184 const String::Utf8Value arg(args[i]);
185 command += " \""+string(*arg)+"\"";
186 }
187
188 return Boolean::New(JsSend(command));
189}
190
191Handle<Value> InterpreterV8::FuncSleep(const Arguments& args)
192{
193 if (args.Length()==0)
194 {
195 JsSleep(1);
196 return Undefined();
197 }
198
199 if (args.Length()!=1)
200 return ThrowException(String::New("Number of arguments must be exactly 1."));
201
202 if (!args[0]->IsUint32())
203 return ThrowException(String::New("Argument 1 must be an uint32."));
204
205 JsSleep(args[0]->Int32Value());
206
207 return Undefined();
208}
209
210Handle<Value> InterpreterV8::FuncState(const Arguments& args)
211{
212 if (args.Length()!=1)
213 return ThrowException(String::New("Number of arguments must be exactly 1."));
214
215 if (!args[0]->IsString())
216 return ThrowException(String::New("Argument 1 must be a string."));
217
218 // Return state.name/state.index
219
220 HandleScope handle_scope;
221
222 const String::Utf8Value str(args[0]);
223
224 const State rc = JsState(*str);
225
226 //if (rc.first<=-256)
227 // return Undefined();
228
229 Handle<ObjectTemplate> obj = ObjectTemplate::New();
230
231 obj->Set(String::New("index"), rc.index<=-256?Undefined():Integer::New(rc.index), ReadOnly);
232 obj->Set(String::New("name"), rc.index<=-256?Undefined():String::New(rc.name.c_str()), ReadOnly);
233 obj->Set(String::New("time"), Date::New(rc.time.JavaDate()), ReadOnly);
234 //obj->Set(String::New("toString"), String::New(("[Object state "+string(*str)+":"+to_string(rc.index)+"]").c_str()));
235
236 return handle_scope.Close(obj->NewInstance());
237}
238
239Handle<Value> InterpreterV8::FuncExit(const Arguments &)
240{
241 v8::V8::TerminateExecution(fThreadId);
242 return ThrowException(String::New("exit"));
243/*
244 if (args.Length()!=1)
245 return ThrowException(String::New("Number of arguments must be exactly 1."));
246
247 if (!args[0]->IsUint32())
248 return ThrowException(String::New("Argument 1 must be an uint32."));
249
250 const HandleScope handle_scope;
251
252 JsSleep(args[0]->Int32Value());
253*/
254 return Undefined();
255}
256
257// The callback that is invoked by v8 whenever the JavaScript 'print'
258// function is called. Prints its arguments on stdout separated by
259// spaces and ending with a newline.
260Handle<Value> InterpreterV8::FuncPrint(const Arguments& args)
261{
262 for (int i=0; i<args.Length(); i++)
263 {
264 const HandleScope handle_scope;
265
266 const String::Utf8Value str(args[i]);
267 if (*str)
268 JsPrint(*str);
269 }
270 return Undefined();
271}
272
273Handle<Value> InterpreterV8::FuncAlarm(const Arguments& args)
274{
275 for (int i=0; i<args.Length(); i++)
276 {
277 const HandleScope handle_scope;
278
279 const String::Utf8Value str(args[i]);
280 if (*str)
281 JsAlarm(*str);
282 }
283
284 if (args.Length()==0)
285 JsAlarm();
286
287 return Undefined();
288}
289
290Handle<Value> InterpreterV8::FuncOut(const Arguments& args)
291{
292 for (int i=0; i<args.Length(); i++)
293 {
294 const HandleScope handle_scope;
295
296 const String::Utf8Value str(args[i]);
297 if (*str)
298 JsOut(*str);
299 }
300 return Undefined();
301}
302
303// The callback that is invoked by v8 whenever the JavaScript 'load'
304// function is called. Loads, compiles and executes its argument
305// JavaScript file.
306Handle<Value> InterpreterV8::FuncInclude(const Arguments& args)
307{
308 for (int i = 0; i<args.Length(); i++)
309 {
310 const HandleScope handle_scope;
311
312 const String::Utf8Value file(args[i]);
313 if (*file == NULL)
314 return ThrowException(String::New(("Error loading file '"+string(*file)+"'").c_str()));
315
316 if (!ExecuteFile(*file))
317 return ThrowException(String::New(("Execution of '"+string(*file)+"' failed").c_str()));
318 }
319 return Undefined();
320}
321
322Handle<Value> InterpreterV8::FuncVersion(const Arguments&)
323{
324 return String::New(V8::GetVersion());
325}
326
327Handle<Value> InterpreterV8::FuncDbClose(const Arguments &args)
328{
329 HandleScope handle_scope;
330
331 void *ptr = Local<External>::Cast(args.This()->GetInternalField(0))->Value();
332 if (!ptr)
333 return Boolean::New(false);
334
335#ifdef HAVE_SQL
336 Database *db = reinterpret_cast<Database*>(ptr);
337 auto it = find(fDatabases.begin(), fDatabases.end(), db);
338 fDatabases.erase(it);
339 delete db;
340#endif
341
342 args.This()->SetInternalField(0, External::New(0));
343
344 return Boolean::New(true);
345}
346Handle<Value> InterpreterV8::FuncDbQuery(const Arguments &args)
347{
348 if (args.Length()!=1)
349 return ThrowException(String::New("Number of arguments must be exactly 1."));
350
351 if (!args[0]->IsString())
352 return ThrowException(String::New("Both arguments must be a string."));
353
354 HandleScope handle_scope;
355
356 void *ptr = Local<External>::Cast(args.This()->GetInternalField(0))->Value();
357 if (!ptr)
358 return Undefined();
359
360 const String::Utf8Value query(args[0]);
361
362#ifdef HAVE_SQL
363 try
364 {
365 Database *db = reinterpret_cast<Database*>(ptr);
366
367 const mysqlpp::StoreQueryResult res = db->query(*query).store();
368
369 Handle<Array> ret = Array::New();
370 ret->Set(String::New("table"), String::New(res.table()), ReadOnly);
371
372 Handle<Array> cols = Array::New();
373
374 int irow=0;
375 for (vector<mysqlpp::Row>::const_iterator it=res.begin(); it<res.end(); it++)
376 {
377 Handle<Array> row = Array::New();
378
379 const mysqlpp::FieldNames *list = it->field_list().list;
380
381 for (size_t i=0; i<it->size(); i++)
382 {
383 const Handle<Value> name = String::New((*list)[i].c_str());
384 if (irow==0)
385 cols->Set(Integer::NewFromUnsigned(i), name, ReadOnly);
386
387 if ((*it)[i].is_null())
388 {
389 row->Set(name, Undefined(), ReadOnly);
390 continue;
391 }
392
393 const string sql_type = (*it)[i].type().sql_name();
394
395 const bool uns = sql_type.find("UNSIGNED")==string::npos;
396
397 if (sql_type.find("BIGINT")!=string::npos)
398 {
399 if (uns)
400 {
401 const uint64_t val = (uint64_t)(*it)[i];
402 if (val>UINT32_MAX)
403 row->Set(name, Number::New(val), ReadOnly);
404 else
405 row->Set(name, Integer::NewFromUnsigned(val), ReadOnly);
406 }
407 else
408 {
409 const int64_t val = (int64_t)(*it)[i];
410 if (val<INT32_MIN || val>INT32_MAX)
411 row->Set(name, Number::New(val), ReadOnly);
412 else
413 row->Set(name, Integer::NewFromUnsigned(val), ReadOnly);
414 }
415 continue;
416 }
417
418 // 32 bit
419 if (sql_type.find("INT")!=string::npos)
420 {
421 if (uns)
422 row->Set(name, Integer::NewFromUnsigned((uint32_t)(*it)[i]), ReadOnly);
423 else
424 row->Set(name, Integer::New((int32_t)(*it)[i]), ReadOnly);
425 }
426
427 if (sql_type.find("BOOL")!=string::npos )
428 {
429 row->Set(name, Boolean::New((bool)(*it)[i]), ReadOnly);
430 continue;
431 }
432
433 if (sql_type.find("FLOAT")!=string::npos)
434 {
435 ostringstream val;
436 val << setprecision(7) << (float)(*it)[i];
437 row->Set(name, Number::New(stod(val.str())), ReadOnly);
438 continue;
439
440 }
441 if (sql_type.find("DOUBLE")!=string::npos)
442 {
443 row->Set(name, Number::New((double)(*it)[i]), ReadOnly);
444 continue;
445 }
446
447 if (sql_type.find("CHAR")!=string::npos ||
448 sql_type.find("TEXT")!=string::npos)
449 {
450 row->Set(name, String::New((const char*)(*it)[i]), ReadOnly);
451 continue;
452 }
453
454 if (sql_type.find("TIMESTAMP")!=string::npos)
455 {
456 row->Set(name, Date::New(time_t(mysqlpp::Time((*it)[i]))*1000), ReadOnly);
457 continue;
458 }
459
460 if (sql_type.find("DATETIME")!=string::npos)
461 {
462 row->Set(name, Date::New(time_t(mysqlpp::DateTime((*it)[i]))*1000), ReadOnly);
463 continue;
464 }
465
466 if (sql_type.find(" DATE ")!=string::npos)
467 {
468 row->Set(name, Date::New(time_t((mysqlpp::Date)(*it)[i])*1000), ReadOnly);
469 continue;
470 }
471
472 }
473
474 ret->Set(Integer::NewFromUnsigned(irow++), row, ReadOnly);
475 }
476
477 if (irow>0)
478 ret->Set(String::New("cols"), cols, ReadOnly);
479
480 return handle_scope.Close(ret);
481 }
482 catch (const exception &e)
483 {
484 return ThrowException(String::New(e.what()));
485 }
486#endif
487}
488
489Handle<Value> InterpreterV8::FuncDatabase(const Arguments &args)
490{
491 if (args.Length()!=1)
492 return ThrowException(String::New("Number of arguments must be exactly 1."));
493
494 if (!args[0]->IsString())
495 return ThrowException(String::New("Argument 1 must be a string."));
496
497 HandleScope handle_scope;
498
499 const String::Utf8Value database(args[0]);
500 const String::Utf8Value query (args[1]);
501
502#ifdef HAVE_SQL
503 try
504 {
505 Database *db = new Database(*database);
506 fDatabases.push_back(db);
507
508 Handle<ObjectTemplate> tem = ObjectTemplate::New();
509 tem->Set(String::New("user"), String::New(db->user.c_str()), ReadOnly);
510 tem->Set(String::New("server"), String::New(db->server.c_str()), ReadOnly);
511 tem->Set(String::New("database"), String::New(db->db.c_str()), ReadOnly);
512 tem->Set(String::New("port"), db->port==0?Undefined():Integer::NewFromUnsigned(db->port), ReadOnly);
513 tem->Set(String::New("query"), FunctionTemplate::New(WrapDbQuery), ReadOnly);
514 tem->Set(String::New("close"), FunctionTemplate::New(WrapDbClose), ReadOnly);
515 tem->SetInternalFieldCount(1);
516
517 Handle<Object> obj = tem->NewInstance();
518 obj->SetInternalField(0, External::New(db));
519
520 return handle_scope.Close(obj);
521 }
522 catch (const exception &e)
523 {
524 return ThrowException(String::New(e.what()));
525 }
526#endif
527}
528
529Handle<Value> InterpreterV8::Convert(char type, const char* &ptr)
530{
531 // Dim values are always unsigned per (FACT++) definition
532 switch (type)
533 {
534 case 'F':
535 {
536 // Remove the "imprecision" effect coming from casting a float to
537 // a double and then showing it with double precision
538 ostringstream val;
539 val << setprecision(7) << *reinterpret_cast<const float*>(ptr);
540 Handle<Value> v=Number::New(stod(val.str()));
541 ptr+=4;
542 return v;
543 }
544 case 'D': { Handle<Value> v=Number::New(*reinterpret_cast<const double*>(ptr)); ptr+=8; return v; }
545 case 'I':
546 case 'L': { Handle<Value> v=Integer::NewFromUnsigned(*reinterpret_cast<const uint32_t*>(ptr)); ptr += 4; return v; }
547 case 'X':
548 {
549 const uint64_t val = *reinterpret_cast<const uint64_t*>(ptr);
550 ptr += 8;
551 if (val>UINT32_MAX)
552 return Number::New(val);
553 return Integer::NewFromUnsigned(val);
554 }
555 case 'S': { Handle<Value> v=Integer::NewFromUnsigned(*reinterpret_cast<const uint16_t*>(ptr)); ptr += 2; return v; }
556 case 'C': { Handle<Value> v=Integer::NewFromUnsigned((uint16_t)*reinterpret_cast<const uint8_t*>(ptr)); ptr += 1; return v; }
557 case ':': { Handle<Value> v=String::New(ptr); return v; }
558 }
559 return Undefined();
560}
561
562Handle<Value> InterpreterV8::FuncClose(const Arguments &args)
563{
564 HandleScope handle_scope;
565
566 //const void *ptr = Local<External>::Cast(info.This()->GetInternalField(0))->Value();
567
568 const String::Utf8Value str(args.Holder()->Get(String::New("name")));
569 return Boolean::New(JsUnsubscribe(*str));
570}
571
572Handle<Value> InterpreterV8::FuncGetData(const Arguments &args)
573{
574 HandleScope handle_scope;
575
576 const String::Utf8Value str(args.Holder()->Get(String::New("name")));
577
578 const pair<uint64_t, EventImp *> p = JsGetEvent(*str);
579
580 const EventImp *evt = p.second;
581 if (!evt)
582 return Undefined();
583
584 //if (counter==cnt)
585 // return info.Holder();//Holder()->Get(String::New("data"));
586
587 const vector<Description> vec = JsDescription(*str);
588
589 Handle<Array> ret = Array::New();
590 ret->Set(String::New("format"), String::New(evt->GetFormat().c_str()), ReadOnly);
591 ret->Set(String::New("named"), Boolean::New(vec.size()>0), ReadOnly);
592 ret->Set(String::New("counter"), Integer::New(p.first), ReadOnly);
593 ret->Set(String::New("time"), Date::New(evt->GetJavaDate()), ReadOnly);
594 ret->Set(String::New("qos"), Integer::New(evt->GetQoS()), ReadOnly);
595 ret->Set(String::New("size"), Integer::New(evt->GetSize()), ReadOnly);
596
597 typedef boost::char_separator<char> separator;
598 const boost::tokenizer<separator> tokenizer(evt->GetFormat(), separator(";:"));
599
600 const vector<string> tok(tokenizer.begin(), tokenizer.end());
601
602 Handle<Array> obj = tok.size()==1 ? ret : Array::New();
603
604 const char *ptr = evt->GetText();
605 try
606 {
607 size_t pos = 1;
608 for (auto it=tok.begin(); it!=tok.end(); it++, pos++)
609 {
610 if (ptr>=evt->GetText())
611 return handle_scope.Close(ret);
612
613 char type = (*it)[0];
614 it++;
615
616 if (it==tok.end() && type=='C')
617 type = ':';
618
619 if (it==tok.end() && type!=':')
620 return ThrowException(String::New(("Format string invalid '"+evt->GetFormat()+"'").c_str()));
621
622 string name = pos<vec.size() ? vec[pos].name : "";
623 if (tok.size()==1)
624 name = "data";
625
626 const uint32_t cnt = it==tok.end() ? 1 : stoi(it->c_str());
627
628 if (cnt==1)
629 {
630 const Handle<Value> v = Convert(type, ptr);
631 if (tok.size()>1)
632 obj->Set(pos-1, v);
633 if (!name.empty())
634 obj->Set(String::New(name.c_str()), v);
635 }
636 else
637 {
638 Handle<Array> a = Array::New(cnt);
639 for (uint32_t i=0; i<cnt; i++)
640 a->Set(i, Convert(type, ptr));
641 if (tok.size()>1)
642 obj->Set(pos-1, a);
643 if (!name.empty())
644 obj->Set(String::New(name.c_str()), a);
645 }
646
647 if (it==tok.end())
648 break;
649 }
650
651 if (tok.size()>1)
652 ret->Set(String::New("data"), obj, ReadOnly);
653
654 return handle_scope.Close(ret);
655 }
656 catch (...)
657 {
658 return ThrowException(String::New(("Format string conversion '"+evt->GetFormat()+"' failed.").c_str()));
659 }
660}
661
662/*
663void Cleanup( Persistent<Value> object, void *parameter )
664{
665 cout << "======================> RemoveMyObj()" << endl;
666}*/
667
668Handle<Value> InterpreterV8::FuncOpen(const Arguments &args)
669{
670 if (args.Length()!=1)
671 return ThrowException(String::New("Number of arguments must be exactly 1."));
672
673 if (!args[0]->IsString())
674 return ThrowException(String::New("Argument 1 must be a string."));
675
676 //if (!args.IsConstructCall())
677 // return ThrowException(String::New("Must be used as constructor."));
678
679 HandleScope handle_scope;
680
681 const String::Utf8Value str(args[0]);
682
683 void *ptr = JsSubscribe(*str);
684 if (ptr==0)
685 return ThrowException(String::New(("Subscription to '"+string(*str)+"' already exists.").c_str()));
686
687 Handle<ObjectTemplate> tem = ObjectTemplate::New();
688 tem->Set(String::New("get"), FunctionTemplate::New(WrapGetData), ReadOnly);
689 tem->Set(String::New("close"), FunctionTemplate::New(WrapClose), ReadOnly);
690 tem->Set(String::New("name"), String::New(*str), ReadOnly);
691 tem->SetInternalFieldCount(1);
692 //tem->Set(String::New("toString"), String::New(("[object Dim "+string(*str)+"]").c_str()), ReadOnly);
693
694 Handle<Object> obj = tem->NewInstance();
695 obj->SetInternalField(0, External::New(ptr));
696
697 return handle_scope.Close(obj);
698
699 // Persistent<Object> p = Persistent<Object>::New(obj->NewInstance());
700 // obj.MakeWeak((void*)1, Cleanup);
701 // return obj;
702}
703
704bool InterpreterV8::JsRun(const string &filename, const map<string, string> &map)
705{
706 v8::Locker locker;
707 fThreadId = V8::GetCurrentThreadId();
708
709 JsLoad(filename);
710
711 HandleScope handle_scope;
712
713 // Create a template for the global object.
714 Handle<ObjectTemplate> dim = ObjectTemplate::New();
715 dim->Set(String::New("print"), FunctionTemplate::New(WrapPrint), ReadOnly);
716 dim->Set(String::New("alarm"), FunctionTemplate::New(WrapAlarm), ReadOnly);
717 dim->Set(String::New("out"), FunctionTemplate::New(WrapOut), ReadOnly);
718 dim->Set(String::New("wait"), FunctionTemplate::New(WrapWait), ReadOnly);
719 dim->Set(String::New("send"), FunctionTemplate::New(WrapSend), ReadOnly);
720 dim->Set(String::New("state"), FunctionTemplate::New(WrapState), ReadOnly);
721 dim->Set(String::New("sleep"), FunctionTemplate::New(WrapSleep), ReadOnly);
722 dim->Set(String::New("open"), FunctionTemplate::New(WrapOpen), ReadOnly);
723 dim->Set(String::New("database"), FunctionTemplate::New(WrapDatabase), ReadOnly);
724
725 Handle<ObjectTemplate> global = ObjectTemplate::New();
726 global->Set(String::New("dim"), dim, ReadOnly);
727 global->Set(String::New("include"), FunctionTemplate::New(WrapInclude), ReadOnly);
728 global->Set(String::New("exit"), FunctionTemplate::New(WrapExit), ReadOnly);
729 global->Set(String::New("version"), FunctionTemplate::New(InterpreterV8::FuncVersion), ReadOnly);
730
731 // Persistent
732 Persistent<Context> context = Context::New(NULL, global);
733 if (context.IsEmpty())
734 {
735 //printf("Error creating context\n");
736 return false;
737 }
738
739 v8::Context::Scope scope(context);
740
741 Local<Array> args = Array::New(map.size());
742 for (auto it=map.begin(); it!=map.end(); it++)
743 args->Set(String::New(it->first.c_str()), String::New(it->second.c_str()));
744 context->Global()->Set(String::New("$"), args, ReadOnly);
745 context->Global()->Set(String::New("arg"), args, ReadOnly);
746
747 JsStart(filename);
748
749 //context->Enter();
750 v8::Locker::StartPreemption(10);
751 const bool rc = ExecuteFile(filename);
752
753 // -----
754 // This is how an exit handler could look like, but there is no way to interrupt it
755 // -----
756 // Handle<Object> obj = Handle<Object>::Cast(context->Global()->Get(String::New("dim")));
757 // if (!obj.IsEmpty())
758 // {
759 // Handle<Value> onexit = obj->Get(String::New("onexit"));
760 // if (!onexit->IsUndefined())
761 // Handle<Function>::Cast(onexit)->NewInstance(0, NULL); // argc, argv
762 // // Handle<Object> result = Handle<Function>::Cast(onexit)->NewInstance(0, NULL); // argc, argv
763 // }
764
765 v8::Locker::StopPreemption();
766 //context->Exit();
767
768 context.Dispose();
769
770#ifdef HAVE_SQL
771 for (auto it=fDatabases.begin(); it!=fDatabases.end(); it++)
772 delete *it;
773 fDatabases.clear();
774#endif
775
776
777 JsEnd(filename);
778
779 return rc;
780}
781
782void InterpreterV8::JsStop()
783{
784 Locker locker;
785 //cout << "Terminate " << fThreadId << endl;
786 if (This->fThreadId>=0)
787 V8::TerminateExecution(This->fThreadId);
788 //cout << "Terminate " << fThreadId << endl;
789 Unlocker unlocker;
790}
791
792#endif
793
Note: See TracBrowser for help on using the repository browser.