GlobalObject.cs 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. using System;
  2. using System.Globalization;
  3. using Jint.Native.Object;
  4. using Jint.Runtime;
  5. using Jint.Runtime.Descriptors;
  6. using Jint.Runtime.Descriptors.Specialized;
  7. namespace Jint.Native.Global
  8. {
  9. public sealed class GlobalObject : ObjectInstance
  10. {
  11. private readonly Engine _engine;
  12. private GlobalObject(Engine engine, ObjectInstance prototype)
  13. : base(engine, prototype)
  14. {
  15. _engine = engine;
  16. }
  17. public static GlobalObject CreateGlobalObject(Engine engine, ObjectInstance prototype)
  18. {
  19. var global = new GlobalObject(engine, prototype);
  20. // Global object properties
  21. global.DefineOwnProperty("NaN", new DataDescriptor(double.NaN), false);
  22. global.DefineOwnProperty("Infinity", new DataDescriptor(double.PositiveInfinity), false);
  23. global.DefineOwnProperty("undefined", new DataDescriptor(Undefined.Instance), false);
  24. // Global object functions
  25. global.DefineOwnProperty("parseInt", new ClrDataDescriptor<object, object>(engine, ParseInt) { }, false);
  26. global.DefineOwnProperty("parseFloat", new ClrDataDescriptor<object, object>(engine, ParseFloat), false);
  27. global.DefineOwnProperty("isNaN", new ClrDataDescriptor<object, bool>(engine, IsNaN), false);
  28. global.DefineOwnProperty("isFinite", new ClrDataDescriptor<object, bool>(engine, IsFinite), false);
  29. global.DefineOwnProperty("decodeURI", new ClrDataDescriptor<object, string>(engine, DecodeUri), false);
  30. global.DefineOwnProperty("decodeURIComponent", new ClrDataDescriptor<object, string>(engine, DecodeUriComponent), false);
  31. global.DefineOwnProperty("encodeURI", new ClrDataDescriptor<object, string>(engine, EncodeUri), false);
  32. global.DefineOwnProperty("encodeURIComponent", new ClrDataDescriptor<object, string>(engine, EncodeUriComponent), false);
  33. return global;
  34. }
  35. /// <summary>
  36. /// http://www.ecma-international.org/ecma-262/5.1/#sec-15.1.2.2
  37. /// </summary>
  38. public static object ParseInt(object thisObject, object[] arguments)
  39. {
  40. int radix = arguments.Length > 1 ? TypeConverter.ToInt32(arguments[1]) : 10;
  41. object v = arguments[0];
  42. if (radix == 0)
  43. {
  44. radix = 10;
  45. }
  46. if (radix < 2 || radix > 36)
  47. {
  48. return double.NaN;
  49. }
  50. try
  51. {
  52. var s = TypeConverter.ToString(v);
  53. return Convert.ToInt32(s.TrimStart(), radix);
  54. }
  55. catch
  56. {
  57. return double.NaN;
  58. }
  59. }
  60. /// <summary>
  61. /// http://www.ecma-international.org/ecma-262/5.1/#sec-15.1.2.3
  62. /// </summary>
  63. public static object ParseFloat(object thisObject, object[] arguments)
  64. {
  65. object v = arguments[0];
  66. var s = TypeConverter.ToString(v);
  67. double n;
  68. if (double.TryParse(s, NumberStyles.AllowDecimalPoint, CultureInfo.InvariantCulture, out n))
  69. {
  70. return n;
  71. }
  72. return double.NaN;
  73. }
  74. /// <summary>
  75. /// http://www.ecma-international.org/ecma-262/5.1/#sec-15.1.2.4
  76. /// </summary>
  77. public static bool IsNaN(object thisObject, object[] arguments)
  78. {
  79. var x = TypeConverter.ToNumber(arguments[0]);
  80. return double.IsNaN(x);
  81. }
  82. /// <summary>
  83. /// http://www.ecma-international.org/ecma-262/5.1/#sec-15.1.2.5
  84. /// </summary>
  85. public static bool IsFinite(object thisObject, object[] arguments)
  86. {
  87. if (arguments.Length != 1)
  88. {
  89. return false;
  90. }
  91. var n = TypeConverter.ToNumber(arguments[0]);
  92. if (n == double.NaN || n == double.PositiveInfinity || n == double.NegativeInfinity)
  93. {
  94. return false;
  95. }
  96. return true;
  97. }
  98. /// <summary>
  99. /// http://www.ecma-international.org/ecma-262/5.1/#sec-15.1.3.1
  100. /// </summary>
  101. /// <param name="thisObject"></param>
  102. /// <param name="arguments"></param>
  103. /// <returns></returns>
  104. public static string DecodeUri(object thisObject, object[] arguments)
  105. {
  106. if (arguments.Length < 1 || arguments[0] == Undefined.Instance)
  107. {
  108. return "";
  109. }
  110. return Uri.UnescapeDataString(arguments[0].ToString().Replace("+", " "));
  111. }
  112. private static readonly char[] ReservedEncoded = new [] { ';', ',', '/', '?', ':', '@', '&', '=', '+', '$', '#' };
  113. private static readonly char[] ReservedEncodedComponent = new [] { '-', '_', '.', '!', '~', '*', '\'', '(', ')', '[', ']' };
  114. /// <summary>
  115. /// http://www.ecma-international.org/ecma-262/5.1/#sec-15.1.3.2
  116. /// </summary>
  117. /// <param name="thisObject"></param>
  118. /// <param name="arguments"></param>
  119. /// <returns></returns>
  120. public static string EncodeUri(object thisObject, object[] arguments)
  121. {
  122. if (arguments.Length < 1 || arguments[0] == Undefined.Instance)
  123. {
  124. return "";
  125. }
  126. string encoded = Uri.EscapeDataString(arguments[0].ToString());
  127. foreach (char c in ReservedEncoded)
  128. {
  129. encoded = encoded.Replace(Uri.EscapeDataString(c.ToString()), c.ToString());
  130. }
  131. foreach (char c in ReservedEncodedComponent)
  132. {
  133. encoded = encoded.Replace(Uri.EscapeDataString(c.ToString()), c.ToString());
  134. }
  135. return encoded.ToUpper();
  136. }
  137. /// <summary>
  138. /// http://www.ecma-international.org/ecma-262/5.1/#sec-15.1.3.3
  139. /// </summary>
  140. /// <param name="thisObject"></param>
  141. /// <param name="arguments"></param>
  142. /// <returns></returns>
  143. public static string DecodeUriComponent(object thisObject, object[] arguments)
  144. {
  145. if (arguments.Length < 1 || arguments[0] == Undefined.Instance)
  146. {
  147. return "";
  148. }
  149. return Uri.UnescapeDataString(arguments[0].ToString().Replace("+", " "));
  150. }
  151. /// <summary>
  152. /// http://www.ecma-international.org/ecma-262/5.1/#sec-15.1.3.4
  153. /// </summary>
  154. /// <param name="thisObject"></param>
  155. /// <param name="arguments"></param>
  156. /// <returns></returns>
  157. public static string EncodeUriComponent(object thisObject, object[] arguments)
  158. {
  159. if (arguments.Length < 1 || arguments[0] == Undefined.Instance)
  160. {
  161. return "";
  162. }
  163. string encoded = Uri.EscapeDataString(arguments[0].ToString());
  164. foreach (char c in ReservedEncodedComponent)
  165. {
  166. encoded = encoded.Replace(Uri.EscapeDataString(c.ToString()), c.ToString().ToUpper());
  167. }
  168. return encoded;
  169. }
  170. }
  171. }