public JsValue EvaluateCallExpression(CallExpression callExpression) { var callee = EvaluateExpression(callExpression.Callee); if (_engine.Options._IsDebugMode) { _engine.DebugHandler.AddToDebugCallStack(callExpression); } JsValue thisObject; // todo: implement as in http://www.ecma-international.org/ecma-262/5.1/#sec-11.2.4 JsValue[] arguments; if (callExpression.Cached) { arguments = callExpression.CachedArguments; } else { arguments = callExpression.Arguments.Select(EvaluateExpression).Select(_engine.GetValue).ToArray(); if (callExpression.CanBeCached) { // The arguments array can be cached if they are all literals if (callExpression.Arguments.All(x => x is Literal)) { callExpression.CachedArguments = arguments; callExpression.Cached = true; } else { callExpression.CanBeCached = false; } } } var func = _engine.GetValue(callee); var r = callee as Reference; if (_engine.Options._MaxRecursionDepth >= 0) { var stackItem = new CallStackElement(callExpression, func, r != null ? r.GetReferencedName() : "anonymous function"); var recursionDepth = _engine.CallStack.Push(stackItem); if (recursionDepth > _engine.Options._MaxRecursionDepth) { _engine.CallStack.Pop(); throw new RecursionDepthOverflowException(_engine.CallStack, stackItem.ToString()); } } if (func == Undefined.Instance) { throw new JavaScriptException(_engine.TypeError, r == null ? "" : string.Format("Object has no method '{0}'", (callee as Reference).GetReferencedName())); } if (!func.IsObject()) { throw new JavaScriptException(_engine.TypeError, r == null ? "" : string.Format("Property '{0}' of object is not a function", (callee as Reference).GetReferencedName())); } var callable = func.TryCast <ICallable>(); if (callable == null) { throw new JavaScriptException(_engine.TypeError); } if (r != null) { if (r.IsPropertyReference()) { thisObject = r.GetBase(); } else { var env = r.GetBase().TryCast <EnvironmentRecord>(); thisObject = env.ImplicitThisValue(); } } else { thisObject = Undefined.Instance; } // is it a direct call to eval ? http://www.ecma-international.org/ecma-262/5.1/#sec-15.1.2.1.1 if (r != null && r.GetReferencedName() == "eval" && callable is EvalFunctionInstance) { return(((EvalFunctionInstance)callable).Call(thisObject, arguments, true)); } var result = callable.Call(thisObject, arguments); if (_engine.Options._IsDebugMode) { _engine.DebugHandler.PopDebugCallStack(); } if (_engine.Options._MaxRecursionDepth >= 0) { _engine.CallStack.Pop(); } return(result); }
public JsValue EvaluateCallExpression(CallExpression callExpression) { var callee = EvaluateExpression(callExpression.Callee); if (_engine.Options.IsDebugMode()) { _engine.DebugHandler.AddToDebugCallStack(callExpression); } JsValue thisObject; // todo: implement as in http://www.ecma-international.org/ecma-262/5.1/#sec-11.2.4 var arguments = callExpression.Arguments.Select(EvaluateExpression).Select(_engine.GetValue).ToArray(); var func = _engine.GetValue(callee); var r = callee as Reference; var isRecursionHandled = _engine.Options.GetMaxRecursionDepth() >= 0; if (isRecursionHandled) { var stackItem = new CallStackElement(callExpression, func, r != null ? r.GetReferencedName() : "anonymous function"); var recursionDepth = _engine.CallStack.Push(stackItem); if (recursionDepth > _engine.Options.GetMaxRecursionDepth()) { _engine.CallStack.Pop(); throw new RecursionDepthOverflowException(_engine.CallStack, stackItem.ToString()); } } if (func == Undefined.Instance) { throw new JavaScriptException(_engine.TypeError, r == null ? "" : string.Format("Object has no method '{0}'", (callee as Reference).GetReferencedName())); } if (!func.IsObject()) { throw new JavaScriptException(_engine.TypeError, r == null ? "" : string.Format("Property '{0}' of object is not a function", (callee as Reference).GetReferencedName())); } var callable = func.TryCast<ICallable>(); if (callable == null) { throw new JavaScriptException(_engine.TypeError); } if (r != null) { if (r.IsPropertyReference()) { thisObject = r.GetBase(); } else { var env = r.GetBase().TryCast<EnvironmentRecord>(); thisObject = env.ImplicitThisValue(); } } else { thisObject = Undefined.Instance; } // is it a direct call to eval ? http://www.ecma-international.org/ecma-262/5.1/#sec-15.1.2.1.1 if (r != null && r.GetReferencedName() == "eval" && callable is EvalFunctionInstance) { return ((EvalFunctionInstance) callable).Call(thisObject, arguments, true); } var result = callable.Call(thisObject, arguments); if (_engine.Options.IsDebugMode()) { _engine.DebugHandler.PopDebugCallStack(); } if (isRecursionHandled) { _engine.CallStack.Pop(); } return result; }