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)); } }
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())); } }
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(); }
/* * * 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)); }
/// <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()); }
/// <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); }
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(); }
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); }
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); }
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)); } }