finally blocks should not set the exception stack trace when re-throwing the exception.
[WebKit-https.git] / Source / JavaScriptCore / 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 "DebuggerEvalEnabler.h"
34 #include "DebuggerScope.h"
35 #include "Exception.h"
36 #include "Interpreter.h"
37 #include "JSFunction.h"
38 #include "JSLexicalEnvironment.h"
39 #include "JSCInlines.h"
40 #include "Parser.h"
41 #include "StackVisitor.h"
42 #include "StrongInlines.h"
43
44 namespace JSC {
45
46 class LineAndColumnFunctor {
47 public:
48     StackVisitor::Status operator()(StackVisitor& visitor)
49     {
50         visitor->computeLineAndColumn(m_line, m_column);
51         return StackVisitor::Done;
52     }
53
54     unsigned line() const { return m_line; }
55     unsigned column() const { return m_column; }
56
57 private:
58     unsigned m_line;
59     unsigned m_column;
60 };
61
62 class FindCallerMidStackFunctor {
63 public:
64     FindCallerMidStackFunctor(CallFrame* callFrame)
65         : m_callFrame(callFrame)
66         , m_callerFrame(nullptr)
67     { }
68
69     StackVisitor::Status operator()(StackVisitor& visitor)
70     {
71         if (visitor->callFrame() == m_callFrame) {
72             m_callerFrame = visitor->callerFrame();
73             return StackVisitor::Done;
74         }
75         return StackVisitor::Continue;
76     }
77
78     CallFrame* getCallerFrame() const { return m_callerFrame; }
79
80 private:
81     CallFrame* m_callFrame;
82     CallFrame* m_callerFrame;
83 };
84
85 DebuggerCallFrame::DebuggerCallFrame(CallFrame* callFrame)
86     : m_callFrame(callFrame)
87 {
88     m_position = positionForCallFrame(m_callFrame);
89 }
90
91 PassRefPtr<DebuggerCallFrame> DebuggerCallFrame::callerFrame()
92 {
93     ASSERT(isValid());
94     if (!isValid())
95         return 0;
96
97     if (m_caller)
98         return m_caller;
99
100     FindCallerMidStackFunctor functor(m_callFrame);
101     m_callFrame->vm().topCallFrame->iterate(functor);
102
103     CallFrame* callerFrame = functor.getCallerFrame();
104     if (!callerFrame)
105         return 0;
106
107     m_caller = DebuggerCallFrame::create(callerFrame);
108     return m_caller;
109 }
110
111 JSC::JSGlobalObject* DebuggerCallFrame::vmEntryGlobalObject() const
112 {
113     ASSERT(isValid());
114     if (!isValid())
115         return 0;
116     return m_callFrame->vmEntryGlobalObject();
117 }
118
119 SourceID DebuggerCallFrame::sourceID() const
120 {
121     ASSERT(isValid());
122     if (!isValid())
123         return noSourceID;
124     return sourceIDForCallFrame(m_callFrame);
125 }
126
127 String DebuggerCallFrame::functionName() const
128 {
129     ASSERT(isValid());
130     if (!isValid())
131         return String();
132     JSFunction* function = jsDynamicCast<JSFunction*>(m_callFrame->callee());
133     if (!function)
134         return String();
135
136     return getCalculatedDisplayName(m_callFrame, function);
137 }
138
139 DebuggerScope* DebuggerCallFrame::scope()
140 {
141     ASSERT(isValid());
142     if (!isValid())
143         return 0;
144
145     if (!m_scope) {
146         VM& vm = m_callFrame->vm();
147         JSScope* scope;
148         CodeBlock* codeBlock = m_callFrame->codeBlock();
149         if (codeBlock && codeBlock->scopeRegister().isValid())
150             scope = m_callFrame->scope(codeBlock->scopeRegister().offset());
151         else if (JSCallee* callee = jsDynamicCast<JSCallee*>(m_callFrame->callee()))
152             scope = callee->scope();
153         else
154             scope = m_callFrame->lexicalGlobalObject();
155
156         m_scope.set(vm, DebuggerScope::create(vm, scope));
157     }
158     return m_scope.get();
159 }
160
161 DebuggerCallFrame::Type DebuggerCallFrame::type() const
162 {
163     ASSERT(isValid());
164     if (!isValid())
165         return ProgramType;
166
167     if (jsDynamicCast<JSFunction*>(m_callFrame->callee()))
168         return FunctionType;
169
170     return ProgramType;
171 }
172
173 JSValue DebuggerCallFrame::thisValue() const
174 {
175     ASSERT(isValid());
176     return thisValueForCallFrame(m_callFrame);
177 }
178
179 // Evaluate some JavaScript code in the scope of this frame.
180 JSValue DebuggerCallFrame::evaluate(const String& script, Exception*& exception)
181 {
182     ASSERT(isValid());
183     CallFrame* callFrame = m_callFrame;
184     if (!callFrame)
185         return jsNull();
186
187     JSLockHolder lock(callFrame);
188
189     if (!callFrame->codeBlock())
190         return JSValue();
191     
192     DebuggerEvalEnabler evalEnabler(callFrame);
193     VM& vm = callFrame->vm();
194     auto& codeBlock = *callFrame->codeBlock();
195     ThisTDZMode thisTDZMode = codeBlock.unlinkedCodeBlock()->constructorKind() == ConstructorKind::Derived ? ThisTDZMode::AlwaysCheck : ThisTDZMode::CheckIfNeeded;
196     EvalExecutable* eval = EvalExecutable::create(callFrame, makeSource(script), codeBlock.isStrictMode(), thisTDZMode);
197     if (vm.exception()) {
198         exception = vm.exception();
199         vm.clearException();
200         return jsUndefined();
201     }
202
203     JSValue thisValue = thisValueForCallFrame(callFrame);
204     JSValue result = vm.interpreter->execute(eval, callFrame, thisValue, scope()->jsScope());
205     if (vm.exception()) {
206         exception = vm.exception();
207         vm.clearException();
208     }
209     ASSERT(result);
210     return result;
211 }
212
213 void DebuggerCallFrame::invalidate()
214 {
215     RefPtr<DebuggerCallFrame> frame = this;
216     while (frame) {
217         frame->m_callFrame = nullptr;
218         if (frame->m_scope) {
219             frame->m_scope->invalidateChain();
220             frame->m_scope.clear();
221         }
222         frame = frame->m_caller.release();
223     }
224 }
225
226 TextPosition DebuggerCallFrame::positionForCallFrame(CallFrame* callFrame)
227 {
228     if (!callFrame)
229         return TextPosition();
230
231     LineAndColumnFunctor functor;
232     callFrame->iterate(functor);
233     return TextPosition(OrdinalNumber::fromOneBasedInt(functor.line()), OrdinalNumber::fromOneBasedInt(functor.column()));
234 }
235
236 SourceID DebuggerCallFrame::sourceIDForCallFrame(CallFrame* callFrame)
237 {
238     ASSERT(callFrame);
239     CodeBlock* codeBlock = callFrame->codeBlock();
240     if (!codeBlock)
241         return noSourceID;
242     return codeBlock->ownerExecutable()->sourceID();
243 }
244
245 JSValue DebuggerCallFrame::thisValueForCallFrame(CallFrame* callFrame)
246 {
247     if (!callFrame)
248         return jsNull();
249
250     ECMAMode ecmaMode = NotStrictMode;
251     CodeBlock* codeBlock = callFrame->codeBlock();
252     if (codeBlock && codeBlock->isStrictMode())
253         ecmaMode = StrictMode;
254     JSValue thisValue = callFrame->thisValue().toThis(callFrame, ecmaMode);
255     return thisValue;
256 }
257
258 } // namespace JSC