ObjectPrototype.cs 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. using Jint.Collections;
  2. using Jint.Native.Symbol;
  3. using Jint.Runtime;
  4. using Jint.Runtime.Descriptors;
  5. using Jint.Runtime.Interop;
  6. namespace Jint.Native.Object
  7. {
  8. public sealed class ObjectPrototype : ObjectInstance
  9. {
  10. private ObjectConstructor _objectConstructor;
  11. private ObjectPrototype(Engine engine) : base(engine)
  12. {
  13. }
  14. public static ObjectPrototype CreatePrototypeObject(Engine engine, ObjectConstructor objectConstructor)
  15. {
  16. var obj = new ObjectPrototype(engine)
  17. {
  18. _objectConstructor = objectConstructor
  19. };
  20. return obj;
  21. }
  22. protected override void Initialize()
  23. {
  24. const PropertyFlag propertyFlags = PropertyFlag.Configurable | PropertyFlag.Writable;
  25. const PropertyFlag lengthFlags = PropertyFlag.Configurable;
  26. var properties = new PropertyDictionary(8, checkExistingKeys: false)
  27. {
  28. ["constructor"] = new PropertyDescriptor(_objectConstructor, propertyFlags),
  29. ["toString"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "toString", ToObjectString, 0, lengthFlags), propertyFlags),
  30. ["toLocaleString"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "toLocaleString", ToLocaleString, 0, lengthFlags), propertyFlags),
  31. ["valueOf"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "valueOf", ValueOf, 0, lengthFlags), propertyFlags),
  32. ["hasOwnProperty"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "hasOwnProperty", HasOwnProperty, 1, lengthFlags), propertyFlags),
  33. ["isPrototypeOf"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "isPrototypeOf", IsPrototypeOf, 1, lengthFlags), propertyFlags),
  34. ["propertyIsEnumerable"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "propertyIsEnumerable", PropertyIsEnumerable, 1, lengthFlags), propertyFlags)
  35. };
  36. SetProperties(properties);
  37. }
  38. private JsValue PropertyIsEnumerable(JsValue thisObject, JsValue[] arguments)
  39. {
  40. var p = TypeConverter.ToPropertyKey(arguments[0]);
  41. var o = TypeConverter.ToObject(Engine, thisObject);
  42. var desc = o.GetOwnProperty(p);
  43. if (desc == PropertyDescriptor.Undefined)
  44. {
  45. return false;
  46. }
  47. return desc.Enumerable;
  48. }
  49. private JsValue ValueOf(JsValue thisObject, JsValue[] arguments)
  50. {
  51. var o = TypeConverter.ToObject(Engine, thisObject);
  52. return o;
  53. }
  54. private JsValue IsPrototypeOf(JsValue thisObject, JsValue[] arguments)
  55. {
  56. var arg = arguments[0];
  57. if (!arg.IsObject())
  58. {
  59. return false;
  60. }
  61. var v = arg.AsObject();
  62. var o = TypeConverter.ToObject(Engine, thisObject);
  63. while (true)
  64. {
  65. v = v.Prototype;
  66. if (ReferenceEquals(v, null))
  67. {
  68. return false;
  69. }
  70. if (ReferenceEquals(o, v))
  71. {
  72. return true;
  73. }
  74. }
  75. }
  76. private JsValue ToLocaleString(JsValue thisObject, JsValue[] arguments)
  77. {
  78. var o = TypeConverter.ToObject(Engine, thisObject);
  79. var func = o.Get("toString");
  80. var callable = func as ICallable ?? ExceptionHelper.ThrowTypeErrorNoEngine<ICallable>("Can only invoke functions");
  81. return TypeConverter.ToString(callable.Call(thisObject, arguments));
  82. }
  83. /// <summary>
  84. /// http://www.ecma-international.org/ecma-262/5.1/#sec-15.2.4.2
  85. /// </summary>
  86. /// <param name="thisObject"></param>
  87. /// <param name="arguments"></param>
  88. /// <returns></returns>
  89. public JsValue ToObjectString(JsValue thisObject, JsValue[] arguments)
  90. {
  91. if (thisObject.IsUndefined())
  92. {
  93. return "[object Undefined]";
  94. }
  95. if (thisObject.IsNull())
  96. {
  97. return "[object Null]";
  98. }
  99. var o = TypeConverter.ToObject(Engine, thisObject);
  100. var tag = o.Get(GlobalSymbolRegistry.ToStringTag);
  101. if (!tag.IsString())
  102. {
  103. tag = o.Class.ToString();
  104. }
  105. return "[object " + tag + "]";
  106. }
  107. /// <summary>
  108. /// http://www.ecma-international.org/ecma-262/5.1/#sec-15.2.4.5
  109. /// </summary>
  110. public JsValue HasOwnProperty(JsValue thisObject, JsValue[] arguments)
  111. {
  112. var p = TypeConverter.ToPropertyKey(arguments[0]);
  113. var o = TypeConverter.ToObject(Engine, thisObject);
  114. var desc = o.GetOwnProperty(p);
  115. return desc != PropertyDescriptor.Undefined;
  116. }
  117. }
  118. }