diff --git a/examples/event-loop.js b/examples/event-loop.js index 9494853..b9e9712 100644 --- a/examples/event-loop.js +++ b/examples/event-loop.js @@ -116,7 +116,10 @@ function makeToolbar() { let timeoutHandle = null; btnCustom.onClicked(() => { if (timeoutHandle) { + console.log('before clearTimeout', timeoutHandle); clearTimeout(timeoutHandle); + console.log('after clearTimeout', timeoutHandle); + timeoutHandle = null; return; } @@ -125,7 +128,9 @@ function makeToolbar() { timeoutHandle = setTimeout((a, b, c) => { const elapsed = Date.now() - now; logAppend(`Custom setTimeout: ${now} - elapsed ${elapsed} ms. Args: ${a} ${b} ${c}`); + timeoutHandle = null; }, 1000, 'custom', 'args', 2); + console.log('after timeoutHandle', timeoutHandle); }); toolbar.append(btnCustom, false); diff --git a/index.js b/index.js index 12b140d..db57153 100644 --- a/index.js +++ b/index.js @@ -50,44 +50,59 @@ function startLoop() { asyncHook.enable(); setTimeoutNode = global.setTimeout; - global.setTimeout = function(cb, t) { + global.setTimeout = function(cb, timeout) { + const timeoutHandle = {running: true}; + const args = Array.prototype.slice.call(arguments, 2); - return binding.lib.setTimeout(function() { - cb.apply(null, args); - }, t); - }; + binding.lib.Ui.startTimer(timeout, function() { + // console.log('timeoutHandle.running ', timeoutHandle.running); + if (timeoutHandle.running) { + cb.apply(null, args); + } + return false; + }); + return timeoutHandle; + } clearTimeoutNode = global.clearTimeout; - global.clearTimeout = function(obj) { - if (obj && obj.constructor === binding.lib.TimeoutHandle) { + + global.clearTimeout = function(timeoutHandle) { + if (timeoutHandle && typeof timeoutHandle.running === 'boolean') { + timeoutHandle.running = false; // console.log('patched clearTimeout called'); - binding.lib.clearTimeout(obj); } else { // console.log('node clearTimeout called'); // not created by us, use original // clearTimeoutNode - clearTimeoutNode(obj); + clearTimeoutNode(timeoutHandle); } }; setIntervalNode = global.setInterval; - global.setInterval = function(cb, t) { + global.setInterval = function(cb, timeout) { + const timeoutHandle = {running: true}; const args = Array.prototype.slice.call(arguments, 2); - return binding.lib.setInterval(function() { - cb.apply(null, args); - }, t); - }; + binding.lib.Ui.startTimer(timeout, function() { + if (timeoutHandle.running) { + cb.apply(null, args); + return true; + } + return false; + }); + return timeoutHandle; + } clearIntervalNode = global.clearInterval; - global.clearInterval = function(obj) { - if (obj && obj.constructor === binding.lib.TimeoutHandle) { + + global.clearInterval = function(timeoutHandle) { + if (timeoutHandle && typeof timeoutHandle.running === 'boolean') { + timeoutHandle.running = false; // console.log('patched clearInterval called'); - binding.lib.clearInterval(obj); } else { // console.log('node clearInterval called'); // not created by us, use original // clearTimeoutNode - clearIntervalNode(obj); + clearIntervalNode(timeoutHandle); } } } diff --git a/package-lock.json b/package-lock.json index 75a7eaf..00207eb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "libui-node", - "version": "0.1.0", + "version": "0.3.0-rc1", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/src/Ui.cc b/src/Ui.cc index 5342ead..9563d57 100644 --- a/src/Ui.cc +++ b/src/Ui.cc @@ -10,6 +10,11 @@ static int onShouldQuit_cb(void *data) { return 0; } +static int uiTimer_cb(void *data) { + nbind::cbFunction *cb = (nbind::cbFunction *)data; + return cb->call(); +} + struct Ui { static void main() { uiMain(); @@ -40,6 +45,11 @@ struct Ui { uiFreeInitError(err); } } + + static void startTimer(int ms, nbind::cbFunction &cb) { + nbind::cbFunction *callbackJs = new nbind::cbFunction(cb); + uiTimer(ms, uiTimer_cb, callbackJs); + } }; NBIND_CLASS(Ui) { @@ -49,4 +59,5 @@ NBIND_CLASS(Ui) { method(mainStep); method(mainSteps); method(onShouldQuit); + method(startTimer); } diff --git a/src/arch/darwin/timer.mm b/src/arch/darwin/timer.mm deleted file mode 100644 index 43537b6..0000000 --- a/src/arch/darwin/timer.mm +++ /dev/null @@ -1,40 +0,0 @@ -#include "timer.h" -#include "nbind/api.h" -#import - -TimeoutHandle *setTimeout(nbind::cbFunction &cb, unsigned int timeout) { - nbind::cbFunction *callbackJs = new nbind::cbFunction(cb); - TimeoutHandle *timeoutHandle = new TimeoutHandle(callbackJs); - timeoutHandle->handle = - [NSTimer scheduledTimerWithTimeInterval:timeout / 1000.0 - repeats:NO - block:^(NSTimer *timer) { - CALL_JSCB(timeoutHandle); - timeoutHandle->destroy(); - }]; - return timeoutHandle; -} - -void clearTimeout(TimeoutHandle *timeoutHandle) { - NSTimer *handle = (NSTimer *)timeoutHandle->handle; - [handle invalidate]; - timeoutHandle->destroy(); -} - -TimeoutHandle *setInterval(nbind::cbFunction &cb, unsigned int timeout) { - nbind::cbFunction *callbackJs = new nbind::cbFunction(cb); - TimeoutHandle *timeoutHandle = new TimeoutHandle(callbackJs); - timeoutHandle->handle = - [NSTimer scheduledTimerWithTimeInterval:timeout / 1000.0 - repeats:YES - block:^(NSTimer *timer) { - CALL_JSCB(timeoutHandle); - }]; - return timeoutHandle; -} - -void clearInterval(TimeoutHandle *timeoutHandle) { - NSTimer *handle = (NSTimer *)timeoutHandle->handle; - [handle invalidate]; - timeoutHandle->destroy(); -} diff --git a/src/arch/unix/timer.cc b/src/arch/unix/timer.cc deleted file mode 100644 index 5b0347d..0000000 --- a/src/arch/unix/timer.cc +++ /dev/null @@ -1,39 +0,0 @@ -#include "timer.h" -#include "nbind/api.h" - -gboolean glib_timeout_cb(TimeoutHandle *timeoutHandle) { - CALL_JSCB(timeoutHandle); - timeoutHandle->destroy(); - return FALSE; -} - -gboolean glib_interval_cb(TimeoutHandle *timeoutHandle) { - CALL_JSCB(timeoutHandle); - return TRUE; -} - -TimeoutHandle *setTimeout(nbind::cbFunction &cb, unsigned int timeout) { - nbind::cbFunction *callbackJs = new nbind::cbFunction(cb); - TimeoutHandle *timeoutHandle = new TimeoutHandle(callbackJs); - timeoutHandle->handle = - g_timeout_add(timeout, (GSourceFunc)glib_timeout_cb, timeoutHandle); - return timeoutHandle; -} - -void clearTimeout(TimeoutHandle *timeoutHandle) { - g_source_remove(timeoutHandle->handle); - timeoutHandle->destroy(); -} - -TimeoutHandle *setInterval(nbind::cbFunction &cb, unsigned int timeout) { - nbind::cbFunction *callbackJs = new nbind::cbFunction(cb); - TimeoutHandle *timeoutHandle = new TimeoutHandle(callbackJs); - timeoutHandle->handle = - g_timeout_add(timeout, (GSourceFunc)glib_interval_cb, timeoutHandle); - return timeoutHandle; -} - -void clearInterval(TimeoutHandle *timeoutHandle) { - g_source_remove(timeoutHandle->handle); - timeoutHandle->destroy(); -} diff --git a/src/arch/win32/timer.cc b/src/arch/win32/timer.cc deleted file mode 100644 index af8fd90..0000000 --- a/src/arch/win32/timer.cc +++ /dev/null @@ -1,52 +0,0 @@ -#include -#include "nbind/api.h" -#include "timer.h" - -static std::map timersMap; - -void killTimer(TimeoutHandle *timeoutHandle) { - KillTimer(NULL, timeoutHandle->handle); - timersMap.erase(timeoutHandle->handle); - timeoutHandle->destroy(); -} - -void CALLBACK win_timeout_cb(HWND hwnd, UINT uMsg, UINT_PTR idEvent, - DWORD dwTime) { - TimeoutHandle *timeoutHandle = timersMap[idEvent]; - CALL_JSCB(timeoutHandle); - killTimer(timeoutHandle); -} - -void CALLBACK win_interval_cb(HWND hwnd, UINT uMsg, UINT_PTR idEvent, - DWORD dwTime) { - TimeoutHandle *timeoutHandle = timersMap[idEvent]; - CALL_JSCB(timeoutHandle); -} - -TimeoutHandle *setTimeout(nbind::cbFunction &cb, unsigned int timeout) { - nbind::cbFunction *callbackJs = new nbind::cbFunction(cb); - TimeoutHandle *timeoutHandle = new TimeoutHandle(callbackJs); - // SetTimer could work with a NULL window. - // https://stackoverflow.com/questions/7531650/can-i-use-a-settimer-api-in-a-console-c-application - timeoutHandle->handle = SetTimer(NULL, NULL, timeout, win_timeout_cb); - timersMap[timeoutHandle->handle] = timeoutHandle; - return timeoutHandle; -} - -void clearTimeout(TimeoutHandle *timeoutHandle) { - if (!timeoutHandle->destroyed) { - killTimer(timeoutHandle); - } -} - -TimeoutHandle *setInterval(nbind::cbFunction &cb, unsigned int timeout) { - nbind::cbFunction *callbackJs = new nbind::cbFunction(cb); - TimeoutHandle *timeoutHandle = new TimeoutHandle(callbackJs); - timeoutHandle->handle = SetTimer(NULL, NULL, timeout, win_interval_cb); - timersMap[timeoutHandle->handle] = timeoutHandle; - return timeoutHandle; -} - -void clearInterval(TimeoutHandle *timeoutHandle) { - killTimer(timeoutHandle); -} diff --git a/src/timer-common.cc b/src/timer-common.cc deleted file mode 100644 index 1bf5954..0000000 --- a/src/timer-common.cc +++ /dev/null @@ -1,27 +0,0 @@ -#include "nbind/api.h" -#include "timer.h" - -TimeoutHandle::TimeoutHandle(nbind::cbFunction *callbackJs) { - this->callbackJs = callbackJs; - this->destroyed = false; -} - -void TimeoutHandle::destroy() { - if (this->destroyed) { - return; - } - - delete this->callbackJs; - this->destroyed = true; -} - -#include "nbind/nbind.h" - -NBIND_GLOBAL() { - function(setTimeout); - function(clearTimeout); - function(setInterval); - function(clearInterval); -} - -NBIND_CLASS(TimeoutHandle) {}