92
93
if (message.IsEmpty()) {
93
94
// V8 didn't provide any extra information about this error; just
94
95
// print the exception.
95
printf("%s\n", exception_string);
96
my_error(ER_SCRIPT, MYF(0), exception_string);
97
// Print (filename):(line number): (message).
98
v8::String::Utf8Value filename(message->GetScriptResourceName());
99
const char* filename_string = ToCString(filename);
98
char buf[2048]; // TODO: magic number. I'm sure this will crash if you supply a line of javascript longer than 2048.
100
99
int linenum = message->GetLineNumber();
101
printf("%s:%i: %s\n", filename_string, linenum, exception_string);
100
sprintf(buf, "At line %i: %s (Do SHOW ERRORS for more information.)", linenum, exception_string);
101
my_error(ER_SCRIPT, MYF(0), buf);
102
102
// Print line of source code.
103
103
v8::String::Utf8Value sourceline(message->GetSourceLine());
104
104
const char* sourceline_string = ToCString(sourceline);
105
printf("%s\n", sourceline_string);
106
// Print wavy underline (GetUnderline is deprecated).
105
sprintf(buf, "Line %i: %s", linenum, sourceline_string);
106
my_error(ER_SCRIPT, MYF(0), buf);
107
107
int start = message->GetStartColumn();
108
for (int i = 0; i < start; i++) {
111
int end = message->GetEndColumn();
112
for (int i = start; i < end; i++) {
108
sprintf(buf, "Check your script starting at: '%.50s'", &sourceline_string[start]);
109
my_error(ER_SCRIPT, MYF(0), buf);
116
110
v8::String::Utf8Value stack_trace(try_catch->StackTrace());
117
111
if (stack_trace.length() > 0) {
118
112
const char* stack_trace_string = ToCString(stack_trace);
119
printf("%s\n", stack_trace_string);
113
my_error(ER_SCRIPT, MYF(0), stack_trace_string);
127
121
* @note I only compiled this with -O0 but should work with default O2 also.
129
* @todo Accepts more than one parameter, but doesn't use them.
130
* @todo How does it work if I want to return integers and doubles?
123
* @todo datetime and row_result types are not yet handled
131
124
* @todo v8 exceptions are printed to the log. Should be converted to
132
125
* drizzle warning/error and returned with result.
133
126
* @todo Probably the v8 stuff will be moved to it's own function in the future.
127
* @todo Some of the v8 stuff should be done in initialize()
134
128
* @todo Documentation for drizzle manual in .rst format
135
* @todo When available, use v8::Isolate instead of v8::Locker for multithreading
129
* @todo When available, use v8::Isolate instead of v8::Locker for multithreading (or a mix of both)
131
* @note DECIMAL_RESULT type is now a double in JavaScript. This could lose precision.
132
* But to send them as strings would also be awkward (+ operator will do unexpected things).
133
* In any case, we'd need some biginteger (bigdecimal?) kind of library to do anything with higher
134
* precision values anyway. If you want to keep the precision, you can cast your
135
* decimal values to strings explicitly when passing them as arguments.
137
137
* @param res Pointer to the drizzled::String object that will contain the result
138
138
* @return a drizzled::String containing the value returned by executed JavaScript code (value of last executed statement)
147
147
String *source_str=NULL;
148
148
source_str = args[0]->val_str( str );
150
// TODO Some of this (ObjectTemplate bindings) should probably be
151
// moved to initialize, but then it must be allocated on the heap.
153
150
// Need to use Locker in multi-threaded app. v8 is unlocked by the destructor
154
151
// when locker goes out of scope.
155
152
// TODO: Newer versions of v8 provide an Isolate class where you can get a
173
170
// v8::Array can only be created when context is already entered (otherwise v8 segfaults!)
174
171
v8::Persistent<v8::Context> context = v8::Context::New( NULL, global );
175
172
if ( context.IsEmpty() ) {
176
// TODO: how do I set warning/error in the drizzle result?
177
printf( "Error in js_eval() while creating JavaScript context in v8.\n" );
174
sprintf(buf, "Error in js_eval() while creating JavaScript context in %s.", JS_ENGINE);
175
my_error(ER_SCRIPT, MYF(0), buf);
180
178
context->Enter();
183
181
for( uint64_t n = 1; n < arg_count; n++ )
185
183
// Need to do this differently for ints, doubles and strings
184
// TODO: Should also handle dates. See is_datetime() in drizzled/item.h.
186
185
// TODO: There is also ROW_RESULT. Is that relevant here? What does it look like? I could pass rows as an array or object.
187
186
if( args[n]->result_type() == INT_RESULT ){
188
187
if( args[n]->is_unsigned() ) {
193
192
} else if ( args[n]->result_type() == REAL_RESULT || args[n]->result_type() == DECIMAL_RESULT ) {
194
193
a->Set( n-1, v8::Number::New(args[n]->val_real() ) );
195
// TODO: Here's a question: Should DECIMAL_RESULT be sent as double or string?
196
// Kind of unusable either way, we'd need to bind some biginteger arithmetic library into the js environment to make them usable
197
194
} else if ( true || args[n]->result_type() == STRING_RESULT ) {
198
195
// Default to creating string values in JavaScript
199
196
a->Set( n-1, v8::String::New(args[n]->val_str(str)->c_str() ) );
226
223
v8::Handle<v8::String> source = v8::String::New(source_str->c_str());
227
224
v8::Handle<v8::Script> script = v8::Script::Compile(source);
228
225
if ( script.IsEmpty() ) {
229
// TODO: how do I set warning/error in the drizzle result?
230
// Print errors that happened during compilation.
231
226
ReportException(&try_catch);
234
229
result = script->Run();
235
230
if ( result.IsEmpty() ) {
236
231
assert( try_catch.HasCaught() );
237
// TODO: how do I set warning/error in the drizzle result?
238
// Print errors that happened during execution.
239
232
ReportException( &try_catch );
240
233
// Dispose of Persistent objects before returning. (Is it needed?)