• Nikitos's avatar
    Работа кусками по кадрам: $.task и $.scene.loadAsync
    · 265d395a
    Nikitos создал
    Пробел из docs/TASKS.md §12.5: был только `$.loading.run`, который выполняет ПО
    ОДНОМУ шагу за кадр — если шаг сам длинный (генерация карты, тёплая загрузка),
    кадр всё равно замирает. Фоновой загрузки не было вовсе.
    
    * createScheduler()/createGeneratorScheduler() — чистые планировщики: работа
      делится по ВРЕМЕНИ (бюджет мс на кадр), а не по числу шагов;
    * $.task.chunked({ total, step, budget, label, done }) — шаги по индексу;
      $.task.each(generator) — генератор сам решает, когда закончил; $.task.list() —
      список по кадрам; running()/abortAll();
    * label показывает и обновляет экран загрузки; done(cancelled) сообщает об
      отмене или исключении — исключение внутри шага отменяет задачу, а не роняет
      кадр;
    * $.scene.loadAsync(name, { steps }) — экран загрузки, шаги по кадрам и только
      потом переход в сцену;
    * бюджет проверяется не на каждой итерации (вызов часов сам стоит времени), а
      раз в четыре; нулевой и отрицательный бюджет поднимаются до минимума, чтобы
      цикл не зависал.
    
    Тест нашёл настоящую ловушку QuickJS: у генераторной функции нет `.next`
    (в отличие от V8), поэтому `$.task.each(function*(){…})` падал. Теперь
    планировщик принимает и функцию, и готовый итератор.
    
    Проверка: tests/js/task_test.mjs (11 проверок: бюджет, продолжение с того же
    места, прогресс, отмена, исключение, генератор), полный набор qjs и агентских
    тестов зелёный.
    265d395a