ScriptSnippetModel.js [plain text]
WebInspector.ScriptSnippetModel = function(workspace)
{
this._workspace = workspace;
this._uiSourceCodeForScriptId = {};
this._scriptForUISourceCode = new Map();
this._uiSourceCodeForSnippetId = {};
this._snippetIdForUISourceCode = new Map();
this._snippetStorage = new WebInspector.SnippetStorage("script", "Script snippet #");
this._lastSnippetEvaluationIndexSetting = WebInspector.settings.createSetting("lastSnippetEvaluationIndex", 0);
this._snippetScriptMapping = new WebInspector.SnippetScriptMapping(this);
this._workspaceProvider = new WebInspector.SimpleWorkspaceProvider(this._workspace, WebInspector.projectTypes.Snippets);
this.reset();
WebInspector.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.GlobalObjectCleared, this._debuggerReset, this);
}
WebInspector.ScriptSnippetModel.prototype = {
get scriptMapping()
{
return this._snippetScriptMapping;
},
_loadSnippets: function()
{
var snippets = this._snippetStorage.snippets();
for (var i = 0; i < snippets.length; ++i)
this._addScriptSnippet(snippets[i]);
},
createScriptSnippet: function()
{
var snippet = this._snippetStorage.createSnippet();
return this._addScriptSnippet(snippet);
},
_addScriptSnippet: function(snippet)
{
var uiSourceCode = this._workspaceProvider.addFileByName("", snippet.name, new WebInspector.SnippetContentProvider(snippet), true);
var scriptFile = new WebInspector.SnippetScriptFile(this, uiSourceCode);
uiSourceCode.setScriptFile(scriptFile);
this._snippetIdForUISourceCode.put(uiSourceCode, snippet.id);
uiSourceCode.setSourceMapping(this._snippetScriptMapping);
this._uiSourceCodeForSnippetId[snippet.id] = uiSourceCode;
return uiSourceCode;
},
deleteScriptSnippet: function(uiSourceCode)
{
var snippetId = this._snippetIdForUISourceCode.get(uiSourceCode);
var snippet = this._snippetStorage.snippetForId(snippetId);
this._snippetStorage.deleteSnippet(snippet);
this._removeBreakpoints(uiSourceCode);
this._releaseSnippetScript(uiSourceCode);
delete this._uiSourceCodeForSnippetId[snippet.id];
this._snippetIdForUISourceCode.remove(uiSourceCode);
this._workspaceProvider.removeFileByName("", snippet.name);
},
renameScriptSnippet: function(uiSourceCode, newName)
{
var breakpointLocations = this._removeBreakpoints(uiSourceCode);
var snippetId = this._snippetIdForUISourceCode.get(uiSourceCode);
var snippet = this._snippetStorage.snippetForId(snippetId);
if (!snippet || !newName || snippet.name === newName)
return;
snippet.name = newName;
this._restoreBreakpoints(uiSourceCode, breakpointLocations);
},
_setScriptSnippetContent: function(uiSourceCode, newContent)
{
var snippetId = this._snippetIdForUISourceCode.get(uiSourceCode);
var snippet = this._snippetStorage.snippetForId(snippetId);
snippet.content = newContent;
},
_scriptSnippetEdited: function(uiSourceCode)
{
var script = this._scriptForUISourceCode.get(uiSourceCode);
if (!script)
return;
var breakpointLocations = this._removeBreakpoints(uiSourceCode);
var scriptUISourceCode = this._releaseSnippetScript(uiSourceCode);
this._restoreBreakpoints(uiSourceCode, breakpointLocations);
if (scriptUISourceCode)
this._restoreBreakpoints(scriptUISourceCode, breakpointLocations);
},
_nextEvaluationIndex: function(snippetId)
{
var evaluationIndex = this._lastSnippetEvaluationIndexSetting.get() + 1;
this._lastSnippetEvaluationIndexSetting.set(evaluationIndex);
return evaluationIndex;
},
evaluateScriptSnippet: function(uiSourceCode)
{
var breakpointLocations = this._removeBreakpoints(uiSourceCode);
this._releaseSnippetScript(uiSourceCode);
this._restoreBreakpoints(uiSourceCode, breakpointLocations);
var snippetId = this._snippetIdForUISourceCode.get(uiSourceCode);
var evaluationIndex = this._nextEvaluationIndex(snippetId);
uiSourceCode._evaluationIndex = evaluationIndex;
var evaluationUrl = this._evaluationSourceURL(uiSourceCode);
var expression = uiSourceCode.workingCopy();
if (WebInspector.debuggerModel.selectedCallFrame() || !Capabilities.separateScriptCompilationAndExecutionEnabled) {
expression = uiSourceCode.workingCopy() + "\n//@ sourceURL=" + evaluationUrl + "\n";
WebInspector.evaluateInConsole(expression, true);
return;
}
WebInspector.showConsole();
DebuggerAgent.compileScript(expression, evaluationUrl, compileCallback.bind(this));
function compileCallback(error, scriptId, syntaxErrorMessage)
{
if (!uiSourceCode || uiSourceCode._evaluationIndex !== evaluationIndex)
return;
if (error) {
console.error(error);
return;
}
if (!scriptId) {
var consoleMessage = WebInspector.ConsoleMessage.create(
WebInspector.ConsoleMessage.MessageSource.JS,
WebInspector.ConsoleMessage.MessageLevel.Error,
syntaxErrorMessage || "");
WebInspector.console.addMessage(consoleMessage);
return;
}
var breakpointLocations = this._removeBreakpoints(uiSourceCode);
this._restoreBreakpoints(uiSourceCode, breakpointLocations);
this._runScript(scriptId);
}
},
_runScript: function(scriptId)
{
var currentExecutionContext = WebInspector.runtimeModel.currentExecutionContext();
DebuggerAgent.runScript(scriptId, currentExecutionContext ? currentExecutionContext.id : undefined, "console", false, runCallback.bind(this));
function runCallback(error, result, wasThrown)
{
if (error) {
console.error(error);
return;
}
this._printRunScriptResult(result, wasThrown);
}
},
_printRunScriptResult: function(result, wasThrown)
{
var level = (wasThrown ? WebInspector.ConsoleMessage.MessageLevel.Error : WebInspector.ConsoleMessage.MessageLevel.Log);
var message = WebInspector.ConsoleMessage.create(WebInspector.ConsoleMessage.MessageSource.JS, level, "", undefined, undefined, undefined, undefined, [result]);
WebInspector.console.addMessage(message)
},
_rawLocationToUILocation: function(rawLocation)
{
var uiSourceCode = this._uiSourceCodeForScriptId[rawLocation.scriptId];
return new WebInspector.UILocation(uiSourceCode, rawLocation.lineNumber, rawLocation.columnNumber || 0);
},
_uiLocationToRawLocation: function(uiSourceCode, lineNumber, columnNumber)
{
var script = this._scriptForUISourceCode.get(uiSourceCode);
if (!script)
return null;
return WebInspector.debuggerModel.createRawLocation(script, lineNumber, columnNumber);
},
_addScript: function(script)
{
var snippetId = this._snippetIdForSourceURL(script.sourceURL);
if (!snippetId)
return;
var uiSourceCode = this._uiSourceCodeForSnippetId[snippetId];
if (!uiSourceCode || this._evaluationSourceURL(uiSourceCode) !== script.sourceURL)
return;
console.assert(!this._scriptForUISourceCode.get(uiSourceCode));
this._uiSourceCodeForScriptId[script.scriptId] = uiSourceCode;
this._scriptForUISourceCode.put(uiSourceCode, script);
uiSourceCode.scriptFile().setHasDivergedFromVM(false);
script.pushSourceMapping(this._snippetScriptMapping);
},
_removeBreakpoints: function(uiSourceCode)
{
var breakpointLocations = WebInspector.breakpointManager.breakpointLocationsForUISourceCode(uiSourceCode);
for (var i = 0; i < breakpointLocations.length; ++i)
breakpointLocations[i].breakpoint.remove();
return breakpointLocations;
},
_restoreBreakpoints: function(uiSourceCode, breakpointLocations)
{
for (var i = 0; i < breakpointLocations.length; ++i) {
var uiLocation = breakpointLocations[i].uiLocation;
var breakpoint = breakpointLocations[i].breakpoint;
WebInspector.breakpointManager.setBreakpoint(uiSourceCode, uiLocation.lineNumber, breakpoint.condition(), breakpoint.enabled());
}
},
_releaseSnippetScript: function(uiSourceCode)
{
var script = this._scriptForUISourceCode.get(uiSourceCode);
if (!script)
return null;
uiSourceCode.scriptFile().setIsDivergingFromVM(true);
uiSourceCode.scriptFile().setHasDivergedFromVM(true);
delete this._uiSourceCodeForScriptId[script.scriptId];
this._scriptForUISourceCode.remove(uiSourceCode);
delete uiSourceCode._evaluationIndex;
script.popSourceMapping(this._snippetScriptMapping);
uiSourceCode.scriptFile().setIsDivergingFromVM(false);
return script.rawLocationToUILocation(0, 0).uiSourceCode;
},
_debuggerReset: function()
{
for (var snippetId in this._uiSourceCodeForSnippetId) {
var uiSourceCode = this._uiSourceCodeForSnippetId[snippetId];
this._releaseSnippetScript(uiSourceCode);
}
},
_evaluationSourceURL: function(uiSourceCode)
{
var evaluationSuffix = "_" + uiSourceCode._evaluationIndex;
var snippetId = this._snippetIdForUISourceCode.get(uiSourceCode);
return WebInspector.Script.snippetSourceURLPrefix + snippetId + evaluationSuffix;
},
_snippetIdForSourceURL: function(sourceURL)
{
var snippetPrefix = WebInspector.Script.snippetSourceURLPrefix;
if (!sourceURL.startsWith(snippetPrefix))
return null;
var splittedURL = sourceURL.substring(snippetPrefix.length).split("_");
var snippetId = splittedURL[0];
return snippetId;
},
reset: function()
{
this._uiSourceCodeForScriptId = {};
this._scriptForUISourceCode = new Map();
this._uiSourceCodeForSnippetId = {};
this._snippetIdForUISourceCode = new Map();
this._workspaceProvider.reset();
this._loadSnippets();
},
__proto__: WebInspector.Object.prototype
}
WebInspector.SnippetScriptFile = function(scriptSnippetModel, uiSourceCode)
{
WebInspector.ScriptFile.call(this);
this._scriptSnippetModel = scriptSnippetModel;
this._uiSourceCode = uiSourceCode;
this._hasDivergedFromVM = true;
this._uiSourceCode.addEventListener(WebInspector.UISourceCode.Events.WorkingCopyCommitted, this._workingCopyCommitted, this);
this._uiSourceCode.addEventListener(WebInspector.UISourceCode.Events.WorkingCopyChanged, this._workingCopyChanged, this);
}
WebInspector.SnippetScriptFile.prototype = {
hasDivergedFromVM: function()
{
return this._hasDivergedFromVM;
},
setHasDivergedFromVM: function(hasDivergedFromVM)
{
this._hasDivergedFromVM = hasDivergedFromVM;
},
isDivergingFromVM: function()
{
return this._isDivergingFromVM;
},
checkMapping: function()
{
},
isMergingToVM: function()
{
return false;
},
setIsDivergingFromVM: function(isDivergingFromVM)
{
this._isDivergingFromVM = isDivergingFromVM;
},
_workingCopyCommitted: function()
{
this._scriptSnippetModel._setScriptSnippetContent(this._uiSourceCode, this._uiSourceCode.workingCopy());
},
_workingCopyChanged: function()
{
this._scriptSnippetModel._scriptSnippetEdited(this._uiSourceCode);
},
__proto__: WebInspector.Object.prototype
}
WebInspector.SnippetScriptMapping = function(scriptSnippetModel)
{
this._scriptSnippetModel = scriptSnippetModel;
}
WebInspector.SnippetScriptMapping.prototype = {
rawLocationToUILocation: function(rawLocation)
{
var debuggerModelLocation = (rawLocation);
return this._scriptSnippetModel._rawLocationToUILocation(debuggerModelLocation);
},
uiLocationToRawLocation: function(uiSourceCode, lineNumber, columnNumber)
{
return this._scriptSnippetModel._uiLocationToRawLocation(uiSourceCode, lineNumber, columnNumber);
},
isIdentity: function()
{
return true;
},
snippetIdForSourceURL: function(sourceURL)
{
return this._scriptSnippetModel._snippetIdForSourceURL(sourceURL);
},
addScript: function(script)
{
this._scriptSnippetModel._addScript(script);
}
}
WebInspector.SnippetContentProvider = function(snippet)
{
WebInspector.StaticContentProvider.call(this, WebInspector.resourceTypes.Script, snippet.content);
}
WebInspector.SnippetContentProvider.prototype = {
__proto__: WebInspector.StaticContentProvider.prototype
}
WebInspector.scriptSnippetModel = null;