CompilerScriptMapping.js 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  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. * @constructor
  32. * @implements {WebInspector.ScriptSourceMapping}
  33. * @param {WebInspector.Workspace} workspace
  34. * @param {WebInspector.SimpleWorkspaceProvider} networkWorkspaceProvider
  35. */
  36. WebInspector.CompilerScriptMapping = function(workspace, networkWorkspaceProvider)
  37. {
  38. this._workspace = workspace;
  39. this._workspace.addEventListener(WebInspector.Workspace.Events.UISourceCodeAdded, this._uiSourceCodeAddedToWorkspace, this);
  40. this._networkWorkspaceProvider = networkWorkspaceProvider;
  41. /** @type {!Object.<string, WebInspector.SourceMap>} */
  42. this._sourceMapForSourceMapURL = {};
  43. /** @type {!Object.<string, Array.<function(?WebInspector.SourceMap)>>} */
  44. this._pendingSourceMapLoadingCallbacks = {};
  45. /** @type {!Object.<string, WebInspector.SourceMap>} */
  46. this._sourceMapForScriptId = {};
  47. /** @type {!Map.<WebInspector.SourceMap, WebInspector.Script>} */
  48. this._scriptForSourceMap = new Map();
  49. /** @type {!Object.<string, WebInspector.SourceMap>} */
  50. this._sourceMapForURL = {};
  51. WebInspector.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.GlobalObjectCleared, this._debuggerReset, this);
  52. }
  53. WebInspector.CompilerScriptMapping.prototype = {
  54. /**
  55. * @param {WebInspector.RawLocation} rawLocation
  56. * @return {WebInspector.UILocation}
  57. */
  58. rawLocationToUILocation: function(rawLocation)
  59. {
  60. var debuggerModelLocation = /** @type {WebInspector.DebuggerModel.Location} */ (rawLocation);
  61. var sourceMap = this._sourceMapForScriptId[debuggerModelLocation.scriptId];
  62. if (!sourceMap)
  63. return null;
  64. var lineNumber = debuggerModelLocation.lineNumber;
  65. var columnNumber = debuggerModelLocation.columnNumber || 0;
  66. var entry = sourceMap.findEntry(lineNumber, columnNumber);
  67. if (!entry || entry.length === 2)
  68. return null;
  69. var url = entry[2];
  70. var uiSourceCode = this._workspace.uiSourceCodeForURL(url);
  71. if (!uiSourceCode)
  72. return null;
  73. return new WebInspector.UILocation(uiSourceCode, entry[3], entry[4]);
  74. },
  75. /**
  76. * @param {WebInspector.UISourceCode} uiSourceCode
  77. * @param {number} lineNumber
  78. * @param {number} columnNumber
  79. * @return {WebInspector.DebuggerModel.Location}
  80. */
  81. uiLocationToRawLocation: function(uiSourceCode, lineNumber, columnNumber)
  82. {
  83. if (!uiSourceCode.url)
  84. return null;
  85. var sourceMap = this._sourceMapForURL[uiSourceCode.url];
  86. if (!sourceMap)
  87. return null;
  88. var entry = sourceMap.findEntryReversed(uiSourceCode.url, lineNumber);
  89. return WebInspector.debuggerModel.createRawLocation(this._scriptForSourceMap.get(sourceMap) || null, entry[0], entry[1]);
  90. },
  91. /**
  92. * @return {boolean}
  93. */
  94. isIdentity: function()
  95. {
  96. return false;
  97. },
  98. /**
  99. * @param {WebInspector.Script} script
  100. */
  101. addScript: function(script)
  102. {
  103. script.pushSourceMapping(this);
  104. this.loadSourceMapForScript(script, sourceMapLoaded.bind(this));
  105. /**
  106. * @param {?WebInspector.SourceMap} sourceMap
  107. */
  108. function sourceMapLoaded(sourceMap)
  109. {
  110. if (!sourceMap)
  111. return;
  112. if (this._scriptForSourceMap.get(sourceMap)) {
  113. this._sourceMapForScriptId[script.scriptId] = sourceMap;
  114. script.updateLocations();
  115. return;
  116. }
  117. this._sourceMapForScriptId[script.scriptId] = sourceMap;
  118. this._scriptForSourceMap.put(sourceMap, script);
  119. var sourceURLs = sourceMap.sources();
  120. for (var i = 0; i < sourceURLs.length; ++i) {
  121. var sourceURL = sourceURLs[i];
  122. if (this._sourceMapForURL[sourceURL])
  123. continue;
  124. this._sourceMapForURL[sourceURL] = sourceMap;
  125. if (!this._workspace.hasMappingForURL(sourceURL) && !this._workspace.uiSourceCodeForURL(sourceURL)) {
  126. var contentProvider = sourceMap.sourceContentProvider(sourceURL, WebInspector.resourceTypes.Script);
  127. this._networkWorkspaceProvider.addFileForURL(sourceURL, contentProvider, true);
  128. }
  129. var uiSourceCode = this._workspace.uiSourceCodeForURL(sourceURL);
  130. if (uiSourceCode) {
  131. this._bindUISourceCode(uiSourceCode);
  132. uiSourceCode.isContentScript = script.isContentScript;
  133. }
  134. }
  135. script.updateLocations();
  136. }
  137. },
  138. /**
  139. * @param {WebInspector.UISourceCode} uiSourceCode
  140. */
  141. _bindUISourceCode: function(uiSourceCode)
  142. {
  143. uiSourceCode.setSourceMapping(this);
  144. },
  145. /**
  146. * @param {WebInspector.Event} event
  147. */
  148. _uiSourceCodeAddedToWorkspace: function(event)
  149. {
  150. var uiSourceCode = /** @type {WebInspector.UISourceCode} */ (event.data);
  151. if (!uiSourceCode.url || !this._sourceMapForURL[uiSourceCode.url])
  152. return;
  153. this._bindUISourceCode(uiSourceCode);
  154. },
  155. /**
  156. * @param {WebInspector.Script} script
  157. * @param {function(?WebInspector.SourceMap)} callback
  158. */
  159. loadSourceMapForScript: function(script, callback)
  160. {
  161. // script.sourceURL can be a random string, but is generally an absolute path -> complete it to inspected page url for
  162. // relative links.
  163. if (!script.sourceMapURL) {
  164. callback(null);
  165. return;
  166. }
  167. var scriptURL = WebInspector.ParsedURL.completeURL(WebInspector.inspectedPageURL, script.sourceURL);
  168. if (!scriptURL) {
  169. callback(null);
  170. return;
  171. }
  172. var sourceMapURL = WebInspector.ParsedURL.completeURL(scriptURL, script.sourceMapURL);
  173. if (!sourceMapURL) {
  174. callback(null);
  175. return;
  176. }
  177. var sourceMap = this._sourceMapForSourceMapURL[sourceMapURL];
  178. if (sourceMap) {
  179. callback(sourceMap);
  180. return;
  181. }
  182. var pendingCallbacks = this._pendingSourceMapLoadingCallbacks[sourceMapURL];
  183. if (pendingCallbacks) {
  184. pendingCallbacks.push(callback);
  185. return;
  186. }
  187. pendingCallbacks = [callback];
  188. this._pendingSourceMapLoadingCallbacks[sourceMapURL] = pendingCallbacks;
  189. WebInspector.SourceMap.load(sourceMapURL, scriptURL, sourceMapLoaded.bind(this));
  190. /**
  191. * @param {?WebInspector.SourceMap} sourceMap
  192. */
  193. function sourceMapLoaded(sourceMap)
  194. {
  195. var callbacks = this._pendingSourceMapLoadingCallbacks[sourceMapURL];
  196. delete this._pendingSourceMapLoadingCallbacks[sourceMapURL];
  197. if (!callbacks)
  198. return;
  199. if (sourceMap)
  200. this._sourceMapForSourceMapURL[sourceMapURL] = sourceMap;
  201. for (var i = 0; i < callbacks.length; ++i)
  202. callbacks[i](sourceMap);
  203. }
  204. },
  205. _debuggerReset: function()
  206. {
  207. this._sourceMapForSourceMapURL = {};
  208. this._pendingSourceMapLoadingCallbacks = {};
  209. this._sourceMapForScriptId = {};
  210. this._scriptForSourceMap = new Map();
  211. this._sourceMapForURL = {};
  212. }
  213. }