1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
7 * @implements {WebInspector.TargetManager.Observer}
8 * @param {!WebInspector.TargetManager} targetManager
9 * @param {!WebInspector.Workspace} workspace
10 * @param {!WebInspector.NetworkWorkspaceBinding} networkWorkspaceBinding
12 WebInspector.DebuggerWorkspaceBinding = function(targetManager, workspace, networkWorkspaceBinding)
14 this._workspace = workspace;
15 this._networkWorkspaceBinding = networkWorkspaceBinding;
17 /** @type {!Map.<!WebInspector.Target, !WebInspector.DebuggerWorkspaceBinding.TargetData>} */
18 this._targetToData = new Map();
19 targetManager.observeTargets(this);
21 targetManager.addModelListener(WebInspector.DebuggerModel, WebInspector.DebuggerModel.Events.GlobalObjectCleared, this._globalObjectCleared, this);
22 targetManager.addModelListener(WebInspector.DebuggerModel, WebInspector.DebuggerModel.Events.DebuggerResumed, this._debuggerResumed, this);
23 workspace.addEventListener(WebInspector.Workspace.Events.UISourceCodeRemoved, this._uiSourceCodeRemoved, this);
24 workspace.addEventListener(WebInspector.Workspace.Events.ProjectRemoved, this._projectRemoved, this);
27 WebInspector.DebuggerWorkspaceBinding.prototype = {
29 * @param {!WebInspector.Target} target
31 targetAdded: function(target)
33 this._targetToData.set(target, new WebInspector.DebuggerWorkspaceBinding.TargetData(target, this));
37 * @param {!WebInspector.Target} target
39 targetRemoved: function(target)
41 var targetData = this._targetToData.get(target);
42 targetData._dispose();
43 this._targetToData.remove(target);
47 * @param {!WebInspector.Event} event
49 _uiSourceCodeRemoved: function(event)
51 var uiSourceCode = /** @type {!WebInspector.UISourceCode} */ (event.data);
52 var targetDatas = this._targetToData.values();
53 for (var i = 0; i < targetDatas.length; ++i)
54 targetDatas[i]._uiSourceCodeRemoved(uiSourceCode);
58 * @param {!WebInspector.Event} event
60 _projectRemoved: function(event)
62 var project = /** @type {!WebInspector.Project} */ (event.data);
63 var targetDatas = this._targetToData.values();
64 var uiSourceCodes = project.uiSourceCodes();
65 for (var i = 0; i < targetDatas.length; ++i) {
66 for (var j = 0; j < uiSourceCodes.length; ++j)
67 targetDatas[i]._uiSourceCodeRemoved(uiSourceCodes[j]);
72 * @param {!WebInspector.Script} script
73 * @param {!WebInspector.DebuggerSourceMapping} sourceMapping
75 pushSourceMapping: function(script, sourceMapping)
77 var info = this._ensureInfoForScript(script);
78 info._pushSourceMapping(sourceMapping);
82 * @param {!WebInspector.Script} script
83 * @return {!WebInspector.DebuggerSourceMapping}
85 popSourceMapping: function(script)
87 var info = this._infoForScript(script.target(), script.scriptId);
89 return info._popSourceMapping();
93 * @param {!WebInspector.Target} target
94 * @param {!WebInspector.UISourceCode} uiSourceCode
95 * @param {?WebInspector.DebuggerSourceMapping} sourceMapping
97 setSourceMapping: function(target, uiSourceCode, sourceMapping)
99 var data = this._targetToData.get(target);
101 data._setSourceMapping(uiSourceCode, sourceMapping);
105 * @param {!WebInspector.Script} script
107 updateLocations: function(script)
109 var info = this._infoForScript(script.target(), script.scriptId);
111 info._updateLocations();
115 * @param {!WebInspector.DebuggerModel.Location} rawLocation
116 * @param {function(!WebInspector.UILocation):(boolean|undefined)} updateDelegate
117 * @return {!WebInspector.DebuggerWorkspaceBinding.Location}
119 createLiveLocation: function(rawLocation, updateDelegate)
121 var info = this._infoForScript(rawLocation.target(), rawLocation.scriptId);
122 console.assert(info);
123 var location = new WebInspector.DebuggerWorkspaceBinding.Location(info._script, rawLocation, this, updateDelegate);
124 info._addLocation(location);
129 * @param {!WebInspector.DebuggerModel.CallFrame} callFrame
130 * @param {function(!WebInspector.UILocation):(boolean|undefined)} updateDelegate
131 * @return {!WebInspector.DebuggerWorkspaceBinding.Location}
133 createCallFrameLiveLocation: function(callFrame, updateDelegate)
135 var target = callFrame.target();
136 this._ensureInfoForScript(callFrame.script)
137 var location = this.createLiveLocation(callFrame.location(), updateDelegate);
138 this._registerCallFrameLiveLocation(target, location);
143 * @param {!WebInspector.DebuggerModel.Location} rawLocation
144 * @return {!WebInspector.UILocation}
146 rawLocationToUILocation: function(rawLocation)
148 var info = this._infoForScript(rawLocation.target(), rawLocation.scriptId);
149 console.assert(info);
150 return info._rawLocationToUILocation(rawLocation);
154 * @param {!WebInspector.Target} target
155 * @param {!WebInspector.UISourceCode} uiSourceCode
156 * @param {number} lineNumber
157 * @param {number} columnNumber
158 * @return {?WebInspector.DebuggerModel.Location}
160 uiLocationToRawLocation: function(target, uiSourceCode, lineNumber, columnNumber)
162 var targetData = this._targetToData.get(target);
163 return targetData ? /** @type {?WebInspector.DebuggerModel.Location} */ (targetData._uiLocationToRawLocation(uiSourceCode, lineNumber, columnNumber)) : null;
167 * @param {!WebInspector.UISourceCode} uiSourceCode
168 * @param {number} lineNumber
169 * @param {number} columnNumber
170 * @return {!Array.<!WebInspector.DebuggerModel.Location>}
172 uiLocationToRawLocations: function(uiSourceCode, lineNumber, columnNumber)
175 var targetDatas = this._targetToData.values();
176 for (var i = 0; i < targetDatas.length; ++i) {
177 var rawLocation = targetDatas[i]._uiLocationToRawLocation(uiSourceCode, lineNumber, columnNumber);
179 result.push(rawLocation);
185 * @param {!WebInspector.UISourceCode} uiSourceCode
186 * @param {number} lineNumber
189 uiLineHasMapping: function(uiSourceCode, lineNumber)
191 var targetDatas = this._targetToData.values();
192 for (var i = 0; i < targetDatas.length; ++i) {
193 if (!targetDatas[i]._uiLineHasMapping(uiSourceCode, lineNumber))
200 * @param {!WebInspector.Target} target
201 * @return {?WebInspector.LiveEditSupport}
203 liveEditSupport: function(target)
205 var targetData = this._targetToData.get(target);
206 return targetData ? targetData._liveEditSupport : null;
210 * @param {!WebInspector.UISourceCode} uiSourceCode
211 * @param {!WebInspector.Target} target
212 * @return {?WebInspector.ResourceScriptFile}
214 scriptFile: function(uiSourceCode, target)
216 var targetData = this._targetToData.get(target);
217 return targetData ? targetData._resourceMapping.scriptFile(uiSourceCode) : null;
221 * @param {!WebInspector.Event} event
223 _globalObjectCleared: function(event)
225 var debuggerModel = /** @type {!WebInspector.DebuggerModel} */ (event.target);
226 this._reset(debuggerModel.target());
230 * @param {!WebInspector.Target} target
232 _reset: function(target)
234 var targetData = this._targetToData.get(target);
235 targetData.callFrameLocations.values().forEach(function(location) { location.dispose(); });
236 targetData.callFrameLocations.clear();
240 * @param {!WebInspector.Script} script
241 * @return {!WebInspector.DebuggerWorkspaceBinding.ScriptInfo}
243 _ensureInfoForScript: function(script)
245 var scriptDataMap = this._targetToData.get(script.target()).scriptDataMap;
246 var info = scriptDataMap.get(script.scriptId);
248 info = new WebInspector.DebuggerWorkspaceBinding.ScriptInfo(script);
249 scriptDataMap.set(script.scriptId, info);
256 * @param {!WebInspector.Target} target
257 * @param {string} scriptId
258 * @return {?WebInspector.DebuggerWorkspaceBinding.ScriptInfo}
260 _infoForScript: function(target, scriptId)
262 var data = this._targetToData.get(target);
265 return data.scriptDataMap.get(scriptId) || null;
269 * @param {!WebInspector.Target} target
270 * @param {!WebInspector.DebuggerWorkspaceBinding.Location} location
272 _registerCallFrameLiveLocation: function(target, location)
274 var locations = this._targetToData.get(target).callFrameLocations;
275 locations.add(location);
279 * @param {!WebInspector.DebuggerWorkspaceBinding.Location} location
281 _removeLiveLocation: function(location)
283 var info = this._infoForScript(location._script.target(), location._script.scriptId);
285 info._removeLocation(location);
289 * @param {!WebInspector.Event} event
291 _debuggerResumed: function(event)
293 var debuggerModel = /** @type {!WebInspector.DebuggerModel} */ (event.target);
294 this._reset(debuggerModel.target());
300 * @param {!WebInspector.Target} target
301 * @param {!WebInspector.DebuggerWorkspaceBinding} debuggerWorkspaceBinding
303 WebInspector.DebuggerWorkspaceBinding.TargetData = function(target, debuggerWorkspaceBinding)
305 this._target = target;
307 /** @type {!StringMap.<!WebInspector.DebuggerWorkspaceBinding.ScriptInfo>} */
308 this.scriptDataMap = new StringMap();
310 /** @type {!Set.<!WebInspector.DebuggerWorkspaceBinding.Location>} */
311 this.callFrameLocations = new Set();
313 var debuggerModel = target.debuggerModel;
314 var workspace = debuggerWorkspaceBinding._workspace;
316 this._liveEditSupport = new WebInspector.LiveEditSupport(target, workspace, debuggerWorkspaceBinding);
317 this._defaultMapping = new WebInspector.DefaultScriptMapping(debuggerModel, workspace, debuggerWorkspaceBinding);
318 this._resourceMapping = new WebInspector.ResourceScriptMapping(debuggerModel, workspace, debuggerWorkspaceBinding);
319 this._compilerMapping = new WebInspector.CompilerScriptMapping(debuggerModel, workspace, debuggerWorkspaceBinding._networkWorkspaceBinding, debuggerWorkspaceBinding);
321 /** @type {!WebInspector.LiveEditSupport} */
322 this._liveEditSupport = new WebInspector.LiveEditSupport(target, workspace, debuggerWorkspaceBinding);
324 /** @type {!Map.<!WebInspector.UISourceCode, !WebInspector.DebuggerSourceMapping>} */
325 this._uiSourceCodeToSourceMapping = new Map();
327 debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.ParsedScriptSource, this._parsedScriptSource, this);
328 debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.FailedToParseScriptSource, this._parsedScriptSource, this);
331 WebInspector.DebuggerWorkspaceBinding.TargetData.prototype = {
333 * @param {!WebInspector.Event} event
335 _parsedScriptSource: function(event)
337 var script = /** @type {!WebInspector.Script} */ (event.data);
338 this._defaultMapping.addScript(script);
340 if (script.isSnippet()) {
341 WebInspector.scriptSnippetModel.addScript(script);
345 this._resourceMapping.addScript(script);
347 if (WebInspector.settings.jsSourceMapsEnabled.get())
348 this._compilerMapping.addScript(script);
352 * @param {!WebInspector.UISourceCode} uiSourceCode
353 * @param {?WebInspector.DebuggerSourceMapping} sourceMapping
355 _setSourceMapping: function(uiSourceCode, sourceMapping)
357 if (this._uiSourceCodeToSourceMapping.get(uiSourceCode) === sourceMapping)
361 this._uiSourceCodeToSourceMapping.set(uiSourceCode, sourceMapping);
363 this._uiSourceCodeToSourceMapping.remove(uiSourceCode);
365 uiSourceCode.dispatchEventToListeners(WebInspector.UISourceCode.Events.SourceMappingChanged, {target: this._target, isIdentity: sourceMapping ? sourceMapping.isIdentity() : false});
369 * @param {!WebInspector.UISourceCode} uiSourceCode
370 * @param {number} lineNumber
371 * @param {number} columnNumber
372 * @return {?WebInspector.DebuggerModel.Location}
374 _uiLocationToRawLocation: function(uiSourceCode, lineNumber, columnNumber)
376 var sourceMapping = this._uiSourceCodeToSourceMapping.get(uiSourceCode);
377 return sourceMapping ? sourceMapping.uiLocationToRawLocation(uiSourceCode, lineNumber, columnNumber) : null;
381 * @param {!WebInspector.UISourceCode} uiSourceCode
382 * @param {number} lineNumber
385 _uiLineHasMapping: function(uiSourceCode, lineNumber)
387 var sourceMapping = this._uiSourceCodeToSourceMapping.get(uiSourceCode);
388 return sourceMapping ? sourceMapping.uiLineHasMapping(uiSourceCode, lineNumber) : true;
392 * @param {!WebInspector.UISourceCode} uiSourceCode
394 _uiSourceCodeRemoved: function(uiSourceCode)
396 this._uiSourceCodeToSourceMapping.remove(uiSourceCode);
401 this._compilerMapping.dispose();
402 this._resourceMapping.dispose();
403 this._defaultMapping.dispose();
404 this._uiSourceCodeToSourceMapping.clear();
410 * @param {!WebInspector.Script} script
412 WebInspector.DebuggerWorkspaceBinding.ScriptInfo = function(script)
414 this._script = script;
416 /** @type {!Array.<!WebInspector.DebuggerSourceMapping>} */
417 this._sourceMappings = [];
419 /** @type {!Set.<!WebInspector.LiveLocation>} */
420 this._locations = new Set();
423 WebInspector.DebuggerWorkspaceBinding.ScriptInfo.prototype = {
425 * @param {!WebInspector.DebuggerSourceMapping} sourceMapping
427 _pushSourceMapping: function(sourceMapping)
429 this._sourceMappings.push(sourceMapping);
430 this._updateLocations();
434 * @return {!WebInspector.DebuggerSourceMapping}
436 _popSourceMapping: function()
438 var sourceMapping = this._sourceMappings.pop();
439 this._updateLocations();
440 return sourceMapping;
444 * @param {!WebInspector.LiveLocation} location
446 _addLocation: function(location)
448 this._locations.add(location);
453 * @param {!WebInspector.LiveLocation} location
455 _removeLocation: function(location)
457 this._locations.remove(location);
460 _updateLocations: function()
462 var items = this._locations.values();
463 for (var i = 0; i < items.length; ++i)
468 * @param {!WebInspector.DebuggerModel.Location} rawLocation
469 * @return {!WebInspector.UILocation}
471 _rawLocationToUILocation: function(rawLocation)
474 for (var i = this._sourceMappings.length - 1; !uiLocation && i >= 0; --i)
475 uiLocation = this._sourceMappings[i].rawLocationToUILocation(rawLocation);
476 console.assert(uiLocation, "Script raw location cannot be mapped to any UI location.");
477 return /** @type {!WebInspector.UILocation} */ (uiLocation);
484 * @extends {WebInspector.LiveLocation}
485 * @param {!WebInspector.Script} script
486 * @param {!WebInspector.DebuggerModel.Location} rawLocation
487 * @param {!WebInspector.DebuggerWorkspaceBinding} binding
488 * @param {function(!WebInspector.UILocation):(boolean|undefined)} updateDelegate
490 WebInspector.DebuggerWorkspaceBinding.Location = function(script, rawLocation, binding, updateDelegate)
492 WebInspector.LiveLocation.call(this, updateDelegate);
493 this._script = script;
494 this._rawLocation = rawLocation;
495 this._binding = binding;
498 WebInspector.DebuggerWorkspaceBinding.Location.prototype = {
500 * @return {!WebInspector.UILocation}
502 uiLocation: function()
504 var debuggerModelLocation = this._rawLocation;
505 return this._binding.rawLocationToUILocation(debuggerModelLocation);
510 WebInspector.LiveLocation.prototype.dispose.call(this);
511 this._binding._removeLiveLocation(this);
514 __proto__: WebInspector.LiveLocation.prototype
520 WebInspector.DebuggerSourceMapping = function()
524 WebInspector.DebuggerSourceMapping.prototype = {
526 * @param {!WebInspector.DebuggerModel.Location} rawLocation
527 * @return {?WebInspector.UILocation}
529 rawLocationToUILocation: function(rawLocation) { },
532 * @param {!WebInspector.UISourceCode} uiSourceCode
533 * @param {number} lineNumber
534 * @param {number} columnNumber
535 * @return {?WebInspector.DebuggerModel.Location}
537 uiLocationToRawLocation: function(uiSourceCode, lineNumber, columnNumber) { },
542 isIdentity: function() { },
545 * @param {!WebInspector.UISourceCode} uiSourceCode
546 * @param {number} lineNumber
549 uiLineHasMapping: function(uiSourceCode, lineNumber) { }
553 * @type {!WebInspector.DebuggerWorkspaceBinding}
555 WebInspector.debuggerWorkspaceBinding;