/** 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;
using JavaScript.Debugger;
namespace JavaScript
{
/// <summary>
///
/// </summary>
public class JsEngine
{
public JsEngine( JsObject global )
{
global.AddGlobalFunctions();
m_globals.Add( global );
AddGlobalVar( "Object", new JsObject() );
AddGlobalVar( "String", new TypeString("") );
AddGlobalVar( "Array", new TypeArray() );
AddGlobalVar( "Date", new TypeDate() );
AddGlobalVar( "Math", new TypeMath() );
AddGlobalVar( "Number", new TypeNumber() );
AddGlobalVar( "RegExp", new TypeRegExp() );
AddGlobalVar( "Function", new TypeFunctionObject() );
}
public JsEngine( ) : this( new JsObject() )
{
}
public JsObject Eval( string scr )
{
return Eval( scr, 1 );
}
public JsObject Eval( string script, int startline )
{
return Eval(script, null, startline);
//Debug.Assert(0 != startline, "startline is one based");
//Parser parser = new Parser(m_strictParsing);
//ExecList code = parser.Parse(script, startline);
//JsInterp interp = new JsInterp( (JsObject)m_globals[0], code );
//for ( int x = 1; x < m_globals.Count; x++ )
//{
// interp.Context.EnterGlobalContext( (JsObject)m_globals[x] );
//}
//return interp.Run( );
}
public JsObject Eval( string src, JsObject context, int startline )
{
Debug.Assert(0 != startline, "startline is one based");
Parser parser = new Parser(m_strictParsing);
ExecList code = parser.Parse(src, startline);
JsInterp interp = new JsInterp( (JsObject)m_globals[0], code, m_strictTyping );
for ( int x = 1; x < m_globals.Count; x++ )
{
interp.Context.EnterGlobalContext( (JsObject)m_globals[x] );
}
if (context != null)
{
interp.Context.EnterContext(context);
}
if (m_debugger != null)
{
if (m_debugger.Visible)
{
return m_debugger.PushEval(interp);
}
else
{
m_debugger.Dispose();
m_debugger = null;
}
}
try
{
return interp.Run();
}
catch (DebuggerException de)
{
m_debugger = new DebugWindow(this, de);
m_debugger.ShowDialog();
JsObject ret = m_debugger.ReturnValue;
m_debugger.Dispose();
m_debugger = null;
return ret;
}
}
public void Start( string script, int startline )
{
Debug.Assert(0 != startline, "startline is one based");
m_complete = false;
Parser parser = new Parser(m_strictParsing);
ExecList code = parser.Parse( script, startline );
m_interp = new JsInterp( (JsObject)m_globals[0], code, m_strictTyping );
for ( int x = 1; x < m_globals.Count; x++ )
{
m_interp.Context.EnterGlobalContext( (JsObject)m_globals[x] );
}
m_interp.PrepareToRun();
}
public void Step()
{
m_complete = m_interp.Step();
}
public bool Completed()
{
return m_complete;
}
public JsObject ReturnValue
{
get
{
return m_interp.ReturnValue();
}
}
public bool StrictParsing
{
get { return m_strictParsing; }
set { m_strictParsing = value; }
}
public bool StrictTyping
{
get { return m_strictTyping; }
set { m_strictTyping = value; }
}
public bool IsInDebugger
{
get { return m_debugger != null; }
}
public void EndDebugging()
{
if (m_debugger == null)
{
return;
}
m_debugger.EndSession();
}
public JsInterp PrepareInterp(string src, int startline, JsObject context)
{
Debug.Assert(0 != startline, "startline is one based");
Parser parser = new Parser(m_strictParsing);
ExecList code = parser.Parse(src, startline);
JsInterp interp = new JsInterp((JsObject)m_globals[0], code, m_strictTyping);
for (int x = 1; x < m_globals.Count; x++)
{
interp.Context.EnterGlobalContext((JsObject)m_globals[x]);
}
if (context != null)
{
interp.Context.EnterContext(context);
}
return interp;
}
public Command CurrentCommand
{
get
{
return m_interp.DebugGetCurrentCommand();
}
}
public int Position
{
get
{
return m_interp.Position;
}
}
/// <summary>
/// Add the object to the global namespace. Same effect as "var doc = new Whatever();"
/// This allows external programs to define global objects, such as "document" or "window".
/// </summary>
/// <param name="obj"></param>
public void AddGlobalVar( string name, JsObject obj )
{
((JsObject)m_globals[0]).SetProperty( name, obj );
}
public void AddGlobalContext( JsObject ctx )
{
m_globals.Add( ctx );
}
public Stack<object> DebugGetStack()
{
return m_interp.DebugGetStack();
}
public StackFrame DebugGetContext()
{
return m_interp.Context;
}
protected List<JsObject> m_globals = new List<JsObject>();
protected JsInterp m_interp;
protected bool m_complete;
protected bool m_strictParsing = true;
protected bool m_strictTyping = false;
protected DebugWindow m_debugger;
}
public class DebuggerException : Exception
{
//private JsEngine m_engine;
private JsInterp m_interp;
public DebuggerException(/*JsEngine engine, */JsInterp interp)
: base()
{
//m_engine = engine;
m_interp = interp;
}
//public JsEngine JsEngine
//{
// get { return m_engine; }
//}
public JsInterp JsInterp
{
get { return m_interp; }
}
}
}