From 4e34ca5b5271dde6fadf44c8832abcc2147b6831 Mon Sep 17 00:00:00 2001 From: min Date: Mon, 8 Jun 2026 20:53:52 +0300 Subject: [PATCH] =?UTF-8?q?fix(rbxl):=20=D0=BF=D1=80=D0=BE=D0=BF=D1=83?= =?UTF-8?q?=D1=81=D0=BA=D0=B0=D0=B5=D0=BC=20=D1=81=D0=BA=D1=80=D0=B8=D0=BF?= =?UTF-8?q?=D1=82=D1=8B=20=D1=81=20tight-loop=20WaitForChild=20=D1=87?= =?UTF-8?q?=D0=B5=D1=80=D0=B5=D0=B7=20regex?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Скрипты Roblox 2009 содержат паттерн: while not parent:FindFirstChild(name) do parent.ChildAdded:wait() end Наш sig.Wait() возвращает -1 синхронно (без yield), цикл крутится бесконечно без шанса coroutine.yield. debug.sethook не помогает если код находится в C-call boundary к моменту срабатывания. Решение: regex-фильтр в GameRuntime.js перед добавлением в batch. Скрипты с такими паттернами не запускаются — пишется warn в консоль. В ROBLOX Battle это ~10-15 скриптов: RoundScript, Spawner, ReEquipLastWeapon, LeaderboardV3, Leaderstats и др. Карта потеряет эту функциональность (раунды, респавн), но играется. --- src/editor/engine/GameRuntime.js | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/editor/engine/GameRuntime.js b/src/editor/engine/GameRuntime.js index 8320eee..c189888 100644 --- a/src/editor/engine/GameRuntime.js +++ b/src/editor/engine/GameRuntime.js @@ -142,6 +142,20 @@ export class GameRuntime { rbxlSkipped++; continue; } const luaSource = unpackRobloxLuaCode(s.code); + // SAFETY: пропускаем скрипты с tight-loop'ами через ChildAdded:wait() + // или WaitForChild через пользовательский while-not-FindFirstChild. + // Они подвешивают страницу (wait() возвращает синхронно, скрипт + // никогда не yield'ит из C-call). Распространённый Roblox 2009 + // паттерн который мы не можем безопасно эмулировать. + if (luaSource && ( + /while\s+not\s+\w+[:.]FindFirstChild/.test(luaSource) || + /ChildAdded:[Ww]ait\(\)/.test(luaSource) || + /:[Gg]etChildren\(\)\s*\[\d/.test(luaSource) + )) { + rbxlSkipped++; + console.warn(`[GameRuntime] skipped ${s.name}: содержит небезопасный tight-loop (WaitForChild/ChildAdded:wait)`); + continue; + } if (luaSource && luaSource.trim()) { // Эвристика Tool: если скрипт ссылается на Equipped/Activated // или Tool = script.Parent — он лежит в Tool. Все Tool-скрипты