~drizzle-trunk/drizzle/development

2370.2.1 by Henrik Ingo
Adding new plugin "js_eval" that takes 1 or more strings as arguments
1
/* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
2
 *  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
3
 *
2370.2.6 by Henrik Ingo
Change copyright from Sun Microsystems to myself :-)
4
 *  Copyright (C) 2011, Henrik Ingo.
2370.2.1 by Henrik Ingo
Adding new plugin "js_eval" that takes 1 or more strings as arguments
5
 *
6
 *  This program is free software; you can redistribute it and/or modify
7
 *  it under the terms of the GNU General Public License as published by
8
 *  the Free Software Foundation; version 2 of the License.
9
 *
10
 *  This program is distributed in the hope that it will be useful,
11
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 *  GNU General Public License for more details.
14
 *
15
 *  You should have received a copy of the GNU General Public License
16
 *  along with this program; if not, write to the Free Software
17
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
18
 */
19
20
#include <config.h>
2370.2.2 by Henrik Ingo
js_eval() : Working execution of JavaScript code with the v8 engine.
21
#include <stdio.h>
2370.2.1 by Henrik Ingo
Adding new plugin "js_eval" that takes 1 or more strings as arguments
22
2370.2.7 by Henrik Ingo
Use my_error() to return v8 errors to the client instead of stdout/log.
23
#include <drizzled/error.h>
2370.2.1 by Henrik Ingo
Adding new plugin "js_eval" that takes 1 or more strings as arguments
24
#include <drizzled/plugin/function.h>
25
#include <drizzled/function/str/strfunc.h>
2370.2.11 by Henrik Ingo
Arguments that are of type DATETIME are now created as JavaScript
26
#include <drizzled/temporal.h>
2370.2.1 by Henrik Ingo
Adding new plugin "js_eval" that takes 1 or more strings as arguments
27
2370.2.2 by Henrik Ingo
js_eval() : Working execution of JavaScript code with the v8 engine.
28
#include <v8.h>
2370.2.3 by Henrik Ingo
Use v8::Locker to allow multiple threads to use v8 engine.
29
#define JS_ENGINE "v8"
2370.2.2 by Henrik Ingo
js_eval() : Working execution of JavaScript code with the v8 engine.
30
2370.2.1 by Henrik Ingo
Adding new plugin "js_eval" that takes 1 or more strings as arguments
31
using namespace std;
32
using namespace drizzled;
33
2370.2.2 by Henrik Ingo
js_eval() : Working execution of JavaScript code with the v8 engine.
34
2370.2.10 by Henrik Ingo
Change names and style of the v8 sample code to drizzle like code.
35
namespace drizzle_plugin {
36
namespace js {
37
2370.2.3 by Henrik Ingo
Use v8::Locker to allow multiple threads to use v8 engine.
38
v8::Handle<v8::Value> V8Version(const v8::Arguments& args);
39
v8::Handle<v8::Value> JsEngine(const v8::Arguments& args);
2370.2.10 by Henrik Ingo
Change names and style of the v8 sample code to drizzle like code.
40
const char* v8_to_char(const v8::String::Utf8Value& value);
41
void emit_drizzle_error(v8::TryCatch* try_catch);
2370.2.2 by Henrik Ingo
js_eval() : Working execution of JavaScript code with the v8 engine.
42
43
44
// TODO: So this is a function that returns strings? 
45
// What is the class for functions that return mixed types?
2370.2.10 by Henrik Ingo
Change names and style of the v8 sample code to drizzle like code.
46
// Or is this as it should be, apparently js('1') + js('2') does the right thing already.
2370.2.1 by Henrik Ingo
Adding new plugin "js_eval" that takes 1 or more strings as arguments
47
2370.2.18 by Henrik Ingo
Small style fixes from Olaf's review (thanks).
48
class JsFunction : public Item_str_func
2370.2.1 by Henrik Ingo
Adding new plugin "js_eval" that takes 1 or more strings as arguments
49
{
50
public:
51
  String *val_str(String *);
52
53
  const char *func_name() const 
54
  { 
2370.2.8 by Henrik Ingo
Change name from js_eval() to just js(), also change name of plugin itself.
55
    return "js"; 
2370.2.1 by Henrik Ingo
Adding new plugin "js_eval" that takes 1 or more strings as arguments
56
  }
57
58
  void fix_length_and_dec() 
59
  { 
60
    maybe_null= 1;
61
    max_length= MAX_BLOB_WIDTH;   
62
  }
63
64
  bool check_argument_count(int n)
65
  {
66
    return (n >= 1);
67
  }
68
};
69
2370.2.2 by Henrik Ingo
js_eval() : Working execution of JavaScript code with the v8 engine.
70
/**
2370.2.11 by Henrik Ingo
Arguments that are of type DATETIME are now created as JavaScript
71
 * @brief Extracts a C string from a V8 Utf8Value
2370.2.2 by Henrik Ingo
js_eval() : Working execution of JavaScript code with the v8 engine.
72
 * 
2370.2.10 by Henrik Ingo
Change names and style of the v8 sample code to drizzle like code.
73
 * Idea copied from v8 sources, samples/shell.cc. Makes code easier to read than
74
 * (char *)(*utf8value)
2370.2.2 by Henrik Ingo
js_eval() : Working execution of JavaScript code with the v8 engine.
75
 */
2370.2.10 by Henrik Ingo
Change names and style of the v8 sample code to drizzle like code.
76
const char* v8_to_char(const v8::String::Utf8Value& value) {
77
  return *value ? *value : "<javascript v8 string conversion failed>";
2370.2.2 by Henrik Ingo
js_eval() : Working execution of JavaScript code with the v8 engine.
78
}
79
80
/**
2370.2.12 by Henrik Ingo
Add missing doxygen comments to a few helper functions. Cleanup
81
 * @brief Take v8 exception and emit Drizzle error to client
2370.2.10 by Henrik Ingo
Change names and style of the v8 sample code to drizzle like code.
82
 * 
83
 * This is adapted from ReportException() in v8 samples/shell.cc. 
2370.2.2 by Henrik Ingo
js_eval() : Working execution of JavaScript code with the v8 engine.
84
 */
2370.2.18 by Henrik Ingo
Small style fixes from Olaf's review (thanks).
85
void emit_drizzle_error(v8::TryCatch* try_catch)
86
{
2370.2.2 by Henrik Ingo
js_eval() : Working execution of JavaScript code with the v8 engine.
87
  v8::HandleScope handle_scope;
88
  v8::String::Utf8Value exception(try_catch->Exception());
2370.2.10 by Henrik Ingo
Change names and style of the v8 sample code to drizzle like code.
89
  const char* exception_string = v8_to_char(exception);
2370.2.2 by Henrik Ingo
js_eval() : Working execution of JavaScript code with the v8 engine.
90
  v8::Handle<v8::Message> message = try_catch->Message();
91
  if (message.IsEmpty()) {
92
    // V8 didn't provide any extra information about this error; just
93
    // print the exception.
2370.2.7 by Henrik Ingo
Use my_error() to return v8 errors to the client instead of stdout/log.
94
    my_error(ER_SCRIPT, MYF(0), exception_string);
2370.2.2 by Henrik Ingo
js_eval() : Working execution of JavaScript code with the v8 engine.
95
  } else {
2370.2.10 by Henrik Ingo
Change names and style of the v8 sample code to drizzle like code.
96
    char buf[2048]; 
2370.2.2 by Henrik Ingo
js_eval() : Working execution of JavaScript code with the v8 engine.
97
    int linenum = message->GetLineNumber();
2370.2.10 by Henrik Ingo
Change names and style of the v8 sample code to drizzle like code.
98
    sprintf(buf, "At line %i: %.1900s (Do SHOW ERRORS for more information.)", linenum, exception_string);
2370.2.7 by Henrik Ingo
Use my_error() to return v8 errors to the client instead of stdout/log.
99
    my_error(ER_SCRIPT, MYF(0), buf);
2370.2.10 by Henrik Ingo
Change names and style of the v8 sample code to drizzle like code.
100
    // Print line of source code and where error happened.
2370.2.2 by Henrik Ingo
js_eval() : Working execution of JavaScript code with the v8 engine.
101
    v8::String::Utf8Value sourceline(message->GetSourceLine());
2370.2.10 by Henrik Ingo
Change names and style of the v8 sample code to drizzle like code.
102
    const char* sourceline_string = v8_to_char(sourceline);
103
    sprintf(buf, "Line %i: %.160s", linenum, sourceline_string);
2370.2.7 by Henrik Ingo
Use my_error() to return v8 errors to the client instead of stdout/log.
104
    my_error(ER_SCRIPT, MYF(0), buf);    
2370.2.2 by Henrik Ingo
js_eval() : Working execution of JavaScript code with the v8 engine.
105
    int start = message->GetStartColumn();
2370.2.7 by Henrik Ingo
Use my_error() to return v8 errors to the client instead of stdout/log.
106
    sprintf(buf, "Check your script starting at: '%.50s'", &sourceline_string[start]);
107
    my_error(ER_SCRIPT, MYF(0), buf);
2370.2.2 by Henrik Ingo
js_eval() : Working execution of JavaScript code with the v8 engine.
108
    v8::String::Utf8Value stack_trace(try_catch->StackTrace());
109
    if (stack_trace.length() > 0) {
2370.2.10 by Henrik Ingo
Change names and style of the v8 sample code to drizzle like code.
110
      const char* stack_trace_string = v8_to_char(stack_trace);
2370.2.7 by Henrik Ingo
Use my_error() to return v8 errors to the client instead of stdout/log.
111
      my_error(ER_SCRIPT, MYF(0), stack_trace_string);
2370.2.2 by Henrik Ingo
js_eval() : Working execution of JavaScript code with the v8 engine.
112
    }
113
  }
114
}
115
116
/**
2370.2.11 by Henrik Ingo
Arguments that are of type DATETIME are now created as JavaScript
117
 * @brief Implements js() - execute JavaScript code
2370.2.2 by Henrik Ingo
js_eval() : Working execution of JavaScript code with the v8 engine.
118
 * 
2370.2.13 by Henrik Ingo
Add 2 items to todo list.
119
 * @todo row_result types are not yet handled, what are they anyway?
120
 * @todo Lot's of performance optimizations postponed for later version:
121
 *  * When available, use v8::Isolate instead of v8::Locker for multithreading 
122
 * (or a mix of both). 
123
 *  * As part of this work, refactor v8 stuff into separate 
2370.2.10 by Henrik Ingo
Change names and style of the v8 sample code to drizzle like code.
124
 * function, proxy, factory or something...
2370.2.13 by Henrik Ingo
Add 2 items to todo list.
125
 *  * Save the compiled script so it can be used again if same script is run
126
 * many times
127
 *  * Some of the v8 stuff should be done in initialize()
2370.2.7 by Henrik Ingo
Use my_error() to return v8 errors to the client instead of stdout/log.
128
 * 
2370.2.10 by Henrik Ingo
Change names and style of the v8 sample code to drizzle like code.
129
 * @note DECIMAL_RESULT type is now a double in JavaScript. This could lose 
130
 * precision. But to send them as strings would also be awkward (+ operator will 
131
 * do unexpected things). In any case, we'd need some biginteger (bigdecimal?) 
132
 * kind of library to do anything with higher precision values anyway. If you 
133
 * want to keep the precision, you can cast your decimal values to strings 
134
 * explicitly when passing them as arguments.
2370.2.2 by Henrik Ingo
js_eval() : Working execution of JavaScript code with the v8 engine.
135
 * 
136
 * @param res Pointer to the drizzled::String object that will contain the result
137
 * @return a drizzled::String containing the value returned by executed JavaScript code (value of last executed statement) 
138
 */
2370.2.8 by Henrik Ingo
Change name from js_eval() to just js(), also change name of plugin itself.
139
String *JsFunction::val_str( String *str )
2370.2.1 by Henrik Ingo
Adding new plugin "js_eval" that takes 1 or more strings as arguments
140
{
2370.2.5 by Henrik Ingo
Honoring EcmaScript standard arguments are made available as arguments[]
141
  assert( fixed == 1 );
2370.2.2 by Henrik Ingo
js_eval() : Working execution of JavaScript code with the v8 engine.
142
  // If we return from any of the error conditions during method, then 
143
  // return value of the drizzle function is null.
144
  null_value= true; 
145
  
146
  String *source_str=NULL;
2370.2.5 by Henrik Ingo
Honoring EcmaScript standard arguments are made available as arguments[]
147
  source_str = args[0]->val_str( str ); 
2370.2.2 by Henrik Ingo
js_eval() : Working execution of JavaScript code with the v8 engine.
148
  
2370.2.3 by Henrik Ingo
Use v8::Locker to allow multiple threads to use v8 engine.
149
  // Need to use Locker in multi-threaded app. v8 is unlocked by the destructor 
150
  // when locker goes out of scope.
151
  // TODO: Newer versions of v8 provide an Isolate class where you can get a 
152
  // separate instance of v8 (ie one per thread). v8 2.5.9.9 in Ubuntu 11.04 does 
153
  // not yet offer it.
154
  v8::Locker locker;
2370.2.2 by Henrik Ingo
js_eval() : Working execution of JavaScript code with the v8 engine.
155
  // Pass code and arguments into v8...
156
  v8::HandleScope handle_scope;
2370.2.3 by Henrik Ingo
Use v8::Locker to allow multiple threads to use v8 engine.
157
  // Create a template for the global object and populate a drizzle object.
158
  v8::Handle<v8::ObjectTemplate> global  = v8::ObjectTemplate::New();
159
  // Drizzle will contain API's to drizzle variables, functions and tables
2370.2.4 by Henrik Ingo
Arguments 2 to N are now passed to the js script in array argv.
160
  v8::Handle<v8::ObjectTemplate> db = v8::ObjectTemplate::New();
161
  v8::Handle<v8::ObjectTemplate> js = v8::ObjectTemplate::New();
2370.2.3 by Henrik Ingo
Use v8::Locker to allow multiple threads to use v8 engine.
162
  // Bind the 'version' function 
2370.2.5 by Henrik Ingo
Honoring EcmaScript standard arguments are made available as arguments[]
163
  global->Set( v8::String::New("db"), db );
164
  db->Set( v8::String::New("js"), js );
165
  js->Set( v8::String::New("version"), v8::FunctionTemplate::New(V8Version) );
166
  js->Set( v8::String::New("engine"), v8::FunctionTemplate::New(JsEngine) );
2370.2.4 by Henrik Ingo
Arguments 2 to N are now passed to the js script in array argv.
167
  
168
  // Now bind the arguments into argv[]
169
  // v8::Array can only be created when context is already entered (otherwise v8 segfaults!)
2370.2.5 by Henrik Ingo
Honoring EcmaScript standard arguments are made available as arguments[]
170
  v8::Persistent<v8::Context> context = v8::Context::New( NULL, global );
171
  if ( context.IsEmpty() ) {
2370.2.7 by Henrik Ingo
Use my_error() to return v8 errors to the client instead of stdout/log.
172
    char buf[100];
2370.2.8 by Henrik Ingo
Change name from js_eval() to just js(), also change name of plugin itself.
173
    sprintf(buf, "Error in js() while creating JavaScript context in %s.", JS_ENGINE);
2370.2.7 by Henrik Ingo
Use my_error() to return v8 errors to the client instead of stdout/log.
174
    my_error(ER_SCRIPT, MYF(0), buf);
2370.2.2 by Henrik Ingo
js_eval() : Working execution of JavaScript code with the v8 engine.
175
    return NULL;
176
  }
177
  context->Enter();
2370.2.4 by Henrik Ingo
Arguments 2 to N are now passed to the js script in array argv.
178
   
179
  v8::Handle<v8::Array> a = v8::Array::New(arg_count-1);
180
  for( uint64_t n = 1; n < arg_count; n++ )
181
  {
2370.2.5 by Henrik Ingo
Honoring EcmaScript standard arguments are made available as arguments[]
182
    // Need to do this differently for ints, doubles and strings
183
    // TODO: There is also ROW_RESULT. Is that relevant here? What does it look like? I could pass rows as an array or object.
184
    if( args[n]->result_type() == INT_RESULT ){
2370.2.15 by Henrik Ingo
Added tests for JS().
185
      // TODO: Turns out Drizzle doesn't do unsigned. So this code path can never happen? (I can't test it at least...)
2370.2.5 by Henrik Ingo
Honoring EcmaScript standard arguments are made available as arguments[]
186
      if( args[n]->is_unsigned() ) {
187
        a->Set( n-1, v8::Integer::NewFromUnsigned( (uint32_t) args[n]->val_uint() ) );
188
      } else {
189
        a->Set( n-1, v8::Integer::New((int32_t)args[n]->val_int() ) );
190
      }
191
    } else if ( args[n]->result_type() == REAL_RESULT || args[n]->result_type() == DECIMAL_RESULT ) {
192
      a->Set( n-1, v8::Number::New(args[n]->val_real() ) );
193
    } else if ( true || args[n]->result_type() == STRING_RESULT ) {
2370.2.11 by Henrik Ingo
Arguments that are of type DATETIME are now created as JavaScript
194
      if ( args[n]->is_datetime() ) {
195
        // DATE/TIME values are also STRING_RESULT, make them a Date type in v8
196
        // Now we need to get the unix timestamp integer, surprisingly tricky...
197
        // TODO: This should really be just args[n]->get_epoch_seconds(). I need to write a separate patch for Item class one of these days.
198
        type::Time ltime;
199
        Timestamp temporal;
200
        args[n]->get_date(ltime, 0);
201
        temporal.set_years(ltime.year);
202
        temporal.set_months(ltime.month);
203
        temporal.set_days(ltime.day);
204
        temporal.set_hours(ltime.hour);
205
        temporal.set_minutes(ltime.minute);
206
        temporal.set_seconds(ltime.second);
207
        temporal.set_epoch_seconds();
208
        if (temporal.is_valid())
209
        {
210
          time_t tmp;
211
          temporal.to_time_t(tmp);
212
          // Pay attention, Ecmascript defines a date as *milliseconds* since unix epoch
213
          // Also, on platforms where time_t is 32 bit, we need explicit cast to 64 bit integer
214
          a->Set( n-1, v8::Date::New(((uint64_t)tmp)*1000) );
215
        } else {
216
          a->Set( n-1, v8::String::New(args[n]->val_str(str)->c_str() ) );
217
        }
218
      } else {
219
        // Default to creating string values in JavaScript
220
        a->Set( n-1, v8::String::New(args[n]->val_str(str)->c_str() ) );
221
      }
2370.2.5 by Henrik Ingo
Honoring EcmaScript standard arguments are made available as arguments[]
222
    }
223
    // If user has given a name to the arguments, pass these as global variables
224
    if( ! args[n]->is_autogenerated_name ) {
225
      if( args[n]->result_type() == INT_RESULT ){
226
        if( args[n]->is_unsigned() ) {
2370.2.11 by Henrik Ingo
Arguments that are of type DATETIME are now created as JavaScript
227
          context->Global()->Set( v8::String::New( args[n]->name ), v8::Integer::NewFromUnsigned( (uint32_t) args[n]->val_uint() ) );
2370.2.5 by Henrik Ingo
Honoring EcmaScript standard arguments are made available as arguments[]
228
        } else {
2370.2.11 by Henrik Ingo
Arguments that are of type DATETIME are now created as JavaScript
229
          context->Global()->Set( v8::String::New( args[n]->name ), v8::Integer::New((int32_t)args[n]->val_int() ) );
2370.2.5 by Henrik Ingo
Honoring EcmaScript standard arguments are made available as arguments[]
230
        }
231
      } else if ( args[n]->result_type() == REAL_RESULT || args[n]->result_type() == DECIMAL_RESULT ) {
2370.2.11 by Henrik Ingo
Arguments that are of type DATETIME are now created as JavaScript
232
        context->Global()->Set( v8::String::New( args[n]->name ), v8::Number::New(args[n]->val_real() ) );
2370.2.5 by Henrik Ingo
Honoring EcmaScript standard arguments are made available as arguments[]
233
      } else if ( true || args[n]->result_type() == STRING_RESULT ) {
2370.2.11 by Henrik Ingo
Arguments that are of type DATETIME are now created as JavaScript
234
      if ( args[n]->is_datetime() ) {
235
        // DATE/TIME values are also STRING_RESULT, make them a Date type in v8
236
        // Now we need to get the unix timestamp integer, surprisingly tricky...
237
        // TODO: This should really be just args[n]->get_epoch_seconds(). I need to write a separate patch for Item class one of these days.
238
        type::Time ltime;
239
        Timestamp temporal;
240
        args[n]->get_date(ltime, 0);
241
        temporal.set_years(ltime.year);
242
        temporal.set_months(ltime.month);
243
        temporal.set_days(ltime.day);
244
        temporal.set_hours(ltime.hour);
245
        temporal.set_minutes(ltime.minute);
246
        temporal.set_seconds(ltime.second);
247
        temporal.set_epoch_seconds();
248
        if (temporal.is_valid())
249
        {
250
          time_t tmp;
251
          temporal.to_time_t(tmp);
252
          // Pay attention, Ecmascript defines a date as *milliseconds* since unix epoch
253
          // Also, on platforms where time_t is 32 bit, we need explicit cast to 64 bit integer
254
          context->Global()->Set( v8::String::New( args[n]->name ), v8::Date::New(((uint64_t)tmp)*1000) );
255
        } else {
256
          context->Global()->Set( v8::String::New( args[n]->name ), v8::String::New(args[n]->val_str(str)->c_str() ) );
257
        }
258
      } else {
259
        context->Global()->Set( v8::String::New( args[n]->name ), v8::String::New(args[n]->val_str(str)->c_str() ) );
260
      }
2370.2.5 by Henrik Ingo
Honoring EcmaScript standard arguments are made available as arguments[]
261
      }
262
    }
2370.2.4 by Henrik Ingo
Arguments 2 to N are now passed to the js script in array argv.
263
  }
264
  //Need to fetch the global element back from context, global doesn't work anymore
2370.2.5 by Henrik Ingo
Honoring EcmaScript standard arguments are made available as arguments[]
265
  context->Global()->Set( v8::String::New("arguments"), a );
2370.2.4 by Henrik Ingo
Arguments 2 to N are now passed to the js script in array argv.
266
2370.2.2 by Henrik Ingo
js_eval() : Working execution of JavaScript code with the v8 engine.
267
  
268
  
269
  // Compile the source code.
270
  v8::TryCatch try_catch;
271
  v8::Handle<v8::Value> result;
2370.2.4 by Henrik Ingo
Arguments 2 to N are now passed to the js script in array argv.
272
  // Create a v8 string containing the JavaScript source code.
273
  // Convert from drizzled::String to char* string to v8::String.
274
  v8::Handle<v8::String> source = v8::String::New(source_str->c_str());
2370.2.2 by Henrik Ingo
js_eval() : Working execution of JavaScript code with the v8 engine.
275
  v8::Handle<v8::Script> script = v8::Script::Compile(source);
2370.2.5 by Henrik Ingo
Honoring EcmaScript standard arguments are made available as arguments[]
276
  if ( script.IsEmpty() ) {
2370.2.10 by Henrik Ingo
Change names and style of the v8 sample code to drizzle like code.
277
    emit_drizzle_error(&try_catch);
2370.2.2 by Henrik Ingo
js_eval() : Working execution of JavaScript code with the v8 engine.
278
    return NULL;
279
  } else {
280
    result = script->Run();
2370.2.5 by Henrik Ingo
Honoring EcmaScript standard arguments are made available as arguments[]
281
    if ( result.IsEmpty() ) {
282
      assert( try_catch.HasCaught() );
2370.2.10 by Henrik Ingo
Change names and style of the v8 sample code to drizzle like code.
283
      emit_drizzle_error( &try_catch );
2370.2.3 by Henrik Ingo
Use v8::Locker to allow multiple threads to use v8 engine.
284
      // Dispose of Persistent objects before returning. (Is it needed?)
285
      context->Exit();
286
      context.Dispose();
2370.2.2 by Henrik Ingo
js_eval() : Working execution of JavaScript code with the v8 engine.
287
      return NULL;
288
    } else {
2370.2.5 by Henrik Ingo
Honoring EcmaScript standard arguments are made available as arguments[]
289
      assert( !try_catch.HasCaught() );
290
      if ( result->IsUndefined() ) {
291
        // Nothing wrong here, but we return Undefined as NULL.
2370.2.3 by Henrik Ingo
Use v8::Locker to allow multiple threads to use v8 engine.
292
        // Dispose of Persistent objects before returning. (Is it needed?)
293
        context->Exit();
294
        context.Dispose();
2370.2.2 by Henrik Ingo
js_eval() : Working execution of JavaScript code with the v8 engine.
295
        return NULL;
296
      }
297
    }
298
  }
299
    
300
  // Run the script to get the result.
301
  //v8::Handle<v8::Value> foo = script->Run();
302
  v8::Handle<v8::String> rstring = result->ToString();
303
  
304
  // Convert the result to a drizzled::String and print it.
305
  // Allocate space to the drizzled::String 
2370.2.4 by Henrik Ingo
Arguments 2 to N are now passed to the js script in array argv.
306
  str->free(); //TODO: Check the source for alloc(), but apparently I don't need this line?
2370.2.5 by Henrik Ingo
Honoring EcmaScript standard arguments are made available as arguments[]
307
  str->alloc( rstring->Utf8Length() );
2370.2.2 by Henrik Ingo
js_eval() : Working execution of JavaScript code with the v8 engine.
308
  // Now copy string from v8 heap to drizzled heap
2370.2.5 by Henrik Ingo
Honoring EcmaScript standard arguments are made available as arguments[]
309
  rstring->WriteUtf8( str->ptr() );
2370.2.2 by Henrik Ingo
js_eval() : Working execution of JavaScript code with the v8 engine.
310
  // drizzled::String doesn't actually set string length properly in alloc(), so set it now
2370.2.5 by Henrik Ingo
Honoring EcmaScript standard arguments are made available as arguments[]
311
  str->length( rstring->Utf8Length() );
2370.2.1 by Henrik Ingo
Adding new plugin "js_eval" that takes 1 or more strings as arguments
312
 
2370.2.2 by Henrik Ingo
js_eval() : Working execution of JavaScript code with the v8 engine.
313
  context->Exit();
314
  context.Dispose();
2370.2.1 by Henrik Ingo
Adding new plugin "js_eval" that takes 1 or more strings as arguments
315
2370.2.2 by Henrik Ingo
js_eval() : Working execution of JavaScript code with the v8 engine.
316
  // There was no error and value returned is not undefined, so it's not null.
2370.2.1 by Henrik Ingo
Adding new plugin "js_eval" that takes 1 or more strings as arguments
317
  null_value= false;
2370.2.4 by Henrik Ingo
Arguments 2 to N are now passed to the js script in array argv.
318
  return str;
2370.2.1 by Henrik Ingo
Adding new plugin "js_eval" that takes 1 or more strings as arguments
319
}
320
2370.2.2 by Henrik Ingo
js_eval() : Working execution of JavaScript code with the v8 engine.
321
322
323
2370.2.8 by Henrik Ingo
Change name from js_eval() to just js(), also change name of plugin itself.
324
plugin::Create_function<JsFunction> *js_function = NULL;
2370.2.1 by Henrik Ingo
Adding new plugin "js_eval" that takes 1 or more strings as arguments
325
2370.2.5 by Henrik Ingo
Honoring EcmaScript standard arguments are made available as arguments[]
326
static int initialize( module::Context &context )
2370.2.1 by Henrik Ingo
Adding new plugin "js_eval" that takes 1 or more strings as arguments
327
{
2370.2.8 by Henrik Ingo
Change name from js_eval() to just js(), also change name of plugin itself.
328
  js_function = new plugin::Create_function<JsFunction>("js");
329
  context.add( js_function );
2370.2.3 by Henrik Ingo
Use v8::Locker to allow multiple threads to use v8 engine.
330
  // Initialize V8
331
  v8::V8::Initialize();
2370.2.1 by Henrik Ingo
Adding new plugin "js_eval" that takes 1 or more strings as arguments
332
  return 0;
333
}
334
2370.2.2 by Henrik Ingo
js_eval() : Working execution of JavaScript code with the v8 engine.
335
2370.2.12 by Henrik Ingo
Add missing doxygen comments to a few helper functions. Cleanup
336
/* Functions that are part of the JavaScript API ***************************/
2370.2.2 by Henrik Ingo
js_eval() : Working execution of JavaScript code with the v8 engine.
337
2370.2.12 by Henrik Ingo
Add missing doxygen comments to a few helper functions. Cleanup
338
/**
339
 * @brief Binds as db.js.version() inside JavaScript.
340
 * @return Version number of v8 engine
341
 */
2370.2.5 by Henrik Ingo
Honoring EcmaScript standard arguments are made available as arguments[]
342
v8::Handle<v8::Value> V8Version( const v8::Arguments& ) {
343
  return v8::String::New( v8::V8::GetVersion() );
2370.2.2 by Henrik Ingo
js_eval() : Working execution of JavaScript code with the v8 engine.
344
}
345
2370.2.12 by Henrik Ingo
Add missing doxygen comments to a few helper functions. Cleanup
346
/**
347
 * @brief Binds as db.js.engine() inside JavaScript.
348
 * @return The string "v8"
349
 */
2370.2.5 by Henrik Ingo
Honoring EcmaScript standard arguments are made available as arguments[]
350
v8::Handle<v8::Value> JsEngine( const v8::Arguments& ) {
351
  return v8::String::New( JS_ENGINE );
2370.2.3 by Henrik Ingo
Use v8::Locker to allow multiple threads to use v8 engine.
352
}
2370.2.2 by Henrik Ingo
js_eval() : Working execution of JavaScript code with the v8 engine.
353
2370.2.10 by Henrik Ingo
Change names and style of the v8 sample code to drizzle like code.
354
} // namespace js
355
356
} // namespace drizzle_plugin
2370.2.2 by Henrik Ingo
js_eval() : Working execution of JavaScript code with the v8 engine.
357
2370.2.1 by Henrik Ingo
Adding new plugin "js_eval" that takes 1 or more strings as arguments
358
DRIZZLE_DECLARE_PLUGIN
359
{
360
  DRIZZLE_VERSION_ID,
2370.2.8 by Henrik Ingo
Change name from js_eval() to just js(), also change name of plugin itself.
361
  "js",
2370.2.17 by Henrik Ingo
Wrote end user documentation for JS().
362
  "0.9",
2370.2.1 by Henrik Ingo
Adding new plugin "js_eval" that takes 1 or more strings as arguments
363
  "Henrik Ingo",
364
  "Execute JavaScript code with supplied arguments",
365
  PLUGIN_LICENSE_GPL,
2370.2.10 by Henrik Ingo
Change names and style of the v8 sample code to drizzle like code.
366
  drizzle_plugin::js::initialize, /* Plugin Init */
2370.2.1 by Henrik Ingo
Adding new plugin "js_eval" that takes 1 or more strings as arguments
367
  NULL,   /* depends */              
368
  NULL    /* config options */
369
}
370
DRIZZLE_DECLARE_PLUGIN_END;
371