diff --git a/atom/browser/api/event_emitter.cc b/atom/browser/api/event_emitter.cc index 7fdcfa138c74..9cf7ba520c0f 100644 --- a/atom/browser/api/event_emitter.cc +++ b/atom/browser/api/event_emitter.cc @@ -8,8 +8,6 @@ #include "native_mate/arguments.h" #include "native_mate/object_template_builder.h" -#include "atom/common/node_includes.h" - namespace mate { namespace { @@ -38,11 +36,9 @@ v8::Local CreateEventObject(v8::Isolate* isolate) { EventEmitter::EventEmitter() { } -bool EventEmitter::CallEmit(v8::Isolate* isolate, - const base::StringPiece& name, - content::WebContents* sender, - IPC::Message* message, - ValueArray args) { +v8::Local EventEmitter::CreateEvent(v8::Isolate* isolate, + content::WebContents* sender, + IPC::Message* message) const { v8::Local event; bool use_native_event = sender && message; @@ -53,16 +49,7 @@ bool EventEmitter::CallEmit(v8::Isolate* isolate, } else { event = CreateEventObject(isolate); } - - // args = [name, event, args...]; - args.insert(args.begin(), event); - args.insert(args.begin(), mate::StringToV8(isolate, name)); - - // this.emit.apply(this, args); - node::MakeCallback(isolate, GetWrapper(isolate), "emit", args.size(), - &args[0]); - - return event->Get(StringToV8(isolate, "defaultPrevented"))->BooleanValue(); + return event; } } // namespace mate diff --git a/atom/browser/api/event_emitter.h b/atom/browser/api/event_emitter.h index 776fd5e2dd52..a249ce23f087 100644 --- a/atom/browser/api/event_emitter.h +++ b/atom/browser/api/event_emitter.h @@ -7,6 +7,7 @@ #include +#include "atom/common/event_emitter_caller.h" #include "native_mate/wrappable.h" namespace content { @@ -41,18 +42,16 @@ class EventEmitter : public Wrappable { const Args&... args) { v8::Locker locker(isolate()); v8::HandleScope handle_scope(isolate()); - - ValueArray converted = { ConvertToV8(isolate(), args)... }; - return CallEmit(isolate(), name, sender, message, converted); + v8::Local event = CreateEvent(isolate(), sender, message); + EmitEvent(isolate(), GetWrapper(isolate()), name, event, args...); + return event->Get( + StringToV8(isolate(), "defaultPrevented"))->BooleanValue(); } private: - // Lower level implementations. - bool CallEmit(v8::Isolate* isolate, - const base::StringPiece& name, - content::WebContents* sender, - IPC::Message* message, - ValueArray args); + v8::Local CreateEvent(v8::Isolate* isolate, + content::WebContents* sender, + IPC::Message* message) const; DISALLOW_COPY_AND_ASSIGN(EventEmitter); }; diff --git a/atom/common/event_emitter_caller.cc b/atom/common/event_emitter_caller.cc new file mode 100644 index 000000000000..85f56a233731 --- /dev/null +++ b/atom/common/event_emitter_caller.cc @@ -0,0 +1,33 @@ +// Copyright (c) 2015 GitHub, Inc. +// Use of this source code is governed by the MIT license that can be +// found in the LICENSE file. + +#include "atom/common/event_emitter_caller.h" + +namespace mate { + +namespace internal { + +v8::Local CallEmitWithArgs(v8::Isolate* isolate, + v8::Local obj, + ValueVector* args) { + v8::Local emit_name = StringToSymbol(isolate, "emit"); + v8::Local emit = obj->Get(emit_name); + if (emit.IsEmpty() || !emit->IsFunction()) { + isolate->ThrowException(v8::Exception::TypeError( + StringToV8(isolate, "\"emit\" is not a function"))); + return v8::Undefined(isolate); + } + + v8::MaybeLocal result = emit.As()->Call( + isolate->GetCurrentContext(), obj, args->size(), &args->front()); + if (result.IsEmpty()) { + return v8::Undefined(isolate); + } + + return result.ToLocalChecked(); +} + +} // namespace internal + +} // namespace mate diff --git a/atom/common/event_emitter_caller.h b/atom/common/event_emitter_caller.h new file mode 100644 index 000000000000..40755cb0d66f --- /dev/null +++ b/atom/common/event_emitter_caller.h @@ -0,0 +1,40 @@ +// Copyright (c) 2015 GitHub, Inc. +// Use of this source code is governed by the MIT license that can be +// found in the LICENSE file. + +#ifndef ATOM_COMMON_EVENT_EMITTER_CALLER_H_ +#define ATOM_COMMON_EVENT_EMITTER_CALLER_H_ + +#include + +#include "native_mate/converter.h" + +namespace mate { + +namespace internal { + +using ValueVector = std::vector>; + +v8::Local CallEmitWithArgs(v8::Isolate* isolate, + v8::Local obj, + ValueVector* args); + +} // namespace internal + +// obj.emit(name, args...); +// The caller is responsible of allocating a HandleScope. +template +v8::Local EmitEvent(v8::Isolate* isolate, + v8::Local obj, + const base::StringPiece& name, + const Args&... args) { + internal::ValueVector converted_args = { + ConvertToV8(isolate, name), + ConvertToV8(isolate, args)..., + }; + return internal::CallEmitWithArgs(isolate, obj, &converted_args); +} + +} // namespace mate + +#endif // ATOM_COMMON_EVENT_EMITTER_CALLER_H_ diff --git a/filenames.gypi b/filenames.gypi index d1e210580925..dfb8a0d9489c 100644 --- a/filenames.gypi +++ b/filenames.gypi @@ -249,6 +249,8 @@ 'atom/common/crash_reporter/win/crash_service_main.h', 'atom/common/draggable_region.cc', 'atom/common/draggable_region.h', + 'atom/common/event_emitter_caller.cc', + 'atom/common/event_emitter_caller.h', 'atom/common/google_api_key.h', 'atom/common/linux/application_info.cc', 'atom/common/native_mate_converters/accelerator_converter.cc',