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 "Interpreter.h"
36 #include "JSFunction.h"
37 #include "JSLexicalEnvironment.h"
38 #include "JSCInlines.h"
40 #include "StackVisitor.h"
41 #include "StrongInlines.h"
45 class LineAndColumnFunctor
{
47 StackVisitor::Status
operator()(StackVisitor
& visitor
)
49 visitor
->computeLineAndColumn(m_line
, m_column
);
50 return StackVisitor::Done
;
53 unsigned line() const { return m_line
; }
54 unsigned column() const { return m_column
; }
61 class FindCallerMidStackFunctor
{
63 FindCallerMidStackFunctor(CallFrame
* callFrame
)
64 : m_callFrame(callFrame
)
65 , m_callerFrame(nullptr)
68 StackVisitor::Status
operator()(StackVisitor
& visitor
)
70 if (visitor
->callFrame() == m_callFrame
) {
71 m_callerFrame
= visitor
->callerFrame();
72 return StackVisitor::Done
;
74 return StackVisitor::Continue
;
77 CallFrame
* getCallerFrame() const { return m_callerFrame
; }
80 CallFrame
* m_callFrame
;
81 CallFrame
* m_callerFrame
;
84 DebuggerCallFrame::DebuggerCallFrame(CallFrame
* callFrame
)
85 : m_callFrame(callFrame
)
87 m_position
= positionForCallFrame(m_callFrame
);
90 RefPtr
<DebuggerCallFrame
> DebuggerCallFrame::callerFrame()
99 FindCallerMidStackFunctor
functor(m_callFrame
);
100 m_callFrame
->vm().topCallFrame
->iterate(functor
);
102 CallFrame
* callerFrame
= functor
.getCallerFrame();
106 m_caller
= DebuggerCallFrame::create(callerFrame
);
110 JSC::JSGlobalObject
* DebuggerCallFrame::vmEntryGlobalObject() const
115 return m_callFrame
->vmEntryGlobalObject();
118 SourceID
DebuggerCallFrame::sourceID() const
123 return sourceIDForCallFrame(m_callFrame
);
126 String
DebuggerCallFrame::functionName() const
131 JSFunction
* function
= jsDynamicCast
<JSFunction
*>(m_callFrame
->callee());
135 return getCalculatedDisplayName(m_callFrame
, function
);
138 DebuggerScope
* DebuggerCallFrame::scope()
145 VM
& vm
= m_callFrame
->vm();
147 CodeBlock
* codeBlock
= m_callFrame
->codeBlock();
148 if (codeBlock
&& codeBlock
->scopeRegister().isValid())
149 scope
= m_callFrame
->scope(codeBlock
->scopeRegister().offset());
150 else if (JSCallee
* callee
= jsDynamicCast
<JSCallee
*>(m_callFrame
->callee()))
151 scope
= callee
->scope();
153 scope
= m_callFrame
->lexicalGlobalObject();
155 m_scope
.set(vm
, DebuggerScope::create(vm
, scope
));
157 return m_scope
.get();
160 DebuggerCallFrame::Type
DebuggerCallFrame::type() const
166 if (jsDynamicCast
<JSFunction
*>(m_callFrame
->callee()))
172 JSValue
DebuggerCallFrame::thisValue() const
175 return thisValueForCallFrame(m_callFrame
);
178 // Evaluate some JavaScript code in the scope of this frame.
179 JSValue
DebuggerCallFrame::evaluate(const String
& script
, NakedPtr
<Exception
>& exception
)
182 CallFrame
* callFrame
= m_callFrame
;
186 JSLockHolder
lock(callFrame
);
188 if (!callFrame
->codeBlock())
191 DebuggerEvalEnabler
evalEnabler(callFrame
);
192 VM
& vm
= callFrame
->vm();
193 auto& codeBlock
= *callFrame
->codeBlock();
194 ThisTDZMode thisTDZMode
= codeBlock
.unlinkedCodeBlock()->constructorKind() == ConstructorKind::Derived
? ThisTDZMode::AlwaysCheck
: ThisTDZMode::CheckIfNeeded
;
195 EvalExecutable
* eval
= EvalExecutable::create(callFrame
, makeSource(script
), codeBlock
.isStrictMode(), thisTDZMode
);
196 if (vm
.exception()) {
197 exception
= vm
.exception();
199 return jsUndefined();
202 JSValue thisValue
= thisValueForCallFrame(callFrame
);
203 JSValue result
= vm
.interpreter
->execute(eval
, callFrame
, thisValue
, scope()->jsScope());
204 if (vm
.exception()) {
205 exception
= vm
.exception();
212 void DebuggerCallFrame::invalidate()
214 RefPtr
<DebuggerCallFrame
> frame
= this;
216 frame
->m_callFrame
= nullptr;
217 if (frame
->m_scope
) {
218 frame
->m_scope
->invalidateChain();
219 frame
->m_scope
.clear();
221 frame
= frame
->m_caller
.release();
225 TextPosition
DebuggerCallFrame::positionForCallFrame(CallFrame
* callFrame
)
228 return TextPosition();
230 LineAndColumnFunctor functor
;
231 callFrame
->iterate(functor
);
232 return TextPosition(OrdinalNumber::fromOneBasedInt(functor
.line()), OrdinalNumber::fromOneBasedInt(functor
.column()));
235 SourceID
DebuggerCallFrame::sourceIDForCallFrame(CallFrame
* callFrame
)
238 CodeBlock
* codeBlock
= callFrame
->codeBlock();
241 return codeBlock
->ownerExecutable()->sourceID();
244 JSValue
DebuggerCallFrame::thisValueForCallFrame(CallFrame
* callFrame
)
249 ECMAMode ecmaMode
= NotStrictMode
;
250 CodeBlock
* codeBlock
= callFrame
->codeBlock();
251 if (codeBlock
&& codeBlock
->isStrictMode())
252 ecmaMode
= StrictMode
;
253 JSValue thisValue
= callFrame
->thisValue().toThis(callFrame
, ecmaMode
);