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 #include <v8-debug.h> 37 38 namespace WebCore { 39 40 JavaScriptCallFrame::JavaScriptCallFrame(v8::Handle<v8::Context> debuggerContext, v8::Handle<v8::Object> callFrame) 41 : m_isolate(v8::Isolate::GetCurrent()) 42 , m_debuggerContext(m_isolate, debuggerContext) 43 , m_callFrame(m_isolate, callFrame) 44 { 45 ScriptWrappable::init(this); 46 } 47 48 JavaScriptCallFrame::~JavaScriptCallFrame() 49 { 50 } 51 52 JavaScriptCallFrame* JavaScriptCallFrame::caller() 53 { 54 if (!m_caller) { 55 v8::HandleScope handleScope(m_isolate); 56 v8::Handle<v8::Context> debuggerContext = m_debuggerContext.newLocal(m_isolate); 57 v8::Context::Scope contextScope(debuggerContext); 58 v8::Handle<v8::Value> callerFrame = m_callFrame.newLocal(m_isolate)->Get(v8AtomicString(m_isolate, "caller")); 59 if (!callerFrame->IsObject()) 60 return 0; 61 m_caller = JavaScriptCallFrame::create(debuggerContext, v8::Handle<v8::Object>::Cast(callerFrame)); 62 } 63 return m_caller.get(); 64 } 65 66 int JavaScriptCallFrame::callV8FunctionReturnInt(const char* name) const 67 { 68 v8::HandleScope handleScope(m_isolate); 69 v8::Handle<v8::Object> callFrame = m_callFrame.newLocal(m_isolate); 70 v8::Handle<v8::Function> func = v8::Handle<v8::Function>::Cast(callFrame->Get(v8AtomicString(m_isolate, name))); 71 v8::Handle<v8::Value> result = func->Call(callFrame, 0, 0); 72 if (result->IsInt32()) 73 return result->Int32Value(); 74 return 0; 75 } 76 77 String JavaScriptCallFrame::callV8FunctionReturnString(const char* name) const 78 { 79 v8::HandleScope handleScope(m_isolate); 80 v8::Handle<v8::Object> callFrame = m_callFrame.newLocal(m_isolate); 81 v8::Handle<v8::Function> func = v8::Handle<v8::Function>::Cast(callFrame->Get(v8AtomicString(m_isolate, name))); 82 v8::Handle<v8::Value> result = func->Call(callFrame, 0, 0); 83 return toCoreStringWithUndefinedOrNullCheck(result); 84 } 85 86 int JavaScriptCallFrame::sourceID() const 87 { 88 return callV8FunctionReturnInt("sourceID"); 89 } 90 91 int JavaScriptCallFrame::line() const 92 { 93 return callV8FunctionReturnInt("line"); 94 } 95 96 int JavaScriptCallFrame::column() const 97 { 98 return callV8FunctionReturnInt("column"); 99 } 100 101 String JavaScriptCallFrame::functionName() const 102 { 103 return callV8FunctionReturnString("functionName"); 104 } 105 106 v8::Handle<v8::Value> JavaScriptCallFrame::scopeChain() const 107 { 108 v8::Handle<v8::Object> callFrame = m_callFrame.newLocal(m_isolate); 109 v8::Handle<v8::Function> func = v8::Handle<v8::Function>::Cast(callFrame->Get(v8AtomicString(m_isolate, "scopeChain"))); 110 v8::Handle<v8::Array> scopeChain = v8::Handle<v8::Array>::Cast(func->Call(callFrame, 0, 0)); 111 v8::Handle<v8::Array> result = v8::Array::New(m_isolate, scopeChain->Length()); 112 for (uint32_t i = 0; i < scopeChain->Length(); i++) 113 result->Set(i, scopeChain->Get(i)); 114 return result; 115 } 116 117 int JavaScriptCallFrame::scopeType(int scopeIndex) const 118 { 119 v8::Handle<v8::Array> scopeType = v8::Handle<v8::Array>::Cast(m_callFrame.newLocal(m_isolate)->Get(v8AtomicString(m_isolate, "scopeType"))); 120 return scopeType->Get(scopeIndex)->Int32Value(); 121 } 122 123 v8::Handle<v8::Value> JavaScriptCallFrame::thisObject() const 124 { 125 return m_callFrame.newLocal(m_isolate)->Get(v8AtomicString(m_isolate, "thisObject")); 126 } 127 128 String JavaScriptCallFrame::stepInPositions() const 129 { 130 return callV8FunctionReturnString("stepInPositions"); 131 } 132 133 bool JavaScriptCallFrame::isAtReturn() const 134 { 135 v8::HandleScope handleScope(m_isolate); 136 v8::Context::Scope contextScope(m_debuggerContext.newLocal(m_isolate)); 137 v8::Handle<v8::Value> result = m_callFrame.newLocal(m_isolate)->Get(v8AtomicString(m_isolate, "isAtReturn")); 138 if (result->IsBoolean()) 139 return result->BooleanValue(); 140 return false; 141 } 142 143 v8::Handle<v8::Value> JavaScriptCallFrame::returnValue() const 144 { 145 return m_callFrame.newLocal(m_isolate)->Get(v8AtomicString(m_isolate, "returnValue")); 146 } 147 148 v8::Handle<v8::Value> JavaScriptCallFrame::evaluate(const String& expression) 149 { 150 v8::Handle<v8::Object> callFrame = m_callFrame.newLocal(m_isolate); 151 v8::Handle<v8::Function> evalFunction = v8::Handle<v8::Function>::Cast(callFrame->Get(v8AtomicString(m_isolate, "evaluate"))); 152 v8::Handle<v8::Value> argv[] = { v8String(m_debuggerContext.newLocal(m_isolate)->GetIsolate(), expression) }; 153 return evalFunction->Call(callFrame, WTF_ARRAY_LENGTH(argv), argv); 154 } 155 156 v8::Handle<v8::Value> JavaScriptCallFrame::restart() 157 { 158 v8::Handle<v8::Object> callFrame = m_callFrame.newLocal(m_isolate); 159 v8::Handle<v8::Function> restartFunction = v8::Handle<v8::Function>::Cast(callFrame->Get(v8AtomicString(m_isolate, "restart"))); 160 v8::Debug::SetLiveEditEnabled(m_isolate, true); 161 v8::Handle<v8::Value> result = restartFunction->Call(callFrame, 0, 0); 162 v8::Debug::SetLiveEditEnabled(m_isolate, false); 163 return result; 164 } 165 166 ScriptValue JavaScriptCallFrame::setVariableValue(ScriptState* scriptState, int scopeNumber, const String& variableName, const ScriptValue& newValue) 167 { 168 ScriptState::Scope scriptScope(scriptState); 169 v8::Handle<v8::Object> callFrame = m_callFrame.newLocal(m_isolate); 170 v8::Handle<v8::Function> setVariableValueFunction = v8::Handle<v8::Function>::Cast(callFrame->Get(v8AtomicString(m_isolate, "setVariableValue"))); 171 v8::Handle<v8::Value> argv[] = { 172 v8::Handle<v8::Value>(v8::Integer::New(m_isolate, scopeNumber)), 173 v8String(m_isolate, variableName), 174 newValue.v8Value() 175 }; 176 return ScriptValue(scriptState, setVariableValueFunction->Call(callFrame, WTF_ARRAY_LENGTH(argv), argv)); 177 } 178 179 void JavaScriptCallFrame::trace(Visitor* visitor) 180 { 181 visitor->trace(m_caller); 182 } 183 184 } // namespace WebCore 185