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 "src/inspector/java-script-call-frame.h" 32 33 #include "src/debug/debug-interface.h" 34 #include "src/inspector/string-util.h" 35 36 namespace v8_inspector { 37 38 JavaScriptCallFrame::JavaScriptCallFrame(v8::Local<v8::Context> debuggerContext, 39 v8::Local<v8::Object> callFrame) 40 : m_isolate(debuggerContext->GetIsolate()), 41 m_debuggerContext(m_isolate, debuggerContext), 42 m_callFrame(m_isolate, callFrame) {} 43 44 JavaScriptCallFrame::~JavaScriptCallFrame() {} 45 46 int JavaScriptCallFrame::callV8FunctionReturnInt(const char* name) const { 47 v8::HandleScope handleScope(m_isolate); 48 v8::MicrotasksScope microtasks(m_isolate, 49 v8::MicrotasksScope::kDoNotRunMicrotasks); 50 v8::Local<v8::Context> context = 51 v8::Local<v8::Context>::New(m_isolate, m_debuggerContext); 52 v8::Local<v8::Object> callFrame = 53 v8::Local<v8::Object>::New(m_isolate, m_callFrame); 54 v8::Local<v8::Function> func = v8::Local<v8::Function>::Cast( 55 callFrame->Get(context, toV8StringInternalized(m_isolate, name)) 56 .ToLocalChecked()); 57 v8::Local<v8::Value> result; 58 if (!func->Call(context, callFrame, 0, nullptr).ToLocal(&result) || 59 !result->IsInt32()) 60 return 0; 61 return result.As<v8::Int32>()->Value(); 62 } 63 64 int JavaScriptCallFrame::contextId() const { 65 return callV8FunctionReturnInt("contextId"); 66 } 67 68 bool JavaScriptCallFrame::isAtReturn() const { 69 v8::HandleScope handleScope(m_isolate); 70 v8::Local<v8::Context> context = 71 v8::Local<v8::Context>::New(m_isolate, m_debuggerContext); 72 v8::Local<v8::Object> callFrame = 73 v8::Local<v8::Object>::New(m_isolate, m_callFrame); 74 v8::Local<v8::Value> result; 75 if (!callFrame->Get(context, toV8StringInternalized(m_isolate, "isAtReturn")) 76 .ToLocal(&result) || 77 !result->IsBoolean()) 78 return false; 79 return result.As<v8::Boolean>()->BooleanValue(context).FromMaybe(false); 80 } 81 82 v8::MaybeLocal<v8::Object> JavaScriptCallFrame::details() const { 83 v8::MicrotasksScope microtasks(m_isolate, 84 v8::MicrotasksScope::kDoNotRunMicrotasks); 85 v8::Local<v8::Context> context = 86 v8::Local<v8::Context>::New(m_isolate, m_debuggerContext); 87 v8::Local<v8::Object> callFrame = 88 v8::Local<v8::Object>::New(m_isolate, m_callFrame); 89 v8::Local<v8::Function> func = v8::Local<v8::Function>::Cast( 90 callFrame->Get(context, toV8StringInternalized(m_isolate, "details")) 91 .ToLocalChecked()); 92 v8::TryCatch try_catch(m_isolate); 93 v8::Local<v8::Value> details; 94 if (func->Call(context, callFrame, 0, nullptr).ToLocal(&details)) { 95 return v8::Local<v8::Object>::Cast(details); 96 } 97 return v8::MaybeLocal<v8::Object>(); 98 } 99 100 v8::MaybeLocal<v8::Value> JavaScriptCallFrame::evaluate( 101 v8::Local<v8::Value> expression, bool throwOnSideEffect) { 102 v8::MicrotasksScope microtasks(m_isolate, 103 v8::MicrotasksScope::kRunMicrotasks); 104 v8::Local<v8::Context> context = 105 v8::Local<v8::Context>::New(m_isolate, m_debuggerContext); 106 v8::Local<v8::Object> callFrame = 107 v8::Local<v8::Object>::New(m_isolate, m_callFrame); 108 v8::Local<v8::Function> evalFunction = v8::Local<v8::Function>::Cast( 109 callFrame->Get(context, toV8StringInternalized(m_isolate, "evaluate")) 110 .ToLocalChecked()); 111 v8::Local<v8::Value> argv[] = { 112 expression, v8::Boolean::New(m_isolate, throwOnSideEffect)}; 113 return evalFunction->Call(context, callFrame, arraysize(argv), argv); 114 } 115 116 v8::MaybeLocal<v8::Value> JavaScriptCallFrame::restart() { 117 v8::MicrotasksScope microtasks(m_isolate, 118 v8::MicrotasksScope::kDoNotRunMicrotasks); 119 v8::Local<v8::Context> context = 120 v8::Local<v8::Context>::New(m_isolate, m_debuggerContext); 121 v8::Local<v8::Object> callFrame = 122 v8::Local<v8::Object>::New(m_isolate, m_callFrame); 123 v8::Local<v8::Function> restartFunction = v8::Local<v8::Function>::Cast( 124 callFrame->Get(context, toV8StringInternalized(m_isolate, "restart")) 125 .ToLocalChecked()); 126 v8::TryCatch try_catch(m_isolate); 127 v8::debug::SetLiveEditEnabled(m_isolate, true); 128 v8::MaybeLocal<v8::Value> result = restartFunction->Call( 129 m_debuggerContext.Get(m_isolate), callFrame, 0, nullptr); 130 v8::debug::SetLiveEditEnabled(m_isolate, false); 131 return result; 132 } 133 134 v8::MaybeLocal<v8::Value> JavaScriptCallFrame::setVariableValue( 135 int scopeNumber, v8::Local<v8::Value> variableName, 136 v8::Local<v8::Value> newValue) { 137 v8::MicrotasksScope microtasks(m_isolate, 138 v8::MicrotasksScope::kDoNotRunMicrotasks); 139 v8::Local<v8::Context> context = 140 v8::Local<v8::Context>::New(m_isolate, m_debuggerContext); 141 v8::Local<v8::Object> callFrame = 142 v8::Local<v8::Object>::New(m_isolate, m_callFrame); 143 v8::Local<v8::Function> setVariableValueFunction = 144 v8::Local<v8::Function>::Cast( 145 callFrame 146 ->Get(context, 147 toV8StringInternalized(m_isolate, "setVariableValue")) 148 .ToLocalChecked()); 149 v8::Local<v8::Value> argv[] = { 150 v8::Local<v8::Value>(v8::Integer::New(m_isolate, scopeNumber)), 151 variableName, newValue}; 152 v8::TryCatch try_catch(m_isolate); 153 return setVariableValueFunction->Call(context, callFrame, arraysize(argv), 154 argv); 155 } 156 157 } // namespace v8_inspector 158