/* * Copyright (C) 2010 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. */ (function () { var DebuggerScript = {}; DebuggerScript.PauseOnExceptionsState = { DontPauseOnExceptions : 0, PauseOnAllExceptions : 1, PauseOnUncaughtExceptions: 2 }; DebuggerScript._pauseOnExceptionsState = DebuggerScript.PauseOnExceptionsState.DontPauseOnExceptions; Debug.clearBreakOnException(); Debug.clearBreakOnUncaughtException(); DebuggerScript.getAfterCompileScript = function(eventData) { return DebuggerScript._formatScript(eventData.script_.script_); } DebuggerScript.getWorkerScripts = function() { var result = []; var scripts = Debug.scripts(); for (var i = 0; i < scripts.length; ++i) { var script = scripts[i]; // Workers don't share same V8 heap now so there is no need to complicate stuff with // the context id like we do to discriminate between scripts from different pages. // However we need to filter out v8 native scripts. if (script.context_data && script.context_data === "worker") result.push(DebuggerScript._formatScript(script)); } return result; } DebuggerScript.getScripts = function(contextData) { var result = []; if (!contextData) return result; var comma = contextData.indexOf(","); if (comma === -1) return result; // Context data is a string in the following format: // ("page"|"injected")","<page id> var idSuffix = contextData.substring(comma); // including the comma var scripts = Debug.scripts(); for (var i = 0; i < scripts.length; ++i) { var script = scripts[i]; if (script.context_data && script.context_data.lastIndexOf(idSuffix) != -1) result.push(DebuggerScript._formatScript(script)); } return result; } DebuggerScript._formatScript = function(script) { return { id: script.id, name: script.nameOrSourceURL(), source: script.source, lineOffset: script.line_offset, columnOffset: script.column_offset, isContentScript: !!script.context_data && script.context_data.indexOf("injected") == 0 }; } DebuggerScript.setBreakpoint = function(execState, args) { var breakId = Debug.setScriptBreakPointById(args.sourceID, args.lineNumber, args.columnNumber, args.condition); var locations = Debug.findBreakPointActualLocations(breakId); if (!locations.length) return undefined; args.lineNumber = locations[0].line; args.columnNumber = locations[0].column; return breakId.toString(); } DebuggerScript.removeBreakpoint = function(execState, args) { Debug.findBreakPoint(args.breakpointId, true); } DebuggerScript.pauseOnExceptionsState = function() { return DebuggerScript._pauseOnExceptionsState; } DebuggerScript.setPauseOnExceptionsState = function(newState) { DebuggerScript._pauseOnExceptionsState = newState; if (DebuggerScript.PauseOnExceptionsState.PauseOnAllExceptions === newState) Debug.setBreakOnException(); else Debug.clearBreakOnException(); if (DebuggerScript.PauseOnExceptionsState.PauseOnUncaughtExceptions === newState) Debug.setBreakOnUncaughtException(); else Debug.clearBreakOnUncaughtException(); } DebuggerScript.currentCallFrame = function(execState, args) { var frameCount = execState.frameCount(); if (frameCount === 0) return undefined; var topFrame; for (var i = frameCount - 1; i >= 0; i--) { var frameMirror = execState.frame(i); topFrame = DebuggerScript._frameMirrorToJSCallFrame(frameMirror, topFrame); } return topFrame; } DebuggerScript.stepIntoStatement = function(execState) { execState.prepareStep(Debug.StepAction.StepIn, 1); } DebuggerScript.stepOverStatement = function(execState) { execState.prepareStep(Debug.StepAction.StepNext, 1); } DebuggerScript.stepOutOfFunction = function(execState) { execState.prepareStep(Debug.StepAction.StepOut, 1); } DebuggerScript.editScriptSource = function(scriptId, newSource) { var scripts = Debug.scripts(); var scriptToEdit = null; for (var i = 0; i < scripts.length; i++) { if (scripts[i].id == scriptId) { scriptToEdit = scripts[i]; break; } } if (!scriptToEdit) throw("Script not found"); var changeLog = []; Debug.LiveEdit.SetScriptSource(scriptToEdit, newSource, false, changeLog); return scriptToEdit.source; } DebuggerScript.clearBreakpoints = function(execState, args) { Debug.clearAllBreakPoints(); } DebuggerScript.setBreakpointsActivated = function(execState, args) { Debug.debuggerFlags().breakPointsActive.setValue(args.enabled); } DebuggerScript._frameMirrorToJSCallFrame = function(frameMirror, callerFrame) { // Get function name. var func; try { func = frameMirror.func(); } catch(e) { } var functionName; if (func) functionName = func.name() || func.inferredName(); // Get script ID. var script = func.script(); var sourceID = script && script.id(); // Get location. var location = frameMirror.sourceLocation(); // Get this object. var thisObject = frameMirror.details_.receiver(); // Get scope chain array in format: [<scope type>, <scope object>, <scope type>, <scope object>,...] var scopeChain = []; var scopeType = []; for (var i = 0; i < frameMirror.scopeCount(); i++) { var scopeMirror = frameMirror.scope(i); var scopeObjectMirror = scopeMirror.scopeObject(); var scopeObject; switch (scopeMirror.scopeType()) { case ScopeType.Local: case ScopeType.Closure: // For transient objects we create a "persistent" copy that contains // the same properties. scopeObject = {}; // Reset scope object prototype to null so that the proto properties // don't appear in the local scope section. scopeObject.__proto__ = null; var properties = scopeObjectMirror.properties(); for (var j = 0; j < properties.length; j++) { var name = properties[j].name(); if (name.charAt(0) === ".") continue; // Skip internal variables like ".arguments" scopeObject[name] = properties[j].value_; } break; case ScopeType.Global: case ScopeType.With: case ScopeType.Catch: scopeObject = scopeMirror.details_.object(); break; } scopeType.push(scopeMirror.scopeType()); scopeChain.push(scopeObject); } function evaluate(expression) { return frameMirror.evaluate(expression, false).value(); } return { "sourceID": sourceID, "line": location.line, "column": location.column, "functionName": functionName, "thisObject": thisObject, "scopeChain": scopeChain, "scopeType": scopeType, "evaluate": evaluate, "caller": callerFrame }; } return DebuggerScript; })();