2 * Copyright (C) 2008, 2013, 2014 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
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.
30 #include "DebuggerCallFrame.h"
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"
41 #include "StackVisitor.h"
42 #include "StrongInlines.h"
46 class LineAndColumnFunctor {
48 StackVisitor::Status operator()(StackVisitor& visitor)
50 visitor->computeLineAndColumn(m_line, m_column);
51 return StackVisitor::Done;
54 unsigned line() const { return m_line; }
55 unsigned column() const { return m_column; }
62 class FindCallerMidStackFunctor {
64 FindCallerMidStackFunctor(CallFrame* callFrame)
65 : m_callFrame(callFrame)
66 , m_callerFrame(nullptr)
69 StackVisitor::Status operator()(StackVisitor& visitor)
71 if (visitor->callFrame() == m_callFrame) {
72 m_callerFrame = visitor->callerFrame();
73 return StackVisitor::Done;
75 return StackVisitor::Continue;
78 CallFrame* getCallerFrame() const { return m_callerFrame; }
81 CallFrame* m_callFrame;
82 CallFrame* m_callerFrame;
85 DebuggerCallFrame::DebuggerCallFrame(CallFrame* callFrame)
86 : m_callFrame(callFrame)
88 m_position = positionForCallFrame(m_callFrame);
91 RefPtr<DebuggerCallFrame> DebuggerCallFrame::callerFrame()
100 FindCallerMidStackFunctor functor(m_callFrame);
101 m_callFrame->vm().topCallFrame->iterate(functor);
103 CallFrame* callerFrame = functor.getCallerFrame();
107 m_caller = DebuggerCallFrame::create(callerFrame);
111 JSC::JSGlobalObject* DebuggerCallFrame::vmEntryGlobalObject() const
116 return m_callFrame->vmEntryGlobalObject();
119 SourceID DebuggerCallFrame::sourceID() const
124 return sourceIDForCallFrame(m_callFrame);
127 String DebuggerCallFrame::functionName() const
132 JSFunction* function = jsDynamicCast<JSFunction*>(m_callFrame->callee());
136 return getCalculatedDisplayName(m_callFrame, function);
139 DebuggerScope* DebuggerCallFrame::scope()
146 VM& vm = m_callFrame->vm();
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();
154 scope = m_callFrame->lexicalGlobalObject();
156 m_scope.set(vm, DebuggerScope::create(vm, scope));
158 return m_scope.get();
161 DebuggerCallFrame::Type DebuggerCallFrame::type() const
167 if (jsDynamicCast<JSFunction*>(m_callFrame->callee()))
173 JSValue DebuggerCallFrame::thisValue() const
176 return thisValueForCallFrame(m_callFrame);
179 // Evaluate some JavaScript code in the scope of this frame.
180 JSValue DebuggerCallFrame::evaluate(const String& script, Exception*& exception)
184 CallFrame* callFrame = m_callFrame;
188 JSLockHolder lock(callFrame);
190 if (!callFrame->codeBlock())
193 DebuggerEvalEnabler evalEnabler(callFrame);
194 VM& vm = callFrame->vm();
195 auto& codeBlock = *callFrame->codeBlock();
196 ThisTDZMode thisTDZMode = codeBlock.unlinkedCodeBlock()->constructorKind() == ConstructorKind::Derived ? ThisTDZMode::AlwaysCheck : ThisTDZMode::CheckIfNeeded;
197 EvalExecutable* eval = EvalExecutable::create(callFrame, makeSource(script), codeBlock.isStrictMode(), thisTDZMode);
198 if (vm.exception()) {
199 exception = vm.exception();
201 return jsUndefined();
204 JSValue thisValue = thisValueForCallFrame(callFrame);
205 JSValue result = vm.interpreter->execute(eval, callFrame, thisValue, scope()->jsScope());
206 if (vm.exception()) {
207 exception = vm.exception();
214 void DebuggerCallFrame::invalidate()
216 RefPtr<DebuggerCallFrame> frame = this;
218 frame->m_callFrame = nullptr;
219 if (frame->m_scope) {
220 frame->m_scope->invalidateChain();
221 frame->m_scope.clear();
223 frame = frame->m_caller.release();
227 TextPosition DebuggerCallFrame::positionForCallFrame(CallFrame* callFrame)
230 return TextPosition();
232 LineAndColumnFunctor functor;
233 callFrame->iterate(functor);
234 return TextPosition(OrdinalNumber::fromOneBasedInt(functor.line()), OrdinalNumber::fromOneBasedInt(functor.column()));
237 SourceID DebuggerCallFrame::sourceIDForCallFrame(CallFrame* callFrame)
240 CodeBlock* codeBlock = callFrame->codeBlock();
243 return codeBlock->ownerExecutable()->sourceID();
246 JSValue DebuggerCallFrame::thisValueForCallFrame(CallFrame* callFrame)
251 ECMAMode ecmaMode = NotStrictMode;
252 CodeBlock* codeBlock = callFrame->codeBlock();
253 if (codeBlock && codeBlock->isStrictMode())
254 ecmaMode = StrictMode;
255 JSValue thisValue = callFrame->thisValue().toThis(callFrame, ecmaMode);