initial import
[vuplus_webkit] / Source / WebCore / bindings / v8 / DebuggerScript.js
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
33 var DebuggerScript = {};
34
35 DebuggerScript.PauseOnExceptionsState = {
36     DontPauseOnExceptions : 0,
37     PauseOnAllExceptions : 1,
38     PauseOnUncaughtExceptions: 2
39 };
40
41 DebuggerScript._pauseOnExceptionsState = DebuggerScript.PauseOnExceptionsState.DontPauseOnExceptions;
42 Debug.clearBreakOnException();
43 Debug.clearBreakOnUncaughtException();
44
45 DebuggerScript.getAfterCompileScript = function(eventData)
46 {
47     return DebuggerScript._formatScript(eventData.script_.script_);
48 }
49
50 DebuggerScript.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
65 DebuggerScript.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
87 DebuggerScript._formatScript = function(script)
88 {
89     var lineEnds = script.line_ends;
90     var lineCount = lineEnds.length;
91     var endLine = script.line_offset + lineCount - 1;
92     var endColumn;
93     if (lineCount === 1)
94         endColumn = script.source.length + script.column_offset;
95     else
96         endColumn = script.source.length - (script.line_ends[lineCount - 2] + 1);
97
98     return {
99         id: script.id,
100         name: script.nameOrSourceURL(),
101         source: script.source,
102         startLine: script.line_offset,
103         startColumn: script.column_offset,
104         endLine: endLine,
105         endColumn: endColumn,
106         isContentScript: !!script.context_data && script.context_data.indexOf("injected") == 0
107     };
108 }
109
110 DebuggerScript.setBreakpoint = function(execState, args)
111 {
112     var breakId = Debug.setScriptBreakPointById(args.sourceID, args.lineNumber, args.columnNumber, args.condition);
113
114     var locations = Debug.findBreakPointActualLocations(breakId);
115     if (!locations.length)
116         return undefined;
117     args.lineNumber = locations[0].line;
118     args.columnNumber = locations[0].column;
119     return breakId.toString();
120 }
121
122 DebuggerScript.removeBreakpoint = function(execState, args)
123 {
124     Debug.findBreakPoint(args.breakpointId, true);
125 }
126
127 DebuggerScript.pauseOnExceptionsState = function()
128 {
129     return DebuggerScript._pauseOnExceptionsState;
130 }
131
132 DebuggerScript.setPauseOnExceptionsState = function(newState)
133 {
134     DebuggerScript._pauseOnExceptionsState = newState;
135
136     if (DebuggerScript.PauseOnExceptionsState.PauseOnAllExceptions === newState)
137         Debug.setBreakOnException();
138     else
139         Debug.clearBreakOnException();
140
141     if (DebuggerScript.PauseOnExceptionsState.PauseOnUncaughtExceptions === newState)
142         Debug.setBreakOnUncaughtException();
143     else
144         Debug.clearBreakOnUncaughtException();
145 }
146
147 DebuggerScript.currentCallFrame = function(execState, args)
148 {
149     var frameCount = execState.frameCount();
150     if (frameCount === 0)
151         return undefined;
152
153     var topFrame;
154     for (var i = frameCount - 1; i >= 0; i--) {
155         var frameMirror = execState.frame(i);
156         topFrame = DebuggerScript._frameMirrorToJSCallFrame(frameMirror, topFrame);
157     }
158     return topFrame;
159 }
160
161 DebuggerScript.stepIntoStatement = function(execState)
162 {
163     execState.prepareStep(Debug.StepAction.StepIn, 1);
164 }
165
166 DebuggerScript.stepOverStatement = function(execState)
167 {
168     execState.prepareStep(Debug.StepAction.StepNext, 1);
169 }
170
171 DebuggerScript.stepOutOfFunction = function(execState)
172 {
173     execState.prepareStep(Debug.StepAction.StepOut, 1);
174 }
175
176 DebuggerScript.setScriptSource = function(scriptId, newSource, preview)
177 {
178     var scripts = Debug.scripts();
179     var scriptToEdit = null;
180     for (var i = 0; i < scripts.length; i++) {
181         if (scripts[i].id == scriptId) {
182             scriptToEdit = scripts[i];
183             break;
184         }
185     }
186     if (!scriptToEdit)
187         throw("Script not found");
188
189     var changeLog = [];
190     return Debug.LiveEdit.SetScriptSource(scriptToEdit, newSource, preview, changeLog);
191 }
192
193 DebuggerScript.clearBreakpoints = function(execState, args)
194 {
195     Debug.clearAllBreakPoints();
196 }
197
198 DebuggerScript.setBreakpointsActivated = function(execState, args)
199 {
200     Debug.debuggerFlags().breakPointsActive.setValue(args.enabled);
201 }
202
203 DebuggerScript._frameMirrorToJSCallFrame = function(frameMirror, callerFrame)
204 {
205     // Get function name.
206     var func;
207     try {
208         func = frameMirror.func();
209     } catch(e) {
210     }
211     var functionName;
212     if (func)
213         functionName = func.name() || func.inferredName();
214
215     // Get script ID.
216     var script = func.script();
217     var sourceID = script && script.id();
218
219     // Get location.
220     var location  = frameMirror.sourceLocation();
221
222     // Get this object.
223     var thisObject = frameMirror.details_.receiver();
224
225     // Get scope chain array in format: [<scope type>, <scope object>, <scope type>, <scope object>,...]
226     var scopeChain = [];
227     var scopeType = [];
228     for (var i = 0; i < frameMirror.scopeCount(); i++) {
229         var scopeMirror = frameMirror.scope(i);
230         var scopeObjectMirror = scopeMirror.scopeObject();
231
232         var scopeObject;
233         switch (scopeMirror.scopeType()) {
234         case ScopeType.Local:
235         case ScopeType.Closure:
236             // For transient objects we create a "persistent" copy that contains
237             // the same properties.
238             scopeObject = {};
239             // Reset scope object prototype to null so that the proto properties
240             // don't appear in the local scope section.
241             scopeObject.__proto__ = null;
242             var properties = scopeObjectMirror.properties();
243             for (var j = 0; j < properties.length; j++) {
244                 var name = properties[j].name();
245                 if (name.charAt(0) === ".")
246                     continue; // Skip internal variables like ".arguments"
247                 scopeObject[name] = properties[j].value_;
248             }
249             break;
250         case ScopeType.Global:
251         case ScopeType.With:
252         case ScopeType.Catch:
253             scopeObject = scopeMirror.details_.object();
254             break;
255         }
256
257         scopeType.push(scopeMirror.scopeType());
258         scopeChain.push(scopeObject);
259     }
260
261     function evaluate(expression) {
262         return frameMirror.evaluate(expression, false).value();
263     }
264
265     return {
266         "sourceID": sourceID,
267         "line": location ? location.line : 0,
268         "column": location ? location.column : 0,
269         "functionName": functionName,
270         "thisObject": thisObject,
271         "scopeChain": scopeChain,
272         "scopeType": scopeType,
273         "evaluate": evaluate,
274         "caller": callerFrame
275     };
276 }
277
278 return DebuggerScript;
279 })();