fix(rbxl): пропускаем скрипты с tight-loop WaitForChild через regex

Скрипты 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 и др. Карта потеряет
эту функциональность (раунды, респавн), но играется.
This commit is contained in:
min 2026-06-08 20:53:52 +03:00
parent 38d135586b
commit 4e34ca5b52

View File

@ -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-скрипты