95 lines
3.4 KiB
JavaScript
95 lines
3.4 KiB
JavaScript
// DOM 环境冒烟:mock 浏览器 API,跑通入口 main.js 的初始化 + 若干帧
|
|
const noop = () => { };
|
|
const els = new Map();
|
|
|
|
function mkEl(id = '') {
|
|
const el = {
|
|
id, tagName: 'DIV', value: '', textContent: '', innerHTML: '',
|
|
style: {}, dataset: {}, children: [], width: 800, height: 608,
|
|
classList: { add: noop, remove: noop, toggle: noop, contains: () => false },
|
|
addEventListener: noop, removeEventListener: noop, appendChild: noop,
|
|
querySelector: () => mkEl(), querySelectorAll: () => [],
|
|
getBoundingClientRect: () => ({ left: 0, top: 0, width: 800, height: 608 }),
|
|
getContext: () => ctx2d,
|
|
focus: noop, click: noop,
|
|
};
|
|
return el;
|
|
}
|
|
const ctx2d = new Proxy({
|
|
canvas: { width: 800, height: 608 },
|
|
measureText: () => ({ width: 12 }),
|
|
createLinearGradient: () => ({ addColorStop: noop }),
|
|
createRadialGradient: () => ({ addColorStop: noop }),
|
|
getImageData: () => ({ data: [] }),
|
|
}, {
|
|
get(t, k) { return k in t ? t[k] : noop; },
|
|
set(t, k, v) { t[k] = v; return true; },
|
|
});
|
|
|
|
const handlers = {};
|
|
const addL = (t, fn) => { (handlers[t] = handlers[t] || []).push(fn); };
|
|
|
|
globalThis.location = { search: '', href: 'http://localhost/', pathname: '/', reload: noop };
|
|
Object.defineProperty(globalThis, 'navigator', { value: { maxTouchPoints: 0, userAgent: 'node' }, configurable: true });
|
|
globalThis.matchMedia = q => ({ matches: false, media: q, addEventListener: noop, removeEventListener: noop });
|
|
globalThis.window = {
|
|
addEventListener: addL, removeEventListener: noop,
|
|
AudioContext: null, webkitAudioContext: null,
|
|
innerWidth: 1280, innerHeight: 800,
|
|
location: globalThis.location, navigator: globalThis.navigator,
|
|
matchMedia: globalThis.matchMedia,
|
|
};
|
|
globalThis.addEventListener = addL;
|
|
globalThis.removeEventListener = noop;
|
|
globalThis.confirm = () => true;
|
|
globalThis.alert = noop;
|
|
globalThis.localStorage = {
|
|
_d: {},
|
|
getItem(k) { return this._d[k] ?? null; },
|
|
setItem(k, v) { this._d[k] = String(v); },
|
|
removeItem(k) { delete this._d[k]; },
|
|
};
|
|
globalThis.document = {
|
|
getElementById(id) { if (!els.has(id)) els.set(id, mkEl(id)); return els.get(id); },
|
|
querySelector(s) { return mkEl(s); },
|
|
querySelectorAll() { return []; },
|
|
createElement(t) { const e = mkEl(); e.tagName = t.toUpperCase(); return e; },
|
|
addEventListener: addL,
|
|
body: mkEl('body'),
|
|
};
|
|
let frames = 0;
|
|
globalThis.requestAnimationFrame = (fn) => {
|
|
if (frames++ > 12) return 0;
|
|
setTimeout(() => fn(performance.now() + frames * 16.7), 0);
|
|
return frames;
|
|
};
|
|
|
|
try {
|
|
await import('../js/main.js');
|
|
console.log('✅ main.js 初始化成功');
|
|
} catch (e) {
|
|
console.log('❌ main.js 初始化失败: ' + e.message);
|
|
console.log(e.stack.split('\n').slice(0, 5).join('\n'));
|
|
process.exit(1);
|
|
}
|
|
|
|
// 等几帧
|
|
await new Promise(r => setTimeout(r, 200));
|
|
|
|
const { LEVELS } = await import('../js/levels/index.js');
|
|
const api = globalThis.window.__IW;
|
|
console.log('✅ 已跑 ' + frames + ' 帧,状态=' + (api ? api.G.state : '?'));
|
|
if (api) {
|
|
// 逐个关卡启动一次,确认不炸
|
|
let bad = 0;
|
|
for (const lv of LEVELS) {
|
|
try {
|
|
api.startLevel(lv, lv.index ?? -1);
|
|
for (let i = 0; i < 90; i++) { /* 由 rAF 驱动,这里只验证构造 */ }
|
|
if (!api.G.level || !api.G.player) throw new Error('未创建关卡');
|
|
} catch (e) { console.log(' ✗ ' + lv.id + ': ' + e.message); bad++; }
|
|
}
|
|
console.log(bad ? `❌ ${bad} 个关卡启动失败` : `✅ 全部 ${LEVELS.length} 关均可启动`);
|
|
}
|
|
process.exit(0);
|