'use strict'; const {randomUUID}=require('node:crypto'); // Native ownership only: renderer tab labels never own or replace a WebContents. function createTabRegistry({createView,attach=()=>{},detach=()=>{},dispose=()=>{},maxTabs=32}={}) { if(typeof createView!=='function'||![attach,detach,dispose].every(fn=>typeof fn==='function')||!Number.isSafeInteger(maxTabs)||maxTabs<1||maxTabs>128)throw TypeError('Invalid native tab registry'); const tabs=new Map(),byContents=new Map();let activeId=null,activation=0,policyVersion=0,paused=true,closed=false; const requireTab=id=>{const tab=tabs.get(id);if(!tab||tab.contents.isDestroyed())throw Error('Unknown native tab');return tab;}; const invalidate=tab=>{tab.navigationId++;tab.security.visualApproval=null;tab.security.visualToken='';tab.security.visualRevision=-1;tab.security.visualScanner?.reset();}; function create({group=''}={}) { if(closed||tabs.size>=maxTabs)throw Error('Native tab capacity reached'); if(typeof group!=='string'||group.length>100)throw TypeError('Invalid tab group'); const view=createView(),contents=view?.webContents; if(!contents||!Number.isSafeInteger(contents.id)||contents.isDestroyed()||byContents.has(contents.id))throw Error('Invalid native tab view'); const tab={id:randomUUID(),view,group,navigationId:0,title:'New Tab',color:'#edf1f6',startPage:true,security:{visualApproval:null,visualToken:'',visualRevision:-1,visualPending:null,visualBlocked:null,contentBlocked:null,visualScanner:null}}; Object.defineProperty(tab,'contents',{value:contents,enumerable:false,writable:false,configurable:false}); view.setVisible(false);tabs.set(tab.id,tab);byContents.set(contents.id,tab); if(!activeId)activate(tab.id);return tab; } function activate(id) { const next=requireTab(id);if(id===activeId)return next; const previous=tabs.get(activeId);if(previous){if(!previous.contents.isDestroyed())previous.view.setVisible(false);detach(previous.view);} activeId=id;activation++;attach(next.view);next.view.setVisible(false);return next; } function remove(id) { const tab=tabs.get(id);if(!tab)throw Error('Unknown native tab');const wasActive=id===activeId;invalidate(tab);if(!tab.contents.isDestroyed())tab.view.setVisible(false); tabs.delete(id);byContents.delete(tab.contents.id); if(wasActive){if(!tab.contents.isDestroyed())detach(tab.view);activeId=null;activation++;} try{dispose(tab);}finally{if(!tab.contents.isDestroyed())tab.contents.close({waitForBeforeUnload:false});} if(wasActive&&!closed){const next=[...tabs.values()].find(item=>!item.contents.isDestroyed());if(next)activate(next.id);} } function context(id=activeId,{foreground=true}={}) { const tab=requireTab(id);return Object.freeze({tabId:tab.id,webContents:tab.contents,navigationId:tab.navigationId,url:tab.contents.getURL(),policyVersion,activation:foreground?activation:null,foreground,paused}); } function current(token,{expectedURL=token?.url}={}) { const tab=token&&tabs.get(token.tabId); return !!tab&&!paused&&!token.paused&&!tab.contents.isDestroyed()&&tab.contents===token.webContents&&tab.navigationId===token.navigationId&&policyVersion===token.policyVersion&&tab.contents.getURL()===expectedURL&&(!token.foreground||(activeId===tab.id&&activation===token.activation)); } function quarantine() { paused=true;activation++; for(const tab of tabs.values()){invalidate(tab);if(!tab.contents.isDestroyed()){tab.contents.stop();tab.view.setVisible(false);tab.security.developerToolsGuard?.close();tab.contents.closeDevTools?.();}} } function resume(version) { if(!Number.isSafeInteger(version)||version<1||versionactiveId?requireTab(activeId):null, fromContents:id=>byContents.get(id)||null,all:()=>[...tabs.values()], navigation:id=>invalidate(requireTab(id)), close:()=>{closed=true;quarantine();for(const id of [...tabs.keys()])remove(id);}, summary:()=>({activeTabId:activeId,tabs:[...tabs.values()].map(tab=>({id:tab.id,group:tab.group,title:tab.title,url:tab.contents.getURL(),startPage:tab.startPage,color:tab.color,canGoBack:tab.contents.navigationHistory?.canGoBack()||false,canGoForward:tab.contents.navigationHistory?.canGoForward()||false}))})}; } module.exports={createTabRegistry};