Files
youle_cocos/cocoscreator_projects/scripts/verify-room-resource-cycles.mjs
joywayer 35216f75e7 feat: integrate room framework and isolated subgame bundles
Complete room UI and protocol integration, move game definitions and resources behind bundle entries, publish authoritative version XML, and document single-game builds. Include all current resource changes and experiment artifacts.
2026-09-09 03:13:18 +08:00

21 lines
2.6 KiB
JavaScript

/** Actual Cocos allocations and event ownership; no network game session or server mutation. */
export async function verifyRoomResourceCycles(avatarUrl){
const e=await System.import('cc'),modules=Array.from(System.entries()).map(([,m])=>m),get=name=>modules.find(m=>m[name])?.[name];
const assert=(ok,message)=>{if(!ok)throw Error(message);},tick=()=>new Promise(r=>setTimeout(r,25));
const canvas=e.director.getScene().getChildByName('Canvas'),startup=e.director.getScene().getComponentInChildren('PlatformStartup'),cache=get('roomAvatarCache'),Ui=get('RoomUi');
const owners=new Ui(message=>{throw Error(message);});const nodes=[new e.Node('avatar-test-a'),new e.Node('avatar-test-b')];
nodes.forEach(node=>{node.parent=canvas;node.addComponent(e.Sprite);owners.avatar(node,avatarUrl);});
const lease=cache.acquire(avatarUrl),asset=await lease.value;lease.release();await tick();
assert(nodes.every(node=>node.getComponent(e.Sprite).spriteFrame===asset.frame),'same URL shares one actual SpriteFrame');assert(cache.leases===2,'each node owns one lease');owners.dispose();nodes.forEach(node=>node.destroy());await tick();assert(cache.leases===0,'avatar owners release all leases');
const Chat=get('RoomChatPanel'),definitions={erqiwang:e.js.getClassByName('GameEntry_erqiwang').definition,Game_Surface_3:e.js.getClassByName('GameEntry_Game_Surface_3').definition},Scope=get('RoomScope');
const baseline=canvas.children.length;let current=null;let count=0;
for(let i=0;i<100;i++){
const scope=new Scope(i+1,()=>{});current=new Chat(canvas,startup.roomChatPrefab,startup.chatPhrasePrefab,startup.chatHistoryPrefab,definitions.erqiwang.chat,{text(){},phrase(){},expression(){},voice(){},error:message=>{throw Error(message);},readAnnouncements(){}});
const owned=current;scope.own(()=>owned.dispose());
current.open();current.select('History');current.render({app:{phase:'logged-in'},room:{kind:'inside'},roomSocial:{history:[{id:i+1,kind:'text',sender:{nickname:'cycle '+i,avatar:avatarUrl},text:'生命周期检查'}],announcements:[]}},false,'');
await tick();const errors=scope.dispose();assert(errors.length===0,'scope release has no errors');assert(scope.resourceCount===0,'scope owns no resources after leave');current=null;await tick();count++;
}
assert(canvas.children.length===baseline,'100 UI room scopes return node count to baseline');assert(cache.leases===0,'100 UI room scopes return avatar leases to zero');
return {cycles:count,nodesBefore:baseline,nodesAfter:canvas.children.length,activeAvatarLeases:cache.leases,cachedAvatarResources:cache.size,sharedSpriteFrame:true};
}