Home | History | Annotate | Download | only in debug
      1 // Copyright 2015 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 #ifndef V8_DEBUG_DEBUG_SCOPES_H_
      6 #define V8_DEBUG_DEBUG_SCOPES_H_
      7 
      8 #include "src/debug/debug-frames.h"
      9 #include "src/frames.h"
     10 
     11 namespace v8 {
     12 namespace internal {
     13 
     14 // Iterate over the actual scopes visible from a stack frame or from a closure.
     15 // The iteration proceeds from the innermost visible nested scope outwards.
     16 // All scopes are backed by an actual context except the local scope,
     17 // which is inserted "artificially" in the context chain.
     18 class ScopeIterator {
     19  public:
     20   enum ScopeType {
     21     ScopeTypeGlobal = 0,
     22     ScopeTypeLocal,
     23     ScopeTypeWith,
     24     ScopeTypeClosure,
     25     ScopeTypeCatch,
     26     ScopeTypeBlock,
     27     ScopeTypeScript,
     28     ScopeTypeEval,
     29     ScopeTypeModule
     30   };
     31 
     32   static const int kScopeDetailsTypeIndex = 0;
     33   static const int kScopeDetailsObjectIndex = 1;
     34   static const int kScopeDetailsNameIndex = 2;
     35   static const int kScopeDetailsStartPositionIndex = 3;
     36   static const int kScopeDetailsEndPositionIndex = 4;
     37   static const int kScopeDetailsFunctionIndex = 5;
     38   static const int kScopeDetailsSize = 6;
     39 
     40   enum Option { DEFAULT, IGNORE_NESTED_SCOPES, COLLECT_NON_LOCALS };
     41 
     42   ScopeIterator(Isolate* isolate, FrameInspector* frame_inspector,
     43                 Option options = DEFAULT);
     44 
     45   ScopeIterator(Isolate* isolate, Handle<JSFunction> function);
     46 
     47   MUST_USE_RESULT MaybeHandle<JSObject> MaterializeScopeDetails();
     48 
     49   // More scopes?
     50   bool Done() {
     51     DCHECK(!failed_);
     52     return context_.is_null();
     53   }
     54 
     55   bool Failed() { return failed_; }
     56 
     57   // Move to the next scope.
     58   void Next();
     59 
     60   // Return the type of the current scope.
     61   ScopeType Type();
     62 
     63   // Return the JavaScript object with the content of the current scope.
     64   MaybeHandle<JSObject> ScopeObject();
     65 
     66   bool HasContext();
     67 
     68   // Set variable value and return true on success.
     69   bool SetVariableValue(Handle<String> variable_name, Handle<Object> new_value);
     70 
     71   Handle<ScopeInfo> CurrentScopeInfo();
     72 
     73   // Return the context for this scope. For the local context there might not
     74   // be an actual context.
     75   Handle<Context> CurrentContext();
     76 
     77   // Populate the set with collected non-local variable names.
     78   Handle<StringSet> GetNonLocals();
     79 
     80 #ifdef DEBUG
     81   // Debug print of the content of the current scope.
     82   void DebugPrint();
     83 #endif
     84 
     85  private:
     86   struct ExtendedScopeInfo {
     87     ExtendedScopeInfo(Handle<ScopeInfo> info, int start, int end)
     88         : scope_info(info), start_position(start), end_position(end) {}
     89     explicit ExtendedScopeInfo(Handle<ScopeInfo> info)
     90         : scope_info(info), start_position(-1), end_position(-1) {}
     91     Handle<ScopeInfo> scope_info;
     92     int start_position;
     93     int end_position;
     94     bool is_hidden() { return start_position == -1 && end_position == -1; }
     95   };
     96 
     97   Isolate* isolate_;
     98   FrameInspector* const frame_inspector_;
     99   Handle<Context> context_;
    100   List<ExtendedScopeInfo> nested_scope_chain_;
    101   Handle<StringSet> non_locals_;
    102   bool seen_script_scope_;
    103   bool failed_;
    104 
    105   inline JavaScriptFrame* GetFrame() {
    106     return frame_inspector_->GetArgumentsFrame();
    107   }
    108 
    109   inline Handle<JSFunction> GetFunction() {
    110     return Handle<JSFunction>::cast(frame_inspector_->GetFunction());
    111   }
    112 
    113   void RetrieveScopeChain(Scope* scope);
    114 
    115   void CollectNonLocals(Scope* scope);
    116 
    117   void UnwrapEvaluationContext();
    118 
    119   MUST_USE_RESULT MaybeHandle<JSObject> MaterializeScriptScope();
    120   MUST_USE_RESULT MaybeHandle<JSObject> MaterializeLocalScope();
    121   MUST_USE_RESULT MaybeHandle<JSObject> MaterializeModuleScope();
    122   Handle<JSObject> MaterializeClosure();
    123   Handle<JSObject> MaterializeCatchScope();
    124   Handle<JSObject> MaterializeInnerScope();
    125   Handle<JSObject> WithContextExtension();
    126 
    127   bool SetLocalVariableValue(Handle<String> variable_name,
    128                              Handle<Object> new_value);
    129   bool SetInnerScopeVariableValue(Handle<String> variable_name,
    130                                   Handle<Object> new_value);
    131   bool SetClosureVariableValue(Handle<String> variable_name,
    132                                Handle<Object> new_value);
    133   bool SetScriptVariableValue(Handle<String> variable_name,
    134                               Handle<Object> new_value);
    135   bool SetCatchVariableValue(Handle<String> variable_name,
    136                              Handle<Object> new_value);
    137 
    138   // Helper functions.
    139   bool SetParameterValue(Handle<ScopeInfo> scope_info, JavaScriptFrame* frame,
    140                          Handle<String> parameter_name,
    141                          Handle<Object> new_value);
    142   bool SetStackVariableValue(Handle<ScopeInfo> scope_info,
    143                              JavaScriptFrame* frame,
    144                              Handle<String> variable_name,
    145                              Handle<Object> new_value);
    146   bool SetContextVariableValue(Handle<ScopeInfo> scope_info,
    147                                Handle<Context> context,
    148                                Handle<String> variable_name,
    149                                Handle<Object> new_value);
    150 
    151   void CopyContextLocalsToScopeObject(Handle<ScopeInfo> scope_info,
    152                                       Handle<Context> context,
    153                                       Handle<JSObject> scope_object);
    154   void CopyContextExtensionToScopeObject(Handle<Context> context,
    155                                          Handle<JSObject> scope_object,
    156                                          KeyCollectionMode mode);
    157 
    158   // Get the chain of nested scopes within this scope for the source statement
    159   // position. The scopes will be added to the list from the outermost scope to
    160   // the innermost scope. Only nested block, catch or with scopes are tracked
    161   // and will be returned, but no inner function scopes.
    162   void GetNestedScopeChain(Isolate* isolate, Scope* scope,
    163                            int statement_position);
    164 
    165   DISALLOW_IMPLICIT_CONSTRUCTORS(ScopeIterator);
    166 };
    167 
    168 }  // namespace internal
    169 }  // namespace v8
    170 
    171 #endif  // V8_DEBUG_DEBUG_SCOPES_H_
    172