mirror of
https://bitbucket.org/chromiumembedded/cef
synced 2025-04-13 18:32:07 +02:00
Reduce persistent CEF V8 memory usage by tracking objects on a per-context basis and not persisting objects when the underlying V8 handle is unused (issue #484).
git-svn-id: https://chromiumembedded.googlecode.com/svn/trunk@884 5089003a-bbd8-11dd-ad1f-f1f9622dbc98
This commit is contained in:
parent
59fe4fbab3
commit
f4e653adca
@ -39,7 +39,7 @@ static const char kCefContextState[] = "Cef::ContextState";
|
|||||||
|
|
||||||
// Memory manager.
|
// Memory manager.
|
||||||
|
|
||||||
class CefV8TrackManager : public CefTrackManager {
|
class CefV8TrackManager {
|
||||||
public:
|
public:
|
||||||
CefV8TrackManager()
|
CefV8TrackManager()
|
||||||
: context_safety_impl_(IMPL_HASH) {
|
: context_safety_impl_(IMPL_HASH) {
|
||||||
@ -128,6 +128,14 @@ class CefV8TrackManager : public CefTrackManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AddGlobalTrackObject(CefTrackNode* object) {
|
||||||
|
global_manager_.Add(object);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DeleteGlobalTrackObject(CefTrackNode* object) {
|
||||||
|
global_manager_.Delete(object);
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum ContextSafetyImpl {
|
enum ContextSafetyImpl {
|
||||||
IMPL_DISABLED,
|
IMPL_DISABLED,
|
||||||
@ -142,6 +150,10 @@ class CefV8TrackManager : public CefTrackManager {
|
|||||||
|
|
||||||
// Used with IMPL_VALUE.
|
// Used with IMPL_VALUE.
|
||||||
v8::Persistent<v8::String> context_state_key_;
|
v8::Persistent<v8::String> context_state_key_;
|
||||||
|
|
||||||
|
// Used for globally tracked objects that are not associated with a particular
|
||||||
|
// context.
|
||||||
|
CefTrackManager global_manager_;
|
||||||
};
|
};
|
||||||
|
|
||||||
base::LazyInstance<CefV8TrackManager> g_v8_tracker = LAZY_INSTANCE_INITIALIZER;
|
base::LazyInstance<CefV8TrackManager> g_v8_tracker = LAZY_INSTANCE_INITIALIZER;
|
||||||
@ -150,10 +162,12 @@ class V8TrackObject : public CefTrackNode {
|
|||||||
public:
|
public:
|
||||||
V8TrackObject()
|
V8TrackObject()
|
||||||
: external_memory_(0) {
|
: external_memory_(0) {
|
||||||
|
v8::V8::AdjustAmountOfExternalAllocatedMemory(
|
||||||
|
static_cast<int>(sizeof(V8TrackObject)));
|
||||||
}
|
}
|
||||||
~V8TrackObject() {
|
~V8TrackObject() {
|
||||||
if (external_memory_ != 0)
|
v8::V8::AdjustAmountOfExternalAllocatedMemory(
|
||||||
v8::V8::AdjustAmountOfExternalAllocatedMemory(-external_memory_);
|
-static_cast<int>(sizeof(V8TrackObject)) - external_memory_);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline int GetExternallyAllocatedMemory() {
|
inline int GetExternallyAllocatedMemory() {
|
||||||
@ -231,18 +245,56 @@ class V8TrackString : public CefTrackNode {
|
|||||||
std::string string_;
|
std::string string_;
|
||||||
};
|
};
|
||||||
|
|
||||||
void TrackAdd(CefTrackNode* object) {
|
|
||||||
g_v8_tracker.Pointer()->Add(object);
|
|
||||||
}
|
|
||||||
|
|
||||||
void TrackDelete(CefTrackNode* object) {
|
// Manages the life span of a CefTrackNode associated with a persistent Object
|
||||||
g_v8_tracker.Pointer()->Delete(object);
|
// or Function.
|
||||||
}
|
class CefV8MakeWeakParam {
|
||||||
|
public:
|
||||||
|
CefV8MakeWeakParam(scoped_refptr<CefV8ContextState> context_state,
|
||||||
|
CefTrackNode* object)
|
||||||
|
: context_state_(context_state),
|
||||||
|
object_(object) {
|
||||||
|
DCHECK(object_);
|
||||||
|
|
||||||
|
v8::V8::AdjustAmountOfExternalAllocatedMemory(
|
||||||
|
static_cast<int>(sizeof(CefV8MakeWeakParam)));
|
||||||
|
|
||||||
|
if (context_state_.get()) {
|
||||||
|
// |object_| will be deleted when:
|
||||||
|
// A. The associated context is released, or
|
||||||
|
// B. TrackDestructor is called for the weak handle.
|
||||||
|
DCHECK(context_state_->IsValid());
|
||||||
|
context_state_->AddTrackObject(object_);
|
||||||
|
} else {
|
||||||
|
// |object_| will be deleted when:
|
||||||
|
// A. The process shuts down, or
|
||||||
|
// B. TrackDestructor is called for the weak handle.
|
||||||
|
g_v8_tracker.Pointer()->AddGlobalTrackObject(object_);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
~CefV8MakeWeakParam() {
|
||||||
|
if (context_state_.get()) {
|
||||||
|
// If the associated context is still valid then delete |object_|.
|
||||||
|
// Otherwise, |object_| will already have been deleted.
|
||||||
|
if (context_state_->IsValid())
|
||||||
|
context_state_->DeleteTrackObject(object_);
|
||||||
|
} else {
|
||||||
|
g_v8_tracker.Pointer()->DeleteGlobalTrackObject(object_);
|
||||||
|
}
|
||||||
|
|
||||||
|
v8::V8::AdjustAmountOfExternalAllocatedMemory(
|
||||||
|
-static_cast<int>(sizeof(CefV8MakeWeakParam)));
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
scoped_refptr<CefV8ContextState> context_state_;
|
||||||
|
CefTrackNode* object_;
|
||||||
|
};
|
||||||
|
|
||||||
// Callback for weak persistent reference destruction.
|
// Callback for weak persistent reference destruction.
|
||||||
void TrackDestructor(v8::Persistent<v8::Value> object, void* parameter) {
|
void TrackDestructor(v8::Persistent<v8::Value> object, void* parameter) {
|
||||||
if (parameter)
|
if (parameter)
|
||||||
TrackDelete(static_cast<CefTrackNode*>(parameter));
|
delete static_cast<CefV8MakeWeakParam*>(parameter);
|
||||||
|
|
||||||
object.Dispose();
|
object.Dispose();
|
||||||
object.Clear();
|
object.Clear();
|
||||||
@ -346,7 +398,7 @@ v8::Handle<v8::Value> FunctionCallbackImpl(const v8::Arguments& args) {
|
|||||||
} else {
|
} else {
|
||||||
CefV8ValueImpl* rv = static_cast<CefV8ValueImpl*>(retval.get());
|
CefV8ValueImpl* rv = static_cast<CefV8ValueImpl*>(retval.get());
|
||||||
if (rv)
|
if (rv)
|
||||||
return rv->GetHandle();
|
return rv->GetHandle(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -380,7 +432,7 @@ v8::Handle<v8::Value> AccessorGetterCallbackImpl(v8::Local<v8::String> property,
|
|||||||
} else {
|
} else {
|
||||||
CefV8ValueImpl* rv = static_cast<CefV8ValueImpl*>(retval.get());
|
CefV8ValueImpl* rv = static_cast<CefV8ValueImpl*>(retval.get());
|
||||||
if (rv)
|
if (rv)
|
||||||
return rv->GetHandle();
|
return rv->GetHandle(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -428,7 +480,7 @@ class ExtensionWrapper : public v8::Extension {
|
|||||||
// The reference will be released when the process exits.
|
// The reference will be released when the process exits.
|
||||||
V8TrackObject* object = new V8TrackObject;
|
V8TrackObject* object = new V8TrackObject;
|
||||||
object->SetHandler(handler);
|
object->SetHandler(handler);
|
||||||
TrackAdd(object);
|
g_v8_tracker.Pointer()->AddGlobalTrackObject(object);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -507,9 +559,9 @@ bool CefRegisterExtension(const CefString& extension_name,
|
|||||||
CEF_REQUIRE_RT_RETURN(false);
|
CEF_REQUIRE_RT_RETURN(false);
|
||||||
|
|
||||||
V8TrackString* name = new V8TrackString(extension_name);
|
V8TrackString* name = new V8TrackString(extension_name);
|
||||||
TrackAdd(name);
|
g_v8_tracker.Pointer()->AddGlobalTrackObject(name);
|
||||||
V8TrackString* code = new V8TrackString(javascript_code);
|
V8TrackString* code = new V8TrackString(javascript_code);
|
||||||
TrackAdd(code);
|
g_v8_tracker.Pointer()->AddGlobalTrackObject(code);
|
||||||
|
|
||||||
ExtensionWrapper* wrapper = new ExtensionWrapper(name->GetString(),
|
ExtensionWrapper* wrapper = new ExtensionWrapper(name->GetString(),
|
||||||
code->GetString(), handler.get());
|
code->GetString(), handler.get());
|
||||||
@ -567,21 +619,21 @@ bool CefV8Context::InContext() {
|
|||||||
|
|
||||||
#define CEF_V8_REQUIRE_OBJECT_RETURN(ret) \
|
#define CEF_V8_REQUIRE_OBJECT_RETURN(ret) \
|
||||||
CEF_V8_REQUIRE_VALID_RETURN(ret); \
|
CEF_V8_REQUIRE_VALID_RETURN(ret); \
|
||||||
if (!GetHandle()->IsObject()) { \
|
if (!GetHandle(false)->IsObject()) { \
|
||||||
NOTREACHED() << "V8 value is not an object"; \
|
NOTREACHED() << "V8 value is not an object"; \
|
||||||
return ret; \
|
return ret; \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define CEF_V8_REQUIRE_ARRAY_RETURN(ret) \
|
#define CEF_V8_REQUIRE_ARRAY_RETURN(ret) \
|
||||||
CEF_V8_REQUIRE_VALID_RETURN(ret); \
|
CEF_V8_REQUIRE_VALID_RETURN(ret); \
|
||||||
if (!GetHandle()->IsArray()) { \
|
if (!GetHandle(false)->IsArray()) { \
|
||||||
NOTREACHED() << "V8 value is not an array"; \
|
NOTREACHED() << "V8 value is not an array"; \
|
||||||
return ret; \
|
return ret; \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define CEF_V8_REQUIRE_FUNCTION_RETURN(ret) \
|
#define CEF_V8_REQUIRE_FUNCTION_RETURN(ret) \
|
||||||
CEF_V8_REQUIRE_VALID_RETURN(ret); \
|
CEF_V8_REQUIRE_VALID_RETURN(ret); \
|
||||||
if (!GetHandle()->IsFunction()) { \
|
if (!GetHandle(false)->IsFunction()) { \
|
||||||
NOTREACHED() << "V8 value is not a function"; \
|
NOTREACHED() << "V8 value is not a function"; \
|
||||||
return ret; \
|
return ret; \
|
||||||
}
|
}
|
||||||
@ -743,12 +795,21 @@ WebKit::WebFrame* CefV8ContextImpl::GetWebFrame() {
|
|||||||
// CefV8ValueImpl::Handle
|
// CefV8ValueImpl::Handle
|
||||||
|
|
||||||
CefV8ValueImpl::Handle::~Handle() {
|
CefV8ValueImpl::Handle::~Handle() {
|
||||||
if (tracker_) {
|
// Persist the |tracker_| object (call MakeWeak) if:
|
||||||
TrackAdd(tracker_);
|
// A. The value represents an Object or Function, and
|
||||||
handle_.MakeWeak(tracker_, TrackDestructor);
|
// B. The handle has been passed into a V8 function or used as a return value
|
||||||
|
// from a V8 callback, and
|
||||||
|
// C. The associated context, if any, is still valid.
|
||||||
|
if (tracker_ && tracker_should_persist_ &&
|
||||||
|
(!context_state_.get() || context_state_->IsValid())) {
|
||||||
|
handle_.MakeWeak(new CefV8MakeWeakParam(context_state_, tracker_),
|
||||||
|
TrackDestructor);
|
||||||
} else {
|
} else {
|
||||||
handle_.Dispose();
|
handle_.Dispose();
|
||||||
handle_.Clear();
|
handle_.Clear();
|
||||||
|
|
||||||
|
if (tracker_)
|
||||||
|
delete tracker_;
|
||||||
}
|
}
|
||||||
tracker_ = NULL;
|
tracker_ = NULL;
|
||||||
}
|
}
|
||||||
@ -935,68 +996,68 @@ bool CefV8ValueImpl::IsValid() {
|
|||||||
bool CefV8ValueImpl::IsUndefined() {
|
bool CefV8ValueImpl::IsUndefined() {
|
||||||
CEF_REQUIRE_RT_RETURN(false);
|
CEF_REQUIRE_RT_RETURN(false);
|
||||||
CEF_V8_REQUIRE_VALID_RETURN(false);
|
CEF_V8_REQUIRE_VALID_RETURN(false);
|
||||||
return GetHandle()->IsUndefined();
|
return GetHandle(false)->IsUndefined();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CefV8ValueImpl::IsNull() {
|
bool CefV8ValueImpl::IsNull() {
|
||||||
CEF_REQUIRE_RT_RETURN(false);
|
CEF_REQUIRE_RT_RETURN(false);
|
||||||
CEF_V8_REQUIRE_VALID_RETURN(false);
|
CEF_V8_REQUIRE_VALID_RETURN(false);
|
||||||
return GetHandle()->IsNull();
|
return GetHandle(false)->IsNull();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CefV8ValueImpl::IsBool() {
|
bool CefV8ValueImpl::IsBool() {
|
||||||
CEF_REQUIRE_RT_RETURN(false);
|
CEF_REQUIRE_RT_RETURN(false);
|
||||||
CEF_V8_REQUIRE_VALID_RETURN(false);
|
CEF_V8_REQUIRE_VALID_RETURN(false);
|
||||||
return (GetHandle()->IsBoolean() || GetHandle()->IsTrue()
|
return (GetHandle(false)->IsBoolean() || GetHandle(false)->IsTrue() ||
|
||||||
|| GetHandle()->IsFalse());
|
GetHandle(false)->IsFalse());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CefV8ValueImpl::IsInt() {
|
bool CefV8ValueImpl::IsInt() {
|
||||||
CEF_REQUIRE_RT_RETURN(false);
|
CEF_REQUIRE_RT_RETURN(false);
|
||||||
CEF_V8_REQUIRE_VALID_RETURN(false);
|
CEF_V8_REQUIRE_VALID_RETURN(false);
|
||||||
return GetHandle()->IsInt32();
|
return GetHandle(false)->IsInt32();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CefV8ValueImpl::IsUInt() {
|
bool CefV8ValueImpl::IsUInt() {
|
||||||
CEF_REQUIRE_RT_RETURN(false);
|
CEF_REQUIRE_RT_RETURN(false);
|
||||||
CEF_V8_REQUIRE_VALID_RETURN(false);
|
CEF_V8_REQUIRE_VALID_RETURN(false);
|
||||||
return GetHandle()->IsUint32();
|
return GetHandle(false)->IsUint32();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CefV8ValueImpl::IsDouble() {
|
bool CefV8ValueImpl::IsDouble() {
|
||||||
CEF_REQUIRE_RT_RETURN(false);
|
CEF_REQUIRE_RT_RETURN(false);
|
||||||
CEF_V8_REQUIRE_VALID_RETURN(false);
|
CEF_V8_REQUIRE_VALID_RETURN(false);
|
||||||
return GetHandle()->IsNumber();
|
return GetHandle(false)->IsNumber();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CefV8ValueImpl::IsDate() {
|
bool CefV8ValueImpl::IsDate() {
|
||||||
CEF_REQUIRE_RT_RETURN(false);
|
CEF_REQUIRE_RT_RETURN(false);
|
||||||
CEF_V8_REQUIRE_VALID_RETURN(false);
|
CEF_V8_REQUIRE_VALID_RETURN(false);
|
||||||
return GetHandle()->IsDate();
|
return GetHandle(false)->IsDate();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CefV8ValueImpl::IsString() {
|
bool CefV8ValueImpl::IsString() {
|
||||||
CEF_REQUIRE_RT_RETURN(false);
|
CEF_REQUIRE_RT_RETURN(false);
|
||||||
CEF_V8_REQUIRE_VALID_RETURN(false);
|
CEF_V8_REQUIRE_VALID_RETURN(false);
|
||||||
return GetHandle()->IsString();
|
return GetHandle(false)->IsString();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CefV8ValueImpl::IsObject() {
|
bool CefV8ValueImpl::IsObject() {
|
||||||
CEF_REQUIRE_RT_RETURN(false);
|
CEF_REQUIRE_RT_RETURN(false);
|
||||||
CEF_V8_REQUIRE_VALID_RETURN(false);
|
CEF_V8_REQUIRE_VALID_RETURN(false);
|
||||||
return GetHandle()->IsObject();
|
return GetHandle(false)->IsObject();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CefV8ValueImpl::IsArray() {
|
bool CefV8ValueImpl::IsArray() {
|
||||||
CEF_REQUIRE_RT_RETURN(false);
|
CEF_REQUIRE_RT_RETURN(false);
|
||||||
CEF_V8_REQUIRE_VALID_RETURN(false);
|
CEF_V8_REQUIRE_VALID_RETURN(false);
|
||||||
return GetHandle()->IsArray();
|
return GetHandle(false)->IsArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CefV8ValueImpl::IsFunction() {
|
bool CefV8ValueImpl::IsFunction() {
|
||||||
CEF_REQUIRE_RT_RETURN(false);
|
CEF_REQUIRE_RT_RETURN(false);
|
||||||
CEF_V8_REQUIRE_VALID_RETURN(false);
|
CEF_V8_REQUIRE_VALID_RETURN(false);
|
||||||
return GetHandle()->IsFunction();
|
return GetHandle(false)->IsFunction();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CefV8ValueImpl::IsSame(CefRefPtr<CefV8Value> that) {
|
bool CefV8ValueImpl::IsSame(CefRefPtr<CefV8Value> that) {
|
||||||
@ -1006,11 +1067,11 @@ bool CefV8ValueImpl::IsSame(CefRefPtr<CefV8Value> that) {
|
|||||||
v8::HandleScope handle_scope;
|
v8::HandleScope handle_scope;
|
||||||
|
|
||||||
v8::Handle<v8::Value> thatHandle;
|
v8::Handle<v8::Value> thatHandle;
|
||||||
v8::Handle<v8::Value> thisHandle = GetHandle();
|
v8::Handle<v8::Value> thisHandle = GetHandle(false);
|
||||||
|
|
||||||
CefV8ValueImpl* impl = static_cast<CefV8ValueImpl*>(that.get());
|
CefV8ValueImpl* impl = static_cast<CefV8ValueImpl*>(that.get());
|
||||||
if (impl)
|
if (impl)
|
||||||
thatHandle = impl->GetHandle();
|
thatHandle = impl->GetHandle(false);
|
||||||
|
|
||||||
return (thisHandle == thatHandle);
|
return (thisHandle == thatHandle);
|
||||||
}
|
}
|
||||||
@ -1018,13 +1079,13 @@ bool CefV8ValueImpl::IsSame(CefRefPtr<CefV8Value> that) {
|
|||||||
bool CefV8ValueImpl::GetBoolValue() {
|
bool CefV8ValueImpl::GetBoolValue() {
|
||||||
CEF_REQUIRE_RT_RETURN(false);
|
CEF_REQUIRE_RT_RETURN(false);
|
||||||
CEF_V8_REQUIRE_VALID_RETURN(false);
|
CEF_V8_REQUIRE_VALID_RETURN(false);
|
||||||
if (GetHandle()->IsTrue()) {
|
if (GetHandle(false)->IsTrue()) {
|
||||||
return true;
|
return true;
|
||||||
} else if (GetHandle()->IsFalse()) {
|
} else if (GetHandle(false)->IsFalse()) {
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
v8::HandleScope handle_scope;
|
v8::HandleScope handle_scope;
|
||||||
v8::Local<v8::Boolean> val = GetHandle()->ToBoolean();
|
v8::Local<v8::Boolean> val = GetHandle(false)->ToBoolean();
|
||||||
return val->Value();
|
return val->Value();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1033,7 +1094,7 @@ int32 CefV8ValueImpl::GetIntValue() {
|
|||||||
CEF_REQUIRE_RT_RETURN(0);
|
CEF_REQUIRE_RT_RETURN(0);
|
||||||
CEF_V8_REQUIRE_VALID_RETURN(0);
|
CEF_V8_REQUIRE_VALID_RETURN(0);
|
||||||
v8::HandleScope handle_scope;
|
v8::HandleScope handle_scope;
|
||||||
v8::Local<v8::Int32> val = GetHandle()->ToInt32();
|
v8::Local<v8::Int32> val = GetHandle(false)->ToInt32();
|
||||||
return val->Value();
|
return val->Value();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1041,7 +1102,7 @@ uint32 CefV8ValueImpl::GetUIntValue() {
|
|||||||
CEF_REQUIRE_RT_RETURN(0);
|
CEF_REQUIRE_RT_RETURN(0);
|
||||||
CEF_V8_REQUIRE_VALID_RETURN(0);
|
CEF_V8_REQUIRE_VALID_RETURN(0);
|
||||||
v8::HandleScope handle_scope;
|
v8::HandleScope handle_scope;
|
||||||
v8::Local<v8::Uint32> val = GetHandle()->ToUint32();
|
v8::Local<v8::Uint32> val = GetHandle(false)->ToUint32();
|
||||||
return val->Value();
|
return val->Value();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1049,7 +1110,7 @@ double CefV8ValueImpl::GetDoubleValue() {
|
|||||||
CEF_REQUIRE_RT_RETURN(0.);
|
CEF_REQUIRE_RT_RETURN(0.);
|
||||||
CEF_V8_REQUIRE_VALID_RETURN(0.);
|
CEF_V8_REQUIRE_VALID_RETURN(0.);
|
||||||
v8::HandleScope handle_scope;
|
v8::HandleScope handle_scope;
|
||||||
v8::Local<v8::Number> val = GetHandle()->ToNumber();
|
v8::Local<v8::Number> val = GetHandle(false)->ToNumber();
|
||||||
return val->Value();
|
return val->Value();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1057,7 +1118,7 @@ CefTime CefV8ValueImpl::GetDateValue() {
|
|||||||
CEF_REQUIRE_RT_RETURN(CefTime(0.));
|
CEF_REQUIRE_RT_RETURN(CefTime(0.));
|
||||||
CEF_V8_REQUIRE_VALID_RETURN(CefTime(0.));
|
CEF_V8_REQUIRE_VALID_RETURN(CefTime(0.));
|
||||||
v8::HandleScope handle_scope;
|
v8::HandleScope handle_scope;
|
||||||
v8::Local<v8::Number> val = GetHandle()->ToNumber();
|
v8::Local<v8::Number> val = GetHandle(false)->ToNumber();
|
||||||
// Convert from milliseconds to seconds.
|
// Convert from milliseconds to seconds.
|
||||||
return CefTime(val->Value() / 1000);
|
return CefTime(val->Value() / 1000);
|
||||||
}
|
}
|
||||||
@ -1067,7 +1128,7 @@ CefString CefV8ValueImpl::GetStringValue() {
|
|||||||
CEF_REQUIRE_RT_RETURN(rv);
|
CEF_REQUIRE_RT_RETURN(rv);
|
||||||
CEF_V8_REQUIRE_VALID_RETURN(rv);
|
CEF_V8_REQUIRE_VALID_RETURN(rv);
|
||||||
v8::HandleScope handle_scope;
|
v8::HandleScope handle_scope;
|
||||||
GetCefString(GetHandle()->ToString(), rv);
|
GetCefString(GetHandle(false)->ToString(), rv);
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1076,7 +1137,7 @@ bool CefV8ValueImpl::IsUserCreated() {
|
|||||||
CEF_V8_REQUIRE_OBJECT_RETURN(false);
|
CEF_V8_REQUIRE_OBJECT_RETURN(false);
|
||||||
|
|
||||||
v8::HandleScope handle_scope;
|
v8::HandleScope handle_scope;
|
||||||
v8::Local<v8::Object> obj = GetHandle()->ToObject();
|
v8::Local<v8::Object> obj = GetHandle(false)->ToObject();
|
||||||
|
|
||||||
V8TrackObject* tracker = V8TrackObject::Unwrap(obj);
|
V8TrackObject* tracker = V8TrackObject::Unwrap(obj);
|
||||||
return (tracker != NULL);
|
return (tracker != NULL);
|
||||||
@ -1124,7 +1185,7 @@ bool CefV8ValueImpl::HasValue(const CefString& key) {
|
|||||||
CEF_V8_REQUIRE_OBJECT_RETURN(false);
|
CEF_V8_REQUIRE_OBJECT_RETURN(false);
|
||||||
|
|
||||||
v8::HandleScope handle_scope;
|
v8::HandleScope handle_scope;
|
||||||
v8::Local<v8::Object> obj = GetHandle()->ToObject();
|
v8::Local<v8::Object> obj = GetHandle(false)->ToObject();
|
||||||
return obj->Has(GetV8String(key));
|
return obj->Has(GetV8String(key));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1138,7 +1199,7 @@ bool CefV8ValueImpl::HasValue(int index) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
v8::HandleScope handle_scope;
|
v8::HandleScope handle_scope;
|
||||||
v8::Local<v8::Object> obj = GetHandle()->ToObject();
|
v8::Local<v8::Object> obj = GetHandle(false)->ToObject();
|
||||||
return obj->Has(index);
|
return obj->Has(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1147,7 +1208,7 @@ bool CefV8ValueImpl::DeleteValue(const CefString& key) {
|
|||||||
CEF_V8_REQUIRE_OBJECT_RETURN(false);
|
CEF_V8_REQUIRE_OBJECT_RETURN(false);
|
||||||
|
|
||||||
v8::HandleScope handle_scope;
|
v8::HandleScope handle_scope;
|
||||||
v8::Local<v8::Object> obj = GetHandle()->ToObject();
|
v8::Local<v8::Object> obj = GetHandle(false)->ToObject();
|
||||||
|
|
||||||
v8::TryCatch try_catch;
|
v8::TryCatch try_catch;
|
||||||
try_catch.SetVerbose(true);
|
try_catch.SetVerbose(true);
|
||||||
@ -1165,7 +1226,7 @@ bool CefV8ValueImpl::DeleteValue(int index) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
v8::HandleScope handle_scope;
|
v8::HandleScope handle_scope;
|
||||||
v8::Local<v8::Object> obj = GetHandle()->ToObject();
|
v8::Local<v8::Object> obj = GetHandle(false)->ToObject();
|
||||||
|
|
||||||
v8::TryCatch try_catch;
|
v8::TryCatch try_catch;
|
||||||
try_catch.SetVerbose(true);
|
try_catch.SetVerbose(true);
|
||||||
@ -1178,7 +1239,7 @@ CefRefPtr<CefV8Value> CefV8ValueImpl::GetValue(const CefString& key) {
|
|||||||
CEF_V8_REQUIRE_OBJECT_RETURN(NULL);
|
CEF_V8_REQUIRE_OBJECT_RETURN(NULL);
|
||||||
|
|
||||||
v8::HandleScope handle_scope;
|
v8::HandleScope handle_scope;
|
||||||
v8::Local<v8::Object> obj = GetHandle()->ToObject();
|
v8::Local<v8::Object> obj = GetHandle(false)->ToObject();
|
||||||
|
|
||||||
v8::TryCatch try_catch;
|
v8::TryCatch try_catch;
|
||||||
try_catch.SetVerbose(true);
|
try_catch.SetVerbose(true);
|
||||||
@ -1198,7 +1259,7 @@ CefRefPtr<CefV8Value> CefV8ValueImpl::GetValue(int index) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
v8::HandleScope handle_scope;
|
v8::HandleScope handle_scope;
|
||||||
v8::Local<v8::Object> obj = GetHandle()->ToObject();
|
v8::Local<v8::Object> obj = GetHandle(false)->ToObject();
|
||||||
|
|
||||||
v8::TryCatch try_catch;
|
v8::TryCatch try_catch;
|
||||||
try_catch.SetVerbose(true);
|
try_catch.SetVerbose(true);
|
||||||
@ -1217,11 +1278,11 @@ bool CefV8ValueImpl::SetValue(const CefString& key,
|
|||||||
CefV8ValueImpl* impl = static_cast<CefV8ValueImpl*>(value.get());
|
CefV8ValueImpl* impl = static_cast<CefV8ValueImpl*>(value.get());
|
||||||
if (impl) {
|
if (impl) {
|
||||||
v8::HandleScope handle_scope;
|
v8::HandleScope handle_scope;
|
||||||
v8::Local<v8::Object> obj = GetHandle()->ToObject();
|
v8::Local<v8::Object> obj = GetHandle(false)->ToObject();
|
||||||
|
|
||||||
v8::TryCatch try_catch;
|
v8::TryCatch try_catch;
|
||||||
try_catch.SetVerbose(true);
|
try_catch.SetVerbose(true);
|
||||||
bool set = obj->Set(GetV8String(key), impl->GetHandle(),
|
bool set = obj->Set(GetV8String(key), impl->GetHandle(true),
|
||||||
static_cast<v8::PropertyAttribute>(attribute));
|
static_cast<v8::PropertyAttribute>(attribute));
|
||||||
return (!HasCaught(try_catch) && set);
|
return (!HasCaught(try_catch) && set);
|
||||||
} else {
|
} else {
|
||||||
@ -1242,11 +1303,11 @@ bool CefV8ValueImpl::SetValue(int index, CefRefPtr<CefV8Value> value) {
|
|||||||
CefV8ValueImpl* impl = static_cast<CefV8ValueImpl*>(value.get());
|
CefV8ValueImpl* impl = static_cast<CefV8ValueImpl*>(value.get());
|
||||||
if (impl) {
|
if (impl) {
|
||||||
v8::HandleScope handle_scope;
|
v8::HandleScope handle_scope;
|
||||||
v8::Local<v8::Object> obj = GetHandle()->ToObject();
|
v8::Local<v8::Object> obj = GetHandle(false)->ToObject();
|
||||||
|
|
||||||
v8::TryCatch try_catch;
|
v8::TryCatch try_catch;
|
||||||
try_catch.SetVerbose(true);
|
try_catch.SetVerbose(true);
|
||||||
bool set = obj->Set(index, impl->GetHandle());
|
bool set = obj->Set(index, impl->GetHandle(true));
|
||||||
return (!HasCaught(try_catch) && set);
|
return (!HasCaught(try_catch) && set);
|
||||||
} else {
|
} else {
|
||||||
NOTREACHED() << "invalid input parameter";
|
NOTREACHED() << "invalid input parameter";
|
||||||
@ -1260,7 +1321,7 @@ bool CefV8ValueImpl::SetValue(const CefString& key, AccessControl settings,
|
|||||||
CEF_V8_REQUIRE_OBJECT_RETURN(false);
|
CEF_V8_REQUIRE_OBJECT_RETURN(false);
|
||||||
|
|
||||||
v8::HandleScope handle_scope;
|
v8::HandleScope handle_scope;
|
||||||
v8::Local<v8::Object> obj = GetHandle()->ToObject();
|
v8::Local<v8::Object> obj = GetHandle(false)->ToObject();
|
||||||
|
|
||||||
CefRefPtr<CefV8Accessor> accessorPtr;
|
CefRefPtr<CefV8Accessor> accessorPtr;
|
||||||
|
|
||||||
@ -1289,7 +1350,7 @@ bool CefV8ValueImpl::GetKeys(std::vector<CefString>& keys) {
|
|||||||
CEF_V8_REQUIRE_OBJECT_RETURN(false);
|
CEF_V8_REQUIRE_OBJECT_RETURN(false);
|
||||||
|
|
||||||
v8::HandleScope handle_scope;
|
v8::HandleScope handle_scope;
|
||||||
v8::Local<v8::Object> obj = GetHandle()->ToObject();
|
v8::Local<v8::Object> obj = GetHandle(false)->ToObject();
|
||||||
v8::Local<v8::Array> arr_keys = obj->GetPropertyNames();
|
v8::Local<v8::Array> arr_keys = obj->GetPropertyNames();
|
||||||
uint32_t len = arr_keys->Length();
|
uint32_t len = arr_keys->Length();
|
||||||
for (uint32_t i = 0; i < len; ++i) {
|
for (uint32_t i = 0; i < len; ++i) {
|
||||||
@ -1306,7 +1367,7 @@ bool CefV8ValueImpl::SetUserData(CefRefPtr<CefBase> user_data) {
|
|||||||
CEF_V8_REQUIRE_OBJECT_RETURN(false);
|
CEF_V8_REQUIRE_OBJECT_RETURN(false);
|
||||||
|
|
||||||
v8::HandleScope handle_scope;
|
v8::HandleScope handle_scope;
|
||||||
v8::Local<v8::Object> obj = GetHandle()->ToObject();
|
v8::Local<v8::Object> obj = GetHandle(false)->ToObject();
|
||||||
|
|
||||||
V8TrackObject* tracker = V8TrackObject::Unwrap(obj);
|
V8TrackObject* tracker = V8TrackObject::Unwrap(obj);
|
||||||
if (tracker) {
|
if (tracker) {
|
||||||
@ -1322,7 +1383,7 @@ CefRefPtr<CefBase> CefV8ValueImpl::GetUserData() {
|
|||||||
CEF_V8_REQUIRE_OBJECT_RETURN(NULL);
|
CEF_V8_REQUIRE_OBJECT_RETURN(NULL);
|
||||||
|
|
||||||
v8::HandleScope handle_scope;
|
v8::HandleScope handle_scope;
|
||||||
v8::Local<v8::Object> obj = GetHandle()->ToObject();
|
v8::Local<v8::Object> obj = GetHandle(false)->ToObject();
|
||||||
|
|
||||||
V8TrackObject* tracker = V8TrackObject::Unwrap(obj);
|
V8TrackObject* tracker = V8TrackObject::Unwrap(obj);
|
||||||
if (tracker)
|
if (tracker)
|
||||||
@ -1336,7 +1397,7 @@ int CefV8ValueImpl::GetExternallyAllocatedMemory() {
|
|||||||
CEF_V8_REQUIRE_OBJECT_RETURN(0);
|
CEF_V8_REQUIRE_OBJECT_RETURN(0);
|
||||||
|
|
||||||
v8::HandleScope handle_scope;
|
v8::HandleScope handle_scope;
|
||||||
v8::Local<v8::Object> obj = GetHandle()->ToObject();
|
v8::Local<v8::Object> obj = GetHandle(false)->ToObject();
|
||||||
|
|
||||||
V8TrackObject* tracker = V8TrackObject::Unwrap(obj);
|
V8TrackObject* tracker = V8TrackObject::Unwrap(obj);
|
||||||
if (tracker)
|
if (tracker)
|
||||||
@ -1350,7 +1411,7 @@ int CefV8ValueImpl::AdjustExternallyAllocatedMemory(int change_in_bytes) {
|
|||||||
CEF_V8_REQUIRE_OBJECT_RETURN(0);
|
CEF_V8_REQUIRE_OBJECT_RETURN(0);
|
||||||
|
|
||||||
v8::HandleScope handle_scope;
|
v8::HandleScope handle_scope;
|
||||||
v8::Local<v8::Object> obj = GetHandle()->ToObject();
|
v8::Local<v8::Object> obj = GetHandle(false)->ToObject();
|
||||||
|
|
||||||
V8TrackObject* tracker = V8TrackObject::Unwrap(obj);
|
V8TrackObject* tracker = V8TrackObject::Unwrap(obj);
|
||||||
if (tracker)
|
if (tracker)
|
||||||
@ -1364,7 +1425,7 @@ int CefV8ValueImpl::GetArrayLength() {
|
|||||||
CEF_V8_REQUIRE_ARRAY_RETURN(0);
|
CEF_V8_REQUIRE_ARRAY_RETURN(0);
|
||||||
|
|
||||||
v8::HandleScope handle_scope;
|
v8::HandleScope handle_scope;
|
||||||
v8::Local<v8::Object> obj = GetHandle()->ToObject();
|
v8::Local<v8::Object> obj = GetHandle(false)->ToObject();
|
||||||
v8::Local<v8::Array> arr = v8::Local<v8::Array>::Cast(obj);
|
v8::Local<v8::Array> arr = v8::Local<v8::Array>::Cast(obj);
|
||||||
return arr->Length();
|
return arr->Length();
|
||||||
}
|
}
|
||||||
@ -1375,7 +1436,7 @@ CefString CefV8ValueImpl::GetFunctionName() {
|
|||||||
CEF_V8_REQUIRE_FUNCTION_RETURN(rv);
|
CEF_V8_REQUIRE_FUNCTION_RETURN(rv);
|
||||||
|
|
||||||
v8::HandleScope handle_scope;
|
v8::HandleScope handle_scope;
|
||||||
v8::Local<v8::Object> obj = GetHandle()->ToObject();
|
v8::Local<v8::Object> obj = GetHandle(false)->ToObject();
|
||||||
v8::Local<v8::Function> func = v8::Local<v8::Function>::Cast(obj);
|
v8::Local<v8::Function> func = v8::Local<v8::Function>::Cast(obj);
|
||||||
GetCefString(v8::Handle<v8::String>::Cast(func->GetName()), rv);
|
GetCefString(v8::Handle<v8::String>::Cast(func->GetName()), rv);
|
||||||
return rv;
|
return rv;
|
||||||
@ -1386,7 +1447,7 @@ CefRefPtr<CefV8Handler> CefV8ValueImpl::GetFunctionHandler() {
|
|||||||
CEF_V8_REQUIRE_FUNCTION_RETURN(NULL);
|
CEF_V8_REQUIRE_FUNCTION_RETURN(NULL);
|
||||||
|
|
||||||
v8::HandleScope handle_scope;
|
v8::HandleScope handle_scope;
|
||||||
v8::Local<v8::Object> obj = GetHandle()->ToObject();
|
v8::Local<v8::Object> obj = GetHandle(false)->ToObject();
|
||||||
|
|
||||||
V8TrackObject* tracker = V8TrackObject::Unwrap(obj);
|
V8TrackObject* tracker = V8TrackObject::Unwrap(obj);
|
||||||
if (tracker)
|
if (tracker)
|
||||||
@ -1423,14 +1484,14 @@ CefRefPtr<CefV8Value> CefV8ValueImpl::ExecuteFunctionWithContext(
|
|||||||
|
|
||||||
v8::Context::Scope context_scope(context_local);
|
v8::Context::Scope context_scope(context_local);
|
||||||
|
|
||||||
v8::Local<v8::Object> obj = GetHandle()->ToObject();
|
v8::Local<v8::Object> obj = GetHandle(false)->ToObject();
|
||||||
v8::Local<v8::Function> func = v8::Local<v8::Function>::Cast(obj);
|
v8::Local<v8::Function> func = v8::Local<v8::Function>::Cast(obj);
|
||||||
v8::Handle<v8::Object> recv;
|
v8::Handle<v8::Object> recv;
|
||||||
|
|
||||||
// Default to the global object if no object or a non-object was provided.
|
// Default to the global object if no object or a non-object was provided.
|
||||||
if (object.get() && object->IsObject()) {
|
if (object.get() && object->IsObject()) {
|
||||||
CefV8ValueImpl* recv_impl = static_cast<CefV8ValueImpl*>(object.get());
|
CefV8ValueImpl* recv_impl = static_cast<CefV8ValueImpl*>(object.get());
|
||||||
recv = v8::Handle<v8::Object>::Cast(recv_impl->GetHandle());
|
recv = v8::Handle<v8::Object>::Cast(recv_impl->GetHandle(true));
|
||||||
} else {
|
} else {
|
||||||
recv = context_local->Global();
|
recv = context_local->Global();
|
||||||
}
|
}
|
||||||
@ -1439,8 +1500,10 @@ CefRefPtr<CefV8Value> CefV8ValueImpl::ExecuteFunctionWithContext(
|
|||||||
v8::Handle<v8::Value> *argv = NULL;
|
v8::Handle<v8::Value> *argv = NULL;
|
||||||
if (argc > 0) {
|
if (argc > 0) {
|
||||||
argv = new v8::Handle<v8::Value>[argc];
|
argv = new v8::Handle<v8::Value>[argc];
|
||||||
for (int i = 0; i < argc; ++i)
|
for (int i = 0; i < argc; ++i) {
|
||||||
argv[i] = static_cast<CefV8ValueImpl*>(arguments[i].get())->GetHandle();
|
argv[i] =
|
||||||
|
static_cast<CefV8ValueImpl*>(arguments[i].get())->GetHandle(true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CefRefPtr<CefV8Value> retval;
|
CefRefPtr<CefV8Value> retval;
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "include/cef_v8.h"
|
#include "include/cef_v8.h"
|
||||||
|
#include "libcef/common/tracker.h"
|
||||||
#include "libcef/renderer/thread_util.h"
|
#include "libcef/renderer/thread_util.h"
|
||||||
|
|
||||||
#include "v8/include/v8.h"
|
#include "v8/include/v8.h"
|
||||||
@ -30,10 +31,25 @@ class CefV8ContextState : public base::RefCounted<CefV8ContextState> {
|
|||||||
virtual ~CefV8ContextState() {}
|
virtual ~CefV8ContextState() {}
|
||||||
|
|
||||||
bool IsValid() { return valid_; }
|
bool IsValid() { return valid_; }
|
||||||
void Detach() { valid_ = false; }
|
void Detach() {
|
||||||
|
DCHECK(valid_);
|
||||||
|
valid_ = false;
|
||||||
|
track_manager_.DeleteAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
void AddTrackObject(CefTrackNode* object) {
|
||||||
|
DCHECK(valid_);
|
||||||
|
track_manager_.Add(object);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DeleteTrackObject(CefTrackNode* object) {
|
||||||
|
DCHECK(valid_);
|
||||||
|
track_manager_.Delete(object);
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool valid_;
|
bool valid_;
|
||||||
|
CefTrackManager track_manager_;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Base class for V8 Handle types.
|
// Base class for V8 Handle types.
|
||||||
@ -54,7 +70,7 @@ class CefV8HandleBase :
|
|||||||
// context will be used.
|
// context will be used.
|
||||||
explicit CefV8HandleBase(v8::Handle<v8::Context> context);
|
explicit CefV8HandleBase(v8::Handle<v8::Context> context);
|
||||||
|
|
||||||
private:
|
protected:
|
||||||
scoped_refptr<CefV8ContextState> context_state_;
|
scoped_refptr<CefV8ContextState> context_state_;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -184,7 +200,9 @@ class CefV8ValueImpl : public CefV8Value {
|
|||||||
CefRefPtr<CefV8Value> object,
|
CefRefPtr<CefV8Value> object,
|
||||||
const CefV8ValueList& arguments) OVERRIDE;
|
const CefV8ValueList& arguments) OVERRIDE;
|
||||||
|
|
||||||
v8::Handle<v8::Value> GetHandle() { return handle_->GetHandle(); }
|
v8::Handle<v8::Value> GetHandle(bool should_persist) {
|
||||||
|
return handle_->GetHandle(should_persist);
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// Test for and record any exception.
|
// Test for and record any exception.
|
||||||
@ -198,12 +216,15 @@ class CefV8ValueImpl : public CefV8Value {
|
|||||||
Handle(v8::Handle<v8::Context> context, handleType v, CefTrackNode* tracker)
|
Handle(v8::Handle<v8::Context> context, handleType v, CefTrackNode* tracker)
|
||||||
: CefV8HandleBase(context),
|
: CefV8HandleBase(context),
|
||||||
handle_(persistentType::New(v)),
|
handle_(persistentType::New(v)),
|
||||||
tracker_(tracker) {
|
tracker_(tracker),
|
||||||
|
tracker_should_persist_(false) {
|
||||||
}
|
}
|
||||||
virtual ~Handle();
|
virtual ~Handle();
|
||||||
|
|
||||||
handleType GetHandle() {
|
handleType GetHandle(bool should_persist) {
|
||||||
DCHECK(IsValid());
|
DCHECK(IsValid());
|
||||||
|
if (should_persist && tracker_ && !tracker_should_persist_)
|
||||||
|
tracker_should_persist_ = true;
|
||||||
return handle_;
|
return handle_;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -214,6 +235,10 @@ class CefV8ValueImpl : public CefV8Value {
|
|||||||
// internal data or function handler objects that are reference counted.
|
// internal data or function handler objects that are reference counted.
|
||||||
CefTrackNode* tracker_;
|
CefTrackNode* tracker_;
|
||||||
|
|
||||||
|
// True if the |tracker_| object needs to persist due to an Object or
|
||||||
|
// Function type being passed into V8.
|
||||||
|
bool tracker_should_persist_;
|
||||||
|
|
||||||
DISALLOW_COPY_AND_ASSIGN(Handle);
|
DISALLOW_COPY_AND_ASSIGN(Handle);
|
||||||
};
|
};
|
||||||
scoped_refptr<Handle> handle_;
|
scoped_refptr<Handle> handle_;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user