text: import*as Common from"../common/common.js";import*as SDK from"../sdk/sdk.js";import*as Workspace from"../workspace/workspace.js";import{DebuggerWorkspaceBinding}from"./DebuggerWorkspaceBinding.js";import{LiveLocation,LiveLocationPool}from"./LiveLocation.js";let breakpointManagerInstance;export class BreakpointManager extends Common.ObjectWrapper.ObjectWrapper{constructor(e,t,i){super(),this._storage=new Storage,this._workspace=t,this._targetManager=e,this._debuggerWorkspaceBinding=i,this._breakpointsForUISourceCode=new Map,this._breakpointByStorageId=new Map,this._workspace.addEventListener(Workspace.Workspace.Events.UISourceCodeAdded,this._uiSourceCodeAdded,this),this._workspace.addEventListener(Workspace.Workspace.Events.UISourceCodeRemoved,this._uiSourceCodeRemoved,this)}static instance(e={forceNew:null,targetManager:null,workspace:null,debuggerWorkspaceBinding:null}){const{forceNew:t,targetManager:i,workspace:o,debuggerWorkspaceBinding:r}=e;if(!breakpointManagerInstance||t){if(!i||!o||!r)throw new Error("Unable to create settings: targetManager, workspace, and debuggerWorkspaceBinding must be provided: "+(new Error).stack);breakpointManagerInstance=new BreakpointManager(i,o,r)}return breakpointManagerInstance}static _breakpointStorageId(e,t,i){return e?e+":"+t+":"+i:""}async copyBreakpoints(e,t){const i=this._storage.breakpointItems(e);for(const e of i)await this.setBreakpoint(t,e.lineNumber,e.columnNumber,e.condition,e.enabled)}_restoreBreakpoints(e){const t=e.url();if(!t)return;this._storage.mute();const i=this._storage.breakpointItems(t);for(const t of i)this._innerSetBreakpoint(e,t.lineNumber,t.columnNumber,t.condition,t.enabled);this._storage.unmute()}_uiSourceCodeAdded(e){const t=e.data;this._restoreBreakpoints(t)}_uiSourceCodeRemoved(e){const t=e.data;this.breakpointLocationsForUISourceCode(t).forEach(e=>e.breakpoint.removeUISourceCode(t))}async setBreakpoint(e,t,i,o,r){let n=new Workspace.UISourceCode.UILocation(e,t,i);const s=await this._debuggerWorkspaceBinding.normalizeUILocation(n);return s.id()!==n.id()&&(Common.Revealer.reveal(s),n=s),this._innerSetBreakpoint(n.uiSourceCode,n.lineNumber,n.columnNumber,o,r)}_innerSetBreakpoint(e,t,i,o,r){const n=BreakpointManager._breakpointStorageId(e.url(),t,i);let s=this._breakpointByStorageId.get(n);return s?(s._updateState(o,r),s.addUISourceCode(e),s._updateBreakpoint(),s):(s=new Breakpoint(this,e,e.url(),t,i,o,r),this._breakpointByStorageId.set(n,s),s)}findBreakpoint(e){const t=this._breakpointsForUISourceCode.get(e.uiSourceCode);return t&&t.get(e.id())||null}async possibleBreakpoints(e,t){const i=DebuggerWorkspaceBinding.instance().uiLocationToRawLocations(e,t.startLine,t.startColumn),o=DebuggerWorkspaceBinding.instance().uiLocationToRawLocations(e,t.endLine,t.endColumn),[r,n]=await Promise.all([i,o]),s=new Map;for(const e of n)s.set(e.debuggerModel,e);let a=null,d=null;for(const e of r){const t=s.get(e.debuggerModel);if(t){a=e,d=t;break}}return a&&d?a.debuggerModel.getPossibleBreakpoints(a,d,!1).then(async function(t){const i=t.map(e=>this._debuggerWorkspaceBinding.rawLocationToUILocation(e));let o=await Promise.all(i);if(o=o.filter(t=>t&&t.uiSourceCode===e),!o.length)return[];o.sort(Workspace.UISourceCode.UILocation.comparator);let r=o[0];const n=[r];for(const e of o)e.id()!==r.id()&&(n.push(e),r=e);return n}.bind(this)):Promise.resolve([])}breakpointLocationsForUISourceCode(e){const t=this._breakpointsForUISourceCode.get(e);return t?Array.from(t.values()):[]}allBreakpointLocations(){const e=[];for(const t of this._breakpointsForUISourceCode.values())e.push(...t.values());return e}_removeBreakpoint(e,t){t&&this._storage._removeBreakpoint(e),this._breakpointByStorageId.delete(e._breakpointStorageId())}_uiLocationAdded(e,t){let i=this._breakpointsForUISourceCode.get(t.uiSourceCode);i||(i=new Map,this._breakpointsForUISourceCode.set(t.uiSourceCode,i));const o={breakpoint:e,uiLocation:t};i.set(t.id(),o),this.dispatchEventToListeners(Events.BreakpointAdded,o)}_uiLocationRemoved(e,t){const i=this._breakpointsForUISourceCode.get(t.uiSourceCode);if(!i)return;i.get(t.id())&&(i.delete(t.id()),0===i.size&&this._breakpointsForUISourceCode.delete(t.uiSourceCode),this.dispatchEventToListeners(Events.BreakpointRemoved,{breakpoint:e,uiLocation:t}))}}export const Events={BreakpointAdded:Symbol("breakpoint-added"),BreakpointRemoved:Symbol("breakpoint-removed")};export class Breakpoint{constructor(e,t,i,o,r,n,s){this._breakpointManager=e,this._url=i,this._lineNumber=o,this._columnNumber=r,this._uiLocations=new Set,this._uiSourceCodes=new Set,this._condition,this._enabled,this._isRemoved,this._currentState=null,this._modelBreakpoints=new Map,this._updateState(n,s),this.addUISourceCode(t),this._breakpointManager._targetManager.observeModels(SDK.DebuggerModel.DebuggerModel,this)}async refreshInDebugger(){if(!this._isRemoved){const e=Array.from(this._modelBreakpoints.values());return Promise.all(e.map(e=>e._refreshBreakpoint()))}}modelAdded(e){const t=this._breakpointManager._debuggerWorkspaceBinding;this._modelBreakpoints.set(e,new ModelBreakpoint(e,this,t))}modelRemoved(e){const t=this._modelBreakpoints.get(e);this._modelBreakpoints.delete(e),t._cleanUpAfterDebuggerIsGone(),t._removeEventListeners()}addUISourceCode(e){this._uiSourceCodes.has(e)||(this._uiSourceCodes.add(e),this.bound()||this._breakpointManager._uiLocationAdded(this,this._defaultUILocation(e)))}clearUISourceCodes(){this.bound()||this._removeAllUnboundLocations(),this._uiSourceCodes.clear()}removeUISourceCode(e){if(this._uiSourceCodes.has(e)&&(this._uiSourceCodes.delete(e),this.bound()||this._breakpointManager._uiLocationRemoved(this,this._defaultUILocation(e))),this.bound()){for(const t of this._uiLocations)t.uiSourceCode===e&&(this._uiLocations.delete(t),this._breakpointManager._uiLocationRemoved(this,t));this.bound()||this._isRemoved||this._addAllUnboundLocations()}}url(){return this._url}lineNumber(){return this._lineNumber}columnNumber(){return this._columnNumber}_uiLocationAdded(e){this._isRemoved||(this.bound()||this._removeAllUnboundLocations(),this._uiLocations.add(e),this._breakpointManager._uiLocationAdded(this,e))}_uiLocationRemoved(e){this._uiLocations.has(e)&&(this._uiLocations.delete(e),this._breakpointManager._uiLocationRemoved(this,e),this.bound()||this._isRemoved||this._addAllUnboundLocations())}enabled(){return this._enabled}bound(){return 0!==this._uiLocations.size}setEnabled(e){this._updateState(this._condition,e)}condition(){return this._condition}setCondition(e){this._updateState(e,this._enabled)}_updateState(e,t){this._enabled===t&&this._condition===e||(this._enabled=t,this._condition=e,this._breakpointManager._storage._updateBreakpoint(this),this._updateBreakpoint())}_updateBreakpoint(){this.bound()||(this._removeAllUnboundLocations(),this._isRemoved||this._addAllUnboundLocations());for(const e of this._modelBreakpoints.values())e._scheduleUpdateInDebugger()}remove(e){this._isRemoved=!0;const t=!e;for(const e of this._modelBreakpoints.values())e._scheduleUpdateInDebugger(),e._removeEventListeners();this._breakpointManager._removeBreakpoint(this,t),this._breakpointManager._targetManager.unobserveModels(SDK.DebuggerModel.DebuggerModel,this),this.clearUISourceCodes()}_breakpointStorageId(){return BreakpointManager._breakpointStorageId(this._url,this._lineNumber,this._columnNumber)}_resetLocations(){this.clearUISourceCodes();for(const e of this._modelBreakpoints.values())e._resetLocations()}_defaultUILocation(e){return e.uiLocation(this._lineNumber,this._columnNumber)}_removeAllUnboundLocations(){for(const e of this._uiSourceCodes)this._breakpointManager._uiLocationRemoved(this,this._defaultUILocation(e))}_addAllUnboundLocations(){for(const e of this._uiSourceCodes)this._breakpointManager._uiLocationAdded(this,this._defaultUILocation(e))}}export class ModelBreakpoint{constructor(e,t,i){this._debuggerModel=e,this._breakpoint=t,this._debuggerWorkspaceBinding=i,this._liveLocations=new LiveLocationPool,this._uiLocations=new Map,this._debuggerModel.addEventListener(SDK.DebuggerModel.Events.DebuggerWasDisabled,this._cleanUpAfterDebuggerIsGone,this),this._debuggerModel.addEventListener(SDK.DebuggerModel.Events.DebuggerWasEnabled,this._scheduleUpdateInDebugger,this),this._hasPendingUpdate=!1,this._isUpdating=!1,this._cancelCallback=!1,this._currentState=null,this._debuggerModel.debuggerEnabled()&&this._scheduleUpdateInDebugger()}_resetLocations(){for(const e of this._uiLocations.values())this._breakpoint._uiLocationRemoved(e);this._uiLocations.clear(),this._liveLocations.disposeAll()}_scheduleUpdateInDebugger(){this._isUpdating?this._hasPendingUpdate=!0:(this._isUpdating=!0,this._updateInDebugger(this._didUpdateInDebugger.bind(this)))}_didUpdateInDebugger(){this._isUpdating=!1,this._hasPendingUpdate&&(this._hasPendingUpdate=!1,this._scheduleUpdateInDebugger())}_scriptDiverged(){for(const e of this._breakpoint._uiSourceCodes){const t=this._debuggerWorkspaceBinding.scriptFile(e,this._debuggerModel);if(t&&t.hasDivergedFromVM())return!0}return!1}async _updateInDebugger(e){if(this._debuggerModel.target().isDisposed())return this._cleanUpAfterDebuggerIsGone(),void e();const t=this._breakpoint._lineNumber,i=this._breakpoint._columnNumber,o=this._breakpoint.condition();let r,n,s=null;for(const e of this._breakpoint._uiSourceCodes){if(s=(await DebuggerWorkspaceBinding.instance().uiLocationToRawLocations(e,t,i)).find(e=>e.debuggerModel===this._debuggerModel),s)break}if(this._breakpoint._isRemoved||!this._breakpoint.enabled()||this._scriptDiverged())r=null;else if(s&&s.script()){const e=s.script();r=e.sourceURL?new Breakpoint.State(e.sourceURL,null,null,s.lineNumber,s.columnNumber,o):new Breakpoint.State(null,e.scriptId,e.hash,s.lineNumber,s.columnNumber,o)}else if(this._breakpoint._currentState&&this._breakpoint._currentState.url){const e=this._breakpoint._currentState;r=new Breakpoint.State(e.url,null,null,e.lineNumber,e.columnNumber,o)}else this._breakpoint._uiSourceCodes.size>0&&(r=new Breakpoint.State(this._breakpoint.url(),null,null,t,i,o));if(!this._debuggerId||!Breakpoint.State.equals(r,this._currentState))return this._breakpoint._currentState=r,this._debuggerId?(await this._refreshBreakpoint(),void e()):void(r?(this._currentState=r,r.url?n=await this._debuggerModel.setBreakpointByURL(r.url,r.lineNumber,r.columnNumber,r.condition):r.scriptId&&r.scriptHash&&(n=await this._debuggerModel.setBreakpointInAnonymousScript(r.scriptId,r.scriptHash,r.lineNumber,r.columnNumber,r.condition)),n&&n.breakpointId?await this._didSetBreakpointInDebugger(e,n.breakpointId,n.locations):await this._didSetBreakpointInDebugger(e,null,[])):e());e()}async _refreshBreakpoint(){this._debuggerId&&(this._resetLocations(),await this._debuggerModel.removeBreakpoint(this._debuggerId),this._didRemoveFromDebugger(),this._currentState=null,this._scheduleUpdateInDebugger())}async _didSetBreakpointInDebugger(e,t,i){if(this._cancelCallback)return this._cancelCallback=!1,void e();if(!t)return this._breakpoint.remove(!0),void e();this._debuggerId=t,this._debuggerModel.addBreakpointListener(this._debuggerId,this._breakpointResolved,this);for(const e of i)if(!await this._addResolvedLocation(e))break;e()}_didRemoveFromDebugger(){this._cancelCallback?this._cancelCallback=!1:(this._resetLocations(),this._debuggerModel.removeBreakpointListener(this._debuggerId,this._breakpointResolved,this),delete this._debuggerId)}async _breakpointResolved(e){await this._addResolvedLocation(e.data)}async _locationUpdated(e){const t=this._uiLocations.get(e),i=await e.uiLocation();t&&this._breakpoint._uiLocationRemoved(t),i?(this._uiLocations.set(e,i),this._breakpoint._uiLocationAdded(i)):this._uiLocations.delete(e)}async _addResolvedLocation(e){const t=await this._debuggerWorkspaceBinding.rawLocationToUILocation(e);if(!t)return!1;const i=this._breakpoint._breakpointManager.findBreakpoint(t);return i&&i.breakpoint!==this._breakpoint?(this._breakpoint.remove(!1),!1):(await this._debuggerWorkspaceBinding.createLiveLocation(e,this._locationUpdated.bind(this),this._liveLocations),!0)}_cleanUpAfterDebuggerIsGone(){this._isUpdating&&(this._cancelCallback=!0),this._resetLocations(),this._currentState=null,this._debuggerId&&this._didRemoveFromDebugger()}_removeEventListeners(){this._debuggerModel.removeEventListener(SDK.DebuggerModel.Events.DebuggerWasDisabled,this._cleanUpAfterDebuggerIsGone,this),this._debuggerModel.removeEventListener(SDK.DebuggerModel.Events.DebuggerWasEnabled,this._scheduleUpdateInDebugger,this)}}Breakpoint.State=class{constructor(e,t,i,o,r,n){this.url=e,this.scriptId=t,this.scriptHash=i,this.lineNumber=o,this.columnNumber=r,this.condition=n}static equals(e,t){return!(!e||!t)&&(e.url===t.url&&e.scriptId===t.scriptId&&e.scriptHash===t.scriptHash&&e.lineNumber===t.lineNumber&&e.columnNumber===t.columnNumber&&e.condition===t.condition)}};class Storage{constructor(){this._setting=Common.Settings.Settings.instance().createLocalSetting("breakpoints",[]),this._breakpoints=new Map;const e=this._setting.get();for(const t of e)t.columnNumber=t.columnNumber||0,this._breakpoints.set(BreakpointManager._breakpointStorageId(t.url,t.lineNumber,t.columnNumber),t);this._muted}mute(){this._muted=!0}unmute(){delete this._muted}breakpointItems(e){return Array.from(this._breakpoints.values()).filter(t=>t.url===e)}_updateBreakpoint(e){!this._muted&&e._breakpointStorageId()&&(this._breakpoints.set(e._breakpointStorageId(),new Storage.Item(e)),this._save())}_removeBreakpoint(e){this._muted||(this._breakpoints.delete(e._breakpointStorageId()),this._save())}_save(){this._setting.set(Array.from(this._breakpoints.values()))}}Storage.Item=class{constructor(e){this.url=e._url,this.lineNumber=e.lineNumber(),this.columnNumber=e.columnNumber(),this.condition=e.condition(),this.enabled=e.enabled()}};export let BreakpointLocation;