123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116 |
- using Jint.Collections;
- using Jint.Native.Object;
- using Jint.Native.Symbol;
- using Jint.Runtime;
- using Jint.Runtime.Descriptors;
- using Jint.Runtime.Interop;
- namespace Jint.Native.FinalizationRegistry;
- /// <summary>
- /// https://tc39.es/ecma262/#sec-properties-of-the-finalization-registry-prototype-object
- /// </summary>
- internal sealed class FinalizationRegistryPrototype : Prototype
- {
- private readonly FinalizationRegistryConstructor _constructor;
- public FinalizationRegistryPrototype(
- Engine engine,
- Realm realm,
- FinalizationRegistryConstructor constructor,
- ObjectPrototype objectPrototype) : base(engine, realm)
- {
- _constructor = constructor;
- _prototype = objectPrototype;
- }
- protected override void Initialize()
- {
- const PropertyFlag PropertyFlags = PropertyFlag.NonEnumerable;
- var properties = new PropertyDictionary(4, checkExistingKeys: false)
- {
- [KnownKeys.Constructor] = new(_constructor, PropertyFlag.NonEnumerable), ["register"] = new(new ClrFunction(Engine, "register", Register, 2, PropertyFlag.Configurable), PropertyFlags), ["unregister"] = new(new ClrFunction(Engine, "unregister", Unregister, 1, PropertyFlag.Configurable), PropertyFlags), ["cleanupSome"] = new(new ClrFunction(Engine, "cleanupSome", CleanupSome, 0, PropertyFlag.Configurable), PropertyFlags),
- };
- SetProperties(properties);
- var symbols = new SymbolDictionary(1) { [GlobalSymbolRegistry.ToStringTag] = new("FinalizationRegistry", PropertyFlag.Configurable) };
- SetSymbols(symbols);
- }
- /// <summary>
- /// https://tc39.es/ecma262/#sec-finalization-registry.prototype.register
- /// </summary>
- private JsValue Register(JsValue thisObject, JsValue[] arguments)
- {
- var finalizationRegistry = AssertFinalizationRegistryInstance(thisObject);
- var target = arguments.At(0);
- var heldValue = arguments.At(1);
- var unregisterToken = arguments.At(2);
- if (!target.CanBeHeldWeakly(_engine.GlobalSymbolRegistry))
- {
- ExceptionHelper.ThrowTypeError(_realm, "target must be an object or symbol");
- }
- if (SameValue(target, heldValue))
- {
- ExceptionHelper.ThrowTypeError(_realm, "target and holdings must not be same");
- }
- if (!unregisterToken.CanBeHeldWeakly(_engine.GlobalSymbolRegistry))
- {
- if (!unregisterToken.IsUndefined())
- {
- ExceptionHelper.ThrowTypeError(_realm, unregisterToken + " must be an object");
- }
- }
- var cell = new Cell(target, heldValue, unregisterToken);
- finalizationRegistry.AddCell(cell);
- return Undefined;
- }
- /// <summary>
- /// https://tc39.es/ecma262/#sec-finalization-registry.prototype.unregister
- /// </summary>
- private JsValue Unregister(JsValue thisObject, JsValue[] arguments)
- {
- var finalizationRegistry = AssertFinalizationRegistryInstance(thisObject);
- var unregisterToken = arguments.At(0);
- if (!unregisterToken.CanBeHeldWeakly(_engine.GlobalSymbolRegistry))
- {
- ExceptionHelper.ThrowTypeError(_realm, unregisterToken + " must be an object or symbol");
- }
- return finalizationRegistry.Remove(unregisterToken);
- }
- private JsValue CleanupSome(JsValue thisObject, JsValue[] arguments)
- {
- var finalizationRegistry = AssertFinalizationRegistryInstance(thisObject);
- var callback = arguments.At(0);
- if (!callback.IsUndefined() && callback is not ICallable)
- {
- ExceptionHelper.ThrowTypeError(_realm, callback + " must be callable");
- }
- FinalizationRegistryInstance.CleanupFinalizationRegistry(callback as ICallable);
- return Undefined;
- }
- private FinalizationRegistryInstance AssertFinalizationRegistryInstance(JsValue thisObject)
- {
- if (thisObject is FinalizationRegistryInstance finalizationRegistryInstance)
- {
- return finalizationRegistryInstance;
- }
- ExceptionHelper.ThrowTypeError(_realm, "object must be a FinalizationRegistry");
- return default;
- }
- }
|