diff --git a/common/api/atom_bindings.cc b/common/api/atom_bindings.cc index f8fbccc81198..f2a88a7d2748 100644 --- a/common/api/atom_bindings.cc +++ b/common/api/atom_bindings.cc @@ -16,13 +16,29 @@ namespace { static int kMaxCallStackSize = 200; // Same with WebKit. -static uv_async_t dummy_uv_handle; +// Async handle to wake up uv loop. +static uv_async_t g_dummy_uv_handle; +// Async handle to execute the stored v8 callback. +static uv_async_t g_callback_uv_handle; + +// Stored v8 callback, to be called by the async handler. +RefCountedV8Function g_v8_callback; + +// Dummy class type that used for crashing the program. struct DummyClass { bool crash; }; +// Dummy async handler that does nothing. void UvNoOp(uv_async_t* handle, int status) { } +// Async handler to execute the stored v8 callback. +void UvOnCallback(uv_async_t* handle, int status) { + v8::HandleScope handle_scope(node_isolate); + v8::Handle global = v8::Context::GetCurrent()->Global(); + g_v8_callback->NewHandle()->Call(global, 0, NULL); +} + v8::Handle DumpStackFrame(v8::Handle stack_frame) { v8::Local result = v8::Object::New(); result->Set(ToV8Value("line"), ToV8Value(stack_frame->GetLineNumber())); @@ -44,7 +60,8 @@ v8::Handle DumpStackFrame(v8::Handle stack_frame) { node::node_module_struct* GetBuiltinModule(const char *name, bool is_browser); AtomBindings::AtomBindings() { - uv_async_init(uv_default_loop(), &dummy_uv_handle, UvNoOp); + uv_async_init(uv_default_loop(), &g_dummy_uv_handle, UvNoOp); + uv_async_init(uv_default_loop(), &g_callback_uv_handle, UvOnCallback); } AtomBindings::~AtomBindings() { @@ -58,6 +75,7 @@ void AtomBindings::BindTo(v8::Handle process) { NODE_SET_METHOD(process, "activateUvLoop", ActivateUVLoop); NODE_SET_METHOD(process, "log", Log); NODE_SET_METHOD(process, "getCurrentStackTrace", GetCurrentStackTrace); + NODE_SET_METHOD(process, "scheduleCallback", ScheduleCallback); process->Get(v8::String::New("versions"))->ToObject()-> Set(v8::String::New("atom-shell"), v8::String::New(ATOM_VERSION_STRING)); @@ -115,7 +133,7 @@ void AtomBindings::Crash(const v8::FunctionCallbackInfo& args) { // static void AtomBindings::ActivateUVLoop( const v8::FunctionCallbackInfo& args) { - uv_async_send(&dummy_uv_handle); + uv_async_send(&g_dummy_uv_handle); } // static @@ -146,4 +164,12 @@ void AtomBindings::GetCurrentStackTrace( args.GetReturnValue().Set(result); } +// static +void AtomBindings::ScheduleCallback( + const v8::FunctionCallbackInfo& args) { + if (!FromV8Arguments(args, &g_v8_callback)) + return node::ThrowTypeError("Bad arguments"); + uv_async_send(&g_callback_uv_handle); +} + } // namespace atom diff --git a/common/api/atom_bindings.h b/common/api/atom_bindings.h index a414bea22566..27b2cee908c0 100644 --- a/common/api/atom_bindings.h +++ b/common/api/atom_bindings.h @@ -26,6 +26,7 @@ class AtomBindings { static void Log(const v8::FunctionCallbackInfo& args); static void GetCurrentStackTrace( const v8::FunctionCallbackInfo& args); + static void ScheduleCallback(const v8::FunctionCallbackInfo& args); DISALLOW_COPY_AND_ASSIGN(AtomBindings); };