/* 224-1a 배수 판 창구(rehome) — 진짜 `observeViewportSize`(B05_Profile_UI_Drainage_Parts.ts)를 * 가짜 창 둘 위에서 돌려 JSON 으로 냄. * · 처음 = 판이 놓인 창(메인)의 관찰자 * · rehome = 옛 관찰자 끊고 지금 놓인 창(새 창)의 관찰자로 · 직전 크기 이어받아 배율 유지 * · disconnect = 지금 관찰자 끊음 */ const fs = require("fs"); const path = require("path"); const { makeLoader } = require("./helper_ts_stub_loader.cjs"); const ROOT = path.join(__dirname, "..", ".."); const stub = new Proxy({}, { get: () => () => "" }); /** TS 한 장을 CommonJS 로 — 상대 경로는 진짜(공용 창 · 지도 셈만), 나머지는 빈 함수. */ const { loadTs } = makeLoader({ root: ROOT, requireFor: (full) => (request) => /common_util_view_window|B04_PreProcess_UI_MapRender/.test(request) ? loadTs(path.join(path.dirname(full), `${request}.ts`)) : stub, }); /** 가짜 창 — 관찰자를 모아 두고 크기를 바꿔 울림. */ function fakeWindow(name) { const win = { name, observers: [] }; win.ResizeObserver = class { constructor(fn) { this.fn = fn; this.live = false; win.observers.push(this); } observe() { this.live = true; } disconnect() { this.live = false; } }; return win; } const main = fakeWindow("main"); const popup = fakeWindow("popup"); global.window = main; const parts = loadTs(path.join(ROOT, "B05_Profile", "B05_Profile_UI_Drainage_Parts.ts")); const doc = { defaultView: main }; let size = { width: 400, height: 300 }; const viewport = { ownerDocument: doc, getBoundingClientRect: () => ({ ...size }) }; const fire = (win) => win.observers.filter((o) => o.live).forEach((o) => o.fn()); let view = { scale: 2, offsetX: 10, offsetY: -5 }; const applied = []; let redraws = 0; const META = { x_min: 0, x_max: 4000, y_min: 0, y_max: 3000, width_meters: 4000, height_meters: 3000, }; const watcher = parts.observeViewportSize(viewport, { meta: () => META, anchor: () => ({ width: 0, height: 0, ...view }), apply: (next) => (applied.push(next), (view = next)), redraw: () => (redraws += 1), }); const out = { firstOwner: main.observers.length === 1 && popup.observers.length === 0 }; fire(main); // 처음 크기 기억 out.firstApplied = applied.length; // 새 창으로 옮김 — 메인 관찰자 끊고 새 창 관찰자로 doc.defaultView = popup; watcher.rehome(); out.mainLive = main.observers.some((o) => o.live); out.popupLive = popup.observers.filter((o) => o.live).length; size = { width: 800, height: 600 }; // 새 창에서 두 배로 커짐 fire(popup); out.afterGrow = { applied: applied.length, ...view }; // 메인 창 관찰자가 울려도(이미 끊김) 아무 일 없음 fire(main); out.mainIgnored = applied.length; // 제자리 — 다시 메인 doc.defaultView = main; watcher.rehome(); out.backPopupLive = popup.observers.some((o) => o.live); out.backMainLive = main.observers.filter((o) => o.live).length; watcher.disconnect(); out.afterDispose = [...main.observers, ...popup.observers].some((o) => o.live); out.redraws = redraws; process.stdout.write(JSON.stringify(out));