1 /* 2 * Copyright (C) 2012 Google Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions are 6 * met: 7 * 8 * * Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * * Redistributions in binary form must reproduce the above 11 * copyright notice, this list of conditions and the following disclaimer 12 * in the documentation and/or other materials provided with the 13 * distribution. 14 * * Neither the name of Google Inc. nor the names of its 15 * contributors may be used to endorse or promote products derived from 16 * this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31 /** 32 * @constructor 33 * @param {!WebInspector.Workspace} workspace 34 */ 35 WebInspector.LiveEditSupport = function(workspace) 36 { 37 this._workspaceProvider = new WebInspector.SimpleWorkspaceProvider(workspace, WebInspector.projectTypes.LiveEdit); 38 WebInspector.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.GlobalObjectCleared, this._debuggerReset, this); 39 this._debuggerReset(); 40 } 41 42 WebInspector.LiveEditSupport.prototype = { 43 /** 44 * @param {!WebInspector.UISourceCode} uiSourceCode 45 * @return {!WebInspector.UISourceCode} 46 */ 47 uiSourceCodeForLiveEdit: function(uiSourceCode) 48 { 49 var rawLocation = uiSourceCode.uiLocationToRawLocation(0, 0); 50 var debuggerModelLocation = /** @type {!WebInspector.DebuggerModel.Location} */ (rawLocation); 51 var script = WebInspector.debuggerModel.scriptForId(debuggerModelLocation.scriptId); 52 var uiLocation = script.rawLocationToUILocation(0, 0); 53 54 // FIXME: Support live editing of scripts mapped to some file. 55 if (uiLocation.uiSourceCode !== uiSourceCode) 56 return uiLocation.uiSourceCode; 57 if (this._uiSourceCodeForScriptId[script.scriptId]) 58 return this._uiSourceCodeForScriptId[script.scriptId]; 59 60 console.assert(!script.isInlineScript()); 61 var liveEditUISourceCode = this._workspaceProvider.addUniqueFileForURL(script.sourceURL, script, true, script.isContentScript); 62 63 liveEditUISourceCode.setScriptFile(new WebInspector.LiveEditScriptFile(uiSourceCode, liveEditUISourceCode, script.scriptId)); 64 this._uiSourceCodeForScriptId[script.scriptId] = liveEditUISourceCode; 65 this._scriptIdForUISourceCode.put(liveEditUISourceCode, script.scriptId); 66 return liveEditUISourceCode; 67 }, 68 69 _debuggerReset: function() 70 { 71 /** @type {!Object.<string, !WebInspector.UISourceCode>} */ 72 this._uiSourceCodeForScriptId = {}; 73 /** @type {!Map.<!WebInspector.UISourceCode, string>} */ 74 this._scriptIdForUISourceCode = new Map(); 75 this._workspaceProvider.reset(); 76 }, 77 } 78 79 /** 80 * @param {?string} error 81 * @param {!DebuggerAgent.SetScriptSourceError=} errorData 82 * @param {!WebInspector.Script=} contextScript 83 */ 84 WebInspector.LiveEditSupport.logDetailedError = function(error, errorData, contextScript) 85 { 86 var warningLevel = WebInspector.ConsoleMessage.MessageLevel.Warning; 87 if (!errorData) { 88 if (error) 89 WebInspector.log(WebInspector.UIString("LiveEdit failed: %s", error), warningLevel, false); 90 return; 91 } 92 var compileError = errorData.compileError; 93 if (compileError) { 94 var message = "LiveEdit compile failed: " + compileError.message; 95 if (contextScript) 96 message += " at " + contextScript.sourceURL + ":" + compileError.lineNumber + ":" + compileError.columnNumber; 97 WebInspector.log(message, WebInspector.ConsoleMessage.MessageLevel.Error, false); 98 } else { 99 WebInspector.log("Unknown LiveEdit error: " + JSON.stringify(errorData) + "; " + error, warningLevel, false); 100 } 101 } 102 103 WebInspector.LiveEditSupport.logSuccess = function() 104 { 105 WebInspector.log(WebInspector.UIString("Recompilation and update succeeded."), WebInspector.ConsoleMessage.MessageLevel.Debug, false); 106 } 107 108 /** 109 * @constructor 110 * @implements {WebInspector.ScriptFile} 111 * @extends {WebInspector.Object} 112 * @param {!WebInspector.UISourceCode} uiSourceCode 113 * @param {!WebInspector.UISourceCode} liveEditUISourceCode 114 * @param {string} scriptId 115 */ 116 WebInspector.LiveEditScriptFile = function(uiSourceCode, liveEditUISourceCode, scriptId) 117 { 118 WebInspector.ScriptFile.call(this); 119 this._uiSourceCode = uiSourceCode; 120 this._liveEditUISourceCode = liveEditUISourceCode; 121 this._scriptId = scriptId; 122 this._liveEditUISourceCode.addEventListener(WebInspector.UISourceCode.Events.WorkingCopyCommitted, this._workingCopyCommitted, this); 123 } 124 125 WebInspector.LiveEditScriptFile.prototype = { 126 _workingCopyCommitted: function(event) 127 { 128 /** 129 * @param {?string} error 130 * @param {!DebuggerAgent.SetScriptSourceError=} errorData 131 * @this {WebInspector.LiveEditScriptFile} 132 */ 133 function innerCallback(error, errorData) 134 { 135 if (error) { 136 var script = WebInspector.debuggerModel.scriptForId(this._scriptId); 137 WebInspector.LiveEditSupport.logDetailedError(error, errorData, script); 138 return; 139 } 140 WebInspector.LiveEditSupport.logSuccess(); 141 } 142 143 var script = WebInspector.debuggerModel.scriptForId(this._scriptId); 144 WebInspector.debuggerModel.setScriptSource(script.scriptId, this._liveEditUISourceCode.workingCopy(), innerCallback.bind(this)); 145 }, 146 147 /** 148 * @return {boolean} 149 */ 150 hasDivergedFromVM: function() 151 { 152 return true; 153 }, 154 155 /** 156 * @return {boolean} 157 */ 158 isDivergingFromVM: function() 159 { 160 return false; 161 }, 162 163 /** 164 * @return {boolean} 165 */ 166 isMergingToVM: function() 167 { 168 return false; 169 }, 170 171 checkMapping: function() 172 { 173 }, 174 175 __proto__: WebInspector.Object.prototype 176 } 177 178 /** @type {!WebInspector.LiveEditSupport} */ 179 WebInspector.liveEditSupport; 180