#pragma warning disable CA1859 // Use concrete types when possible for improved performance -- most of constructor methods return JsValue using Jint.Native.Function; using Jint.Native.Iterator; using Jint.Native.Object; using Jint.Native.Symbol; using Jint.Runtime; using Jint.Runtime.Descriptors; using Jint.Runtime.Interop; namespace Jint.Native.Map; public sealed class MapConstructor : Constructor { private static readonly JsString _functionName = new("Map"); internal MapConstructor( Engine engine, Realm realm, FunctionPrototype functionPrototype, ObjectPrototype objectPrototype) : base(engine, realm, _functionName) { _prototype = functionPrototype; PrototypeObject = new MapPrototype(engine, realm, this, objectPrototype); _length = new PropertyDescriptor(0, PropertyFlag.Configurable); _prototypeDescriptor = new PropertyDescriptor(PrototypeObject, PropertyFlag.AllForbidden); } private MapPrototype PrototypeObject { get; } protected override void Initialize() { const PropertyFlag PropertyFlags = PropertyFlag.Writable | PropertyFlag.Configurable; var properties = new PropertyDictionary(1, checkExistingKeys: false) { ["groupBy"] = new(new ClrFunction(Engine, "groupBy", GroupBy, 2, PropertyFlag.Configurable), PropertyFlags), }; SetProperties(properties); var symbols = new SymbolDictionary(1) { [GlobalSymbolRegistry.Species] = new GetSetPropertyDescriptor(get: new ClrFunction(_engine, "get [Symbol.species]", Species, 0, PropertyFlag.Configurable), set: Undefined, PropertyFlag.Configurable) }; SetSymbols(symbols); } public JsMap Construct() => ConstructMap(this); /// /// https://tc39.es/ecma262/#sec-map-iterable /// public override ObjectInstance Construct(JsCallArguments arguments, JsValue newTarget) { var map = ConstructMap(newTarget); if (arguments.Length > 0 && !arguments[0].IsNullOrUndefined()) { var adder = ((ObjectInstance) map).Get("set"); var iterator = arguments.At(0).GetIterator(_realm); IteratorProtocol.AddEntriesFromIterable(map, iterator, adder); } return map; } private JsMap ConstructMap(JsValue newTarget) { if (newTarget.IsUndefined()) { Throw.TypeError(_realm); } var map = OrdinaryCreateFromConstructor( newTarget, static intrinsics => intrinsics.Map.PrototypeObject, static (Engine engine, Realm realm, object? _) => new JsMap(engine, realm)); return map; } /// /// https://tc39.es/proposal-array-grouping/#sec-map.groupby /// private JsValue GroupBy(JsValue thisObject, JsCallArguments arguments) { var items = arguments.At(0); var callbackfn = arguments.At(1); var grouping = GroupByHelper.GroupBy(_engine, _realm, items, callbackfn, mapMode: true); var map = (JsMap) Construct(_realm.Intrinsics.Map); foreach (var pair in grouping) { map.Set(pair.Key, pair.Value); } return map; } private static JsValue Species(JsValue thisObject, JsCallArguments arguments) { return thisObject; } }