ProxyConstructor.cs 3.5 KB

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