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)
        {
            if (!(that is RegExpObj))
                throw new ShouldThrowTypeError();

            if (!HasArgs(args))
                throw new ArgumentException();

            var regexp = that as RegExpObj;
            var str = JsTypeConverter.ToString(args[0]);
            var length = str.Length;
            var lastIndex = JsTypeConverter.ToInt32(that.Get("lastIndex"));
            var global = JsTypeConverter.ToBoolean(that.Get("global"));

            if (global)
                lastIndex = 0;

            if (lastIndex < 0 || lastIndex > length)
            {
                lastIndex = 0;
                return null;
            }

            var match = regexp.Match.Match(str, lastIndex);

            if (!match.Success)
            {
                lastIndex = 0;
                return null;
            }

            int n = match.Groups.Count;
            int e = match.Index + match.Length;

            if (global)
                lastIndex = e;

            var resultArray = Context.ArrayConstructor.Construct();
            resultArray.SetOwnProperty("index", match.Index);
            resultArray.SetOwnProperty("input", str);
            resultArray.SetOwnProperty("length", n);

            var d = 0.0D;
            foreach (Group group in match.Groups)
                resultArray.SetOwnProperty(d++, group.Value);

            return resultArray;
        }
        public override object Call(IObj that, object[] args)
        {
            if (!(that is RegExpObj))
                throw new ShouldThrowTypeError();

            return (that.Get("exec") as IFunction).Call(that, args) != null;
        }
        public override object Call(IObj that, object[] args)
        {
            if(!HasArgs(args, 1))
                throw new NotImplementedException();

            var newArray = Context.ArrayConstructor.Construct();
            var len = JsTypeConverter.ToNumber(that.Get("length"));
            var start = JsTypeConverter.ToNumber(args[0]);

            var ks = (start < 0.0)
                    ? Math.Max(len + start, 0.0D)
                    : Math.Min(start, len);

            var end = args.Length > 1 ? JsTypeConverter.ToNumber(args[1]) : len;

            var ke = (end < 0.0)
                     ? Math.Max(len + end, 0.0D)
                     : Math.Min(end, len);

            var n = 0.0D;
            object val;

            while(ks < ke)
            {
                if (that.TryGet(ks, out val))
                    newArray.SetOwnProperty(n, val);

                ++ks;
                ++n;
            }

            return newArray;
        }
        public override object Call(IObj that, object[] args)
        {
            var n = (double) JsTypeConverter.ToInt32(that.Get("length"));

            foreach (var arg in args)
                that.Put(n++, arg);

            return n;
        }
        public override object Call(IObj that, object[] args)
        {
            // 15.4.4.5
            string sep;

            if (HasArgs(args))
            {
                if (args[0] is Undefined)
                {
                    sep = ",";
                }
                else
                {
                    sep = JsTypeConverter.ToString(args[0]);
                }
            }
            else
            {
                sep = ",";
            }

            var length = JsTypeConverter.ToInt32(that.Get("length"));

            if (length == 0)
                return "";

            var sb = new StringBuilder();

            for (var i = 0.0D; i < (double)length; ++i)
            {
                var val = that.Get(i);
                sb.Append(sep);

                if (!(val is Undefined))
                    sb.Append(JsTypeConverter.ToString(val));
            }

            if (sep.Length > 0)
                return sb.ToString().Substring(sep.Length, sb.Length - sep.Length);

            return sb.ToString();
        }
        public override object Call(IObj that, object[] args)
        {
            if (!(that is RegExpObj))
                throw new ShouldThrowTypeError();

            var regExpObj = that as RegExpObj;
            var multiline = JsTypeConverter.ToBoolean(regExpObj.Get("multiline"));
            var global = JsTypeConverter.ToBoolean(regExpObj.Get("global"));
            var ignoreCase = JsTypeConverter.ToBoolean(regExpObj.Get("ignoreCase"));

            return "/" + JsTypeConverter.ToString(that.Get("source")) + "/" +
                    (multiline ? "m" : "") +
                    (global ? "g" : "") +
                    (ignoreCase ? "i" : "");
        }
        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;
            }
        }
 public override object Call(IObj that, object[] args)
 {
     return (that.Get("toString") as IFunction).Call(that, args);
 }