aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAkshay Nair <phenax5@gmail.com>2025-03-23 16:59:16 +0530
committerAkshay Nair <phenax5@gmail.com>2025-03-23 16:59:34 +0530
commit18b3e4939931c0d2bf779d2e52cb0c90e282ec97 (patch)
treee9afabef77660b8cfcd8a37006c9db38c4bc8aa6 /src
parent1f018902a8e1d1138c9a56106bce7aa7982a247b (diff)
downloadnull-browser-18b3e4939931c0d2bf779d2e52cb0c90e282ec97.tar.gz
null-browser-18b3e4939931c0d2bf779d2e52cb0c90e282ec97.zip
Fix segfault with evaluate, add keymap accidentally popping wrong value
+ add demnu config.lua example
Diffstat (limited to 'src')
-rw-r--r--src/AsyncEventLoop.cpp33
-rw-r--r--src/AsyncEventLoop.hpp3
-rw-r--r--src/LuaRuntime.cpp103
-rw-r--r--src/LuaRuntime.hpp14
-rw-r--r--src/widgets/MainWindow.cpp18
-rw-r--r--src/widgets/MainWindow.hpp1
6 files changed, 78 insertions, 94 deletions
diff --git a/src/AsyncEventLoop.cpp b/src/AsyncEventLoop.cpp
index 6c9b42d..6c6333f 100644
--- a/src/AsyncEventLoop.cpp
+++ b/src/AsyncEventLoop.cpp
@@ -3,8 +3,6 @@
#include <mutex>
#include <queue>
#include <thread>
-#include <utility>
-#include <uv.h>
#include "AsyncEventLoop.hpp"
@@ -23,6 +21,8 @@ AsyncEventLoop::AsyncEventLoop() {
std::this_thread::sleep_for(std::chrono::milliseconds(50));
}
+void AsyncEventLoop::wake() { uv_async_send(&asyncHandle); }
+
void AsyncEventLoop::processTasks() {
std::queue<std::function<void()>> tasks;
@@ -41,10 +41,9 @@ void AsyncEventLoop::processTasks() {
void AsyncEventLoop::runLoop() {
isLoopRunning = true;
while (isLoopRunning) {
- /* int _result = */ uv_run(loop, UV_RUN_NOWAIT);
- // qDebug() << "Tasks handled:" << result;
- // uv_print_active_handles(loop, stdout);
- // if (result == 0)
+ // qDebug() << "loop iteration" << uv_loop_alive(loop);
+ uv_run(loop, UV_RUN_NOWAIT);
+ // qDebug() << "uv_run() returned: " << result;
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
}
@@ -54,33 +53,28 @@ AsyncEventLoop::~AsyncEventLoop() {
return;
isLoopRunning = false;
- // Clear the tasks queue
+ // Wake it up. Stab it to death. (clear async queue)
+ wake();
+ std::this_thread::sleep_for(std::chrono::milliseconds(100));
{
std::lock_guard<std::mutex> lock(tasksQueueMutex);
std::queue<std::function<void()>>().swap(tasksQueue);
}
-
- // Wake it up. Stab it to death.
- uv_async_send(&asyncHandle);
- std::this_thread::sleep_for(std::chrono::milliseconds(100));
uv_stop(loop);
// Close all handles
AsyncEventLoop::closeHandle(reinterpret_cast<uv_handle_t *>(&asyncHandle));
uv_walk(loop, AsyncEventLoop::closeHandle, nullptr);
- while (uv_run(loop, UV_RUN_ONCE) != 0)
- ;
+ while (uv_run(loop, UV_RUN_NOWAIT) != 0)
+ std::this_thread::sleep_for(std::chrono::milliseconds(100));
// TODO: Fix pending handler case (setTimeout(100) wait(20) close() -> error)
- qDebug() << "join start";
if (loopThread.joinable())
loopThread.join();
- qDebug() << "join done";
- while (uv_loop_close(loop) == UV_EBUSY) {
- uv_walk(loop, AsyncEventLoop::closeHandle, nullptr);
- uv_run(loop, UV_RUN_NOWAIT);
- }
+ while (uv_loop_close(loop))
+ uv_run(loop, UV_RUN_DEFAULT);
+
free(loop);
loop = nullptr;
}
@@ -93,5 +87,6 @@ void AsyncEventLoop::asyncHandleCallback(uv_async_t *handle) {
void AsyncEventLoop::closeHandle(uv_handle_t *handle, void *) {
if (!uv_is_closing(handle)) {
uv_close(handle, [](uv_handle_t *h) { h->data = nullptr; });
+ uv_unref(handle);
}
}
diff --git a/src/AsyncEventLoop.hpp b/src/AsyncEventLoop.hpp
index 29c2958..5718909 100644
--- a/src/AsyncEventLoop.hpp
+++ b/src/AsyncEventLoop.hpp
@@ -15,6 +15,7 @@ public:
AsyncEventLoop();
~AsyncEventLoop();
+ void wake();
DEFINE_GETTER(getUVLoop, loop)
template <typename F> void queueTask(F &&task) {
@@ -22,7 +23,7 @@ public:
std::lock_guard<std::mutex> lock(tasksQueueMutex);
tasksQueue.push(std::forward<F>(task));
}
- uv_async_send(&asyncHandle);
+ wake();
}
protected:
diff --git a/src/LuaRuntime.cpp b/src/LuaRuntime.cpp
index cdf95b0..274ec29 100644
--- a/src/LuaRuntime.cpp
+++ b/src/LuaRuntime.cpp
@@ -13,23 +13,7 @@ const char *web_global_name = "web";
LuaRuntime::LuaRuntime() {
state = luaL_newstate();
luaL_openlibs(state);
-
- // Load `web`
- luaL_Reg weblib[] = {
- {"open", &LuaRuntime::lua_onUrlOpen},
- {"tabopen", &LuaRuntime::lua_onUrlTabOpen},
- {nullptr, nullptr},
- };
- luaL_newlib(state, weblib);
- lua_setglobal(state, web_global_name);
-
- lua_getglobal(state, web_global_name);
- luaL_Reg keymaplib[] = {
- {"set", &LuaRuntime::lua_addKeymap},
- };
- luaL_newlib(state, keymaplib);
- lua_setfield(state, -2, "keymap");
- lua_pop(state, 1);
+ preserveTop(state, { initWebLib(); })
}
void LuaRuntime::startEventLoop() {
@@ -46,10 +30,10 @@ void LuaRuntime::startEventLoop() {
}
void LuaRuntime::stopEventLoop() {
- if (eventLoop == nullptr)
- return;
- delete eventLoop;
- eventLoop = nullptr;
+ if (eventLoop != nullptr) {
+ delete eventLoop;
+ eventLoop = nullptr;
+ }
// Clear the uv global
lua_pushnil(state);
@@ -59,28 +43,26 @@ void LuaRuntime::stopEventLoop() {
void LuaRuntime::evaluate(QString code) {
eventLoop->queueTask([this, code]() {
- if (luaL_dostring(state, code.toStdString().c_str()) != LUA_OK) {
- const char *value = lua_tostring(state, -1);
- lua_pop(state, 1);
-
- qDebug() << "Lua Error: " << value;
- emit evaluationFailed(value);
- } else {
- QVariant value = getValue(-1);
- lua_pop(state, 1);
-
- qDebug() << "result: " << value;
- emit evaluationCompleted(value);
- }
+ preserveTop(state, {
+ if (luaL_dostring(state, code.toStdString().c_str()) != LUA_OK) {
+ const char *value = lua_tostring(state, -1);
+ qDebug() << "Lua Error: " << value;
+ emit evaluationFailed(value);
+ } else {
+ QVariant value = getLuaValue(-1);
+ qDebug() << "result: " << value;
+ emit evaluationCompleted(value);
+ }
+ })
});
}
QVariant LuaRuntime::evaluateSync(QString code) {
luaL_dostring(state, code.toStdString().c_str());
- return getValue(-1); // TODO: error handling
+ return getLuaValue(-1); // TODO: error handling
}
-QVariant LuaRuntime::getValue(int idx) {
+QVariant LuaRuntime::getLuaValue(int idx) {
if (lua_isstring(state, idx))
return lua_tostring(state, idx);
@@ -117,15 +99,13 @@ int LuaRuntime::lua_addKeymap(lua_State *state) {
lua_pushvalue(state, 3);
int functionRef = luaL_ref(state, LUA_REGISTRYINDEX);
auto action = [state, functionRef]() {
- qDebug() << "key action";
-
- lua_rawgeti(state, LUA_REGISTRYINDEX, functionRef);
- if (lua_pcall(state, 0, 0, 0) != LUA_OK) {
- const char *error = lua_tostring(state, -1);
- qDebug() << "Error calling Lua function:" << error;
- lua_pop(state, 1);
- }
- lua_pop(state, 1);
+ preserveTop(state, {
+ lua_rawgeti(state, LUA_REGISTRYINDEX, functionRef);
+ if (lua_pcall(state, 0, 0, 0) != LUA_OK) {
+ const char *error = lua_tostring(state, -1);
+ qDebug() << "Error calling Lua function:" << error;
+ }
+ })
};
// TODO: Cleanup function ref on after keymap clear
@@ -136,11 +116,34 @@ int LuaRuntime::lua_addKeymap(lua_State *state) {
}
void LuaRuntime::loadFile(QString path) {
- qDebug() << "Loading: " << path;
- if (luaL_dofile(state, path.toStdString().c_str()) != LUA_OK) {
- qDebug() << "Load file error:" << lua_tostring(state, -1);
- lua_pop(state, 1);
- }
+ queueTask([this, path]() {
+ preserveTop(state, {
+ qDebug() << "Loading: " << path;
+ if (luaL_dofile(state, path.toStdString().c_str()) != LUA_OK) {
+ qDebug() << "Load file error:" << lua_tostring(state, -1);
+ }
+ })
+ });
+}
+
+void LuaRuntime::initWebLib() {
+ // web
+ luaL_Reg weblib[] = {
+ {"open", &LuaRuntime::lua_onUrlOpen},
+ {"tabopen", &LuaRuntime::lua_onUrlTabOpen},
+ {nullptr, nullptr},
+ };
+ luaL_newlib(state, weblib);
+ lua_setglobal(state, web_global_name);
+
+ // web.keymap
+ lua_getglobal(state, web_global_name);
+ luaL_Reg keymaplib[] = {
+ {"set", &LuaRuntime::lua_addKeymap},
+ };
+ luaL_newlib(state, keymaplib);
+ lua_setfield(state, -2, "keymap");
+ // lua_pop(state, 1);
}
LuaRuntime::~LuaRuntime() {
diff --git a/src/LuaRuntime.hpp b/src/LuaRuntime.hpp
index 9f672e9..3d44282 100644
--- a/src/LuaRuntime.hpp
+++ b/src/LuaRuntime.hpp
@@ -7,6 +7,11 @@
#include "AsyncEventLoop.hpp"
#include "widgets/WebViewStack.hpp"
+#define preserveTop(STATE, BODY) \
+ int __top = lua_gettop(STATE); \
+ BODY; \
+ lua_settop(STATE, __top);
+
class LuaRuntime : public QObject {
Q_OBJECT
@@ -17,16 +22,14 @@ public:
}
void evaluate(QString code);
- QVariant evaluateSync(QString code);
-
void loadFile(QString path);
+ QVariant evaluateSync(QString code);
void stopEventLoop();
void startEventLoop();
-
- QVariant getValue(int idx);
-
DELEGATE(eventLoop, queueTask, queueTask)
+
+ QVariant getLuaValue(int idx);
DEFINE_GETTER(getState, state)
signals:
@@ -39,6 +42,7 @@ signals:
protected:
LuaRuntime();
~LuaRuntime();
+ void initWebLib();
static int lua_onUrlOpen(lua_State *state);
static int lua_onUrlTabOpen(lua_State *state);
static int lua_addKeymap(lua_State *state);
diff --git a/src/widgets/MainWindow.cpp b/src/widgets/MainWindow.cpp
index ce03bce..df8da53 100644
--- a/src/widgets/MainWindow.cpp
+++ b/src/widgets/MainWindow.cpp
@@ -51,26 +51,8 @@ MainWindow::MainWindow() {
keymapEvaluator->addKeymap(KeyMode::Insert, "<esc>", [keymapEvaluator]() {
keymapEvaluator->setCurrentMode(KeyMode::Normal);
});
-
keymapEvaluator->addKeymap(KeyMode::Normal, "<c-t>a",
[]() { qDebug() << "Stuff"; });
- keymapEvaluator->addKeymap(KeyMode::Normal, "<c-t>b",
- []() { qDebug() << "Else"; });
-}
-
-void MainWindow::keyPressEvent(QKeyEvent *event) {
- auto combo = event->keyCombination();
-
- if (combo.key() == Qt::Key_J &&
- combo.keyboardModifiers().testFlag(Qt::ControlModifier)) {
- inputMediator->nextWebView();
- } else if (combo.key() == Qt::Key_K &&
- combo.keyboardModifiers().testFlag(Qt::ControlModifier)) {
- inputMediator->previousWebView();
- } else if (combo.key() == Qt::Key_W &&
- combo.keyboardModifiers().testFlag(Qt::ControlModifier)) {
- inputMediator->closeCurrentWebView();
- }
}
bool MainWindow::eventFilter(QObject *, QEvent *event) {
diff --git a/src/widgets/MainWindow.hpp b/src/widgets/MainWindow.hpp
index 2bbc42e..c3118fc 100644
--- a/src/widgets/MainWindow.hpp
+++ b/src/widgets/MainWindow.hpp
@@ -10,7 +10,6 @@ public:
MainWindow();
private:
- void keyPressEvent(QKeyEvent *event) override;
bool eventFilter(QObject *object, QEvent *event) override;
private: