ProxyConstructor.cs 3.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. using Jint.Collections;
  2. using Jint.Native.Function;
  3. using Jint.Native.Object;
  4. using Jint.Runtime;
  5. using Jint.Runtime.Descriptors;
  6. using Jint.Runtime.Interop;
  7. namespace Jint.Native.Proxy
  8. {
  9. public sealed class ProxyConstructor : FunctionInstance, IConstructor
  10. {
  11. private static readonly JsString _name = new JsString("Proxy");
  12. private static readonly JsString PropertyProxy = new JsString("proxy");
  13. private static readonly JsString PropertyRevoke = new JsString("revoke");
  14. internal ProxyConstructor(
  15. Engine engine,
  16. Realm realm)
  17. : base(engine, realm, _name)
  18. {
  19. _length = new PropertyDescriptor(2, PropertyFlag.Configurable);
  20. }
  21. public override JsValue Call(JsValue thisObject, JsValue[] arguments)
  22. {
  23. ExceptionHelper.ThrowTypeError(_realm, "Constructor Proxy requires 'new'");
  24. return null;
  25. }
  26. /// <summary>
  27. /// https://www.ecma-international.org/ecma-262/6.0/index.html#sec-proxy-object-internal-methods-and-internal-slots-construct-argumentslist-newtarget
  28. /// </summary>
  29. public ObjectInstance Construct(JsValue[] arguments, JsValue newTarget)
  30. {
  31. var target = arguments.At(0);
  32. var handler = arguments.At(1);
  33. if (!target.IsObject() || !handler.IsObject())
  34. {
  35. ExceptionHelper.ThrowTypeError(_realm, "Cannot create proxy with a non-object as target or handler");
  36. }
  37. return Construct(target.AsObject(), handler.AsObject());
  38. }
  39. protected override void Initialize()
  40. {
  41. var properties = new PropertyDictionary(1, checkExistingKeys: false)
  42. {
  43. ["revocable"] = new PropertyDescriptor(new ClrFunctionInstance(_engine, "revocable", Revocable, 2, PropertyFlag.Configurable), true, true, true)
  44. };
  45. SetProperties(properties);
  46. }
  47. protected internal override ObjectInstance GetPrototypeOf()
  48. {
  49. return _realm.Intrinsics.Function.Prototype;
  50. }
  51. public ProxyInstance Construct(ObjectInstance target, ObjectInstance handler)
  52. {
  53. if (target is ProxyInstance targetProxy && targetProxy._handler is null)
  54. {
  55. ExceptionHelper.ThrowTypeError(_realm);
  56. }
  57. if (handler is ProxyInstance handlerProxy && handlerProxy._handler is null)
  58. {
  59. ExceptionHelper.ThrowTypeError(_realm);
  60. }
  61. var instance = new ProxyInstance(Engine, target, handler);
  62. return instance;
  63. }
  64. private JsValue Revocable(JsValue thisObject, JsValue[] arguments)
  65. {
  66. var p = Construct(arguments, thisObject);
  67. System.Func<JsValue, JsValue[], JsValue> revoke = (JsValue thisObject, JsValue[] arguments) =>
  68. {
  69. var proxy = (ProxyInstance) p;
  70. proxy._handler = null;
  71. proxy._target = null;
  72. return Undefined;
  73. };
  74. var result = _realm.Intrinsics.Object.Construct(System.Array.Empty<JsValue>());
  75. result.DefineOwnProperty(PropertyRevoke, new PropertyDescriptor(new ClrFunctionInstance(_engine, name: null, revoke, 0, PropertyFlag.Configurable), PropertyFlag.ConfigurableEnumerableWritable));
  76. result.DefineOwnProperty(PropertyProxy, new PropertyDescriptor(p, PropertyFlag.ConfigurableEnumerableWritable));
  77. return result;
  78. }
  79. }
  80. }