- 원인 B06 = 구조물을 놓으면 새 측점 카드가 빈 설계로 먼저 서고 다시 셈 뒤 화면 밖 카드는 쉬는 틈 줄에서만 갈아 끼움 · 시간 제한이 없어 틈이 안 오는 창(ORCA 내장 · 가려진 창)에서는 설계선 · 옹벽 없는 카드가 그대로 남음(검증_sub1 옹벽 7+5 · 7+10 재현 · 다시 셈 값은 맞음) - 고침 = createIdleQueue 쉬는 틈 한도 200 ms(늦어도 그 안에 그림) - 원인 B05 = 「횡단」 판이 고름 바뀜만 들어 고른 구조물을 들고 들어오면 빈 판 · 다시 누르면 고름이 풀림 - 고침 = 판 만들 때 지금 고름을 한 번 따라감(판은 안 폄) - 시험 test_494_1_idle_queue(쉬는 틈 없는 창 흉내 · 들어올 때 고름 · 고치기 전 빨강) · helper_411_a 에 readSelection 흉내 · 들어옴 장면 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
52 lines
2.3 KiB
JavaScript
52 lines
2.3 KiB
JavaScript
/* PLAN 494-1 단위검증 헬퍼 — 화면 밖 횡단 카드 줄(`createIdleQueue`)이 쉬는 틈이 안 와도 그려지는가.
|
|
* `B06_Section_UI_Section_Common.ts` 에서 그 함수만 꺼내 트랜스파일해 Node 로 돌린다(다른 import 안 끎).
|
|
* 가짜 창 = 쉬는 틈이 영영 안 오는 브라우저(ORCA 내장 · 가려진 창) — 시간 제한을 준 부탁만 그 시간에 불림.
|
|
* 결과는 표준출력에 JSON 한 벌.
|
|
*/
|
|
const fs = require("fs");
|
|
const path = require("path");
|
|
const ts = require(path.join(__dirname, "..", "..", "config", "node_modules", "typescript"));
|
|
|
|
const file = path.join(__dirname, "..", "..", "B06_Section", "B06_Section_UI_Section_Common.ts");
|
|
const src = fs.readFileSync(file, "utf-8").split("\r\n").join("\n");
|
|
const body = src.match(/export function createIdleQueue[\s\S]*?\n}\n/);
|
|
if (!body) throw new Error("createIdleQueue 못 찾음");
|
|
// 함수가 쓰는 파일 머리 상수(대문자 이름 한 줄)
|
|
const consts = [...src.matchAll(/^const [A-Z_]+ = [^;\n]+;$/gm)].map((m) => m[0]).join("\n");
|
|
const js = ts.transpileModule(`${consts}\n${body[0]}`, {
|
|
compilerOptions: { module: ts.ModuleKind.CommonJS, target: ts.ScriptTarget.ES2020 },
|
|
}).outputText;
|
|
|
|
let now = 0;
|
|
const timers = []; // { at, fn }
|
|
const window = {
|
|
requestIdleCallback: (fn, options) => {
|
|
// 쉬는 틈 없음 — 시간 제한이 있을 때만 그 시간에 부름(didTimeout)
|
|
if (options && Number.isFinite(options.timeout))
|
|
timers.push({
|
|
at: now + options.timeout,
|
|
fn: () => fn({ didTimeout: true, timeRemaining: () => 0 }),
|
|
});
|
|
return timers.length + 1;
|
|
},
|
|
setTimeout: (fn, ms) => (timers.push({ at: now + (ms || 0), fn }), timers.length + 1),
|
|
};
|
|
const mod = { exports: {} };
|
|
new Function("module", "exports", "window", js)(mod, mod.exports, window);
|
|
const { createIdleQueue } = mod.exports;
|
|
|
|
const ran = [];
|
|
const q = createIdleQueue((m) => ran.push(m), 2);
|
|
[145, 150, 155, 160, 165].forEach((m) => q.queue.add(m));
|
|
q.drain();
|
|
// 2 초 흐름 — 그 사이 불릴 것 모두 부름
|
|
for (;;) {
|
|
timers.sort((a, b) => a.at - b.at);
|
|
const next = timers[0];
|
|
if (!next || next.at > 2000) break;
|
|
timers.shift();
|
|
now = next.at;
|
|
next.fn();
|
|
}
|
|
process.stdout.write(JSON.stringify({ ran, left: [...q.queue], elapsedMs: now }));
|