/* * Copyright (c) 2020, Andreas Kling * Copyright (c) 2020-2022, Linus Groh * * SPDX-License-Identifier: BSD-2-Clause */ #pragma once #include #include #include #include #include #include #include #include #include namespace JS { class Array : public Object { JS_OBJECT(Array, Object); GC_DECLARE_ALLOCATOR(Array); public: static ThrowCompletionOr> create(Realm&, u64 length, Object* prototype = nullptr); static GC::Ref create_from(Realm&, ReadonlySpan); template static GC::Ref create_from(Realm& realm, Value const (&values)[N]) { return create_from(realm, ReadonlySpan { values, N }); } // Non-standard but equivalent to CreateArrayFromList. template static GC::Ref create_from(Realm& realm, ReadonlySpan elements, Function map_fn) { auto values = GC::RootVector { realm.heap() }; values.ensure_capacity(elements.size()); for (auto const& element : elements) values.append(map_fn(element)); return Array::create_from(realm, values); } virtual ~Array() override = default; virtual ThrowCompletionOr> internal_get_own_property(PropertyKey const&) const override final; virtual ThrowCompletionOr internal_define_own_property(PropertyKey const&, PropertyDescriptor const&, Optional* precomputed_get_own_property = nullptr) override final; virtual ThrowCompletionOr internal_delete(PropertyKey const&) override; virtual ThrowCompletionOr> internal_own_property_keys() const override final; [[nodiscard]] bool length_is_writable() const { return m_length_writable; } protected: explicit Array(Object& prototype); private: virtual bool is_array_exotic_object() const final { return true; } ThrowCompletionOr set_length(PropertyDescriptor const&); bool m_length_writable { true }; }; template<> inline bool Object::fast_is() const { return is_array_exotic_object(); } enum class Holes { SkipHoles, ReadThroughHoles, }; ThrowCompletionOr> sort_indexed_properties(VM&, Object const&, size_t length, Function(Value, Value)> const& sort_compare, Holes holes); ThrowCompletionOr compare_array_elements(VM&, Value x, Value y, FunctionObject* comparefn); }