Exemplo n.º 1
0
        /// <summary>
        /// http://www.ecma-international.org/ecma-262/5.1/#sec-12.6.4
        /// </summary>
        /// <param name="forInStatement"></param>
        /// <returns></returns>
        public Completion ExecuteForInStatement(ForInStatement forInStatement)
        {
            Identifier identifier = forInStatement.Left.Type == SyntaxNodes.VariableDeclaration
                                        ? forInStatement.Left.As <VariableDeclaration>().Declarations.First().Id
                                        : forInStatement.Left.As <Identifier>();

            var varRef     = _engine.EvaluateExpression(identifier) as Reference;
            var exprRef    = _engine.EvaluateExpression(forInStatement.Right);
            var experValue = _engine.GetValue(exprRef);

            if (experValue == Undefined.Instance || experValue == Null.Instance)
            {
                return(new Completion(Completion.Normal, null, null));
            }


            var     obj = TypeConverter.ToObject(_engine, experValue);
            JsValue v   = Null.Instance;

            // keys are constructed using the prototype chain
            var cursor        = obj;
            var processedKeys = new HashSet <string>();

            while (cursor != null)
            {
                var keys = _engine.Object.GetOwnPropertyNames(Undefined.Instance, Arguments.From(cursor)).AsArray();

                for (var i = 0; i < keys.GetLength(); i++)
                {
                    var p = keys.GetOwnProperty(i.ToString()).Value.AsString();

                    if (processedKeys.Contains(p))
                    {
                        continue;
                    }

                    processedKeys.Add(p);

                    // collection might be modified by inner statement
                    if (cursor.GetOwnProperty(p) == PropertyDescriptor.Undefined)
                    {
                        continue;
                    }


                    var value = cursor.GetOwnProperty(p);
                    if (!value.Enumerable.HasValue || !value.Enumerable.Value)
                    {
                        continue;
                    }

                    _engine.PutValue(varRef, p);

                    var stmt = ExecuteStatement(forInStatement.Body);
                    if (stmt.Value != null)
                    {
                        v = stmt.Value;
                    }
                    if (stmt.Type == Completion.Break)
                    {
                        return(new Completion(Completion.Normal, v, null));
                    }
                    if (stmt.Type != Completion.Continue)
                    {
                        if (stmt.Type != Completion.Normal)
                        {
                            return(stmt);
                        }
                    }
                }

                cursor = cursor.Prototype;
            }

            return(new Completion(Completion.Normal, v, null));
        }
Exemplo n.º 2
0
        public JsValue EvaluateUnaryExpression(UnaryExpression unaryExpression)
        {
            var       value = _engine.EvaluateExpression(unaryExpression.Argument);
            Reference r;

            switch (unaryExpression.Operator)
            {
            case UnaryOperator.Plus:
                return(TypeConverter.ToNumber(_engine.GetValue(value)));

            case UnaryOperator.Minus:
                var n = TypeConverter.ToNumber(_engine.GetValue(value));
                return(double.IsNaN(n) ? double.NaN : n *-1);

            case UnaryOperator.BitwiseNot:
                return(~TypeConverter.ToInt32(_engine.GetValue(value)));

            case UnaryOperator.LogicalNot:
                return(!TypeConverter.ToBoolean(_engine.GetValue(value)));

            case UnaryOperator.Delete:
                r = value as Reference;
                if (r == null)
                {
                    return(true);
                }
                if (r.IsUnresolvableReference())
                {
                    if (r.IsStrict())
                    {
                        throw new JavaScriptException(_engine.SyntaxError);
                    }

                    return(true);
                }
                if (r.IsPropertyReference())
                {
                    var o = TypeConverter.ToObject(_engine, r.GetBase());
                    return(o.Delete(r.GetReferencedName(), r.IsStrict()));
                }
                if (r.IsStrict())
                {
                    throw new JavaScriptException(_engine.SyntaxError);
                }
                var bindings = r.GetBase().TryCast <EnvironmentRecord>();
                return(bindings.DeleteBinding(r.GetReferencedName()));

            case UnaryOperator.Void:
                _engine.GetValue(value);
                return(Undefined.Instance);

            case UnaryOperator.TypeOf:
                r = value as Reference;
                if (r != null)
                {
                    if (r.IsUnresolvableReference())
                    {
                        return("undefined");
                    }
                }
                var v = _engine.GetValue(value);
                if (v == Undefined.Instance)
                {
                    return("undefined");
                }
                if (v == Null.Instance)
                {
                    return("object");
                }
                switch (v.Type)
                {
                case Types.Boolean: return("boolean");

                case Types.Number: return("number");

                case Types.String: return("string");
                }
                if (v.TryCast <ICallable>() != null)
                {
                    return("function");
                }
                return("object");

            default:
                throw new ArgumentException();
            }
        }