1 // Copyright (c) 2015 GitHub, Inc. All rights reserved.
2 // Use of this source code is governed by the MIT license that can be
3 // found in the LICENSE file.
5 #include "atom/common/native_mate_converters/callback.h"
6 #include "tizen/common/env_variables.h"
8 using content::BrowserThread;
16 struct TranslaterHolder {
17 Translater translater;
20 // Cached JavaScript version of |CallTranslater|.
21 v8::Persistent<v8::FunctionTemplate> g_call_translater;
23 void CallTranslater(v8::Local<v8::External> external,
24 v8::Local<v8::Object> state,
25 mate::Arguments* args) {
26 v8::Isolate* isolate = args->isolate();
28 // Check if the callback has already been called.
29 v8::Local<v8::String> called_symbol = mate::StringToSymbol(isolate, "called");
30 if (state->Has(called_symbol)) {
31 args->ThrowError("callback can only be called for once");
34 state->Set(called_symbol, v8::Boolean::New(isolate, true));
37 TranslaterHolder* holder = static_cast<TranslaterHolder*>(external->Value());
38 holder->translater.Run(args);
42 // func.bind(func, arg1).
43 // NB(zcbenz): Using C++11 version crashes VS.
44 v8::Local<v8::Value> BindFunctionWith(v8::Isolate* isolate,
45 v8::Local<v8::Context> context,
46 v8::Local<v8::Function> func,
47 v8::Local<v8::Value> arg1,
48 v8::Local<v8::Value> arg2) {
49 v8::MaybeLocal<v8::Value> bind = func->Get(mate::StringToV8(isolate, "bind"));
50 CHECK(!bind.IsEmpty());
51 v8::Local<v8::Function> bind_func =
52 v8::Local<v8::Function>::Cast(bind.ToLocalChecked());
53 v8::Local<v8::Value> converted[] = { func, arg1, arg2 };
54 return bind_func->Call(
55 context, func, arraysize(converted), converted).ToLocalChecked();
60 // Destroy the class on UI thread when possible.
61 struct DeleteOnUIThread {
63 static void Destruct(const T* x) {
64 if ((::tizen::is_single_process || Locker::IsBrowserProcess()) &&
65 !BrowserThread::CurrentlyOn(BrowserThread::UI)) {
66 BrowserThread::DeleteSoon(BrowserThread::UI, FROM_HERE, x);
73 // Like v8::Global, but ref-counted.
75 class RefCountedGlobal : public base::RefCountedThreadSafe<RefCountedGlobal<T>,
78 RefCountedGlobal(v8::Isolate* isolate, v8::Local<v8::Value> value)
79 : handle_(isolate, v8::Local<T>::Cast(value)) {
82 bool IsAlive() const {
83 return !handle_.IsEmpty();
86 v8::Local<T> NewHandle(v8::Isolate* isolate) const {
87 return v8::Local<T>::New(isolate, handle_);
91 v8::Global<T> handle_;
93 DISALLOW_COPY_AND_ASSIGN(RefCountedGlobal);
96 SafeV8Function::SafeV8Function(v8::Isolate* isolate, v8::Local<v8::Value> value)
97 : v8_function_(new RefCountedGlobal<v8::Function>(isolate, value)) {
100 SafeV8Function::SafeV8Function(const SafeV8Function& other)
101 : v8_function_(other.v8_function_) {
104 SafeV8Function::~SafeV8Function() {
107 bool SafeV8Function::IsAlive() const {
108 return v8_function_.get() && v8_function_->IsAlive();
111 v8::Local<v8::Function> SafeV8Function::NewHandle(v8::Isolate* isolate) const {
112 return v8_function_->NewHandle(isolate);
115 v8::Local<v8::Value> CreateFunctionFromTranslater(
116 v8::Isolate* isolate, const Translater& translater) {
117 // The FunctionTemplate is cached.
118 if (g_call_translater.IsEmpty())
119 g_call_translater.Reset(
121 mate::CreateFunctionTemplate(isolate, base::Bind(&CallTranslater)));
123 v8::Local<v8::FunctionTemplate> call_translater =
124 v8::Local<v8::FunctionTemplate>::New(isolate, g_call_translater);
125 auto* holder = new TranslaterHolder;
126 holder->translater = translater;
127 return BindFunctionWith(isolate,
128 isolate->GetCurrentContext(),
129 call_translater->GetFunction(),
130 v8::External::New(isolate, holder),
131 v8::Object::New(isolate));
134 } // namespace internal