From 46b9f02fb504ec7ad1b8efe4292b97792cd08bdf Mon Sep 17 00:00:00 2001
From: Marshall Greenblatt <magreenblatt@gmail.com>
Date: Wed, 25 Jul 2012 09:45:49 +0000
Subject: [PATCH] Add new CefV8StackTrace and CefV8StackFrame interfaces to
 support retrieval of the JavaScript stack trace for the currently active V8
 context (issue #682).

git-svn-id: https://chromiumembedded.googlecode.com/svn/trunk@725 5089003a-bbd8-11dd-ad1f-f1f9622dbc98
---
 cef1/cef_paths.gypi                           |   8 +
 cef1/include/capi/cef_v8_capi.h               |  86 ++++++++++
 cef1/include/cef_v8.h                         |  81 ++++++++++
 cef1/libcef/v8_impl.cc                        | 151 +++++++++++++++---
 cef1/libcef/v8_impl.h                         | 145 ++++++++++-------
 .../libcef_dll/cpptoc/v8stack_frame_cpptoc.cc | 142 ++++++++++++++++
 cef1/libcef_dll/cpptoc/v8stack_frame_cpptoc.h |  37 +++++
 .../libcef_dll/cpptoc/v8stack_trace_cpptoc.cc |  79 +++++++++
 cef1/libcef_dll/cpptoc/v8stack_trace_cpptoc.h |  37 +++++
 .../libcef_dll/ctocpp/v8stack_frame_ctocpp.cc | 121 ++++++++++++++
 cef1/libcef_dll/ctocpp/v8stack_frame_ctocpp.h |  48 ++++++
 .../libcef_dll/ctocpp/v8stack_trace_ctocpp.cc |  65 ++++++++
 cef1/libcef_dll/ctocpp/v8stack_trace_ctocpp.h |  43 +++++
 cef1/libcef_dll/libcef_dll.cc                 |   4 +
 cef1/libcef_dll/wrapper/libcef_dll_wrapper.cc |   4 +
 cef1/tests/unittests/v8_unittest.cc           |  89 +++++++++++
 16 files changed, 1062 insertions(+), 78 deletions(-)
 create mode 100644 cef1/libcef_dll/cpptoc/v8stack_frame_cpptoc.cc
 create mode 100644 cef1/libcef_dll/cpptoc/v8stack_frame_cpptoc.h
 create mode 100644 cef1/libcef_dll/cpptoc/v8stack_trace_cpptoc.cc
 create mode 100644 cef1/libcef_dll/cpptoc/v8stack_trace_cpptoc.h
 create mode 100644 cef1/libcef_dll/ctocpp/v8stack_frame_ctocpp.cc
 create mode 100644 cef1/libcef_dll/ctocpp/v8stack_frame_ctocpp.h
 create mode 100644 cef1/libcef_dll/ctocpp/v8stack_trace_ctocpp.cc
 create mode 100644 cef1/libcef_dll/ctocpp/v8stack_trace_ctocpp.h

diff --git a/cef1/cef_paths.gypi b/cef1/cef_paths.gypi
index e719e56dd..7cc04e958 100644
--- a/cef1/cef_paths.gypi
+++ b/cef1/cef_paths.gypi
@@ -184,6 +184,10 @@
       'libcef_dll/cpptoc/v8exception_cpptoc.h',
       'libcef_dll/ctocpp/v8handler_ctocpp.cc',
       'libcef_dll/ctocpp/v8handler_ctocpp.h',
+      'libcef_dll/cpptoc/v8stack_frame_cpptoc.cc',
+      'libcef_dll/cpptoc/v8stack_frame_cpptoc.h',
+      'libcef_dll/cpptoc/v8stack_trace_cpptoc.cc',
+      'libcef_dll/cpptoc/v8stack_trace_cpptoc.h',
       'libcef_dll/cpptoc/v8value_cpptoc.cc',
       'libcef_dll/cpptoc/v8value_cpptoc.h',
       'libcef_dll/cpptoc/web_plugin_info_cpptoc.cc',
@@ -292,6 +296,10 @@
       'libcef_dll/ctocpp/v8exception_ctocpp.h',
       'libcef_dll/cpptoc/v8handler_cpptoc.cc',
       'libcef_dll/cpptoc/v8handler_cpptoc.h',
+      'libcef_dll/ctocpp/v8stack_frame_ctocpp.cc',
+      'libcef_dll/ctocpp/v8stack_frame_ctocpp.h',
+      'libcef_dll/ctocpp/v8stack_trace_ctocpp.cc',
+      'libcef_dll/ctocpp/v8stack_trace_ctocpp.h',
       'libcef_dll/ctocpp/v8value_ctocpp.cc',
       'libcef_dll/ctocpp/v8value_ctocpp.h',
       'libcef_dll/ctocpp/web_plugin_info_ctocpp.cc',
diff --git a/cef1/include/capi/cef_v8_capi.h b/cef1/include/capi/cef_v8_capi.h
index c0facab62..8c4c23db3 100644
--- a/cef1/include/capi/cef_v8_capi.h
+++ b/cef1/include/capi/cef_v8_capi.h
@@ -698,6 +698,92 @@ CEF_EXPORT cef_v8value_t* cef_v8value_create_function(const cef_string_t* name,
     cef_v8handler_t* handler);
 
 
+///
+// Structure representing a V8 stack trace. The functions of this structure may
+// only be called on the UI thread.
+///
+typedef struct _cef_v8stack_trace_t {
+  ///
+  // Base structure.
+  ///
+  cef_base_t base;
+
+  ///
+  // Returns the number of stack frames.
+  ///
+  int (CEF_CALLBACK *get_frame_count)(struct _cef_v8stack_trace_t* self);
+
+  ///
+  // Returns the stack frame at the specified 0-based index.
+  ///
+  struct _cef_v8stack_frame_t* (CEF_CALLBACK *get_frame)(
+      struct _cef_v8stack_trace_t* self, int index);
+} cef_v8stack_trace_t;
+
+
+///
+// Returns the stack trace for the currently active context. |frame_limit| is
+// the maximum number of frames that will be captured.
+///
+CEF_EXPORT cef_v8stack_trace_t* cef_v8stack_trace_get_current(int frame_limit);
+
+
+///
+// Structure representing a V8 stack frame. The functions of this structure may
+// only be called on the UI thread.
+///
+typedef struct _cef_v8stack_frame_t {
+  ///
+  // Base structure.
+  ///
+  cef_base_t base;
+
+  ///
+  // Returns the name of the resource script that contains the function.
+  ///
+  // The resulting string must be freed by calling cef_string_userfree_free().
+  cef_string_userfree_t (CEF_CALLBACK *get_script_name)(
+      struct _cef_v8stack_frame_t* self);
+
+  ///
+  // Returns the name of the resource script that contains the function or the
+  // sourceURL value if the script name is undefined and its source ends with a
+  // "//@ sourceURL=..." string.
+  ///
+  // The resulting string must be freed by calling cef_string_userfree_free().
+  cef_string_userfree_t (CEF_CALLBACK *get_script_name_or_source_url)(
+      struct _cef_v8stack_frame_t* self);
+
+  ///
+  // Returns the name of the function.
+  ///
+  // The resulting string must be freed by calling cef_string_userfree_free().
+  cef_string_userfree_t (CEF_CALLBACK *get_function_name)(
+      struct _cef_v8stack_frame_t* self);
+
+  ///
+  // Returns the 1-based line number for the function call or 0 if unknown.
+  ///
+  int (CEF_CALLBACK *get_line_number)(struct _cef_v8stack_frame_t* self);
+
+  ///
+  // Returns the 1-based column offset on the line for the function call or 0 if
+  // unknown.
+  ///
+  int (CEF_CALLBACK *get_column)(struct _cef_v8stack_frame_t* self);
+
+  ///
+  // Returns true (1) if the function was compiled using eval().
+  ///
+  int (CEF_CALLBACK *is_eval)(struct _cef_v8stack_frame_t* self);
+
+  ///
+  // Returns true (1) if the function was called as a constructor via "new".
+  ///
+  int (CEF_CALLBACK *is_constructor)(struct _cef_v8stack_frame_t* self);
+} cef_v8stack_frame_t;
+
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/cef1/include/cef_v8.h b/cef1/include/cef_v8.h
index 9f6e198ec..70dd729f6 100644
--- a/cef1/include/cef_v8.h
+++ b/cef1/include/cef_v8.h
@@ -46,6 +46,7 @@
 
 class CefV8Exception;
 class CefV8Handler;
+class CefV8StackFrame;
 class CefV8Value;
 
 
@@ -739,4 +740,84 @@ class CefV8Value : public virtual CefBase {
       const CefV8ValueList& arguments) =0;
 };
 
+///
+// Class representing a V8 stack trace. The methods of this class may only be
+// called on the UI thread.
+///
+/*--cef(source=library)--*/
+class CefV8StackTrace : public virtual CefBase {
+ public:
+  ///
+  // Returns the stack trace for the currently active context. |frame_limit| is
+  // the maximum number of frames that will be captured.
+  ///
+  /*--cef()--*/
+  static CefRefPtr<CefV8StackTrace> GetCurrent(int frame_limit);
+
+  ///
+  // Returns the number of stack frames.
+  ///
+  /*--cef()--*/
+  virtual int GetFrameCount() =0;
+
+  ///
+  // Returns the stack frame at the specified 0-based index.
+  ///
+  /*--cef()--*/
+  virtual CefRefPtr<CefV8StackFrame> GetFrame(int index) =0;
+};
+
+///
+// Class representing a V8 stack frame. The methods of this class may only be
+// called on the UI thread.
+///
+/*--cef(source=library)--*/
+class CefV8StackFrame : public virtual CefBase {
+ public:
+  ///
+  // Returns the name of the resource script that contains the function.
+  ///
+  /*--cef()--*/
+  virtual CefString GetScriptName() =0;
+
+  ///
+  // Returns the name of the resource script that contains the function or the
+  // sourceURL value if the script name is undefined and its source ends with
+  // a "//@ sourceURL=..." string.
+  ///
+  /*--cef()--*/
+  virtual CefString GetScriptNameOrSourceURL() =0;
+
+  ///
+  // Returns the name of the function.
+  ///
+  /*--cef()--*/
+  virtual CefString GetFunctionName() =0;
+
+  ///
+  // Returns the 1-based line number for the function call or 0 if unknown.
+  ///
+  /*--cef()--*/
+  virtual int GetLineNumber() =0;
+
+  ///
+  // Returns the 1-based column offset on the line for the function call or 0 if
+  // unknown.
+  ///
+  /*--cef()--*/
+  virtual int GetColumn() =0;
+
+  ///
+  // Returns true if the function was compiled using eval().
+  ///
+  /*--cef()--*/
+  virtual bool IsEval() =0;
+
+  ///
+  // Returns true if the function was called as a constructor via "new".
+  ///
+  /*--cef()--*/
+  virtual bool IsConstructor() =0;
+};
+
 #endif  // CEF_INCLUDE_CEF_V8_H_
diff --git a/cef1/libcef/v8_impl.cc b/cef1/libcef/v8_impl.cc
index e2cdf6d26..064c53407 100644
--- a/cef1/libcef/v8_impl.cc
+++ b/cef1/libcef/v8_impl.cc
@@ -184,16 +184,19 @@ v8::Handle<v8::String> GetV8String(const CefString& str) {
 
 #if defined(CEF_STRING_TYPE_UTF16)
 void v8impl_string_dtor(char16* str) {
-    delete [] str;
+  delete [] str;
 }
 #elif defined(CEF_STRING_TYPE_UTF8)
 void v8impl_string_dtor(char* str) {
-    delete [] str;
+  delete [] str;
 }
 #endif
 
 // Convert a v8::String to CefString.
 void GetCefString(v8::Handle<v8::String> str, CefString& out) {
+  if (str.IsEmpty())
+    return;
+
 #if defined(CEF_STRING_TYPE_WIDE)
   // Allocate enough space for a worst-case conversion.
   int len = str->Utf8Length();
@@ -431,7 +434,7 @@ bool CefRegisterExtension(const CefString& extension_name,
 }
 
 
-// CefV8Context implementation.
+// CefV8Context
 
 // static
 CefRefPtr<CefV8Context> CefV8Context::GetCurrentContext() {
@@ -465,7 +468,7 @@ bool CefV8Context::InContext() {
 }
 
 
-// CefV8ContextImpl implementation.
+// CefV8ContextImpl
 
 #define CEF_V8_REQUIRE_OBJECT_RETURN(ret) \
   if (!GetHandle()->IsObject()) { \
@@ -486,11 +489,11 @@ bool CefV8Context::InContext() {
   }
 
 CefV8ContextImpl::CefV8ContextImpl(v8::Handle<v8::Context> context)
+  : handle_(new Handle(context))
 #ifndef NDEBUG
-  : enter_count_(0)
+    , enter_count_(0)
 #endif
 {  // NOLINT(whitespace/braces)
-  v8_context_ = new CefV8ContextHandle(context);
 }
 
 CefV8ContextImpl::~CefV8ContextImpl() {
@@ -527,13 +530,13 @@ CefRefPtr<CefV8Value> CefV8ContextImpl::GetGlobal() {
   CEF_REQUIRE_UI_THREAD(NULL);
 
   v8::HandleScope handle_scope;
-  v8::Context::Scope context_scope(v8_context_->GetHandle());
-  return new CefV8ValueImpl(v8_context_->GetHandle()->Global());
+  v8::Context::Scope context_scope(GetHandle());
+  return new CefV8ValueImpl(GetHandle()->Global());
 }
 
 bool CefV8ContextImpl::Enter() {
   CEF_REQUIRE_UI_THREAD(false);
-  v8_context_->GetHandle()->Enter();
+  GetHandle()->Enter();
 #ifndef NDEBUG
   ++enter_count_;
 #endif
@@ -543,7 +546,7 @@ bool CefV8ContextImpl::Enter() {
 bool CefV8ContextImpl::Exit() {
   CEF_REQUIRE_UI_THREAD(false);
   DLOG_ASSERT(enter_count_ > 0);
-  v8_context_->GetHandle()->Exit();
+  GetHandle()->Exit();
 #ifndef NDEBUG
   --enter_count_;
 #endif
@@ -576,8 +579,8 @@ bool CefV8ContextImpl::Eval(const CefString& code,
   }
 
   v8::HandleScope handle_scope;
-  v8::Context::Scope context_scope(v8_context_->GetHandle());
-  v8::Local<v8::Object> obj = v8_context_->GetHandle()->Global();
+  v8::Context::Scope context_scope(GetHandle());
+  v8::Local<v8::Object> obj = GetHandle()->Global();
 
   // Retrieve the eval function.
   v8::Local<v8::Value> val = obj->Get(v8::String::New("eval"));
@@ -611,28 +614,26 @@ bool CefV8ContextImpl::Eval(const CefString& code,
 }
 
 v8::Local<v8::Context> CefV8ContextImpl::GetContext() {
-  return v8::Local<v8::Context>::New(v8_context_->GetHandle());
+  return v8::Local<v8::Context>::New(GetHandle());
 }
 
 WebKit::WebFrame* CefV8ContextImpl::GetWebFrame() {
   v8::HandleScope handle_scope;
-  v8::Context::Scope context_scope(v8_context_->GetHandle());
+  v8::Context::Scope context_scope(GetHandle());
   WebKit::WebFrame* frame = WebKit::WebFrame::frameForCurrentContext();
   return frame;
 }
 
 
-// CefV8ValueHandle
+// CefV8ValueImpl::Handle
 
-// Custom destructor for a v8 value handle which gets called only on the UI
-// thread.
-CefV8ValueHandle::~CefV8ValueHandle() {
+CefV8ValueImpl::Handle::~Handle() {
   if (tracker_) {
     TrackAdd(tracker_);
-    v8_handle_.MakeWeak(tracker_, TrackDestructor);
+    handle_.MakeWeak(tracker_, TrackDestructor);
   } else {
-    v8_handle_.Dispose();
-    v8_handle_.Clear();
+    handle_.Dispose();
+    handle_.Clear();
   }
   tracker_ = NULL;
 }
@@ -814,8 +815,8 @@ CefRefPtr<CefV8Value> CefV8Value::CreateFunction(
 
 CefV8ValueImpl::CefV8ValueImpl(v8::Handle<v8::Value> value,
                                CefTrackNode* tracker)
-    : rethrow_exceptions_(false) {
-  v8_value_ = new CefV8ValueHandle(value, tracker);
+    : handle_(new Handle(value, tracker)),
+      rethrow_exceptions_(false) {
 }
 
 CefV8ValueImpl::~CefV8ValueImpl() {
@@ -968,7 +969,7 @@ CefRefPtr<CefV8Exception> CefV8ValueImpl::GetException() {
 }
 
 bool CefV8ValueImpl::ClearException() {
- CEF_REQUIRE_UI_THREAD(NULL);
+  CEF_REQUIRE_UI_THREAD(NULL);
   CEF_V8_REQUIRE_OBJECT_RETURN(NULL);
 
   last_exception_ = NULL;
@@ -1370,3 +1371,105 @@ bool CefV8ValueImpl::HasCaught(v8::TryCatch& try_catch) {
     return false;
   }
 }
+
+
+// CefV8StackTrace
+
+// static
+CefRefPtr<CefV8StackTrace> CefV8StackTrace::GetCurrent(int frame_limit) {
+  CEF_REQUIRE_VALID_CONTEXT(NULL);
+  CEF_REQUIRE_UI_THREAD(NULL);
+
+  v8::Handle<v8::StackTrace> stackTrace =
+        v8::StackTrace::CurrentStackTrace(
+            frame_limit, v8::StackTrace::kDetailed);
+  if (stackTrace.IsEmpty())
+    return NULL;
+  return new CefV8StackTraceImpl(stackTrace);
+}
+
+
+// CefV8StackTraceImpl
+
+CefV8StackTraceImpl::CefV8StackTraceImpl(v8::Handle<v8::StackTrace> handle)
+    : handle_(new Handle(handle)) {
+}
+
+CefV8StackTraceImpl::~CefV8StackTraceImpl() {
+}
+
+int CefV8StackTraceImpl::GetFrameCount() {
+  CEF_REQUIRE_UI_THREAD(0);
+  v8::HandleScope handle_scope;
+  return GetHandle()->GetFrameCount();
+}
+
+CefRefPtr<CefV8StackFrame> CefV8StackTraceImpl::GetFrame(int index) {
+  CEF_REQUIRE_UI_THREAD(NULL);
+  v8::HandleScope handle_scope;
+  v8::Handle<v8::StackFrame> stackFrame = GetHandle()->GetFrame(index);
+  if (stackFrame.IsEmpty())
+    return NULL;
+  return new CefV8StackFrameImpl(stackFrame);
+}
+
+
+// CefV8StackFrameImpl
+
+CefV8StackFrameImpl::CefV8StackFrameImpl(v8::Handle<v8::StackFrame> handle)
+    : handle_(new Handle(handle)) {
+}
+
+CefV8StackFrameImpl::~CefV8StackFrameImpl() {
+}
+
+CefString CefV8StackFrameImpl::GetScriptName() {
+  CefString rv;
+  CEF_REQUIRE_UI_THREAD(rv);
+  v8::HandleScope handle_scope;
+  GetCefString(v8::Handle<v8::String>::Cast(GetHandle()->GetScriptName()), rv);
+  return rv;
+}
+
+CefString CefV8StackFrameImpl::GetScriptNameOrSourceURL() {
+  CefString rv;
+  CEF_REQUIRE_UI_THREAD(rv);
+  v8::HandleScope handle_scope;
+  GetCefString(
+      v8::Handle<v8::String>::Cast(GetHandle()->GetScriptNameOrSourceURL()),
+      rv);
+  return rv;
+}
+
+CefString CefV8StackFrameImpl::GetFunctionName() {
+  CefString rv;
+  CEF_REQUIRE_UI_THREAD(rv);
+  v8::HandleScope handle_scope;
+  GetCefString(
+      v8::Handle<v8::String>::Cast(GetHandle()->GetFunctionName()), rv);
+  return rv;
+}
+
+int CefV8StackFrameImpl::GetLineNumber() {
+  CEF_REQUIRE_UI_THREAD(0);
+  v8::HandleScope handle_scope;
+  return GetHandle()->GetLineNumber();
+}
+
+int CefV8StackFrameImpl::GetColumn() {
+  CEF_REQUIRE_UI_THREAD(0);
+  v8::HandleScope handle_scope;
+  return GetHandle()->GetColumn();
+}
+
+bool CefV8StackFrameImpl::IsEval() {
+  CEF_REQUIRE_UI_THREAD(false);
+  v8::HandleScope handle_scope;
+  return GetHandle()->IsEval();
+}
+
+bool CefV8StackFrameImpl::IsConstructor() {
+  CEF_REQUIRE_UI_THREAD(false);
+  v8::HandleScope handle_scope;
+  return GetHandle()->IsConstructor();
+}
diff --git a/cef1/libcef/v8_impl.h b/cef1/libcef/v8_impl.h
index ca42909c9..11dfc7d25 100644
--- a/cef1/libcef/v8_impl.h
+++ b/cef1/libcef/v8_impl.h
@@ -21,43 +21,37 @@ class WebFrame;
 
 // Template for V8 Handle types. This class is used to ensure that V8 objects
 // are only released on the UI thread.
-template <class v8class>
-class CefReleaseV8HandleOnUIThread
-    : public base::RefCountedThreadSafe<CefReleaseV8HandleOnUIThread<v8class>,
-                                        CefThread::DeleteOnUIThread> {
+template <typename v8class>
+class CefV8Handle :
+    public base::RefCountedThreadSafe<CefV8Handle<v8class>,
+                                      CefThread::DeleteOnUIThread> {
  public:
   typedef v8::Handle<v8class> handleType;
   typedef v8::Persistent<v8class> persistentType;
-  typedef CefReleaseV8HandleOnUIThread<v8class> superType;
 
-  explicit CefReleaseV8HandleOnUIThread(handleType v) {
-    v8_handle_ = persistentType::New(v);
+  CefV8Handle(handleType v)
+      : handle_(persistentType::New(v)) {
   }
-  virtual ~CefReleaseV8HandleOnUIThread() {
+  ~CefV8Handle() {
+    handle_.Dispose();
+    handle_.Clear();
   }
 
-  handleType GetHandle() {
-    return v8_handle_;
-  }
+  handleType GetHandle() { return handle_; }
 
-  persistentType v8_handle_;
+ protected:
+  persistentType handle_;
+
+  DISALLOW_COPY_AND_ASSIGN(CefV8Handle);
 };
 
-// Special class for a v8::Context to ensure that it is deleted from the UI
-// thread.
-class CefV8ContextHandle : public CefReleaseV8HandleOnUIThread<v8::Context> {
- public:
-  explicit CefV8ContextHandle(handleType context)
-    : superType(context) {
-  }
-
-  // Context handles are disposed rather than makeweak.
-  ~CefV8ContextHandle() {
-    v8_handle_.Dispose();
-    v8_handle_.Clear();
-  }
+// Specialization for v8::Value with empty implementation to avoid incorrect
+// usage.
+template <>
+class CefV8Handle<v8::Value> {
 };
 
+
 class CefV8ContextImpl : public CefV8Context {
  public:
   explicit CefV8ContextImpl(v8::Handle<v8::Context> context);
@@ -76,8 +70,11 @@ class CefV8ContextImpl : public CefV8Context {
   v8::Local<v8::Context> GetContext();
   WebKit::WebFrame* GetWebFrame();
 
+  v8::Handle<v8::Context> GetHandle() { return handle_->GetHandle(); }
+
  protected:
-  scoped_refptr<CefV8ContextHandle> v8_context_;
+  typedef CefV8Handle<v8::Context> Handle;
+  scoped_refptr<Handle> handle_;
 
 #ifndef NDEBUG
   // Used in debug builds to catch missing Exits in destructor.
@@ -85,29 +82,7 @@ class CefV8ContextImpl : public CefV8Context {
 #endif
 
   IMPLEMENT_REFCOUNTING(CefV8ContextImpl);
-};
-
-// Special class for a v8::Value to ensure that it is deleted from the UI
-// thread.
-class CefV8ValueHandle: public CefReleaseV8HandleOnUIThread<v8::Value> {
- public:
-  CefV8ValueHandle(handleType value, CefTrackNode* tracker)
-    : superType(value),
-      tracker_(tracker) {
-  }
-  // Destructor implementation is provided in v8_impl.cc.
-  ~CefV8ValueHandle();
-
-  CefTrackNode* GetTracker() {
-    return tracker_;
-  }
-
- private:
-  // For Object and Function types, we need to hold on to a reference to their
-  // internal data or function handler objects that are reference counted.
-  CefTrackNode* tracker_;
-
-  DISALLOW_COPY_AND_ASSIGN(CefV8ValueHandle);
+  DISALLOW_COPY_AND_ASSIGN(CefV8ContextImpl);
 };
 
 class CefV8ValueImpl : public CefV8Value {
@@ -166,16 +141,37 @@ class CefV8ValueImpl : public CefV8Value {
       CefRefPtr<CefV8Value> object,
       const CefV8ValueList& arguments) OVERRIDE;
 
-  inline v8::Handle<v8::Value> GetHandle() {
-    DCHECK(v8_value_.get());
-    return v8_value_->GetHandle();
-  }
+  v8::Handle<v8::Value> GetHandle() { return handle_->GetHandle(); }
 
  protected:
   // Test for and record any exception.
   bool HasCaught(v8::TryCatch& try_catch);
 
-  scoped_refptr<CefV8ValueHandle> v8_value_;
+  class Handle :
+      public base::RefCountedThreadSafe<Handle, CefThread::DeleteOnUIThread> {
+   public:
+    typedef v8::Handle<v8::Value> handleType;
+    typedef v8::Persistent<v8::Value> persistentType;
+
+    Handle(handleType v, CefTrackNode* tracker)
+        : handle_(persistentType::New(v)),
+          tracker_(tracker) {
+    }
+    ~Handle();
+
+    handleType GetHandle() { return handle_; }
+
+   private:
+    persistentType handle_;
+
+    // For Object and Function types, we need to hold on to a reference to their
+    // internal data or function handler objects that are reference counted.
+    CefTrackNode* tracker_;
+
+    DISALLOW_COPY_AND_ASSIGN(Handle);
+  };
+  scoped_refptr<Handle> handle_;
+
   CefRefPtr<CefV8Exception> last_exception_;
   bool rethrow_exceptions_;
 
@@ -183,4 +179,45 @@ class CefV8ValueImpl : public CefV8Value {
   DISALLOW_COPY_AND_ASSIGN(CefV8ValueImpl);
 };
 
+class CefV8StackTraceImpl : public CefV8StackTrace {
+ public:
+  explicit CefV8StackTraceImpl(v8::Handle<v8::StackTrace> handle);
+  virtual ~CefV8StackTraceImpl();
+
+  virtual int GetFrameCount() OVERRIDE;
+  virtual CefRefPtr<CefV8StackFrame> GetFrame(int index) OVERRIDE;
+
+  v8::Handle<v8::StackTrace> GetHandle() { return handle_->GetHandle(); }
+
+ protected:
+  typedef CefV8Handle<v8::StackTrace> Handle;
+  scoped_refptr<Handle> handle_;
+
+  IMPLEMENT_REFCOUNTING(CefV8StackTraceImpl);
+  DISALLOW_COPY_AND_ASSIGN(CefV8StackTraceImpl);
+};
+
+class CefV8StackFrameImpl : public CefV8StackFrame {
+ public:
+  explicit CefV8StackFrameImpl(v8::Handle<v8::StackFrame> handle);
+  virtual ~CefV8StackFrameImpl();
+
+  virtual CefString GetScriptName() OVERRIDE;
+  virtual CefString GetScriptNameOrSourceURL() OVERRIDE;
+  virtual CefString GetFunctionName() OVERRIDE;
+  virtual int GetLineNumber() OVERRIDE;
+  virtual int GetColumn() OVERRIDE;
+  virtual bool IsEval() OVERRIDE;
+  virtual bool IsConstructor() OVERRIDE;
+
+  v8::Handle<v8::StackFrame> GetHandle() { return handle_->GetHandle(); }
+
+ protected:
+  typedef CefV8Handle<v8::StackFrame> Handle;
+  scoped_refptr<Handle> handle_;
+
+  IMPLEMENT_REFCOUNTING(CefV8StackFrameImpl);
+  DISALLOW_COPY_AND_ASSIGN(CefV8StackFrameImpl);
+};
+
 #endif  // CEF_LIBCEF_V8_IMPL_H_
diff --git a/cef1/libcef_dll/cpptoc/v8stack_frame_cpptoc.cc b/cef1/libcef_dll/cpptoc/v8stack_frame_cpptoc.cc
new file mode 100644
index 000000000..3da6bc6c8
--- /dev/null
+++ b/cef1/libcef_dll/cpptoc/v8stack_frame_cpptoc.cc
@@ -0,0 +1,142 @@
+// Copyright (c) 2012 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. If making changes by
+// hand only do so within the body of existing method and function
+// implementations. See the translator.README.txt file in the tools directory
+// for more information.
+//
+
+#include "libcef_dll/cpptoc/v8stack_frame_cpptoc.h"
+
+
+// MEMBER FUNCTIONS - Body may be edited by hand.
+
+cef_string_userfree_t CEF_CALLBACK v8stack_frame_get_script_name(
+    struct _cef_v8stack_frame_t* self) {
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  DCHECK(self);
+  if (!self)
+    return NULL;
+
+  // Execute
+  CefString _retval = CefV8StackFrameCppToC::Get(self)->GetScriptName();
+
+  // Return type: string
+  return _retval.DetachToUserFree();
+}
+
+cef_string_userfree_t CEF_CALLBACK v8stack_frame_get_script_name_or_source_url(
+    struct _cef_v8stack_frame_t* self) {
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  DCHECK(self);
+  if (!self)
+    return NULL;
+
+  // Execute
+  CefString _retval = CefV8StackFrameCppToC::Get(
+      self)->GetScriptNameOrSourceURL();
+
+  // Return type: string
+  return _retval.DetachToUserFree();
+}
+
+cef_string_userfree_t CEF_CALLBACK v8stack_frame_get_function_name(
+    struct _cef_v8stack_frame_t* self) {
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  DCHECK(self);
+  if (!self)
+    return NULL;
+
+  // Execute
+  CefString _retval = CefV8StackFrameCppToC::Get(self)->GetFunctionName();
+
+  // Return type: string
+  return _retval.DetachToUserFree();
+}
+
+int CEF_CALLBACK v8stack_frame_get_line_number(
+    struct _cef_v8stack_frame_t* self) {
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  DCHECK(self);
+  if (!self)
+    return 0;
+
+  // Execute
+  int _retval = CefV8StackFrameCppToC::Get(self)->GetLineNumber();
+
+  // Return type: simple
+  return _retval;
+}
+
+int CEF_CALLBACK v8stack_frame_get_column(struct _cef_v8stack_frame_t* self) {
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  DCHECK(self);
+  if (!self)
+    return 0;
+
+  // Execute
+  int _retval = CefV8StackFrameCppToC::Get(self)->GetColumn();
+
+  // Return type: simple
+  return _retval;
+}
+
+int CEF_CALLBACK v8stack_frame_is_eval(struct _cef_v8stack_frame_t* self) {
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  DCHECK(self);
+  if (!self)
+    return 0;
+
+  // Execute
+  bool _retval = CefV8StackFrameCppToC::Get(self)->IsEval();
+
+  // Return type: bool
+  return _retval;
+}
+
+int CEF_CALLBACK v8stack_frame_is_constructor(
+    struct _cef_v8stack_frame_t* self) {
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  DCHECK(self);
+  if (!self)
+    return 0;
+
+  // Execute
+  bool _retval = CefV8StackFrameCppToC::Get(self)->IsConstructor();
+
+  // Return type: bool
+  return _retval;
+}
+
+
+// CONSTRUCTOR - Do not edit by hand.
+
+CefV8StackFrameCppToC::CefV8StackFrameCppToC(CefV8StackFrame* cls)
+    : CefCppToC<CefV8StackFrameCppToC, CefV8StackFrame, cef_v8stack_frame_t>(
+        cls) {
+  struct_.struct_.get_script_name = v8stack_frame_get_script_name;
+  struct_.struct_.get_script_name_or_source_url =
+      v8stack_frame_get_script_name_or_source_url;
+  struct_.struct_.get_function_name = v8stack_frame_get_function_name;
+  struct_.struct_.get_line_number = v8stack_frame_get_line_number;
+  struct_.struct_.get_column = v8stack_frame_get_column;
+  struct_.struct_.is_eval = v8stack_frame_is_eval;
+  struct_.struct_.is_constructor = v8stack_frame_is_constructor;
+}
+
+#ifndef NDEBUG
+template<> long CefCppToC<CefV8StackFrameCppToC, CefV8StackFrame,
+    cef_v8stack_frame_t>::DebugObjCt = 0;
+#endif
+
diff --git a/cef1/libcef_dll/cpptoc/v8stack_frame_cpptoc.h b/cef1/libcef_dll/cpptoc/v8stack_frame_cpptoc.h
new file mode 100644
index 000000000..d5ee79a23
--- /dev/null
+++ b/cef1/libcef_dll/cpptoc/v8stack_frame_cpptoc.h
@@ -0,0 +1,37 @@
+// Copyright (c) 2012 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. If making changes by
+// hand only do so within the body of existing method and function
+// implementations. See the translator.README.txt file in the tools directory
+// for more information.
+//
+
+#ifndef CEF_LIBCEF_DLL_CPPTOC_V8STACK_FRAME_CPPTOC_H_
+#define CEF_LIBCEF_DLL_CPPTOC_V8STACK_FRAME_CPPTOC_H_
+#pragma once
+
+#ifndef BUILDING_CEF_SHARED
+#pragma message("Warning: "__FILE__" may be accessed DLL-side only")
+#else  // BUILDING_CEF_SHARED
+
+#include "include/cef_v8.h"
+#include "include/capi/cef_v8_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 CefV8StackFrameCppToC
+    : public CefCppToC<CefV8StackFrameCppToC, CefV8StackFrame,
+        cef_v8stack_frame_t> {
+ public:
+  explicit CefV8StackFrameCppToC(CefV8StackFrame* cls);
+  virtual ~CefV8StackFrameCppToC() {}
+};
+
+#endif  // BUILDING_CEF_SHARED
+#endif  // CEF_LIBCEF_DLL_CPPTOC_V8STACK_FRAME_CPPTOC_H_
+
diff --git a/cef1/libcef_dll/cpptoc/v8stack_trace_cpptoc.cc b/cef1/libcef_dll/cpptoc/v8stack_trace_cpptoc.cc
new file mode 100644
index 000000000..c7c884c5a
--- /dev/null
+++ b/cef1/libcef_dll/cpptoc/v8stack_trace_cpptoc.cc
@@ -0,0 +1,79 @@
+// Copyright (c) 2012 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. If making changes by
+// hand only do so within the body of existing method and function
+// implementations. See the translator.README.txt file in the tools directory
+// for more information.
+//
+
+#include "libcef_dll/cpptoc/v8stack_frame_cpptoc.h"
+#include "libcef_dll/cpptoc/v8stack_trace_cpptoc.h"
+
+
+// GLOBAL FUNCTIONS - Body may be edited by hand.
+
+CEF_EXPORT cef_v8stack_trace_t* cef_v8stack_trace_get_current(int frame_limit) {
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Execute
+  CefRefPtr<CefV8StackTrace> _retval = CefV8StackTrace::GetCurrent(
+      frame_limit);
+
+  // Return type: refptr_same
+  return CefV8StackTraceCppToC::Wrap(_retval);
+}
+
+
+// MEMBER FUNCTIONS - Body may be edited by hand.
+
+int CEF_CALLBACK v8stack_trace_get_frame_count(
+    struct _cef_v8stack_trace_t* self) {
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  DCHECK(self);
+  if (!self)
+    return 0;
+
+  // Execute
+  int _retval = CefV8StackTraceCppToC::Get(self)->GetFrameCount();
+
+  // Return type: simple
+  return _retval;
+}
+
+struct _cef_v8stack_frame_t* CEF_CALLBACK v8stack_trace_get_frame(
+    struct _cef_v8stack_trace_t* self, int index) {
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  DCHECK(self);
+  if (!self)
+    return NULL;
+
+  // Execute
+  CefRefPtr<CefV8StackFrame> _retval = CefV8StackTraceCppToC::Get(
+      self)->GetFrame(
+      index);
+
+  // Return type: refptr_same
+  return CefV8StackFrameCppToC::Wrap(_retval);
+}
+
+
+// CONSTRUCTOR - Do not edit by hand.
+
+CefV8StackTraceCppToC::CefV8StackTraceCppToC(CefV8StackTrace* cls)
+    : CefCppToC<CefV8StackTraceCppToC, CefV8StackTrace, cef_v8stack_trace_t>(
+        cls) {
+  struct_.struct_.get_frame_count = v8stack_trace_get_frame_count;
+  struct_.struct_.get_frame = v8stack_trace_get_frame;
+}
+
+#ifndef NDEBUG
+template<> long CefCppToC<CefV8StackTraceCppToC, CefV8StackTrace,
+    cef_v8stack_trace_t>::DebugObjCt = 0;
+#endif
+
diff --git a/cef1/libcef_dll/cpptoc/v8stack_trace_cpptoc.h b/cef1/libcef_dll/cpptoc/v8stack_trace_cpptoc.h
new file mode 100644
index 000000000..b2b65352f
--- /dev/null
+++ b/cef1/libcef_dll/cpptoc/v8stack_trace_cpptoc.h
@@ -0,0 +1,37 @@
+// Copyright (c) 2012 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. If making changes by
+// hand only do so within the body of existing method and function
+// implementations. See the translator.README.txt file in the tools directory
+// for more information.
+//
+
+#ifndef CEF_LIBCEF_DLL_CPPTOC_V8STACK_TRACE_CPPTOC_H_
+#define CEF_LIBCEF_DLL_CPPTOC_V8STACK_TRACE_CPPTOC_H_
+#pragma once
+
+#ifndef BUILDING_CEF_SHARED
+#pragma message("Warning: "__FILE__" may be accessed DLL-side only")
+#else  // BUILDING_CEF_SHARED
+
+#include "include/cef_v8.h"
+#include "include/capi/cef_v8_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 CefV8StackTraceCppToC
+    : public CefCppToC<CefV8StackTraceCppToC, CefV8StackTrace,
+        cef_v8stack_trace_t> {
+ public:
+  explicit CefV8StackTraceCppToC(CefV8StackTrace* cls);
+  virtual ~CefV8StackTraceCppToC() {}
+};
+
+#endif  // BUILDING_CEF_SHARED
+#endif  // CEF_LIBCEF_DLL_CPPTOC_V8STACK_TRACE_CPPTOC_H_
+
diff --git a/cef1/libcef_dll/ctocpp/v8stack_frame_ctocpp.cc b/cef1/libcef_dll/ctocpp/v8stack_frame_ctocpp.cc
new file mode 100644
index 000000000..8d685df90
--- /dev/null
+++ b/cef1/libcef_dll/ctocpp/v8stack_frame_ctocpp.cc
@@ -0,0 +1,121 @@
+// Copyright (c) 2012 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. If making changes by
+// hand only do so within the body of existing method and function
+// implementations. See the translator.README.txt file in the tools directory
+// for more information.
+//
+
+#include "libcef_dll/ctocpp/v8stack_frame_ctocpp.h"
+
+
+// VIRTUAL METHODS - Body may be edited by hand.
+
+CefString CefV8StackFrameCToCpp::GetScriptName() {
+  if (CEF_MEMBER_MISSING(struct_, get_script_name))
+    return CefString();
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Execute
+  cef_string_userfree_t _retval = struct_->get_script_name(struct_);
+
+  // Return type: string
+  CefString _retvalStr;
+  _retvalStr.AttachToUserFree(_retval);
+  return _retvalStr;
+}
+
+CefString CefV8StackFrameCToCpp::GetScriptNameOrSourceURL() {
+  if (CEF_MEMBER_MISSING(struct_, get_script_name_or_source_url))
+    return CefString();
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Execute
+  cef_string_userfree_t _retval = struct_->get_script_name_or_source_url(
+      struct_);
+
+  // Return type: string
+  CefString _retvalStr;
+  _retvalStr.AttachToUserFree(_retval);
+  return _retvalStr;
+}
+
+CefString CefV8StackFrameCToCpp::GetFunctionName() {
+  if (CEF_MEMBER_MISSING(struct_, get_function_name))
+    return CefString();
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Execute
+  cef_string_userfree_t _retval = struct_->get_function_name(struct_);
+
+  // Return type: string
+  CefString _retvalStr;
+  _retvalStr.AttachToUserFree(_retval);
+  return _retvalStr;
+}
+
+int CefV8StackFrameCToCpp::GetLineNumber() {
+  if (CEF_MEMBER_MISSING(struct_, get_line_number))
+    return 0;
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Execute
+  int _retval = struct_->get_line_number(struct_);
+
+  // Return type: simple
+  return _retval;
+}
+
+int CefV8StackFrameCToCpp::GetColumn() {
+  if (CEF_MEMBER_MISSING(struct_, get_column))
+    return 0;
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Execute
+  int _retval = struct_->get_column(struct_);
+
+  // Return type: simple
+  return _retval;
+}
+
+bool CefV8StackFrameCToCpp::IsEval() {
+  if (CEF_MEMBER_MISSING(struct_, is_eval))
+    return false;
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Execute
+  int _retval = struct_->is_eval(struct_);
+
+  // Return type: bool
+  return _retval?true:false;
+}
+
+bool CefV8StackFrameCToCpp::IsConstructor() {
+  if (CEF_MEMBER_MISSING(struct_, is_constructor))
+    return false;
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Execute
+  int _retval = struct_->is_constructor(struct_);
+
+  // Return type: bool
+  return _retval?true:false;
+}
+
+
+#ifndef NDEBUG
+template<> long CefCToCpp<CefV8StackFrameCToCpp, CefV8StackFrame,
+    cef_v8stack_frame_t>::DebugObjCt = 0;
+#endif
+
diff --git a/cef1/libcef_dll/ctocpp/v8stack_frame_ctocpp.h b/cef1/libcef_dll/ctocpp/v8stack_frame_ctocpp.h
new file mode 100644
index 000000000..6a6a32999
--- /dev/null
+++ b/cef1/libcef_dll/ctocpp/v8stack_frame_ctocpp.h
@@ -0,0 +1,48 @@
+// Copyright (c) 2012 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. If making changes by
+// hand only do so within the body of existing method and function
+// implementations. See the translator.README.txt file in the tools directory
+// for more information.
+//
+
+#ifndef CEF_LIBCEF_DLL_CTOCPP_V8STACK_FRAME_CTOCPP_H_
+#define CEF_LIBCEF_DLL_CTOCPP_V8STACK_FRAME_CTOCPP_H_
+#pragma once
+
+#ifndef USING_CEF_SHARED
+#pragma message("Warning: "__FILE__" may be accessed wrapper-side only")
+#else  // USING_CEF_SHARED
+
+#include "include/cef_v8.h"
+#include "include/capi/cef_v8_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 CefV8StackFrameCToCpp
+    : public CefCToCpp<CefV8StackFrameCToCpp, CefV8StackFrame,
+        cef_v8stack_frame_t> {
+ public:
+  explicit CefV8StackFrameCToCpp(cef_v8stack_frame_t* str)
+      : CefCToCpp<CefV8StackFrameCToCpp, CefV8StackFrame, cef_v8stack_frame_t>(
+          str) {}
+  virtual ~CefV8StackFrameCToCpp() {}
+
+  // CefV8StackFrame methods
+  virtual CefString GetScriptName() OVERRIDE;
+  virtual CefString GetScriptNameOrSourceURL() OVERRIDE;
+  virtual CefString GetFunctionName() OVERRIDE;
+  virtual int GetLineNumber() OVERRIDE;
+  virtual int GetColumn() OVERRIDE;
+  virtual bool IsEval() OVERRIDE;
+  virtual bool IsConstructor() OVERRIDE;
+};
+
+#endif  // USING_CEF_SHARED
+#endif  // CEF_LIBCEF_DLL_CTOCPP_V8STACK_FRAME_CTOCPP_H_
+
diff --git a/cef1/libcef_dll/ctocpp/v8stack_trace_ctocpp.cc b/cef1/libcef_dll/ctocpp/v8stack_trace_ctocpp.cc
new file mode 100644
index 000000000..a569e3948
--- /dev/null
+++ b/cef1/libcef_dll/ctocpp/v8stack_trace_ctocpp.cc
@@ -0,0 +1,65 @@
+// Copyright (c) 2012 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. If making changes by
+// hand only do so within the body of existing method and function
+// implementations. See the translator.README.txt file in the tools directory
+// for more information.
+//
+
+#include "libcef_dll/ctocpp/v8stack_frame_ctocpp.h"
+#include "libcef_dll/ctocpp/v8stack_trace_ctocpp.h"
+
+
+// STATIC METHODS - Body may be edited by hand.
+
+CefRefPtr<CefV8StackTrace> CefV8StackTrace::GetCurrent(int frame_limit) {
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Execute
+  cef_v8stack_trace_t* _retval = cef_v8stack_trace_get_current(
+      frame_limit);
+
+  // Return type: refptr_same
+  return CefV8StackTraceCToCpp::Wrap(_retval);
+}
+
+
+// VIRTUAL METHODS - Body may be edited by hand.
+
+int CefV8StackTraceCToCpp::GetFrameCount() {
+  if (CEF_MEMBER_MISSING(struct_, get_frame_count))
+    return 0;
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Execute
+  int _retval = struct_->get_frame_count(struct_);
+
+  // Return type: simple
+  return _retval;
+}
+
+CefRefPtr<CefV8StackFrame> CefV8StackTraceCToCpp::GetFrame(int index) {
+  if (CEF_MEMBER_MISSING(struct_, get_frame))
+    return NULL;
+
+  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
+
+  // Execute
+  cef_v8stack_frame_t* _retval = struct_->get_frame(struct_,
+      index);
+
+  // Return type: refptr_same
+  return CefV8StackFrameCToCpp::Wrap(_retval);
+}
+
+
+#ifndef NDEBUG
+template<> long CefCToCpp<CefV8StackTraceCToCpp, CefV8StackTrace,
+    cef_v8stack_trace_t>::DebugObjCt = 0;
+#endif
+
diff --git a/cef1/libcef_dll/ctocpp/v8stack_trace_ctocpp.h b/cef1/libcef_dll/ctocpp/v8stack_trace_ctocpp.h
new file mode 100644
index 000000000..05ac92a90
--- /dev/null
+++ b/cef1/libcef_dll/ctocpp/v8stack_trace_ctocpp.h
@@ -0,0 +1,43 @@
+// Copyright (c) 2012 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. If making changes by
+// hand only do so within the body of existing method and function
+// implementations. See the translator.README.txt file in the tools directory
+// for more information.
+//
+
+#ifndef CEF_LIBCEF_DLL_CTOCPP_V8STACK_TRACE_CTOCPP_H_
+#define CEF_LIBCEF_DLL_CTOCPP_V8STACK_TRACE_CTOCPP_H_
+#pragma once
+
+#ifndef USING_CEF_SHARED
+#pragma message("Warning: "__FILE__" may be accessed wrapper-side only")
+#else  // USING_CEF_SHARED
+
+#include "include/cef_v8.h"
+#include "include/capi/cef_v8_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 CefV8StackTraceCToCpp
+    : public CefCToCpp<CefV8StackTraceCToCpp, CefV8StackTrace,
+        cef_v8stack_trace_t> {
+ public:
+  explicit CefV8StackTraceCToCpp(cef_v8stack_trace_t* str)
+      : CefCToCpp<CefV8StackTraceCToCpp, CefV8StackTrace, cef_v8stack_trace_t>(
+          str) {}
+  virtual ~CefV8StackTraceCToCpp() {}
+
+  // CefV8StackTrace methods
+  virtual int GetFrameCount() OVERRIDE;
+  virtual CefRefPtr<CefV8StackFrame> GetFrame(int index) OVERRIDE;
+};
+
+#endif  // USING_CEF_SHARED
+#endif  // CEF_LIBCEF_DLL_CTOCPP_V8STACK_TRACE_CTOCPP_H_
+
diff --git a/cef1/libcef_dll/libcef_dll.cc b/cef1/libcef_dll/libcef_dll.cc
index 9df6cc97c..f04f6fabb 100644
--- a/cef1/libcef_dll/libcef_dll.cc
+++ b/cef1/libcef_dll/libcef_dll.cc
@@ -40,6 +40,8 @@
 #include "libcef_dll/cpptoc/stream_writer_cpptoc.h"
 #include "libcef_dll/cpptoc/v8context_cpptoc.h"
 #include "libcef_dll/cpptoc/v8exception_cpptoc.h"
+#include "libcef_dll/cpptoc/v8stack_frame_cpptoc.h"
+#include "libcef_dll/cpptoc/v8stack_trace_cpptoc.h"
 #include "libcef_dll/cpptoc/v8value_cpptoc.h"
 #include "libcef_dll/cpptoc/web_plugin_info_cpptoc.h"
 #include "libcef_dll/cpptoc/web_urlrequest_cpptoc.h"
@@ -154,6 +156,8 @@ CEF_EXPORT void cef_shutdown() {
   DCHECK_EQ(CefV8ContextHandlerCToCpp::DebugObjCt, 0);
   DCHECK_EQ(CefV8ExceptionCppToC::DebugObjCt, 0);
   DCHECK_EQ(CefV8HandlerCToCpp::DebugObjCt, 0);
+  DCHECK_EQ(CefV8StackFrameCppToC::DebugObjCt, 0);
+  DCHECK_EQ(CefV8StackTraceCppToC::DebugObjCt, 0);
   DCHECK_EQ(CefV8ValueCppToC::DebugObjCt, 0);
   DCHECK_EQ(CefWebPluginInfoCppToC::DebugObjCt, 0);
   DCHECK_EQ(CefWebURLRequestClientCToCpp::DebugObjCt, 0);
diff --git a/cef1/libcef_dll/wrapper/libcef_dll_wrapper.cc b/cef1/libcef_dll/wrapper/libcef_dll_wrapper.cc
index 1909a902d..14496bfff 100644
--- a/cef1/libcef_dll/wrapper/libcef_dll_wrapper.cc
+++ b/cef1/libcef_dll/wrapper/libcef_dll_wrapper.cc
@@ -71,6 +71,8 @@
 #include "libcef_dll/ctocpp/stream_writer_ctocpp.h"
 #include "libcef_dll/ctocpp/v8context_ctocpp.h"
 #include "libcef_dll/ctocpp/v8exception_ctocpp.h"
+#include "libcef_dll/ctocpp/v8stack_frame_ctocpp.h"
+#include "libcef_dll/ctocpp/v8stack_trace_ctocpp.h"
 #include "libcef_dll/ctocpp/v8value_ctocpp.h"
 #include "libcef_dll/ctocpp/web_plugin_info_ctocpp.h"
 #include "libcef_dll/ctocpp/web_urlrequest_ctocpp.h"
@@ -156,6 +158,8 @@ CEF_GLOBAL void CefShutdown() {
   DCHECK_EQ(CefV8ContextHandlerCppToC::DebugObjCt, 0);
   DCHECK_EQ(CefV8ExceptionCToCpp::DebugObjCt, 0);
   DCHECK_EQ(CefV8HandlerCppToC::DebugObjCt, 0);
+  DCHECK_EQ(CefV8StackFrameCToCpp::DebugObjCt, 0);
+  DCHECK_EQ(CefV8StackTraceCToCpp::DebugObjCt, 0);
   DCHECK_EQ(CefV8ValueCToCpp::DebugObjCt, 0);
   DCHECK_EQ(CefWebPluginInfoCToCpp::DebugObjCt, 0);
   DCHECK_EQ(CefWebURLRequestCToCpp::DebugObjCt, 0);
diff --git a/cef1/tests/unittests/v8_unittest.cc b/cef1/tests/unittests/v8_unittest.cc
index 2ae369877..b881d266d 100644
--- a/cef1/tests/unittests/v8_unittest.cc
+++ b/cef1/tests/unittests/v8_unittest.cc
@@ -54,6 +54,7 @@ enum V8TestMode {
   V8TEST_CONTEXT_EVAL_EXCEPTION,
   V8TEST_CONTEXT_ENTERED,
   V8TEST_BINDING,
+  V8TEST_STACK_TRACE,
 };
 
 
@@ -176,6 +177,9 @@ class V8TestHandler : public TestHandler {
       case V8TEST_BINDING:
         RunBindingTest();
         break;
+      case V8TEST_STACK_TRACE:
+        RunStackTraceTest();
+        break;
       default:
         ADD_FAILURE();
         DestroyTest();
@@ -1398,6 +1402,90 @@ class V8TestHandler : public TestHandler {
     DestroyTest();
   }
 
+  void RunStackTraceTest() {
+    CefRefPtr<CefV8Context> context = GetContext();
+
+    static const char* kFuncName = "myfunc";
+
+    class Handler : public CefV8Handler {
+     public:
+      Handler() {}
+      virtual bool Execute(const CefString& name,
+                         CefRefPtr<CefV8Value> object,
+                         const CefV8ValueList& arguments,
+                         CefRefPtr<CefV8Value>& retval,
+                         CefString& exception) OVERRIDE {
+        EXPECT_STREQ(kFuncName, name.ToString().c_str());
+
+        stack_trace_ = CefV8StackTrace::GetCurrent(10);
+
+        retval = CefV8Value::CreateInt(3);
+        got_execute_.yes();
+        return true;
+      }
+
+      TrackCallback got_execute_;
+      CefRefPtr<CefV8StackTrace> stack_trace_;
+
+      IMPLEMENT_REFCOUNTING(Handler);
+    };
+
+    // Enter the V8 context.
+    EXPECT_TRUE(context->Enter());
+
+    Handler* handler = new Handler;
+    CefRefPtr<CefV8Handler> handlerPtr(handler);
+
+    CefRefPtr<CefV8Value> func =
+        CefV8Value::CreateFunction(kFuncName, handler);
+    EXPECT_TRUE(func.get());
+    CefRefPtr<CefV8Value> obj = context->GetGlobal();
+    EXPECT_TRUE(obj.get());
+    obj->SetValue(kFuncName, func, V8_PROPERTY_ATTRIBUTE_NONE);
+
+    CefRefPtr<CefV8Value> retval;
+    CefRefPtr<CefV8Exception> exception;
+
+    EXPECT_TRUE(context->Eval(
+        "function jsfunc() { return window.myfunc(); }\n"
+        "jsfunc();",
+        retval, exception));
+    EXPECT_TRUE(retval.get());
+    EXPECT_TRUE(retval->IsInt());
+    EXPECT_EQ(3, retval->GetIntValue());
+    EXPECT_FALSE(exception.get());
+
+    EXPECT_TRUE(handler->stack_trace_.get());
+    EXPECT_EQ(2, handler->stack_trace_->GetFrameCount());
+
+    CefRefPtr<CefV8StackFrame> frame;
+
+    frame = handler->stack_trace_->GetFrame(0);
+    EXPECT_TRUE(frame->GetScriptName().empty());
+    EXPECT_TRUE(frame->GetScriptNameOrSourceURL().empty());
+    EXPECT_STREQ("jsfunc", frame->GetFunctionName().ToString().c_str());
+    EXPECT_EQ(1, frame->GetLineNumber());
+    EXPECT_EQ(35, frame->GetColumn());
+    EXPECT_TRUE(frame.get());
+    EXPECT_TRUE(frame->IsEval());
+    EXPECT_FALSE(frame->IsConstructor());
+
+    frame = handler->stack_trace_->GetFrame(1);
+    EXPECT_TRUE(frame->GetScriptName().empty());
+    EXPECT_TRUE(frame->GetScriptNameOrSourceURL().empty());
+    EXPECT_TRUE(frame->GetFunctionName().empty());
+    EXPECT_EQ(2, frame->GetLineNumber());
+    EXPECT_EQ(1, frame->GetColumn());
+    EXPECT_TRUE(frame.get());
+    EXPECT_TRUE(frame->IsEval());
+    EXPECT_FALSE(frame->IsConstructor());
+
+    // Exit the V8 context.
+    EXPECT_TRUE(context->Exit());
+
+    DestroyTest();
+  }
+
   virtual void OnLoadEnd(CefRefPtr<CefBrowser> browser,
                          CefRefPtr<CefFrame> frame,
                          int httpStatusCode) OVERRIDE {
@@ -1521,6 +1609,7 @@ V8_TEST(ContextEval, V8TEST_CONTEXT_EVAL);
 V8_TEST(ContextEvalException, V8TEST_CONTEXT_EVAL_EXCEPTION);
 V8_TEST_EX(ContextEntered, V8TEST_CONTEXT_ENTERED, NULL);
 V8_TEST_EX(Binding, V8TEST_BINDING, kV8BindingTestUrl);
+V8_TEST(StackTrace, V8TEST_STACK_TRACE);
 
 
 namespace {