Index: trunk/FACT++/src/InterpreterV8.cc
===================================================================
--- trunk/FACT++/src/InterpreterV8.cc	(revision 14177)
+++ trunk/FACT++/src/InterpreterV8.cc	(revision 14185)
@@ -341,5 +341,7 @@
 
         Handle<Array> ret = Array::New();
-        ret->Set(String::New("table"), String::New(res.table()));
+        ret->Set(String::New("table"), String::New(res.table()), ReadOnly);
+
+        Handle<Array> cols = Array::New();
 
         int irow=0;
@@ -353,8 +355,10 @@
             {
                 const Handle<Value> name = String::New((*list)[i].c_str());
+                if (irow==0)
+                    cols->Set(Integer::NewFromUnsigned(i), name, ReadOnly);
 
                 if ((*it)[i].is_null())
                 {
-                    row->Set(name, Undefined());
+                    row->Set(name, Undefined(), ReadOnly);
                     continue;
                 }
@@ -370,7 +374,7 @@
                         const uint64_t val = (uint64_t)(*it)[i];
                         if (val>UINT32_MAX)
-                            row->Set(name, Number::New(val));
+                            row->Set(name, Number::New(val), ReadOnly);
                         else
-                            row->Set(name, Integer::NewFromUnsigned(val));
+                            row->Set(name, Integer::NewFromUnsigned(val), ReadOnly);
                     }
                     else
@@ -378,7 +382,7 @@
                         const int64_t val = (int64_t)(*it)[i];
                         if (val<INT32_MIN || val>INT32_MAX)
-                            row->Set(name, Number::New(val));
+                            row->Set(name, Number::New(val), ReadOnly);
                         else
-                            row->Set(name, Integer::NewFromUnsigned(val));
+                            row->Set(name, Integer::NewFromUnsigned(val), ReadOnly);
                     }
                     continue;
@@ -389,12 +393,12 @@
                 {
                     if (uns)
-                        row->Set(name, Integer::NewFromUnsigned((uint32_t)(*it)[i]));
+                        row->Set(name, Integer::NewFromUnsigned((uint32_t)(*it)[i]), ReadOnly);
                     else
-                        row->Set(name, Integer::New((int32_t)(*it)[i]));
+                        row->Set(name, Integer::New((int32_t)(*it)[i]), ReadOnly);
                 }
 
                 if (sql_type.find("BOOL")!=string::npos )
                 {
-                    row->Set(name, Boolean::New((bool)(*it)[i]));
+                    row->Set(name, Boolean::New((bool)(*it)[i]), ReadOnly);
                     continue;
                 }
@@ -404,5 +408,5 @@
                     ostringstream val;
                     val << setprecision(7) << (float)(*it)[i];
-                    row->Set(name, Number::New(stod(val.str())));
+                    row->Set(name, Number::New(stod(val.str())), ReadOnly);
                     continue;
 
@@ -410,5 +414,5 @@
                 if (sql_type.find("DOUBLE")!=string::npos)
                 {
-                    row->Set(name, Number::New((double)(*it)[i]));
+                    row->Set(name, Number::New((double)(*it)[i]), ReadOnly);
                     continue;
                 }
@@ -417,5 +421,5 @@
                     sql_type.find("TEXT")!=string::npos)
                 {
-                    row->Set(name, String::New((const char*)(*it)[i]));
+                    row->Set(name, String::New((const char*)(*it)[i]), ReadOnly);
                     continue;
                 }
@@ -423,5 +427,5 @@
                 if (sql_type.find("TIMESTAMP")!=string::npos)
                 {
-                    row->Set(name, Date::New(time_t(mysqlpp::Time((*it)[i]))*1000));
+                    row->Set(name, Date::New(time_t(mysqlpp::Time((*it)[i]))*1000), ReadOnly);
                     continue;
                 }
@@ -429,5 +433,5 @@
                 if (sql_type.find("DATETIME")!=string::npos)
                 {
-                    row->Set(name, Date::New(time_t(mysqlpp::DateTime((*it)[i]))*1000));
+                    row->Set(name, Date::New(time_t(mysqlpp::DateTime((*it)[i]))*1000), ReadOnly);
                     continue;
                 }
@@ -435,5 +439,5 @@
                 if (sql_type.find(" DATE ")!=string::npos)
                 {
-                    row->Set(name, Date::New(time_t((mysqlpp::Date)(*it)[i])*1000));
+                    row->Set(name, Date::New(time_t((mysqlpp::Date)(*it)[i])*1000), ReadOnly);
                     continue;
                 }
@@ -441,6 +445,9 @@
             }
 
-            ret->Set(Integer::New(irow++), row);
+            ret->Set(Integer::NewFromUnsigned(irow++), row, ReadOnly);
         }
+
+        if (irow>0)
+            ret->Set(String::New("cols"), cols, ReadOnly);
 
         return handle_scope.Close(ret);
@@ -711,4 +718,17 @@
     v8::Locker::StartPreemption(10);
     const bool rc = ExecuteFile(filename);
+
+    // -----
+    // This is how an exit handler could look like, but there is no way to interrupt it
+    // -----
+    // Handle<Object> obj = Handle<Object>::Cast(context->Global()->Get(String::New("dim")));
+    // if (!obj.IsEmpty())
+    // {
+    //     Handle<Value> onexit = obj->Get(String::New("onexit"));
+    //     if (!onexit->IsUndefined())
+    //         Handle<Function>::Cast(onexit)->NewInstance(0, NULL); // argc, argv
+    //     // Handle<Object> result = Handle<Function>::Cast(onexit)->NewInstance(0, NULL); // argc, argv
+    // }
+
     v8::Locker::StopPreemption();
     //context->Exit();
@@ -730,10 +750,10 @@
 void InterpreterV8::JsStop()
 {
-    v8::Locker locker;
+    Locker locker;
     //cout << "Terminate " << fThreadId << endl;
     if (This->fThreadId>=0)
-        v8::V8::TerminateExecution(This->fThreadId);
+        V8::TerminateExecution(This->fThreadId);
     //cout << "Terminate " << fThreadId << endl;
-    v8::Unlocker unlocker;
+    Unlocker unlocker;
 }
 
