/* * 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 JS_API 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_set(PropertyKey const&, Value value, Value receiver, CacheablePropertyMetadata*, PropertyLookupPhase) override; virtual ThrowCompletionOr internal_define_own_property(PropertyKey const&, PropertyDescriptor const&, Optional* precomputed_get_own_property = nullptr) override final; virtual ThrowCompletionOr internal_has_property(PropertyKey const&) const 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; } void set_is_proxy_target(bool is_proxy_target) { m_is_proxy_target = is_proxy_target; } virtual void visit_edges(Cell::Visitor& visitor) override; protected: explicit Array(Realm& realm, Object& prototype); private: virtual bool is_array_exotic_object() const final { return true; } ThrowCompletionOr set_length(PropertyDescriptor const&); GC::Ref m_realm; bool m_length_writable { true }; bool m_is_proxy_target { false }; }; template<> inline bool Object::fast_is() const { return is_array_exotic_object(); } enum class Holes { SkipHoles, ReadThroughHoles, }; JS_API ThrowCompletionOr> sort_indexed_properties(VM&, Object const&, size_t length, Function(Value, Value)> const& sort_compare, Holes holes); JS_API ThrowCompletionOr compare_array_elements(VM&, Value x, Value y, FunctionObject* comparefn); }