]> git.saurik.com Git - apple/javascriptcore.git/blob - debugger/DebuggerCallFrame.cpp
83fb67f3afcdde3875ad5c08fd8073f88b8f80d2
[apple/javascriptcore.git] / debugger / DebuggerCallFrame.cpp
1 /*
2 * Copyright (C) 2008, 2013, 2014 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 *
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of Apple Inc. ("Apple") nor the names of
14 * its contributors may be used to endorse or promote products derived
15 * from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
18 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
21 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 #include "config.h"
30 #include "DebuggerCallFrame.h"
31
32 #include "CodeBlock.h"
33 #include "Interpreter.h"
34 #include "JSActivation.h"
35 #include "JSFunction.h"
36 #include "JSCInlines.h"
37 #include "Parser.h"
38 #include "StackVisitor.h"
39
40 namespace JSC {
41
42 class LineAndColumnFunctor {
43 public:
44 StackVisitor::Status operator()(StackVisitor& visitor)
45 {
46 visitor->computeLineAndColumn(m_line, m_column);
47 return StackVisitor::Done;
48 }
49
50 unsigned line() const { return m_line; }
51 unsigned column() const { return m_column; }
52
53 private:
54 unsigned m_line;
55 unsigned m_column;
56 };
57
58 DebuggerCallFrame::DebuggerCallFrame(CallFrame* callFrame)
59 : m_callFrame(callFrame)
60 {
61 m_position = positionForCallFrame(m_callFrame);
62 }
63
64 PassRefPtr<DebuggerCallFrame> DebuggerCallFrame::callerFrame()
65 {
66 ASSERT(isValid());
67 if (!isValid())
68 return 0;
69
70 if (m_caller)
71 return m_caller;
72
73 CallFrame* callerFrame = m_callFrame->callerFrameSkippingVMEntrySentinel();
74 if (!callerFrame)
75 return 0;
76
77 m_caller = DebuggerCallFrame::create(callerFrame);
78 return m_caller;
79 }
80
81 JSC::JSGlobalObject* DebuggerCallFrame::vmEntryGlobalObject() const
82 {
83 ASSERT(isValid());
84 if (!isValid())
85 return 0;
86 return m_callFrame->vmEntryGlobalObject();
87 }
88
89 SourceID DebuggerCallFrame::sourceID() const
90 {
91 ASSERT(isValid());
92 if (!isValid())
93 return noSourceID;
94 return sourceIDForCallFrame(m_callFrame);
95 }
96
97 String DebuggerCallFrame::functionName() const
98 {
99 ASSERT(isValid());
100 if (!isValid())
101 return String();
102 JSObject* function = m_callFrame->callee();
103 if (!function)
104 return String();
105
106 return getCalculatedDisplayName(m_callFrame, function);
107 }
108
109 JSScope* DebuggerCallFrame::scope() const
110 {
111 ASSERT(isValid());
112 if (!isValid())
113 return 0;
114
115 CodeBlock* codeBlock = m_callFrame->codeBlock();
116 if (codeBlock && codeBlock->needsActivation() && !m_callFrame->hasActivation()) {
117 JSActivation* activation = JSActivation::create(*codeBlock->vm(), m_callFrame, codeBlock);
118 m_callFrame->setActivation(activation);
119 m_callFrame->setScope(activation);
120 }
121
122 return m_callFrame->scope();
123 }
124
125 DebuggerCallFrame::Type DebuggerCallFrame::type() const
126 {
127 ASSERT(isValid());
128 if (!isValid())
129 return ProgramType;
130
131 if (m_callFrame->callee())
132 return FunctionType;
133
134 return ProgramType;
135 }
136
137 JSValue DebuggerCallFrame::thisValue() const
138 {
139 ASSERT(isValid());
140 return thisValueForCallFrame(m_callFrame);
141 }
142
143 // Evaluate some JavaScript code in the scope of this frame.
144 JSValue DebuggerCallFrame::evaluate(const String& script, JSValue& exception)
145 {
146 ASSERT(isValid());
147 CallFrame* callFrame = m_callFrame;
148 if (!callFrame)
149 return jsNull();
150
151 JSLockHolder lock(callFrame);
152
153 if (!callFrame->codeBlock())
154 return JSValue();
155
156 VM& vm = callFrame->vm();
157 EvalExecutable* eval = EvalExecutable::create(callFrame, makeSource(script), callFrame->codeBlock()->isStrictMode());
158 if (vm.exception()) {
159 exception = vm.exception();
160 vm.clearException();
161 return jsUndefined();
162 }
163
164 JSValue thisValue = thisValueForCallFrame(callFrame);
165 JSValue result = vm.interpreter->execute(eval, callFrame, thisValue, scope());
166 if (vm.exception()) {
167 exception = vm.exception();
168 vm.clearException();
169 }
170 ASSERT(result);
171 return result;
172 }
173
174 void DebuggerCallFrame::invalidate()
175 {
176 m_callFrame = nullptr;
177 RefPtr<DebuggerCallFrame> frame = m_caller.release();
178 while (frame) {
179 frame->m_callFrame = nullptr;
180 frame = frame->m_caller.release();
181 }
182 }
183
184 TextPosition DebuggerCallFrame::positionForCallFrame(CallFrame* callFrame)
185 {
186 if (!callFrame)
187 return TextPosition();
188
189 LineAndColumnFunctor functor;
190 callFrame->iterate(functor);
191 return TextPosition(OrdinalNumber::fromOneBasedInt(functor.line()), OrdinalNumber::fromOneBasedInt(functor.column()));
192 }
193
194 SourceID DebuggerCallFrame::sourceIDForCallFrame(CallFrame* callFrame)
195 {
196 ASSERT(callFrame);
197 CodeBlock* codeBlock = callFrame->codeBlock();
198 if (!codeBlock)
199 return noSourceID;
200 return codeBlock->ownerExecutable()->sourceID();
201 }
202
203 JSValue DebuggerCallFrame::thisValueForCallFrame(CallFrame* callFrame)
204 {
205 if (!callFrame)
206 return jsNull();
207
208 ECMAMode ecmaMode = NotStrictMode;
209 CodeBlock* codeBlock = callFrame->codeBlock();
210 if (codeBlock && codeBlock->isStrictMode())
211 ecmaMode = StrictMode;
212 JSValue thisValue = callFrame->thisValue().toThis(callFrame, ecmaMode);
213 return thisValue;
214 }
215
216 } // namespace JSC