internal void AddToDebugCallStack(CallExpression callExpression) { var identifier = callExpression.Callee as Identifier; if (identifier != null) { var stack = identifier.Name + "("; var paramStrings = new List<string>(); foreach (var argument in callExpression.Arguments) { if (argument != null) { var argIdentifier = argument as Identifier; paramStrings.Add(argIdentifier != null ? argIdentifier.Name : "null"); } else { paramStrings.Add("null"); } } stack += string.Join(", ", paramStrings); stack += ")"; _debugCallStack.Push(stack); } }
private static ExpressionTree<SyntaxNode> GetDefinitionReturnExpression(CallExpression define) { var expr = define?.Arguments.LastOrDefault(); if (expr != null) { return new ExpressionTree<SyntaxNode>(expr); } return null; }
private static bool IsDefineStatement(CallExpression functionExpr) { if (functionExpr.Callee.Type != SyntaxNodes.Identifier) { return false; } var identifier = functionExpr?.Callee.As<Identifier>(); return identifier?.Name == "define"; }
private static void addEmptyArrayArgumentTo(CallExpression call, string script, int argumentIndex, int[] range) { var expression = new ArrayExpression() { Elements = new Expression[0], Location = new Jint.Parser.Location { Source = script, Start = new Jint.Parser.Position { /*TODO*/ }, End = new Jint.Parser.Position { /*TODO*/ } }, Range = range }; call.Arguments.Insert(argumentIndex, expression); }
public CallStackElement(CallExpression callExpression, JsValue function, string shortDescription) { _shortDescription = shortDescription; CallExpression = callExpression; Function = function; }
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; }
public JsValue EvaluateCallExpression(CallExpression callExpression) { var callee = EvaluateExpression(callExpression.Callee); 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; 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); } return callable.Call(thisObject, arguments); }
private void EmitCallExpression(CallExpression e) { bool suppress = false; if(e.Callee is Identifier) { // global function call? var id = e.Callee as Identifier; if(_suppressedglobalfunctions.Contains(id.Name)) { suppress = true; } } if (!suppress) { Emit(e.Callee); EmitFunctionCallArguments(e.Arguments); } else { // skip this call statement. } }
private void ProcessDefineCall(ref RequireCall parentCall, CallExpression callExpression, NodeWithChildren parentNode) { var argCount = callExpression.Arguments.Count(); if (argCount < 1 || argCount > 3) { throw new Exception("Invalid number of arguments for define() call " + relativeFileName); } var defineCall = new RequireCall { Type = RequireCallType.Define, IsModule = true, ParentNode = parentNode }; if (parentCall != null) { parentCall.Children.Add(defineCall); } else { result.RequireCalls.Add(defineCall); } parentCall = defineCall; Expression moduleDefinition = null; Expression depsArray = null; // define('name', [deps], function () {}) if (argCount == 3) { depsArray = callExpression.Arguments.ElementAt(1); moduleDefinition = callExpression.Arguments.ElementAt(2); var identifierLiteral = callExpression.Arguments.ElementAt(0).As<Literal>(); if (identifierLiteral == null) { throw new Exception("The first argument in a define call with 3 arguments was not a string literal." + relativeFileName); } parentCall.ModuleIdentifierNode = identifierLiteral; defineCall.Id = identifierLiteral.Value.ToString(); } // define([deps], function () {}) if (argCount == 2) { depsArray = callExpression.Arguments.ElementAt(0); moduleDefinition = callExpression.Arguments.ElementAt(1); } // define(function () {}) if (argCount == 1) { moduleDefinition = callExpression.Arguments.ElementAt(0); } if (depsArray != null) { defineCall.Dependencies.AddRange(this.ProcessDependencyArray(depsArray, parentCall)); } ProcessModuleDefinition(moduleDefinition, parentCall, parentNode); }
private void ProcessRequireCall(ref RequireCall parentCall, CallExpression callExpression, NodeWithChildren parentNode) { var argCount = callExpression.Arguments.Count(); if (argCount < 1 || argCount > 2) { throw new Exception("Invalid number of arguments for require() call " + relativeFileName); } var requireCall = new RequireCall { Type = RequireCallType.Require, ParentNode = parentNode }; if (parentCall != null) { parentCall.Children.Add(requireCall); } else { result.RequireCalls.Add(requireCall); } parentCall = requireCall; var firstArg = callExpression.Arguments.First(); var secondArg = callExpression.Arguments.Last(); if (argCount == 1) { var singleDep = firstArg.As<Literal>(); if (singleDep != null) { requireCall.SingleDependencyNode = singleDep; requireCall.Dependencies.Add(singleDep.Value.ToString()); } else if (firstArg is ArrayExpression) { var deps = this.ProcessDependencyArray(firstArg, requireCall); requireCall.Dependencies.AddRange(deps); } else { throw new Exception("Could not read argument for require() call " + relativeFileName); } } else if (argCount == 2) { requireCall.IsModule = true; var deps = this.ProcessDependencyArray(firstArg, requireCall); requireCall.Dependencies.AddRange(deps); this.ProcessModuleDefinition(secondArg, parentCall, parentNode); } }
private IList<IScript> GetDirectReferences(string fromModule, CallExpression callExpression, Func<string, IScript> referenceLoader) { var dependencies = GetDependencies(fromModule, callExpression); return dependencies.Select(referenceLoader).ToList(); }
private IEnumerable<string> GetDependencies(string fromModule, CallExpression define) { var referencesExpr = define?.Arguments.FirstOrDefault(a => a.Type == SyntaxNodes.ArrayExpression); return ExtractReferencesFromArgument(fromModule, referencesExpr); }