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 40namespace JSC { 41 42class LineAndColumnFunctor { 43public: 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 53private: 54 unsigned m_line; 55 unsigned m_column; 56}; 57 58DebuggerCallFrame::DebuggerCallFrame(CallFrame* callFrame) 59 : m_callFrame(callFrame) 60{ 61 m_position = positionForCallFrame(m_callFrame); 62} 63 64PassRefPtr<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 81JSC::JSGlobalObject* DebuggerCallFrame::vmEntryGlobalObject() const 82{ 83 ASSERT(isValid()); 84 if (!isValid()) 85 return 0; 86 return m_callFrame->vmEntryGlobalObject(); 87} 88 89SourceID DebuggerCallFrame::sourceID() const 90{ 91 ASSERT(isValid()); 92 if (!isValid()) 93 return noSourceID; 94 return sourceIDForCallFrame(m_callFrame); 95} 96 97String 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 109JSScope* 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 125DebuggerCallFrame::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 137JSValue 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. 144JSValue 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 174void 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 184TextPosition 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 194SourceID 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 203JSValue 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 217