Introduce CefV8Exception for returning detailed exception information from CefV8Value::ExecuteFunction*() and add the ability to re-throw exceptions. (issue #317).

git-svn-id: https://chromiumembedded.googlecode.com/svn/trunk@371 5089003a-bbd8-11dd-ad1f-f1f9622dbc98
This commit is contained in:
Marshall Greenblatt 2011-11-10 22:57:23 +00:00
parent cee94a1db9
commit 28f171b26f
16 changed files with 876 additions and 93 deletions

View File

@ -401,6 +401,8 @@
'libcef_dll/cpptoc/stream_writer_cpptoc.h',
'libcef_dll/cpptoc/v8context_cpptoc.cc',
'libcef_dll/cpptoc/v8context_cpptoc.h',
'libcef_dll/cpptoc/v8exception_cpptoc.cc',
'libcef_dll/cpptoc/v8exception_cpptoc.h',
'libcef_dll/cpptoc/v8value_cpptoc.cc',
'libcef_dll/cpptoc/v8value_cpptoc.h',
'libcef_dll/cpptoc/web_urlrequest_cpptoc.cc',

View File

@ -204,6 +204,8 @@
'libcef_dll/ctocpp/stream_writer_ctocpp.h',
'libcef_dll/ctocpp/v8context_ctocpp.cc',
'libcef_dll/ctocpp/v8context_ctocpp.h',
'libcef_dll/ctocpp/v8exception_ctocpp.cc',
'libcef_dll/ctocpp/v8exception_ctocpp.h',
'libcef_dll/ctocpp/v8value_ctocpp.cc',
'libcef_dll/ctocpp/v8value_ctocpp.h',
'libcef_dll/ctocpp/web_urlrequest_ctocpp.cc',

View File

@ -2300,10 +2300,11 @@ class CefV8Handler : public virtual CefBase
{
public:
///
// Execute with the specified argument list and return value. Return true if
// the method was handled. To invoke V8 callback functions outside the scope
// of this method you need to keep references to the current V8 context
// (CefV8Context) along with any necessary callback objects.
// Handle execution of the function identified by |name|. |object| is the
// receiver ('this' object) of the function. |arguments| is the list of
// arguments passed to the function. If execution succeeds set |retval| to the
// function return value. If execution fails set |exception| to the exception
// that will be thrown. Return true if execution was handled.
///
/*--cef()--*/
virtual bool Execute(const CefString& name,
@ -2323,9 +2324,11 @@ class CefV8Accessor : public virtual CefBase
{
public:
///
// Called to get an accessor value. |name| is the name of the property being
// accessed. |object| is the This() object from V8's AccessorInfo structure.
// |retval| is the value to return for this property. Return true if handled.
// Handle retrieval the accessor value identified by |name|. |object| is the
// receiver ('this' object) of the accessor. If retrieval succeeds set
// |retval| to the return value. If retrieval fails set |exception| to the
// exception that will be thrown. Return true if accessor retrieval was
// handled.
///
/*--cef()--*/
virtual bool Get(const CefString& name,
@ -2334,10 +2337,11 @@ public:
CefString& exception) =0;
///
// Called to set an accessor value. |name| is the name of the property being
// accessed. |value| is the new value being assigned to this property.
// |object| is the This() object from V8's AccessorInfo structure. Return true
// if handled.
// Handle assignment of the accessor value identified by |name|. |object| is
// the receiver ('this' object) of the accessor. |value| is the new value
// being assigned to the accessor. If assignment fails set |exception| to the
// exception that will be thrown. Return true if accessor assignment was
// handled.
///
/*--cef()--*/
virtual bool Set(const CefString& name,
@ -2346,6 +2350,67 @@ public:
CefString& exception) =0;
};
///
// Class representing a V8 exception.
///
/*--cef(source=library)--*/
class CefV8Exception : public virtual CefBase
{
public:
///
// Returns the exception message.
///
/*--cef()--*/
virtual CefString GetMessage() =0;
///
// Returns the line of source code that the exception occurred within.
///
/*--cef()--*/
virtual CefString GetSourceLine() =0;
///
// Returns the resource name for the script from where the function causing
// the error originates.
///
/*--cef()--*/
virtual CefString GetScriptResourceName() =0;
///
// Returns the 1-based number of the line where the error occurred or 0 if the
// line number is unknown.
///
/*--cef()--*/
virtual int GetLineNumber() =0;
///
// Returns the index within the script of the first character where the error
// occurred.
///
/*--cef()--*/
virtual int GetStartPosition() =0;
///
// Returns the index within the script of the last character where the error
// occurred.
///
/*--cef()--*/
virtual int GetEndPosition() =0;
///
// Returns the index within the line of the first character where the error
// occurred.
///
/*--cef()--*/
virtual int GetStartColumn() =0;
///
// Returns the index within the line of the last character where the error
// occurred.
///
/*--cef()--*/
virtual int GetEndColumn() =0;
};
///
// Class representing a V8 value. The methods of this class should only be
@ -2394,23 +2459,35 @@ public:
/*--cef()--*/
static CefRefPtr<CefV8Value> CreateString(const CefString& value);
///
// Create a new CefV8Value object of type object.
// Create a new CefV8Value object of type object. This method should only be
// called from within the scope of a CefJSBindingHandler, CefV8Handler or
// CefV8Accessor callback, or in combination with calling Enter() and Exit()
// on a stored CefV8Context reference.
///
/*--cef()--*/
static CefRefPtr<CefV8Value> CreateObject(CefRefPtr<CefBase> user_data);
///
// Create a new CefV8Value object of type object with accessors.
// Create a new CefV8Value object of type object with accessors. This method
// should only be called from within the scope of a CefJSBindingHandler,
// CefV8Handler or CefV8Accessor callback, or in combination with calling
// Enter() and Exit() on a stored CefV8Context reference.
///
/*--cef(capi_name=cef_v8value_create_object_with_accessor)--*/
static CefRefPtr<CefV8Value> CreateObject(CefRefPtr<CefBase> user_data,
CefRefPtr<CefV8Accessor> accessor);
///
// Create a new CefV8Value object of type array.
// Create a new CefV8Value object of type array. This method should only be
// called from within the scope of a CefJSBindingHandler, CefV8Handler or
// CefV8Accessor callback, or in combination with calling Enter() and Exit()
// on a stored CefV8Context reference.
///
/*--cef()--*/
static CefRefPtr<CefV8Value> CreateArray();
///
// Create a new CefV8Value object of type function.
// Create a new CefV8Value object of type function. This method should only be
// called from within the scope of a CefJSBindingHandler, CefV8Handler or
// CefV8Accessor callback, or in combination with calling Enter() and Exit()
// on a stored CefV8Context reference.
///
/*--cef()--*/
static CefRefPtr<CefV8Value> CreateFunction(const CefString& name,
@ -2601,24 +2678,39 @@ public:
virtual CefRefPtr<CefV8Handler> GetFunctionHandler() =0;
///
// Execute the function using the current V8 context.
// Execute the function using the current V8 context. This method should only
// be called from within the scope of a CefV8Handler or CefV8Accessor
// callback, or in combination with calling Enter() and Exit() on a stored
// CefV8Context reference. |object| is the receiver ('this' object) of the
// function. |arguments| is the list of arguments that will be passed to the
// function. If execution succeeds |retval| will be set to the function return
// value. If execution fails |exception| will be set to the exception that was
// thrown. If |rethrow_exception| is true any exception will also be re-
// thrown. This method returns false if called incorrectly.
///
/*--cef()--*/
virtual bool ExecuteFunction(CefRefPtr<CefV8Value> object,
const CefV8ValueList& arguments,
CefRefPtr<CefV8Value>& retval,
CefString& exception) =0;
CefRefPtr<CefV8Exception>& exception,
bool rethrow_exception) =0;
///
// Execute the function using the specified V8 context.
// Execute the function using the specified V8 context. |object| is the
// receiver ('this' object) of the function. |arguments| is the list of
// arguments that will be passed to the function. If execution succeeds
// |retval| will be set to the function return value. If execution fails
// |exception| will be set to the exception that was thrown. If
// |rethrow_exception| is true any exception will also be re-thrown. This
// method returns false if called incorrectly.
///
/*--cef()--*/
virtual bool ExecuteFunctionWithContext(CefRefPtr<CefV8Context> context,
CefRefPtr<CefV8Value> object,
const CefV8ValueList& arguments,
CefRefPtr<CefV8Value>& retval,
CefString& exception) =0;
CefRefPtr<CefV8Exception>& exception,
bool rethrow_exception) =0;
};

View File

@ -2079,10 +2079,11 @@ typedef struct _cef_v8handler_t
cef_base_t base;
///
// Execute with the specified argument list and return value. Return true (1)
// if the function was handled. To invoke V8 callback functions outside the
// scope of this function you need to keep references to the current V8
// context (cef_v8context_t) along with any necessary callback objects.
// Handle execution of the function identified by |name|. |object| is the
// receiver ('this' object) of the function. |arguments| is the list of
// arguments passed to the function. If execution succeeds set |retval| to the
// function return value. If execution fails set |exception| to the exception
// that will be thrown. Return true (1) if execution was handled.
///
int (CEF_CALLBACK *execute)(struct _cef_v8handler_t* self,
const cef_string_t* name, struct _cef_v8value_t* object,
@ -2103,9 +2104,10 @@ typedef struct _cef_v8accessor_t
cef_base_t base;
///
// Called to get an accessor value. |name| is the name of the property being
// accessed. |object| is the This() object from V8's AccessorInfo structure.
// |retval| is the value to return for this property. Return true (1) if
// Handle retrieval the accessor value identified by |name|. |object| is the
// receiver ('this' object) of the accessor. If retrieval succeeds set
// |retval| to the return value. If retrieval fails set |exception| to the
// exception that will be thrown. Return true (1) if accessor retrieval was
// handled.
///
int (CEF_CALLBACK *get)(struct _cef_v8accessor_t* self,
@ -2113,10 +2115,11 @@ typedef struct _cef_v8accessor_t
struct _cef_v8value_t** retval, cef_string_t* exception);
///
// Called to set an accessor value. |name| is the name of the property being
// accessed. |value| is the new value being assigned to this property.
// |object| is the This() object from V8's AccessorInfo structure. Return true
// (1) if handled.
// Handle assignment of the accessor value identified by |name|. |object| is
// the receiver ('this' object) of the accessor. |value| is the new value
// being assigned to the accessor. If assignment fails set |exception| to the
// exception that will be thrown. Return true (1) if accessor assignment was
// handled.
///
int (CEF_CALLBACK *set)(struct _cef_v8accessor_t* self,
const cef_string_t* name, struct _cef_v8value_t* object,
@ -2125,6 +2128,69 @@ typedef struct _cef_v8accessor_t
} cef_v8accessor_t;
///
// Structure representing a V8 exception.
///
typedef struct _cef_v8exception_t
{
// Base structure.
cef_base_t base;
///
// Returns the exception message.
///
// The resulting string must be freed by calling cef_string_userfree_free().
cef_string_userfree_t (CEF_CALLBACK *get_message)(
struct _cef_v8exception_t* self);
///
// Returns the line of source code that the exception occurred within.
///
// The resulting string must be freed by calling cef_string_userfree_free().
cef_string_userfree_t (CEF_CALLBACK *get_source_line)(
struct _cef_v8exception_t* self);
///
// Returns the resource name for the script from where the function causing
// the error originates.
///
// The resulting string must be freed by calling cef_string_userfree_free().
cef_string_userfree_t (CEF_CALLBACK *get_script_resource_name)(
struct _cef_v8exception_t* self);
///
// Returns the 1-based number of the line where the error occurred or 0 if the
// line number is unknown.
///
int (CEF_CALLBACK *get_line_number)(struct _cef_v8exception_t* self);
///
// Returns the index within the script of the first character where the error
// occurred.
///
int (CEF_CALLBACK *get_start_position)(struct _cef_v8exception_t* self);
///
// Returns the index within the script of the last character where the error
// occurred.
///
int (CEF_CALLBACK *get_end_position)(struct _cef_v8exception_t* self);
///
// Returns the index within the line of the first character where the error
// occurred.
///
int (CEF_CALLBACK *get_start_column)(struct _cef_v8exception_t* self);
///
// Returns the index within the line of the last character where the error
// occurred.
///
int (CEF_CALLBACK *get_end_column)(struct _cef_v8exception_t* self);
} cef_v8exception_t;
///
// Structure representing a V8 value. The functions of this structure should
// only be called on the UI thread.
@ -2323,20 +2389,36 @@ typedef struct _cef_v8value_t
struct _cef_v8value_t* self);
///
// Execute the function using the current V8 context.
// Execute the function using the current V8 context. This function should
// only be called from within the scope of a cef_v8handler_t or
// cef_v8accessor_t callback, or in combination with calling enter() and
// exit() on a stored cef_v8context_t reference. |object| is the receiver
// ('this' object) of the function. |arguments| is the list of arguments that
// will be passed to the function. If execution succeeds |retval| will be set
// to the function return value. If execution fails |exception| will be set to
// the exception that was thrown. If |rethrow_exception| is true (1) any
// exception will also be re- thrown. This function returns false (0) if
// called incorrectly.
///
int (CEF_CALLBACK *execute_function)(struct _cef_v8value_t* self,
struct _cef_v8value_t* object, size_t argumentCount,
struct _cef_v8value_t* const* arguments, struct _cef_v8value_t** retval,
cef_string_t* exception);
struct _cef_v8exception_t** exception, int rethrow_exception);
///
// Execute the function using the specified V8 context.
// Execute the function using the specified V8 context. |object| is the
// receiver ('this' object) of the function. |arguments| is the list of
// arguments that will be passed to the function. If execution succeeds
// |retval| will be set to the function return value. If execution fails
// |exception| will be set to the exception that was thrown. If
// |rethrow_exception| is true (1) any exception will also be re-thrown. This
// function returns false (0) if called incorrectly.
///
int (CEF_CALLBACK *execute_function_with_context)(struct _cef_v8value_t* self,
struct _cef_v8context_t* context, struct _cef_v8value_t* object,
size_t argumentCount, struct _cef_v8value_t* const* arguments,
struct _cef_v8value_t** retval, cef_string_t* exception);
struct _cef_v8value_t** retval, struct _cef_v8exception_t** exception,
int rethrow_exception);
} cef_v8value_t;
@ -2377,23 +2459,36 @@ CEF_EXPORT cef_v8value_t* cef_v8value_create_date(const cef_time_t* date);
CEF_EXPORT cef_v8value_t* cef_v8value_create_string(const cef_string_t* value);
///
// Create a new cef_v8value_t object of type object.
// Create a new cef_v8value_t object of type object. This function should only
// be called from within the scope of a cef_jsbinding_handler_t, cef_v8handler_t
// or cef_v8accessor_t callback, or in combination with calling enter() and
// exit() on a stored cef_v8context_t reference.
///
CEF_EXPORT cef_v8value_t* cef_v8value_create_object(cef_base_t* user_data);
///
// Create a new cef_v8value_t object of type object with accessors.
// Create a new cef_v8value_t object of type object with accessors. This
// function should only be called from within the scope of a
// cef_jsbinding_handler_t, cef_v8handler_t or cef_v8accessor_t callback, or in
// combination with calling enter() and exit() on a stored cef_v8context_t
// reference.
///
CEF_EXPORT cef_v8value_t* cef_v8value_create_object_with_accessor(
cef_base_t* user_data, cef_v8accessor_t* accessor);
///
// Create a new cef_v8value_t object of type array.
// Create a new cef_v8value_t object of type array. This function should only be
// called from within the scope of a cef_jsbinding_handler_t, cef_v8handler_t or
// cef_v8accessor_t callback, or in combination with calling enter() and exit()
// on a stored cef_v8context_t reference.
///
CEF_EXPORT cef_v8value_t* cef_v8value_create_array();
///
// Create a new cef_v8value_t object of type function.
// Create a new cef_v8value_t object of type function. This function should only
// be called from within the scope of a cef_jsbinding_handler_t, cef_v8handler_t
// or cef_v8accessor_t callback, or in combination with calling enter() and
// exit() on a stored cef_v8context_t reference.
///
CEF_EXPORT cef_v8value_t* cef_v8value_create_function(const cef_string_t* name,
cef_v8handler_t* handler);

View File

@ -284,6 +284,54 @@ private:
CefV8Handler* handler_;
};
class CefV8ExceptionImpl : public CefV8Exception
{
public:
explicit CefV8ExceptionImpl(v8::Handle<v8::Message> message)
: line_number_(0),
start_position_(0),
end_position_(0),
start_column_(0),
end_column_(0)
{
if (message.IsEmpty())
return;
GetCefString(message->Get(), message_);
GetCefString(message->GetSourceLine(), source_line_);
if (!message->GetScriptResourceName().IsEmpty())
GetCefString(message->GetScriptResourceName()->ToString(), script_);
line_number_ = message->GetLineNumber();
start_position_ = message->GetStartPosition();
end_position_ = message->GetEndPosition();
start_column_ = message->GetStartColumn();
end_column_ = message->GetEndColumn();
}
virtual CefString GetMessage() OVERRIDE { return message_; }
virtual CefString GetSourceLine() OVERRIDE { return source_line_; }
virtual CefString GetScriptResourceName() OVERRIDE { return script_; }
virtual int GetLineNumber() OVERRIDE { return line_number_; }
virtual int GetStartPosition() OVERRIDE { return start_position_; }
virtual int GetEndPosition() OVERRIDE { return end_position_; }
virtual int GetStartColumn() OVERRIDE { return start_column_; }
virtual int GetEndColumn() OVERRIDE { return end_column_; }
protected:
CefString message_;
CefString source_line_;
CefString script_;
int line_number_;
int start_position_;
int end_position_;
int start_column_;
int end_column_;
IMPLEMENT_REFCOUNTING(CefV8ExceptionImpl);
};
} // namespace
bool CefRegisterExtension(const CefString& extension_name,
@ -974,12 +1022,13 @@ CefRefPtr<CefV8Handler> CefV8ValueImpl::GetFunctionHandler()
bool CefV8ValueImpl::ExecuteFunction(CefRefPtr<CefV8Value> object,
const CefV8ValueList& arguments,
CefRefPtr<CefV8Value>& retval,
CefString& exception)
CefRefPtr<CefV8Exception>& exception,
bool rethrow_exception)
{
// An empty context value defaults to the current context.
CefRefPtr<CefV8Context> context;
return ExecuteFunctionWithContext(context, object, arguments, retval,
exception);
exception, rethrow_exception);
}
bool CefV8ValueImpl::ExecuteFunctionWithContext(
@ -987,7 +1036,8 @@ bool CefV8ValueImpl::ExecuteFunctionWithContext(
CefRefPtr<CefV8Value> object,
const CefV8ValueList& arguments,
CefRefPtr<CefV8Value>& retval,
CefString& exception)
CefRefPtr<CefV8Exception>& exception,
bool rethrow_exception)
{
CEF_REQUIRE_UI_THREAD(false);
if(!GetHandle()->IsFunction()) {
@ -1031,11 +1081,9 @@ bool CefV8ValueImpl::ExecuteFunctionWithContext(
v8::TryCatch try_catch;
v8::Local<v8::Value> func_rv = func->Call(recv, argc, argv);
if (try_catch.HasCaught()) {
v8::Local<v8::Message> msg = try_catch.Message();
if (msg.IsEmpty())
exception = "CEF received an empty exception message.";
else
GetCefString(msg->Get(), exception);
exception = new CefV8ExceptionImpl(try_catch.Message());
if (rethrow_exception)
try_catch.ReThrow();
} else {
retval = new CefV8ValueImpl(func_rv);
}

View File

@ -144,13 +144,15 @@ public:
virtual bool ExecuteFunction(CefRefPtr<CefV8Value> object,
const CefV8ValueList& arguments,
CefRefPtr<CefV8Value>& retval,
CefString& exception) OVERRIDE;
CefRefPtr<CefV8Exception>& exception,
bool rethrow_exception) OVERRIDE;
virtual bool ExecuteFunctionWithContext(
CefRefPtr<CefV8Context> context,
CefRefPtr<CefV8Value> object,
const CefV8ValueList& arguments,
CefRefPtr<CefV8Value>& retval,
CefString& exception) OVERRIDE;
CefRefPtr<CefV8Exception>& exception,
bool rethrow_exception) OVERRIDE;
inline v8::Handle<v8::Value> GetHandle()
{

View File

@ -0,0 +1,117 @@
// Copyright (c) 2011 The Chromium Embedded Framework Authors. All rights
// reserved. Use of this source code is governed by a BSD-style license that
// can be found in the LICENSE file.
//
// ---------------------------------------------------------------------------
//
// A portion of this file was generated by the CEF translator tool. When
// making changes by hand only do so within the body of existing function
// implementations. See the translator.README.txt file in the tools directory
// for more information.
//
#include "libcef_dll/cpptoc/v8exception_cpptoc.h"
// MEMBER FUNCTIONS - Body may be edited by hand.
cef_string_userfree_t CEF_CALLBACK v8exception_get_message(
struct _cef_v8exception_t* self)
{
DCHECK(self);
if (!self)
return NULL;
CefString str = CefV8ExceptionCppToC::Get(self)->GetMessage();
return str.DetachToUserFree();
}
cef_string_userfree_t CEF_CALLBACK v8exception_get_source_line(
struct _cef_v8exception_t* self)
{
DCHECK(self);
if (!self)
return NULL;
CefString str = CefV8ExceptionCppToC::Get(self)->GetSourceLine();
return str.DetachToUserFree();
}
cef_string_userfree_t CEF_CALLBACK v8exception_get_script_resource_name(
struct _cef_v8exception_t* self)
{
DCHECK(self);
if (!self)
return NULL;
CefString str = CefV8ExceptionCppToC::Get(self)->GetScriptResourceName();
return str.DetachToUserFree();
}
int CEF_CALLBACK v8exception_get_line_number(struct _cef_v8exception_t* self)
{
DCHECK(self);
if (!self)
return 0;
return CefV8ExceptionCppToC::Get(self)->GetLineNumber();
}
int CEF_CALLBACK v8exception_get_start_position(struct _cef_v8exception_t* self)
{
DCHECK(self);
if (!self)
return 0;
return CefV8ExceptionCppToC::Get(self)->GetStartPosition();
}
int CEF_CALLBACK v8exception_get_end_position(struct _cef_v8exception_t* self)
{
DCHECK(self);
if (!self)
return 0;
return CefV8ExceptionCppToC::Get(self)->GetEndPosition();
}
int CEF_CALLBACK v8exception_get_start_column(struct _cef_v8exception_t* self)
{
DCHECK(self);
if (!self)
return 0;
return CefV8ExceptionCppToC::Get(self)->GetStartColumn();
}
int CEF_CALLBACK v8exception_get_end_column(struct _cef_v8exception_t* self)
{
DCHECK(self);
if (!self)
return 0;
return CefV8ExceptionCppToC::Get(self)->GetEndColumn();
}
// CONSTRUCTOR - Do not edit by hand.
CefV8ExceptionCppToC::CefV8ExceptionCppToC(CefV8Exception* cls)
: CefCppToC<CefV8ExceptionCppToC, CefV8Exception, cef_v8exception_t>(cls)
{
struct_.struct_.get_message = v8exception_get_message;
struct_.struct_.get_source_line = v8exception_get_source_line;
struct_.struct_.get_script_resource_name =
v8exception_get_script_resource_name;
struct_.struct_.get_line_number = v8exception_get_line_number;
struct_.struct_.get_start_position = v8exception_get_start_position;
struct_.struct_.get_end_position = v8exception_get_end_position;
struct_.struct_.get_start_column = v8exception_get_start_column;
struct_.struct_.get_end_column = v8exception_get_end_column;
}
#ifndef NDEBUG
template<> long CefCppToC<CefV8ExceptionCppToC, CefV8Exception,
cef_v8exception_t>::DebugObjCt = 0;
#endif

View File

@ -0,0 +1,34 @@
// Copyright (c) 2011 The Chromium Embedded Framework Authors. All rights
// reserved. Use of this source code is governed by a BSD-style license that
// can be found in the LICENSE file.
//
// ---------------------------------------------------------------------------
//
// This file was generated by the CEF translator tool and should not edited
// by hand. See the translator.README.txt file in the tools directory for
// more information.
//
#ifndef _V8EXCEPTION_CPPTOC_H
#define _V8EXCEPTION_CPPTOC_H
#ifndef BUILDING_CEF_SHARED
#pragma message("Warning: "__FILE__" may be accessed DLL-side only")
#else // BUILDING_CEF_SHARED
#include "include/cef.h"
#include "include/cef_capi.h"
#include "libcef_dll/cpptoc/cpptoc.h"
// Wrap a C++ class with a C structure.
// This class may be instantiated and accessed DLL-side only.
class CefV8ExceptionCppToC
: public CefCppToC<CefV8ExceptionCppToC, CefV8Exception, cef_v8exception_t>
{
public:
CefV8ExceptionCppToC(CefV8Exception* cls);
virtual ~CefV8ExceptionCppToC() {}
};
#endif // BUILDING_CEF_SHARED
#endif // _V8EXCEPTION_CPPTOC_H

View File

@ -11,6 +11,7 @@
//
#include "libcef_dll/cpptoc/v8context_cpptoc.h"
#include "libcef_dll/cpptoc/v8exception_cpptoc.h"
#include "libcef_dll/cpptoc/v8value_cpptoc.h"
#include "libcef_dll/ctocpp/base_ctocpp.h"
#include "libcef_dll/ctocpp/v8accessor_ctocpp.h"
@ -445,7 +446,7 @@ cef_v8handler_t* CEF_CALLBACK v8value_get_function_handler(
int CEF_CALLBACK v8value_execute_function(struct _cef_v8value_t* self,
struct _cef_v8value_t* object, size_t argumentCount,
struct _cef_v8value_t* const* arguments, struct _cef_v8value_t** retval,
cef_string_t* exception)
cef_v8exception_t** exception, int rethrow_exception)
{
DCHECK(self);
if(!self)
@ -454,17 +455,21 @@ int CEF_CALLBACK v8value_execute_function(struct _cef_v8value_t* self,
CefRefPtr<CefV8Value> objectPtr;
if(object)
objectPtr = CefV8ValueCppToC::Unwrap(object);
CefV8ValueList argsList;
for(size_t i = 0; i < argumentCount; i++) {
argsList.push_back(CefV8ValueCppToC::Unwrap(arguments[i]));
}
CefRefPtr<CefV8Value> retvalPtr;
CefString exceptionStr(exception);
CefV8ValueList argsList;
for(size_t i = 0; i < argumentCount; i++)
argsList.push_back(CefV8ValueCppToC::Unwrap(arguments[i]));
CefRefPtr<CefV8Value> retvalPtr;
CefRefPtr<CefV8Exception> exceptionPtr;
bool rv = CefV8ValueCppToC::Get(self)->ExecuteFunction(objectPtr,
argsList, retvalPtr, exceptionStr);
if(retvalPtr.get() && retval)
argsList, retvalPtr, exceptionPtr, rethrow_exception?true:false);
if( retvalPtr.get() && retval)
*retval = CefV8ValueCppToC::Wrap(retvalPtr);
if (exceptionPtr.get() && exception)
*exception = CefV8ExceptionCppToC::Wrap(exceptionPtr);
return rv;
}
@ -473,7 +478,7 @@ int CEF_CALLBACK v8value_execute_function_with_context(
struct _cef_v8value_t* self, cef_v8context_t* context,
struct _cef_v8value_t* object, size_t argumentCount,
struct _cef_v8value_t* const* arguments, struct _cef_v8value_t** retval,
cef_string_t* exception)
cef_v8exception_t** exception, int rethrow_exception)
{
DCHECK(self);
if(!self)
@ -482,20 +487,26 @@ int CEF_CALLBACK v8value_execute_function_with_context(
CefRefPtr<CefV8Context> contextPtr;
if(context)
contextPtr = CefV8ContextCppToC::Unwrap(context);
CefRefPtr<CefV8Value> objectPtr;
if(object)
objectPtr = CefV8ValueCppToC::Unwrap(object);
CefV8ValueList argsList;
for(size_t i = 0; i < argumentCount; i++) {
for(size_t i = 0; i < argumentCount; i++)
argsList.push_back(CefV8ValueCppToC::Unwrap(arguments[i]));
}
CefRefPtr<CefV8Value> retvalPtr;
CefString exceptionStr(exception);
CefRefPtr<CefV8Value> retvalPtr;
CefRefPtr<CefV8Exception> exceptionPtr;
bool rv = CefV8ValueCppToC::Get(self)->ExecuteFunctionWithContext(
contextPtr, objectPtr, argsList, retvalPtr, exceptionStr);
if(retvalPtr.get() && retval)
contextPtr, objectPtr, argsList, retvalPtr, exceptionPtr,
rethrow_exception?true:false);
if (retvalPtr.get() && retval)
*retval = CefV8ValueCppToC::Wrap(retvalPtr);
if (exceptionPtr.get() && exception)
*exception = CefV8ExceptionCppToC::Wrap(exceptionPtr);
return rv;
}

View File

@ -0,0 +1,96 @@
// Copyright (c) 2011 The Chromium Embedded Framework Authors. All rights
// reserved. Use of this source code is governed by a BSD-style license that
// can be found in the LICENSE file.
//
// ---------------------------------------------------------------------------
//
// A portion of this file was generated by the CEF translator tool. When
// making changes by hand only do so within the body of existing static and
// virtual method implementations. See the translator.README.txt file in the
// tools directory for more information.
//
#include "libcef_dll/ctocpp/v8exception_ctocpp.h"
// VIRTUAL METHODS - Body may be edited by hand.
CefString CefV8ExceptionCToCpp::GetMessage()
{
CefString str;
if (CEF_MEMBER_MISSING(struct_, get_message))
return str;
cef_string_userfree_t strPtr = struct_->get_message(struct_);
str.AttachToUserFree(strPtr);
return str;
}
CefString CefV8ExceptionCToCpp::GetSourceLine()
{
CefString str;
if (CEF_MEMBER_MISSING(struct_, get_source_line))
return str;
cef_string_userfree_t strPtr = struct_->get_source_line(struct_);
str.AttachToUserFree(strPtr);
return str;
}
CefString CefV8ExceptionCToCpp::GetScriptResourceName()
{
CefString str;
if (CEF_MEMBER_MISSING(struct_, get_script_resource_name))
return str;
cef_string_userfree_t strPtr = struct_->get_script_resource_name(struct_);
str.AttachToUserFree(strPtr);
return str;
}
int CefV8ExceptionCToCpp::GetLineNumber()
{
if (CEF_MEMBER_MISSING(struct_, get_line_number))
return 0;
return struct_->get_line_number(struct_);
}
int CefV8ExceptionCToCpp::GetStartPosition()
{
if (CEF_MEMBER_MISSING(struct_, get_start_position))
return 0;
return struct_->get_start_position(struct_);
}
int CefV8ExceptionCToCpp::GetEndPosition()
{
if (CEF_MEMBER_MISSING(struct_, get_end_position))
return 0;
return struct_->get_end_position(struct_);
}
int CefV8ExceptionCToCpp::GetStartColumn()
{
if (CEF_MEMBER_MISSING(struct_, get_start_column))
return 0;
return struct_->get_start_column(struct_);
}
int CefV8ExceptionCToCpp::GetEndColumn()
{
if (CEF_MEMBER_MISSING(struct_, get_end_column))
return 0;
return struct_->get_end_column(struct_);
}
#ifndef NDEBUG
template<> long CefCToCpp<CefV8ExceptionCToCpp, CefV8Exception,
cef_v8exception_t>::DebugObjCt = 0;
#endif

View File

@ -0,0 +1,47 @@
// Copyright (c) 2011 The Chromium Embedded Framework Authors. All rights
// reserved. Use of this source code is governed by a BSD-style license that
// can be found in the LICENSE file.
//
// -------------------------------------------------------------------------
//
// This file was generated by the CEF translator tool and should not edited
// by hand. See the translator.README.txt file in the tools directory for
// more information.
//
#ifndef _V8EXCEPTION_CTOCPP_H
#define _V8EXCEPTION_CTOCPP_H
#ifndef USING_CEF_SHARED
#pragma message("Warning: "__FILE__" may be accessed wrapper-side only")
#else // USING_CEF_SHARED
#include "include/cef.h"
#include "include/cef_capi.h"
#include "libcef_dll/ctocpp/ctocpp.h"
// Wrap a C structure with a C++ class.
// This class may be instantiated and accessed wrapper-side only.
class CefV8ExceptionCToCpp
: public CefCToCpp<CefV8ExceptionCToCpp, CefV8Exception, cef_v8exception_t>
{
public:
CefV8ExceptionCToCpp(cef_v8exception_t* str)
: CefCToCpp<CefV8ExceptionCToCpp, CefV8Exception, cef_v8exception_t>(
str) {}
virtual ~CefV8ExceptionCToCpp() {}
// CefV8Exception methods
virtual CefString GetMessage() OVERRIDE;
virtual CefString GetSourceLine() OVERRIDE;
virtual CefString GetScriptResourceName() OVERRIDE;
virtual int GetLineNumber() OVERRIDE;
virtual int GetStartPosition() OVERRIDE;
virtual int GetEndPosition() OVERRIDE;
virtual int GetStartColumn() OVERRIDE;
virtual int GetEndColumn() OVERRIDE;
};
#endif // USING_CEF_SHARED
#endif // _V8EXCEPTION_CTOCPP_H

View File

@ -14,6 +14,7 @@
#include "libcef_dll/cpptoc/v8accessor_cpptoc.h"
#include "libcef_dll/cpptoc/v8handler_cpptoc.h"
#include "libcef_dll/ctocpp/v8context_ctocpp.h"
#include "libcef_dll/ctocpp/v8exception_ctocpp.h"
#include "libcef_dll/ctocpp/v8value_ctocpp.h"
#include "libcef_dll/transfer_util.h"
@ -403,7 +404,7 @@ CefRefPtr<CefV8Handler> CefV8ValueCToCpp::GetFunctionHandler()
bool CefV8ValueCToCpp::ExecuteFunction(CefRefPtr<CefV8Value> object,
const CefV8ValueList& arguments, CefRefPtr<CefV8Value>& retval,
CefString& exception)
CefRefPtr<CefV8Exception>& exception, bool rethrow_exception)
{
if(CEF_MEMBER_MISSING(struct_, execute_function))
return false;
@ -417,12 +418,17 @@ bool CefV8ValueCToCpp::ExecuteFunction(CefRefPtr<CefV8Value> object,
}
cef_v8value_t* retvalStruct = NULL;
cef_v8exception_t* exeptionStruct = NULL;
int rv = struct_->execute_function(struct_,
object.get() ? CefV8ValueCToCpp::Unwrap(object): NULL,
argsSize, argsStructPtr, &retvalStruct, exception.GetWritableStruct());
if(retvalStruct)
argsSize, argsStructPtr, &retvalStruct, &exeptionStruct,
rethrow_exception);
if (retvalStruct)
retval = CefV8ValueCToCpp::Wrap(retvalStruct);
if (exeptionStruct)
exception = CefV8ExceptionCToCpp::Wrap(exeptionStruct);
if(argsStructPtr)
delete [] argsStructPtr;
@ -433,7 +439,7 @@ bool CefV8ValueCToCpp::ExecuteFunction(CefRefPtr<CefV8Value> object,
bool CefV8ValueCToCpp::ExecuteFunctionWithContext(
CefRefPtr<CefV8Context> context, CefRefPtr<CefV8Value> object,
const CefV8ValueList& arguments, CefRefPtr<CefV8Value>& retval,
CefString& exception)
CefRefPtr<CefV8Exception>& exception, bool rethrow_exception)
{
if(CEF_MEMBER_MISSING(struct_, execute_function_with_context))
return false;
@ -447,14 +453,18 @@ bool CefV8ValueCToCpp::ExecuteFunctionWithContext(
}
cef_v8value_t* retvalStruct = NULL;
cef_v8exception_t* exeptionStruct = NULL;
int rv = struct_->execute_function_with_context(struct_,
context.get() ? CefV8ContextCToCpp::Unwrap(context): NULL,
object.get() ? CefV8ValueCToCpp::Unwrap(object): NULL,
argsSize, argsStructPtr, &retvalStruct, exception.GetWritableStruct());
argsSize, argsStructPtr, &retvalStruct, &exeptionStruct,
rethrow_exception);
if(retvalStruct)
retval = CefV8ValueCToCpp::Wrap(retvalStruct);
if (exeptionStruct)
exception = CefV8ExceptionCToCpp::Wrap(exeptionStruct);
if(argsStructPtr)
delete [] argsStructPtr;

View File

@ -65,10 +65,11 @@ public:
virtual CefRefPtr<CefV8Handler> GetFunctionHandler() OVERRIDE;
virtual bool ExecuteFunction(CefRefPtr<CefV8Value> object,
const CefV8ValueList& arguments, CefRefPtr<CefV8Value>& retval,
CefString& exception) OVERRIDE;
CefRefPtr<CefV8Exception>& exception, bool rethrow_exception) OVERRIDE;
virtual bool ExecuteFunctionWithContext(CefRefPtr<CefV8Context> context,
CefRefPtr<CefV8Value> object, const CefV8ValueList& arguments,
CefRefPtr<CefV8Value>& retval, CefString& exception) OVERRIDE;
CefRefPtr<CefV8Value>& retval, CefRefPtr<CefV8Exception>& exception,
bool rethrow_exception) OVERRIDE;
};
#endif // USING_CEF_SHARED

View File

@ -20,7 +20,7 @@ public:
CefRefPtr<CefV8Value> object,
const CefV8ValueList& arguments,
CefRefPtr<CefV8Value>& retval,
CefString& exception)
CefString& exception) OVERRIDE
{
if(name == "Dump")
{
@ -51,12 +51,19 @@ public:
return false;
CefV8ValueList argList;
bool result;
// Execute the function stored in the first argument to retrieve an
// object.
CefRefPtr<CefV8Value> objectPtr;
if(!arguments[0]->ExecuteFunction(object, argList, objectPtr, exception))
CefRefPtr<CefV8Exception> exceptionPtr;
result = arguments[0]->ExecuteFunction(object, argList, objectPtr,
exceptionPtr, false);
if (exceptionPtr.get())
exception = exceptionPtr->GetMessage();
if (!result)
return false;
// Verify that the returned value is an object.
if(!objectPtr.get() || !objectPtr->IsObject())
return false;
@ -74,7 +81,11 @@ public:
argList.push_back(arguments[i]);
// Execute the member function.
return funcPtr->ExecuteFunction(arguments[0], argList, retval, exception);
result = funcPtr->ExecuteFunction(arguments[0], argList, retval,
exceptionPtr, false);
if (exceptionPtr.get())
exception = exceptionPtr->GetMessage();
return result;
}
return false;
}

View File

@ -36,9 +36,9 @@ void UIT_InvokeScript(CefRefPtr<CefBrowser> browser)
args.push_back(arg0);
CefRefPtr<CefV8Value> retVal;
CefString exception;
CefRefPtr<CefV8Exception> exception;
if (evalFunc->ExecuteFunctionWithContext(v8Context, globalObj, args, retVal,
exception)) {
exception, false)) {
if (retVal.get()) {
frame->ExecuteJavaScript(
std::string("alert('InvokeScript returns ") +
@ -47,7 +47,7 @@ void UIT_InvokeScript(CefRefPtr<CefBrowser> browser)
} else {
frame->ExecuteJavaScript(
std::string("alert('InvokeScript returns exception: ") +
exception.ToString() + "!');",
exception->GetMessage().ToString() + "!');",
url, 0);
}
} else {

View File

@ -135,9 +135,9 @@ public:
args.push_back(CefV8Value::CreateBool(true));
args.push_back(CefV8Value::CreateString("10"));
CefRefPtr<CefV8Value> rv;
CefString exception;
CefRefPtr<CefV8Exception> exception;
ASSERT_TRUE(arguments[argct]->ExecuteFunction(
arguments[argct], args, rv, exception));
arguments[argct], args, rv, exception, false));
ASSERT_TRUE(rv.get() != NULL);
ASSERT_TRUE(rv->IsDouble());
ASSERT_EQ(19.5, rv->GetDoubleValue());
@ -151,10 +151,11 @@ public:
args.push_back(CefV8Value::CreateDouble(5));
args.push_back(CefV8Value::CreateDouble(0));
CefRefPtr<CefV8Value> rv;
CefString exception;
CefRefPtr<CefV8Exception> exception;
ASSERT_TRUE(arguments[argct]->ExecuteFunction(
arguments[argct], args, rv, exception));
ASSERT_EQ(exception, "Uncaught My Exception");
arguments[argct], args, rv, exception, false));
ASSERT_TRUE(exception.get());
ASSERT_EQ(exception->GetMessage(), "Uncaught My Exception");
}
argct++;
@ -651,10 +652,11 @@ public:
{
CefV8ValueList args;
CefRefPtr<CefV8Value> rv;
CefString exception;
CefRefPtr<CefV8Exception> exception;
CefRefPtr<CefV8Value> empty;
ASSERT_TRUE(funcIFrame_->ExecuteFunctionWithContext(contextIFrame_, empty,
args, rv, exception));
args, rv, exception,
false));
}
void AsyncTestContext(CefRefPtr<CefV8Context> ec,
@ -692,18 +694,18 @@ public:
{
CefV8ValueList args;
CefRefPtr<CefV8Value> rv;
CefString exception;
CefRefPtr<CefV8Exception> exception;
CefRefPtr<CefV8Value> empty;
ASSERT_TRUE(func->ExecuteFunctionWithContext(context, empty, args, rv,
exception));
if(exception == "Uncaught My Exception")
exception, false));
if(exception.get() && exception->GetMessage() == "Uncaught My Exception")
got_exception_.yes();
}
void AsyncTestNavigation(CefRefPtr<CefV8Context> context,
CefRefPtr<CefV8Value> func)
{
CefString exception;
CefRefPtr<CefV8Exception> exception;
CefV8ValueList args;
CefRefPtr<CefV8Value> rv, obj, url;
@ -728,8 +730,8 @@ public:
args.push_back(obj);
ASSERT_TRUE(func->ExecuteFunctionWithContext(context, global, args, rv,
exception));
if(exception.empty())
exception, false));
if(!exception.get())
got_navigation_.yes();
context->Exit();
@ -1180,7 +1182,7 @@ public:
CefRefPtr<TestInternalHandler> test_;
IMPLEMENT_REFCOUNTING(Handler);
IMPLEMENT_REFCOUNTING(TestHandler);
};
TestInternalHandler()
@ -1404,3 +1406,216 @@ TEST(V8Test, Internal)
EXPECT_TRUE(handler->got_execute2_.isSet());
EXPECT_FALSE(handler->got_execute2_fail_.isSet());
}
namespace {
static const int kNumExceptionTests = 3;
class TestExceptionHandler : public TestHandler
{
public:
class TestHandler : public CefV8Handler
{
public:
TestHandler(CefRefPtr<TestExceptionHandler> test)
: test_(test)
{
}
virtual bool Execute(const CefString& name,
CefRefPtr<CefV8Value> object,
const CefV8ValueList& arguments,
CefRefPtr<CefV8Value>& retval,
CefString& exception) OVERRIDE
{
if (name == "register") {
if (arguments.size() == 1 && arguments[0]->IsFunction()) {
test_->got_register_.yes();
// Keep pointers to the callback function and context.
test_->test_func_ = arguments[0];
test_->test_context_ = CefV8Context::GetCurrentContext();
return true;
}
} else if (name == "execute") {
if (arguments.size() == 2 && arguments[0]->IsInt() &&
arguments[1]->IsBool()) {
// Execute the test callback function.
test_->ExecuteTestCallback(arguments[0]->GetIntValue(),
arguments[1]->GetBoolValue());
return true;
}
} else if (name == "result") {
if (arguments.size() == 1 && arguments[0]->IsString()) {
std::string value = arguments[0]->GetStringValue();
if (value == "no_exception")
test_->got_no_exception_result_.yes();
else if (value == "exception")
test_->got_exception_result_.yes();
else if (value == "done")
test_->got_done_result_.yes();
else
return false;
return true;
}
}
return false;
}
CefRefPtr<TestExceptionHandler> test_;
IMPLEMENT_REFCOUNTING(TestHandler);
};
TestExceptionHandler()
{
}
virtual void RunTest() OVERRIDE
{
std::string testHtml =
"<html><body>\n"
"<script language=\"JavaScript\">\n"
// JS callback function that throws an exception.
"function testFunc() {\n"
" throw 'Some test exception';\n"
"}\n"
// Register the callback function.
"window.test.register(testFunc);\n"
// Test 1: Execute the callback without re-throwing the exception.
"window.test.execute(1, false);\n"
// Test 2: Execute the callback, re-throw and catch the exception.
"try {\n"
" window.test.execute(2, true);\n"
// This line should never execute.
" window.test.result('no_exception');\n"
"} catch(e) {\n"
" window.test.result('exception');\n"
"}\n"
// Verify that JS execution continues.
"window.test.result('done');\n"
"</script>\n"
"</body></html>";
AddResource("http://tests/run.html", testHtml, "text/html");
CreateBrowser("http://tests/run.html");
}
// Execute the callback function.
void ExecuteTestCallback(int test, bool rethrow_exception)
{
if(test <= 0 || test > kNumExceptionTests)
return;
got_execute_test_[test-1].yes();
if (!test_func_.get())
return;
CefV8ValueList args;
CefRefPtr<CefV8Value> retval;
CefRefPtr<CefV8Exception> exception;
if (test_func_->ExecuteFunctionWithContext(test_context_, NULL, args,
retval, exception, rethrow_exception)) {
got_execute_function_[test-1].yes();
if (exception.get()) {
got_exception_[test-1].yes();
std::string message = exception->GetMessage();
EXPECT_EQ("Uncaught Some test exception", message) << "test = " << test;
std::string source_line = exception->GetSourceLine();
EXPECT_EQ(" throw 'Some test exception';", source_line) << "test = " <<
test;
std::string script = exception->GetScriptResourceName();
EXPECT_EQ("http://tests/run.html", script) << "test = " << test;
int line_number = exception->GetLineNumber();
EXPECT_EQ(4, line_number) << "test = " << test;
int start_pos = exception->GetStartPosition();
EXPECT_EQ(25, start_pos) << "test = " << test;
int end_pos = exception->GetEndPosition();
EXPECT_EQ(26, end_pos) << "test = " << test;
int start_col = exception->GetStartColumn();
EXPECT_EQ(2, start_col) << "test = " << test;
int end_col = exception->GetEndColumn();
EXPECT_EQ(3, end_col) << "test = " << test;
}
}
if (test == kNumExceptionTests)
DestroyTest();
}
virtual void OnLoadEnd(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
int httpStatusCode) OVERRIDE
{
got_load_end_.yes();
// Test 3: Execute the callback asynchronously without re-throwing the
// exception.
CefPostTask(TID_UI,
NewCefRunnableMethod(this, &TestExceptionHandler::ExecuteTestCallback,
3, false));
}
virtual void OnJSBinding(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
CefRefPtr<CefV8Value> object) OVERRIDE
{
// Create the functions that will be used during the test.
CefRefPtr<CefV8Value> obj = CefV8Value::CreateObject(NULL, NULL);
CefRefPtr<CefV8Handler> handler = new TestHandler(this);
obj->SetValue("register",
CefV8Value::CreateFunction("register", handler),
V8_PROPERTY_ATTRIBUTE_NONE);
obj->SetValue("execute",
CefV8Value::CreateFunction("execute", handler),
V8_PROPERTY_ATTRIBUTE_NONE);
obj->SetValue("result",
CefV8Value::CreateFunction("result", handler),
V8_PROPERTY_ATTRIBUTE_NONE);
object->SetValue("test", obj, V8_PROPERTY_ATTRIBUTE_NONE);
}
CefRefPtr<CefV8Value> test_func_;
CefRefPtr<CefV8Context> test_context_;
TrackCallback got_register_;
TrackCallback got_load_end_;
TrackCallback got_execute_test_[kNumExceptionTests];
TrackCallback got_execute_function_[kNumExceptionTests];
TrackCallback got_exception_[kNumExceptionTests];
TrackCallback got_exception_result_;
TrackCallback got_no_exception_result_;
TrackCallback got_done_result_;
};
} // namespace
// Test V8 exception results.
TEST(V8Test, Exception)
{
CefRefPtr<TestExceptionHandler> handler = new TestExceptionHandler();
handler->ExecuteTest();
EXPECT_TRUE(handler->got_register_);
EXPECT_TRUE(handler->got_load_end_);
EXPECT_TRUE(handler->got_exception_result_);
EXPECT_FALSE(handler->got_no_exception_result_);
EXPECT_TRUE(handler->got_done_result_);
for (int i = 0; i < kNumExceptionTests; ++i) {
EXPECT_TRUE(handler->got_execute_test_[i]) << "test = " << i+1;
EXPECT_TRUE(handler->got_execute_function_[i]) << "test = " << i+1;
EXPECT_TRUE(handler->got_exception_[i]) << "test = " << i+1;
}
}