On Sat, Mar 14, 2009 at 3:43 PM, Alex Iskander <[email protected]> wrote:
> I just tested code almost just like that, and it worked fine. Logically,
> there should be no problem with it, as long as you catch the error. Where
> things will not work is when your "catch" is in a function calling the
> JavaScript.
When you say "calling JS", do you mean using Script::Run(), or do you
mean "using the v8 API to exec operations on JS objects"? i'm not
using Script::Run() (or similar) except at the top-most level of the
app (the shell).
> Because the JavaScript frames don't keep track of themselves the
> same way, C++ won't be able to trace back up them to deliver the exception
> to the right place.
My initial experiment in this direction was a proxy function like this:
Handle<Value> Toss( char const * fmt, ... );
which produces a printf-style exception message and returns
ThrowException(the error message). However, i found that using that
function lead to stack corruption (for reasons i can't explain - use
the same code in SpiderMonkey-based stuff). So... my assumption was
that i don't know the whole story about the JS stack (but it doesn't
seem to follow the same rules as the C++ stack?), and thus i'm leary
of using C++ exceptions. However, without exceptions i can't do
certain forms of automatic type conversion (e.g. JS-to-(T &), which
needs to throw if the conversion cannot happen, to avoid a segfault).
> I tested that as well. To reiterate, throwing and
> catching an exception inside a function called from JavaScript is fine.
> Throwing an exception meant to be caught outside of the function called from
> JavaScript won't work, because C++ won't be able to find the catch.
Where does that leave me with proxy functions? e.g. a user binds
MyType::foo() to a JS function. That binding necessarily creates a
proxy function which 1) convers argv.This() to a native object and
then forwards to MyType::foo(). Must i then catch in foo() or can i do
it in the (template-generated) proxy function/wrapper? i.e. do i
*need* to catch it at the most local point possible or can i let it
propagate up the stack a bit to be caught by a more generic handler?
For example:
template < typename A0, typename A1, typename NativeFunc >
Handle<Value> FwdToFunc2( NativeFunc func, Arguments const & argv )
{
if( argv.Length() != 2 ) return
ThrowException(String::New("Requires exactly 2 arguments!");
// ^^^ if i use my Toss() function instead of ThrowException() i
get stack corruption here!!!
try{
return CastToJS( func( CastFromJS<A0>(argv[0]),
CastFromJS<A1>(argv[1]) ) );
}
catch(exception const & ex) {
return ThrowException(String::New(ex.what());
}
// is everything okay here as long as i don't propagate a native exception?
return ...;
}
What i'm worried about most there is the actual call to func(), as
that can of course perform arbitrary v8 operations and i don't know
what happens to v8's internals if a function call from five levels
deep into func()'s call chain throws and i don't catch it until the
above block.
i know it "should" work, but after getting stack corruption in some
cases when dealing with exceptions in v8 i'm a tad bit nervous about
it.
--
----- stephan beal
http://wanderinghorse.net/home/stephan/
--~--~---------~--~----~------------~-------~--~----~
v8-users mailing list
[email protected]
http://groups.google.com/group/v8-users
-~----------~----~----~----~------~----~------~--~---