ObjectPrototype.cs 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  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. /// https://tc39.es/ecma262/#sec-object.prototype.tostring
  85. /// </summary>
  86. public JsValue ToObjectString(JsValue thisObject, JsValue[] arguments)
  87. {
  88. if (thisObject.IsUndefined())
  89. {
  90. return "[object Undefined]";
  91. }
  92. if (thisObject.IsNull())
  93. {
  94. return "[object Null]";
  95. }
  96. var o = TypeConverter.ToObject(Engine, thisObject);
  97. var tag = o.Get(GlobalSymbolRegistry.ToStringTag);
  98. if (!tag.IsString())
  99. {
  100. tag = o.Class.ToString();
  101. }
  102. return "[object " + tag + "]";
  103. }
  104. /// <summary>
  105. /// http://www.ecma-international.org/ecma-262/5.1/#sec-15.2.4.5
  106. /// </summary>
  107. public JsValue HasOwnProperty(JsValue thisObject, JsValue[] arguments)
  108. {
  109. var p = TypeConverter.ToPropertyKey(arguments[0]);
  110. var o = TypeConverter.ToObject(Engine, thisObject);
  111. var desc = o.GetOwnProperty(p);
  112. return desc != PropertyDescriptor.Undefined;
  113. }
  114. }
  115. }