After some resent tests, I found that my implementation cannot handle a lot of recursion. Although, after I conducted several tests in Firefox, I found that this might be more common than I originally thought. I believe the main problem is that my implementation requires 3 calls to call the function. The first call is made using a method with a name Callthat ensures that the call is made to the called object and receives the value of any arguments that are references. The second call is made using a method with a name Callthat is defined in the interfaceICallable. This method creates a new execution context and builds a lambda expression if it was not created. The last call is made for the lambda, which the function object encapsulates. Obviously the function call is pretty heavy, but I'm sure with a little tweaking I can make recursion a viable tool when using this implementation.
public static object Call(ExecutionContext context, object value, object[] args)
{
var func = Reference.GetValue(value) as ICallable;
if (func == null)
{
throw new TypeException();
}
if (args != null && args.Length > 0)
{
for (int i = 0; i < args.Length; i++)
{
args[i] = Reference.GetValue(args[i]);
}
}
var reference = value as Reference;
if (reference != null)
{
if (reference.IsProperty)
{
return func.Call(reference.Value, args);
}
else
{
return func.Call(((EnviromentRecord)reference.Value).ImplicitThisValue(), args);
}
}
return func.Call(Undefined.Value, args);
}
public object Call(object thisObject, object[] arguments)
{
var lexicalEnviroment = Scope.NewDeclarativeEnviroment();
var variableEnviroment = Scope.NewDeclarativeEnviroment();
var thisBinding = thisObject ?? Engine.GlobalEnviroment.GlobalObject;
var newContext = new ExecutionContext(Engine, lexicalEnviroment, variableEnviroment, thisBinding);
Engine.EnterContext(newContext);
var result = Function.Value(newContext, arguments);
Engine.LeaveContext();
return result;
}
source
share