import*as Host from"../host/host.js";import*as SDK from"../sdk/sdk.js";import*as UI from"../ui/ui.js";import{LinearMemoryInspectorPaneImpl}from"./LinearMemoryInspectorPane.js";const LINEAR_MEMORY_INSPECTOR_OBJECT_GROUP="linear-memory-inspector",MEMORY_TRANSFER_MIN_CHUNK_SIZE=1e3;export const ACCEPTED_MEMORY_TYPES=["webassemblymemory","typedarray","dataview","arraybuffer"];let controllerInstance;export class RemoteArrayBufferWrapper{constructor(e){this.remoteArrayBuffer=e}length(){return this.remoteArrayBuffer.byteLength()}async getRange(e,t){const r=Math.min(t,this.length());if(e<0||e>r)return console.error(`Requesting invalid range of memory: (${e}, ${t})`),new Uint8Array(0);const o=await this.remoteArrayBuffer.bytes(e,r);return new Uint8Array(o)}}async function getBufferFromObject(e){console.assert("object"===e.type),console.assert(void 0!==e.subtype&&ACCEPTED_MEMORY_TYPES.includes(e.subtype));const t=await e.runtimeModel()._agent.invoke_callFunctionOn({objectId:e.objectId,functionDeclaration:"function() { return this instanceof ArrayBuffer || this instanceof SharedArrayBuffer ? this : this.buffer; }",silent:!0,objectGroup:"linear-memory-inspector"}),r=t.getError();if(r)throw new Error(`Remote object representing ArrayBuffer could not be retrieved: ${r}`);return e=e.runtimeModel().createRemoteObject(t.result),new SDK.RemoteObject.RemoteArrayBuffer(e)}export class LinearMemoryInspectorController extends SDK.SDKModel.SDKModelObserver{constructor(){super(),this.paneInstance=LinearMemoryInspectorPaneImpl.instance(),this.bufferIdToRemoteObject=new Map,SDK.SDKModel.TargetManager.instance().observeModels(SDK.RuntimeModel.RuntimeModel,this),SDK.SDKModel.TargetManager.instance().addModelListener(SDK.DebuggerModel.DebuggerModel,SDK.DebuggerModel.Events.GlobalObjectCleared,this.onGlobalObjectClear,this),this.paneInstance.addEventListener("view-closed",this.viewClosed.bind(this)),SDK.SDKModel.TargetManager.instance().addModelListener(SDK.DebuggerModel.DebuggerModel,SDK.DebuggerModel.Events.DebuggerPaused,this.onDebuggerPause,this)}static instance(){return controllerInstance||(controllerInstance=new LinearMemoryInspectorController,controllerInstance)}static async getMemoryForAddress(e,t){const r=Math.max(0,t-500),o=r+1e3;return{memory:await e.getRange(r,o),offset:r}}static async getMemoryRange(e,t,r){if(t<0||t>r||t>=e.length())throw new Error("Requested range is out of bounds.");const o=Math.max(r,t+1e3);return await e.getRange(t,o)}async openInspectorView(e,t){void 0!==t?Host.userMetrics.linearMemoryInspectorTarget(Host.UserMetrics.LinearMemoryInspectorTarget.DWARFInspectableAddress):e.subtype===Protocol.Runtime.RemoteObjectSubtype.Arraybuffer?Host.userMetrics.linearMemoryInspectorTarget(Host.UserMetrics.LinearMemoryInspectorTarget.ArrayBuffer):e.subtype===Protocol.Runtime.RemoteObjectSubtype.Dataview?Host.userMetrics.linearMemoryInspectorTarget(Host.UserMetrics.LinearMemoryInspectorTarget.DataView):e.subtype===Protocol.Runtime.RemoteObjectSubtype.Typedarray?Host.userMetrics.linearMemoryInspectorTarget(Host.UserMetrics.LinearMemoryInspectorTarget.TypedArray):(console.assert(e.subtype===Protocol.Runtime.RemoteObjectSubtype.Webassemblymemory),Host.userMetrics.linearMemoryInspectorTarget(Host.UserMetrics.LinearMemoryInspectorTarget.WebAssemblyMemory));const r=await getBufferFromObject(e),{internalProperties:o}=await r.object().getOwnProperties(!1),n=o?.find((({name:e})=>"[[ArrayBufferData]]"===e)),s=n?.value?.value;if(!s)throw new Error("Unable to find backing store id for array buffer");const a=o?.find((({name:e})=>"[[WebAssemblyMemory]]"===e)),i=a?.value;if(this.bufferIdToRemoteObject.has(s))return this.paneInstance.reveal(s,t),void UI.ViewManager.ViewManager.instance().showView("linear-memory-inspector");const c=String(i?i.description:r.object().description);this.bufferIdToRemoteObject.set(s,r.object());const l=new RemoteArrayBufferWrapper(r);this.paneInstance.create(s,c,l,t),UI.ViewManager.ViewManager.instance().showView("linear-memory-inspector")}modelRemoved(e){for(const[t,r]of this.bufferIdToRemoteObject)e===r.runtimeModel()&&(this.bufferIdToRemoteObject.delete(t),this.paneInstance.close(t))}onDebuggerPause(e){const t=e.data;for(const[r,o]of this.bufferIdToRemoteObject)t.runtimeModel()===o.runtimeModel()&&this.paneInstance.refreshView(r)}onGlobalObjectClear(e){const t=e.data;this.modelRemoved(t.runtimeModel())}viewClosed(e){const t=e.data,r=this.bufferIdToRemoteObject.get(t);r&&r.release(),this.bufferIdToRemoteObject.delete(e.data)}}