- Fix memory leaks in V8 usage (issue #323).
- Improve performance of V8 string conversions (issue #323). - Add V8 performance test to cefclient (issue #323). - Add the ability to return exceptions from V8 accessors (issue #327). - Return undefined instead of null from a V8 handler if no return value is specified (issue #329). git-svn-id: https://chromiumembedded.googlecode.com/svn/trunk@291 5089003a-bbd8-11dd-ad1f-f1f9622dbc98
This commit is contained in:
parent
792e78795f
commit
32402b2287
1
cef.gyp
1
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',
|
||||
|
|
|
@ -2210,7 +2210,8 @@ public:
|
|||
/*--cef()--*/
|
||||
virtual bool Get(const CefString& name,
|
||||
const CefRefPtr<CefV8Value> object,
|
||||
CefRefPtr<CefV8Value>& retval) =0;
|
||||
CefRefPtr<CefV8Value>& 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<CefV8Value> object,
|
||||
const CefRefPtr<CefV8Value> value) =0;
|
||||
const CefRefPtr<CefV8Value> value,
|
||||
CefString& exception) =0;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -97,54 +97,102 @@ CefRefPtr<CefBrowserImpl> FindBrowserForFrame(WebKit::WebFrame *frame)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
// Convert a wide string to a V8 string.
|
||||
// Convert a CefString to a V8::String.
|
||||
v8::Handle<v8::String> GetV8String(const CefString& str)
|
||||
{
|
||||
#if defined(CEF_STRING_TYPE_UTF16)
|
||||
// Already a UTF16 string.
|
||||
return v8::String::New(
|
||||
reinterpret_cast<uint16_t*>(
|
||||
const_cast<CefString::char_type*>(str.c_str())),
|
||||
str.length());
|
||||
#elif defined(CEF_STRING_TYPE_UTF8)
|
||||
// Already a UTF8 string.
|
||||
return v8::String::New(const_cast<char*>(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<v8::String> 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<v8::String> 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<uint16_t*>(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<v8::Value> FunctionCallbackImpl(const v8::Arguments& args)
|
||||
{
|
||||
v8::HandleScope handle_scope;
|
||||
|
||||
CefV8Handler* handler =
|
||||
static_cast<CefV8Handler*>(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<v8::String>::Cast(args.Callee()->GetName()));
|
||||
CefString func_name;
|
||||
GetCefString(v8::Handle<v8::String>::Cast(args.Callee()->GetName()),
|
||||
func_name);
|
||||
CefRefPtr<CefV8Value> object = new CefV8ValueImpl(args.This());
|
||||
CefRefPtr<CefV8Value> retval;
|
||||
CefString exception;
|
||||
v8::Handle<v8::Value> 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<CefV8ValueImpl*>(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<v8::Value> AccessorGetterCallbackImpl(v8::Local<v8::String> property,
|
|||
{
|
||||
v8::HandleScope handle_scope;
|
||||
|
||||
v8::Handle<v8::Value> value = v8::Undefined();
|
||||
v8::Handle<v8::Object> obj = info.This();
|
||||
v8::Handle<v8::String> key = v8::String::New("Cef::Accessor");
|
||||
|
||||
|
@ -166,14 +213,21 @@ v8::Handle<v8::Value> AccessorGetterCallbackImpl(v8::Local<v8::String> property,
|
|||
if (accessorPtr) {
|
||||
CefRefPtr<CefV8Value> retval;
|
||||
CefRefPtr<CefV8Value> object = new CefV8ValueImpl(obj);
|
||||
CefString name = GetString(property);
|
||||
if (accessorPtr->Get(name, object, retval)) {
|
||||
CefV8ValueImpl* rv = static_cast<CefV8ValueImpl*>(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<CefV8ValueImpl*>(retval.get());
|
||||
if (rv)
|
||||
return rv->GetHandle();
|
||||
}
|
||||
}
|
||||
}
|
||||
return value;
|
||||
|
||||
return v8::Undefined();
|
||||
}
|
||||
|
||||
void AccessorSetterCallbackImpl(v8::Local<v8::String> property,
|
||||
|
@ -190,12 +244,17 @@ void AccessorSetterCallbackImpl(v8::Local<v8::String> property,
|
|||
accessorPtr = static_cast<CefV8Accessor*>(v8::External::Unwrap(
|
||||
obj->Get(key)));
|
||||
}
|
||||
|
||||
|
||||
if (accessorPtr) {
|
||||
CefRefPtr<CefV8Value> object = new CefV8ValueImpl(obj);
|
||||
CefRefPtr<CefV8Value> 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<v8::String> 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<CefV8Value> 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<CefV8Value> value)
|
|||
if(impl) {
|
||||
v8::HandleScope handle_scope;
|
||||
v8::Local<v8::Object> 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<CefString>& keys)
|
|||
uint32_t len = arr_keys->Length();
|
||||
for(uint32_t i = 0; i < len; ++i) {
|
||||
v8::Local<v8::Value> 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<v8::Object> obj = GetHandle()->ToObject();
|
||||
v8::Local<v8::Function> func = v8::Local<v8::Function>::Cast(obj);
|
||||
rv = GetString(v8::Handle<v8::String>::Cast(func->GetName()));
|
||||
GetCefString(v8::Handle<v8::String>::Cast(func->GetName()), rv);
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
@ -963,7 +1031,7 @@ bool CefV8ValueImpl::ExecuteFunctionWithContext(
|
|||
v8::TryCatch try_catch;
|
||||
v8::Local<v8::Value> 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);
|
||||
|
||||
|
|
|
@ -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<CefV8Value> 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;
|
||||
}
|
||||
|
||||
|
|
|
@ -17,7 +17,8 @@
|
|||
// VIRTUAL METHODS - Body may be edited by hand.
|
||||
|
||||
bool CefV8AccessorCToCpp::Get(const CefString& name,
|
||||
const CefRefPtr<CefV8Value> object, CefRefPtr<CefV8Value>& retval)
|
||||
const CefRefPtr<CefV8Value> object, CefRefPtr<CefV8Value>& 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<CefV8Value> object, const CefRefPtr<CefV8Value> value)
|
||||
const CefRefPtr<CefV8Value> object, const CefRefPtr<CefV8Value> 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;
|
||||
}
|
||||
|
|
|
@ -32,9 +32,9 @@ public:
|
|||
|
||||
// CefV8Accessor methods
|
||||
virtual bool Get(const CefString& name, const CefRefPtr<CefV8Value> object,
|
||||
CefRefPtr<CefV8Value>& retval) OVERRIDE;
|
||||
CefRefPtr<CefV8Value>& retval, CefString& exception) OVERRIDE;
|
||||
virtual bool Set(const CefString& name, const CefRefPtr<CefV8Value> object,
|
||||
const CefRefPtr<CefV8Value> value) OVERRIDE;
|
||||
const CefRefPtr<CefV8Value> value, CefString& exception) OVERRIDE;
|
||||
};
|
||||
|
||||
#endif // BUILDING_CEF_SHARED
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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<CefV8Value>& 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<CefBrowser> browser)
|
|||
"</pre></body></html>";
|
||||
browser->GetMainFrame()->LoadString(html, "about:blank");
|
||||
}
|
||||
|
||||
void RunExtensionPerfTest(CefRefPtr<CefBrowser> browser)
|
||||
{
|
||||
CefRefPtr<CefStreamReader> resourceStream;
|
||||
#if defined(OS_WIN)
|
||||
resourceStream = GetBinaryResourceReader(IDS_EXTENSIONPERF);
|
||||
#elif defined(OS_MACOSX)
|
||||
resourceStream = GetBinaryResourceReader("extensionperf.html");
|
||||
#endif
|
||||
browser->GetMainFrame()->LoadStream(resourceStream, "about:blank");
|
||||
}
|
||||
|
|
|
@ -12,5 +12,6 @@ void InitExtensionTest();
|
|||
|
||||
// Run the test.
|
||||
void RunExtensionTest(CefRefPtr<CefBrowser> browser);
|
||||
void RunExtensionPerfTest(CefRefPtr<CefBrowser> browser);
|
||||
|
||||
#endif // _CEFCLIENT_EXTENSION_TEST_H
|
||||
|
|
|
@ -0,0 +1,131 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>JavaScript Extension: Performance</title>
|
||||
<style>
|
||||
body { font-family: Tahoma, Serif; font-size: 9pt; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>JavaScript Extension: Performance</h1>
|
||||
|
||||
<div><span id="statusBox"></span> <progress id="progressBox" value="0" style="display:none"></progress></div>
|
||||
|
||||
<div style="padding-top:10px; padding-bottom:10px">
|
||||
<table id="resultTable" border="1" cellspacing="1" cellpadding="4" width="100%">
|
||||
<thead>
|
||||
<tr>
|
||||
<td>Name</td>
|
||||
<td>Min</td>
|
||||
<td>Avg</td>
|
||||
<td>Max</td>
|
||||
<td>Probes</td>
|
||||
</tr>
|
||||
</thead>
|
||||
<!-- result rows here -->
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<script type="text/javascript">
|
||||
(function () {
|
||||
var asyncExecution = true;
|
||||
var testIterations = 100000;
|
||||
var totalProbes = 10;
|
||||
var probeDelay = 0;
|
||||
|
||||
var collectProbes = false;
|
||||
|
||||
function dummyCallTest() {
|
||||
for (var i = 0; i < testIterations; i++) {
|
||||
cef.test.dummy();
|
||||
}
|
||||
}
|
||||
|
||||
function execTestFunc(func) {
|
||||
var begin = new Date();
|
||||
func();
|
||||
var end = new Date();
|
||||
return (end - begin);
|
||||
}
|
||||
|
||||
function execTest(test) {
|
||||
function nextStep() {
|
||||
if (asyncExecution) {
|
||||
setTimeout(function () { execTest(test); }, probeDelay);
|
||||
} else {
|
||||
execTest(test);
|
||||
}
|
||||
}
|
||||
|
||||
function nextTest() {
|
||||
appendResult(test);
|
||||
// ...
|
||||
}
|
||||
|
||||
updateStatus(test);
|
||||
if (!test.warmedUp) {
|
||||
execTestFunc(test.func);
|
||||
test.warmedUp = true;
|
||||
return nextStep();
|
||||
}
|
||||
|
||||
if (test.probe >= test.totalProbes) {
|
||||
test.avg = test.total / test.totalProbes;
|
||||
return nextTest();
|
||||
}
|
||||
|
||||
var elapsed = execTestFunc(test.func);
|
||||
test.total += elapsed;
|
||||
if (!test.min) test.min = elapsed;
|
||||
else if (test.min > elapsed) test.min = elapsed;
|
||||
if (!test.max) test.max = elapsed;
|
||||
else if (test.max < elapsed) test.max = elapsed;
|
||||
if (collectProbes) {
|
||||
test.results.push(elapsed);
|
||||
}
|
||||
test.probe++;
|
||||
|
||||
return nextStep();
|
||||
}
|
||||
|
||||
function updateStatus(test) {
|
||||
var statusBox = document.getElementById("statusBox");
|
||||
var progressBox = document.getElementById("progressBox");
|
||||
|
||||
if (test.probe >= test.totalProbes) {
|
||||
statusBox.innerText = test.name + " completed.";
|
||||
progressBox.style.display = 'none';
|
||||
} else {
|
||||
statusBox.innerText = test.name + " (" + test.probe + "/" + test.totalProbes + ")";
|
||||
progressBox.value = (test.probe / test.totalProbes);
|
||||
progressBox.style.display = 'inline';
|
||||
}
|
||||
}
|
||||
|
||||
function appendResult(test) {
|
||||
var e = document.getElementById("resultTable");
|
||||
|
||||
e.insertAdjacentHTML("beforeEnd",
|
||||
["<tr>",
|
||||
"<td>", test.name, "</td>",
|
||||
"<td>", test.min, "ms</td>",
|
||||
"<td>", test.avg, "ms</td>",
|
||||
"<td>", test.max, "ms</td>",
|
||||
"<td>", test.results.join(", "), "</td>",
|
||||
"<tr>"
|
||||
].join("")
|
||||
);
|
||||
}
|
||||
|
||||
function runTest(name, func) {
|
||||
var test = { name: name, func: func, warmedUp: false, total: 0, totalProbes: totalProbes, probe: 0, results: [] };
|
||||
setTimeout(function () { execTest(test); }, 10);
|
||||
}
|
||||
|
||||
runTest("dummyCall", dummyCallTest);
|
||||
|
||||
})();
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -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_
|
||||
|
|
|
@ -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<CefStreamReader> GetBinaryResourceReader(int binaryId);
|
||||
|
|
|
@ -396,11 +396,15 @@ public:
|
|||
CefRefPtr<CefV8Value>& retval,
|
||||
CefString& exception) = 0;
|
||||
|
||||
virtual bool Get(const CefString& name, const CefRefPtr<CefV8Value> object,
|
||||
CefRefPtr<CefV8Value>& retval) = 0;
|
||||
virtual bool Get(const CefString& name,
|
||||
const CefRefPtr<CefV8Value> object,
|
||||
CefRefPtr<CefV8Value>& retval,
|
||||
CefString& exception) = 0;
|
||||
|
||||
virtual bool Set(const CefString& name, const CefRefPtr<CefV8Value> object,
|
||||
const CefRefPtr<CefV8Value> value) = 0;
|
||||
virtual bool Set(const CefString& name,
|
||||
const CefRefPtr<CefV8Value> object,
|
||||
const CefRefPtr<CefV8Value> value,
|
||||
CefString& exception) = 0;
|
||||
};
|
||||
|
||||
class DelegatingV8Handler : public CefV8Handler
|
||||
|
@ -417,7 +421,7 @@ public:
|
|||
CefRefPtr<CefV8Value> object,
|
||||
const CefV8ValueList& arguments,
|
||||
CefRefPtr<CefV8Value>& 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<CefV8Value> object,
|
||||
CefRefPtr<CefV8Value>& retval)
|
||||
bool Get(const CefString& name,
|
||||
const CefRefPtr<CefV8Value> object,
|
||||
CefRefPtr<CefV8Value>& retval,
|
||||
CefString& exception) OVERRIDE
|
||||
{
|
||||
return delegate_->Get(name, object, retval);
|
||||
return delegate_->Get(name, object, retval, exception);
|
||||
}
|
||||
|
||||
bool Set(const CefString& name, const CefRefPtr<CefV8Value> object,
|
||||
const CefRefPtr<CefV8Value> value)
|
||||
bool Set(const CefString& name,
|
||||
const CefRefPtr<CefV8Value> object,
|
||||
const CefRefPtr<CefV8Value> 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<CefV8Handler> funcHandler(new DelegatingV8Handler(this));
|
||||
CefRefPtr<CefV8Value> helloFunc =
|
||||
CefV8Value::CreateFunction("hello", funcHandler);
|
||||
CefV8Value::CreateFunction("hello", funcHandler);
|
||||
object->SetValue("hello", helloFunc);
|
||||
|
||||
CefRefPtr<CefV8Value> fromIFrameFunc =
|
||||
CefV8Value::CreateFunction("fromIFrame", funcHandler);
|
||||
CefV8Value::CreateFunction("fromIFrame", funcHandler);
|
||||
object->SetValue("fromIFrame", fromIFrameFunc);
|
||||
|
||||
CefRefPtr<CefV8Value> goFunc =
|
||||
CefV8Value::CreateFunction("begin", funcHandler);
|
||||
CefV8Value::CreateFunction("begin", funcHandler);
|
||||
object->SetValue("begin", goFunc);
|
||||
|
||||
CefRefPtr<CefV8Value> doneFunc =
|
||||
CefV8Value::CreateFunction("end", funcHandler);
|
||||
CefV8Value::CreateFunction("end", funcHandler);
|
||||
object->SetValue("end", doneFunc);
|
||||
|
||||
CefRefPtr<CefV8Value> compFunc =
|
||||
CefV8Value::CreateFunction("comp", funcHandler);
|
||||
CefV8Value::CreateFunction("comp", funcHandler);
|
||||
object->SetValue("comp", compFunc);
|
||||
|
||||
// Used for testing exceptions returned from accessors.
|
||||
CefRefPtr<CefV8Value> gotGetExceptionFunc =
|
||||
CefV8Value::CreateFunction("gotGetException", funcHandler);
|
||||
object->SetValue("gotGetException", gotGetExceptionFunc);
|
||||
CefRefPtr<CefV8Value> gotSetExceptionFunc =
|
||||
CefV8Value::CreateFunction("gotSetException", funcHandler);
|
||||
object->SetValue("gotSetException", gotSetExceptionFunc);
|
||||
|
||||
// Create an object with accessor based properties:
|
||||
CefRefPtr<CefBase> blankBase;
|
||||
CefRefPtr<CefV8Accessor> 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<CefV8Value> 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<CefV8Value> object,
|
||||
const CefV8ValueList& arguments,
|
||||
CefRefPtr<CefV8Value>& retval,
|
||||
CefString& exception)
|
||||
CefString& exception) OVERRIDE
|
||||
{
|
||||
CefRefPtr<CefV8Context> cc = CefV8Context::GetCurrentContext();
|
||||
CefRefPtr<CefV8Context> 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<CefV8Value> object,
|
||||
CefRefPtr<CefV8Value>& retval)
|
||||
bool Get(const CefString& name,
|
||||
const CefRefPtr<CefV8Value> object,
|
||||
CefRefPtr<CefV8Value>& 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<CefV8Value> object,
|
||||
const CefRefPtr<CefV8Value> value)
|
||||
bool Set(const CefString& name,
|
||||
const CefRefPtr<CefV8Value> object,
|
||||
const CefRefPtr<CefV8Value> 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_);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue