Bloglog

/*
* Copyright (C) 2012 Plainware 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
* @extends {WebInspector.Object}
* @param {WebInspector.Workspace} workspace
*/
WebInspector.ScriptSnippetModel = function(workspace) {
this._workspace = workspace;
/** {Object.<string, webinspector.uisourcecode=””>} */
this._uiSourceCodeForScriptId = {};
this._scriptForUISourceCode = new Map();
/** {Object.<string, webinspector.uisourcecode=””>} */
this._uiSourceCodeForSnippetId = {};
this._snippetIdForUISourceCode = new Map();</string,></string,>

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 = {
/**
* @return {WebInspector.SnippetScriptMapping}
*/
get scriptMapping() {
return this._snippetScriptMapping;
},

_loadSnippets: function() {
var snippets = this._snippetStorage.snippets();
for (var i = 0; i < snippets.length; ++i)
this._addScriptSnippet(snippets[i]);
},

/**
 * @return {WebInspector.UISourceCode}
 */
createScriptSnippet: function() {
    var snippet = this._snippetStorage.createSnippet();
    return this._addScriptSnippet(snippet);
},

/**
 * @param {WebInspector.Snippet} snippet
 * @return {WebInspector.UISourceCode}
 */
_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;
},

/**
 * @param {WebInspector.UISourceCode} 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);
},

/**
 * @param {WebInspector.UISourceCode} uiSourceCode
 * @param {string} newName
 */
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);
},

/**
 * @param {WebInspector.UISourceCode} uiSourceCode
 * @param {string} newContent
 */
_setScriptSnippetContent: function(uiSourceCode, newContent) {
    var snippetId = this._snippetIdForUISourceCode.get(uiSourceCode);
    var snippet = this._snippetStorage.snippetForId(snippetId);
    snippet.content = newContent;
},

/**
 * @param {WebInspector.UISourceCode} uiSourceCode
 */
_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);
},

/**
 * @param {string} snippetId
 * @return {number}
 */
_nextEvaluationIndex: function(snippetId) {
    var evaluationIndex = this._lastSnippetEvaluationIndexSetting.get() + 1;
    this._lastSnippetEvaluationIndexSetting.set(evaluationIndex);
    return evaluationIndex;
},

/**
 * @param {WebInspector.UISourceCode} uiSourceCode
 */
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();

    // In order to stop on the breakpoints during the snippet evaluation we need to compile and run it separately.
    // If separate compilation and execution is not supported by the port we fall back to evaluation in console.
    // In case we don't need that since debugger is already paused.
    // We do the same when we are stopped on the call frame  since debugger is already paused and can not stop on breakpoint anymore.
    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));

    /**
     * @param {?string} error
     * @param {string=} scriptId
     * @param {string=} syntaxErrorMessage
     */
    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);
    }
},

/**
 * @param {DebuggerAgent.ScriptId} scriptId
 */
_runScript: function(scriptId) {
    var currentExecutionContext = WebInspector.runtimeModel.currentExecutionContext();
    DebuggerAgent.runScript(scriptId, currentExecutionContext ? currentExecutionContext.id : undefined, "console", false, runCallback.bind(this));

    /**
     * @param {?string} error
     * @param {?RuntimeAgent.RemoteObject} result
     * @param {boolean=} wasThrown
     */
    function runCallback(error, result, wasThrown) {
        if (error) {
            console.error(error);
            return;
        }

        this._printRunScriptResult(result, wasThrown);
    }
},

/**
 * @param {?RuntimeAgent.RemoteObject} result
 * @param {boolean=} 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)
},

/**
 * @param {WebInspector.DebuggerModel.Location} rawLocation
 * @return {WebInspector.UILocation}
 */
_rawLocationToUILocation: function(rawLocation) {
    var uiSourceCode = this._uiSourceCodeForScriptId[rawLocation.scriptId];
    return new WebInspector.UILocation(uiSourceCode, rawLocation.lineNumber, rawLocation.columnNumber || 0);
},

/**
 * @param {WebInspector.UISourceCode} uiSourceCode
 * @param {number} lineNumber
 * @param {number} columnNumber
 * @return {WebInspector.DebuggerModel.Location}
 */
_uiLocationToRawLocation: function(uiSourceCode, lineNumber, columnNumber) {
    var script = this._scriptForUISourceCode.get(uiSourceCode);
    if (!script)
        return null;

    return WebInspector.debuggerModel.createRawLocation(script, lineNumber, columnNumber);
},

/**
 * @param {WebInspector.Script} script
 */
_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);
},

/**
 * @param {WebInspector.UISourceCode} uiSourceCode
 * @return {Array.<object>}*/_removeBreakpoints: function(uiSourceCode) {var breakpointLocations = WebInspector.breakpointManager.breakpointLocationsForUISourceCode(uiSourceCode);for (var i = 0; i &lt; breakpointLocations.length; ++i)            breakpointLocations[i].breakpoint.remove();        return breakpointLocations;    },    /**     * @param {WebInspector.UISourceCode} uiSourceCode     * @param {Array.<object>} breakpointLocations*/_restoreBreakpoints: function(uiSourceCode, breakpointLocations) {for (var i = 0; i &lt; breakpointLocations.length; ++i) {            var uiLocation = breakpointLocations[i].uiLocation;            var breakpoint = breakpointLocations[i].breakpoint;            WebInspector.breakpointManager.setBreakpoint(uiSourceCode, uiLocation.lineNumber, breakpoint.condition(), breakpoint.enabled());        }    },    /**     * @param {WebInspector.UISourceCode} uiSourceCode     * @return {WebInspector.UISourceCode}     */    _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);        }    },    /**     * @param {WebInspector.UISourceCode} uiSourceCode     * @return {string}     */    _evaluationSourceURL: function(uiSourceCode) {        var evaluationSuffix = "_" + uiSourceCode._evaluationIndex;        var snippetId = this._snippetIdForUISourceCode.get(uiSourceCode);        return WebInspector.Script.snippetSourceURLPrefix + snippetId + evaluationSuffix;    },    /**     * @param {string} sourceURL     * @return {string|null}     */    _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() {        /** @type {!Object.<string, webinspector.uisourcecode="">} */this._uiSourceCodeForScriptId = {};this._scriptForUISourceCode = new Map();/** @type {!Object.<string, webinspector.uisourcecode="">} */this._uiSourceCodeForSnippetId = {};this._snippetIdForUISourceCode = new Map();this._workspaceProvider.reset();this._loadSnippets();},__proto__: WebInspector.Object.prototype}/*** @constructor* @implements {WebInspector.ScriptFile}* @extends {WebInspector.Object}* @param {WebInspector.ScriptSnippetModel} scriptSnippetModel* @param {WebInspector.UISourceCode} uiSourceCode*/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 = {/*** @return {boolean}*/hasDivergedFromVM: function() {return this._hasDivergedFromVM;},/*** @param {boolean} hasDivergedFromVM*/setHasDivergedFromVM: function(hasDivergedFromVM) {this._hasDivergedFromVM = hasDivergedFromVM;},/*** @return {boolean}*/isDivergingFromVM: function() {return this._isDivergingFromVM;},checkMapping: function() {},/*** @return {boolean}*/isMergingToVM: function() {return false;},/*** @param {boolean} isDivergingFromVM*/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}/*** @constructor* @implements {WebInspector.ScriptSourceMapping}* @param {WebInspector.ScriptSnippetModel} scriptSnippetModel*/WebInspector.SnippetScriptMapping = function(scriptSnippetModel) {this._scriptSnippetModel = scriptSnippetModel;}WebInspector.SnippetScriptMapping.prototype = {/*** @param {WebInspector.RawLocation} rawLocation* @return {WebInspector.UILocation}*/rawLocationToUILocation: function(rawLocation) {var debuggerModelLocation = /** @type {WebInspector.DebuggerModel.Location} */ (rawLocation);return this._scriptSnippetModel._rawLocationToUILocation(debuggerModelLocation);},/*** @param {WebInspector.UISourceCode} uiSourceCode* @param {number} lineNumber* @param {number} columnNumber* @return {WebInspector.DebuggerModel.Location}*/uiLocationToRawLocation: function(uiSourceCode, lineNumber, columnNumber) {return this._scriptSnippetModel._uiLocationToRawLocation(uiSourceCode, lineNumber, columnNumber);},/*** @return {boolean}*/isIdentity: function() {return true;},/*** @param {string} sourceURL* @return {string|null}*/snippetIdForSourceURL: function(sourceURL) {return this._scriptSnippetModel._snippetIdForSourceURL(sourceURL);},/*** @param {WebInspector.Script} script*/addScript: function(script) {this._scriptSnippetModel._addScript(script);}}/*** @constructor* @extends {WebInspector.StaticContentProvider}* @param {WebInspector.Snippet} snippet*/WebInspector.SnippetContentProvider = function(snippet) {WebInspector.StaticContentProvider.call(this, WebInspector.resourceTypes.Script, snippet.content);}WebInspector.SnippetContentProvider.prototype = {__proto__: WebInspector.StaticContentProvider.prototype}/*** @type {?WebInspector.ScriptSnippetModel}*/WebInspector.scriptSnippetModel = null;/* * Copyright (C) 2012 Plainware All rights reserved.** Redistribution and use in source and binary forms, with or without* modification, are permitted provided that the following conditions are* met:** 1. Redistributions of source code must retain the above copyright* notice, this list of conditions and the following disclaimer.** 2. 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.** THIS SOFTWARE IS PROVIDED BY Plainware AND ITS 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 Plainware* OR ITS 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* @extends {WebInspector.PanelDescriptor}* @implements {WebInspector.ContextMenu.Provider}*/WebInspector.ScriptsPanelDescriptor = function(){WebInspector.PanelDescriptor.call(this, "scripts", WebInspector.UIString("Sources"), "ScriptsPanel", "ScriptsPanel.js");WebInspector.ContextMenu.registerProvider(this);}WebInspector.ScriptsPanelDescriptor.prototype = {/*** @param {WebInspector.ContextMenu} contextMenu* @param {Object} target*/appendApplicableItems: function(event, contextMenu, target){var hasApplicableItems = target instanceof WebInspector.UISourceCode;if (!hasApplicableItems &amp;&amp; target instanceof WebInspector.RemoteObject) {var remoteObject = /** @type {WebInspector.RemoteObject} */ (target);if (remoteObject.type !== "function")return;}this.panel().appendApplicableItems(event, contextMenu, target);},registerShortcuts: function(){var section = WebInspector.shortcutsScreen.section(WebInspector.UIString("Sources Panel"));section.addAlternateKeys(WebInspector.ScriptsPanelDescriptor.ShortcutKeys.PauseContinue, WebInspector.UIString("Pause/Continue"));section.addAlternateKeys(WebInspector.ScriptsPanelDescriptor.ShortcutKeys.StepOver, WebInspector.UIString("Step over"));section.addAlternateKeys(WebInspector.ScriptsPanelDescriptor.ShortcutKeys.StepInto, WebInspector.UIString("Step into"));section.addAlternateKeys(WebInspector.ScriptsPanelDescriptor.ShortcutKeys.StepOut, WebInspector.UIString("Step out"));var nextAndPrevFrameKeys = WebInspector.ScriptsPanelDescriptor.ShortcutKeys.NextCallFrame.concat(WebInspector.ScriptsPanelDescriptor.ShortcutKeys.PrevCallFrame);section.addRelatedKeys(nextAndPrevFrameKeys, WebInspector.UIString("Next/previous call frame"));section.addAlternateKeys(WebInspector.ScriptsPanelDescriptor.ShortcutKeys.EvaluateSelectionInConsole, WebInspector.UIString("Evaluate selection in console"));section.addAlternateKeys(WebInspector.ScriptsPanelDescriptor.ShortcutKeys.GoToMember, WebInspector.UIString("Go to member"));section.addAlternateKeys(WebInspector.ScriptsPanelDescriptor.ShortcutKeys.ToggleBreakpoint, WebInspector.UIString("Toggle breakpoint"));},__proto__: WebInspector.PanelDescriptor.prototype}WebInspector.ScriptsPanelDescriptor.ShortcutKeys = {PauseContinue: [WebInspector.KeyboardShortcut.makeDescriptor(WebInspector.KeyboardShortcut.Keys.F8),WebInspector.KeyboardShortcut.makeDescriptor(WebInspector.KeyboardShortcut.Keys.Slash, WebInspector.KeyboardShortcut.Modifiers.CtrlOrMeta)],StepOver: [WebInspector.KeyboardShortcut.makeDescriptor(WebInspector.KeyboardShortcut.Keys.F10),WebInspector.KeyboardShortcut.makeDescriptor(WebInspector.KeyboardShortcut.Keys.SingleQuote, WebInspector.KeyboardShortcut.Modifiers.CtrlOrMeta)],StepInto: [WebInspector.KeyboardShortcut.makeDescriptor(WebInspector.KeyboardShortcut.Keys.F11),WebInspector.KeyboardShortcut.makeDescriptor(WebInspector.KeyboardShortcut.Keys.Semicolon, WebInspector.KeyboardShortcut.Modifiers.CtrlOrMeta)],StepOut: [WebInspector.KeyboardShortcut.makeDescriptor(WebInspector.KeyboardShortcut.Keys.F11, WebInspector.KeyboardShortcut.Modifiers.Shift),WebInspector.KeyboardShortcut.makeDescriptor(WebInspector.KeyboardShortcut.Keys.Semicolon, WebInspector.KeyboardShortcut.Modifiers.Shift | WebInspector.KeyboardShortcut.Modifiers.CtrlOrMeta)],EvaluateSelectionInConsole: [WebInspector.KeyboardShortcut.makeDescriptor("e", WebInspector.KeyboardShortcut.Modifiers.Shift | WebInspector.KeyboardShortcut.Modifiers.Ctrl)],GoToMember: [WebInspector.KeyboardShortcut.makeDescriptor("o", WebInspector.KeyboardShortcut.Modifiers.CtrlOrMeta | WebInspector.KeyboardShortcut.Modifiers.Shift)],ToggleBreakpoint: [WebInspector.KeyboardShortcut.makeDescriptor("b", WebInspector.KeyboardShortcut.Modifiers.CtrlOrMeta)],NextCallFrame: [WebInspector.KeyboardShortcut.makeDescriptor(WebInspector.KeyboardShortcut.Keys.Period, WebInspector.KeyboardShortcut.Modifiers.Ctrl)],PrevCallFrame: [WebInspector.KeyboardShortcut.makeDescriptor(WebInspector.KeyboardShortcut.Keys.Comma, WebInspector.KeyboardShortcut.Modifiers.Ctrl)]};</string,></string,></object></object>