Beispiel #1
0
        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);
 }
Beispiel #5
0
 public CallStackElement(CallExpression callExpression, JsValue function, string shortDescription)
 {
     _shortDescription = shortDescription;
     CallExpression = callExpression;
     Function = function;
 }
Beispiel #6
0
        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;
        }
Beispiel #7
0
        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);
        }