Coverage Report

Created: 2026-09-14 07:15

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/serenity/Userland/Libraries/LibJS/Runtime/Value.h
Line
Count
Source
1
/*
2
 * Copyright (c) 2020-2021, Andreas Kling <kling@serenityos.org>
3
 * Copyright (c) 2020-2023, Linus Groh <linusg@serenityos.org>
4
 * Copyright (c) 2022, David Tuin <davidot@serenityos.org>
5
 *
6
 * SPDX-License-Identifier: BSD-2-Clause
7
 */
8
9
#pragma once
10
11
#include <AK/Assertions.h>
12
#include <AK/BitCast.h>
13
#include <AK/ByteString.h>
14
#include <AK/Format.h>
15
#include <AK/Forward.h>
16
#include <AK/Function.h>
17
#include <AK/IntegralMath.h>
18
#include <AK/Math/Constants.h>
19
#include <AK/Result.h>
20
#include <AK/String.h>
21
#include <AK/Types.h>
22
#include <LibJS/Forward.h>
23
#include <LibJS/Heap/GCPtr.h>
24
#include <math.h>
25
26
namespace JS {
27
28
// 2 ** 53 - 1
29
static constexpr double MAX_ARRAY_LIKE_INDEX = 9007199254740991.0;
30
// Unique bit representation of negative zero (only sign bit set)
31
static constexpr u64 NEGATIVE_ZERO_BITS = ((u64)1 << 63);
32
33
static_assert(sizeof(double) == 8);
34
static_assert(sizeof(void*) == sizeof(double) || sizeof(void*) == sizeof(u32));
35
// To make our Value representation compact we can use the fact that IEEE
36
// doubles have a lot (2^52 - 2) of NaN bit patterns. The canonical form being
37
// just 0x7FF8000000000000 i.e. sign = 0 exponent is all ones and the top most
38
// bit of the mantissa set.
39
static constexpr u64 CANON_NAN_BITS = bit_cast<u64>(AK::NaN<double>);
40
static_assert(CANON_NAN_BITS == 0x7FF8000000000000);
41
// (Unfortunately all the other values are valid so we have to convert any
42
// incoming NaNs to this pattern although in practice it seems only the negative
43
// version of these CANON_NAN_BITS)
44
// +/- Infinity are represented by a full exponent but without any bits of the
45
// mantissa set.
46
static constexpr u64 POSITIVE_INFINITY_BITS = bit_cast<u64>(AK::Infinity<double>);
47
static constexpr u64 NEGATIVE_INFINITY_BITS = bit_cast<u64>(-AK::Infinity<double>);
48
static_assert(POSITIVE_INFINITY_BITS == 0x7FF0000000000000);
49
static_assert(NEGATIVE_INFINITY_BITS == 0xFFF0000000000000);
50
// However as long as any bit is set in the mantissa with the exponent of all
51
// ones this value is a NaN, and it even ignores the sign bit.
52
// (NOTE: we have to use __builtin_isnan here since some isnan implementations are not constexpr)
53
static_assert(__builtin_isnan(bit_cast<double>(0x7FF0000000000001)));
54
static_assert(__builtin_isnan(bit_cast<double>(0xFFF0000000040000)));
55
// This means we can use all of these NaNs to store all other options for Value.
56
// To make sure all of these other representations we use 0x7FF8 as the base top
57
// 2 bytes which ensures the value is always a NaN.
58
static constexpr u64 BASE_TAG = 0x7FF8;
59
// This leaves the sign bit and the three lower bits for tagging a value and then
60
// 48 bits of potential payload.
61
// First the pointer backed types (Object, String etc.), to signify this category
62
// and make stack scanning easier we use the sign bit (top most bit) of 1 to
63
// signify that it is a pointer backed type.
64
static constexpr u64 IS_CELL_BIT = 0x8000 | BASE_TAG;
65
// On all current 64-bit systems this code runs pointer actually only use the
66
// lowest 6 bytes which fits neatly into our NaN payload with the top two bytes
67
// left over for marking it as a NaN and tagging the type.
68
// Note that we do need to take care when extracting the pointer value but this
69
// is explained in the extract_pointer method.
70
71
// This leaves us 3 bits to tag the type of pointer:
72
static constexpr u64 OBJECT_TAG = 0b001 | IS_CELL_BIT;
73
static constexpr u64 STRING_TAG = 0b010 | IS_CELL_BIT;
74
static constexpr u64 SYMBOL_TAG = 0b011 | IS_CELL_BIT;
75
static constexpr u64 ACCESSOR_TAG = 0b100 | IS_CELL_BIT;
76
static constexpr u64 BIGINT_TAG = 0b101 | IS_CELL_BIT;
77
78
// We can then by extracting the top 13 bits quickly check if a Value is
79
// pointer backed.
80
static constexpr u64 IS_CELL_PATTERN = 0xFFF8ULL;
81
static_assert((OBJECT_TAG & IS_CELL_PATTERN) == IS_CELL_PATTERN);
82
static_assert((STRING_TAG & IS_CELL_PATTERN) == IS_CELL_PATTERN);
83
static_assert((CANON_NAN_BITS & IS_CELL_PATTERN) != IS_CELL_PATTERN);
84
static_assert((NEGATIVE_INFINITY_BITS & IS_CELL_PATTERN) != IS_CELL_PATTERN);
85
86
// Then for the non pointer backed types we don't set the sign bit and use the
87
// three lower bits for tagging as well.
88
static constexpr u64 UNDEFINED_TAG = 0b110 | BASE_TAG;
89
static constexpr u64 NULL_TAG = 0b111 | BASE_TAG;
90
static constexpr u64 BOOLEAN_TAG = 0b001 | BASE_TAG;
91
static constexpr u64 INT32_TAG = 0b010 | BASE_TAG;
92
static constexpr u64 EMPTY_TAG = 0b011 | BASE_TAG;
93
// Notice how only undefined and null have the top bit set, this mean we can
94
// quickly check for nullish values by checking if the top and bottom bits are set
95
// but the middle one isn't.
96
static constexpr u64 IS_NULLISH_EXTRACT_PATTERN = 0xFFFEULL;
97
static constexpr u64 IS_NULLISH_PATTERN = 0x7FFEULL;
98
static_assert((UNDEFINED_TAG & IS_NULLISH_EXTRACT_PATTERN) == IS_NULLISH_PATTERN);
99
static_assert((NULL_TAG & IS_NULLISH_EXTRACT_PATTERN) == IS_NULLISH_PATTERN);
100
static_assert((BOOLEAN_TAG & IS_NULLISH_EXTRACT_PATTERN) != IS_NULLISH_PATTERN);
101
static_assert((INT32_TAG & IS_NULLISH_EXTRACT_PATTERN) != IS_NULLISH_PATTERN);
102
static_assert((EMPTY_TAG & IS_NULLISH_EXTRACT_PATTERN) != IS_NULLISH_PATTERN);
103
// We also have the empty tag to represent array holes however since empty
104
// values are not valid anywhere else we can use this "value" to our advantage
105
// in Optional<Value> to represent the empty optional.
106
107
static constexpr u64 TAG_EXTRACTION = 0xFFFF000000000000;
108
static constexpr u64 TAG_SHIFT = 48;
109
static constexpr u64 SHIFTED_BOOLEAN_TAG = BOOLEAN_TAG << TAG_SHIFT;
110
static constexpr u64 SHIFTED_INT32_TAG = INT32_TAG << TAG_SHIFT;
111
static constexpr u64 SHIFTED_IS_CELL_PATTERN = IS_CELL_PATTERN << TAG_SHIFT;
112
113
// Summary:
114
// To pack all the different value in to doubles we use the following schema:
115
// s = sign, e = exponent, m = mantissa
116
// The top part is the tag and the bottom the payload.
117
// 0bseeeeeeeeeeemmmm mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
118
// 0b0111111111111000 0... is the only real NaN
119
// 0b1111111111111xxx yyy... xxx = pointer type, yyy = pointer value
120
// 0b0111111111111xxx yyy... xxx = non-pointer type, yyy = value or 0 if just type
121
122
// Future expansion: We are not fully utilizing all the possible bit patterns
123
// yet, these choices were made to make it easy to implement and understand.
124
// We can for example drop the always 1 top bit of the mantissa expanding our
125
// options from 8 tags to 15 but since we currently only use 5 for both sign bits
126
// this is not needed.
127
128
class Value {
129
public:
130
    enum class PreferredType {
131
        Default,
132
        String,
133
        Number,
134
    };
135
136
0
    [[nodiscard]] u16 tag() const { return m_value.tag; }
137
138
446k
    bool is_empty() const { return m_value.tag == EMPTY_TAG; }
139
400k
    bool is_undefined() const { return m_value.tag == UNDEFINED_TAG; }
140
400k
    bool is_null() const { return m_value.tag == NULL_TAG; }
141
136k
    bool is_number() const { return is_double() || is_int32(); }
142
0
    bool is_string() const { return m_value.tag == STRING_TAG; }
143
765
    bool is_object() const { return m_value.tag == OBJECT_TAG; }
144
400k
    bool is_boolean() const { return m_value.tag == BOOLEAN_TAG; }
145
0
    bool is_symbol() const { return m_value.tag == SYMBOL_TAG; }
146
357
    bool is_accessor() const { return m_value.tag == ACCESSOR_TAG; }
147
0
    bool is_bigint() const { return m_value.tag == BIGINT_TAG; }
148
0
    bool is_nullish() const { return (m_value.tag & IS_NULLISH_EXTRACT_PATTERN) == IS_NULLISH_PATTERN; }
149
510
    bool is_cell() const { return (m_value.tag & IS_CELL_PATTERN) == IS_CELL_PATTERN; }
150
    ThrowCompletionOr<bool> is_array(VM&) const;
151
    bool is_function() const;
152
    bool is_constructor() const;
153
    bool is_error() const;
154
    ThrowCompletionOr<bool> is_regexp(VM&) const;
155
156
    bool is_nan() const
157
0
    {
158
0
        return m_value.encoded == CANON_NAN_BITS;
159
0
    }
160
161
    bool is_infinity() const
162
0
    {
163
0
        static_assert(NEGATIVE_INFINITY_BITS == (0x1ULL << 63 | POSITIVE_INFINITY_BITS));
164
0
        return (0x1ULL << 63 | m_value.encoded) == NEGATIVE_INFINITY_BITS;
165
0
    }
166
167
    bool is_positive_infinity() const
168
0
    {
169
0
        return m_value.encoded == POSITIVE_INFINITY_BITS;
170
0
    }
171
172
    bool is_negative_infinity() const
173
0
    {
174
0
        return m_value.encoded == NEGATIVE_INFINITY_BITS;
175
0
    }
176
177
    bool is_positive_zero() const
178
0
    {
179
0
        return m_value.encoded == 0 || (is_int32() && as_i32() == 0);
180
0
    }
181
182
    bool is_negative_zero() const
183
0
    {
184
0
        return m_value.encoded == NEGATIVE_ZERO_BITS;
185
0
    }
186
187
    bool is_integral_number() const
188
0
    {
189
0
        if (is_int32())
190
0
            return true;
191
0
        return is_finite_number() && trunc(as_double()) == as_double();
192
0
    }
193
194
    bool is_finite_number() const
195
0
    {
196
0
        if (!is_number())
197
0
            return false;
198
0
        if (is_int32())
199
0
            return true;
200
0
        return !is_nan() && !is_infinity();
201
0
    }
202
203
    Value()
204
1.16M
        : Value(EMPTY_TAG << TAG_SHIFT, (u64)0)
205
1.16M
    {
206
1.16M
    }
207
208
    template<typename T>
209
    requires(IsSameIgnoringCV<T, bool>) explicit Value(T value)
210
816
        : Value(BOOLEAN_TAG << TAG_SHIFT, (u64)value)
211
816
    {
212
816
    }
213
214
    explicit Value(double value)
215
1.46M
    {
216
1.46M
        bool is_negative_zero = bit_cast<u64>(value) == NEGATIVE_ZERO_BITS;
217
1.46M
        if (value >= NumericLimits<i32>::min() && value <= NumericLimits<i32>::max() && trunc(value) == value && !is_negative_zero) {
218
1.19M
            VERIFY(!(SHIFTED_INT32_TAG & (static_cast<i32>(value) & 0xFFFFFFFFul)));
219
1.19M
            m_value.encoded = SHIFTED_INT32_TAG | (static_cast<i32>(value) & 0xFFFFFFFFul);
220
1.19M
        } else {
221
269k
            if (isnan(value)) [[unlikely]]
222
51
                m_value.encoded = CANON_NAN_BITS;
223
269k
            else
224
269k
                m_value.as_double = value;
225
269k
        }
226
1.46M
    }
227
228
    // NOTE: A couple of integral types are excluded here:
229
    // - i32 has its own dedicated Value constructor
230
    // - i64 cannot safely be cast to a double
231
    // - bool isn't a number type and has its own dedicated Value constructor
232
    template<typename T>
233
    requires(IsIntegral<T> && !IsSameIgnoringCV<T, i32> && !IsSameIgnoringCV<T, i64> && !IsSameIgnoringCV<T, bool>) explicit Value(T value)
234
5
    {
235
5
        if (value > NumericLimits<i32>::max()) {
236
0
            m_value.as_double = static_cast<double>(value);
237
5
        } else {
238
5
            VERIFY(!(SHIFTED_INT32_TAG & (static_cast<i32>(value) & 0xFFFFFFFFul)));
239
5
            m_value.encoded = SHIFTED_INT32_TAG | (static_cast<i32>(value) & 0xFFFFFFFFul);
240
5
        }
241
5
    }
Unexecuted instantiation: JS::Value::Value<unsigned char>(unsigned char) requires (((IsIntegral<unsigned char>)&&(!(IsSameIgnoringCV<unsigned char, int>)))&&(!(IsSameIgnoringCV<unsigned char, long>)))&&(!(IsSameIgnoringCV<unsigned char, bool>))
Unexecuted instantiation: JS::Value::Value<unsigned short>(unsigned short) requires (((IsIntegral<unsigned short>)&&(!(IsSameIgnoringCV<unsigned short, int>)))&&(!(IsSameIgnoringCV<unsigned short, long>)))&&(!(IsSameIgnoringCV<unsigned short, bool>))
Unexecuted instantiation: JS::Value::Value<signed char>(signed char) requires (((IsIntegral<signed char>)&&(!(IsSameIgnoringCV<signed char, int>)))&&(!(IsSameIgnoringCV<signed char, long>)))&&(!(IsSameIgnoringCV<signed char, bool>))
Unexecuted instantiation: JS::Value::Value<short>(short) requires (((IsIntegral<short>)&&(!(IsSameIgnoringCV<short, int>)))&&(!(IsSameIgnoringCV<short, long>)))&&(!(IsSameIgnoringCV<short, bool>))
JS::Value::Value<unsigned long>(unsigned long) requires (((IsIntegral<unsigned long>)&&(!(IsSameIgnoringCV<unsigned long, int>)))&&(!(IsSameIgnoringCV<unsigned long, long>)))&&(!(IsSameIgnoringCV<unsigned long, bool>))
Line
Count
Source
234
5
    {
235
5
        if (value > NumericLimits<i32>::max()) {
236
0
            m_value.as_double = static_cast<double>(value);
237
5
        } else {
238
5
            VERIFY(!(SHIFTED_INT32_TAG & (static_cast<i32>(value) & 0xFFFFFFFFul)));
239
5
            m_value.encoded = SHIFTED_INT32_TAG | (static_cast<i32>(value) & 0xFFFFFFFFul);
240
5
        }
241
5
    }
242
243
    explicit Value(unsigned value)
244
0
    {
245
0
        if (value > NumericLimits<i32>::max()) {
246
0
            m_value.as_double = static_cast<double>(value);
247
0
        } else {
248
0
            VERIFY(!(SHIFTED_INT32_TAG & (static_cast<i32>(value) & 0xFFFFFFFFul)));
249
0
            m_value.encoded = SHIFTED_INT32_TAG | (static_cast<i32>(value) & 0xFFFFFFFFul);
250
0
        }
251
0
    }
252
253
    explicit Value(i32 value)
254
674
        : Value(SHIFTED_INT32_TAG, (u32)value)
255
674
    {
256
674
    }
257
258
    Value(Object const* object)
259
11.7k
        : Value(OBJECT_TAG << TAG_SHIFT, reinterpret_cast<void const*>(object))
260
11.7k
    {
261
11.7k
    }
262
263
    Value(PrimitiveString const* string)
264
12.4k
        : Value(STRING_TAG << TAG_SHIFT, reinterpret_cast<void const*>(string))
265
12.4k
    {
266
12.4k
    }
267
268
    Value(Symbol const* symbol)
269
0
        : Value(SYMBOL_TAG << TAG_SHIFT, reinterpret_cast<void const*>(symbol))
270
0
    {
271
0
    }
272
273
    Value(Accessor const* accessor)
274
357
        : Value(ACCESSOR_TAG << TAG_SHIFT, reinterpret_cast<void const*>(accessor))
275
357
    {
276
357
    }
277
278
    Value(BigInt const* bigint)
279
0
        : Value(BIGINT_TAG << TAG_SHIFT, reinterpret_cast<void const*>(bigint))
280
0
    {
281
0
    }
282
283
    template<typename T>
284
    Value(GCPtr<T> ptr)
285
102
        : Value(ptr.ptr())
286
102
    {
287
102
    }
JS::Value::Value<JS::Object>(JS::GCPtr<JS::Object>)
Line
Count
Source
285
102
        : Value(ptr.ptr())
286
102
    {
287
102
    }
Unexecuted instantiation: JS::Value::Value<JS::FunctionObject>(JS::GCPtr<JS::FunctionObject>)
Unexecuted instantiation: JS::Value::Value<JS::PrimitiveString>(JS::GCPtr<JS::PrimitiveString>)
Unexecuted instantiation: JS::Value::Value<JS::Symbol>(JS::GCPtr<JS::Symbol>)
Unexecuted instantiation: JS::Value::Value<JS::ECMAScriptFunctionObject>(JS::GCPtr<JS::ECMAScriptFunctionObject>)
Unexecuted instantiation: JS::Value::Value<JS::Temporal::PlainDate>(JS::GCPtr<JS::Temporal::PlainDate>)
Unexecuted instantiation: JS::Value::Value<JS::Temporal::ZonedDateTime>(JS::GCPtr<JS::Temporal::ZonedDateTime>)
Unexecuted instantiation: JS::Value::Value<Web::HTML::WindowProxy>(JS::GCPtr<Web::HTML::WindowProxy>)
Unexecuted instantiation: JS::Value::Value<Web::WebIDL::DOMException>(JS::GCPtr<Web::WebIDL::DOMException>)
Unexecuted instantiation: JS::Value::Value<Web::DOM::Element>(JS::GCPtr<Web::DOM::Element>)
Unexecuted instantiation: JS::Value::Value<Web::FileAPI::Blob>(JS::GCPtr<Web::FileAPI::Blob>)
Unexecuted instantiation: JS::Value::Value<Web::DOM::Node const>(JS::GCPtr<Web::DOM::Node const>)
Unexecuted instantiation: JS::Value::Value<Web::HTML::NavigationHistoryEntry>(JS::GCPtr<Web::HTML::NavigationHistoryEntry>)
Unexecuted instantiation: JS::Value::Value<JS::TypedArrayBase>(JS::GCPtr<JS::TypedArrayBase>)
Unexecuted instantiation: JS::Value::Value<Web::Fetch::Response>(JS::GCPtr<Web::Fetch::Response>)
Unexecuted instantiation: JS::Value::Value<Web::DOM::AbortSignal>(JS::GCPtr<Web::DOM::AbortSignal>)
Unexecuted instantiation: JS::Value::Value<Web::Streams::TransformStreamDefaultController>(JS::GCPtr<Web::Streams::TransformStreamDefaultController>)
Unexecuted instantiation: JS::Value::Value<Web::HTML::WindowProxy const>(JS::GCPtr<Web::HTML::WindowProxy const>)
Unexecuted instantiation: JS::Value::Value<Web::HTML::Location>(JS::GCPtr<Web::HTML::Location>)
Unexecuted instantiation: JS::Value::Value<JS::Promise>(JS::GCPtr<JS::Promise>)
Unexecuted instantiation: JS::Value::Value<Web::WebAssembly::Table>(JS::GCPtr<Web::WebAssembly::Table>)
Unexecuted instantiation: JS::Value::Value<Web::WebAssembly::Memory>(JS::GCPtr<Web::WebAssembly::Memory>)
288
289
    template<typename T>
290
    Value(NonnullGCPtr<T> ptr)
291
23.4k
        : Value(ptr.ptr())
292
23.4k
    {
293
23.4k
    }
Unexecuted instantiation: JS::Value::Value<JS::RegExpObject>(JS::NonnullGCPtr<JS::RegExpObject>)
JS::Value::Value<JS::ReferenceError>(JS::NonnullGCPtr<JS::ReferenceError>)
Line
Count
Source
291
11
        : Value(ptr.ptr())
292
11
    {
293
11
    }
JS::Value::Value<JS::FunctionObject>(JS::NonnullGCPtr<JS::FunctionObject>)
Line
Count
Source
291
561
        : Value(ptr.ptr())
292
561
    {
293
561
    }
Unexecuted instantiation: JS::Value::Value<JS::ECMAScriptFunctionObject>(JS::NonnullGCPtr<JS::ECMAScriptFunctionObject>)
JS::Value::Value<JS::NativeFunction>(JS::NonnullGCPtr<JS::NativeFunction>)
Line
Count
Source
291
9.63k
        : Value(ptr.ptr())
292
9.63k
    {
293
9.63k
    }
JS::Value::Value<JS::PrimitiveString>(JS::NonnullGCPtr<JS::PrimitiveString>)
Line
Count
Source
291
12.4k
        : Value(ptr.ptr())
292
12.4k
    {
293
12.4k
    }
JS::Value::Value<JS::Object>(JS::NonnullGCPtr<JS::Object>)
Line
Count
Source
291
676
        : Value(ptr.ptr())
292
676
    {
293
676
    }
Unexecuted instantiation: JS::Value::Value<JS::InternalError>(JS::NonnullGCPtr<JS::InternalError>)
JS::Value::Value<JS::Array>(JS::NonnullGCPtr<JS::Array>)
Line
Count
Source
291
5
        : Value(ptr.ptr())
292
5
    {
293
5
    }
Unexecuted instantiation: JS::Value::Value<JS::TypeError>(JS::NonnullGCPtr<JS::TypeError>)
Unexecuted instantiation: JS::Value::Value<JS::BigInt>(JS::NonnullGCPtr<JS::BigInt>)
Unexecuted instantiation: JS::Value::Value<JS::IteratorRecord>(JS::NonnullGCPtr<JS::IteratorRecord>)
Unexecuted instantiation: JS::Value::Value<JS::Accessor>(JS::NonnullGCPtr<JS::Accessor>)
Unexecuted instantiation: JS::Value::Value<JS::SyntaxError>(JS::NonnullGCPtr<JS::SyntaxError>)
Unexecuted instantiation: JS::Value::Value<JS::SuppressedError>(JS::NonnullGCPtr<JS::SuppressedError>)
Unexecuted instantiation: JS::Value::Value<JS::PromiseConstructor>(JS::NonnullGCPtr<JS::PromiseConstructor>)
Unexecuted instantiation: JS::Value::Value<JS::RangeError>(JS::NonnullGCPtr<JS::RangeError>)
Unexecuted instantiation: JS::Value::Value<JS::ArrayIterator>(JS::NonnullGCPtr<JS::ArrayIterator>)
Unexecuted instantiation: JS::Value::Value<JS::AsyncGenerator>(JS::NonnullGCPtr<JS::AsyncGenerator>)
Unexecuted instantiation: JS::Value::Value<JS::Promise>(JS::NonnullGCPtr<JS::Promise>)
Unexecuted instantiation: JS::Value::Value<JS::GeneratorObject>(JS::NonnullGCPtr<JS::GeneratorObject>)
Unexecuted instantiation: JS::Value::Value<JS::AggregateErrorConstructor>(JS::NonnullGCPtr<JS::AggregateErrorConstructor>)
Unexecuted instantiation: JS::Value::Value<JS::ArrayConstructor>(JS::NonnullGCPtr<JS::ArrayConstructor>)
Unexecuted instantiation: JS::Value::Value<JS::ArrayBufferConstructor>(JS::NonnullGCPtr<JS::ArrayBufferConstructor>)
Unexecuted instantiation: JS::Value::Value<JS::BigIntConstructor>(JS::NonnullGCPtr<JS::BigIntConstructor>)
Unexecuted instantiation: JS::Value::Value<JS::BigInt64ArrayConstructor>(JS::NonnullGCPtr<JS::BigInt64ArrayConstructor>)
Unexecuted instantiation: JS::Value::Value<JS::BigUint64ArrayConstructor>(JS::NonnullGCPtr<JS::BigUint64ArrayConstructor>)
Unexecuted instantiation: JS::Value::Value<JS::BooleanConstructor>(JS::NonnullGCPtr<JS::BooleanConstructor>)
Unexecuted instantiation: JS::Value::Value<JS::DataViewConstructor>(JS::NonnullGCPtr<JS::DataViewConstructor>)
Unexecuted instantiation: JS::Value::Value<JS::DateConstructor>(JS::NonnullGCPtr<JS::DateConstructor>)
Unexecuted instantiation: JS::Value::Value<JS::DisposableStackConstructor>(JS::NonnullGCPtr<JS::DisposableStackConstructor>)
Unexecuted instantiation: JS::Value::Value<JS::ErrorConstructor>(JS::NonnullGCPtr<JS::ErrorConstructor>)
Unexecuted instantiation: JS::Value::Value<JS::EvalErrorConstructor>(JS::NonnullGCPtr<JS::EvalErrorConstructor>)
Unexecuted instantiation: JS::Value::Value<JS::FinalizationRegistryConstructor>(JS::NonnullGCPtr<JS::FinalizationRegistryConstructor>)
Unexecuted instantiation: JS::Value::Value<JS::Float32ArrayConstructor>(JS::NonnullGCPtr<JS::Float32ArrayConstructor>)
Unexecuted instantiation: JS::Value::Value<JS::Float64ArrayConstructor>(JS::NonnullGCPtr<JS::Float64ArrayConstructor>)
Unexecuted instantiation: JS::Value::Value<JS::FunctionConstructor>(JS::NonnullGCPtr<JS::FunctionConstructor>)
Unexecuted instantiation: JS::Value::Value<JS::Int8ArrayConstructor>(JS::NonnullGCPtr<JS::Int8ArrayConstructor>)
Unexecuted instantiation: JS::Value::Value<JS::Int16ArrayConstructor>(JS::NonnullGCPtr<JS::Int16ArrayConstructor>)
Unexecuted instantiation: JS::Value::Value<JS::Int32ArrayConstructor>(JS::NonnullGCPtr<JS::Int32ArrayConstructor>)
Unexecuted instantiation: JS::Value::Value<JS::IteratorConstructor>(JS::NonnullGCPtr<JS::IteratorConstructor>)
Unexecuted instantiation: JS::Value::Value<JS::MapConstructor>(JS::NonnullGCPtr<JS::MapConstructor>)
Unexecuted instantiation: JS::Value::Value<JS::NumberConstructor>(JS::NonnullGCPtr<JS::NumberConstructor>)
Unexecuted instantiation: JS::Value::Value<JS::ObjectConstructor>(JS::NonnullGCPtr<JS::ObjectConstructor>)
Unexecuted instantiation: JS::Value::Value<JS::ProxyConstructor>(JS::NonnullGCPtr<JS::ProxyConstructor>)
Unexecuted instantiation: JS::Value::Value<JS::RangeErrorConstructor>(JS::NonnullGCPtr<JS::RangeErrorConstructor>)
Unexecuted instantiation: JS::Value::Value<JS::ReferenceErrorConstructor>(JS::NonnullGCPtr<JS::ReferenceErrorConstructor>)
Unexecuted instantiation: JS::Value::Value<JS::RegExpConstructor>(JS::NonnullGCPtr<JS::RegExpConstructor>)
Unexecuted instantiation: JS::Value::Value<JS::SetConstructor>(JS::NonnullGCPtr<JS::SetConstructor>)
Unexecuted instantiation: JS::Value::Value<JS::ShadowRealmConstructor>(JS::NonnullGCPtr<JS::ShadowRealmConstructor>)
Unexecuted instantiation: JS::Value::Value<JS::SharedArrayBufferConstructor>(JS::NonnullGCPtr<JS::SharedArrayBufferConstructor>)
Unexecuted instantiation: JS::Value::Value<JS::StringConstructor>(JS::NonnullGCPtr<JS::StringConstructor>)
Unexecuted instantiation: JS::Value::Value<JS::SuppressedErrorConstructor>(JS::NonnullGCPtr<JS::SuppressedErrorConstructor>)
Unexecuted instantiation: JS::Value::Value<JS::SymbolConstructor>(JS::NonnullGCPtr<JS::SymbolConstructor>)
Unexecuted instantiation: JS::Value::Value<JS::SyntaxErrorConstructor>(JS::NonnullGCPtr<JS::SyntaxErrorConstructor>)
Unexecuted instantiation: JS::Value::Value<JS::TypeErrorConstructor>(JS::NonnullGCPtr<JS::TypeErrorConstructor>)
Unexecuted instantiation: JS::Value::Value<JS::Uint8ArrayConstructor>(JS::NonnullGCPtr<JS::Uint8ArrayConstructor>)
Unexecuted instantiation: JS::Value::Value<JS::Uint8ClampedArrayConstructor>(JS::NonnullGCPtr<JS::Uint8ClampedArrayConstructor>)
Unexecuted instantiation: JS::Value::Value<JS::Uint16ArrayConstructor>(JS::NonnullGCPtr<JS::Uint16ArrayConstructor>)
Unexecuted instantiation: JS::Value::Value<JS::Uint32ArrayConstructor>(JS::NonnullGCPtr<JS::Uint32ArrayConstructor>)
Unexecuted instantiation: JS::Value::Value<JS::URIErrorConstructor>(JS::NonnullGCPtr<JS::URIErrorConstructor>)
Unexecuted instantiation: JS::Value::Value<JS::WeakMapConstructor>(JS::NonnullGCPtr<JS::WeakMapConstructor>)
Unexecuted instantiation: JS::Value::Value<JS::WeakRefConstructor>(JS::NonnullGCPtr<JS::WeakRefConstructor>)
Unexecuted instantiation: JS::Value::Value<JS::WeakSetConstructor>(JS::NonnullGCPtr<JS::WeakSetConstructor>)
Unexecuted instantiation: JS::Value::Value<JS::AtomicsObject>(JS::NonnullGCPtr<JS::AtomicsObject>)
Unexecuted instantiation: JS::Value::Value<JS::Intl::Intl>(JS::NonnullGCPtr<JS::Intl::Intl>)
Unexecuted instantiation: JS::Value::Value<JS::JSONObject>(JS::NonnullGCPtr<JS::JSONObject>)
Unexecuted instantiation: JS::Value::Value<JS::MathObject>(JS::NonnullGCPtr<JS::MathObject>)
Unexecuted instantiation: JS::Value::Value<JS::ReflectObject>(JS::NonnullGCPtr<JS::ReflectObject>)
Unexecuted instantiation: JS::Value::Value<JS::Temporal::Temporal>(JS::NonnullGCPtr<JS::Temporal::Temporal>)
Unexecuted instantiation: JS::Value::Value<JS::URIError>(JS::NonnullGCPtr<JS::URIError>)
JS::Value::Value<JS::InternalErrorConstructor>(JS::NonnullGCPtr<JS::InternalErrorConstructor>)
Line
Count
Source
291
51
        : Value(ptr.ptr())
292
51
    {
293
51
    }
JS::Value::Value<JS::ConsoleObject>(JS::NonnullGCPtr<JS::ConsoleObject>)
Line
Count
Source
291
51
        : Value(ptr.ptr())
292
51
    {
293
51
    }
Unexecuted instantiation: JS::Value::Value<JS::BoundFunction>(JS::NonnullGCPtr<JS::BoundFunction>)
Unexecuted instantiation: JS::Value::Value<JS::Intl::SegmentIterator>(JS::NonnullGCPtr<JS::Intl::SegmentIterator>)
Unexecuted instantiation: JS::Value::Value<JS::ArrayBuffer>(JS::NonnullGCPtr<JS::ArrayBuffer>)
Unexecuted instantiation: JS::Value::Value<JS::DisposableStack>(JS::NonnullGCPtr<JS::DisposableStack>)
Unexecuted instantiation: JS::Value::Value<JS::Intl::Locale>(JS::NonnullGCPtr<JS::Intl::Locale>)
Unexecuted instantiation: JS::Value::Value<JS::Intl::Segments>(JS::NonnullGCPtr<JS::Intl::Segments>)
Unexecuted instantiation: JS::Value::Value<JS::Intl::CollatorConstructor>(JS::NonnullGCPtr<JS::Intl::CollatorConstructor>)
Unexecuted instantiation: JS::Value::Value<JS::Intl::DateTimeFormatConstructor>(JS::NonnullGCPtr<JS::Intl::DateTimeFormatConstructor>)
Unexecuted instantiation: JS::Value::Value<JS::Intl::DisplayNamesConstructor>(JS::NonnullGCPtr<JS::Intl::DisplayNamesConstructor>)
Unexecuted instantiation: JS::Value::Value<JS::Intl::DurationFormatConstructor>(JS::NonnullGCPtr<JS::Intl::DurationFormatConstructor>)
Unexecuted instantiation: JS::Value::Value<JS::Intl::ListFormatConstructor>(JS::NonnullGCPtr<JS::Intl::ListFormatConstructor>)
Unexecuted instantiation: JS::Value::Value<JS::Intl::LocaleConstructor>(JS::NonnullGCPtr<JS::Intl::LocaleConstructor>)
Unexecuted instantiation: JS::Value::Value<JS::Intl::NumberFormatConstructor>(JS::NonnullGCPtr<JS::Intl::NumberFormatConstructor>)
Unexecuted instantiation: JS::Value::Value<JS::Intl::PluralRulesConstructor>(JS::NonnullGCPtr<JS::Intl::PluralRulesConstructor>)
Unexecuted instantiation: JS::Value::Value<JS::Intl::RelativeTimeFormatConstructor>(JS::NonnullGCPtr<JS::Intl::RelativeTimeFormatConstructor>)
Unexecuted instantiation: JS::Value::Value<JS::Intl::SegmenterConstructor>(JS::NonnullGCPtr<JS::Intl::SegmenterConstructor>)
Unexecuted instantiation: JS::Value::Value<JS::Iterator>(JS::NonnullGCPtr<JS::Iterator>)
Unexecuted instantiation: JS::Value::Value<JS::IteratorHelper>(JS::NonnullGCPtr<JS::IteratorHelper>)
Unexecuted instantiation: JS::Value::Value<JS::Map>(JS::NonnullGCPtr<JS::Map>)
Unexecuted instantiation: JS::Value::Value<JS::MapIterator>(JS::NonnullGCPtr<JS::MapIterator>)
Unexecuted instantiation: JS::Value::Value<JS::PromiseAllResolveElementFunction>(JS::NonnullGCPtr<JS::PromiseAllResolveElementFunction>)
Unexecuted instantiation: JS::Value::Value<JS::PromiseAllSettledResolveElementFunction>(JS::NonnullGCPtr<JS::PromiseAllSettledResolveElementFunction>)
Unexecuted instantiation: JS::Value::Value<JS::PromiseAllSettledRejectElementFunction>(JS::NonnullGCPtr<JS::PromiseAllSettledRejectElementFunction>)
Unexecuted instantiation: JS::Value::Value<JS::AggregateError>(JS::NonnullGCPtr<JS::AggregateError>)
Unexecuted instantiation: JS::Value::Value<JS::PromiseAnyRejectElementFunction>(JS::NonnullGCPtr<JS::PromiseAnyRejectElementFunction>)
Unexecuted instantiation: JS::Value::Value<JS::RegExpStringIterator>(JS::NonnullGCPtr<JS::RegExpStringIterator>)
Unexecuted instantiation: JS::Value::Value<JS::Set>(JS::NonnullGCPtr<JS::Set>)
Unexecuted instantiation: JS::Value::Value<JS::Object const>(JS::NonnullGCPtr<JS::Object const>)
Unexecuted instantiation: JS::Value::Value<JS::SetIterator>(JS::NonnullGCPtr<JS::SetIterator>)
Unexecuted instantiation: JS::Value::Value<JS::WrappedFunction>(JS::NonnullGCPtr<JS::WrappedFunction>)
Unexecuted instantiation: JS::Value::Value<JS::StringIterator>(JS::NonnullGCPtr<JS::StringIterator>)
Unexecuted instantiation: JS::Value::Value<JS::Symbol>(JS::NonnullGCPtr<JS::Symbol>)
Unexecuted instantiation: JS::Value::Value<JS::Temporal::Duration>(JS::NonnullGCPtr<JS::Temporal::Duration>)
Unexecuted instantiation: JS::Value::Value<JS::Temporal::Calendar>(JS::NonnullGCPtr<JS::Temporal::Calendar>)
Unexecuted instantiation: JS::Value::Value<JS::Temporal::PlainDate>(JS::NonnullGCPtr<JS::Temporal::PlainDate>)
Unexecuted instantiation: JS::Value::Value<JS::Temporal::CalendarConstructor>(JS::NonnullGCPtr<JS::Temporal::CalendarConstructor>)
Unexecuted instantiation: JS::Value::Value<JS::Temporal::DurationConstructor>(JS::NonnullGCPtr<JS::Temporal::DurationConstructor>)
Unexecuted instantiation: JS::Value::Value<JS::Temporal::InstantConstructor>(JS::NonnullGCPtr<JS::Temporal::InstantConstructor>)
Unexecuted instantiation: JS::Value::Value<JS::Temporal::PlainDateConstructor>(JS::NonnullGCPtr<JS::Temporal::PlainDateConstructor>)
Unexecuted instantiation: JS::Value::Value<JS::Temporal::PlainDateTimeConstructor>(JS::NonnullGCPtr<JS::Temporal::PlainDateTimeConstructor>)
Unexecuted instantiation: JS::Value::Value<JS::Temporal::PlainMonthDayConstructor>(JS::NonnullGCPtr<JS::Temporal::PlainMonthDayConstructor>)
Unexecuted instantiation: JS::Value::Value<JS::Temporal::PlainTimeConstructor>(JS::NonnullGCPtr<JS::Temporal::PlainTimeConstructor>)
Unexecuted instantiation: JS::Value::Value<JS::Temporal::PlainYearMonthConstructor>(JS::NonnullGCPtr<JS::Temporal::PlainYearMonthConstructor>)
Unexecuted instantiation: JS::Value::Value<JS::Temporal::TimeZoneConstructor>(JS::NonnullGCPtr<JS::Temporal::TimeZoneConstructor>)
Unexecuted instantiation: JS::Value::Value<JS::Temporal::ZonedDateTimeConstructor>(JS::NonnullGCPtr<JS::Temporal::ZonedDateTimeConstructor>)
Unexecuted instantiation: JS::Value::Value<JS::Temporal::Now>(JS::NonnullGCPtr<JS::Temporal::Now>)
Unexecuted instantiation: JS::Value::Value<JS::Temporal::TimeZone>(JS::NonnullGCPtr<JS::Temporal::TimeZone>)
Unexecuted instantiation: JS::Value::Value<JS::Temporal::Instant>(JS::NonnullGCPtr<JS::Temporal::Instant>)
Unexecuted instantiation: JS::Value::Value<JS::WeakMap>(JS::NonnullGCPtr<JS::WeakMap>)
Unexecuted instantiation: JS::Value::Value<JS::WeakSet>(JS::NonnullGCPtr<JS::WeakSet>)
Unexecuted instantiation: JS::Value::Value<JS::EvalError>(JS::NonnullGCPtr<JS::EvalError>)
Unexecuted instantiation: JS::Value::Value<Web::WebIDL::DOMException>(JS::NonnullGCPtr<Web::WebIDL::DOMException>)
Unexecuted instantiation: JS::Value::Value<Web::DOM::Element>(JS::NonnullGCPtr<Web::DOM::Element>)
Unexecuted instantiation: JS::Value::Value<Web::DOM::HTMLCollection>(JS::NonnullGCPtr<Web::DOM::HTMLCollection>)
Unexecuted instantiation: JS::Value::Value<Web::CSS::FontFace>(JS::NonnullGCPtr<Web::CSS::FontFace>)
Unexecuted instantiation: JS::Value::Value<JS::Uint8Array>(JS::NonnullGCPtr<JS::Uint8Array>)
Unexecuted instantiation: JS::Value::Value<Web::Crypto::CryptoKey>(JS::NonnullGCPtr<Web::Crypto::CryptoKey>)
Unexecuted instantiation: JS::Value::Value<Web::Crypto::CryptoKeyPair>(JS::NonnullGCPtr<Web::Crypto::CryptoKeyPair>)
Unexecuted instantiation: JS::Value::Value<Web::HTML::RadioNodeList>(JS::NonnullGCPtr<Web::HTML::RadioNodeList>)
Unexecuted instantiation: JS::Value::Value<Web::FileAPI::File>(JS::NonnullGCPtr<Web::FileAPI::File>)
Unexecuted instantiation: JS::Value::Value<Web::HTML::AudioTrack>(JS::NonnullGCPtr<Web::HTML::AudioTrack>)
Unexecuted instantiation: JS::Value::Value<Web::HTML::NavigationHistoryEntry>(JS::NonnullGCPtr<Web::HTML::NavigationHistoryEntry>)
Unexecuted instantiation: JS::Value::Value<JS::BooleanObject>(JS::NonnullGCPtr<JS::BooleanObject>)
Unexecuted instantiation: JS::Value::Value<JS::NumberObject>(JS::NonnullGCPtr<JS::NumberObject>)
Unexecuted instantiation: JS::Value::Value<JS::BigIntObject>(JS::NonnullGCPtr<JS::BigIntObject>)
Unexecuted instantiation: JS::Value::Value<JS::StringObject>(JS::NonnullGCPtr<JS::StringObject>)
Unexecuted instantiation: JS::Value::Value<JS::Date>(JS::NonnullGCPtr<JS::Date>)
Unexecuted instantiation: JS::Value::Value<JS::DataView>(JS::NonnullGCPtr<JS::DataView>)
Unexecuted instantiation: JS::Value::Value<JS::Error>(JS::NonnullGCPtr<JS::Error>)
Unexecuted instantiation: JS::Value::Value<Web::Bindings::PlatformObject>(JS::NonnullGCPtr<Web::Bindings::PlatformObject>)
Unexecuted instantiation: JS::Value::Value<Web::Geometry::DOMPoint>(JS::NonnullGCPtr<Web::Geometry::DOMPoint>)
Unexecuted instantiation: JS::Value::Value<Web::HTML::TextTrack>(JS::NonnullGCPtr<Web::HTML::TextTrack>)
Unexecuted instantiation: JS::Value::Value<Web::HTML::VideoTrack>(JS::NonnullGCPtr<Web::HTML::VideoTrack>)
Unexecuted instantiation: JS::Value::Value<Web::Internals::Inspector>(JS::NonnullGCPtr<Web::Internals::Inspector>)
Unexecuted instantiation: JS::Value::Value<Web::Internals::Internals>(JS::NonnullGCPtr<Web::Internals::Internals>)
Unexecuted instantiation: JS::Value::Value<Web::PerformanceTimeline::PerformanceObserverEntryList>(JS::NonnullGCPtr<Web::PerformanceTimeline::PerformanceObserverEntryList>)
Unexecuted instantiation: JS::Value::Value<Web::PerformanceTimeline::PerformanceObserver>(JS::NonnullGCPtr<Web::PerformanceTimeline::PerformanceObserver>)
Unexecuted instantiation: JS::Value::Value<Web::FileAPI::Blob>(JS::NonnullGCPtr<Web::FileAPI::Blob>)
Unexecuted instantiation: JS::Value::Value<Web::XHR::FormData>(JS::NonnullGCPtr<Web::XHR::FormData>)
Unexecuted instantiation: JS::Value::Value<Web::HTML::DataTransferItem>(JS::NonnullGCPtr<Web::HTML::DataTransferItem>)
Unexecuted instantiation: JS::Value::Value<Web::Streams::ReadableStreamDefaultController>(JS::NonnullGCPtr<Web::Streams::ReadableStreamDefaultController>)
Unexecuted instantiation: JS::Value::Value<Web::Streams::WritableStreamDefaultController>(JS::NonnullGCPtr<Web::Streams::WritableStreamDefaultController>)
Unexecuted instantiation: JS::Value::Value<Web::Streams::TransformStreamDefaultController>(JS::NonnullGCPtr<Web::Streams::TransformStreamDefaultController>)
Unexecuted instantiation: JS::Value::Value<Web::Streams::ReadableByteStreamController>(JS::NonnullGCPtr<Web::Streams::ReadableByteStreamController>)
Unexecuted instantiation: JS::Value::Value<Web::HTML::Location>(JS::NonnullGCPtr<Web::HTML::Location>)
Unexecuted instantiation: JS::Value::Value<Web::WebIDL::ObservableArray>(JS::NonnullGCPtr<Web::WebIDL::ObservableArray>)
Unexecuted instantiation: JS::Value::Value<Web::DOMURL::URLSearchParamsIterator>(JS::NonnullGCPtr<Web::DOMURL::URLSearchParamsIterator>)
Unexecuted instantiation: JS::Value::Value<Web::Fetch::HeadersIterator>(JS::NonnullGCPtr<Web::Fetch::HeadersIterator>)
Unexecuted instantiation: JS::Value::Value<Web::HTML::TextTrackCue>(JS::NonnullGCPtr<Web::HTML::TextTrackCue>)
Unexecuted instantiation: JS::Value::Value<Web::WebAssembly::Module>(JS::NonnullGCPtr<Web::WebAssembly::Module>)
Unexecuted instantiation: JS::Value::Value<Web::WebAssembly::Instance>(JS::NonnullGCPtr<Web::WebAssembly::Instance>)
Unexecuted instantiation: JS::Value::Value<Web::WebAudio::AudioBuffer>(JS::NonnullGCPtr<Web::WebAudio::AudioBuffer>)
Unexecuted instantiation: JS::Value::Value<Web::XHR::FormDataIterator>(JS::NonnullGCPtr<Web::XHR::FormDataIterator>)
294
295
    template<typename T>
296
    Value(Handle<T> const& ptr)
297
0
        : Value(ptr.ptr())
298
0
    {
299
0
    }
Unexecuted instantiation: JS::Value::Value<Web::CSS::FontFace>(JS::Handle<Web::CSS::FontFace> const&)
Unexecuted instantiation: JS::Value::Value<JS::Object>(JS::Handle<JS::Object> const&)
Unexecuted instantiation: JS::Value::Value<Web::HTML::RadioNodeList>(JS::Handle<Web::HTML::RadioNodeList> const&)
Unexecuted instantiation: JS::Value::Value<Web::HTML::ImageBitmap>(JS::Handle<Web::HTML::ImageBitmap> const&)
300
301
    double as_double() const
302
136k
    {
303
136k
        VERIFY(is_number());
304
136k
        if (is_int32())
305
2.19k
            return as_i32();
306
133k
        return m_value.as_double;
307
136k
    }
308
309
    bool as_bool() const
310
0
    {
311
0
        VERIFY(is_boolean());
312
0
        return static_cast<bool>(m_value.encoded & 0x1);
313
0
    }
314
315
    Object& as_object()
316
255
    {
317
255
        VERIFY(is_object());
318
255
        return *extract_pointer<Object>();
319
255
    }
320
321
    Object const& as_object() const
322
255
    {
323
255
        VERIFY(is_object());
324
255
        return *extract_pointer<Object>();
325
255
    }
326
327
    PrimitiveString& as_string()
328
0
    {
329
0
        VERIFY(is_string());
330
0
        return *extract_pointer<PrimitiveString>();
331
0
    }
332
333
    PrimitiveString const& as_string() const
334
0
    {
335
0
        VERIFY(is_string());
336
0
        return *extract_pointer<PrimitiveString>();
337
0
    }
338
339
    Symbol& as_symbol()
340
0
    {
341
0
        VERIFY(is_symbol());
342
0
        return *extract_pointer<Symbol>();
343
0
    }
344
345
    Symbol const& as_symbol() const
346
0
    {
347
0
        VERIFY(is_symbol());
348
0
        return *extract_pointer<Symbol>();
349
0
    }
350
351
    Cell& as_cell()
352
0
    {
353
0
        VERIFY(is_cell());
354
0
        return *extract_pointer<Cell>();
355
0
    }
356
357
    Cell& as_cell() const
358
0
    {
359
0
        VERIFY(is_cell());
360
0
        return *extract_pointer<Cell>();
361
0
    }
362
363
    Accessor& as_accessor()
364
0
    {
365
0
        VERIFY(is_accessor());
366
0
        return *extract_pointer<Accessor>();
367
0
    }
368
369
    BigInt const& as_bigint() const
370
0
    {
371
0
        VERIFY(is_bigint());
372
0
        return *extract_pointer<BigInt>();
373
0
    }
374
375
    BigInt& as_bigint()
376
0
    {
377
0
        VERIFY(is_bigint());
378
0
        return *extract_pointer<BigInt>();
379
0
    }
380
381
    Array& as_array();
382
    FunctionObject& as_function();
383
    FunctionObject const& as_function() const;
384
385
0
    u64 encoded() const { return m_value.encoded; }
386
387
    ThrowCompletionOr<String> to_string(VM&) const;
388
    ThrowCompletionOr<ByteString> to_byte_string(VM&) const;
389
    ThrowCompletionOr<Utf16String> to_utf16_string(VM&) const;
390
    ThrowCompletionOr<String> to_well_formed_string(VM&) const;
391
    ThrowCompletionOr<NonnullGCPtr<PrimitiveString>> to_primitive_string(VM&);
392
    ThrowCompletionOr<Value> to_primitive(VM&, PreferredType preferred_type = PreferredType::Default) const;
393
    ThrowCompletionOr<NonnullGCPtr<Object>> to_object(VM&) const;
394
    ThrowCompletionOr<Value> to_numeric(VM&) const;
395
    ThrowCompletionOr<Value> to_number(VM&) const;
396
    ThrowCompletionOr<NonnullGCPtr<BigInt>> to_bigint(VM&) const;
397
    ThrowCompletionOr<i64> to_bigint_int64(VM&) const;
398
    ThrowCompletionOr<u64> to_bigint_uint64(VM&) const;
399
    ThrowCompletionOr<double> to_double(VM&) const;
400
    ThrowCompletionOr<PropertyKey> to_property_key(VM&) const;
401
    ThrowCompletionOr<i32> to_i32(VM&) const;
402
    ThrowCompletionOr<u32> to_u32(VM&) const;
403
    ThrowCompletionOr<i16> to_i16(VM&) const;
404
    ThrowCompletionOr<u16> to_u16(VM&) const;
405
    ThrowCompletionOr<i8> to_i8(VM&) const;
406
    ThrowCompletionOr<u8> to_u8(VM&) const;
407
    ThrowCompletionOr<u8> to_u8_clamp(VM&) const;
408
    ThrowCompletionOr<size_t> to_length(VM&) const;
409
    ThrowCompletionOr<size_t> to_index(VM&) const;
410
    ThrowCompletionOr<double> to_integer_or_infinity(VM&) const;
411
    bool to_boolean() const;
412
413
    ThrowCompletionOr<Value> get(VM&, PropertyKey const&) const;
414
    ThrowCompletionOr<GCPtr<FunctionObject>> get_method(VM&, PropertyKey const&) const;
415
416
    [[nodiscard]] String to_string_without_side_effects() const;
417
418
    Value value_or(Value fallback) const
419
0
    {
420
0
        if (is_empty())
421
0
            return fallback;
422
0
        return *this;
423
0
    }
424
425
    [[nodiscard]] NonnullGCPtr<PrimitiveString> typeof_(VM&) const;
426
427
    bool operator==(Value const&) const;
428
429
    template<typename... Args>
430
    [[nodiscard]] ALWAYS_INLINE ThrowCompletionOr<Value> invoke(VM&, PropertyKey const& property_key, Args... args);
431
432
    static constexpr FlatPtr extract_pointer_bits(u64 encoded)
433
510
    {
434
#ifdef AK_ARCH_32_BIT
435
        // For 32-bit system the pointer fully fits so we can just return it directly.
436
        static_assert(sizeof(void*) == sizeof(u32));
437
        return static_cast<FlatPtr>(encoded & 0xffff'ffff);
438
#elif ARCH(X86_64) || ARCH(RISCV64)
439
        // For x86_64 and riscv64 the top 16 bits should be sign extending the "real" top bit (47th).
440
510
        return AK::sign_extend(encoded, 48);
441
#elif ARCH(AARCH64)
442
        // For AArch64 the top 16 bits of the pointer should be zero.
443
        return static_cast<FlatPtr>(encoded & 0xffff'ffff'ffffULL);
444
#else
445
#    error "Unknown architecture. Don't know whether pointers need to be sign-extended."
446
#endif
447
510
    }
448
449
    // A double is any Value which does not have the full exponent and top mantissa bit set or has
450
    // exactly only those bits set.
451
136k
    bool is_double() const { return (m_value.encoded & CANON_NAN_BITS) != CANON_NAN_BITS || (m_value.encoded == CANON_NAN_BITS); }
452
806k
    bool is_int32() const { return m_value.tag == INT32_TAG; }
453
454
    i32 as_i32() const
455
267k
    {
456
267k
        VERIFY(is_int32());
457
267k
        return static_cast<i32>(m_value.encoded & 0xFFFFFFFF);
458
267k
    }
459
460
    bool to_boolean_slow_case() const;
461
462
private:
463
    ThrowCompletionOr<Value> to_number_slow_case(VM&) const;
464
    ThrowCompletionOr<Value> to_numeric_slow_case(VM&) const;
465
    ThrowCompletionOr<Value> to_primitive_slow_case(VM&, PreferredType) const;
466
467
    Value(u64 tag, u64 val)
468
1.18M
    {
469
1.18M
        VERIFY(!(tag & val));
470
1.18M
        m_value.encoded = tag | val;
471
1.18M
    }
472
473
    template<typename PointerType>
474
    Value(u64 tag, PointerType const* ptr)
475
24.6k
    {
476
24.6k
        if (!ptr) {
477
            // Make sure all nullptrs are null
478
0
            m_value.tag = NULL_TAG;
479
0
            return;
480
0
        }
481
482
24.6k
        VERIFY((tag & 0x8000000000000000ul) == 0x8000000000000000ul);
483
484
        if constexpr (sizeof(PointerType*) < sizeof(u64)) {
485
            m_value.encoded = tag | reinterpret_cast<u32>(ptr);
486
24.6k
        } else {
487
            // NOTE: Pointers in x86-64 use just 48 bits however are supposed to be
488
            //       sign extended up from the 47th bit.
489
            //       This means that all bits above the 47th should be the same as
490
            //       the 47th. When storing a pointer we thus drop the top 16 bits as
491
            //       we can recover it when extracting the pointer again.
492
            //       See also: Value::extract_pointer.
493
24.6k
            m_value.encoded = tag | (reinterpret_cast<u64>(ptr) & 0x0000ffffffffffffULL);
494
24.6k
        }
495
24.6k
    }
496
497
    template<typename PointerType>
498
    PointerType* extract_pointer() const
499
510
    {
500
510
        VERIFY(is_cell());
501
510
        return reinterpret_cast<PointerType*>(extract_pointer_bits(m_value.encoded));
502
510
    }
JS::Object* JS::Value::extract_pointer<JS::Object>() const
Line
Count
Source
499
510
    {
500
510
        VERIFY(is_cell());
501
510
        return reinterpret_cast<PointerType*>(extract_pointer_bits(m_value.encoded));
502
510
    }
Unexecuted instantiation: JS::PrimitiveString* JS::Value::extract_pointer<JS::PrimitiveString>() const
Unexecuted instantiation: JS::Symbol* JS::Value::extract_pointer<JS::Symbol>() const
Unexecuted instantiation: JS::Cell* JS::Value::extract_pointer<JS::Cell>() const
Unexecuted instantiation: JS::Accessor* JS::Value::extract_pointer<JS::Accessor>() const
Unexecuted instantiation: JS::BigInt* JS::Value::extract_pointer<JS::BigInt>() const
503
504
    [[nodiscard]] ThrowCompletionOr<Value> invoke_internal(VM&, PropertyKey const&, Optional<MarkedVector<Value>> arguments);
505
506
    ThrowCompletionOr<i32> to_i32_slow_case(VM&) const;
507
508
    union {
509
        double as_double;
510
        struct {
511
            u64 payload : 48;
512
            u64 tag : 16;
513
        };
514
        u64 encoded;
515
    } m_value { .encoded = 0 };
516
517
    friend Value js_undefined();
518
    friend Value js_null();
519
    friend ThrowCompletionOr<Value> greater_than(VM&, Value lhs, Value rhs);
520
    friend ThrowCompletionOr<Value> greater_than_equals(VM&, Value lhs, Value rhs);
521
    friend ThrowCompletionOr<Value> less_than(VM&, Value lhs, Value rhs);
522
    friend ThrowCompletionOr<Value> less_than_equals(VM&, Value lhs, Value rhs);
523
    friend ThrowCompletionOr<Value> add(VM&, Value lhs, Value rhs);
524
    friend bool same_value_non_number(Value lhs, Value rhs);
525
};
526
527
inline Value js_undefined()
528
22.3k
{
529
22.3k
    return Value(UNDEFINED_TAG << TAG_SHIFT, (u64)0);
530
22.3k
}
531
532
inline Value js_null()
533
0
{
534
0
    return Value(NULL_TAG << TAG_SHIFT, (u64)0);
535
0
}
536
537
inline Value js_nan()
538
51
{
539
51
    return Value(NAN);
540
51
}
541
542
inline Value js_infinity()
543
51
{
544
51
    return Value(INFINITY);
545
51
}
546
547
inline Value js_negative_infinity()
548
0
{
549
0
    return Value(-INFINITY);
550
0
}
551
552
ThrowCompletionOr<Value> greater_than(VM&, Value lhs, Value rhs);
553
ThrowCompletionOr<Value> greater_than_equals(VM&, Value lhs, Value rhs);
554
ThrowCompletionOr<Value> less_than(VM&, Value lhs, Value rhs);
555
ThrowCompletionOr<Value> less_than_equals(VM&, Value lhs, Value rhs);
556
ThrowCompletionOr<Value> bitwise_and(VM&, Value lhs, Value rhs);
557
ThrowCompletionOr<Value> bitwise_or(VM&, Value lhs, Value rhs);
558
ThrowCompletionOr<Value> bitwise_xor(VM&, Value lhs, Value rhs);
559
ThrowCompletionOr<Value> bitwise_not(VM&, Value);
560
ThrowCompletionOr<Value> unary_plus(VM&, Value);
561
ThrowCompletionOr<Value> unary_minus(VM&, Value);
562
ThrowCompletionOr<Value> left_shift(VM&, Value lhs, Value rhs);
563
ThrowCompletionOr<Value> right_shift(VM&, Value lhs, Value rhs);
564
ThrowCompletionOr<Value> unsigned_right_shift(VM&, Value lhs, Value rhs);
565
ThrowCompletionOr<Value> add(VM&, Value lhs, Value rhs);
566
ThrowCompletionOr<Value> sub(VM&, Value lhs, Value rhs);
567
ThrowCompletionOr<Value> mul(VM&, Value lhs, Value rhs);
568
ThrowCompletionOr<Value> div(VM&, Value lhs, Value rhs);
569
ThrowCompletionOr<Value> mod(VM&, Value lhs, Value rhs);
570
ThrowCompletionOr<Value> exp(VM&, Value lhs, Value rhs);
571
ThrowCompletionOr<Value> in(VM&, Value lhs, Value rhs);
572
ThrowCompletionOr<Value> instance_of(VM&, Value lhs, Value rhs);
573
ThrowCompletionOr<Value> ordinary_has_instance(VM&, Value lhs, Value rhs);
574
575
ThrowCompletionOr<bool> is_loosely_equal(VM&, Value lhs, Value rhs);
576
bool is_strictly_equal(Value lhs, Value rhs);
577
bool same_value(Value lhs, Value rhs);
578
bool same_value_zero(Value lhs, Value rhs);
579
bool same_value_non_number(Value lhs, Value rhs);
580
ThrowCompletionOr<TriState> is_less_than(VM&, Value lhs, Value rhs, bool left_first);
581
582
double to_integer_or_infinity(double);
583
584
enum class NumberToStringMode {
585
    WithExponent,
586
    WithoutExponent,
587
};
588
[[nodiscard]] String number_to_string(double, NumberToStringMode = NumberToStringMode::WithExponent);
589
[[nodiscard]] ByteString number_to_byte_string(double, NumberToStringMode = NumberToStringMode::WithExponent);
590
double string_to_number(StringView);
591
592
0
inline bool Value::operator==(Value const& value) const { return same_value(*this, value); }
593
594
}
595
596
namespace AK {
597
598
static_assert(sizeof(JS::Value) == sizeof(double));
599
600
template<>
601
class Optional<JS::Value> {
602
    template<typename U>
603
    friend class Optional;
604
605
public:
606
    using ValueType = JS::Value;
607
608
22
    Optional() = default;
609
610
    template<SameAs<OptionalNone> V>
611
0
    Optional(V) { }
612
613
    Optional(Optional<JS::Value> const& other)
614
0
    {
615
0
        if (other.has_value())
616
0
            m_value = other.m_value;
617
0
    }
618
619
    Optional(Optional&& other)
620
209
        : m_value(other.m_value)
621
209
    {
622
209
    }
623
624
    template<typename U = JS::Value>
625
    requires(!IsSame<OptionalNone, RemoveCVReference<U>>)
626
    explicit(!IsConvertible<U&&, JS::Value>) Optional(U&& value)
627
    requires(!IsSame<RemoveCVReference<U>, Optional<JS::Value>> && IsConstructible<JS::Value, U &&>)
628
22.2k
        : m_value(forward<U>(value))
629
22.2k
    {
630
22.2k
    }
AK::Optional<JS::Value>::Optional<JS::Value&>(JS::Value&) requires (!(IsSame<AK::Detail::__RemoveVolatile<AK::Detail::__RemoveConst<AK::Detail::__RemoveReference<JS::Value&>::Type>::Type>::Type, AK::Optional<JS::Value> >))&&(IsConstructible<JS::Value, JS::Value&>) requires !(IsSame<AK::OptionalNone, AK::Detail::__RemoveVolatile<AK::Detail::__RemoveConst<AK::Detail::__RemoveReference<JS::Value&>::Type>::Type>::Type>)
Line
Count
Source
628
871
        : m_value(forward<U>(value))
629
871
    {
630
871
    }
Unexecuted instantiation: AK::Optional<JS::Value>::Optional<JS::Value const&>(JS::Value const&) requires (!(IsSame<AK::Detail::__RemoveVolatile<AK::Detail::__RemoveConst<AK::Detail::__RemoveReference<JS::Value const&>::Type>::Type>::Type, AK::Optional<JS::Value> >))&&(IsConstructible<JS::Value, JS::Value const&>) requires !(IsSame<AK::OptionalNone, AK::Detail::__RemoveVolatile<AK::Detail::__RemoveConst<AK::Detail::__RemoveReference<JS::Value const&>::Type>::Type>::Type>)
AK::Optional<JS::Value>::Optional<JS::Value>(JS::Value&&) requires (!(IsSame<AK::Detail::__RemoveVolatile<AK::Detail::__RemoveConst<AK::Detail::__RemoveReference<JS::Value>::Type>::Type>::Type, AK::Optional<JS::Value> >))&&(IsConstructible<JS::Value, JS::Value&&>) requires !(IsSame<AK::OptionalNone, AK::Detail::__RemoveVolatile<AK::Detail::__RemoveConst<AK::Detail::__RemoveReference<JS::Value>::Type>::Type>::Type>)
Line
Count
Source
628
10.7k
        : m_value(forward<U>(value))
629
10.7k
    {
630
10.7k
    }
Unexecuted instantiation: AK::Optional<JS::Value>::Optional<JS::NonnullGCPtr<JS::ECMAScriptFunctionObject>&>(JS::NonnullGCPtr<JS::ECMAScriptFunctionObject>&) requires (!(IsSame<AK::Detail::__RemoveVolatile<AK::Detail::__RemoveConst<AK::Detail::__RemoveReference<JS::NonnullGCPtr<JS::ECMAScriptFunctionObject>&>::Type>::Type>::Type, AK::Optional<JS::Value> >))&&(IsConstructible<JS::Value, JS::NonnullGCPtr<JS::ECMAScriptFunctionObject>&>) requires !(IsSame<AK::OptionalNone, AK::Detail::__RemoveVolatile<AK::Detail::__RemoveConst<AK::Detail::__RemoveReference<JS::NonnullGCPtr<JS::ECMAScriptFunctionObject>&>::Type>::Type>::Type>)
Unexecuted instantiation: AK::Optional<JS::Value>::Optional<JS::NonnullGCPtr<JS::FunctionObject>&>(JS::NonnullGCPtr<JS::FunctionObject>&) requires (!(IsSame<AK::Detail::__RemoveVolatile<AK::Detail::__RemoveConst<AK::Detail::__RemoveReference<JS::NonnullGCPtr<JS::FunctionObject>&>::Type>::Type>::Type, AK::Optional<JS::Value> >))&&(IsConstructible<JS::Value, JS::NonnullGCPtr<JS::FunctionObject>&>) requires !(IsSame<AK::OptionalNone, AK::Detail::__RemoveVolatile<AK::Detail::__RemoveConst<AK::Detail::__RemoveReference<JS::NonnullGCPtr<JS::FunctionObject>&>::Type>::Type>::Type>)
Unexecuted instantiation: AK::Optional<JS::Value>::Optional<JS::FunctionObject*>(JS::FunctionObject*&&) requires (!(IsSame<AK::Detail::__RemoveVolatile<AK::Detail::__RemoveConst<AK::Detail::__RemoveReference<JS::FunctionObject*>::Type>::Type>::Type, AK::Optional<JS::Value> >))&&(IsConstructible<JS::Value, JS::FunctionObject*&&>) requires !(IsSame<AK::OptionalNone, AK::Detail::__RemoveVolatile<AK::Detail::__RemoveConst<AK::Detail::__RemoveReference<JS::FunctionObject*>::Type>::Type>::Type>)
Unexecuted instantiation: AK::Optional<JS::Value>::Optional<JS::GCPtr<JS::PrimitiveString>&>(JS::GCPtr<JS::PrimitiveString>&) requires (!(IsSame<AK::Detail::__RemoveVolatile<AK::Detail::__RemoveConst<AK::Detail::__RemoveReference<JS::GCPtr<JS::PrimitiveString>&>::Type>::Type>::Type, AK::Optional<JS::Value> >))&&(IsConstructible<JS::Value, JS::GCPtr<JS::PrimitiveString>&>) requires !(IsSame<AK::OptionalNone, AK::Detail::__RemoveVolatile<AK::Detail::__RemoveConst<AK::Detail::__RemoveReference<JS::GCPtr<JS::PrimitiveString>&>::Type>::Type>::Type>)
Unexecuted instantiation: AK::Optional<JS::Value>::Optional<JS::ECMAScriptFunctionObject*>(JS::ECMAScriptFunctionObject*&&) requires (!(IsSame<AK::Detail::__RemoveVolatile<AK::Detail::__RemoveConst<AK::Detail::__RemoveReference<JS::ECMAScriptFunctionObject*>::Type>::Type>::Type, AK::Optional<JS::Value> >))&&(IsConstructible<JS::Value, JS::ECMAScriptFunctionObject*&&>) requires !(IsSame<AK::OptionalNone, AK::Detail::__RemoveVolatile<AK::Detail::__RemoveConst<AK::Detail::__RemoveReference<JS::ECMAScriptFunctionObject*>::Type>::Type>::Type>)
Unexecuted instantiation: AK::Optional<JS::Value>::Optional<JS::NonnullGCPtr<JS::AsyncGenerator>&>(JS::NonnullGCPtr<JS::AsyncGenerator>&) requires (!(IsSame<AK::Detail::__RemoveVolatile<AK::Detail::__RemoveConst<AK::Detail::__RemoveReference<JS::NonnullGCPtr<JS::AsyncGenerator>&>::Type>::Type>::Type, AK::Optional<JS::Value> >))&&(IsConstructible<JS::Value, JS::NonnullGCPtr<JS::AsyncGenerator>&>) requires !(IsSame<AK::OptionalNone, AK::Detail::__RemoveVolatile<AK::Detail::__RemoveConst<AK::Detail::__RemoveReference<JS::NonnullGCPtr<JS::AsyncGenerator>&>::Type>::Type>::Type>)
Unexecuted instantiation: AK::Optional<JS::Value>::Optional<JS::NonnullGCPtr<JS::Promise> >(JS::NonnullGCPtr<JS::Promise>&&) requires (!(IsSame<AK::Detail::__RemoveVolatile<AK::Detail::__RemoveConst<AK::Detail::__RemoveReference<JS::NonnullGCPtr<JS::Promise> >::Type>::Type>::Type, AK::Optional<JS::Value> >))&&(IsConstructible<JS::Value, JS::NonnullGCPtr<JS::Promise>&&>) requires !(IsSame<AK::OptionalNone, AK::Detail::__RemoveVolatile<AK::Detail::__RemoveConst<AK::Detail::__RemoveReference<JS::NonnullGCPtr<JS::Promise> >::Type>::Type>::Type>)
Unexecuted instantiation: AK::Optional<JS::Value>::Optional<JS::NonnullGCPtr<JS::GeneratorObject>&>(JS::NonnullGCPtr<JS::GeneratorObject>&) requires (!(IsSame<AK::Detail::__RemoveVolatile<AK::Detail::__RemoveConst<AK::Detail::__RemoveReference<JS::NonnullGCPtr<JS::GeneratorObject>&>::Type>::Type>::Type, AK::Optional<JS::Value> >))&&(IsConstructible<JS::Value, JS::NonnullGCPtr<JS::GeneratorObject>&>) requires !(IsSame<AK::OptionalNone, AK::Detail::__RemoveVolatile<AK::Detail::__RemoveConst<AK::Detail::__RemoveReference<JS::NonnullGCPtr<JS::GeneratorObject>&>::Type>::Type>::Type>)
AK::Optional<JS::Value>::Optional<JS::NonnullGCPtr<JS::PrimitiveString> >(JS::NonnullGCPtr<JS::PrimitiveString>&&) requires (!(IsSame<AK::Detail::__RemoveVolatile<AK::Detail::__RemoveConst<AK::Detail::__RemoveReference<JS::NonnullGCPtr<JS::PrimitiveString> >::Type>::Type>::Type, AK::Optional<JS::Value> >))&&(IsConstructible<JS::Value, JS::NonnullGCPtr<JS::PrimitiveString>&&>) requires !(IsSame<AK::OptionalNone, AK::Detail::__RemoveVolatile<AK::Detail::__RemoveConst<AK::Detail::__RemoveReference<JS::NonnullGCPtr<JS::PrimitiveString> >::Type>::Type>::Type>)
Line
Count
Source
628
10.7k
        : m_value(forward<U>(value))
629
10.7k
    {
630
10.7k
    }
Unexecuted instantiation: AK::Optional<JS::Value>::Optional<JS::NonnullGCPtr<JS::Array> >(JS::NonnullGCPtr<JS::Array>&&) requires (!(IsSame<AK::Detail::__RemoveVolatile<AK::Detail::__RemoveConst<AK::Detail::__RemoveReference<JS::NonnullGCPtr<JS::Array> >::Type>::Type>::Type, AK::Optional<JS::Value> >))&&(IsConstructible<JS::Value, JS::NonnullGCPtr<JS::Array>&&>) requires !(IsSame<AK::OptionalNone, AK::Detail::__RemoveVolatile<AK::Detail::__RemoveConst<AK::Detail::__RemoveReference<JS::NonnullGCPtr<JS::Array> >::Type>::Type>::Type>)
Unexecuted instantiation: AK::Optional<JS::Value>::Optional<JS::GCPtr<JS::Object>&>(JS::GCPtr<JS::Object>&) requires (!(IsSame<AK::Detail::__RemoveVolatile<AK::Detail::__RemoveConst<AK::Detail::__RemoveReference<JS::GCPtr<JS::Object>&>::Type>::Type>::Type, AK::Optional<JS::Value> >))&&(IsConstructible<JS::Value, JS::GCPtr<JS::Object>&>) requires !(IsSame<AK::OptionalNone, AK::Detail::__RemoveVolatile<AK::Detail::__RemoveConst<AK::Detail::__RemoveReference<JS::GCPtr<JS::Object>&>::Type>::Type>::Type>)
Unexecuted instantiation: AK::Optional<JS::Value>::Optional<JS::NonnullGCPtr<JS::PrimitiveString>&>(JS::NonnullGCPtr<JS::PrimitiveString>&) requires (!(IsSame<AK::Detail::__RemoveVolatile<AK::Detail::__RemoveConst<AK::Detail::__RemoveReference<JS::NonnullGCPtr<JS::PrimitiveString>&>::Type>::Type>::Type, AK::Optional<JS::Value> >))&&(IsConstructible<JS::Value, JS::NonnullGCPtr<JS::PrimitiveString>&>) requires !(IsSame<AK::OptionalNone, AK::Detail::__RemoveVolatile<AK::Detail::__RemoveConst<AK::Detail::__RemoveReference<JS::NonnullGCPtr<JS::PrimitiveString>&>::Type>::Type>::Type>)
Unexecuted instantiation: AK::Optional<JS::Value>::Optional<JS::NonnullGCPtr<JS::Array>&>(JS::NonnullGCPtr<JS::Array>&) requires (!(IsSame<AK::Detail::__RemoveVolatile<AK::Detail::__RemoveConst<AK::Detail::__RemoveReference<JS::NonnullGCPtr<JS::Array>&>::Type>::Type>::Type, AK::Optional<JS::Value> >))&&(IsConstructible<JS::Value, JS::NonnullGCPtr<JS::Array>&>) requires !(IsSame<AK::OptionalNone, AK::Detail::__RemoveVolatile<AK::Detail::__RemoveConst<AK::Detail::__RemoveReference<JS::NonnullGCPtr<JS::Array>&>::Type>::Type>::Type>)
Unexecuted instantiation: AK::Optional<JS::Value>::Optional<Web::DOM::Element*>(Web::DOM::Element*&&) requires (!(IsSame<AK::Detail::__RemoveVolatile<AK::Detail::__RemoveConst<AK::Detail::__RemoveReference<Web::DOM::Element*>::Type>::Type>::Type, AK::Optional<JS::Value> >))&&(IsConstructible<JS::Value, Web::DOM::Element*&&>) requires !(IsSame<AK::OptionalNone, AK::Detail::__RemoveVolatile<AK::Detail::__RemoveConst<AK::Detail::__RemoveReference<Web::DOM::Element*>::Type>::Type>::Type>)
Unexecuted instantiation: AK::Optional<JS::Value>::Optional<Web::DOM::MutationObserver*&>(Web::DOM::MutationObserver*&) requires (!(IsSame<AK::Detail::__RemoveVolatile<AK::Detail::__RemoveConst<AK::Detail::__RemoveReference<Web::DOM::MutationObserver*&>::Type>::Type>::Type, AK::Optional<JS::Value> >))&&(IsConstructible<JS::Value, Web::DOM::MutationObserver*&>) requires !(IsSame<AK::OptionalNone, AK::Detail::__RemoveVolatile<AK::Detail::__RemoveConst<AK::Detail::__RemoveReference<Web::DOM::MutationObserver*&>::Type>::Type>::Type>)
Unexecuted instantiation: AK::Optional<JS::Value>::Optional<Web::CSS::CSSRule const*>(Web::CSS::CSSRule const*&&) requires (!(IsSame<AK::Detail::__RemoveVolatile<AK::Detail::__RemoveConst<AK::Detail::__RemoveReference<Web::CSS::CSSRule const*>::Type>::Type>::Type, AK::Optional<JS::Value> >))&&(IsConstructible<JS::Value, Web::CSS::CSSRule const*&&>) requires !(IsSame<AK::OptionalNone, AK::Detail::__RemoveVolatile<AK::Detail::__RemoveConst<AK::Detail::__RemoveReference<Web::CSS::CSSRule const*>::Type>::Type>::Type>)
Unexecuted instantiation: AK::Optional<JS::Value>::Optional<Web::CSS::CSSStyleSheet*>(Web::CSS::CSSStyleSheet*&&) requires (!(IsSame<AK::Detail::__RemoveVolatile<AK::Detail::__RemoveConst<AK::Detail::__RemoveReference<Web::CSS::CSSStyleSheet*>::Type>::Type>::Type, AK::Optional<JS::Value> >))&&(IsConstructible<JS::Value, Web::CSS::CSSStyleSheet*&&>) requires !(IsSame<AK::OptionalNone, AK::Detail::__RemoveVolatile<AK::Detail::__RemoveConst<AK::Detail::__RemoveReference<Web::CSS::CSSStyleSheet*>::Type>::Type>::Type>)
Unexecuted instantiation: AK::Optional<JS::Value>::Optional<Web::IntersectionObserver::IntersectionObserver*>(Web::IntersectionObserver::IntersectionObserver*&&) requires (!(IsSame<AK::Detail::__RemoveVolatile<AK::Detail::__RemoveConst<AK::Detail::__RemoveReference<Web::IntersectionObserver::IntersectionObserver*>::Type>::Type>::Type, AK::Optional<JS::Value> >))&&(IsConstructible<JS::Value, Web::IntersectionObserver::IntersectionObserver*&&>) requires !(IsSame<AK::OptionalNone, AK::Detail::__RemoveVolatile<AK::Detail::__RemoveConst<AK::Detail::__RemoveReference<Web::IntersectionObserver::IntersectionObserver*>::Type>::Type>::Type>)
Unexecuted instantiation: AK::Optional<JS::Value>::Optional<Web::DOM::EventTarget*&>(Web::DOM::EventTarget*&) requires (!(IsSame<AK::Detail::__RemoveVolatile<AK::Detail::__RemoveConst<AK::Detail::__RemoveReference<Web::DOM::EventTarget*&>::Type>::Type>::Type, AK::Optional<JS::Value> >))&&(IsConstructible<JS::Value, Web::DOM::EventTarget*&>) requires !(IsSame<AK::OptionalNone, AK::Detail::__RemoveVolatile<AK::Detail::__RemoveConst<AK::Detail::__RemoveReference<Web::DOM::EventTarget*&>::Type>::Type>::Type>)
Unexecuted instantiation: AK::Optional<JS::Value>::Optional<Web::DOM::Attr const*>(Web::DOM::Attr const*&&) requires (!(IsSame<AK::Detail::__RemoveVolatile<AK::Detail::__RemoveConst<AK::Detail::__RemoveReference<Web::DOM::Attr const*>::Type>::Type>::Type, AK::Optional<JS::Value> >))&&(IsConstructible<JS::Value, Web::DOM::Attr const*&&>) requires !(IsSame<AK::OptionalNone, AK::Detail::__RemoveVolatile<AK::Detail::__RemoveConst<AK::Detail::__RemoveReference<Web::DOM::Attr const*>::Type>::Type>::Type>)
Unexecuted instantiation: AK::Optional<JS::Value>::Optional<Web::DOM::Node*>(Web::DOM::Node*&&) requires (!(IsSame<AK::Detail::__RemoveVolatile<AK::Detail::__RemoveConst<AK::Detail::__RemoveReference<Web::DOM::Node*>::Type>::Type>::Type, AK::Optional<JS::Value> >))&&(IsConstructible<JS::Value, Web::DOM::Node*&&>) requires !(IsSame<AK::OptionalNone, AK::Detail::__RemoveVolatile<AK::Detail::__RemoveConst<AK::Detail::__RemoveReference<Web::DOM::Node*>::Type>::Type>::Type>)
Unexecuted instantiation: AK::Optional<JS::Value>::Optional<JS::NonnullGCPtr<Web::WebIDL::DOMException>&>(JS::NonnullGCPtr<Web::WebIDL::DOMException>&) requires (!(IsSame<AK::Detail::__RemoveVolatile<AK::Detail::__RemoveConst<AK::Detail::__RemoveReference<JS::NonnullGCPtr<Web::WebIDL::DOMException>&>::Type>::Type>::Type, AK::Optional<JS::Value> >))&&(IsConstructible<JS::Value, JS::NonnullGCPtr<Web::WebIDL::DOMException>&>) requires !(IsSame<AK::OptionalNone, AK::Detail::__RemoveVolatile<AK::Detail::__RemoveConst<AK::Detail::__RemoveReference<JS::NonnullGCPtr<Web::WebIDL::DOMException>&>::Type>::Type>::Type>)
Unexecuted instantiation: AK::Optional<JS::Value>::Optional<Web::Geometry::DOMRect*>(Web::Geometry::DOMRect*&&) requires (!(IsSame<AK::Detail::__RemoveVolatile<AK::Detail::__RemoveConst<AK::Detail::__RemoveReference<Web::Geometry::DOMRect*>::Type>::Type>::Type, AK::Optional<JS::Value> >))&&(IsConstructible<JS::Value, Web::Geometry::DOMRect*&&>) requires !(IsSame<AK::OptionalNone, AK::Detail::__RemoveVolatile<AK::Detail::__RemoveConst<AK::Detail::__RemoveReference<Web::Geometry::DOMRect*>::Type>::Type>::Type>)
Unexecuted instantiation: AK::Optional<JS::Value>::Optional<JS::GCPtr<Web::DOM::Element> >(JS::GCPtr<Web::DOM::Element>&&) requires (!(IsSame<AK::Detail::__RemoveVolatile<AK::Detail::__RemoveConst<AK::Detail::__RemoveReference<JS::GCPtr<Web::DOM::Element> >::Type>::Type>::Type, AK::Optional<JS::Value> >))&&(IsConstructible<JS::Value, JS::GCPtr<Web::DOM::Element>&&>) requires !(IsSame<AK::OptionalNone, AK::Detail::__RemoveVolatile<AK::Detail::__RemoveConst<AK::Detail::__RemoveReference<JS::GCPtr<Web::DOM::Element> >::Type>::Type>::Type>)
Unexecuted instantiation: AK::Optional<JS::Value>::Optional<Web::FileAPI::File*>(Web::FileAPI::File*&&) requires (!(IsSame<AK::Detail::__RemoveVolatile<AK::Detail::__RemoveConst<AK::Detail::__RemoveReference<Web::FileAPI::File*>::Type>::Type>::Type, AK::Optional<JS::Value> >))&&(IsConstructible<JS::Value, Web::FileAPI::File*&&>) requires !(IsSame<AK::OptionalNone, AK::Detail::__RemoveVolatile<AK::Detail::__RemoveConst<AK::Detail::__RemoveReference<Web::FileAPI::File*>::Type>::Type>::Type>)
Unexecuted instantiation: AK::Optional<JS::Value>::Optional<JS::NonnullGCPtr<Web::HTML::AudioTrack> const&>(JS::NonnullGCPtr<Web::HTML::AudioTrack> const&) requires (!(IsSame<AK::Detail::__RemoveVolatile<AK::Detail::__RemoveConst<AK::Detail::__RemoveReference<JS::NonnullGCPtr<Web::HTML::AudioTrack> const&>::Type>::Type>::Type, AK::Optional<JS::Value> >))&&(IsConstructible<JS::Value, JS::NonnullGCPtr<Web::HTML::AudioTrack> const&>) requires !(IsSame<AK::OptionalNone, AK::Detail::__RemoveVolatile<AK::Detail::__RemoveConst<AK::Detail::__RemoveReference<JS::NonnullGCPtr<Web::HTML::AudioTrack> const&>::Type>::Type>::Type>)
Unexecuted instantiation: AK::Optional<JS::Value>::Optional<JS::NonnullGCPtr<JS::NativeFunction> >(JS::NonnullGCPtr<JS::NativeFunction>&&) requires (!(IsSame<AK::Detail::__RemoveVolatile<AK::Detail::__RemoveConst<AK::Detail::__RemoveReference<JS::NonnullGCPtr<JS::NativeFunction> >::Type>::Type>::Type, AK::Optional<JS::Value> >))&&(IsConstructible<JS::Value, JS::NonnullGCPtr<JS::NativeFunction>&&>) requires !(IsSame<AK::OptionalNone, AK::Detail::__RemoveVolatile<AK::Detail::__RemoveConst<AK::Detail::__RemoveReference<JS::NonnullGCPtr<JS::NativeFunction> >::Type>::Type>::Type>)
Unexecuted instantiation: AK::Optional<JS::Value>::Optional<JS::NonnullGCPtr<Web::HTML::TextTrack> const&>(JS::NonnullGCPtr<Web::HTML::TextTrack> const&) requires (!(IsSame<AK::Detail::__RemoveVolatile<AK::Detail::__RemoveConst<AK::Detail::__RemoveReference<JS::NonnullGCPtr<Web::HTML::TextTrack> const&>::Type>::Type>::Type, AK::Optional<JS::Value> >))&&(IsConstructible<JS::Value, JS::NonnullGCPtr<Web::HTML::TextTrack> const&>) requires !(IsSame<AK::OptionalNone, AK::Detail::__RemoveVolatile<AK::Detail::__RemoveConst<AK::Detail::__RemoveReference<JS::NonnullGCPtr<Web::HTML::TextTrack> const&>::Type>::Type>::Type>)
Unexecuted instantiation: AK::Optional<JS::Value>::Optional<JS::NonnullGCPtr<Web::HTML::VideoTrack> const&>(JS::NonnullGCPtr<Web::HTML::VideoTrack> const&) requires (!(IsSame<AK::Detail::__RemoveVolatile<AK::Detail::__RemoveConst<AK::Detail::__RemoveReference<JS::NonnullGCPtr<Web::HTML::VideoTrack> const&>::Type>::Type>::Type, AK::Optional<JS::Value> >))&&(IsConstructible<JS::Value, JS::NonnullGCPtr<Web::HTML::VideoTrack> const&>) requires !(IsSame<AK::OptionalNone, AK::Detail::__RemoveVolatile<AK::Detail::__RemoveConst<AK::Detail::__RemoveReference<JS::NonnullGCPtr<Web::HTML::VideoTrack> const&>::Type>::Type>::Type>)
Unexecuted instantiation: AK::Optional<JS::Value>::Optional<Web::HTML::MimeType*>(Web::HTML::MimeType*&&) requires (!(IsSame<AK::Detail::__RemoveVolatile<AK::Detail::__RemoveConst<AK::Detail::__RemoveReference<Web::HTML::MimeType*>::Type>::Type>::Type, AK::Optional<JS::Value> >))&&(IsConstructible<JS::Value, Web::HTML::MimeType*&&>) requires !(IsSame<AK::OptionalNone, AK::Detail::__RemoveVolatile<AK::Detail::__RemoveConst<AK::Detail::__RemoveReference<Web::HTML::MimeType*>::Type>::Type>::Type>)
Unexecuted instantiation: AK::Optional<JS::Value>::Optional<Web::HTML::Plugin*>(Web::HTML::Plugin*&&) requires (!(IsSame<AK::Detail::__RemoveVolatile<AK::Detail::__RemoveConst<AK::Detail::__RemoveReference<Web::HTML::Plugin*>::Type>::Type>::Type, AK::Optional<JS::Value> >))&&(IsConstructible<JS::Value, Web::HTML::Plugin*&&>) requires !(IsSame<AK::OptionalNone, AK::Detail::__RemoveVolatile<AK::Detail::__RemoveConst<AK::Detail::__RemoveReference<Web::HTML::Plugin*>::Type>::Type>::Type>)
Unexecuted instantiation: AK::Optional<JS::Value>::Optional<Web::Bindings::PlatformObject*>(Web::Bindings::PlatformObject*&&) requires (!(IsSame<AK::Detail::__RemoveVolatile<AK::Detail::__RemoveConst<AK::Detail::__RemoveReference<Web::Bindings::PlatformObject*>::Type>::Type>::Type, AK::Optional<JS::Value> >))&&(IsConstructible<JS::Value, Web::Bindings::PlatformObject*&&>) requires !(IsSame<AK::OptionalNone, AK::Detail::__RemoveVolatile<AK::Detail::__RemoveConst<AK::Detail::__RemoveReference<Web::Bindings::PlatformObject*>::Type>::Type>::Type>)
Unexecuted instantiation: AK::Optional<JS::Value>::Optional<JS::NonnullGCPtr<Web::PerformanceTimeline::PerformanceObserver>&>(JS::NonnullGCPtr<Web::PerformanceTimeline::PerformanceObserver>&) requires (!(IsSame<AK::Detail::__RemoveVolatile<AK::Detail::__RemoveConst<AK::Detail::__RemoveReference<JS::NonnullGCPtr<Web::PerformanceTimeline::PerformanceObserver>&>::Type>::Type>::Type, AK::Optional<JS::Value> >))&&(IsConstructible<JS::Value, JS::NonnullGCPtr<Web::PerformanceTimeline::PerformanceObserver>&>) requires !(IsSame<AK::OptionalNone, AK::Detail::__RemoveVolatile<AK::Detail::__RemoveConst<AK::Detail::__RemoveReference<JS::NonnullGCPtr<Web::PerformanceTimeline::PerformanceObserver>&>::Type>::Type>::Type>)
Unexecuted instantiation: AK::Optional<JS::Value>::Optional<JS::GCPtr<Web::HTML::WindowProxy> >(JS::GCPtr<Web::HTML::WindowProxy>&&) requires (!(IsSame<AK::Detail::__RemoveVolatile<AK::Detail::__RemoveConst<AK::Detail::__RemoveReference<JS::GCPtr<Web::HTML::WindowProxy> >::Type>::Type>::Type, AK::Optional<JS::Value> >))&&(IsConstructible<JS::Value, JS::GCPtr<Web::HTML::WindowProxy>&&>) requires !(IsSame<AK::OptionalNone, AK::Detail::__RemoveVolatile<AK::Detail::__RemoveConst<AK::Detail::__RemoveReference<JS::GCPtr<Web::HTML::WindowProxy> >::Type>::Type>::Type>)
Unexecuted instantiation: AK::Optional<JS::Value>::Optional<JS::GCPtr<Web::HTML::WindowProxy>&>(JS::GCPtr<Web::HTML::WindowProxy>&) requires (!(IsSame<AK::Detail::__RemoveVolatile<AK::Detail::__RemoveConst<AK::Detail::__RemoveReference<JS::GCPtr<Web::HTML::WindowProxy>&>::Type>::Type>::Type, AK::Optional<JS::Value> >))&&(IsConstructible<JS::Value, JS::GCPtr<Web::HTML::WindowProxy>&>) requires !(IsSame<AK::OptionalNone, AK::Detail::__RemoveVolatile<AK::Detail::__RemoveConst<AK::Detail::__RemoveReference<JS::GCPtr<Web::HTML::WindowProxy>&>::Type>::Type>::Type>)
Unexecuted instantiation: AK::Optional<JS::Value>::Optional<JS::NonnullGCPtr<Web::HTML::DataTransferItem> >(JS::NonnullGCPtr<Web::HTML::DataTransferItem>&&) requires (!(IsSame<AK::Detail::__RemoveVolatile<AK::Detail::__RemoveConst<AK::Detail::__RemoveReference<JS::NonnullGCPtr<Web::HTML::DataTransferItem> >::Type>::Type>::Type, AK::Optional<JS::Value> >))&&(IsConstructible<JS::Value, JS::NonnullGCPtr<Web::HTML::DataTransferItem>&&>) requires !(IsSame<AK::OptionalNone, AK::Detail::__RemoveVolatile<AK::Detail::__RemoveConst<AK::Detail::__RemoveReference<JS::NonnullGCPtr<Web::HTML::DataTransferItem> >::Type>::Type>::Type>)
Unexecuted instantiation: AK::Optional<JS::Value>::Optional<JS::NonnullGCPtr<JS::Object>&>(JS::NonnullGCPtr<JS::Object>&) requires (!(IsSame<AK::Detail::__RemoveVolatile<AK::Detail::__RemoveConst<AK::Detail::__RemoveReference<JS::NonnullGCPtr<JS::Object>&>::Type>::Type>::Type, AK::Optional<JS::Value> >))&&(IsConstructible<JS::Value, JS::NonnullGCPtr<JS::Object>&>) requires !(IsSame<AK::OptionalNone, AK::Detail::__RemoveVolatile<AK::Detail::__RemoveConst<AK::Detail::__RemoveReference<JS::NonnullGCPtr<JS::Object>&>::Type>::Type>::Type>)
Unexecuted instantiation: AK::Optional<JS::Value>::Optional<JS::NonnullGCPtr<Web::HTML::TextTrackCue> const&>(JS::NonnullGCPtr<Web::HTML::TextTrackCue> const&) requires (!(IsSame<AK::Detail::__RemoveVolatile<AK::Detail::__RemoveConst<AK::Detail::__RemoveReference<JS::NonnullGCPtr<Web::HTML::TextTrackCue> const&>::Type>::Type>::Type, AK::Optional<JS::Value> >))&&(IsConstructible<JS::Value, JS::NonnullGCPtr<Web::HTML::TextTrackCue> const&>) requires !(IsSame<AK::OptionalNone, AK::Detail::__RemoveVolatile<AK::Detail::__RemoveConst<AK::Detail::__RemoveReference<JS::NonnullGCPtr<Web::HTML::TextTrackCue> const&>::Type>::Type>::Type>)
631
632
    template<SameAs<OptionalNone> V>
633
    Optional& operator=(V)
634
    {
635
        clear();
636
        return *this;
637
    }
638
639
    Optional& operator=(Optional const& other)
640
0
    {
641
0
        if (this != &other) {
642
0
            clear();
643
0
            m_value = other.m_value;
644
0
        }
645
0
        return *this;
646
0
    }
647
648
    Optional& operator=(Optional&& other)
649
22
    {
650
22
        if (this != &other) {
651
22
            clear();
652
22
            m_value = other.m_value;
653
22
        }
654
22
        return *this;
655
22
    }
656
657
    template<typename O>
658
    ALWAYS_INLINE bool operator==(Optional<O> const& other) const
659
0
    {
660
0
        return has_value() == other.has_value() && (!has_value() || value() == other.value());
661
0
    }
662
663
    template<typename O>
664
    ALWAYS_INLINE bool operator==(O const& other) const
665
0
    {
666
0
        return has_value() && value() == other;
667
0
    }
668
669
    void clear()
670
22
    {
671
22
        m_value = {};
672
22
    }
673
674
    [[nodiscard]] bool has_value() const
675
44.8k
    {
676
44.8k
        return !m_value.is_empty();
677
44.8k
    }
678
679
    [[nodiscard]] JS::Value& value() &
680
165
    {
681
165
        VERIFY(has_value());
682
165
        return m_value;
683
165
    }
684
685
    [[nodiscard]] JS::Value const& value() const&
686
22.2k
    {
687
22.2k
        VERIFY(has_value());
688
22.2k
        return m_value;
689
22.2k
    }
690
691
    [[nodiscard]] JS::Value value() &&
692
0
    {
693
0
        return release_value();
694
0
    }
695
696
    [[nodiscard]] JS::Value release_value()
697
0
    {
698
0
        VERIFY(has_value());
699
0
        JS::Value released_value = m_value;
700
0
        clear();
701
0
        return released_value;
702
0
    }
703
704
    JS::Value value_or(JS::Value const& fallback) const&
705
22.2k
    {
706
22.2k
        if (has_value())
707
22.2k
            return value();
708
0
        return fallback;
709
22.2k
    }
710
711
    [[nodiscard]] JS::Value value_or(JS::Value&& fallback) &&
712
0
    {
713
0
        if (has_value())
714
0
            return value();
715
0
        return fallback;
716
0
    }
717
718
0
    JS::Value const& operator*() const { return value(); }
719
11
    JS::Value& operator*() { return value(); }
720
721
10
    JS::Value const* operator->() const { return &value(); }
722
110
    JS::Value* operator->() { return &value(); }
723
724
private:
725
    JS::Value m_value;
726
};
727
728
template<>
729
struct Formatter<JS::Value> : Formatter<StringView> {
730
    ErrorOr<void> format(FormatBuilder& builder, JS::Value value)
731
0
    {
732
0
        if (value.is_empty())
733
0
            return Formatter<StringView>::format(builder, "<empty>"sv);
734
0
        return Formatter<StringView>::format(builder, value.to_string_without_side_effects());
735
0
    }
736
};
737
738
template<>
739
struct Traits<JS::Value> : DefaultTraits<JS::Value> {
740
0
    static unsigned hash(JS::Value value) { return Traits<u64>::hash(value.encoded()); }
741
0
    static constexpr bool is_trivial() { return true; }
742
};
743
744
}