Пример #1
0
        public override object ExecIdCall(IdFunctionObject f, Context cx, IScriptable scope, IScriptable thisObj, object [] args)
        {
            if (!f.HasTag(NUMBER_TAG))
            {
                return(base.ExecIdCall(f, cx, scope, thisObj, args));
            }
            int id = f.MethodId;

            if (id == Id_constructor)
            {
                double val = (args.Length >= 1) ? ScriptConvert.ToNumber(args [0]) : 0.0;
                if (thisObj == null)
                {
                    // new Number(val) creates a new Number object.
                    return(new BuiltinNumber(val));
                }
                // Number(val) converts val to a number value.
                return(val);
            }

            // The rest of Number.prototype methods require thisObj to be Number
            BuiltinNumber nativeNumber = (thisObj as BuiltinNumber);

            if (nativeNumber == null)
            {
                throw IncompatibleCallError(f);
            }
            double value = nativeNumber.doubleValue;

            switch (id)
            {
            case Id_toLocaleString:
            case Id_toString:
                return(ImplToString(value, args));

            case Id_toSource:
                return("(new Number(" + ScriptConvert.ToString(value) + "))");


            case Id_valueOf:
                return(value);


            case Id_toFixed:
                return(ImplToFixed(value, args));


            case Id_toExponential:
                return(ImplToExponential(value, args));


            case Id_toPrecision:
                return(ImplToPrecision(value, args));

            default:
                throw new ArgumentException(Convert.ToString(id));
            }
        }
Пример #2
0
 private static double toDouble(System.Object value)
 {
     if (value is System.ValueType)
     {
         return(Convert.ToDouble(value));
     }
     else if (value is System.String)
     {
         return(ScriptConvert.ToNumber((System.String)value));
     }
     else if (value is IScriptable)
     {
         if (value is Wrapper)
         {
             // TODO: optimize tail-recursion?
             return(toDouble(((Wrapper)value).Unwrap()));
         }
         else
         {
             return(ScriptConvert.ToNumber(value));
         }
     }
     else
     {
         System.Reflection.MethodInfo meth;
         try {
             meth = value.GetType().GetMethod("doubleValue", new System.Type [0]);
         }
         catch (System.MethodAccessException) {
             meth = null;
         }
         catch (System.Security.SecurityException) {
             meth = null;
         }
         if (meth != null)
         {
             try {
                 return(Convert.ToDouble(meth.Invoke(value, (System.Object [])null)));
             }
             catch (System.UnauthorizedAccessException) {
                 // TODO: ignore, or error message?
                 reportConversionError(value, typeof(double));
             }
             catch (System.Reflection.TargetInvocationException) {
                 // TODO: ignore, or error message?
                 reportConversionError(value, typeof(double));
             }
         }
         return(ScriptConvert.ToNumber(value.ToString()));
     }
 }
Пример #3
0
        public override object ExecIdCall(IdFunctionObject f, Context cx, IScriptable scope, IScriptable thisObj, object [] args)
        {
            int id = f.MethodId;

            switch (id)
            {
            case Id_print:
                for (int i = 0; i < args.Length; i++)
                {
                    if (i > 0)
                    {
                        Console.Out.Write(" ");
                    }
                    Console.Out.Write(ScriptConvert.ToString(args [i]));
                }
                Console.Out.WriteLine();
                return(Undefined.Value);

            case Id_version:
                if (args.Length > 0)
                {
                    if (CliHelper.IsNumber(args [0]))
                    {
                        int newVer = (int)ScriptConvert.ToNumber(args [0]);
                        if (Context.IsValidLanguageVersion(newVer))
                        {
                            cx.Version = Context.ToValidLanguageVersion(newVer);
                        }
                    }
                }
                return((int)cx.Version);

            case Id_options:
                StringBuilder sb = new StringBuilder();
                if (cx.HasFeature(Context.Features.Strict))
                {
                    sb.Append("strict");
                }
                return(sb.ToString());

            case Id_gc:
                GC.Collect();
                return(Undefined.Value);
            }
            throw f.Unknown();
        }
Пример #4
0
        /*
         *
         * See ECMA 15.5.4.7
         *
         */
        private static int js_lastIndexOf(string target, object [] args)
        {
            string search = ScriptConvert.ToString(args, 0);
            double end    = ScriptConvert.ToNumber(args, 1);

            if (double.IsNaN(end) || end > target.Length)
            {
                end = target.Length;
            }
            else if (end < 0)
            {
                end = 0;
            }

            return(lastIndexOf(
                       target.ToCharArray(), 0, target.Length, search.ToCharArray(), 0, search.Length, (int)end));
        }
Пример #5
0
        /// <summary> The global method escape, as per ECMA-262 15.1.2.4.
        /// Includes code for the 'mask' argument supported by the C escape
        /// method, which used to be part of the browser imbedding.  Blame
        /// for the strange constant names should be directed there.
        /// </summary>

        private object js_escape(object [] args)
        {
            const int URL_XALPHAS  = 1;
            const int URL_XPALPHAS = 2;
            const int URL_PATH     = 4;

            string s = ScriptConvert.ToString(args, 0);

            int mask = URL_XALPHAS | URL_XPALPHAS | URL_PATH;

            if (args.Length > 1)
            {
                // the 'mask' argument.  Non-ECMA.
                double d = ScriptConvert.ToNumber(args [1]);
                if (double.IsNaN(d) || ((mask = (int)d) != d) || 0 != (mask & ~(URL_XALPHAS | URL_XPALPHAS | URL_PATH)))
                {
                    throw Context.ReportRuntimeErrorById("msg.bad.esc.mask");
                }
            }

            System.Text.StringBuilder sb = null;
            for (int k = 0, L = s.Length; k != L; ++k)
            {
                int c = s [k];
                if (mask != 0 && ((c >= '0' && c <= '9') || (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || c == '@' || c == '*' || c == '_' || c == '-' || c == '.' || (0 != (mask & URL_PATH) && (c == '/' || c == '+'))))
                {
                    if (sb != null)
                    {
                        sb.Append((char)c);
                    }
                }
                else
                {
                    if (sb == null)
                    {
                        sb = new System.Text.StringBuilder(L + 3);
                        sb.Append(s);
                        sb.Length = k;
                    }

                    int hexSize;
                    if (c < 256)
                    {
                        if (c == ' ' && mask == URL_XPALPHAS)
                        {
                            sb.Append('+');
                            continue;
                        }
                        sb.Append('%');
                        hexSize = 2;
                    }
                    else
                    {
                        sb.Append('%');
                        sb.Append('u');
                        hexSize = 4;
                    }

                    // append hexadecimal form of c left-padded with 0
                    for (int shift = (hexSize - 1) * 4; shift >= 0; shift -= 4)
                    {
                        int digit = 0xf & (c >> shift);
                        int hc    = (digit < 10) ? '0' + digit : 'A' - 10 + digit;
                        sb.Append((char)hc);
                    }
                }
            }

            return((sb == null) ? s : sb.ToString());
        }
Пример #6
0
        /// <summary> The global method parseInt, as per ECMA-262 15.1.2.2.</summary>
        private object js_parseInt(object [] args)
        {
            string s     = ScriptConvert.ToString(args, 0);
            int    radix = ScriptConvert.ToInt32(args, 1);

            int len = s.Length;

            if (len == 0)
            {
                return(double.NaN);
            }

            bool negative = false;
            int  start    = 0;
            char c;

            do
            {
                c = s [start];
                if (!char.IsWhiteSpace(c))
                {
                    break;
                }
                start++;
            }while (start < len);

            if (c == '+' || (negative = (c == '-')))
            {
                start++;
            }

            const int NO_RADIX = -1;

            if (radix == 0)
            {
                radix = NO_RADIX;
            }
            else if (radix < 2 || radix > 36)
            {
                return(double.NaN);
            }
            else if (radix == 16 && len - start > 1 && s [start] == '0')
            {
                c = s [start + 1];
                if (c == 'x' || c == 'X')
                {
                    start += 2;
                }
            }

            if (radix == NO_RADIX)
            {
                radix = 10;
                if (len - start > 1 && s [start] == '0')
                {
                    c = s [start + 1];
                    if (c == 'x' || c == 'X')
                    {
                        radix  = 16;
                        start += 2;
                    }
                    else if ('0' <= c && c <= '9')
                    {
                        radix = 8;
                        start++;
                    }
                }
            }

            double d = ScriptConvert.ToNumber(s, start, radix);

            return(negative ? -d : d);
        }
Пример #7
0
        public virtual object ExecIdCall(IdFunctionObject f, Context cx, IScriptable scope, IScriptable thisObj, object [] args)
        {
            if (f.HasTag(FTAG))
            {
                int methodId = f.MethodId;
                switch (methodId)
                {
                case Id_decodeURI:
                case Id_decodeURIComponent: {
                    string str = ScriptConvert.ToString(args, 0);
                    return(decode(str, methodId == Id_decodeURI));
                }


                case Id_encodeURI:
                case Id_encodeURIComponent: {
                    string str = ScriptConvert.ToString(args, 0);
                    return(encode(str, methodId == Id_encodeURI));
                }


                case Id_escape:
                    return(js_escape(args));


                case Id_eval:
                    return(ImplEval(cx, scope, thisObj, args));


                case Id_isFinite: {
                    bool result;
                    if (args.Length < 1)
                    {
                        result = false;
                    }
                    else
                    {
                        double d = ScriptConvert.ToNumber(args [0]);
                        result = (!double.IsNaN(d) && d != System.Double.PositiveInfinity && d != System.Double.NegativeInfinity);
                    }
                    return(result);
                }


                case Id_isNaN: {
                    // The global method isNaN, as per ECMA-262 15.1.2.6.
                    bool result;
                    if (args.Length < 1)
                    {
                        result = true;
                    }
                    else
                    {
                        double d = ScriptConvert.ToNumber(args [0]);
                        result = (double.IsNaN(d));
                    }
                    return(result);
                }


                case Id_isXMLName: {
                    object name   = (args.Length == 0) ? Undefined.Value : args [0];
                    XMLLib xmlLib = XMLLib.ExtractFromScope(scope);
                    return(xmlLib.IsXMLName(cx, name));
                }


                case Id_parseFloat:
                    return(js_parseFloat(args));


                case Id_parseInt:
                    return(js_parseInt(args));


                case Id_unescape:
                    return(js_unescape(args));


                case Id_uneval: {
                    object value = (args.Length != 0) ? args [0] : Undefined.Value;
                    return(ScriptRuntime.uneval(cx, scope, value));
                }


                case Id_new_CommonError:
                    // The implementation of all the ECMA error constructors
                    // (SyntaxError, TypeError, etc.)
                    return(BuiltinError.make(cx, scope, f, args));
                }
            }
            throw f.Unknown();
        }
Пример #8
0
        internal static XMLName Parse(XMLLib lib, Context cx, Object value)
        {
            XMLName result;

            if (value is XMLName)
            {
                result = (XMLName)value;
            }
            else if (value is String)
            {
                String str  = (String)value;
                long   test = ScriptRuntime.testUint32String(str);
                if (test >= 0)
                {
                    ScriptRuntime.storeUint32Result(cx, test);
                    result = null;
                }
                else
                {
                    result = Parse(lib, cx, str);
                }
            }
            else if (CliHelper.IsNumber(value))
            {
                double d = ScriptConvert.ToNumber(value);
                long   l = (long)d;
                if (l == d && 0 <= l && l <= 0xFFFFFFFFL)
                {
                    ScriptRuntime.storeUint32Result(cx, l);
                    result = null;
                }
                else
                {
                    throw XMLLib.BadXMLName(value);
                }
            }
            else if (value is QName)
            {
                QName  qname  = (QName)value;
                String uri    = qname.Uri;
                bool   number = false;
                result = null;
                if (uri != null && uri.Length == 0)
                {
                    // Only in this case qname.toString() can resemble uint32
                    long test = ScriptRuntime.testUint32String(uri);
                    if (test >= 0)
                    {
                        ScriptRuntime.storeUint32Result(cx, test);
                        number = true;
                    }
                }
                if (!number)
                {
                    result = XMLName.FormProperty(uri, qname.LocalName);
                }
            }
            else if (value is Boolean ||
                     value == Undefined.Value ||
                     value == null)
            {
                throw XMLLib.BadXMLName(value);
            }
            else
            {
                String str  = ScriptConvert.ToString(value);
                long   test = ScriptRuntime.testUint32String(str);
                if (test >= 0)
                {
                    ScriptRuntime.storeUint32Result(cx, test);
                    result = null;
                }
                else
                {
                    result = Parse(lib, cx, str);
                }
            }

            return(result);
        }
Пример #9
0
        public override object ExecIdCall(IdFunctionObject f, Context cx, IScriptable scope, IScriptable thisObj, object [] args)
        {
            if (!f.HasTag(MATH_TAG))
            {
                return(base.ExecIdCall(f, cx, scope, thisObj, args));
            }
            double x, y;
            int    methodId = f.MethodId;

            switch (methodId)
            {
            case Id_toSource:
                return("Math");


            case Id_abs:
                x = ScriptConvert.ToNumber(args, 0);
                // abs(-0.0) should be 0.0, but -0.0 < 0.0 == false
                x = (x == 0.0) ? 0.0 : ((x < 0.0) ? -x : x);
                break;


            case Id_acos:
            case Id_asin:
                x = ScriptConvert.ToNumber(args, 0);
                if (!double.IsNaN(x) && -1.0 <= x && x <= 1.0)
                {
                    x = (methodId == Id_acos) ? Math.Acos(x) : Math.Asin(x);
                }
                else
                {
                    x = System.Double.NaN;
                }
                break;


            case Id_atan:
                x = ScriptConvert.ToNumber(args, 0);
                x = Math.Atan(x);
                break;


            case Id_atan2:
                x = ScriptConvert.ToNumber(args, 0);
                y = ScriptConvert.ToNumber(args, 1);
                if (x == double.PositiveInfinity && y == double.PositiveInfinity)
                {
                    x = NET_WORKAROUND_3;
                }
                else if (x == double.PositiveInfinity && y == double.NegativeInfinity)
                {
                    x = NET_WORKAROUND_1;
                }
                else if (x == double.NegativeInfinity && y == double.PositiveInfinity)
                {
                    x = NET_WORKAROUND_4;
                }
                else if (x == double.NegativeInfinity && y == double.NegativeInfinity)
                {
                    x = NET_WORKAROUND_2;
                }
                else
                {
                    x = Math.Atan2(x, y);
                }
                break;


            case Id_ceil:
                x = ScriptConvert.ToNumber(args, 0);
                x = Math.Ceiling(x);
                break;


            case Id_cos:
                x = ScriptConvert.ToNumber(args, 0);
                x = (x == System.Double.PositiveInfinity || x == System.Double.NegativeInfinity) ? System.Double.NaN : Math.Cos(x);
                break;


            case Id_exp:
                x = ScriptConvert.ToNumber(args, 0);
                x = (x == System.Double.PositiveInfinity) ? x : ((x == System.Double.NegativeInfinity) ? 0.0 : Math.Exp(x));
                break;


            case Id_floor:
                x = ScriptConvert.ToNumber(args, 0);
                x = Math.Floor(x);
                break;


            case Id_log:
                x = ScriptConvert.ToNumber(args, 0);
                // Java's log(<0) = -Infinity; we need NaN
                x = (x < 0) ? System.Double.NaN : Math.Log(x);
                break;


            case Id_max:
            case Id_min:
                x = (methodId == Id_max) ? System.Double.NegativeInfinity : System.Double.PositiveInfinity;
                for (int i = 0; i != args.Length; ++i)
                {
                    double d = ScriptConvert.ToNumber(args [i]);
                    if (double.IsNaN(d))
                    {
                        x = d;     // NaN
                        break;
                    }
                    if (methodId == Id_max)
                    {
                        // if (x < d) x = d; does not work due to -0.0 >= +0.0
                        x = Math.Max(x, d);
                    }
                    else
                    {
                        x = Math.Min(x, d);
                    }
                }
                break;


            case Id_pow:
                x = ScriptConvert.ToNumber(args, 0);
                x = ImplPow(x, ScriptConvert.ToNumber(args, 1));
                break;


            case Id_random:
                x = (new Random()).NextDouble();
                break;


            case Id_round:
                x = ScriptConvert.ToNumber(args, 0);
                if (!double.IsNaN(x) && x != System.Double.PositiveInfinity && x != System.Double.NegativeInfinity)
                {
                    long l = (long)Math.Floor(x + 0.5);
                    if (l != 0)
                    {
                        x = l;
                    }
                    else
                    {
                        // We must propagate the sign of d into the result
                        if (x < 0.0)
                        {
                            x = BuiltinNumber.NegativeZero;
                        }
                        else if (x != 0.0)
                        {
                            x = 0.0;
                        }
                    }
                }
                break;


            case Id_sin:
                x = ScriptConvert.ToNumber(args, 0);
                x = (x == System.Double.PositiveInfinity || x == System.Double.NegativeInfinity) ? System.Double.NaN : Math.Sin(x);
                break;


            case Id_sqrt:
                x = ScriptConvert.ToNumber(args, 0);
                x = Math.Sqrt(x);
                break;


            case Id_tan:
                x = ScriptConvert.ToNumber(args, 0);
                x = Math.Tan(x);
                break;


            default:
                throw new ApplicationException(Convert.ToString(methodId));
            }
            return(x);
        }
Пример #10
0
        public override object ExecIdCall(IdFunctionObject f, Context cx, IScriptable scope, IScriptable thisObj, object [] args)
        {
            if (!f.HasTag(NUMBER_TAG))
            {
                return(base.ExecIdCall(f, cx, scope, thisObj, args));
            }
            int id = f.MethodId;

            if (id == Id_constructor)
            {
                double val = (args.Length >= 1) ? ScriptConvert.ToNumber(args [0]) : 0.0;
                if (thisObj == null)
                {
                    // new Number(val) creates a new Number object.
                    return(new BuiltinNumber(val));
                }
                // Number(val) converts val to a number value.
                return(val);
            }

            // The rest of Number.prototype methods require thisObj to be Number
            BuiltinNumber nativeNumber = (thisObj as BuiltinNumber);

            if (nativeNumber == null)
            {
                throw IncompatibleCallError(f);
            }
            double value = nativeNumber.doubleValue;

            int toBase = 0;

            switch (id)
            {
            case Id_toString:
                toBase = (args.Length == 0) ? 10 : ScriptConvert.ToInt32(args [0]);
                return(ScriptConvert.ToString(value, toBase));

            case Id_toLocaleString: {
                // toLocaleString is just an alias for toString for now
                toBase = (args.Length == 0) ? 10 : ScriptConvert.ToInt32(args [0]);
                return(ScriptConvert.ToString(value, toBase));
            }


            case Id_toSource:
                return("(new Number(" + ScriptConvert.ToString(value) + "))");


            case Id_valueOf:
                return(value);


            case Id_toFixed:
                return(num_to(value, args, DTOSTR_FIXED, DTOSTR_FIXED, -20, 0));


            case Id_toExponential:
                return(num_to(value, args, DTOSTR_STANDARD_EXPONENTIAL, DTOSTR_EXPONENTIAL, 0, 1));


            case Id_toPrecision: {
                if (args.Length < 0 || args [0] == Undefined.Value)
                {
                    return(ScriptConvert.ToString(value));
                }
                int precision = ScriptConvert.ToInt32(args [0]);
                if (precision < 0 || precision > MAX_PRECISION)
                {
                    throw ScriptRuntime.ConstructError("RangeError",
                                                       ScriptRuntime.GetMessage("msg.bad.precision", ScriptConvert.ToString(args [0])));
                }
                return(value.ToString(GetFormatString(precision)));
            }


            default:
                throw new ArgumentException(Convert.ToString(id));
            }
        }