Files
Aislo/resources/tester/helper_298_3_page_dispose.cjs
T
eomsangdonandClaude Opus 5.5 38e6b65f37 test(508-1d 빨강 가림 2/2): 모양 다른 헬퍼 일곱 공용 불러오기로 · 공용 불러오기 옵션 둘(target · rewrite)
- 공용 불러오기: target(트랜스파일 대상) · rewrite(트랜스파일 글 손봄 · import.meta) 옵션
- 280_2(import.meta.env.DEV) · 345_4(import.meta.url) = rewrite · 298_3 = target ES2022
- 322_0 = fileStub(경로 가짜 맵 · .css) · 347 = 파일별 진짜 import 목록 · 427_1 · 459 = load(뿌리 기준)
- 풀이 함수 본문 그대로 · 헬퍼 출력 전 · 후 같음

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-21 18:01:55 +09:00

119 lines
4.2 KiB
JavaScript

/* 298-3 옛 페이지 풀림 단위검증 헬퍼 — `ui_template_window_watch` · `ui_template_overlay_drag` ·
* `design_leave` 를 그 자리에서 트랜스파일 · 페이지를 다섯 번 다시 세운 뒤 창 듣개 수 · 옛 노드 풀림.
* `node --expose-gc` 로 부름 · 결과 JSON 을 stdout 으로.
*/
const path = require("path");
const ts = require(path.join(__dirname, "..", "..", "config", "node_modules", "typescript"));
const { makeLoader, memoryStorage } = require("./helper_ts_stub_loader.cjs");
const ROOT = path.join(__dirname, "..", "..");
const storage = memoryStorage();
const win = new EventTarget();
const doc = new EventTarget();
const counts = { window: 0, document: 0 };
for (const [name, target] of [
["window", win],
["document", doc],
]) {
const add = target.addEventListener.bind(target);
target.addEventListener = (...args) => {
counts[name] += 1;
return add(...args);
};
}
Object.assign(win, {
sessionStorage: storage,
localStorage: storage,
setTimeout,
innerWidth: 1500,
innerHeight: 900,
});
globalThis.window = win;
globalThis.document = doc;
globalThis.sessionStorage = storage;
globalThis.localStorage = storage;
globalThis.requestAnimationFrame = (fn) => (fn(), 1);
let guard = null;
const STUBS = {
"@config/config_frontend": {
ROUTES: { B05_PROFILE: "/b05-profile", B06_SECTION: "/b06-section" },
},
"@ui/ui_template_locale": { t: (key) => key },
"@ui/ui_template_leave_dialog": { leaveOrStay: async () => "stay" },
"../router": { currentRoute: () => "/b05-profile", setLeaveGuard: (fn) => (guard = fn) },
};
const { loadTs } = makeLoader({
root: ROOT,
target: ts.ScriptTarget.ES2022,
requireFor: (full) => (request) => {
if (request in STUBS) return STUBS[request];
if (request.startsWith("@ui/"))
return loadTs(path.join(ROOT, "ui_template", `${request.slice(4)}.ts`));
if (request.startsWith(".")) return loadTs(path.join(path.dirname(full), `${request}.ts`));
return require(request);
},
});
const drag = loadTs(path.join(ROOT, "ui_template", "ui_template_overlay_drag.ts"));
const leave = loadTs(path.join(ROOT, "A00_Common", "design", "design_leave.ts"));
let settles = 0;
function fakeElement() {
const node = new EventTarget();
node.style = {};
node.isConnected = true;
node.offsetWidth = 300;
node.offsetHeight = 40;
node.classList = {
contains: () => false,
add() {},
toggle() {},
remove: () => (settles += 1), // detach 가 부름 = 자리 다시 앉힘
};
node.querySelector = () => null;
node.getBoundingClientRect = () => ({ left: 10, top: 80 });
return node;
}
/** 페이지 한 벌 — 떠남 확인 + 진행단계 패널 · 옛 페이지 노드의 약한 손잡이를 돌려줌. */
function mountPage() {
const page = fakeElement();
const panel = fakeElement();
page.panel = panel; // 페이지 나무 = 패널을 품음
leave.guardDesignLeave("p1", page, async () => {});
page.dragHandle = drag.makePanelDraggable(panel, fakeElement(), "pos");
return { page: new WeakRef(page), panel: new WeakRef(panel), keep: page };
}
(async () => {
const out = {};
let live = mountPage();
out.afterFirst = { ...counts };
const old = [];
for (let index = 0; index < 4; index += 1) {
live.keep.isConnected = false; // 다시 세움 — 옛 페이지는 화면에서 빠지고 버려짐
old.push({ page: live.page, panel: live.panel });
live = mountPage();
}
out.afterFive = { ...counts };
await new Promise((resolve) => setTimeout(resolve, 0));
globalThis.gc();
await new Promise((resolve) => setTimeout(resolve, 0));
globalThis.gc();
out.oldAlive = old.filter((pair) => pair.page.deref() || pair.panel.deref()).length;
out.liveAlive = Boolean(live.page.deref() && live.panel.deref());
// 살아 있는 패널은 창 크기 바뀜을 여전히 들음 · 버려진 패널은 안 부름
settles = 0;
win.dispatchEvent(new Event("resize"));
out.resizeSettles = settles;
// 떠남 확인 — 살아 있는 페이지만(고침 없음 = 안 막음)
const event = new Event("beforeunload", { cancelable: true });
win.dispatchEvent(event);
out.unloadBlocked = event.defaultPrevented;
out.guardSet = typeof guard === "function";
process.stdout.write(JSON.stringify(out));
})();