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