diff options
author | Lorry Tar Creator <lorry-tar-importer@lorry> | 2015-10-15 09:45:50 +0000 |
---|---|---|
committer | Lorry Tar Creator <lorry-tar-importer@lorry> | 2015-10-15 09:45:50 +0000 |
commit | e15dd966d523731101f70ccf768bba12435a0208 (patch) | |
tree | ae9cb828a24ded2585a41af3f21411523b47897d /Source/JavaScriptCore/debugger/DebuggerCallFrame.cpp | |
download | WebKitGtk-tarball-e15dd966d523731101f70ccf768bba12435a0208.tar.gz |
webkitgtk-2.10.2webkitgtk-2.10.2
Diffstat (limited to 'Source/JavaScriptCore/debugger/DebuggerCallFrame.cpp')
-rw-r--r-- | Source/JavaScriptCore/debugger/DebuggerCallFrame.cpp | 261 |
1 files changed, 261 insertions, 0 deletions
diff --git a/Source/JavaScriptCore/debugger/DebuggerCallFrame.cpp b/Source/JavaScriptCore/debugger/DebuggerCallFrame.cpp new file mode 100644 index 000000000..bf093e89b --- /dev/null +++ b/Source/JavaScriptCore/debugger/DebuggerCallFrame.cpp @@ -0,0 +1,261 @@ +/* + * Copyright (C) 2008, 2013, 2014 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Apple Inc. ("Apple") nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "DebuggerCallFrame.h" + +#include "CodeBlock.h" +#include "DebuggerEvalEnabler.h" +#include "DebuggerScope.h" +#include "Interpreter.h" +#include "JSFunction.h" +#include "JSLexicalEnvironment.h" +#include "JSCInlines.h" +#include "Parser.h" +#include "StackVisitor.h" +#include "StrongInlines.h" + +namespace JSC { + +class LineAndColumnFunctor { +public: + StackVisitor::Status operator()(StackVisitor& visitor) + { + visitor->computeLineAndColumn(m_line, m_column); + return StackVisitor::Done; + } + + unsigned line() const { return m_line; } + unsigned column() const { return m_column; } + +private: + unsigned m_line; + unsigned m_column; +}; + +class FindCallerMidStackFunctor { +public: + FindCallerMidStackFunctor(CallFrame* callFrame) + : m_callFrame(callFrame) + , m_callerFrame(nullptr) + { } + + StackVisitor::Status operator()(StackVisitor& visitor) + { + if (visitor->callFrame() == m_callFrame) { + m_callerFrame = visitor->callerFrame(); + return StackVisitor::Done; + } + return StackVisitor::Continue; + } + + CallFrame* getCallerFrame() const { return m_callerFrame; } + +private: + CallFrame* m_callFrame; + CallFrame* m_callerFrame; +}; + +DebuggerCallFrame::DebuggerCallFrame(CallFrame* callFrame) + : m_callFrame(callFrame) +{ + m_position = positionForCallFrame(m_callFrame); +} + +RefPtr<DebuggerCallFrame> DebuggerCallFrame::callerFrame() +{ + ASSERT(isValid()); + if (!isValid()) + return 0; + + if (m_caller) + return m_caller; + + FindCallerMidStackFunctor functor(m_callFrame); + m_callFrame->vm().topCallFrame->iterate(functor); + + CallFrame* callerFrame = functor.getCallerFrame(); + if (!callerFrame) + return nullptr; + + m_caller = DebuggerCallFrame::create(callerFrame); + return m_caller; +} + +JSC::JSGlobalObject* DebuggerCallFrame::vmEntryGlobalObject() const +{ + ASSERT(isValid()); + if (!isValid()) + return 0; + return m_callFrame->vmEntryGlobalObject(); +} + +SourceID DebuggerCallFrame::sourceID() const +{ + ASSERT(isValid()); + if (!isValid()) + return noSourceID; + return sourceIDForCallFrame(m_callFrame); +} + +String DebuggerCallFrame::functionName() const +{ + ASSERT(isValid()); + if (!isValid()) + return String(); + JSFunction* function = jsDynamicCast<JSFunction*>(m_callFrame->callee()); + if (!function) + return String(); + + return getCalculatedDisplayName(m_callFrame, function); +} + +DebuggerScope* DebuggerCallFrame::scope() +{ + ASSERT(isValid()); + if (!isValid()) + return 0; + + if (!m_scope) { + VM& vm = m_callFrame->vm(); + JSScope* scope; + CodeBlock* codeBlock = m_callFrame->codeBlock(); + if (codeBlock && codeBlock->scopeRegister().isValid()) + scope = m_callFrame->scope(codeBlock->scopeRegister().offset()); + else if (JSCallee* callee = jsDynamicCast<JSCallee*>(m_callFrame->callee())) + scope = callee->scope(); + else + scope = m_callFrame->lexicalGlobalObject(); + + m_scope.set(vm, DebuggerScope::create(vm, scope)); + } + return m_scope.get(); +} + +DebuggerCallFrame::Type DebuggerCallFrame::type() const +{ + ASSERT(isValid()); + if (!isValid()) + return ProgramType; + + if (jsDynamicCast<JSFunction*>(m_callFrame->callee())) + return FunctionType; + + return ProgramType; +} + +JSValue DebuggerCallFrame::thisValue() const +{ + ASSERT(isValid()); + return thisValueForCallFrame(m_callFrame); +} + +// Evaluate some JavaScript code in the scope of this frame. +JSValue DebuggerCallFrame::evaluate(const String& script, NakedPtr<Exception>& exception) +{ + ASSERT(isValid()); + CallFrame* callFrame = m_callFrame; + if (!callFrame) + return jsNull(); + + JSLockHolder lock(callFrame); + + if (!callFrame->codeBlock()) + return JSValue(); + + DebuggerEvalEnabler evalEnabler(callFrame); + VM& vm = callFrame->vm(); + auto& codeBlock = *callFrame->codeBlock(); + ThisTDZMode thisTDZMode = codeBlock.unlinkedCodeBlock()->constructorKind() == ConstructorKind::Derived ? ThisTDZMode::AlwaysCheck : ThisTDZMode::CheckIfNeeded; + + VariableEnvironment variablesUnderTDZ; + JSScope::collectVariablesUnderTDZ(scope()->jsScope(), variablesUnderTDZ); + + EvalExecutable* eval = EvalExecutable::create(callFrame, makeSource(script), codeBlock.isStrictMode(), thisTDZMode, &variablesUnderTDZ); + if (vm.exception()) { + exception = vm.exception(); + vm.clearException(); + return jsUndefined(); + } + + JSValue thisValue = thisValueForCallFrame(callFrame); + JSValue result = vm.interpreter->execute(eval, callFrame, thisValue, scope()->jsScope()); + if (vm.exception()) { + exception = vm.exception(); + vm.clearException(); + } + ASSERT(result); + return result; +} + +void DebuggerCallFrame::invalidate() +{ + RefPtr<DebuggerCallFrame> frame = this; + while (frame) { + frame->m_callFrame = nullptr; + if (frame->m_scope) { + frame->m_scope->invalidateChain(); + frame->m_scope.clear(); + } + frame = frame->m_caller.release(); + } +} + +TextPosition DebuggerCallFrame::positionForCallFrame(CallFrame* callFrame) +{ + if (!callFrame) + return TextPosition(); + + LineAndColumnFunctor functor; + callFrame->iterate(functor); + return TextPosition(OrdinalNumber::fromOneBasedInt(functor.line()), OrdinalNumber::fromOneBasedInt(functor.column())); +} + +SourceID DebuggerCallFrame::sourceIDForCallFrame(CallFrame* callFrame) +{ + ASSERT(callFrame); + CodeBlock* codeBlock = callFrame->codeBlock(); + if (!codeBlock) + return noSourceID; + return codeBlock->ownerExecutable()->sourceID(); +} + +JSValue DebuggerCallFrame::thisValueForCallFrame(CallFrame* callFrame) +{ + if (!callFrame) + return jsNull(); + + ECMAMode ecmaMode = NotStrictMode; + CodeBlock* codeBlock = callFrame->codeBlock(); + if (codeBlock && codeBlock->isStrictMode()) + ecmaMode = StrictMode; + JSValue thisValue = callFrame->thisValue().toThis(callFrame, ecmaMode); + return thisValue; +} + +} // namespace JSC |