ConsoleModel.js 15 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
  1. const _events=Symbol('SDK.ConsoleModel.events');export default class ConsoleModel extends Common.Object{constructor(){super();this._messages=[];this._messageByExceptionId=new Map();this._warnings=0;this._errors=0;this._violations=0;this._pageLoadSequenceNumber=0;SDK.targetManager.observeTargets(this);}
  2. targetAdded(target){const resourceTreeModel=target.model(SDK.ResourceTreeModel);if(!resourceTreeModel||resourceTreeModel.cachedResourcesLoaded()){this._initTarget(target);return;}
  3. const eventListener=resourceTreeModel.addEventListener(SDK.ResourceTreeModel.Events.CachedResourcesLoaded,()=>{Common.EventTarget.removeEventListeners([eventListener]);this._initTarget(target);});}
  4. _initTarget(target){const eventListeners=[];const cpuProfilerModel=target.model(SDK.CPUProfilerModel);if(cpuProfilerModel){eventListeners.push(cpuProfilerModel.addEventListener(SDK.CPUProfilerModel.Events.ConsoleProfileStarted,this._consoleProfileStarted.bind(this,cpuProfilerModel)));eventListeners.push(cpuProfilerModel.addEventListener(SDK.CPUProfilerModel.Events.ConsoleProfileFinished,this._consoleProfileFinished.bind(this,cpuProfilerModel)));}
  5. const resourceTreeModel=target.model(SDK.ResourceTreeModel);if(resourceTreeModel&&!target.parentTarget()){eventListeners.push(resourceTreeModel.addEventListener(SDK.ResourceTreeModel.Events.MainFrameNavigated,this._mainFrameNavigated,this));}
  6. const runtimeModel=target.model(SDK.RuntimeModel);if(runtimeModel){eventListeners.push(runtimeModel.addEventListener(SDK.RuntimeModel.Events.ExceptionThrown,this._exceptionThrown.bind(this,runtimeModel)));eventListeners.push(runtimeModel.addEventListener(SDK.RuntimeModel.Events.ExceptionRevoked,this._exceptionRevoked.bind(this,runtimeModel)));eventListeners.push(runtimeModel.addEventListener(SDK.RuntimeModel.Events.ConsoleAPICalled,this._consoleAPICalled.bind(this,runtimeModel)));if(!target.parentTarget()){eventListeners.push(runtimeModel.debuggerModel().addEventListener(SDK.DebuggerModel.Events.GlobalObjectCleared,this._clearIfNecessary,this));}
  7. eventListeners.push(runtimeModel.addEventListener(SDK.RuntimeModel.Events.QueryObjectRequested,this._queryObjectRequested.bind(this,runtimeModel)));}
  8. target[_events]=eventListeners;}
  9. targetRemoved(target){const runtimeModel=target.model(SDK.RuntimeModel);if(runtimeModel){this._messageByExceptionId.delete(runtimeModel);}
  10. Common.EventTarget.removeEventListeners(target[_events]||[]);}
  11. async evaluateCommandInConsole(executionContext,originatingMessage,expression,useCommandLineAPI,awaitPromise){const result=await executionContext.evaluate({expression:expression,objectGroup:'console',includeCommandLineAPI:useCommandLineAPI,silent:false,returnByValue:false,generatePreview:true,replMode:true},Common.settings.moduleSetting('consoleUserActivationEval').get(),awaitPromise);Host.userMetrics.actionTaken(Host.UserMetrics.Action.ConsoleEvaluated);if(result.error){return;}
  12. await Common.console.showPromise();this.dispatchEventToListeners(Events.CommandEvaluated,{result:result.object,commandMessage:originatingMessage,exceptionDetails:result.exceptionDetails});}
  13. addCommandMessage(executionContext,text){const commandMessage=new ConsoleMessage(executionContext.runtimeModel,MessageSource.JS,null,text,MessageType.Command);commandMessage.setExecutionContextId(executionContext.id);this.addMessage(commandMessage);return commandMessage;}
  14. addMessage(msg){msg._pageLoadSequenceNumber=this._pageLoadSequenceNumber;if(msg.source===MessageSource.ConsoleAPI&&msg.type===MessageType.Clear){this._clearIfNecessary();}
  15. this._messages.push(msg);const runtimeModel=msg.runtimeModel();if(msg._exceptionId&&runtimeModel){let modelMap=this._messageByExceptionId.get(runtimeModel);if(!modelMap){modelMap=new Map();this._messageByExceptionId.set(runtimeModel,modelMap);}
  16. modelMap.set(msg._exceptionId,msg);}
  17. this._incrementErrorWarningCount(msg);this.dispatchEventToListeners(Events.MessageAdded,msg);}
  18. _exceptionThrown(runtimeModel,event){const exceptionWithTimestamp=(event.data);const consoleMessage=ConsoleMessage.fromException(runtimeModel,exceptionWithTimestamp.details,undefined,exceptionWithTimestamp.timestamp,undefined);consoleMessage.setExceptionId(exceptionWithTimestamp.details.exceptionId);this.addMessage(consoleMessage);}
  19. _exceptionRevoked(runtimeModel,event){const exceptionId=(event.data);const modelMap=this._messageByExceptionId.get(runtimeModel);const exceptionMessage=modelMap?modelMap.get(exceptionId):null;if(!exceptionMessage){return;}
  20. this._errors--;exceptionMessage.level=MessageLevel.Verbose;this.dispatchEventToListeners(Events.MessageUpdated,exceptionMessage);}
  21. _consoleAPICalled(runtimeModel,event){const call=(event.data);let level=MessageLevel.Info;if(call.type===MessageType.Debug){level=MessageLevel.Verbose;}else if(call.type===MessageType.Error||call.type===MessageType.Assert){level=MessageLevel.Error;}else if(call.type===MessageType.Warning){level=MessageLevel.Warning;}else if(call.type===MessageType.Info||call.type===MessageType.Log){level=MessageLevel.Info;}
  22. let message='';if(call.args.length&&call.args[0].unserializableValue){message=call.args[0].unserializableValue;}else if(call.args.length&&(typeof call.args[0].value!=='object'||call.args[0].value===null)){message=call.args[0].value+'';}else if(call.args.length&&call.args[0].description){message=call.args[0].description;}
  23. const callFrame=call.stackTrace&&call.stackTrace.callFrames.length?call.stackTrace.callFrames[0]:null;const consoleMessage=new ConsoleMessage(runtimeModel,MessageSource.ConsoleAPI,level,(message),call.type,callFrame?callFrame.url:undefined,callFrame?callFrame.lineNumber:undefined,callFrame?callFrame.columnNumber:undefined,call.args,call.stackTrace,call.timestamp,call.executionContextId,undefined,undefined,call.context);this.addMessage(consoleMessage);}
  24. _queryObjectRequested(runtimeModel,event){const consoleMessage=new ConsoleMessage(runtimeModel,MessageSource.ConsoleAPI,MessageLevel.Info,'',MessageType.QueryObjectResult,undefined,undefined,undefined,[event.data.objects]);this.addMessage(consoleMessage);}
  25. _clearIfNecessary(){if(!Common.moduleSetting('preserveConsoleLog').get()){this._clear();}
  26. ++this._pageLoadSequenceNumber;}
  27. _mainFrameNavigated(event){if(Common.moduleSetting('preserveConsoleLog').get()){Common.console.log(Common.UIString('Navigated to %s',event.data.url));}}
  28. _consoleProfileStarted(cpuProfilerModel,event){const data=(event.data);this._addConsoleProfileMessage(cpuProfilerModel,MessageType.Profile,data.scriptLocation,Common.UIString('Profile \'%s\' started.',data.title));}
  29. _consoleProfileFinished(cpuProfilerModel,event){const data=(event.data);this._addConsoleProfileMessage(cpuProfilerModel,MessageType.ProfileEnd,data.scriptLocation,Common.UIString('Profile \'%s\' finished.',data.title));}
  30. _addConsoleProfileMessage(cpuProfilerModel,type,scriptLocation,messageText){const stackTrace=[{functionName:'',scriptId:scriptLocation.scriptId,url:scriptLocation.script()?scriptLocation.script().contentURL():'',lineNumber:scriptLocation.lineNumber,columnNumber:scriptLocation.columnNumber||0}];this.addMessage(new ConsoleMessage(cpuProfilerModel.runtimeModel(),MessageSource.ConsoleAPI,MessageLevel.Info,messageText,type,undefined,undefined,undefined,stackTrace));}
  31. _incrementErrorWarningCount(msg){if(msg.source===MessageSource.Violation){this._violations++;return;}
  32. switch(msg.level){case MessageLevel.Warning:this._warnings++;break;case MessageLevel.Error:this._errors++;break;}}
  33. messages(){return this._messages;}
  34. requestClearMessages(){for(const logModel of SDK.targetManager.models(SDK.LogModel)){logModel.requestClear();}
  35. for(const runtimeModel of SDK.targetManager.models(SDK.RuntimeModel)){runtimeModel.discardConsoleEntries();}
  36. this._clear();}
  37. _clear(){this._messages=[];this._messageByExceptionId.clear();this._errors=0;this._warnings=0;this._violations=0;this.dispatchEventToListeners(Events.ConsoleCleared);}
  38. errors(){return this._errors;}
  39. warnings(){return this._warnings;}
  40. violations(){return this._violations;}
  41. async saveToTempVariable(currentExecutionContext,remoteObject){if(!remoteObject||!currentExecutionContext){failedToSave(null);return;}
  42. const executionContext=(currentExecutionContext);const result=await executionContext.globalObject('',false);if(!!result.exceptionDetails||!result.object){failedToSave(result.object||null);return;}
  43. const globalObject=result.object;const callFunctionResult=await globalObject.callFunction(saveVariable,[SDK.RemoteObject.toCallArgument(remoteObject)]);globalObject.release();if(callFunctionResult.wasThrown||!callFunctionResult.object||callFunctionResult.object.type!=='string'){failedToSave(callFunctionResult.object||null);}else{const text=(callFunctionResult.object.value);const message=this.addCommandMessage(executionContext,text);this.evaluateCommandInConsole(executionContext,message,text,false,false);}
  44. if(callFunctionResult.object){callFunctionResult.object.release();}
  45. function saveVariable(value){const prefix='temp';let index=1;while((prefix+index)in this){++index;}
  46. const name=prefix+index;this[name]=value;return name;}
  47. function failedToSave(result){let message=Common.UIString('Failed to save to temp variable.');if(result){message+=' '+result.description;}
  48. Common.console.error(message);}}}
  49. export const Events={ConsoleCleared:Symbol('ConsoleCleared'),MessageAdded:Symbol('MessageAdded'),MessageUpdated:Symbol('MessageUpdated'),CommandEvaluated:Symbol('CommandEvaluated')};export class ConsoleMessage{constructor(runtimeModel,source,level,messageText,type,url,line,column,parameters,stackTrace,timestamp,executionContextId,scriptId,workerId,context){this._runtimeModel=runtimeModel;this.source=source;this.level=(level);this.messageText=messageText;this.type=type||MessageType.Log;this.url=url||undefined;this.line=line||0;this.column=column||0;this.parameters=parameters;this.stackTrace=stackTrace;this.timestamp=timestamp||Date.now();this.executionContextId=executionContextId||0;this.scriptId=scriptId||null;this.workerId=workerId||null;if(!this.executionContextId&&this._runtimeModel){if(this.scriptId){this.executionContextId=this._runtimeModel.executionContextIdForScriptId(this.scriptId);}else if(this.stackTrace){this.executionContextId=this._runtimeModel.executionContextForStackTrace(this.stackTrace);}}
  50. if(context){this.context=context.match(/[^#]*/)[0];}}
  51. static fromException(runtimeModel,exceptionDetails,messageType,timestamp,forceUrl){return new ConsoleMessage(runtimeModel,MessageSource.JS,MessageLevel.Error,SDK.RuntimeModel.simpleTextFromException(exceptionDetails),messageType,forceUrl||exceptionDetails.url,exceptionDetails.lineNumber,exceptionDetails.columnNumber,exceptionDetails.exception?[SDK.RemoteObject.fromLocalObject(exceptionDetails.text),exceptionDetails.exception]:undefined,exceptionDetails.stackTrace,timestamp,exceptionDetails.executionContextId,exceptionDetails.scriptId);}
  52. runtimeModel(){return this._runtimeModel;}
  53. target(){return this._runtimeModel?this._runtimeModel.target():null;}
  54. setOriginatingMessage(originatingMessage){this._originatingConsoleMessage=originatingMessage;this.executionContextId=originatingMessage.executionContextId;}
  55. setExecutionContextId(executionContextId){this.executionContextId=executionContextId;}
  56. setExceptionId(exceptionId){this._exceptionId=exceptionId;}
  57. originatingMessage(){return this._originatingConsoleMessage;}
  58. isGroupMessage(){return this.type===MessageType.StartGroup||this.type===MessageType.StartGroupCollapsed||this.type===MessageType.EndGroup;}
  59. isGroupStartMessage(){return this.type===MessageType.StartGroup||this.type===MessageType.StartGroupCollapsed;}
  60. isErrorOrWarning(){return(this.level===MessageLevel.Warning||this.level===MessageLevel.Error);}
  61. isGroupable(){const isUngroupableError=this.level===MessageLevel.Error&&(this.source===MessageSource.JS||this.source===MessageSource.Network);return(this.source!==MessageSource.ConsoleAPI&&this.type!==MessageType.Command&&this.type!==MessageType.Result&&this.type!==MessageType.System&&!isUngroupableError);}
  62. groupCategoryKey(){return[this.source,this.level,this.type,this._pageLoadSequenceNumber].join(':');}
  63. isEqual(msg){if(!msg){return false;}
  64. if(!this._isEqualStackTraces(this.stackTrace,msg.stackTrace)){return false;}
  65. if(this.parameters){if(!msg.parameters||this.parameters.length!==msg.parameters.length){return false;}
  66. for(let i=0;i<msg.parameters.length;++i){if(msg.parameters[i].type==='object'&&msg.parameters[i].subtype!=='error'){return false;}
  67. if(this.parameters[i].type!==msg.parameters[i].type||this.parameters[i].value!==msg.parameters[i].value||this.parameters[i].description!==msg.parameters[i].description){return false;}}}
  68. return(this.runtimeModel()===msg.runtimeModel())&&(this.source===msg.source)&&(this.type===msg.type)&&(this.level===msg.level)&&(this.line===msg.line)&&(this.url===msg.url)&&(this.messageText===msg.messageText)&&(this.request===msg.request)&&(this.executionContextId===msg.executionContextId);}
  69. _isEqualStackTraces(stackTrace1,stackTrace2){if(!stackTrace1!==!stackTrace2){return false;}
  70. if(!stackTrace1){return true;}
  71. const callFrames1=stackTrace1.callFrames;const callFrames2=stackTrace2.callFrames;if(callFrames1.length!==callFrames2.length){return false;}
  72. for(let i=0,n=callFrames1.length;i<n;++i){if(callFrames1[i].url!==callFrames2[i].url||callFrames1[i].functionName!==callFrames2[i].functionName||callFrames1[i].lineNumber!==callFrames2[i].lineNumber||callFrames1[i].columnNumber!==callFrames2[i].columnNumber){return false;}}
  73. return this._isEqualStackTraces(stackTrace1.parent,stackTrace2.parent);}}
  74. export const MessageSource={XML:'xml',JS:'javascript',Network:'network',ConsoleAPI:'console-api',Storage:'storage',AppCache:'appcache',Rendering:'rendering',CSS:'css',Security:'security',Deprecation:'deprecation',Worker:'worker',Violation:'violation',Intervention:'intervention',Recommendation:'recommendation',Other:'other'};export const MessageType={Log:'log',Debug:'debug',Info:'info',Error:'error',Warning:'warning',Dir:'dir',DirXML:'dirxml',Table:'table',Trace:'trace',Clear:'clear',StartGroup:'startGroup',StartGroupCollapsed:'startGroupCollapsed',EndGroup:'endGroup',Assert:'assert',Result:'result',Profile:'profile',ProfileEnd:'profileEnd',Command:'command',System:'system',QueryObjectResult:'queryObjectResult'};export const MessageLevel={Verbose:'verbose',Info:'info',Warning:'warning',Error:'error'};export const MessageSourceDisplayName=new Map([[MessageSource.XML,'xml'],[MessageSource.JS,'javascript'],[MessageSource.Network,'network'],[MessageSource.ConsoleAPI,'console-api'],[MessageSource.Storage,'storage'],[MessageSource.AppCache,'appcache'],[MessageSource.Rendering,'rendering'],[MessageSource.CSS,'css'],[MessageSource.Security,'security'],[MessageSource.Deprecation,'deprecation'],[MessageSource.Worker,'worker'],[MessageSource.Violation,'violation'],[MessageSource.Intervention,'intervention'],[MessageSource.Recommendation,'recommendation'],[MessageSource.Other,'other']]);self.SDK=self.SDK||{};SDK=SDK||{};SDK.ConsoleModel=ConsoleModel;SDK.ConsoleMessage=ConsoleMessage;SDK.ConsoleModel.Events=Events;SDK.ConsoleMessage.MessageSource=MessageSource;SDK.ConsoleMessage.MessageType=MessageType;SDK.ConsoleMessage.MessageLevel=MessageLevel;SDK.ConsoleMessage.MessageSourceDisplayName=MessageSourceDisplayName;SDK.consoleModel;