ladybird/Libraries/LibJS/Runtime/PropertyDescriptor.h
Andreas Kling 7025dd1fa7 Libraries: Parse JS strings from UTF-16
Thread UTF-16 string input through JSON, script parsing, Date parsing,
Intl option parsing, Temporal parsing, and the helper library boundaries
that feed those parsers. Preserve ASCII fast paths where the source data
is known to be ASCII.
2026-06-22 19:51:25 +02:00

79 lines
3.1 KiB
C++

/*
* Copyright (c) 2021-2022, Linus Groh <linusg@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <AK/Optional.h>
#include <AK/String.h>
#include <LibGC/Cell.h>
#include <LibJS/Export.h>
#include <LibJS/Forward.h>
#include <LibJS/Runtime/Value.h>
namespace JS {
// 6.2.5 The Property Descriptor Specification Type, https://tc39.es/ecma262/#sec-property-descriptor-specification-type
Value from_property_descriptor(VM&, Optional<PropertyDescriptor> const&);
ThrowCompletionOr<PropertyDescriptor> to_property_descriptor(VM&, Value);
class JS_API PropertyDescriptor {
public:
[[nodiscard]] bool is_accessor_descriptor() const;
[[nodiscard]] bool is_data_descriptor() const;
[[nodiscard]] bool is_generic_descriptor() const;
[[nodiscard]] PropertyAttributes attributes() const;
void complete();
// Not a standard abstract operation, but "If every field in Desc is absent".
[[nodiscard]] bool is_empty() const
{
return !value.has_value() && !get.has_value() && !set.has_value() && !writable.has_value() && !enumerable.has_value() && !configurable.has_value() && !unimplemented.has_value();
}
void visit_edges(GC::Cell::Visitor&);
Optional<Value> value {};
Optional<GC::Ptr<FunctionObject>> get {};
Optional<GC::Ptr<FunctionObject>> set {};
Optional<bool> writable {};
Optional<bool> enumerable {};
Optional<bool> configurable {};
Optional<bool> unimplemented {};
Optional<u32> property_offset {};
};
}
namespace AK {
template<>
struct Formatter<JS::PropertyDescriptor> : Formatter<FormatString> {
ErrorOr<void> format(FormatBuilder& builder, JS::PropertyDescriptor const& property_descriptor)
{
Vector<Utf16String> parts;
if (property_descriptor.value.has_value())
TRY(parts.try_append(Utf16String::formatted("[[Value]]: {}", property_descriptor.value->to_utf16_string_without_side_effects())));
if (property_descriptor.get.has_value())
TRY(parts.try_append(Utf16String::formatted("[[Get]]: JS::Function* @ {:p}", property_descriptor.get->ptr())));
if (property_descriptor.set.has_value())
TRY(parts.try_append(Utf16String::formatted("[[Set]]: JS::Function* @ {:p}", property_descriptor.set->ptr())));
if (property_descriptor.writable.has_value())
TRY(parts.try_append(Utf16String::formatted("[[Writable]]: {}", *property_descriptor.writable)));
if (property_descriptor.enumerable.has_value())
TRY(parts.try_append(Utf16String::formatted("[[Enumerable]]: {}", *property_descriptor.enumerable)));
if (property_descriptor.configurable.has_value())
TRY(parts.try_append(Utf16String::formatted("[[Configurable]]: {}", *property_descriptor.configurable)));
if (property_descriptor.unimplemented.has_value())
TRY(parts.try_append(Utf16String::formatted("[[Unimplemented]]: {}", *property_descriptor.unimplemented)));
return Formatter<Utf16String> {}.format(builder, Utf16String::formatted("PropertyDescriptor {{ {} }}", Utf16String::join(", "sv, parts)));
}
};
}