1ad903a640e787b46b7ad855cc627c8960629ed3
[WebKit-https.git] / Source / WebInspectorUI / UserInterface / Models / CallFrame.js
1 /*
2  * Copyright (C) 2013 Apple 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
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 WebInspector.CallFrame = class CallFrame extends WebInspector.Object
27 {
28     constructor(id, sourceCodeLocation, functionName, thisObject, scopeChain, nativeCode, programCode)
29     {
30         super();
31
32         console.assert(!sourceCodeLocation || sourceCodeLocation instanceof WebInspector.SourceCodeLocation);
33         console.assert(!thisObject || thisObject instanceof WebInspector.RemoteObject);
34         console.assert(!scopeChain || scopeChain instanceof Array);
35
36         this._id = id || null;
37         this._sourceCodeLocation = sourceCodeLocation || null;
38         this._functionName = functionName || null;
39         this._thisObject = thisObject || null;
40         this._scopeChain = scopeChain || [];
41         this._nativeCode = nativeCode || false;
42         this._programCode = programCode || false;
43     }
44
45     // Public
46
47     get id()
48     {
49         return this._id;
50     }
51
52     get sourceCodeLocation()
53     {
54         return this._sourceCodeLocation;
55     }
56
57     get functionName()
58     {
59         return this._functionName;
60     }
61
62     get nativeCode()
63     {
64         return this._nativeCode;
65     }
66
67     get programCode()
68     {
69         return this._programCode;
70     }
71
72     get thisObject()
73     {
74         return this._thisObject;
75     }
76
77     get scopeChain()
78     {
79         return this._scopeChain;
80     }
81
82     saveIdentityToCookie()
83     {
84         // Do nothing. The call frame is torn down when the inspector closes, and
85         // we shouldn't restore call frame content views across debugger pauses.
86     }
87
88     collectScopeChainVariableNames(callback)
89     {
90         var result = {this: true, __proto__: null};
91
92         var pendingRequests = this._scopeChain.length;
93
94         function propertiesCollected(properties)
95         {
96             for (var i = 0; properties && i < properties.length; ++i)
97                 result[properties[i].name] = true;
98
99             if (--pendingRequests)
100                 return;
101
102             callback(result);
103         }
104
105         for (var i = 0; i < this._scopeChain.length; ++i)
106             this._scopeChain[i].objects[0].deprecatedGetAllProperties(propertiesCollected);
107     }
108
109     // Static
110
111     static functionNameFromPayload(payload)
112     {
113         let functionName = payload.functionName;
114         if (functionName === "global code")
115             return WebInspector.UIString("Global Code");
116         if (functionName === "eval code")
117             return WebInspector.UIString("Eval Code");
118         if (functionName === "module code")
119             return WebInspector.UIString("Module Code");
120         return functionName;
121     }
122
123     static programCodeFromPayload(payload)
124     {
125         return payload.functionName.endsWith(" code");
126     }
127
128     static fromDebuggerPayload(payload, scopeChain, sourceCodeLocation)
129     {
130         let id = payload.callFrameId;
131         let thisObject = WebInspector.RemoteObject.fromPayload(payload.this);
132         let functionName = WebInspector.CallFrame.functionNameFromPayload(payload);
133         let nativeCode = false;
134         let programCode = WebInspector.CallFrame.programCodeFromPayload(payload);
135
136         return new WebInspector.CallFrame(id, sourceCodeLocation, functionName, thisObject, scopeChain, nativeCode, programCode);
137     }
138
139     static fromPayload(payload)
140     {
141         console.assert(payload);
142
143         let {url, scriptId} = payload;
144         let nativeCode = false;
145         let sourceCodeLocation = null;
146         let functionName = WebInspector.CallFrame.functionNameFromPayload(payload);
147         let programCode = WebInspector.CallFrame.programCodeFromPayload(payload);
148
149         if (url === "[native code]") {
150             nativeCode = true;
151             url = null;
152         } else if (url || scriptId) {
153             let sourceCode = WebInspector.frameResourceManager.resourceForURL(url);
154             if (!sourceCode)
155                 sourceCode = WebInspector.debuggerManager.scriptsForURL(url)[0];
156             if (!sourceCode && scriptId)
157                 sourceCode = WebInspector.debuggerManager.scriptForIdentifier(scriptId);
158
159             if (sourceCode) {
160                 // The lineNumber is 1-based, but we expect 0-based.
161                 let lineNumber = payload.lineNumber - 1;
162                 sourceCodeLocation = sourceCode.createLazySourceCodeLocation(lineNumber, payload.columnNumber);
163             } else {
164                 // Treat this as native code if we were unable to find a source.
165                 console.assert(!url, "We should have detected source code for something with a url");
166                 nativeCode = true;
167                 url = null;
168             }
169         }
170
171         return new WebInspector.CallFrame(null, sourceCodeLocation, functionName, null, null, nativeCode, programCode);
172     }
173 };