Home | History | Annotate | Download | only in debug
      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-inl.h"
      8 #include "src/debug/debug.h"
      9 #include "src/debug/liveedit.h"
     10 #include "src/frames-inl.h"
     11 #include "src/isolate.h"
     12 #include "src/objects/js-generator-inl.h"
     13 #include "src/wasm/wasm-objects-inl.h"
     14 
     15 namespace v8 {
     16 
     17 std::unique_ptr<debug::ScopeIterator> debug::ScopeIterator::CreateForFunction(
     18     v8::Isolate* v8_isolate, v8::Local<v8::Function> v8_func) {
     19   internal::Handle<internal::JSReceiver> receiver =
     20       internal::Handle<internal::JSReceiver>::cast(Utils::OpenHandle(*v8_func));
     21 
     22   // Besides JSFunction and JSBoundFunction, {v8_func} could be an
     23   // ObjectTemplate with a CallAsFunctionHandler. We only handle plain
     24   // JSFunctions.
     25   if (!receiver->IsJSFunction()) return nullptr;
     26 
     27   internal::Handle<internal::JSFunction> function =
     28       internal::Handle<internal::JSFunction>::cast(receiver);
     29 
     30   // Blink has function objects with callable map, JS_SPECIAL_API_OBJECT_TYPE
     31   // but without context on heap.
     32   if (!function->has_context()) return nullptr;
     33   return std::unique_ptr<debug::ScopeIterator>(new internal::DebugScopeIterator(
     34       reinterpret_cast<internal::Isolate*>(v8_isolate), function));
     35 }
     36 
     37 std::unique_ptr<debug::ScopeIterator>
     38 debug::ScopeIterator::CreateForGeneratorObject(
     39     v8::Isolate* v8_isolate, v8::Local<v8::Object> v8_generator) {
     40   internal::Handle<internal::Object> generator =
     41       Utils::OpenHandle(*v8_generator);
     42   DCHECK(generator->IsJSGeneratorObject());
     43   return std::unique_ptr<debug::ScopeIterator>(new internal::DebugScopeIterator(
     44       reinterpret_cast<internal::Isolate*>(v8_isolate),
     45       internal::Handle<internal::JSGeneratorObject>::cast(generator)));
     46 }
     47 
     48 namespace internal {
     49 
     50 DebugScopeIterator::DebugScopeIterator(Isolate* isolate,
     51                                        FrameInspector* frame_inspector)
     52     : iterator_(isolate, frame_inspector) {
     53   if (!Done() && ShouldIgnore()) Advance();
     54 }
     55 
     56 DebugScopeIterator::DebugScopeIterator(Isolate* isolate,
     57                                        Handle<JSFunction> function)
     58     : iterator_(isolate, function) {
     59   if (!Done() && ShouldIgnore()) Advance();
     60 }
     61 
     62 DebugScopeIterator::DebugScopeIterator(Isolate* isolate,
     63                                        Handle<JSGeneratorObject> generator)
     64     : iterator_(isolate, generator) {
     65   if (!Done() && ShouldIgnore()) Advance();
     66 }
     67 
     68 bool DebugScopeIterator::Done() { return iterator_.Done(); }
     69 
     70 void DebugScopeIterator::Advance() {
     71   DCHECK(!Done());
     72   iterator_.Next();
     73   while (!Done() && ShouldIgnore()) {
     74     iterator_.Next();
     75   }
     76 }
     77 
     78 bool DebugScopeIterator::ShouldIgnore() {
     79   if (GetType() == debug::ScopeIterator::ScopeTypeLocal) return false;
     80   return !iterator_.DeclaresLocals(i::ScopeIterator::Mode::ALL);
     81 }
     82 
     83 v8::debug::ScopeIterator::ScopeType DebugScopeIterator::GetType() {
     84   DCHECK(!Done());
     85   return static_cast<v8::debug::ScopeIterator::ScopeType>(iterator_.Type());
     86 }
     87 
     88 v8::Local<v8::Object> DebugScopeIterator::GetObject() {
     89   DCHECK(!Done());
     90   Handle<JSObject> value = iterator_.ScopeObject(i::ScopeIterator::Mode::ALL);
     91   return Utils::ToLocal(value);
     92 }
     93 
     94 int DebugScopeIterator::GetScriptId() {
     95   DCHECK(!Done());
     96   return iterator_.GetScript()->id();
     97 }
     98 
     99 v8::Local<v8::Value> DebugScopeIterator::GetFunctionDebugName() {
    100   DCHECK(!Done());
    101   Handle<Object> name = iterator_.GetFunctionDebugName();
    102   return Utils::ToLocal(name);
    103 }
    104 
    105 bool DebugScopeIterator::HasLocationInfo() {
    106   return iterator_.HasPositionInfo();
    107 }
    108 
    109 debug::Location DebugScopeIterator::GetStartLocation() {
    110   DCHECK(!Done());
    111   return ToApiHandle<v8::debug::Script>(iterator_.GetScript())
    112       ->GetSourceLocation(iterator_.start_position());
    113 }
    114 
    115 debug::Location DebugScopeIterator::GetEndLocation() {
    116   DCHECK(!Done());
    117   return ToApiHandle<v8::debug::Script>(iterator_.GetScript())
    118       ->GetSourceLocation(iterator_.end_position());
    119 }
    120 
    121 bool DebugScopeIterator::SetVariableValue(v8::Local<v8::String> name,
    122                                           v8::Local<v8::Value> value) {
    123   DCHECK(!Done());
    124   return iterator_.SetVariableValue(Utils::OpenHandle(*name),
    125                                     Utils::OpenHandle(*value));
    126 }
    127 
    128 DebugWasmScopeIterator::DebugWasmScopeIterator(Isolate* isolate,
    129                                                StandardFrame* frame,
    130                                                int inlined_frame_index)
    131     : isolate_(isolate),
    132       frame_(frame),
    133       inlined_frame_index_(inlined_frame_index),
    134       type_(debug::ScopeIterator::ScopeTypeGlobal) {}
    135 
    136 bool DebugWasmScopeIterator::Done() {
    137   return type_ != debug::ScopeIterator::ScopeTypeGlobal &&
    138          type_ != debug::ScopeIterator::ScopeTypeLocal;
    139 }
    140 
    141 void DebugWasmScopeIterator::Advance() {
    142   DCHECK(!Done());
    143   if (type_ == debug::ScopeIterator::ScopeTypeGlobal) {
    144     type_ = debug::ScopeIterator::ScopeTypeLocal;
    145   } else {
    146     // We use ScopeTypeWith type as marker for done.
    147     type_ = debug::ScopeIterator::ScopeTypeWith;
    148   }
    149 }
    150 
    151 v8::debug::ScopeIterator::ScopeType DebugWasmScopeIterator::GetType() {
    152   DCHECK(!Done());
    153   return type_;
    154 }
    155 
    156 v8::Local<v8::Object> DebugWasmScopeIterator::GetObject() {
    157   DCHECK(!Done());
    158   Handle<WasmDebugInfo> debug_info(
    159       WasmInterpreterEntryFrame::cast(frame_)->debug_info(), isolate_);
    160   switch (type_) {
    161     case debug::ScopeIterator::ScopeTypeGlobal:
    162       return Utils::ToLocal(WasmDebugInfo::GetGlobalScopeObject(
    163           debug_info, frame_->fp(), inlined_frame_index_));
    164     case debug::ScopeIterator::ScopeTypeLocal:
    165       return Utils::ToLocal(WasmDebugInfo::GetLocalScopeObject(
    166           debug_info, frame_->fp(), inlined_frame_index_));
    167     default:
    168       return v8::Local<v8::Object>();
    169   }
    170   return v8::Local<v8::Object>();
    171 }
    172 
    173 int DebugWasmScopeIterator::GetScriptId() {
    174   DCHECK(!Done());
    175   return -1;
    176 }
    177 
    178 v8::Local<v8::Value> DebugWasmScopeIterator::GetFunctionDebugName() {
    179   DCHECK(!Done());
    180   return Utils::ToLocal(isolate_->factory()->empty_string());
    181 }
    182 
    183 bool DebugWasmScopeIterator::HasLocationInfo() { return false; }
    184 
    185 debug::Location DebugWasmScopeIterator::GetStartLocation() {
    186   DCHECK(!Done());
    187   return debug::Location();
    188 }
    189 
    190 debug::Location DebugWasmScopeIterator::GetEndLocation() {
    191   DCHECK(!Done());
    192   return debug::Location();
    193 }
    194 
    195 bool DebugWasmScopeIterator::SetVariableValue(v8::Local<v8::String> name,
    196                                               v8::Local<v8::Value> value) {
    197   DCHECK(!Done());
    198   return false;
    199 }
    200 }  // namespace internal
    201 }  // namespace v8
    202