From 18bd91215459bcbcb7927c5fb19df71ab68af948 Mon Sep 17 00:00:00 2001 From: Rom Grk Date: Mon, 16 Jul 2018 18:04:25 -0400 Subject: [PATCH 1/6] draft --- examples/editor.js | 1 + src/closure.cc | 23 +++++---- src/loop.cc | 118 ++++++++++++++++++++++++++------------------- tests/loop.js | 23 +++++++++ 4 files changed, 106 insertions(+), 59 deletions(-) create mode 100644 tests/loop.js diff --git a/examples/editor.js b/examples/editor.js index 0401a699..9814c2cb 100644 --- a/examples/editor.js +++ b/examples/editor.js @@ -153,6 +153,7 @@ const execute = function(command) { textView.on('key-press-event', function(event) { + Gdk.test_error() let keyname = Gdk.keyvalName(event.keyval); let label = Gtk.acceleratorGetLabel(event.keyval, event.state); diff --git a/src/closure.cc b/src/closure.cc index b4e7a927..0a614a60 100644 --- a/src/closure.cc +++ b/src/closure.cc @@ -1,5 +1,5 @@ #include -#include +// #include #include "debug.h" #include "function.h" @@ -13,9 +13,10 @@ namespace GNodeJS { struct Closure { GClosure base; Persistent persistent; - GISignalInfo* info; + GIBaseInfo* info; ~Closure() { + persistent.Reset(); if (info) g_base_info_unref(info); } @@ -40,7 +41,7 @@ void Closure::Marshal(GClosure *base, HandleScope scope(isolate); Local context = Context::New(isolate); Context::Scope context_scope(context); - Nan::TryCatch try_catch; + // Nan::TryCatch try_catch; Local func = Local::New(isolate, closure->persistent); @@ -78,12 +79,14 @@ void Closure::Marshal(GClosure *base, } } else { - auto stackTrace = try_catch.StackTrace(); - if (!stackTrace.IsEmpty()) - printf("%s\n", *Nan::Utf8String(stackTrace.ToLocalChecked())); - else - printf("%s\n", *Nan::Utf8String(try_catch.Exception())); - exit(1); + log("did throw"); + /* auto stackTrace = try_catch.StackTrace(); + * if (!stackTrace.IsEmpty()) + * printf("%s\n", *Nan::Utf8String(stackTrace.ToLocalChecked())); + * else + * printf("%s\n", *Nan::Utf8String(try_catch.Exception())); + * exit(1); */ + // try_catch.ReThrow(); } #ifndef __linux__ @@ -96,7 +99,7 @@ void Closure::Invalidated(gpointer data, GClosure *base) { closure->~Closure(); } -GClosure *MakeClosure(Isolate *isolate, Local function, GISignalInfo* info) { +GClosure *MakeClosure(Isolate *isolate, Local function, GIBaseInfo* info) { Closure *closure = (Closure *) g_closure_new_simple (sizeof (*closure), NULL); closure->persistent.Reset(isolate, function); closure->info = info; diff --git a/src/loop.cc b/src/loop.cc index 4e074351..b562acee 100644 --- a/src/loop.cc +++ b/src/loop.cc @@ -1,73 +1,93 @@ +/* + * Taken from https://github.com/endlessm/eos-knowledge-content-node/blob/master/src/mainloop.cc + * Relicensed in https://github.com/Place1/node-gir/issues/24 + */ + #include #include #include "loop.h" #include "util.h" -/* Integration for the GLib main loop and uv's main loop */ - -/* The way that this works is that we take uv's loop and nest it inside GLib's - * mainloop, since nesting GLib inside uv seems to be fairly impossible until - * either uv allows external sources to drive prepare/check, or until GLib - * exposes an epoll fd to wait on... */ +using namespace v8; namespace GNodeJS { -struct uv_loop_source { - GSource source; - uv_loop_t *loop; +struct ThreadData { + uv_thread_t thread_handle; + uv_mutex_t mutex_handle; + uv_async_t async_handle; + GPollFD *fds; + gint nfds; }; -static gboolean uv_loop_source_prepare (GSource *base, int *timeout) { - struct uv_loop_source *source = (struct uv_loop_source *) base; - uv_update_time (source->loop); +/* + * GLibs mainloop is not easy to embed directly right now. So rather then + * embedding glib's mainloop inside libuvs mainloop, we are running glibs + * mainloop in a separate thread. However we still want to be able to callback + * into v8 javascript context from glib async code, so we call the dispatch + * phase of glibs mainloop back on libuvs main thread. The flow is something + * like + * + * glib thread: poll for events + * glib thread: got events. wakeup libuv thread and lock + * libuv thread: dispatch glib events + * libuv thread: unlock glib thread + * glib thread: poll for events + * ... + * + * If in the future glib moves to epoll to drive its mainloop, we could easily + * embed it inside of libuvs mainloop on the same thread, by polling on a single + * fd. See https://bugzilla.gnome.org/show_bug.cgi?id=156048 + */ +static void DispatchGLibMainloop (uv_async_t *async_handle) { + ThreadData *data = (ThreadData *)async_handle->data; + GMainContext *context = g_main_context_default (); + g_main_context_acquire (context); + g_main_context_dispatch (context); + g_main_context_release (context); + uv_mutex_unlock (&data->mutex_handle); +} - bool loop_alive = uv_loop_alive (source->loop); +static void IterateGLibMainloop (ThreadData *data) { + GMainContext *context = g_main_context_default (); + gint max_priority, timeout; + g_main_context_prepare (context, &max_priority); - /* If the loop is dead, we can simply sleep forever until a GTK+ source - * (presumably) wakes us back up again. */ - if (!loop_alive) - return FALSE; + gint nfds; + while ((nfds = g_main_context_query (context, max_priority, &timeout, data->fds, data->nfds)) > data->nfds) { + delete[] data->fds; + data->fds = new GPollFD[nfds]; + data->nfds = nfds; + } - /* Otherwise, check the timeout. If the timeout is 0, that means we're - * ready to go. Otherwise, keep sleeping until the timeout happens again. */ - int t = uv_backend_timeout (source->loop); - *timeout = t; + g_poll (data->fds, data->nfds, timeout); - if (t == 0) - return TRUE; - else - return FALSE; -} + gboolean some_ready = g_main_context_check (context, max_priority, data->fds, data->nfds); -static gboolean uv_loop_source_dispatch (GSource *base, GSourceFunc callback, gpointer user_data) { - struct uv_loop_source *source = (struct uv_loop_source *) base; - uv_run (source->loop, UV_RUN_NOWAIT); - Util::CallNextTickCallback(); - return G_SOURCE_CONTINUE; + if (some_ready) { + g_main_context_release (context); + uv_async_send(&data->async_handle); + uv_mutex_lock (&data->mutex_handle); + g_main_context_acquire (context); + } } -static GSourceFuncs uv_loop_source_funcs = { - uv_loop_source_prepare, - NULL, - uv_loop_source_dispatch, - NULL, - - NULL, NULL, -}; - -static GSource *uv_loop_source_new (uv_loop_t *loop) { - struct uv_loop_source *source = (struct uv_loop_source *) g_source_new (&uv_loop_source_funcs, sizeof (*source)); - source->loop = loop; - g_source_add_unix_fd (&source->source, - uv_backend_fd (loop), - (GIOCondition) (G_IO_IN | G_IO_OUT | G_IO_ERR)); - return &source->source; +static void RunGLibMainloop (ThreadData *data) { + g_main_context_acquire (g_main_context_default ()); + uv_mutex_lock (&data->mutex_handle); + while (uv_loop_alive (uv_default_loop ())) + IterateGLibMainloop(data); + delete data; } void StartLoop() { - GSource *source = uv_loop_source_new (uv_default_loop ()); - g_source_attach (source, NULL); + ThreadData *data = new ThreadData(); + uv_mutex_init (&data->mutex_handle); + uv_async_init (uv_default_loop (), &data->async_handle, DispatchGLibMainloop); + data->async_handle.data = data; + + uv_thread_create (&data->thread_handle, (uv_thread_cb)RunGLibMainloop, data); } }; diff --git a/tests/loop.js b/tests/loop.js new file mode 100644 index 00000000..afa1bfec --- /dev/null +++ b/tests/loop.js @@ -0,0 +1,23 @@ +/* + * loop.js + */ + + +const gi = require('../lib/') +const Gtk = gi.require('Gtk', '3.0') + +gi.startLoop() +Gtk.init() + +setTimeout(() => { + console.log('timeout') +}, 1000) + +const promise = new Promise(resolve => resolve('promise resolved')) +promise.then(result => console.log(result)) + +setTimeout(() => { + console.log('quit') + Gtk.mainQuit() +}, 5000) +Gtk.main() From ebaba4241d231dafe86ad7429f209e37968d6081 Mon Sep 17 00:00:00 2001 From: Rom Grk Date: Tue, 17 Jul 2018 16:43:04 -0400 Subject: [PATCH 2/6] implement loop stack --- examples/entry.js | 27 +++---- lib/index.js | 7 +- lib/native.js | 13 ++++ lib/overrides/Gtk-3.0.js | 12 ++++ src/closure.cc | 40 +++-------- src/closure.h | 23 ++++++ src/debug.h | 13 ++++ src/gi.cc | 10 ++- src/loop.cc | 148 +++++++++++++++++++++------------------ src/loop.h | 11 ++- 10 files changed, 184 insertions(+), 120 deletions(-) create mode 100644 lib/native.js diff --git a/examples/entry.js b/examples/entry.js index 8054a785..c493a4ca 100644 --- a/examples/entry.js +++ b/examples/entry.js @@ -10,6 +10,20 @@ const Gdk = gi.require('Gdk') gi.startLoop() Gtk.init() + +process.on('uncaughtException', (err) => { + console.log('process.uncaughtException', err) + process.exit(1) +}) +process.on('exit', (code) => { + console.log('process.exit', code) +}) +process.on('SIGINT', () => { + console.log('process.SIGINT') + process.exit(2) +}) + + // main program window const window = new Gtk.Window({ type : Gtk.WindowType.TOPLEVEL @@ -20,17 +34,6 @@ const entry = new Gtk.Entry() entry.on('key-press-event', (event) => { console.log(event) console.log(event.string) - console.log('') - - console.log(event, Object.keys(event)) - console.log(event.__proto__, Object.keys(event.__proto__)) - - const e = new Gdk.EventKey() - console.log(e, Object.keys(e)) - console.log(e.__proto__, Object.keys(e.__proto__)) - - console.log(e.__proto__ === event.__proto__) - console.log(e.__proto__.__proto__ === event.__proto__.__proto__) }) @@ -38,8 +41,6 @@ entry.on('key-press-event', (event) => { window.setDefaultSize(200, 50) window.setResizable(true) window.connect('show', () => { - // bring it on top in OSX - // window.setKeepAbove(true) Gtk.main() }) window.on('destroy', () => Gtk.mainQuit()) diff --git a/lib/index.js b/lib/index.js index 32df522d..3088a44d 100644 --- a/lib/index.js +++ b/lib/index.js @@ -5,12 +5,7 @@ const camelCase = require('lodash.camelcase') const snakeCase = require('lodash.snakecase') -let gi; -try { - gi = require('../build/Release/node-gtk'); -} catch(e) { - gi = require('../build/Debug/node-gtk'); -} +const gi = require('./native.js') // The bootstrap from C here contains functions and methods for each object, // namespaced with underscores. See gi.cc for more information. diff --git a/lib/native.js b/lib/native.js new file mode 100644 index 00000000..9d9d7f4c --- /dev/null +++ b/lib/native.js @@ -0,0 +1,13 @@ +/* + * native.js + */ + +let native + +try { + native = require('../build/Release/node-gtk'); +} catch(e) { + native = require('../build/Debug/node-gtk'); +} + +module.exports = native diff --git a/lib/overrides/Gtk-3.0.js b/lib/overrides/Gtk-3.0.js index 3de543cc..aca14965 100644 --- a/lib/overrides/Gtk-3.0.js +++ b/lib/overrides/Gtk-3.0.js @@ -2,5 +2,17 @@ * Gtk-3.0.js */ +const internal = require('../native.js') + exports.apply = (Gtk) => { + + const originalMain = Gtk.main + Gtk.main = function main() { + const loopStack = internal.GetLoopStack() + + loopStack.push(Gtk.mainQuit) + originalMain() + loopStack.pop() + } + } diff --git a/src/closure.cc b/src/closure.cc index 0a614a60..c6e511a6 100644 --- a/src/closure.cc +++ b/src/closure.cc @@ -1,8 +1,9 @@ #include -// #include +#include +#include "closure.h" #include "debug.h" -#include "function.h" +#include "loop.h" #include "type.h" #include "value.h" @@ -10,26 +11,6 @@ using namespace v8; namespace GNodeJS { -struct Closure { - GClosure base; - Persistent persistent; - GIBaseInfo* info; - - ~Closure() { - persistent.Reset(); - if (info) - g_base_info_unref(info); - } - - static void Marshal(GClosure *closure, - GValue *g_return_value, - uint argc, const GValue *g_argv, - gpointer invocation_hint, - gpointer marshal_data); - - static void Invalidated(gpointer data, GClosure *closure); -}; - void Closure::Marshal(GClosure *base, GValue *g_return_value, uint argc, const GValue *g_argv, @@ -41,7 +22,7 @@ void Closure::Marshal(GClosure *base, HandleScope scope(isolate); Local context = Context::New(isolate); Context::Scope context_scope(context); - // Nan::TryCatch try_catch; + Nan::TryCatch try_catch; Local func = Local::New(isolate, closure->persistent); @@ -79,14 +60,11 @@ void Closure::Marshal(GClosure *base, } } else { - log("did throw"); - /* auto stackTrace = try_catch.StackTrace(); - * if (!stackTrace.IsEmpty()) - * printf("%s\n", *Nan::Utf8String(stackTrace.ToLocalChecked())); - * else - * printf("%s\n", *Nan::Utf8String(try_catch.Exception())); - * exit(1); */ - // try_catch.ReThrow(); + log("'%s' did throw", g_base_info_get_name (closure->info)); + + GNodeJS::QuitLoopStack(); + + try_catch.ReThrow(); } #ifndef __linux__ diff --git a/src/closure.h b/src/closure.h index 96212e1d..9a14b3cc 100644 --- a/src/closure.h +++ b/src/closure.h @@ -6,8 +6,31 @@ #include #include +using v8::Function; +using v8::Persistent; + namespace GNodeJS { +struct Closure { + GClosure base; + Persistent persistent; + GIBaseInfo* info; + + ~Closure() { + persistent.Reset(); + if (info) + g_base_info_unref(info); + } + + static void Marshal(GClosure *closure, + GValue *g_return_value, + uint argc, const GValue *g_argv, + gpointer invocation_hint, + gpointer marshal_data); + + static void Invalidated(gpointer data, GClosure *closure); +}; + GClosure *MakeClosure(v8::Isolate *isolate, v8::Handle function, GISignalInfo* info); }; diff --git a/src/debug.h b/src/debug.h index ffe61580..5111aa5a 100644 --- a/src/debug.h +++ b/src/debug.h @@ -1,6 +1,7 @@ #pragma once +#include #include #define FILE_NAME (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__) @@ -17,6 +18,18 @@ printf("\x1b[0m\n"); } \ while (0) +#ifdef NDEBUG +#define warn(...) +#else +#define warn(...) \ + do { \ + printf("\x1b[1;38;5;202m"); \ + printf("%s:\x1b[0m\x1b[1m %s: %i: \x1b[0m", FILE_NAME, FUNCTION_NAME, __LINE__); \ + printf(__VA_ARGS__); \ + printf("\n"); \ + } while (0) +#endif + #ifdef NDEBUG #define log(...) #else diff --git a/src/gi.cc b/src/gi.cc index c2829502..24a3344a 100644 --- a/src/gi.cc +++ b/src/gi.cc @@ -17,11 +17,11 @@ using GNodeJS::BaseInfo; namespace GNodeJS { - Nan::Persistent moduleCache(Nan::New()); - G_DEFINE_QUARK(gnode_js_object, object); G_DEFINE_QUARK(gnode_js_template, template); + Nan::Persistent moduleCache(Nan::New()); + Local GetModuleCache() { return Nan::New(GNodeJS::moduleCache); } @@ -331,6 +331,11 @@ NAN_METHOD(GetTypeSize) { info.GetReturnValue().Set(Nan::New(size)); } +NAN_METHOD(GetLoopStack) { + auto stack = GNodeJS::GetLoopStack(); + info.GetReturnValue().Set(stack); +} + void InitModule(Local exports, Local module, void *priv) { NAN_EXPORT(exports, Bootstrap); NAN_EXPORT(exports, GetModuleCache); @@ -348,6 +353,7 @@ void InitModule(Local exports, Local module, void *priv) { NAN_EXPORT(exports, InternalFieldCount); NAN_EXPORT(exports, GetBaseClass); NAN_EXPORT(exports, GetTypeSize); + NAN_EXPORT(exports, GetLoopStack); } NODE_MODULE(gi, InitModule) diff --git a/src/loop.cc b/src/loop.cc index b562acee..8a2e458e 100644 --- a/src/loop.cc +++ b/src/loop.cc @@ -1,93 +1,107 @@ -/* - * Taken from https://github.com/endlessm/eos-knowledge-content-node/blob/master/src/mainloop.cc - * Relicensed in https://github.com/Place1/node-gir/issues/24 - */ - #include #include +#include +#include +#include "debug.h" +#include "gi.h" #include "loop.h" #include "util.h" +/* Integration for the GLib main loop and uv's main loop */ + +/* The way that this works is that we take uv's loop and nest it inside GLib's + * mainloop, since nesting GLib inside uv seems to be fairly impossible until + * either uv allows external sources to drive prepare/check, or until GLib + * exposes an epoll fd to wait on... */ + using namespace v8; namespace GNodeJS { -struct ThreadData { - uv_thread_t thread_handle; - uv_mutex_t mutex_handle; - uv_async_t async_handle; - GPollFD *fds; - gint nfds; +static Nan::Persistent loopStack(Nan::New ()); + +struct uv_loop_source { + GSource source; + uv_loop_t *loop; }; -/* - * GLibs mainloop is not easy to embed directly right now. So rather then - * embedding glib's mainloop inside libuvs mainloop, we are running glibs - * mainloop in a separate thread. However we still want to be able to callback - * into v8 javascript context from glib async code, so we call the dispatch - * phase of glibs mainloop back on libuvs main thread. The flow is something - * like - * - * glib thread: poll for events - * glib thread: got events. wakeup libuv thread and lock - * libuv thread: dispatch glib events - * libuv thread: unlock glib thread - * glib thread: poll for events - * ... - * - * If in the future glib moves to epoll to drive its mainloop, we could easily - * embed it inside of libuvs mainloop on the same thread, by polling on a single - * fd. See https://bugzilla.gnome.org/show_bug.cgi?id=156048 - */ -static void DispatchGLibMainloop (uv_async_t *async_handle) { - ThreadData *data = (ThreadData *)async_handle->data; - GMainContext *context = g_main_context_default (); - g_main_context_acquire (context); - g_main_context_dispatch (context); - g_main_context_release (context); - uv_mutex_unlock (&data->mutex_handle); -} +static gboolean uv_loop_source_prepare (GSource *base, int *timeout) { + struct uv_loop_source *source = (struct uv_loop_source *) base; + uv_update_time (source->loop); -static void IterateGLibMainloop (ThreadData *data) { - GMainContext *context = g_main_context_default (); - gint max_priority, timeout; - g_main_context_prepare (context, &max_priority); + bool loop_alive = uv_loop_alive (source->loop); - gint nfds; - while ((nfds = g_main_context_query (context, max_priority, &timeout, data->fds, data->nfds)) > data->nfds) { - delete[] data->fds; - data->fds = new GPollFD[nfds]; - data->nfds = nfds; - } + /* If the loop is dead, we can simply sleep forever until a GTK+ source + * (presumably) wakes us back up again. */ + if (!loop_alive) + return FALSE; - g_poll (data->fds, data->nfds, timeout); + /* Otherwise, check the timeout. If the timeout is 0, that means we're + * ready to go. Otherwise, keep sleeping until the timeout happens again. */ + int t = uv_backend_timeout (source->loop); + *timeout = t; - gboolean some_ready = g_main_context_check (context, max_priority, data->fds, data->nfds); + if (t == 0) + return TRUE; + else + return FALSE; +} - if (some_ready) { - g_main_context_release (context); - uv_async_send(&data->async_handle); - uv_mutex_lock (&data->mutex_handle); - g_main_context_acquire (context); - } +static gboolean uv_loop_source_dispatch (GSource *base, GSourceFunc callback, gpointer user_data) { + struct uv_loop_source *source = (struct uv_loop_source *) base; + uv_run (source->loop, UV_RUN_NOWAIT); + Util::CallNextTickCallback(); + return G_SOURCE_CONTINUE; } -static void RunGLibMainloop (ThreadData *data) { - g_main_context_acquire (g_main_context_default ()); - uv_mutex_lock (&data->mutex_handle); - while (uv_loop_alive (uv_default_loop ())) - IterateGLibMainloop(data); - delete data; +static GSourceFuncs uv_loop_source_funcs = { + uv_loop_source_prepare, + NULL, + uv_loop_source_dispatch, + NULL, + + NULL, NULL, +}; + +static GSource *uv_loop_source_new (uv_loop_t *loop) { + struct uv_loop_source *source = (struct uv_loop_source *) g_source_new (&uv_loop_source_funcs, sizeof (*source)); + source->loop = loop; + g_source_add_unix_fd (&source->source, + uv_backend_fd (loop), + (GIOCondition) (G_IO_IN | G_IO_OUT | G_IO_ERR)); + return &source->source; } void StartLoop() { - ThreadData *data = new ThreadData(); - uv_mutex_init (&data->mutex_handle); - uv_async_init (uv_default_loop (), &data->async_handle, DispatchGLibMainloop); - data->async_handle.data = data; + GSource *source = uv_loop_source_new (uv_default_loop ()); + g_source_attach (source, NULL); +} + +Local GetLoopStack() { + static bool isLoopStackCreated = false; + + if (!isLoopStackCreated) { + isLoopStackCreated = true; + loopStack.Reset(Nan::New()); + } + + return Nan::New(loopStack); +} + +void QuitLoopStack() { + Local stack = GetLoopStack(); + + for (uint32_t i = 0; i < stack->Length(); i++) { + Local fn = Nan::Get(stack, i).ToLocalChecked()->ToObject(); + Local self = fn; + + log("calling %s", *Nan::Utf8String(Nan::Get(fn, UTF8("name")).ToLocalChecked())); + + Nan::CallAsFunction(fn, self, 0, nullptr); + } - uv_thread_create (&data->thread_handle, (uv_thread_cb)RunGLibMainloop, data); + loopStack.Reset(Nan::New()); } }; diff --git a/src/loop.h b/src/loop.h index 64972e90..5e5196b1 100644 --- a/src/loop.h +++ b/src/loop.h @@ -1,8 +1,17 @@ #pragma once +#include +#include + +using namespace v8; + namespace GNodeJS { -void StartLoop(); + void StartLoop(); + + void QuitLoopStack(); + + Local GetLoopStack(); }; From f809f8c2e4f3d150ee1f0e1abf76ea72f572b117 Mon Sep 17 00:00:00 2001 From: Rom Grk Date: Tue, 17 Jul 2018 16:50:50 -0400 Subject: [PATCH 3/6] doc: add overrides.md --- doc/overrides.md | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 doc/overrides.md diff --git a/doc/overrides.md b/doc/overrides.md new file mode 100644 index 00000000..c2f1bb06 --- /dev/null +++ b/doc/overrides.md @@ -0,0 +1,20 @@ +## Implementing overrides + + - [Functions that create GMainLoop](#functions-that-create-gmainloop) + +### Functions that create GMainLoop + +Functions that create a GMainLoop should be wrapped as shown in the snippet below. +The function to quit the created loop must be pushed unto the `loopStack`. +Internally, NodeGTK uses this stack to quit all running loops when an exception occurs. + +```javascript +const originalMain = Gtk.main +Gtk.main = function main() { + const loopStack = require('../native.js').GetLoopStack() + + loopStack.push(Gtk.mainQuit) + originalMain() + loopStack.pop() +} +``` From 6d969184aaceec9ba6d3ee3908c54b1620e68dba Mon Sep 17 00:00:00 2001 From: Rom Grk Date: Tue, 17 Jul 2018 16:53:07 -0400 Subject: [PATCH 4/6] clean example --- examples/editor.js | 1 - 1 file changed, 1 deletion(-) diff --git a/examples/editor.js b/examples/editor.js index 9814c2cb..0401a699 100644 --- a/examples/editor.js +++ b/examples/editor.js @@ -153,7 +153,6 @@ const execute = function(command) { textView.on('key-press-event', function(event) { - Gdk.test_error() let keyname = Gdk.keyvalName(event.keyval); let label = Gtk.acceleratorGetLabel(event.keyval, event.state); From 37ef8b56629443f4b945db0b6ca01176360f2c48 Mon Sep 17 00:00:00 2001 From: Rom Grk Date: Tue, 17 Jul 2018 17:01:51 -0400 Subject: [PATCH 5/6] tests: update loop test to fail --- tests/loop.js | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/tests/loop.js b/tests/loop.js index afa1bfec..f6d3159c 100644 --- a/tests/loop.js +++ b/tests/loop.js @@ -9,15 +9,25 @@ const Gtk = gi.require('Gtk', '3.0') gi.startLoop() Gtk.init() +let didCallTimeout = false +let didCallPromise = false + setTimeout(() => { console.log('timeout') -}, 1000) + didCallTimeout = true +}, 500) const promise = new Promise(resolve => resolve('promise resolved')) -promise.then(result => console.log(result)) +promise.then(result => { + console.log(result) + didCallPromise = true +}) setTimeout(() => { - console.log('quit') Gtk.mainQuit() -}, 5000) + console.assert(didCallTimeout, 'did not call timeout') + console.assert(didCallPromise, 'did not call promise') + console.log('done') +}, 1000) + Gtk.main() From 2011ea8d9a159de238518cfe6dd855daebeda3f9 Mon Sep 17 00:00:00 2001 From: Rom Grk Date: Tue, 17 Jul 2018 17:15:21 -0400 Subject: [PATCH 6/6] loop.cc: remove unuseful initialization --- src/loop.cc | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/loop.cc b/src/loop.cc index 8a2e458e..b55062df 100644 --- a/src/loop.cc +++ b/src/loop.cc @@ -79,13 +79,6 @@ void StartLoop() { } Local GetLoopStack() { - static bool isLoopStackCreated = false; - - if (!isLoopStackCreated) { - isLoopStackCreated = true; - loopStack.Reset(Nan::New()); - } - return Nan::New(loopStack); }