• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright (C) 2010 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(function () {
32
33var DebuggerScript = {};
34
35DebuggerScript.PauseOnExceptionsState = {
36    DontPauseOnExceptions : 0,
37    PauseOnAllExceptions : 1,
38    PauseOnUncaughtExceptions: 2
39};
40
41DebuggerScript._pauseOnExceptionsState = DebuggerScript.PauseOnExceptionsState.DontPauseOnExceptions;
42Debug.clearBreakOnException();
43Debug.clearBreakOnUncaughtException();
44
45DebuggerScript.getAfterCompileScript = function(eventData)
46{
47    return DebuggerScript._formatScript(eventData.script_.script_);
48}
49
50DebuggerScript.getWorkerScripts = function()
51{
52    var result = [];
53    var scripts = Debug.scripts();
54    for (var i = 0; i < scripts.length; ++i) {
55        var script = scripts[i];
56        // Workers don't share same V8 heap now so there is no need to complicate stuff with
57        // the context id like we do to discriminate between scripts from different pages.
58        // However we need to filter out v8 native scripts.
59        if (script.context_data && script.context_data === "worker")
60            result.push(DebuggerScript._formatScript(script));
61    }
62    return result;
63}
64
65DebuggerScript.getScripts = function(contextData)
66{
67    var result = [];
68
69    if (!contextData)
70        return result;
71    var comma = contextData.indexOf(",");
72    if (comma === -1)
73        return result;
74    // Context data is a string in the following format:
75    // ("page"|"injected")","<page id>
76    var idSuffix = contextData.substring(comma); // including the comma
77
78    var scripts = Debug.scripts();
79    for (var i = 0; i < scripts.length; ++i) {
80        var script = scripts[i];
81        if (script.context_data && script.context_data.lastIndexOf(idSuffix) != -1)
82            result.push(DebuggerScript._formatScript(script));
83    }
84    return result;
85}
86
87DebuggerScript._formatScript = function(script)
88{
89    return {
90        id: script.id,
91        name: script.nameOrSourceURL(),
92        source: script.source,
93        lineOffset: script.line_offset,
94        columnOffset: script.column_offset,
95        isContentScript: !!script.context_data && script.context_data.indexOf("injected") == 0
96    };
97}
98
99DebuggerScript.setBreakpoint = function(execState, args)
100{
101    var breakId = Debug.setScriptBreakPointById(args.sourceID, args.lineNumber, args.columnNumber, args.condition);
102
103    var locations = Debug.findBreakPointActualLocations(breakId);
104    if (!locations.length)
105        return undefined;
106    args.lineNumber = locations[0].line;
107    args.columnNumber = locations[0].column;
108    return breakId.toString();
109}
110
111DebuggerScript.removeBreakpoint = function(execState, args)
112{
113    Debug.findBreakPoint(args.breakpointId, true);
114}
115
116DebuggerScript.pauseOnExceptionsState = function()
117{
118    return DebuggerScript._pauseOnExceptionsState;
119}
120
121DebuggerScript.setPauseOnExceptionsState = function(newState)
122{
123    DebuggerScript._pauseOnExceptionsState = newState;
124
125    if (DebuggerScript.PauseOnExceptionsState.PauseOnAllExceptions === newState)
126        Debug.setBreakOnException();
127    else
128        Debug.clearBreakOnException();
129
130    if (DebuggerScript.PauseOnExceptionsState.PauseOnUncaughtExceptions === newState)
131        Debug.setBreakOnUncaughtException();
132    else
133        Debug.clearBreakOnUncaughtException();
134}
135
136DebuggerScript.currentCallFrame = function(execState, args)
137{
138    var frameCount = execState.frameCount();
139    if (frameCount === 0)
140        return undefined;
141
142    var topFrame;
143    for (var i = frameCount - 1; i >= 0; i--) {
144        var frameMirror = execState.frame(i);
145        topFrame = DebuggerScript._frameMirrorToJSCallFrame(frameMirror, topFrame);
146    }
147    return topFrame;
148}
149
150DebuggerScript.stepIntoStatement = function(execState)
151{
152    execState.prepareStep(Debug.StepAction.StepIn, 1);
153}
154
155DebuggerScript.stepOverStatement = function(execState)
156{
157    execState.prepareStep(Debug.StepAction.StepNext, 1);
158}
159
160DebuggerScript.stepOutOfFunction = function(execState)
161{
162    execState.prepareStep(Debug.StepAction.StepOut, 1);
163}
164
165DebuggerScript.editScriptSource = function(scriptId, newSource)
166{
167    var scripts = Debug.scripts();
168    var scriptToEdit = null;
169    for (var i = 0; i < scripts.length; i++) {
170        if (scripts[i].id == scriptId) {
171            scriptToEdit = scripts[i];
172            break;
173        }
174    }
175    if (!scriptToEdit)
176        throw("Script not found");
177
178    var changeLog = [];
179    Debug.LiveEdit.SetScriptSource(scriptToEdit, newSource, false, changeLog);
180    return scriptToEdit.source;
181}
182
183DebuggerScript.clearBreakpoints = function(execState, args)
184{
185    Debug.clearAllBreakPoints();
186}
187
188DebuggerScript.setBreakpointsActivated = function(execState, args)
189{
190    Debug.debuggerFlags().breakPointsActive.setValue(args.enabled);
191}
192
193DebuggerScript._frameMirrorToJSCallFrame = function(frameMirror, callerFrame)
194{
195    // Get function name.
196    var func;
197    try {
198        func = frameMirror.func();
199    } catch(e) {
200    }
201    var functionName;
202    if (func)
203        functionName = func.name() || func.inferredName();
204
205    // Get script ID.
206    var script = func.script();
207    var sourceID = script && script.id();
208
209    // Get location.
210    var location  = frameMirror.sourceLocation();
211
212    // Get this object.
213    var thisObject = frameMirror.details_.receiver();
214
215    // Get scope chain array in format: [<scope type>, <scope object>, <scope type>, <scope object>,...]
216    var scopeChain = [];
217    var scopeType = [];
218    for (var i = 0; i < frameMirror.scopeCount(); i++) {
219        var scopeMirror = frameMirror.scope(i);
220        var scopeObjectMirror = scopeMirror.scopeObject();
221
222        var scopeObject;
223        switch (scopeMirror.scopeType()) {
224        case ScopeType.Local:
225        case ScopeType.Closure:
226            // For transient objects we create a "persistent" copy that contains
227            // the same properties.
228            scopeObject = {};
229            // Reset scope object prototype to null so that the proto properties
230            // don't appear in the local scope section.
231            scopeObject.__proto__ = null;
232            var properties = scopeObjectMirror.properties();
233            for (var j = 0; j < properties.length; j++) {
234                var name = properties[j].name();
235                if (name.charAt(0) === ".")
236                    continue; // Skip internal variables like ".arguments"
237                scopeObject[name] = properties[j].value_;
238            }
239            break;
240        case ScopeType.Global:
241        case ScopeType.With:
242        case ScopeType.Catch:
243            scopeObject = scopeMirror.details_.object();
244            break;
245        }
246
247        scopeType.push(scopeMirror.scopeType());
248        scopeChain.push(scopeObject);
249    }
250
251    function evaluate(expression) {
252        return frameMirror.evaluate(expression, false).value();
253    }
254
255    return {
256        "sourceID": sourceID,
257        "line": location.line,
258        "column": location.column,
259        "functionName": functionName,
260        "thisObject": thisObject,
261        "scopeChain": scopeChain,
262        "scopeType": scopeType,
263        "evaluate": evaluate,
264        "caller": callerFrame
265    };
266}
267
268return DebuggerScript;
269})();
270