fix(lab-content-engine): браузерные баги Фаз 3-4 + чинка сломанного merge

1. cirSim ReferenceError в _pauseAllSims/closeSim (регрессия Фазы 3): глобалы
   экземпляров симуляций объявлены в ленивых файлах -> не существуют до открытия.
   Предсоздаём их как window-свойства (null) -> guard'ы безопасны. (lab-init.js)
2. theory-data.js (вынос THEORY параллельной сессией) не подключался в lab.html
   -> панель теории и fallback loadTheory ломались. Добавил перед _register-all.
3. _pilots.js удалён в Фазе 1, но lab.html ссылался -> 404. Убрал ссылку.
4. /api/lab/sims 500 на неотмигрированном/устаревшем инстансе -> деградация:
   возвращаем пустой каталог + needs_migration вместо 500. (routes/lab.js)

Проверка: vm-доказательство (_pauseAllSims без throw), node --check всех файлов,
lab-sims тесты 11/11. ВАЖНО: на работающем dev-сервере нужен ПЕРЕЗАПУСК (сервер
не авто-мигрирует) — таблица lab_sims уже в live БД.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Maxim Dolgolyov
2026-05-30 16:02:30 +03:00
parent f8c68f940d
commit 9754773324
2 changed files with 23 additions and 1 deletions
+10 -1
View File
@@ -44,7 +44,16 @@ function rowToSim(r) {
/* ── GET /api/lab/sims ─────────────────────────────────────────────────── */
router.get('/sims', (_req, res) => {
const rows = db.prepare(`SELECT * FROM lab_sims ORDER BY sort_order, id`).all();
let rows;
try {
rows = db.prepare(`SELECT * FROM lab_sims ORDER BY sort_order, id`).all();
} catch (e) {
// Деградация вместо 500: если миграция lab_sims ещё не применена на этом
// инстансе (старый процесс/другая БД) — отдаём пустой каталог, чтобы админка
// не падала. Нужно применить миграцию и перезапустить сервер.
console.warn('[lab] lab_sims недоступна (нужна миграция/перезапуск):', e.message);
return res.json({ module_disabled: readModuleDisabled(), sims: [], needs_migration: true });
}
const legacyDisabled = readLegacyDisabledIds();
const sims = rows.map(r => {
const s = rowToSim(r);
+13
View File
@@ -30,6 +30,19 @@
var geomSim = null;
var qualSim = null;
/* Контент-движок, Фаза 3 (ленивая загрузка): часть глобалов с экземплярами
симуляций объявляется внутри их собственных НЫНЕ ЛЕНИВЫХ файлов, поэтому до
первого открытия такой симуляции они не существуют. Legacy-«дробовик»
_pauseAllSims()/closeSim() ссылается на них по голому имени, что до загрузки
любого файла бросало ReferenceError (напр. cirSim). Предсоздаём эти имена как
свойства window (null), чтобы guard'ы безопасно давали false; при загрузке
файла симуляции его собственный var/присваивание обновит тот же глобал. */
['cirSim','reacSim','flaskSim','newtonSim','sandboxSim','crystalSim','orbitalsSim',
'stereoSim','angryBirdsSim','trigSim','pendSim','radioactiveSim','heSim',
'periodicSim','organicSim','_solutionsSim','mirrorSim'].forEach(function (_n) {
if (!(_n in window)) window[_n] = null;
});
var ALL_SIM_BODIES = ['sim-graph','sim-proj','sim-coll','sim-tri','sim-trigcircle','sim-emfield',
'sim-molphys',
'sim-circuit','sim-chemistry','sim-dynamics',