1 /* 2 * Copyright (c) 2010, Google 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 are 6 * met: 7 * 8 * * Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * * Redistributions in binary form must reproduce the above 11 * copyright notice, this list of conditions and the following disclaimer 12 * in the documentation and/or other materials provided with the 13 * distribution. 14 * * Neither the name of Google Inc. nor the names of its 15 * contributors may be used to endorse or promote products derived from 16 * this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31 #include "config.h" 32 #include "core/inspector/JavaScriptCallFrame.h" 33 34 #include "bindings/v8/ScriptValue.h" 35 #include "bindings/v8/V8Binding.h" 36 37 namespace WebCore { 38 39 JavaScriptCallFrame::JavaScriptCallFrame(v8::Handle<v8::Context> debuggerContext, v8::Handle<v8::Object> callFrame) 40 : m_isolate(v8::Isolate::GetCurrent()) 41 , m_debuggerContext(m_isolate, debuggerContext) 42 , m_callFrame(m_isolate, callFrame) 43 { 44 ScriptWrappable::init(this); 45 } 46 47 JavaScriptCallFrame::~JavaScriptCallFrame() 48 { 49 } 50 51 JavaScriptCallFrame* JavaScriptCallFrame::caller() 52 { 53 if (!m_caller) { 54 v8::HandleScope handleScope(m_isolate); 55 v8::Handle<v8::Context> debuggerContext = m_debuggerContext.newLocal(m_isolate); 56 v8::Context::Scope contextScope(debuggerContext); 57 v8::Handle<v8::Value> callerFrame = m_callFrame.newLocal(m_isolate)->Get(v8AtomicString(m_isolate, "caller")); 58 if (!callerFrame->IsObject()) 59 return 0; 60 m_caller = JavaScriptCallFrame::create(debuggerContext, v8::Handle<v8::Object>::Cast(callerFrame)); 61 } 62 return m_caller.get(); 63 } 64 65 int JavaScriptCallFrame::sourceID() const 66 { 67 v8::HandleScope handleScope(m_isolate); 68 v8::Context::Scope contextScope(m_debuggerContext.newLocal(m_isolate)); 69 v8::Handle<v8::Value> result = m_callFrame.newLocal(m_isolate)->Get(v8AtomicString(m_isolate, "sourceID")); 70 if (result->IsInt32()) 71 return result->Int32Value(); 72 return 0; 73 } 74 75 int JavaScriptCallFrame::line() const 76 { 77 v8::HandleScope handleScope(m_isolate); 78 v8::Context::Scope contextScope(m_debuggerContext.newLocal(m_isolate)); 79 v8::Handle<v8::Value> result = m_callFrame.newLocal(m_isolate)->Get(v8AtomicString(m_isolate, "line")); 80 if (result->IsInt32()) 81 return result->Int32Value(); 82 return 0; 83 } 84 85 int JavaScriptCallFrame::column() const 86 { 87 v8::HandleScope handleScope(m_isolate); 88 v8::Context::Scope contextScope(m_debuggerContext.newLocal(m_isolate)); 89 v8::Handle<v8::Value> result = m_callFrame.newLocal(m_isolate)->Get(v8AtomicString(m_isolate, "column")); 90 if (result->IsInt32()) 91 return result->Int32Value(); 92 return 0; 93 } 94 95 String JavaScriptCallFrame::functionName() const 96 { 97 v8::HandleScope handleScope(m_isolate); 98 v8::Context::Scope contextScope(m_debuggerContext.newLocal(m_isolate)); 99 v8::Handle<v8::Value> result = m_callFrame.newLocal(m_isolate)->Get(v8AtomicString(m_isolate, "functionName")); 100 return toCoreStringWithUndefinedOrNullCheck(result); 101 } 102 103 v8::Handle<v8::Value> JavaScriptCallFrame::scopeChain() const 104 { 105 v8::Handle<v8::Array> scopeChain = v8::Handle<v8::Array>::Cast(m_callFrame.newLocal(m_isolate)->Get(v8AtomicString(m_isolate, "scopeChain"))); 106 v8::Handle<v8::Array> result = v8::Array::New(m_isolate, scopeChain->Length()); 107 for (uint32_t i = 0; i < scopeChain->Length(); i++) 108 result->Set(i, scopeChain->Get(i)); 109 return result; 110 } 111 112 int JavaScriptCallFrame::scopeType(int scopeIndex) const 113 { 114 v8::Handle<v8::Array> scopeType = v8::Handle<v8::Array>::Cast(m_callFrame.newLocal(m_isolate)->Get(v8AtomicString(m_isolate, "scopeType"))); 115 return scopeType->Get(scopeIndex)->Int32Value(); 116 } 117 118 v8::Handle<v8::Value> JavaScriptCallFrame::thisObject() const 119 { 120 return m_callFrame.newLocal(m_isolate)->Get(v8AtomicString(m_isolate, "thisObject")); 121 } 122 123 String JavaScriptCallFrame::stepInPositions() const 124 { 125 v8::Handle<v8::Object> callFrame = m_callFrame.newLocal(m_isolate); 126 v8::Handle<v8::Function> stepInPositions = v8::Handle<v8::Function>::Cast(callFrame->Get(v8AtomicString(m_isolate, "stepInPositions"))); 127 v8::Handle<v8::Value> result = stepInPositions->Call(callFrame, 0, 0); 128 return toCoreStringWithUndefinedOrNullCheck(result); 129 } 130 131 bool JavaScriptCallFrame::isAtReturn() const 132 { 133 v8::HandleScope handleScope(m_isolate); 134 v8::Context::Scope contextScope(m_debuggerContext.newLocal(m_isolate)); 135 v8::Handle<v8::Value> result = m_callFrame.newLocal(m_isolate)->Get(v8AtomicString(m_isolate, "isAtReturn")); 136 if (result->IsBoolean()) 137 return result->BooleanValue(); 138 return false; 139 } 140 141 v8::Handle<v8::Value> JavaScriptCallFrame::returnValue() const 142 { 143 return m_callFrame.newLocal(m_isolate)->Get(v8AtomicString(m_isolate, "returnValue")); 144 } 145 146 v8::Handle<v8::Value> JavaScriptCallFrame::evaluate(const String& expression) 147 { 148 v8::Handle<v8::Object> callFrame = m_callFrame.newLocal(m_isolate); 149 v8::Handle<v8::Function> evalFunction = v8::Handle<v8::Function>::Cast(callFrame->Get(v8AtomicString(m_isolate, "evaluate"))); 150 v8::Handle<v8::Value> argv[] = { v8String(m_debuggerContext.newLocal(m_isolate)->GetIsolate(), expression) }; 151 return evalFunction->Call(callFrame, 1, argv); 152 } 153 154 v8::Handle<v8::Value> JavaScriptCallFrame::restart() 155 { 156 v8::Handle<v8::Object> callFrame = m_callFrame.newLocal(m_isolate); 157 v8::Handle<v8::Function> restartFunction = v8::Handle<v8::Function>::Cast(callFrame->Get(v8AtomicString(m_isolate, "restart"))); 158 v8::Debug::SetLiveEditEnabled(true); 159 v8::Handle<v8::Value> result = restartFunction->Call(callFrame, 0, 0); 160 v8::Debug::SetLiveEditEnabled(false); 161 return result; 162 } 163 164 v8::Handle<v8::Object> JavaScriptCallFrame::innerCallFrame() 165 { 166 return m_callFrame.newLocal(m_isolate); 167 } 168 169 ScriptValue JavaScriptCallFrame::setVariableValue(int scopeNumber, const String& variableName, const ScriptValue& newValue) 170 { 171 v8::Handle<v8::Object> callFrame = m_callFrame.newLocal(m_isolate); 172 v8::Handle<v8::Function> setVariableValueFunction = v8::Handle<v8::Function>::Cast(callFrame->Get(v8AtomicString(m_isolate, "setVariableValue"))); 173 v8::Handle<v8::Value> argv[] = { 174 v8::Handle<v8::Value>(v8::Integer::New(scopeNumber, m_isolate)), 175 v8String(m_isolate, variableName), 176 newValue.v8Value() 177 }; 178 return ScriptValue(setVariableValueFunction->Call(callFrame, 3, argv), m_isolate); 179 } 180 181 } // namespace WebCore 182