Coverage Report

Created: 2025-11-02 07:25

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/serenity/Userland/Libraries/LibJS/Runtime/Reference.h
Line
Count
Source
1
/*
2
 * Copyright (c) 2020-2021, Andreas Kling <kling@serenityos.org>
3
 *
4
 * SPDX-License-Identifier: BSD-2-Clause
5
 */
6
7
#pragma once
8
9
#include <LibJS/Runtime/Environment.h>
10
#include <LibJS/Runtime/EnvironmentCoordinate.h>
11
#include <LibJS/Runtime/PropertyKey.h>
12
#include <LibJS/Runtime/Value.h>
13
14
namespace JS {
15
16
Reference make_private_reference(VM&, Value base_value, DeprecatedFlyString const& private_identifier);
17
18
class Reference {
19
public:
20
    enum class BaseType : u8 {
21
        Unresolvable,
22
        Value,
23
        Environment,
24
    };
25
26
    Reference() = default;
27
    Reference(BaseType type, PropertyKey name, bool strict)
28
0
        : m_base_type(type)
29
0
        , m_name(move(name))
30
0
        , m_strict(strict)
31
0
    {
32
0
    }
33
34
    Reference(Value base, PropertyKey name, Value this_value, bool strict = false)
35
0
        : m_base_type(BaseType::Value)
36
0
        , m_base_value(base)
37
0
        , m_name(move(name))
38
0
        , m_this_value(this_value)
39
0
        , m_strict(strict)
40
0
    {
41
0
    }
42
43
    Reference(Environment& base, DeprecatedFlyString referenced_name, bool strict = false, Optional<EnvironmentCoordinate> environment_coordinate = {})
44
0
        : m_base_type(BaseType::Environment)
45
0
        , m_base_environment(&base)
46
0
        , m_name(move(referenced_name))
47
0
        , m_strict(strict)
48
0
        , m_environment_coordinate(move(environment_coordinate))
49
0
    {
50
0
    }
51
52
    Reference(Value base, PrivateName name)
53
0
        : m_base_type(BaseType::Value)
54
0
        , m_base_value(base)
55
0
        , m_this_value(Value {})
56
0
        , m_strict(true)
57
0
        , m_is_private(true)
58
0
        , m_private_name(move(name))
59
0
    {
60
0
    }
61
62
    Value base() const
63
0
    {
64
0
        VERIFY(m_base_type == BaseType::Value);
65
0
        return m_base_value;
66
0
    }
67
68
    Environment& base_environment() const
69
0
    {
70
0
        VERIFY(m_base_type == BaseType::Environment);
71
0
        return *m_base_environment;
72
0
    }
73
74
0
    PropertyKey const& name() const { return m_name; }
75
0
    bool is_strict() const { return m_strict; }
76
77
    // 6.2.4.2 IsUnresolvableReference ( V ), https://tc39.es/ecma262/#sec-isunresolvablereference
78
0
    bool is_unresolvable() const { return m_base_type == BaseType::Unresolvable; }
79
80
    // 6.2.4.1 IsPropertyReference ( V ), https://tc39.es/ecma262/#sec-ispropertyreference
81
    bool is_property_reference() const
82
0
    {
83
0
        if (is_unresolvable())
84
0
            return false;
85
0
        if (m_base_type == BaseType::Environment)
86
0
            return false;
87
0
        return true;
88
0
    }
89
90
    // 6.2.4.7 GetThisValue ( V ), https://tc39.es/ecma262/#sec-getthisvalue
91
    Value get_this_value() const
92
0
    {
93
0
        VERIFY(is_property_reference());
94
0
        if (is_super_reference())
95
0
            return m_this_value;
96
0
        return m_base_value;
97
0
    }
98
99
    // 6.2.4.3 IsSuperReference ( V ), https://tc39.es/ecma262/#sec-issuperreference
100
    bool is_super_reference() const
101
0
    {
102
0
        return !m_this_value.is_empty();
103
0
    }
104
105
    // 6.2.4.4 IsPrivateReference ( V ), https://tc39.es/ecma262/#sec-isprivatereference
106
    bool is_private_reference() const
107
0
    {
108
0
        return m_is_private;
109
0
    }
110
111
    // Note: Non-standard helper.
112
    bool is_environment_reference() const
113
0
    {
114
0
        return m_base_type == BaseType::Environment;
115
0
    }
116
117
    ThrowCompletionOr<void> initialize_referenced_binding(VM&, Value value, Environment::InitializeBindingHint hint = Environment::InitializeBindingHint::Normal) const;
118
119
    ThrowCompletionOr<void> put_value(VM&, Value);
120
    ThrowCompletionOr<Value> get_value(VM&) const;
121
    ThrowCompletionOr<bool> delete_(VM&);
122
123
0
    bool is_valid_reference() const { return m_name.is_valid() || m_is_private; }
124
125
0
    Optional<EnvironmentCoordinate> environment_coordinate() const { return m_environment_coordinate; }
126
127
private:
128
    Completion throw_reference_error(VM&) const;
129
130
    BaseType m_base_type { BaseType::Unresolvable };
131
    union {
132
        Value m_base_value {};
133
        mutable Environment* m_base_environment;
134
    };
135
    PropertyKey m_name;
136
    Value m_this_value;
137
    bool m_strict { false };
138
139
    bool m_is_private { false };
140
    // FIXME: This can (probably) be an union with m_name.
141
    PrivateName m_private_name;
142
143
    Optional<EnvironmentCoordinate> m_environment_coordinate;
144
};
145
146
}