@yuebai008/cli
Version:
Command line interface for rapid qg-minigame development
1 lines • 17.3 kB
JavaScript
import*as Common from"../../core/common/common.js";import*as i18n from"../../core/i18n/i18n.js";import*as SDK from"../../core/sdk/sdk.js";import*as TextUtils from"../text_utils/text_utils.js";import*as Workspace from"../workspace/workspace.js";import{ContentProviderBasedProject}from"./ContentProviderBasedProject.js";import{assertNotNullOrUndefined}from"../../core/platform/platform.js";import{NetworkProject}from"./NetworkProject.js";const UIStrings={errorInDebuggerLanguagePlugin:"Error in debugger language plugin: {PH1}",loadingDebugSymbolsForVia:"[{PH1}] Loading debug symbols for {PH2} (via {PH3})...",loadingDebugSymbolsFor:"[{PH1}] Loading debug symbols for {PH2}...",loadedDebugSymbolsForButDidnt:"[{PH1}] Loaded debug symbols for {PH2}, but didn't find any source files",loadedDebugSymbolsForFound:"[{PH1}] Loaded debug symbols for {PH2}, found {PH3} source file(s)",failedToLoadDebugSymbolsFor:"[{PH1}] Failed to load debug symbols for {PH2} ({PH3})",failedToLoadDebugSymbolsForFunction:'No debug information for function "{PH1}"',debugSymbolsIncomplete:"The debug information for function {PH1} is incomplete"},str_=i18n.i18n.registerUIStrings("models/bindings/DebuggerLanguagePlugins.ts",UIStrings),i18nString=i18n.i18n.getLocalizedString.bind(void 0,str_);function rawModuleIdForScript(e){return`${e.sourceURL}@${e.hash}`}function getRawLocation(e){const{script:t}=e;return{rawModuleId:rawModuleIdForScript(t),codeOffset:e.location().columnNumber-(t.codeOffset()||0),inlineFrameIndex:e.inlineFrameIndex}}class FormattingError extends Error{exception;exceptionDetails;constructor(e,t){const{description:r}=t.exception||{};super(r||t.text),this.exception=e,this.exceptionDetails=t}static makeLocal(e,t){const r={type:"object",subtype:"error",description:t},o={text:"Uncaught",exceptionId:-1,columnNumber:0,lineNumber:0,exception:r},n=e.debuggerModel.runtimeModel().createRemoteObject(r);return new FormattingError(n,o)}}class NamespaceObject extends SDK.RemoteObject.LocalJSONObject{constructor(e){super(e)}get description(){return this.type}get type(){return"namespace"}}class SourceScopeRemoteObject extends SDK.RemoteObject.RemoteObjectImpl{variables;#e;#t;stopId;constructor(e,t,r){super(e.debuggerModel.runtimeModel(),void 0,"object",void 0,null),this.variables=[],this.#e=e,this.#t=r,this.stopId=t}async doGetProperties(e,t,r){if(t)return{properties:[],internalProperties:[]};const o=[],n={};function s(e,t){return new SDK.RemoteObject.RemoteObjectProperty(e,t,!1,!1,!0,!1)}for(const e of this.variables){let t;try{const r=await this.#t.evaluate(e.name,getRawLocation(this.#e),this.stopId);t=r?new ExtensionRemoteObject(this.#e,r,this.#t):new SDK.RemoteObject.LocalJSONObject(void 0)}catch(e){console.warn(e),t=new SDK.RemoteObject.LocalJSONObject(void 0)}if(e.nestedName&&e.nestedName.length>1){let r=n;for(let t=0;t<e.nestedName.length-1;t++){const o=e.nestedName[t];let n=r[o];n||(n=new NamespaceObject({}),r[o]=n),r=n.value}r[e.nestedName[e.nestedName.length-1]]=t}else o.push(s(e.name,t))}for(const e in n)o.push(s(e,n[e]));return{properties:o,internalProperties:[]}}}export class SourceScope{#r;#o;#n;#s;#i;constructor(e,t,r,o,n,s){if(n&&"data:"!==new URL(n).protocol)throw new Error("The icon must be a data:-URL");this.#r=e,this.#o=r,this.#n=o,this.#s=n,this.#i=new SourceScopeRemoteObject(e,t,s)}async getVariableValue(e){for(let t=0;t<this.#i.variables.length;++t){if(this.#i.variables[t].name!==e)continue;const r=await this.#i.getAllProperties(!1,!1);if(!r.properties)continue;const{value:o}=r.properties[t];if(o)return o}return null}callFrame(){return this.#r}type(){return this.#o}typeName(){return this.#n}name(){}range(){return null}object(){return this.#i}description(){return""}icon(){return this.#s}}export class ExtensionRemoteObject extends SDK.RemoteObject.RemoteObject{extensionObject;plugin;callFrame;constructor(e,t,r){super(),this.extensionObject=t,this.plugin=r,this.callFrame=e}get linearMemoryAddress(){return this.extensionObject.linearMemoryAddress}get linearMemorySize(){return this.extensionObject.linearMemorySize}get objectId(){return this.extensionObject.objectId}get type(){return"array"===this.extensionObject.type||"null"===this.extensionObject.type?"object":this.extensionObject.type}get subtype(){if("array"===this.extensionObject.type||"null"===this.extensionObject.type)return this.extensionObject.type}get value(){return this.extensionObject.value}unserializableValue(){}get description(){return this.extensionObject.description}set description(e){}get hasChildren(){return this.extensionObject.hasChildren}get preview(){}get className(){return this.extensionObject.className??null}arrayLength(){return 0}arrayBufferByteLength(){return 0}getOwnProperties(e,t){return this.getAllProperties(!1,e,t)}async getAllProperties(e,t,r){const{objectId:o}=this.extensionObject;if(o){assertNotNullOrUndefined(this.plugin.getProperties);return{properties:(await this.plugin.getProperties(o)).map((e=>new SDK.RemoteObject.RemoteObjectProperty(e.name,new ExtensionRemoteObject(this.callFrame,e.value,this.plugin)))),internalProperties:null}}return{properties:null,internalProperties:null}}release(){const{objectId:e}=this.extensionObject;e&&(assertNotNullOrUndefined(this.plugin.releaseObject),this.plugin.releaseObject(e))}debuggerModel(){return this.callFrame.debuggerModel}runtimeModel(){return this.callFrame.debuggerModel.runtimeModel()}}export class DebuggerLanguagePluginManager{#a;#l;#c;#u;#d;callFrameByStopId=new Map;stopIdByCallFrame=new Map;nextStopId=0n;constructor(e,t,r){this.#a=t,this.#l=r,this.#c=[],this.#u=new Map,e.observeModels(SDK.DebuggerModel.DebuggerModel,this),this.#d=new Map}async evaluateOnCallFrame(e,t){const{script:r}=e,{expression:o,returnByValue:n,throwOnSideEffect:s}=t,{plugin:i}=await this.rawModuleIdAndPluginForScript(r);if(!i)return null;const a=getRawLocation(e);if(0===(await i.rawLocationToSourceLocation(a)).length)return null;if(n)return{error:"Cannot return by value"};if(s)return{error:"Cannot guarantee side-effect freedom"};try{const t=await i.evaluate(o,a,this.stopIdForCallFrame(e));return t?{object:new ExtensionRemoteObject(e,t,i),exceptionDetails:void 0}:{object:new SDK.RemoteObject.LocalJSONObject(void 0),exceptionDetails:void 0}}catch(t){if(t instanceof FormattingError){const{exception:e,exceptionDetails:r}=t;return{object:e,exceptionDetails:r}}const{exception:r,exceptionDetails:o}=FormattingError.makeLocal(e,t.message);return{object:r,exceptionDetails:o}}}stopIdForCallFrame(e){let t=this.stopIdByCallFrame.get(e);return void 0!==t||(t=this.nextStopId++,this.stopIdByCallFrame.set(e,t),this.callFrameByStopId.set(t,e)),t}callFrameForStopId(e){return this.callFrameByStopId.get(e)}expandCallFrames(e){return Promise.all(e.map((async e=>{const t=await this.getFunctionInfo(e.script,e.location());if(t){if("frames"in t&&t.frames.length)return t.frames.map((({name:t},r)=>e.createVirtualCallFrame(r,t)));if("missingSymbolFiles"in t&&t.missingSymbolFiles.length){const r=t.missingSymbolFiles,o=i18nString(UIStrings.debugSymbolsIncomplete,{PH1:e.functionName});e.setMissingDebugInfoDetails({details:o,resources:r})}else e.setMissingDebugInfoDetails({resources:[],details:i18nString(UIStrings.failedToLoadDebugSymbolsForFunction,{PH1:e.functionName})})}return e}))).then((e=>e.flat()))}modelAdded(e){this.#u.set(e,new ModelData(e,this.#a)),e.addEventListener(SDK.DebuggerModel.Events.GlobalObjectCleared,this.globalObjectCleared,this),e.addEventListener(SDK.DebuggerModel.Events.ParsedScriptSource,this.parsedScriptSource,this),e.addEventListener(SDK.DebuggerModel.Events.DebuggerResumed,this.debuggerResumed,this),e.setEvaluateOnCallFrameCallback(this.evaluateOnCallFrame.bind(this)),e.setExpandCallFramesCallback(this.expandCallFrames.bind(this))}modelRemoved(e){e.removeEventListener(SDK.DebuggerModel.Events.GlobalObjectCleared,this.globalObjectCleared,this),e.removeEventListener(SDK.DebuggerModel.Events.ParsedScriptSource,this.parsedScriptSource,this),e.removeEventListener(SDK.DebuggerModel.Events.DebuggerResumed,this.debuggerResumed,this),e.setEvaluateOnCallFrameCallback(null),e.setExpandCallFramesCallback(null);const t=this.#u.get(e);t&&(t.dispose(),this.#u.delete(e)),this.#d.forEach(((t,r)=>{const o=t.scripts.filter((t=>t.debuggerModel!==e));0===o.length?(t.plugin.removeRawModule(r).catch((e=>{Common.Console.Console.instance().error(i18nString(UIStrings.errorInDebuggerLanguagePlugin,{PH1:e.message}))})),this.#d.delete(r)):t.scripts=o}))}globalObjectCleared(e){const t=e.data;this.modelRemoved(t),this.modelAdded(t)}addPlugin(e){this.#c.push(e);for(const e of this.#u.keys())for(const t of e.scripts())this.hasPluginForScript(t)||this.parsedScriptSource({data:t})}removePlugin(e){this.#c=this.#c.filter((t=>t!==e));const t=new Set;this.#d.forEach(((r,o)=>{r.plugin===e&&(r.scripts.forEach((e=>t.add(e))),this.#d.delete(o))}));for(const e of t){this.#u.get(e.debuggerModel).removeScript(e),this.parsedScriptSource({data:e})}}hasPluginForScript(e){const t=rawModuleIdForScript(e),r=this.#d.get(t);return void 0!==r&&r.scripts.includes(e)}async rawModuleIdAndPluginForScript(e){const t=rawModuleIdForScript(e),r=this.#d.get(t);return r&&(await r.addRawModulePromise,r===this.#d.get(t))?{rawModuleId:t,plugin:r.plugin}:{rawModuleId:t,plugin:null}}uiSourceCodeForURL(e,t){const r=this.#u.get(e);return r?r.getProject().uiSourceCodeForURL(t):null}async rawLocationToUILocation(e){const t=e.script();if(!t)return null;const{rawModuleId:r,plugin:o}=await this.rawModuleIdAndPluginForScript(t);if(!o)return null;const n={rawModuleId:r,codeOffset:e.columnNumber-(t.codeOffset()||0),inlineFrameIndex:e.inlineFrameIndex};try{const e=await o.rawLocationToSourceLocation(n);for(const r of e){const e=this.uiSourceCodeForURL(t.debuggerModel,r.sourceFileURL);if(e)return e.uiLocation(r.lineNumber,r.columnNumber>=0?r.columnNumber:void 0)}}catch(e){Common.Console.Console.instance().error(i18nString(UIStrings.errorInDebuggerLanguagePlugin,{PH1:e.message}))}return null}uiLocationToRawLocationRanges(e,t,r=-1){const o=[];return this.scriptsForUISourceCode(e).forEach((n=>{const s=rawModuleIdForScript(n),i=this.#d.get(s);if(!i)return;const{plugin:a}=i;o.push(async function(o,n,s){const i={rawModuleId:o,sourceFileURL:e.url(),lineNumber:t,columnNumber:r},a=await n.sourceLocationToRawLocation(i);if(!a)return[];return a.map((e=>({start:new SDK.DebuggerModel.Location(s.debuggerModel,s.scriptId,0,Number(e.startOffset)+(s.codeOffset()||0)),end:new SDK.DebuggerModel.Location(s.debuggerModel,s.scriptId,0,Number(e.endOffset)+(s.codeOffset()||0))})))}(s,a,n))})),0===o.length?Promise.resolve(null):Promise.all(o).then((e=>e.flat())).catch((e=>(Common.Console.Console.instance().error(i18nString(UIStrings.errorInDebuggerLanguagePlugin,{PH1:e.message})),null)))}async uiLocationToRawLocations(e,t,r){const o=await this.uiLocationToRawLocationRanges(e,t,r);return o?o.map((({start:e})=>e)):null}async uiLocationRangeToRawLocationRanges(e,t){const r=[];for(let o=t.startLine;o<=t.endLine;++o)r.push(this.uiLocationToRawLocationRanges(e,o));const o=[];for(const e of await Promise.all(r)){if(null===e)return null;for(const r of e){const[e,n]=await Promise.all([this.rawLocationToUILocation(r.start),this.rawLocationToUILocation(r.end)]);if(null===e||null===n)continue;t.intersection(new TextUtils.TextRange.TextRange(e.lineNumber,e.columnNumber??0,n.lineNumber,n.columnNumber??1/0)).isEmpty()||o.push(r)}}return o}scriptsForUISourceCode(e){for(const t of this.#u.values()){const r=t.uiSourceCodeToScripts.get(e);if(r)return r}return[]}setDebugInfoURL(e,t){this.hasPluginForScript(e)||(e.debugSymbols={type:"ExternalDWARF",externalURL:t},this.parsedScriptSource({data:e}),e.debuggerModel.setDebugInfoURL(e,t))}parsedScriptSource(e){const t=e.data;if(t.sourceURL)for(const e of this.#c){if(!e.handleScript(t))continue;const r=rawModuleIdForScript(t);let o=this.#d.get(r);if(o)o.scripts.push(t);else{const n=(async()=>{const n=Common.Console.Console.instance(),s=t.sourceURL,i=t.debugSymbols&&t.debugSymbols.externalURL||"";i?n.log(i18nString(UIStrings.loadingDebugSymbolsForVia,{PH1:e.name,PH2:s,PH3:i})):n.log(i18nString(UIStrings.loadingDebugSymbolsFor,{PH1:e.name,PH2:s}));try{const a=!i&&s.startsWith("wasm://")?await t.getWasmBytecode():void 0,l=await e.addRawModule(r,i,{url:s,code:a});if(o!==this.#d.get(r))return[];if("missingSymbolFiles"in l)return{missingSymbolFiles:l.missingSymbolFiles};const c=l;return 0===c.length?n.warn(i18nString(UIStrings.loadedDebugSymbolsForButDidnt,{PH1:e.name,PH2:s})):n.log(i18nString(UIStrings.loadedDebugSymbolsForFound,{PH1:e.name,PH2:s,PH3:c.length})),c}catch(t){return n.error(i18nString(UIStrings.failedToLoadDebugSymbolsFor,{PH1:e.name,PH2:s,PH3:t.message})),this.#d.delete(r),[]}})();o={rawModuleId:r,plugin:e,scripts:[t],addRawModulePromise:n},this.#d.set(r,o)}return void o.addRawModulePromise.then((e=>{if(!("missingSymbolFiles"in e)&&t.debuggerModel.scriptForId(t.scriptId)===t){const r=this.#u.get(t.debuggerModel);r&&(r.addSourceFiles(t,e),this.#l.updateLocations(t))}}))}}debuggerResumed(e){const t=Array.from(this.callFrameByStopId.values()).filter((t=>t.debuggerModel===e.data));for(const e of t){const t=this.stopIdByCallFrame.get(e);assertNotNullOrUndefined(t),this.stopIdByCallFrame.delete(e),this.callFrameByStopId.delete(t)}}getSourcesForScript(e){const t=rawModuleIdForScript(e),r=this.#d.get(t);return r?r.addRawModulePromise:Promise.resolve(void 0)}async resolveScopeChain(e){const t=e.script,{rawModuleId:r,plugin:o}=await this.rawModuleIdAndPluginForScript(t);if(!o)return null;const n={rawModuleId:r,codeOffset:e.location().columnNumber-(t.codeOffset()||0),inlineFrameIndex:e.inlineFrameIndex},s=this.stopIdForCallFrame(e);try{if(0===(await o.rawLocationToSourceLocation(n)).length)return null;const t=new Map,r=await o.listVariablesInScope(n);for(const n of r||[]){let r=t.get(n.scope);if(!r){const{type:i,typeName:a,icon:l}=await o.getScopeInfo(n.scope);r=new SourceScope(e,s,i,a,l,o),t.set(n.scope,r)}r.object().variables.push(n)}return Array.from(t.values())}catch(e){return Common.Console.Console.instance().error(i18nString(UIStrings.errorInDebuggerLanguagePlugin,{PH1:e.message})),null}}async getFunctionInfo(e,t){const{rawModuleId:r,plugin:o}=await this.rawModuleIdAndPluginForScript(e);if(!o)return null;const n={rawModuleId:r,codeOffset:t.columnNumber-(e.codeOffset()||0),inlineFrameIndex:0};try{return await o.getFunctionInfo(n)}catch(e){return Common.Console.Console.instance().warn(i18nString(UIStrings.errorInDebuggerLanguagePlugin,{PH1:e.message})),{frames:[]}}}async getInlinedFunctionRanges(e){const t=e.script();if(!t)return[];const{rawModuleId:r,plugin:o}=await this.rawModuleIdAndPluginForScript(t);if(!o)return[];const n={rawModuleId:r,codeOffset:e.columnNumber-(t.codeOffset()||0)};try{return(await o.getInlinedFunctionRanges(n)).map((e=>({start:new SDK.DebuggerModel.Location(t.debuggerModel,t.scriptId,0,Number(e.startOffset)+(t.codeOffset()||0)),end:new SDK.DebuggerModel.Location(t.debuggerModel,t.scriptId,0,Number(e.endOffset)+(t.codeOffset()||0))})))}catch(e){return Common.Console.Console.instance().warn(i18nString(UIStrings.errorInDebuggerLanguagePlugin,{PH1:e.message})),[]}}async getInlinedCalleesRanges(e){const t=e.script();if(!t)return[];const{rawModuleId:r,plugin:o}=await this.rawModuleIdAndPluginForScript(t);if(!o)return[];const n={rawModuleId:r,codeOffset:e.columnNumber-(t.codeOffset()||0)};try{return(await o.getInlinedCalleesRanges(n)).map((e=>({start:new SDK.DebuggerModel.Location(t.debuggerModel,t.scriptId,0,Number(e.startOffset)+(t.codeOffset()||0)),end:new SDK.DebuggerModel.Location(t.debuggerModel,t.scriptId,0,Number(e.endOffset)+(t.codeOffset()||0))})))}catch(e){return Common.Console.Console.instance().warn(i18nString(UIStrings.errorInDebuggerLanguagePlugin,{PH1:e.message})),[]}}async getMappedLines(e){const t=await Promise.all(this.scriptsForUISourceCode(e).map((e=>this.rawModuleIdAndPluginForScript(e))));let r=null;for(const{rawModuleId:o,plugin:n}of t){if(!n)continue;const t=await n.getMappedLines(o,e.url());void 0!==t&&(null===r?r=new Set(t):t.forEach((e=>r.add(e))))}return r}}class ModelData{project;uiSourceCodeToScripts;constructor(e,t){this.project=new ContentProviderBasedProject(t,"language_plugins::"+e.target().id(),Workspace.Workspace.projectTypes.Network,"",!1),NetworkProject.setTargetForProject(this.project,e.target()),this.uiSourceCodeToScripts=new Map}addSourceFiles(e,t){const r=e.createPageResourceLoadInitiator();for(const o of t){let t=this.project.uiSourceCodeForURL(o);if(t){const r=this.uiSourceCodeToScripts.get(t);r.includes(e)||r.push(e)}else{t=this.project.createUISourceCode(o,Common.ResourceType.resourceTypes.SourceMapScript),NetworkProject.setInitialFrameAttribution(t,e.frameId),this.uiSourceCodeToScripts.set(t,[e]);const n=new SDK.CompilerSourceMappingContentProvider.CompilerSourceMappingContentProvider(o,Common.ResourceType.resourceTypes.SourceMapScript,r),s=Common.ResourceType.ResourceType.mimeFromURL(o)||"text/javascript";this.project.addUISourceCodeWithProvider(t,n,null,s)}}}removeScript(e){this.uiSourceCodeToScripts.forEach(((t,r)=>{0===(t=t.filter((t=>t!==e))).length?(this.uiSourceCodeToScripts.delete(r),this.project.removeUISourceCode(r.url())):this.uiSourceCodeToScripts.set(r,t)}))}dispose(){this.project.dispose()}getProject(){return this.project}}