/** JavaScript -- DOT NET Javascript Library
* Copyright (C) 2005 John Garrison
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
using System;
using System.Collections.Generic;
using System.Diagnostics;
namespace JavaScript
{
public class StackFrame
{
public StackFrame(Stack<StackFrame> outercontext, JsObject global)
{
m_outercontext = outercontext;
EnterGlobalContext( global );
}
public StackFrame(Stack<StackFrame> outercontext, StackFrame stk, TypeFunction fn)
{
m_outercontext = outercontext;
m_fn = fn;
while ( m_globalCount < stk.m_globalCount )
{
EnterGlobalContext( (JsObject)stk.m_context[m_globalCount] );
}
}
public Stack<object> Stack
{
get
{
return m_stack;
}
}
public int Count
{
get
{
return m_context.Count;
}
}
public JsObject Current
{
get
{
return (JsObject)m_context.Peek();
}
}
public Stack<StackFrame> OuterContext
{
get { return m_outercontext; }
}
public void EnterGlobalContext( JsObject ctx )
{
m_context.Push( ctx );
m_globalCount++;
}
public void EnterContext( JsObject ctx )
{
Debug.Assert(null != ctx);
m_context.Push( ctx );
}
public void LeaveContext( )
{
m_context.Pop();
}
public void LeaveStackFrame()
{
}
public void Mark()
{
m_marks.Push( (Int32)m_context.Count );
}
public void UnMark()
{
if ( m_marks.Count == 0 )
{
return;
}
int mark = (Int32)m_marks.Pop();
while ( m_context.Count > mark )
{
m_context.Pop();
}
}
public JsObject This
{
get
{
//for (int x = m_context.Count - 1; x >= 0; x--)
//{
// if (m_context[x].IsThis)
// {
// return m_context[x];
// }
//}
//// return the global context
//return m_context[0];
if (m_context.Count == 1)
{
// return the global context
return m_context[0];
}
if (m_context.Count == 2)
{
return m_context[1];
}
//return m_context[m_context.Count-2];
return m_context[m_globalCount];
}
}
public bool IsInObjectContext
{
get
{
return m_context.Count > 1;
}
}
protected LValue FindProp( string name )
{
bool foundUndefined = false;
LValue undefinedLValue = null;
for ( int x = Count-1; x >= 0; x-- )
{
JsObject obj = (JsObject)m_context[x];
Debug.Assert(obj != null);
LValue lvalue = obj.GetPropertyLValueNoCreate( name );
if ( lvalue != null )
{
if (lvalue.Get() == TypeUndefined.Instance)
{
foundUndefined = true;
undefinedLValue = lvalue;
}
else
{
return lvalue;
}
}
}
if (foundUndefined)
{
return undefinedLValue;
}
LValue lval = Current.GetPropertyLValueNoCreate("prototype");
if (null != lval)
{
JsObject prototype = lval.Get();
if (null != (lval = prototype.GetPropertyLValueNoCreate(name)))
{
return lval;
}
}
return null;
}
public LValue NewLValue(string name)
{
Current.CreateProperty(name, TypeUndefined.Instance);
Debug.Assert(null != Current.GetPropertyLValue(name));
return Current.GetPropertyLValue(name);
}
public bool LValueExists(string name)
{
return FindProp(name) != null;
}
public LValue LValue(string name)
{
LValue lvalue;
if (m_fn != null)
{
if (null != (lvalue = m_fn.GetPropertyLValueNoCreate(name)))
{
return lvalue;
}
}
lvalue = FindProp(name);
if ( lvalue == null )
{
///Current.CreateProperty(name, TypeUndefined.Instance);
This.CreateProperty( name, TypeUndefined.Instance );
lvalue = This.GetPropertyLValue( name );
}
Debug.Assert(null != lvalue);
return lvalue;
}
public JsObject RValue( string name )
{
LValue lvalue = FindProp( name );
if ( lvalue == null )
{
throw new ParseError( "Undefined variable " + name );
}
else
{
return lvalue.Get();
}
}
public JsObject Global
{
get { return (JsObject)m_context[0]; }
}
public ArrayListStack<JsObject> Context
{
get { return m_context; }
}
public TypeFunction Function
{
get { return m_fn; }
}
public object[] ToArray()
{
return m_context.ToArray();
}
protected ArrayListStack<JsObject> m_context = new ArrayListStack<JsObject>();
protected Stack<int> m_marks = new Stack<int>();
protected Stack<object> m_stack = new Stack<object>();
protected int m_globalCount;
protected Stack<StackFrame> m_outercontext;
protected TypeFunction m_fn;
}
}