ladybird/Libraries/LibJS/Runtime/Reference.h
Timothy Flynn 0efa98a57a LibJS+LibWeb+WebContent: Port JS::PropertyKey to UTF-16
This has quite a lot of fall out. But the majority of it is just type or
UDL substitution, where the changes just fall through to other function
calls.

By changing property key storage to UTF-16, the main affected areas are:
* NativeFunction names must now be UTF-16
* Bytecode identifiers must now be UTF-16
* Module/binding names must now be UTF-16
2025-08-05 07:07:15 -04:00

140 lines
4 KiB
C++

/*
* Copyright (c) 2020-2021, Andreas Kling <andreas@ladybird.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <LibJS/Runtime/Environment.h>
#include <LibJS/Runtime/EnvironmentCoordinate.h>
#include <LibJS/Runtime/PropertyKey.h>
#include <LibJS/Runtime/Value.h>
namespace JS {
Reference make_private_reference(VM&, Value base_value, Utf16FlyString const& private_identifier);
class Reference {
public:
enum class BaseType : u8 {
Unresolvable,
Value,
Environment,
};
Reference(BaseType type, PropertyKey name, bool strict)
: m_base_type(type)
, m_name(move(name))
, m_strict(strict)
{
}
Reference(Value base, PropertyKey name, Optional<Value> this_value, bool strict = false)
: m_base_type(BaseType::Value)
, m_base_value(base)
, m_name(move(name))
, m_this_value(this_value)
, m_strict(strict)
{
}
Reference(Environment& base, Utf16FlyString referenced_name, bool strict = false, Optional<EnvironmentCoordinate> environment_coordinate = {})
: m_base_type(BaseType::Environment)
, m_base_environment(&base)
, m_name(move(referenced_name))
, m_strict(strict)
, m_environment_coordinate(move(environment_coordinate))
{
}
Reference(Value base, PrivateName name)
: m_base_type(BaseType::Value)
, m_base_value(base)
, m_name(move(name))
, m_strict(true)
{
}
Value base() const
{
VERIFY(m_base_type == BaseType::Value);
return m_base_value;
}
Environment& base_environment() const
{
VERIFY(m_base_type == BaseType::Environment);
return *m_base_environment;
}
PropertyKey const& name() const { return m_name.get<PropertyKey>(); }
PrivateName const& private_name() const { return m_name.get<PrivateName>(); }
bool is_strict() const { return m_strict; }
// 6.2.4.2 IsUnresolvableReference ( V ), https://tc39.es/ecma262/#sec-isunresolvablereference
bool is_unresolvable() const { return m_base_type == BaseType::Unresolvable; }
// 6.2.4.1 IsPropertyReference ( V ), https://tc39.es/ecma262/#sec-ispropertyreference
bool is_property_reference() const
{
if (is_unresolvable())
return false;
if (m_base_type == BaseType::Environment)
return false;
return true;
}
// 6.2.4.7 GetThisValue ( V ), https://tc39.es/ecma262/#sec-getthisvalue
Value get_this_value() const
{
VERIFY(is_property_reference());
if (is_super_reference())
return m_this_value.value();
return m_base_value;
}
// 6.2.4.3 IsSuperReference ( V ), https://tc39.es/ecma262/#sec-issuperreference
bool is_super_reference() const
{
return m_this_value.has_value();
}
// 6.2.4.4 IsPrivateReference ( V ), https://tc39.es/ecma262/#sec-isprivatereference
bool is_private_reference() const
{
return m_name.has<PrivateName>();
}
// Note: Non-standard helper.
bool is_environment_reference() const
{
return m_base_type == BaseType::Environment;
}
ThrowCompletionOr<void> initialize_referenced_binding(VM&, Value value, Environment::InitializeBindingHint hint = Environment::InitializeBindingHint::Normal) const;
ThrowCompletionOr<void> put_value(VM&, Value);
ThrowCompletionOr<Value> get_value(VM&) const;
ThrowCompletionOr<bool> delete_(VM&);
bool is_valid_reference() const { return true; }
Optional<EnvironmentCoordinate> environment_coordinate() const { return m_environment_coordinate; }
private:
Completion throw_reference_error(VM&) const;
BaseType m_base_type { BaseType::Unresolvable };
union {
Value m_base_value {};
mutable Environment* m_base_environment;
};
Variant<PropertyKey, PrivateName> m_name;
Optional<Value> m_this_value;
bool m_strict { false };
Optional<EnvironmentCoordinate> m_environment_coordinate;
};
}