electron/atom/common/api/atom_api_v8_util.cc
Cheng Zhao 06cf0406fe Dereference remote objects with native code
Previously we rely on the v8util.setDestructor to dereference the remote
objects in JavaScript, however as documented in V8, it is forbidden to
call V8 APIs in object's destructor (e.g. the weak callback), and doing
so would result in crashs.

This commit removes the JavaScript setDestructor method, and avoids
doing the dereference work with V8.
2016-04-26 16:16:22 +09:00

74 lines
2.9 KiB
C++

// Copyright (c) 2013 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#include <string>
#include "atom/common/api/remote_callback_freer.h"
#include "atom/common/api/remote_object_freer.h"
#include "atom/common/native_mate_converters/content_converter.h"
#include "atom/common/node_includes.h"
#include "native_mate/dictionary.h"
#include "v8/include/v8-profiler.h"
namespace {
v8::Local<v8::Value> GetHiddenValue(v8::Isolate* isolate,
v8::Local<v8::Object> object,
v8::Local<v8::String> key) {
v8::Local<v8::Context> context = isolate->GetCurrentContext();
v8::Local<v8::Private> privateKey = v8::Private::ForApi(isolate, key);
v8::Local<v8::Value> value;
v8::Maybe<bool> result = object->HasPrivate(context, privateKey);
if (!(result.IsJust() && result.FromJust()))
return v8::Local<v8::Value>();
if (object->GetPrivate(context, privateKey).ToLocal(&value))
return value;
return v8::Local<v8::Value>();
}
void SetHiddenValue(v8::Isolate* isolate,
v8::Local<v8::Object> object,
v8::Local<v8::String> key,
v8::Local<v8::Value> value) {
if (value.IsEmpty())
return;
v8::Local<v8::Context> context = isolate->GetCurrentContext();
v8::Local<v8::Private> privateKey = v8::Private::ForApi(isolate, key);
object->SetPrivate(context, privateKey, value);
}
void DeleteHiddenValue(v8::Isolate* isolate,
v8::Local<v8::Object> object,
v8::Local<v8::String> key) {
v8::Local<v8::Context> context = isolate->GetCurrentContext();
v8::Local<v8::Private> privateKey = v8::Private::ForApi(isolate, key);
// Actually deleting the value would make force the object into
// dictionary mode which is unnecessarily slow. Instead, we replace
// the hidden value with "undefined".
object->SetPrivate(context, privateKey, v8::Undefined(isolate));
}
int32_t GetObjectHash(v8::Local<v8::Object> object) {
return object->GetIdentityHash();
}
void TakeHeapSnapshot(v8::Isolate* isolate) {
isolate->GetHeapProfiler()->TakeHeapSnapshot();
}
void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused,
v8::Local<v8::Context> context, void* priv) {
mate::Dictionary dict(context->GetIsolate(), exports);
dict.SetMethod("getHiddenValue", &GetHiddenValue);
dict.SetMethod("setHiddenValue", &SetHiddenValue);
dict.SetMethod("deleteHiddenValue", &DeleteHiddenValue);
dict.SetMethod("getObjectHash", &GetObjectHash);
dict.SetMethod("takeHeapSnapshot", &TakeHeapSnapshot);
dict.SetMethod("setRemoteCallbackFreer", &atom::RemoteCallbackFreer::BindTo);
dict.SetMethod("setRemoteObjectFreer", &atom::RemoteObjectFreer::BindTo);
}
} // namespace
NODE_MODULE_CONTEXT_AWARE_BUILTIN(atom_common_v8_util, Initialize)