UNPKG

monaca-lib

Version:

Monaca cloud API bindings for JavaScript

455 lines (408 loc) 15 kB
/* * Copyright (C) 2012 Google Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /** * @constructor * @implements {WebInspector.DebuggerSourceMapping} * @param {!WebInspector.DebuggerModel} debuggerModel * @param {!WebInspector.Workspace} workspace * @param {!WebInspector.NetworkMapping} networkMapping * @param {!WebInspector.DebuggerWorkspaceBinding} debuggerWorkspaceBinding */ WebInspector.ResourceScriptMapping = function(debuggerModel, workspace, networkMapping, debuggerWorkspaceBinding) { this._target = debuggerModel.target(); this._debuggerModel = debuggerModel; this._workspace = workspace; this._workspace.addEventListener(WebInspector.Workspace.Events.UISourceCodeAdded, this._uiSourceCodeAdded, this); this._workspace.addEventListener(WebInspector.Workspace.Events.UISourceCodeRemoved, this._uiSourceCodeRemoved, this); this._networkMapping = networkMapping; this._debuggerWorkspaceBinding = debuggerWorkspaceBinding; /** @type {!Set.<string>} */ this._boundURLs = new Set(); /** @type {!Map.<!WebInspector.UISourceCode, !WebInspector.ResourceScriptFile>} */ this._uiSourceCodeToScriptFile = new Map(); debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.GlobalObjectCleared, this._debuggerReset, this); } WebInspector.ResourceScriptMapping.prototype = { /** * @override * @param {!WebInspector.DebuggerModel.Location} rawLocation * @return {?WebInspector.UILocation} */ rawLocationToUILocation: function(rawLocation) { var debuggerModelLocation = /** @type {!WebInspector.DebuggerModel.Location} */ (rawLocation); var script = debuggerModelLocation.script(); var uiSourceCode = this._workspaceUISourceCodeForScript(script); if (!uiSourceCode) return null; var scriptFile = this.scriptFile(uiSourceCode); if (scriptFile && ((scriptFile.hasDivergedFromVM() && !scriptFile.isMergingToVM()) || scriptFile.isDivergingFromVM())) return null; var lineNumber = debuggerModelLocation.lineNumber - (script.isInlineScriptWithSourceURL() ? script.lineOffset : 0); var columnNumber = debuggerModelLocation.columnNumber || 0; if (script.isInlineScriptWithSourceURL() && !lineNumber && columnNumber) columnNumber -= script.columnOffset; return uiSourceCode.uiLocation(lineNumber, columnNumber); }, /** * @override * @param {!WebInspector.UISourceCode} uiSourceCode * @param {number} lineNumber * @param {number} columnNumber * @return {?WebInspector.DebuggerModel.Location} */ uiLocationToRawLocation: function(uiSourceCode, lineNumber, columnNumber) { var scripts = this._scriptsForUISourceCode(uiSourceCode); console.assert(scripts.length); var script = scripts[0]; if (script.isInlineScriptWithSourceURL()) return this._debuggerModel.createRawLocation(script, lineNumber + script.lineOffset, lineNumber ? columnNumber : columnNumber + script.columnOffset); return this._debuggerModel.createRawLocation(script, lineNumber, columnNumber); }, /** * @param {!WebInspector.Script} script */ addScript: function(script) { if (script.isAnonymousScript()) return; this._debuggerWorkspaceBinding.pushSourceMapping(script, this); var uiSourceCode = this._workspaceUISourceCodeForScript(script); if (!uiSourceCode) return; this._bindUISourceCodeToScripts(uiSourceCode, [script]); }, /** * @override * @return {boolean} */ isIdentity: function() { return true; }, /** * @override * @param {!WebInspector.UISourceCode} uiSourceCode * @param {number} lineNumber * @return {boolean} */ uiLineHasMapping: function(uiSourceCode, lineNumber) { return true; }, /** * @param {!WebInspector.UISourceCode} uiSourceCode * @return {?WebInspector.ResourceScriptFile} */ scriptFile: function(uiSourceCode) { return this._uiSourceCodeToScriptFile.get(uiSourceCode) || null; }, /** * @param {!WebInspector.UISourceCode} uiSourceCode * @param {?WebInspector.ResourceScriptFile} scriptFile */ _setScriptFile: function(uiSourceCode, scriptFile) { if (scriptFile) this._uiSourceCodeToScriptFile.set(uiSourceCode, scriptFile); else this._uiSourceCodeToScriptFile.remove(uiSourceCode); }, /** * @param {!WebInspector.Event} event */ _uiSourceCodeAdded: function(event) { var uiSourceCode = /** @type {!WebInspector.UISourceCode} */ (event.data); if (!this._networkMapping.networkURL(uiSourceCode)) return; if (uiSourceCode.project().isServiceProject()) return; var scripts = this._scriptsForUISourceCode(uiSourceCode); if (!scripts.length) return; this._bindUISourceCodeToScripts(uiSourceCode, scripts); }, /** * @param {!WebInspector.Event} event */ _uiSourceCodeRemoved: function(event) { var uiSourceCode = /** @type {!WebInspector.UISourceCode} */ (event.data); if (!this._networkMapping.networkURL(uiSourceCode)) return; if (uiSourceCode.project().isServiceProject()) return; this._unbindUISourceCode(uiSourceCode); }, /** * @param {!WebInspector.UISourceCode} uiSourceCode */ _hasMergedToVM: function(uiSourceCode) { var scripts = this._scriptsForUISourceCode(uiSourceCode); if (!scripts.length) return; for (var i = 0; i < scripts.length; ++i) this._debuggerWorkspaceBinding.updateLocations(scripts[i]); }, /** * @param {!WebInspector.UISourceCode} uiSourceCode */ _hasDivergedFromVM: function(uiSourceCode) { var scripts = this._scriptsForUISourceCode(uiSourceCode); if (!scripts.length) return; for (var i = 0; i < scripts.length; ++i) this._debuggerWorkspaceBinding.updateLocations(scripts[i]); }, /** * @param {!WebInspector.Script} script * @return {?WebInspector.UISourceCode} */ _workspaceUISourceCodeForScript: function(script) { if (script.isAnonymousScript()) return null; return this._networkMapping.uiSourceCodeForURL(script.sourceURL); }, /** * @param {!WebInspector.UISourceCode} uiSourceCode * @return {!Array.<!WebInspector.Script>} */ _scriptsForUISourceCode: function(uiSourceCode) { if (!this._networkMapping.networkURL(uiSourceCode)) return []; return this._debuggerModel.scriptsForSourceURL(this._networkMapping.networkURL(uiSourceCode)); }, /** * @param {!WebInspector.UISourceCode} uiSourceCode * @param {!Array.<!WebInspector.Script>} scripts */ _bindUISourceCodeToScripts: function(uiSourceCode, scripts) { console.assert(scripts.length); var scriptFile = new WebInspector.ResourceScriptFile(this, uiSourceCode, scripts); this._setScriptFile(uiSourceCode, scriptFile); for (var i = 0; i < scripts.length; ++i) this._debuggerWorkspaceBinding.updateLocations(scripts[i]); this._debuggerWorkspaceBinding.setSourceMapping(this._target, uiSourceCode, this); this._boundURLs.add(this._networkMapping.networkURL(uiSourceCode)); }, /** * @param {!WebInspector.UISourceCode} uiSourceCode */ _unbindUISourceCode: function(uiSourceCode) { var scriptFile = this.scriptFile(uiSourceCode); if (scriptFile) { scriptFile.dispose(); this._setScriptFile(uiSourceCode, null); } this._debuggerWorkspaceBinding.setSourceMapping(this._target, uiSourceCode, null); }, _debuggerReset: function() { var boundURLs = this._boundURLs.valuesArray(); for (var i = 0; i < boundURLs.length; ++i) { var uiSourceCode = this._networkMapping.uiSourceCodeForURL(boundURLs[i]); if (!uiSourceCode) continue; this._unbindUISourceCode(uiSourceCode); } this._boundURLs.clear(); }, dispose: function() { this._debuggerReset(); this._workspace.removeEventListener(WebInspector.Workspace.Events.UISourceCodeAdded, this._uiSourceCodeAdded, this); this._workspace.removeEventListener(WebInspector.Workspace.Events.UISourceCodeRemoved, this._uiSourceCodeRemoved, this); } } /** * @constructor * @extends {WebInspector.Object} * @param {!WebInspector.ResourceScriptMapping} resourceScriptMapping * @param {!WebInspector.UISourceCode} uiSourceCode * @param {!Array.<!WebInspector.Script>} scripts */ WebInspector.ResourceScriptFile = function(resourceScriptMapping, uiSourceCode, scripts) { console.assert(scripts.length); this._resourceScriptMapping = resourceScriptMapping; this._uiSourceCode = uiSourceCode; if (this._uiSourceCode.contentType() === WebInspector.resourceTypes.Script) this._script = scripts[0]; this._uiSourceCode.addEventListener(WebInspector.UISourceCode.Events.WorkingCopyChanged, this._workingCopyChanged, this); this._update(); } WebInspector.ResourceScriptFile.Events = { DidMergeToVM: "DidMergeToVM", DidDivergeFromVM: "DidDivergeFromVM", } WebInspector.ResourceScriptFile.prototype = { /** * @param {function(?string,!DebuggerAgent.SetScriptSourceError=,!WebInspector.Script=)=} callback */ commitLiveEdit: function(callback) { var target = this._resourceScriptMapping._target; /** * @param {?string} error * @param {!DebuggerAgent.SetScriptSourceError=} errorData * @this {WebInspector.ResourceScriptFile} */ function innerCallback(error, errorData) { if (!error) this._scriptSource = source; this._update(); if (callback) callback(error, errorData, this._script); } if (!this._script) return; var source = this._uiSourceCode.workingCopy(); target.debuggerModel.setScriptSource(this._script.scriptId, source, innerCallback.bind(this)); }, /** * @return {boolean} */ _isDiverged: function() { if (this._uiSourceCode.isDirty()) return true; if (!this._script) return false; if (typeof this._scriptSource === "undefined") return false; if (!this._uiSourceCode.workingCopy().startsWith(this._scriptSource)) return true; var suffix = this._uiSourceCode.workingCopy().substr(this._scriptSource.length); return !!suffix.length && !suffix.match(WebInspector.Script.sourceURLRegex); }, /** * @param {!WebInspector.Event} event */ _workingCopyChanged: function(event) { this._update(); }, _update: function() { if (this._isDiverged() && !this._hasDivergedFromVM) this._divergeFromVM(); else if (!this._isDiverged() && this._hasDivergedFromVM) this._mergeToVM(); }, _divergeFromVM: function() { this._isDivergingFromVM = true; this._resourceScriptMapping._hasDivergedFromVM(this._uiSourceCode); delete this._isDivergingFromVM; this._hasDivergedFromVM = true; this.dispatchEventToListeners(WebInspector.ResourceScriptFile.Events.DidDivergeFromVM, this._uiSourceCode); }, _mergeToVM: function() { delete this._hasDivergedFromVM; this._isMergingToVM = true; this._resourceScriptMapping._hasMergedToVM(this._uiSourceCode); delete this._isMergingToVM; this.dispatchEventToListeners(WebInspector.ResourceScriptFile.Events.DidMergeToVM, this._uiSourceCode); }, /** * @return {boolean} */ hasDivergedFromVM: function() { return this._hasDivergedFromVM; }, /** * @return {boolean} */ isDivergingFromVM: function() { return this._isDivergingFromVM; }, /** * @return {boolean} */ isMergingToVM: function() { return this._isMergingToVM; }, checkMapping: function() { if (!this._script) return; if (typeof this._scriptSource !== "undefined") return; this._script.requestContent(callback.bind(this)); /** * @param {?string} source * @this {WebInspector.ResourceScriptFile} */ function callback(source) { this._scriptSource = source; this._update(); } }, /** * @return {?WebInspector.Target} */ target: function() { if (!this._script) return null; return this._script.target(); }, dispose: function() { this._uiSourceCode.removeEventListener(WebInspector.UISourceCode.Events.WorkingCopyChanged, this._workingCopyChanged, this); }, /** * @param {string} sourceMapURL */ addSourceMapURL: function(sourceMapURL) { if (!this._script) return; this._script.addSourceMapURL(sourceMapURL); }, __proto__: WebInspector.Object.prototype }