My codebase is currently running on V8 3.30 in case it matters.
I'm writing a marshalling system to link JS function calls to native C++ code. As part of this system, I need to convert function arguments into native C++ types. For the sake of example, lets say I'm implementing a simple binding to C's "atan2" function.
double atan2(double y, double x);
So, an example v8::FunctionCallback for this case
void V8CallAtan2( const v8::FunctionCallbackInfo<v8::Value>& info )
{
v8::Isolate* isolate = info.GetIsolate();
// Not sure if this is required, since we must be in an isolate scope already to be getting called from script
v8::Isolate::Scope isolateScope(isolate);
// Don't hold onto Local handles allocated by this function
v8::Handle::Scope handleScope(isolate);
// Some simple checks that we're not being stupid
if(info.IsConstructCall())
{
isolate->ThrowException( v8::String::NewFromUtf8( isolate, "Called 'atan2' as a constructor" ) );
return;
}
if(info.Length() != 2)
{
isolate->ThrowException( v8::String::NewFromUtf8( isolate, "Called 'atan2' with incorrect number of arguments." ) );
return;
}
// Extract arguments from the call
v8::Local<v8::Value> yVal = info[0];
v8::Local<v8::Value> xVal = info[1];
// Marshal into native C++ types
double y = yVal->NumberValue(); // HERE1
double x = xVal->NumberValue(); // HERE2
// Call native function
double result = atan2(y,x);
// Marshal return value back into a JS type
v8::Local<v8::Value> resultVal = v8::Number::New(isolate, result);
// and return it to the caller
info.GetReturnValue().Set( resultVal );
}
From reading the source code to NumberValue() it looks like this call could potentially throw a JS exception, which makes sense--the arguments could be of some type that isn't convertible to double. So, if the line at HERE1 throws a JS exception, if my understanding of ThrowException is correct, I'm not allowed to do any further JS operations (including calling NumberValue() at HERE2), and instead need to immediately return control to v8 by returning from my callback -- as I do in the sanity checks before reading the arguments.
But I haven't been able to find a way to ask the Isoalte if there is a pending exception, at least not in the public API. How do I detect this case?
I noticed that newer versions of v8 have Value::NumberValue() return Maybe<double> instead, and I'm considering pushing a v8 upgrade for that reason. But first I want to know if there's a fix without impacting the other users on my team.
Thanks!
-- ryan