using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
namespace JavaScript.Debugger
{
public partial class ContextInspector : Form
{
protected DebugWindow m_debugger;
protected Stack<StackFrame> m_frames;
protected TreeNode[] m_roots;
public ContextInspector(DebugWindow debugger, Stack<StackFrame> frames)
{
InitializeComponent();
m_debugger = debugger;
m_frames = frames;
Rebuild();
treeContexts.ExpandAll();
ListStackFrameProps(m_frames.Peek());
}
public void DebuggerStepped()
{
object selected = (treeContexts.SelectedNode == null)? null : treeContexts.SelectedNode.Tag;
bool redisplay = false;
// the debugger has stepped, so check for changes
if (m_roots.Length != m_frames.Count)
{
// a stack frame has been entered
treeContexts.Nodes.Clear();
Rebuild();
redisplay = true;
}
StackFrame[] sframes = m_frames.ToArray();
for (int x = 0; x < m_roots.Length; x++)
{
if (m_roots[x].Nodes.Count != sframes[x].Context.Count)
{
treeContexts.Nodes.Clear();
Rebuild();
redisplay = true;
break;
}
else
{
// properties
for (int y = 0; y < m_roots[x].Nodes.Count; y++)
{
if (m_roots[x].Nodes[y].Nodes.Count != sframes[x].Context[y].Properties.Count)
{
treeContexts.Nodes.Clear();
Rebuild();
redisplay = true;
break;
}
}
}
}
if (redisplay)
{
//treeContexts.ExpandAll();
for (int x = 0; x < treeContexts.Nodes.Count; x++)
{
if (treeContexts.Nodes[x].Tag == selected)
{
treeContexts.SelectedNode = treeContexts.Nodes[x];
break;
}
}
lstProps.Items.Clear();
if (selected is StackFrame)
{
ListStackFrameProps((StackFrame)selected);
}
else if (selected is JsObject)
{
ListContextProps((JsObject)selected);
}
else if (selected is LValue)
{
ListLValProps((LValue)selected);
}
}
}
private void Rebuild()
{
StackFrame[] sframes = m_frames.ToArray();
m_roots = new TreeNode[sframes.Length];
for (int x = 0; x < m_roots.Length; x++)
{
TreeNode node = new TreeNode(sframes[x].ToString(), ContextObjects(sframes[x]));
m_roots[x] = node;
node.Tag = sframes[x];
treeContexts.Nodes.Add(node);
}
}
private TreeNode[] ContextObjects(StackFrame frame)
{
List<TreeNode> nodes = new List<TreeNode>();
ArrayListStack<JsObject> ctx = frame.Context;
for (int x = ctx.Count-1; x > -1; x--)
{
TreeNode node = new TreeNode(ctx[x].TypeName, ContextObjectProperties(ctx[x]));
node.Tag = ctx[x];
nodes.Add(node);
}
return nodes.ToArray();
}
private TreeNode[] ContextObjectProperties(JsObject ctxo)
{
List<LValue> props = ctxo.Properties;
List<TreeNode> nodes = new List<TreeNode>();
foreach (LValue lv in props)
{
TreeNode node = new TreeNode(lv.Name + "=" + lv.Get().Name);
node.Tag = lv;
nodes.Add(node);
}
return nodes.ToArray();
}
private void ListStackFrameProps(StackFrame frame)
{
if (frame.Stack.Count == 0)
{
lstProps.Items.Add("<<STACK EMPTY>>");
return;
}
object[] stk = frame.Stack.ToArray();
for (int x = 0; x < stk.Length; x++)
{
if (stk[x] is LValue)
{
lstProps.Items.Add( stk[x].ToString() );
}
else if (stk[x] is JsObject)
{
lstProps.Items.Add(stk[x].ToString());
}
}
}
private void ListContextProps(JsObject ctx)
{
List<LValue> props = ctx.Properties;
for (int x = 0; x < props.Count; x++)
{
lstProps.Items.Add(props[x].Name + "=" + props[x].Get().ToString());
}
}
private void ListLValProps(LValue lv)
{
List<LValue> props = lv.Get().Properties;
for (int x = 0; x < props.Count; x++)
{
lstProps.Items.Add(props[x].Name + "=" + props[x].Get().ToString());
}
if (lv.Get() is TypeArray)
{
TypeArray arr = (TypeArray)lv.Get();
string[] keys = arr.Keys;
for (int x = 0; x < keys.Length; x++)
{
lstProps.Items.Add(keys[x] + "=" + arr.GetProperty(keys[x]).ToString());
}
}
}
private void treeContexts_AfterSelect(object sender, TreeViewEventArgs e)
{
lstProps.Items.Clear();
if (e.Node.Tag is StackFrame)
{
// stack frame
ListStackFrameProps((StackFrame)e.Node.Tag);
}
else if (e.Node.Tag is JsObject)
{
// context
ListContextProps((JsObject)e.Node.Tag);
}
else if (e.Node.Tag is LValue)
{
// property
ListLValProps((LValue)e.Node.Tag);
}
}
private void ContextInspector_KeyDown(object sender, KeyEventArgs e)
{
m_debugger.DebugWindow_KeyDown(sender, e);
}
}
}