1// Copyright 2017 the V8 project authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "src/debug/debug-scope-iterator.h" 6 7#include "src/api/api-inl.h" 8#include "src/debug/debug.h" 9#include "src/debug/liveedit.h" 10#include "src/execution/frames-inl.h" 11#include "src/execution/isolate.h" 12#include "src/objects/js-generator-inl.h" 13 14namespace v8 { 15 16std::unique_ptr<debug::ScopeIterator> debug::ScopeIterator::CreateForFunction( 17 v8::Isolate* v8_isolate, v8::Local<v8::Function> v8_func) { 18 internal::Handle<internal::JSReceiver> receiver = 19 internal::Handle<internal::JSReceiver>::cast(Utils::OpenHandle(*v8_func)); 20 21 // Besides JSFunction and JSBoundFunction, {v8_func} could be an 22 // ObjectTemplate with a CallAsFunctionHandler. We only handle plain 23 // JSFunctions. 24 if (!receiver->IsJSFunction()) return nullptr; 25 26 internal::Handle<internal::JSFunction> function = 27 internal::Handle<internal::JSFunction>::cast(receiver); 28 29 // Blink has function objects with callable map, JS_SPECIAL_API_OBJECT_TYPE 30 // but without context on heap. 31 if (!function->has_context()) return nullptr; 32 return std::unique_ptr<debug::ScopeIterator>(new internal::DebugScopeIterator( 33 reinterpret_cast<internal::Isolate*>(v8_isolate), function)); 34} 35 36std::unique_ptr<debug::ScopeIterator> 37debug::ScopeIterator::CreateForGeneratorObject( 38 v8::Isolate* v8_isolate, v8::Local<v8::Object> v8_generator) { 39 internal::Handle<internal::Object> generator = 40 Utils::OpenHandle(*v8_generator); 41 DCHECK(generator->IsJSGeneratorObject()); 42 return std::unique_ptr<debug::ScopeIterator>(new internal::DebugScopeIterator( 43 reinterpret_cast<internal::Isolate*>(v8_isolate), 44 internal::Handle<internal::JSGeneratorObject>::cast(generator))); 45} 46 47namespace internal { 48 49DebugScopeIterator::DebugScopeIterator(Isolate* isolate, 50 FrameInspector* frame_inspector) 51 : iterator_( 52 isolate, frame_inspector, 53 ::v8::internal::ScopeIterator::ReparseStrategy::kFunctionLiteral) { 54 if (!Done() && ShouldIgnore()) Advance(); 55} 56 57DebugScopeIterator::DebugScopeIterator(Isolate* isolate, 58 Handle<JSFunction> function) 59 : iterator_(isolate, function) { 60 if (!Done() && ShouldIgnore()) Advance(); 61} 62 63DebugScopeIterator::DebugScopeIterator(Isolate* isolate, 64 Handle<JSGeneratorObject> generator) 65 : iterator_(isolate, generator) { 66 if (!Done() && ShouldIgnore()) Advance(); 67} 68 69bool DebugScopeIterator::Done() { return iterator_.Done(); } 70 71void DebugScopeIterator::Advance() { 72 DCHECK(!Done()); 73 iterator_.Next(); 74 while (!Done() && ShouldIgnore()) { 75 iterator_.Next(); 76 } 77} 78 79bool DebugScopeIterator::ShouldIgnore() { 80 if (GetType() == debug::ScopeIterator::ScopeTypeLocal) return false; 81 return !iterator_.DeclaresLocals(i::ScopeIterator::Mode::ALL); 82} 83 84v8::debug::ScopeIterator::ScopeType DebugScopeIterator::GetType() { 85 DCHECK(!Done()); 86 return static_cast<v8::debug::ScopeIterator::ScopeType>(iterator_.Type()); 87} 88 89v8::Local<v8::Object> DebugScopeIterator::GetObject() { 90 DCHECK(!Done()); 91 Handle<JSObject> value = iterator_.ScopeObject(i::ScopeIterator::Mode::ALL); 92 return Utils::ToLocal(value); 93} 94 95int DebugScopeIterator::GetScriptId() { 96 DCHECK(!Done()); 97 return iterator_.GetScript()->id(); 98} 99 100v8::Local<v8::Value> DebugScopeIterator::GetFunctionDebugName() { 101 DCHECK(!Done()); 102 Handle<Object> name = iterator_.GetFunctionDebugName(); 103 return Utils::ToLocal(name); 104} 105 106bool DebugScopeIterator::HasLocationInfo() { 107 return iterator_.HasPositionInfo(); 108} 109 110debug::Location DebugScopeIterator::GetStartLocation() { 111 DCHECK(!Done()); 112 return ToApiHandle<v8::debug::Script>(iterator_.GetScript()) 113 ->GetSourceLocation(iterator_.start_position()); 114} 115 116debug::Location DebugScopeIterator::GetEndLocation() { 117 DCHECK(!Done()); 118 return ToApiHandle<v8::debug::Script>(iterator_.GetScript()) 119 ->GetSourceLocation(iterator_.end_position()); 120} 121 122bool DebugScopeIterator::SetVariableValue(v8::Local<v8::String> name, 123 v8::Local<v8::Value> value) { 124 DCHECK(!Done()); 125 return iterator_.SetVariableValue(Utils::OpenHandle(*name), 126 Utils::OpenHandle(*value)); 127} 128 129} // namespace internal 130} // namespace v8 131