mirror of
https://github.com/ONLYOFFICE/core.git
synced 2026-04-07 13:55:33 +08:00
[V8] Fix memory leaks with weak handles
This commit is contained in:
@ -220,6 +220,34 @@ namespace NSJSBase
|
|||||||
m_internal->m_context.Clear();
|
m_internal->m_context.Clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class WeakHandleVisitor : public v8::PersistentHandleVisitor
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
WeakHandleVisitor() = default;
|
||||||
|
|
||||||
|
public:
|
||||||
|
void VisitPersistentHandle(v8::Persistent<v8::Value>* value, uint16_t class_id) override
|
||||||
|
{
|
||||||
|
if (class_id == CJSEmbedObjectPrivate::kWeakHandleId)
|
||||||
|
{
|
||||||
|
v8::Isolate* isolate = v8::Isolate::GetCurrent();
|
||||||
|
v8::HandleScope scope(isolate);
|
||||||
|
v8::Local<v8::Object> handle = value->Get(isolate).As<v8::Object>();
|
||||||
|
v8::Local<v8::External> field = v8::Local<v8::External>::Cast(handle->GetInternalField(0));
|
||||||
|
CJSEmbedObject* native = static_cast<CJSEmbedObject*>(field->Value());
|
||||||
|
delete native;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
static WeakHandleVisitor* getInstance()
|
||||||
|
{
|
||||||
|
static WeakHandleVisitor visitor;
|
||||||
|
return &visitor;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
void CJSContext::Dispose()
|
void CJSContext::Dispose()
|
||||||
{
|
{
|
||||||
#ifdef V8_INSPECTOR
|
#ifdef V8_INSPECTOR
|
||||||
@ -228,7 +256,13 @@ namespace NSJSBase
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
m_internal->m_contextPersistent.Reset();
|
m_internal->m_contextPersistent.Reset();
|
||||||
m_internal->m_isolate->Dispose();
|
// destroy native object in the weak handles before isolate disposal
|
||||||
|
v8::Isolate* isolate = m_internal->m_isolate;
|
||||||
|
{
|
||||||
|
v8::Isolate::Scope scope(isolate);
|
||||||
|
isolate->VisitHandlesWithClassIds(WeakHandleVisitor::getInstance());
|
||||||
|
}
|
||||||
|
isolate->Dispose();
|
||||||
m_internal->m_isolate = NULL;
|
m_internal->m_isolate = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -900,6 +900,8 @@ namespace NSJSBase
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
v8::Persistent<v8::Object> handle;
|
v8::Persistent<v8::Object> handle;
|
||||||
|
// contstant id for all weak native handles
|
||||||
|
static const uint16_t kWeakHandleId = 1;
|
||||||
|
|
||||||
CJSEmbedObjectPrivate(v8::Local<v8::Object> obj)
|
CJSEmbedObjectPrivate(v8::Local<v8::Object> obj)
|
||||||
{
|
{
|
||||||
@ -918,6 +920,8 @@ namespace NSJSBase
|
|||||||
|
|
||||||
handle.Reset(CV8Worker::GetCurrent(), obj);
|
handle.Reset(CV8Worker::GetCurrent(), obj);
|
||||||
handle.SetWeak(pEmbedObject, EmbedObjectWeakCallback, v8::WeakCallbackType::kParameter);
|
handle.SetWeak(pEmbedObject, EmbedObjectWeakCallback, v8::WeakCallbackType::kParameter);
|
||||||
|
// set class_id for being able to iterate over all these handles to destroy them on isolate disposal
|
||||||
|
handle.SetWrapperClassId(kWeakHandleId);
|
||||||
|
|
||||||
pEmbedObject->embed_native_internal = this;
|
pEmbedObject->embed_native_internal = this;
|
||||||
}
|
}
|
||||||
@ -931,8 +935,6 @@ namespace NSJSBase
|
|||||||
|
|
||||||
static void EmbedObjectWeakCallback(const v8::WeakCallbackInfo<CJSEmbedObject>& data)
|
static void EmbedObjectWeakCallback(const v8::WeakCallbackInfo<CJSEmbedObject>& data)
|
||||||
{
|
{
|
||||||
v8::Isolate* isolate = data.GetIsolate();
|
|
||||||
v8::HandleScope scope(isolate);
|
|
||||||
CJSEmbedObject* wrap = data.GetParameter();
|
CJSEmbedObject* wrap = data.GetParameter();
|
||||||
((CJSEmbedObjectPrivate*)wrap->embed_native_internal)->handle.Reset();
|
((CJSEmbedObjectPrivate*)wrap->embed_native_internal)->handle.Reset();
|
||||||
delete wrap;
|
delete wrap;
|
||||||
|
|||||||
Reference in New Issue
Block a user