#pragma warning disable CA1859 // Use concrete types when possible for improved performance -- most of constructor methods return JsValue
using Jint.Native.Object;
using Jint.Runtime;
using Jint.Runtime.Descriptors;
using Jint.Runtime.Interop;
namespace Jint.Native.Proxy;
///
/// https://tc39.es/ecma262/#sec-proxy-constructor
///
internal sealed class ProxyConstructor : Constructor
{
private static readonly JsString _name = new JsString("Proxy");
private static readonly JsString PropertyProxy = new JsString("proxy");
private static readonly JsString PropertyRevoke = new JsString("revoke");
internal ProxyConstructor(
Engine engine,
Realm realm)
: base(engine, realm, _name)
{
_length = new PropertyDescriptor(2, PropertyFlag.Configurable);
}
protected override void Initialize()
{
var properties = new PropertyDictionary(1, checkExistingKeys: false)
{
["revocable"] = new PropertyDescriptor(new ClrFunction(_engine, "revocable", Revocable, 2, PropertyFlag.Configurable), true, true, true)
};
SetProperties(properties);
}
public override ObjectInstance Construct(JsCallArguments arguments, JsValue newTarget)
{
if (newTarget.IsUndefined())
{
Throw.TypeError(_realm);
}
return Construct(arguments.At(0), arguments.At(1));
}
protected internal override ObjectInstance? GetPrototypeOf()
{
return _realm.Intrinsics.Function.Prototype;
}
///
/// https://tc39.es/ecma262/#sec-proxy-target-handler
///
public JsProxy Construct(JsValue target, JsValue handler)
{
return ProxyCreate(target, handler);
}
///
/// https://tc39.es/ecma262/#sec-proxy.revocable
///
private JsValue Revocable(JsValue thisObject, JsCallArguments arguments)
{
var p = ProxyCreate(arguments.At(0), arguments.At(1));
JsValue Revoke(JsValue thisObject, JsCallArguments arguments)
{
p._handler = null;
p._target = null!;
return Undefined;
}
var result = _realm.Intrinsics.Object.Construct([]);
result.DefineOwnProperty(PropertyRevoke, new PropertyDescriptor(new ClrFunction(_engine, name: "", Revoke, 0, PropertyFlag.Configurable), PropertyFlag.ConfigurableEnumerableWritable));
result.DefineOwnProperty(PropertyProxy, new PropertyDescriptor(p, PropertyFlag.ConfigurableEnumerableWritable));
return result;
}
///
/// https://tc39.es/ecma262/#sec-proxycreate
///
private JsProxy ProxyCreate(JsValue target, JsValue handler)
{
if (target is not ObjectInstance targetObject)
{
Throw.TypeError(_realm, "Cannot create proxy with a non-object as target");
return null;
}
if (handler is not ObjectInstance targetHandler)
{
Throw.TypeError(_realm, "Cannot create proxy with a non-object as handler");
return null;
}
var p = new JsProxy(Engine, targetObject, targetHandler);
return p;
}
}