const assert = require('node:assert/strict'); const fs = require('node:fs'); const vm = require('node:vm'); const ts = require('typescript'); const source = ts.transpileModule( fs.readFileSync('assets/Script/module/Tool/GameTool.ts', 'utf8'), { compilerOptions: { target: ts.ScriptTarget.ES2017, module: ts.ModuleKind.CommonJS } }, ).outputText; const subpackageRequests = []; const bundleRequests = []; const bundles = new Map(); let activePrefabLoads = 0; let maxPrefabLoads = 0; let instantiateCalls = 0; let deviceInfo = { platform: 'android', memorySize: 2048 }; const wx = { getDeviceInfo: () => deviceInfo, preDownloadSubpackage(options) { subpackageRequests.push(options); }, }; const cc = { Prefab: class {}, sys: { WECHAT_GAME: 'wechat', platform: 'wechat', OS_ANDROID: 'Android', OS_IOS: 'iOS', os: 'Android', }, fx: {}, game: {}, director: { getScene: () => ({ name: 'HomeScene' }) }, warn() {}, instantiate() { instantiateCalls++; throw new Error('Home warmup must not instantiate'); }, assetManager: { getBundle: name => bundles.get(name) || null, removeBundle(bundle) { bundles.delete(bundle.name); }, loadBundle(name, callback) { bundleRequests.push(name); activePrefabLoads++; maxPrefabLoads = Math.max(maxPrefabLoads, activePrefabLoads); const bundle = { name, releaseAll() {}, load(path, type, done) { setImmediate(() => { activePrefabLoads--; done(null, { path }); }); }, }; bundles.set(name, bundle); setImmediate(() => callback(null, bundle)); }, }, }; const moduleObject = { exports: {} }; vm.runInNewContext(source, { module: moduleObject, exports: moduleObject.exports, require: () => ({ default: {}, MiniGameSdk: { API: {} } }), cc, wx, console, setTimeout, clearTimeout, setImmediate, }); const gameTool = moduleObject.exports.GameTool; cc.fx.GameTool = gameTool; (async () => { const diskReady = gameTool.predownloadGameplayPopupSubpackages(false); assert.equal(subpackageRequests.length, 5, 'all five disk downloads should start together'); const expectedOrder = ['pause', 'win', 'propWindow', 'NewMode', 'lose']; assert.deepEqual(subpackageRequests.map(request => request.name), expectedOrder, 'disk requests must follow the gameplay warmup order'); subpackageRequests.forEach(request => request.success()); assert.equal(await diskReady, true); assert.equal(await gameTool.warmupHomeGameplayPopupAssets(), true); assert.deepEqual(bundleRequests, expectedOrder, 'Bundle requests must use the same order'); assert.equal(maxPrefabLoads, 2, 'Prefab decode concurrency must stay at two'); assert.equal(instantiateCalls, 0, 'HomeScene must not instantiate popup nodes'); assert.equal(gameTool.beginGameplayPopupGameSceneReloadRetention(), true); assert.equal(gameTool.shouldRetainGameplayPopupBundlesForGameSceneReload(), true); gameTool.finishGameplayPopupGameSceneReloadRetention(); assert.equal(gameTool.shouldRetainGameplayPopupBundlesForGameSceneReload(), false); deviceInfo = { platform: 'ios', memorySize: 4096 }; cc.sys.os = cc.sys.OS_IOS; assert.equal(gameTool.beginGameplayPopupGameSceneReloadRetention(), false, 'low-memory iOS must never retain bundles across GameScene reload'); console.log('Popup preload and retention policy checks passed'); })().catch(error => { console.error(error); process.exitCode = 1; });