public override object Call(IObj that, object[] args)
        {
            var len = JsTypeConverter.ToNumber(that.Get("length"));

            if (len == 0.0D)
            {
                that.SetOwnProperty("length", 0.0D);
                return Undefined.Instance;
            }

            object shifted = that.Get(0.0D);
            var d = 1.0D;

            for (; d < len; ++d)
            {
                object val;

                if (that.TryGet(d, out val))
                {
                    that.SetOwnProperty(d - 1.0D, val);
                    that.Delete(d);
                }
                else
                {
                    that.Delete(d - 1.0D);
                }
            }

            that.SetOwnProperty("length", d - 1.0D);
            return shifted;
        }
        public override object Call(IObj that, object[] args)
        {
            var len = JsTypeConverter.ToInt32(that.Get("length"));

            if (len != 0)
            {
                var result = that.Get((double)len - 1);
                that.Delete(len);
                that.Put("length", (double)len - 1);
                return result;
            }

            that.Put("length", (double)len);
            return Undefined.Instance;
        }
        public override object Call(IObj that, object[] args)
        {
            var len = JsTypeConverter.ToNumber(that.Get("length"));
            var vals = new List<object>();
            object val;

            for (var d = 0.0D; d < len; ++d)
            {
                if (that.TryGet(d, out val))
                    vals.Add(val);
            }
            if (!HasArgs(args))
            {
                vals.Sort((a, b) => {
                    var an = JsTypeConverter.ToNumber(JsTypeConverter.ToPrimitive(a));
                    var bn = JsTypeConverter.ToNumber(JsTypeConverter.ToPrimitive(b));
                    return (int)an - (int)bn;
                });
            }
            else
            {
                var func = args[0] as IFunction;
                vals.Sort((a, b) => (int)(double)func.Call(that, new[] { a, b }) );
            }

            for (var d = 0.0D; d < len; ++d)
            {
                if ((int)d < vals.Count)
                {
                    that.SetOwnProperty(d, vals[(int)d]);
                }
                else
                {
                    that.Delete(d);
                }
            }

            return that;
        }
        public override object Call(IObj that, object[] args)
        {
            var len = JsTypeConverter.ToNumber(
                     that.Get("length")
                 );

            var half = Math.Floor(len / 2);

            var begin = 0.0D;
            var end = 0.0D;

            object beginValue;
            object endValue;

            bool hasBegin;
            bool hasEnd;

            while (true)
            {
                if (begin == half)
                    return that;

                end = len - begin - 1;

                hasBegin = that.TryGet(begin, out beginValue);
                hasEnd = that.TryGet(end, out endValue);

                if (!hasEnd)
                {
                    if (!hasBegin)
                    {
                        that.Delete(begin);
                        that.Delete(end);
                    }
                    else
                    {
                        that.SetOwnProperty(end, beginValue);
                        that.Delete(begin);
                    }
                }
                else if (!hasBegin)
                {
                    if (!hasEnd)
                    {
                        that.Delete(begin);
                        that.Delete(end);
                    }
                    else
                    {
                        that.SetOwnProperty(begin, endValue);
                        that.Delete(end);
                    }
                }
                else
                {
                    that.SetOwnProperty(begin, endValue);
                    that.SetOwnProperty(end, beginValue);
                }

                ++begin;
            }
        }