Rewrite variable and property loading.
authorRobert Sesek <rsesek@bluestatic.org>
Wed, 2 Dec 2015 03:50:53 +0000 (22:50 -0500)
committerRobert Sesek <rsesek@bluestatic.org>
Wed, 2 Dec 2015 03:50:53 +0000 (22:50 -0500)
This removes the -[VariableNode dynamicChildren] hack and replaces it with
controller-driven loading.

English.lproj/Debugger.xib
Source/DebuggerBackEnd.h
Source/DebuggerBackEnd.m
Source/DebuggerController.h
Source/DebuggerController.m
Source/VariableNode.h
Source/VariableNode.m

index 617567664091ada654c2b60eaa1bb59db959311b..a8174ca6b16baba2302dd604065c9d19b60b318a 100644 (file)
                 <binding destination="-2" name="contentArray" keyPath="_model.stack" id="myv-aO-biI"/>
             </connections>
         </arrayController>
-        <treeController objectClassName="VariableNode" editable="NO" childrenKeyPath="dynamicChildren" leafKeyPath="isLeaf" id="59" userLabel="VariablesController">
+        <treeController objectClassName="VariableNode" editable="NO" childrenKeyPath="children" countKeyPath="childCount" leafKeyPath="isLeaf" id="59" userLabel="VariablesController">
             <declaredKeys>
                 <string>value</string>
                 <string>name</string>
index c000a1413618851ff3d981e80ca353d3c59da6ac..08bdf0be5c43955bda3a3a2b0013b5e0d2b129f1 100644 (file)
 // Evaluates a given string in the current execution context.
 - (void)evalScript:(NSString*)str callback:(void (^)(NSString*))callback;
 
-// Gets a property by name from the debugger engine. Properties must be
-// retrieved at a certain stack depth.
-- (void)getChildrenOfProperty:(VariableNode*)property
-                      atDepth:(NSInteger)depth
-                     callback:(void (^)(NSArray*))callback;
-
 // Takes a partially loaded stack frame and fetches the rest of the information.
 - (void)loadStackFrame:(StackFrame*)frame;
 
+// Ensures that a variable node's immediate children are loaded, and fetches
+// any that are not. This is done within the scope of the given stack frame.
+- (void)loadVariableNode:(VariableNode*)variable
+           forStackFrame:(StackFrame*)frame;
+
 @end
 
 // Delegate ////////////////////////////////////////////////////////////////////
index 435d858b264cbb465fe2cc62742903e6838108d1..f9f64cd07e119a8837f240a8e0e3e8516d49992b 100644 (file)
   self.status = @"Stopped";
 }
 
-/**
- * Tells the debugger engine to get a specifc property. This also takes in the NSXMLElement
- * that requested it so that the child can be attached.
- */
-- (void)getChildrenOfProperty:(VariableNode*)property
-                      atDepth:(NSInteger)depth
-                     callback:(void (^)(NSArray*))callback {
-  ProtocolClientMessageHandler handler = ^(NSXMLDocument* message) {
-    /*
-     <response>
-       <property> <!-- this is the one we requested -->
-         <property ... /> <!-- these are what we want -->
-       </property>
-     </repsonse>
-     */
-
-    // Detach all the children so we can insert them into another document.
-    NSXMLElement* parent = (NSXMLElement*)[[message rootElement] childAtIndex:0];
-    NSArray* children = [parent children];
-    [parent setChildren:nil];
-
-    callback(children);
-  };
-  [_client sendCommandWithFormat:@"property_get -d %d -n %@" handler:handler, depth, [property fullName]];
-}
-
 - (void)loadStackFrame:(StackFrame*)frame {
   if (frame.loaded)
     return;
   frame.loaded = YES;
 }
 
+- (void)loadVariableNode:(VariableNode*)variable
+           forStackFrame:(StackFrame*)frame {
+  if (variable.children.count == variable.childCount)
+    return;
+
+  [self loadVariableNode:variable forStackFrame:frame dataPage:0 loadedData:@[]];
+}
+
+- (void)loadVariableNode:(VariableNode*)variable
+           forStackFrame:(StackFrame*)frame
+                dataPage:(unsigned int)dataPage
+              loadedData:(NSArray*)loadedData {
+  ProtocolClientMessageHandler handler = ^(NSXMLDocument* message) {
+    /*
+     <response>
+       <property> <!-- this is the one we requested -->
+         <property ... /> <!-- these are what we want -->
+       </property>
+     </repsonse>
+     */
+
+    // Detach all the children so we can insert them into another document.
+    NSXMLElement* parent = (NSXMLElement*)[[message rootElement] childAtIndex:0];
+    NSArray* children = [parent children];
+    [parent setChildren:nil];
+
+    // Check to see if there are more children to load.
+    NSArray* newLoadedData = [loadedData arrayByAddingObjectsFromArray:children];
+
+    unsigned int totalChildren = [[[parent attributeForName:@"numchildren"] stringValue] integerValue];
+    if ([newLoadedData count] < totalChildren) {
+      [self loadVariableNode:variable
+               forStackFrame:frame
+                    dataPage:dataPage + 1
+                  loadedData:newLoadedData];
+    } else {
+      [variable setChildrenFromXMLChildren:newLoadedData];
+    }
+  };
+  [_client sendCommandWithFormat:@"property_get -d %d -n %@ -p %u" handler:handler, frame.index, variable.fullName, dataPage];
+}
+
 // Breakpoint Management ///////////////////////////////////////////////////////
 #pragma mark Breakpoints
 
index cb8f0365e52aa4fb4042f58583843afee9d8a8d3..352d5481df4b6df8ba45b15ce4482db42b12928e 100644 (file)
@@ -63,6 +63,4 @@
 - (IBAction)stepOver:(id)sender;
 - (IBAction)stop:(id)sender;
 
-- (void)fetchChildProperties:(VariableNode*)node;
-
 @end
index 9de546678461e3f1153981420dd175384e226878..c97dcc1e447c43a4fc255bfceb3058c187e36542 100644 (file)
   [connection stop];
 }
 
-- (void)fetchChildProperties:(VariableNode*)node
-{
-  NSArray* selection = [stackArrayController selectedObjects];
-  if (![selection count])
-    return;
-  assert([selection count] == 1);
-  NSInteger depth = [[selection objectAtIndex:0] index];
-  [connection getChildrenOfProperty:node atDepth:depth callback:^(NSArray* properties) {
-    [node setChildrenFromXMLChildren:properties];
-    [variablesTreeController rearrangeObjects];
-  }];
-}
-
 /**
  * NSTableView delegate method that informs the controller that the stack selection did change and that
  * we should update the source viewer
 {
   NSTreeNode* node = [[notif userInfo] objectForKey:@"NSObject"];
   [expandedVariables addObject:[[node representedObject] fullName]];
+
+  [connection loadVariableNode:[node representedObject]
+                 forStackFrame:[[stackArrayController selectedObjects] lastObject]];
 }
 
 /**
index 7752128612a0d8600cd6fb159dfa5158ff8e36cc..c9d7f4bad7543e3642c37c878aa96ef701604530 100644 (file)
@@ -49,9 +49,6 @@
 // the children on a node from the list of children from the XML response.
 - (void)setChildrenFromXMLChildren:(NSArray*)children;
 
-// Returns the children and requests any unloaded ones.
-- (NSArray*)dynamicChildren;
-
 // Whether or not this is a leaf node (i.e. does not have child properties).
 - (BOOL)isLeaf;
 
index 5e38c07707f4e26b945360a66eb3633b268f45e0..6775747230216d4e7a28bb0350421c056a40e3e4 100644 (file)
@@ -16,7 +16,6 @@
 
 #import "VariableNode.h"
 
-#import "AppDelegate.h"
 #include "NSXMLElementAdditions.h"
 
 // Private Properties //////////////////////////////////////////////////////////
 
 - (void)setChildrenFromXMLChildren:(NSArray*)children
 {
+  [self willChangeValueForKey:@"children"];
+
+  [children_ removeAllObjects];
+
   for (NSXMLNode* child in children) {
     // Other child nodes may be the string value.
     if ([child isKindOfClass:[NSXMLElement class]]) {
       [node release];
     }
   }
-}
 
-- (NSArray*)dynamicChildren
-{
-  NSArray* children = self.children;
-  if (![self isLeaf] && (NSInteger)[children count] < self.childCount) {
-    // If this node has children but they haven't been loaded from the backend,
-    // request them asynchronously.
-    [[AppDelegate instance].debugger fetchChildProperties:self];
-  }
-  return children;
+  [self didChangeValueForKey:@"children"];
 }
 
 - (BOOL)isLeaf