diff --git a/cef.gyp b/cef.gyp index fdbe64ea6..20658e615 100644 --- a/cef.gyp +++ b/cef.gyp @@ -55,6 +55,7 @@ 'tests/cefclient/mac/English.lproj/MainMenu.xib', 'tests/cefclient/mac/Info.plist', 'tests/cefclient/res/domaccess.html', + 'tests/cefclient/res/extensionperf.html', 'tests/cefclient/res/localstorage.html', 'tests/cefclient/res/logo.png', 'tests/cefclient/res/xmlhttprequest.html', diff --git a/include/cef.h b/include/cef.h index b61882e1a..b8c69fe99 100644 --- a/include/cef.h +++ b/include/cef.h @@ -2210,7 +2210,8 @@ public: /*--cef()--*/ virtual bool Get(const CefString& name, const CefRefPtr object, - CefRefPtr& retval) =0; + CefRefPtr& retval, + CefString& exception) =0; /// // Called to set an accessor value. |name| is the name of the property being @@ -2221,7 +2222,8 @@ public: /*--cef()--*/ virtual bool Set(const CefString& name, const CefRefPtr object, - const CefRefPtr value) =0; + const CefRefPtr value, + CefString& exception) =0; }; diff --git a/include/cef_capi.h b/include/cef_capi.h index 75315bb66..d3dca895e 100644 --- a/include/cef_capi.h +++ b/include/cef_capi.h @@ -2002,7 +2002,7 @@ typedef struct _cef_v8accessor_t /// int (CEF_CALLBACK *get)(struct _cef_v8accessor_t* self, const cef_string_t* name, struct _cef_v8value_t* object, - struct _cef_v8value_t** retval); + struct _cef_v8value_t** retval, cef_string_t* exception); /// // Called to set an accessor value. |name| is the name of the property being @@ -2012,7 +2012,7 @@ typedef struct _cef_v8accessor_t /// int (CEF_CALLBACK *set)(struct _cef_v8accessor_t* self, const cef_string_t* name, struct _cef_v8value_t* object, - struct _cef_v8value_t* value); + struct _cef_v8value_t* value, cef_string_t* exception); } cef_v8accessor_t; diff --git a/libcef/v8_impl.cc b/libcef/v8_impl.cc index badbbb0b1..8c5014052 100644 --- a/libcef/v8_impl.cc +++ b/libcef/v8_impl.cc @@ -97,54 +97,102 @@ CefRefPtr FindBrowserForFrame(WebKit::WebFrame *frame) return NULL; } -// Convert a wide string to a V8 string. +// Convert a CefString to a V8::String. v8::Handle GetV8String(const CefString& str) { +#if defined(CEF_STRING_TYPE_UTF16) + // Already a UTF16 string. + return v8::String::New( + reinterpret_cast( + const_cast(str.c_str())), + str.length()); +#elif defined(CEF_STRING_TYPE_UTF8) + // Already a UTF8 string. + return v8::String::New(const_cast(str.c_str()), str.length()); +#else + // Convert the string to UTF8. std::string tmpStr = str; return v8::String::New(tmpStr.c_str(), tmpStr.length()); +#endif } -// Convert a V8 string to a UTF8 string. -std::string GetString(v8::Handle str) +#if defined(CEF_STRING_TYPE_UTF16) +void v8impl_string_dtor(char16* str) { + delete [] str; +} +#elif defined(CEF_STRING_TYPE_UTF8) +void v8impl_string_dtor(char* str) +{ + delete [] str; +} +#endif + +// Convert a v8::String to CefString. +void GetCefString(v8::Handle str, CefString& out) +{ +#if defined(CEF_STRING_TYPE_WIDE) // Allocate enough space for a worst-case conversion. int len = str->Utf8Length(); - char* buf = new char[len+1]; - str->WriteUtf8(buf, len+1); - std::string ret(buf, len); + char* buf = new char[len + 1]; + str->WriteUtf8(buf, len + 1); + + // Perform conversion to the wide type. + cef_string_t* retws = out.GetWritableStruct(); + cef_string_utf8_to_wide(buf, len, retws); + delete [] buf; - return ret; +#else // !defined(CEF_STRING_TYPE_WIDE) +#if defined(CEF_STRING_TYPE_UTF16) + int len = str->Length(); + char16* buf = new char16[len + 1]; + str->Write(reinterpret_cast(buf), 0, len + 1); +#else + // Allocate enough space for a worst-case conversion. + int len = str->Utf8Length(); + char* buf = new char[len + 1]; + str->WriteUtf8(buf, len + 1); +#endif + + // Don't perform an extra string copy. + out.clear(); + cef_string_t* retws = out.GetWritableStruct(); + retws->str = buf; + retws->length = len; + retws->dtor = v8impl_string_dtor; +#endif // !defined(CEF_STRING_TYPE_WIDE) } // V8 function callback. v8::Handle FunctionCallbackImpl(const v8::Arguments& args) { v8::HandleScope handle_scope; + CefV8Handler* handler = static_cast(v8::External::Unwrap(args.Data())); - + CefV8ValueList params; for(int i = 0; i < args.Length(); i++) params.push_back(new CefV8ValueImpl(args[i])); - CefString func_name = - GetString(v8::Handle::Cast(args.Callee()->GetName())); + CefString func_name; + GetCefString(v8::Handle::Cast(args.Callee()->GetName()), + func_name); CefRefPtr object = new CefV8ValueImpl(args.This()); CefRefPtr retval; CefString exception; - v8::Handle value = v8::Null(); if(handler->Execute(func_name, object, params, retval, exception)) { - if(!exception.empty()) - value = v8::ThrowException(GetV8String(exception)); + if (!exception.empty()) + return v8::ThrowException(v8::Exception::Error(GetV8String(exception))); else { CefV8ValueImpl* rv = static_cast(retval.get()); - if(rv) - value = rv->GetHandle(); + if (rv) + return rv->GetHandle(); } } - return value; + return v8::Undefined(); } // V8 Accessor callbacks @@ -153,7 +201,6 @@ v8::Handle AccessorGetterCallbackImpl(v8::Local property, { v8::HandleScope handle_scope; - v8::Handle value = v8::Undefined(); v8::Handle obj = info.This(); v8::Handle key = v8::String::New("Cef::Accessor"); @@ -166,14 +213,21 @@ v8::Handle AccessorGetterCallbackImpl(v8::Local property, if (accessorPtr) { CefRefPtr retval; CefRefPtr object = new CefV8ValueImpl(obj); - CefString name = GetString(property); - if (accessorPtr->Get(name, object, retval)) { - CefV8ValueImpl* rv = static_cast(retval.get()); - if (rv) - value = rv->GetHandle(); + CefString name, exception; + GetCefString(property, name); + if (accessorPtr->Get(name, object, retval, exception)) { + if (!exception.empty()) { + return v8::ThrowException( + v8::Exception::Error(GetV8String(exception))); + } else { + CefV8ValueImpl* rv = static_cast(retval.get()); + if (rv) + return rv->GetHandle(); + } } } - return value; + + return v8::Undefined(); } void AccessorSetterCallbackImpl(v8::Local property, @@ -190,12 +244,17 @@ void AccessorSetterCallbackImpl(v8::Local property, accessorPtr = static_cast(v8::External::Unwrap( obj->Get(key))); } - + if (accessorPtr) { CefRefPtr object = new CefV8ValueImpl(obj); CefRefPtr cefValue = new CefV8ValueImpl(value); - CefString name = GetString(property); - accessorPtr->Set(name, object, cefValue); + CefString name, exception; + GetCefString(property, name); + accessorPtr->Set(name, object, cefValue, exception); + if (!exception.empty()) { + v8::ThrowException(v8::Exception::Error(GetV8String(exception))); + return; + } } } @@ -216,7 +275,7 @@ public: v8::Handle name) { return v8::FunctionTemplate::New(FunctionCallbackImpl, - v8::External::New(handler_)); + v8::External::Wrap(handler_)); } void UIT_RegisterExtension() @@ -379,9 +438,13 @@ WebKit::WebFrame* CefV8ContextImpl::GetWebFrame() // thread. CefV8ValueHandle::~CefV8ValueHandle() { - if(tracker_) + if(tracker_) { TrackAdd(tracker_); - v8_handle_.MakeWeak(tracker_, TrackDestructor); + v8_handle_.MakeWeak(tracker_, TrackDestructor); + } else { + v8_handle_.Dispose(); + v8_handle_.Clear(); + } tracker_ = NULL; } @@ -669,7 +732,7 @@ CefString CefV8ValueImpl::GetStringValue() CefString rv; CEF_REQUIRE_UI_THREAD(rv); v8::HandleScope handle_scope; - rv = GetString(GetHandle()->ToString()); + GetCefString(GetHandle()->ToString(), rv); return rv; } @@ -782,6 +845,10 @@ bool CefV8ValueImpl::SetValue(const CefString& key, bool CefV8ValueImpl::SetValue(int index, CefRefPtr value) { CEF_REQUIRE_UI_THREAD(false); + + if (index < 0) + return false; + if(!GetHandle()->IsObject()) { NOTREACHED(); return false; @@ -791,7 +858,7 @@ bool CefV8ValueImpl::SetValue(int index, CefRefPtr value) if(impl) { v8::HandleScope handle_scope; v8::Local obj = GetHandle()->ToObject(); - return obj->Set(v8::Number::New(index), impl->GetHandle()); + return obj->Set(index, impl->GetHandle()); } else { NOTREACHED(); return false; @@ -834,7 +901,8 @@ bool CefV8ValueImpl::GetKeys(std::vector& keys) uint32_t len = arr_keys->Length(); for(uint32_t i = 0; i < len; ++i) { v8::Local value = arr_keys->Get(v8::Integer::New(i)); - CefString str = GetString(value->ToString()); + CefString str; + GetCefString(value->ToString(), str); if(!IsReservedKey(str)) keys.push_back(str); } @@ -883,7 +951,7 @@ CefString CefV8ValueImpl::GetFunctionName() v8::HandleScope handle_scope; v8::Local obj = GetHandle()->ToObject(); v8::Local func = v8::Local::Cast(obj); - rv = GetString(v8::Handle::Cast(func->GetName())); + GetCefString(v8::Handle::Cast(func->GetName()), rv); return rv; } @@ -963,7 +1031,7 @@ bool CefV8ValueImpl::ExecuteFunctionWithContext( v8::TryCatch try_catch; v8::Local func_rv = func->Call(recv, argc, argv); if (try_catch.HasCaught()) - exception = GetString(try_catch.Message()->Get()); + GetCefString(try_catch.Message()->Get(), exception); else retval = new CefV8ValueImpl(func_rv); diff --git a/libcef_dll/cpptoc/v8accessor_cpptoc.cc b/libcef_dll/cpptoc/v8accessor_cpptoc.cc index fda4687ba..712a089f3 100644 --- a/libcef_dll/cpptoc/v8accessor_cpptoc.cc +++ b/libcef_dll/cpptoc/v8accessor_cpptoc.cc @@ -18,7 +18,7 @@ int CEF_CALLBACK v8accessor_get(struct _cef_v8accessor_t* self, const cef_string_t* name, struct _cef_v8value_t* object, - struct _cef_v8value_t** retval) + struct _cef_v8value_t** retval, cef_string_t* exception) { DCHECK(self); if(!self) @@ -29,8 +29,9 @@ int CEF_CALLBACK v8accessor_get(struct _cef_v8accessor_t* self, objectPtr = CefV8ValueCToCpp::Wrap(object); CefRefPtr retValPtr; + CefString exceptionStr(exception); bool rv = CefV8AccessorCppToC::Get(self)->Get(CefString(name), objectPtr, - retValPtr); + retValPtr, exceptionStr); if(rv) { if(retValPtr.get() && retval) *retval = CefV8ValueCToCpp::Unwrap(retValPtr); @@ -41,7 +42,7 @@ int CEF_CALLBACK v8accessor_get(struct _cef_v8accessor_t* self, int CEF_CALLBACK v8accessor_set(struct _cef_v8accessor_t* self, const cef_string_t* name, struct _cef_v8value_t* object, - struct _cef_v8value_t* value) + struct _cef_v8value_t* value, cef_string_t* exception) { DCHECK(self); if(!self) @@ -55,8 +56,9 @@ int CEF_CALLBACK v8accessor_set(struct _cef_v8accessor_t* self, if(value) valuePtr = CefV8ValueCToCpp::Wrap(value); + CefString exceptionStr(exception); bool rv = CefV8AccessorCppToC::Get(self)->Set(CefString(name), objectPtr, - valuePtr); + valuePtr, exceptionStr); return rv; } diff --git a/libcef_dll/ctocpp/v8accessor_ctocpp.cc b/libcef_dll/ctocpp/v8accessor_ctocpp.cc index 4598fe69c..df27076c2 100644 --- a/libcef_dll/ctocpp/v8accessor_ctocpp.cc +++ b/libcef_dll/ctocpp/v8accessor_ctocpp.cc @@ -17,7 +17,8 @@ // VIRTUAL METHODS - Body may be edited by hand. bool CefV8AccessorCToCpp::Get(const CefString& name, - const CefRefPtr object, CefRefPtr& retval) + const CefRefPtr object, CefRefPtr& retval, + CefString& exception) { if(CEF_MEMBER_MISSING(struct_, get)) return false; @@ -25,7 +26,8 @@ bool CefV8AccessorCToCpp::Get(const CefString& name, cef_v8value_t* retvalStruct = NULL; int rv = struct_->get(struct_, name.GetStruct(), - CefV8ValueCppToC::Wrap(object), &retvalStruct); + CefV8ValueCppToC::Wrap(object), &retvalStruct, + exception.GetWritableStruct()); if(retvalStruct) retval = CefV8ValueCppToC::Unwrap(retvalStruct); @@ -33,14 +35,16 @@ bool CefV8AccessorCToCpp::Get(const CefString& name, } bool CefV8AccessorCToCpp::Set(const CefString& name, - const CefRefPtr object, const CefRefPtr value) + const CefRefPtr object, const CefRefPtr value, + CefString& exception) { if(CEF_MEMBER_MISSING(struct_, set)) return false; int rv = struct_->set(struct_, name.GetStruct(), CefV8ValueCppToC::Wrap(object), - CefV8ValueCppToC::Wrap(value)); + CefV8ValueCppToC::Wrap(value), + exception.GetWritableStruct()); return rv ? true : false; } diff --git a/libcef_dll/ctocpp/v8accessor_ctocpp.h b/libcef_dll/ctocpp/v8accessor_ctocpp.h index 0044920fc..a35649c25 100644 --- a/libcef_dll/ctocpp/v8accessor_ctocpp.h +++ b/libcef_dll/ctocpp/v8accessor_ctocpp.h @@ -32,9 +32,9 @@ public: // CefV8Accessor methods virtual bool Get(const CefString& name, const CefRefPtr object, - CefRefPtr& retval) OVERRIDE; + CefRefPtr& retval, CefString& exception) OVERRIDE; virtual bool Set(const CefString& name, const CefRefPtr object, - const CefRefPtr value) OVERRIDE; + const CefRefPtr value, CefString& exception) OVERRIDE; }; #endif // BUILDING_CEF_SHARED diff --git a/tests/cefclient/cefclient.rc b/tests/cefclient/cefclient.rc index 6696c8221..d69de0f30 100644 --- a/tests/cefclient/cefclient.rc +++ b/tests/cefclient/cefclient.rc @@ -37,6 +37,7 @@ IDS_XMLHTTPREQUEST BINARY "res\\xmlhttprequest.html" IDS_DOMACCESS BINARY "res\\domaccess.html" IDS_MODALMAIN BINARY "res\\modalmain.html" IDS_MODALDIALOG BINARY "res\\modaldialog.html" +IDS_EXTENSIONPERF BINARY "res\\extensionperf.html" ///////////////////////////////////////////////////////////////////////////// // @@ -73,6 +74,7 @@ BEGIN MENUITEM "Get Text", ID_TESTS_GETTEXT MENUITEM "JavaScript Binding Handler", ID_TESTS_JAVASCRIPT_BINDING MENUITEM "JavaScript Extension Handler",ID_TESTS_JAVASCRIPT_EXTENSION + MENUITEM "JavaScript Extension Performance",ID_TESTS_JAVASCRIPT_PERFORMANCE MENUITEM "JavaScript Execute", ID_TESTS_JAVASCRIPT_EXECUTE MENUITEM "Plugin", ID_TESTS_PLUGIN MENUITEM "Popup Window", ID_TESTS_POPUP diff --git a/tests/cefclient/cefclient_mac.mm b/tests/cefclient/cefclient_mac.mm index 88b6b44af..6dea323c1 100644 --- a/tests/cefclient/cefclient_mac.mm +++ b/tests/cefclient/cefclient_mac.mm @@ -188,6 +188,7 @@ NSButton* MakeButton(NSRect* rect, NSString* title, NSView* parent) { - (IBAction)testGetText:(id)sender; - (IBAction)testJSBinding:(id)sender; - (IBAction)testJSExtension:(id)sender; +- (IBAction)testJSExtensionPerf:(id)sender; - (IBAction)testJSExecute:(id)sender; - (IBAction)testRequest:(id)sender; - (IBAction)testLocalStorage:(id)sender; @@ -236,6 +237,9 @@ NSButton* MakeButton(NSRect* rect, NSString* title, NSView* parent) { [testMenu addItemWithTitle:@"JavaScript Extension Handler" action:@selector(testJSExtension:) keyEquivalent:@""]; + [testMenu addItemWithTitle:@"JavaScript Extension Performance" + action:@selector(testJSExtensionPerf:) + keyEquivalent:@""]; [testMenu addItemWithTitle:@"JavaScript Execute" action:@selector(testJSExecute:) keyEquivalent:@""]; @@ -397,6 +401,11 @@ NSButton* MakeButton(NSRect* rect, NSString* title, NSView* parent) { RunExtensionTest(g_handler->GetBrowser()); } +- (IBAction)testJSExtensionPerf:(id)sender { + if(g_handler.get() && g_handler->GetBrowserHwnd()) + RunExtensionPerfTest(g_handler->GetBrowser()); +} + - (IBAction)testJSExecute:(id)sender { if(g_handler.get() && g_handler->GetBrowserHwnd()) RunJavaScriptExecuteTest(g_handler->GetBrowser()); diff --git a/tests/cefclient/cefclient_win.cpp b/tests/cefclient/cefclient_win.cpp index 0ce224e6f..a9c832636 100644 --- a/tests/cefclient/cefclient_win.cpp +++ b/tests/cefclient/cefclient_win.cpp @@ -476,6 +476,10 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) if(browser.get()) RunExtensionTest(browser); return 0; + case ID_TESTS_JAVASCRIPT_PERFORMANCE: // Test the V8 performance + if(browser.get()) + RunExtensionPerfTest(browser); + return 0; case ID_TESTS_JAVASCRIPT_EXECUTE: // Test execution of javascript if(browser.get()) RunJavaScriptExecuteTest(browser); diff --git a/tests/cefclient/extension_test.cpp b/tests/cefclient/extension_test.cpp index b6f63d015..b439ec6ae 100644 --- a/tests/cefclient/extension_test.cpp +++ b/tests/cefclient/extension_test.cpp @@ -1,9 +1,9 @@ -// Copyright (c) 2008-2009 The Chromium Embedded Framework Authors. All rights +// 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. #include "extension_test.h" - +#include "resource_util.h" // Implementation of the V8 handler class for the "cef.test" extension. class ClientV8ExtensionHandler : public CefV8Handler @@ -20,7 +20,12 @@ public: CefRefPtr& retval, CefString& exception) { - if(name == "SetTestParam") + if(name == "Dummy") + { + // Used for performance testing. + return true; + } + else if(name == "SetTestParam") { // Handle the SetTestParam native function by saving the string argument // into the local member. @@ -89,6 +94,10 @@ void InitExtensionTest() " native function GetTestObject();" " return GetTestObject();" " };" + " cef.test.dummy = function() {" + " native function Dummy();" + " return Dummy();" + " };" "})();"; CefRegisterExtension("v8/test", code, new ClientV8ExtensionHandler()); } @@ -111,3 +120,14 @@ void RunExtensionTest(CefRefPtr browser) ""; browser->GetMainFrame()->LoadString(html, "about:blank"); } + +void RunExtensionPerfTest(CefRefPtr browser) +{ + CefRefPtr resourceStream; +#if defined(OS_WIN) + resourceStream = GetBinaryResourceReader(IDS_EXTENSIONPERF); +#elif defined(OS_MACOSX) + resourceStream = GetBinaryResourceReader("extensionperf.html"); +#endif + browser->GetMainFrame()->LoadStream(resourceStream, "about:blank"); +} diff --git a/tests/cefclient/extension_test.h b/tests/cefclient/extension_test.h index 154371960..805efa788 100644 --- a/tests/cefclient/extension_test.h +++ b/tests/cefclient/extension_test.h @@ -12,5 +12,6 @@ void InitExtensionTest(); // Run the test. void RunExtensionTest(CefRefPtr browser); +void RunExtensionPerfTest(CefRefPtr browser); #endif // _CEFCLIENT_EXTENSION_TEST_H diff --git a/tests/cefclient/res/extensionperf.html b/tests/cefclient/res/extensionperf.html new file mode 100644 index 000000000..5ac6e7925 --- /dev/null +++ b/tests/cefclient/res/extensionperf.html @@ -0,0 +1,131 @@ + + + + JavaScript Extension: Performance + + + +

JavaScript Extension: Performance

+ +
+ +
+ + + + + + + + + + + +
NameMinAvgMaxProbes
+
+ + + + + diff --git a/tests/cefclient/resource.h b/tests/cefclient/resource.h index 090b598d3..9b2ed6b4d 100644 --- a/tests/cefclient/resource.h +++ b/tests/cefclient/resource.h @@ -52,6 +52,7 @@ #define ID_TESTS_DRAGDROP 32792 #define ID_TESTS_OSRAPP 32793 #define ID_TESTS_MODALDIALOG 32794 +#define ID_TESTS_JAVASCRIPT_PERFORMANCE 32795 #define IDC_STATIC -1 #define IDS_LOGO 1000 #define IDS_UIPLUGIN 1001 @@ -62,6 +63,7 @@ #define IDS_OSRPLUGIN 1006 #define IDS_MODALMAIN 1007 #define IDS_MODALDIALOG 1008 +#define IDS_EXTENSIONPERF 1009 // Avoid files associated with MacOS #define _X86_ diff --git a/tests/cefclient/resource_util.h b/tests/cefclient/resource_util.h index 11cd310fd..dbdbacdaa 100644 --- a/tests/cefclient/resource_util.h +++ b/tests/cefclient/resource_util.h @@ -9,6 +9,8 @@ #if defined(OS_WIN) +#include "resource.h" + // Load a resource of type BINARY bool LoadBinaryResource(int binaryId, DWORD &dwSize, LPBYTE &pBytes); CefRefPtr GetBinaryResourceReader(int binaryId); diff --git a/tests/unittests/v8_unittest.cc b/tests/unittests/v8_unittest.cc index d5a07e40f..8b235e2f4 100644 --- a/tests/unittests/v8_unittest.cc +++ b/tests/unittests/v8_unittest.cc @@ -396,11 +396,15 @@ public: CefRefPtr& retval, CefString& exception) = 0; - virtual bool Get(const CefString& name, const CefRefPtr object, - CefRefPtr& retval) = 0; + virtual bool Get(const CefString& name, + const CefRefPtr object, + CefRefPtr& retval, + CefString& exception) = 0; - virtual bool Set(const CefString& name, const CefRefPtr object, - const CefRefPtr value) = 0; + virtual bool Set(const CefString& name, + const CefRefPtr object, + const CefRefPtr value, + CefString& exception) = 0; }; class DelegatingV8Handler : public CefV8Handler @@ -417,7 +421,7 @@ public: CefRefPtr object, const CefV8ValueList& arguments, CefRefPtr& retval, - CefString& exception) + CefString& exception) OVERRIDE { return delegate_->Execute(name, object, arguments, retval, exception); } @@ -434,16 +438,20 @@ public: DelegatingV8Accessor(CefV8HandlerDelegate *delegate) : delegate_(delegate) { } - bool Get(const CefString& name, const CefRefPtr object, - CefRefPtr& retval) + bool Get(const CefString& name, + const CefRefPtr object, + CefRefPtr& retval, + CefString& exception) OVERRIDE { - return delegate_->Get(name, object, retval); + return delegate_->Get(name, object, retval, exception); } - bool Set(const CefString& name, const CefRefPtr object, - const CefRefPtr value) + bool Set(const CefString& name, + const CefRefPtr object, + const CefRefPtr value, + CefString& exception) OVERRIDE { - return delegate_->Set(name, object, value); + return delegate_->Set(name, object, value, exception); } private: @@ -505,6 +513,11 @@ public: "comp(false,\"a\",\"b\");\n" "try { point.x = -1; } catch(e) { }\n" // should not have any effect. "try { point.y = point.x; theY = point.y; } catch(e) { point.y = 4321; }\n" + // Test get and set exceptions. + "try { exceptObj.makeException = 1; }" + " catch(e) { gotSetException(e.toString()); }\n" + "try { var x = exceptObj.makeException; }" + " catch(e) { gotGetException(e.toString()); }\n" "hello(\"main\", callIFrame);" "function callIFrame() {" " var iframe = document.getElementById('iframe');" @@ -579,25 +592,33 @@ public: CefRefPtr funcHandler(new DelegatingV8Handler(this)); CefRefPtr helloFunc = - CefV8Value::CreateFunction("hello", funcHandler); + CefV8Value::CreateFunction("hello", funcHandler); object->SetValue("hello", helloFunc); CefRefPtr fromIFrameFunc = - CefV8Value::CreateFunction("fromIFrame", funcHandler); + CefV8Value::CreateFunction("fromIFrame", funcHandler); object->SetValue("fromIFrame", fromIFrameFunc); CefRefPtr goFunc = - CefV8Value::CreateFunction("begin", funcHandler); + CefV8Value::CreateFunction("begin", funcHandler); object->SetValue("begin", goFunc); CefRefPtr doneFunc = - CefV8Value::CreateFunction("end", funcHandler); + CefV8Value::CreateFunction("end", funcHandler); object->SetValue("end", doneFunc); CefRefPtr compFunc = - CefV8Value::CreateFunction("comp", funcHandler); + CefV8Value::CreateFunction("comp", funcHandler); object->SetValue("comp", compFunc); + // Used for testing exceptions returned from accessors. + CefRefPtr gotGetExceptionFunc = + CefV8Value::CreateFunction("gotGetException", funcHandler); + object->SetValue("gotGetException", gotGetExceptionFunc); + CefRefPtr gotSetExceptionFunc = + CefV8Value::CreateFunction("gotSetException", funcHandler); + object->SetValue("gotSetException", gotSetExceptionFunc); + // Create an object with accessor based properties: CefRefPtr blankBase; CefRefPtr accessor(new DelegatingV8Accessor(this)); @@ -609,6 +630,15 @@ public: V8_PROPERTY_ATTRIBUTE_NONE); object->SetValue("point", point); + + // Create another object with accessor based properties: + CefRefPtr exceptObj = + CefV8Value::CreateObject(NULL, new DelegatingV8Accessor(this)); + + exceptObj->SetValue("makeException", V8_ACCESS_CONTROL_DEFAULT, + V8_PROPERTY_ATTRIBUTE_NONE); + + object->SetValue("exceptObj", exceptObj); } void CallIFrame() @@ -704,7 +734,7 @@ public: CefRefPtr object, const CefV8ValueList& arguments, CefRefPtr& retval, - CefString& exception) + CefString& exception) OVERRIDE { CefRefPtr cc = CefV8Context::GetCurrentContext(); CefRefPtr ec = CefV8Context::GetEnteredContext(); @@ -797,12 +827,26 @@ public: got_testcomplete_.yes(); DestroyTest(); return true; + } else if (name == "gotGetException") { + if (arguments.size() == 1 && + arguments[0]->GetStringValue() == "Error: My Get Exception") { + got_getexception_.yes(); + } + return true; + } else if (name == "gotSetException") { + if (arguments.size() == 1 && + arguments[0]->GetStringValue() == "Error: My Set Exception") { + got_setexception_.yes(); + } + return true; } return false; } - bool Get(const CefString& name, const CefRefPtr object, - CefRefPtr& retval) + bool Get(const CefString& name, + const CefRefPtr object, + CefRefPtr& retval, + CefString& exception) OVERRIDE { if(name == "x") { got_point_x_read_.yes(); @@ -812,18 +856,26 @@ public: got_point_y_read_.yes(); retval = CefV8Value::CreateInt(y_); return true; + } else if(name == "makeException") { + exception = "My Get Exception"; + return true; } return false; } - bool Set(const CefString& name, const CefRefPtr object, - const CefRefPtr value) + bool Set(const CefString& name, + const CefRefPtr object, + const CefRefPtr value, + CefString& exception) OVERRIDE { if(name == "y") { y_ = value->GetIntValue(); if( y_ == 1234) got_point_y_write_.yes(); return true; + } else if(name == "makeException") { + exception = "My Set Exception"; + return true; } return false; } @@ -845,6 +897,8 @@ public: TrackCallback got_iframe_as_entered_url_; TrackCallback got_no_context_; TrackCallback got_exception_; + TrackCallback got_getexception_; + TrackCallback got_setexception_; TrackCallback got_navigation_; TrackCallback got_testcomplete_; @@ -870,6 +924,8 @@ TEST(V8Test, Context) EXPECT_TRUE(handler->got_correct_entered_url_); EXPECT_TRUE(handler->got_correct_current_url_); EXPECT_TRUE(handler->got_exception_); + EXPECT_TRUE(handler->got_getexception_); + EXPECT_TRUE(handler->got_setexception_); EXPECT_TRUE(handler->got_navigation_); EXPECT_TRUE(handler->got_testcomplete_); }