From 265c2257729c52e3bc12936c47c42c1ccb3f4c51 Mon Sep 17 00:00:00 2001 From: min Date: Mon, 8 Jun 2026 15:46:53 +0300 Subject: [PATCH] =?UTF-8?q?fix(lua):=20pcall=20handler=20=D1=87=D1=82?= =?UTF-8?q?=D0=BE=D0=B1=D1=8B=20wasmoon=20=D0=BD=D0=B5=20=D0=BE=D0=B1?= =?UTF-8?q?=D0=BE=D1=80=D0=B0=D1=87=D0=B8=D0=B2=D0=B0=D0=BB=20return=20val?= =?UTF-8?q?ue?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reblox-handler типа onEquippedLocal часто возвращают значение последнего выражения (например :connect(fn) → conn object). wasmoon на JS-стороне видит этот объект как result и тестирует на promise — крах 'null.then' если в цепочке встретится null/odd-shaped значение. Фикс: оборачиваем fn(a1,...) в pcall — оно поглощает все return values. + Все 'return null' заменены на 'return undefined' (wasmoon quirk из memory: null → PromiseTypeExtension crash). --- src/editor/engine/lua/RobloxShim.js | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/src/editor/engine/lua/RobloxShim.js b/src/editor/engine/lua/RobloxShim.js index 246e050..60122d6 100644 --- a/src/editor/engine/lua/RobloxShim.js +++ b/src/editor/engine/lua/RobloxShim.js @@ -58,7 +58,7 @@ function makeSignal() { } }; sig.fire = sig.Fire; - sig.Wait = () => null; + sig.Wait = () => undefined; sig.wait = sig.Wait; return sig; } @@ -266,7 +266,7 @@ function makeStubCallable() { fn.connect = fn.Connect; fn.Fire = function () {}; fn.fire = fn.Fire; - fn.Wait = function () { return null; }; + fn.Wait = function () { return undefined; }; fn.wait = fn.Wait; return fn; } @@ -1403,7 +1403,13 @@ export function registerRobloxShim(lua, opts) { function __rbxl_drain_handler(fn, a1, a2, a3, a4) __rbxl_next_handler_id = __rbxl_next_handler_id + 1 local handlerId = "handler_" .. __rbxl_next_handler_id - local co = coroutine.create(function() fn(a1, a2, a3, a4) end) + -- Оборачиваем call в pcall чтобы поглотить return value handler'а + -- (RayGun возвращает :connect(...) объект как последнее выражение, + -- что приводит к wasmoon promise-detection crash). pcall возвращает + -- (ok, ret1, ret2, ...) — мы их не используем. + local co = coroutine.create(function() + pcall(fn, a1, a2, a3, a4) + end) __rbxl_register_coroutine(handlerId, co) local ok, ret = coroutine.resume(co) if not ok then @@ -1414,6 +1420,7 @@ export function registerRobloxShim(lua, opts) { elseif coroutine.status(co) == 'dead' then __rbxl_unregister_coroutine(handlerId) end + -- Явно ничего не возвращаем чтобы wasmoon не оборачивал nil end `); // Кешируем ссылку на Lua-функцию запуска handler'а @@ -1469,8 +1476,14 @@ export function registerRobloxShim(lua, opts) { const queue = _pendingHandlerQueue.splice(0, _pendingHandlerQueue.length); for (const h of queue) { try { + // Только реальное число аргументов. wasmoon не любит + // undefined/null — может попытаться обернуть как promise. const a = h.args || []; - luaDrainHandler(h.fn, a[0], a[1], a[2], a[3]); + if (a.length === 0) luaDrainHandler(h.fn); + else if (a.length === 1) luaDrainHandler(h.fn, a[0]); + else if (a.length === 2) luaDrainHandler(h.fn, a[0], a[1]); + else if (a.length === 3) luaDrainHandler(h.fn, a[0], a[1], a[2]); + else luaDrainHandler(h.fn, a[0], a[1], a[2], a[3]); } catch (e) { console.error('[handler-drain]', e); }