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.cpp
Line
Count
Source
1
/*
2
 * Copyright (c) 2020, 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
#include <AK/AllOf.h>
10
#include <AK/Assertions.h>
11
#include <AK/ByteString.h>
12
#include <AK/CharacterTypes.h>
13
#include <AK/FloatingPointStringConversions.h>
14
#include <AK/StringBuilder.h>
15
#include <AK/StringFloatingPointConversions.h>
16
#include <AK/Utf8View.h>
17
#include <LibCrypto/BigInt/SignedBigInteger.h>
18
#include <LibCrypto/NumberTheory/ModularFunctions.h>
19
#include <LibJS/Runtime/AbstractOperations.h>
20
#include <LibJS/Runtime/Accessor.h>
21
#include <LibJS/Runtime/Array.h>
22
#include <LibJS/Runtime/BigInt.h>
23
#include <LibJS/Runtime/BigIntObject.h>
24
#include <LibJS/Runtime/BooleanObject.h>
25
#include <LibJS/Runtime/BoundFunction.h>
26
#include <LibJS/Runtime/Completion.h>
27
#include <LibJS/Runtime/Error.h>
28
#include <LibJS/Runtime/FunctionObject.h>
29
#include <LibJS/Runtime/GlobalObject.h>
30
#include <LibJS/Runtime/NativeFunction.h>
31
#include <LibJS/Runtime/NumberObject.h>
32
#include <LibJS/Runtime/Object.h>
33
#include <LibJS/Runtime/PrimitiveString.h>
34
#include <LibJS/Runtime/ProxyObject.h>
35
#include <LibJS/Runtime/RegExpObject.h>
36
#include <LibJS/Runtime/StringObject.h>
37
#include <LibJS/Runtime/StringPrototype.h>
38
#include <LibJS/Runtime/SymbolObject.h>
39
#include <LibJS/Runtime/Utf16String.h>
40
#include <LibJS/Runtime/VM.h>
41
#include <LibJS/Runtime/Value.h>
42
#include <LibJS/Runtime/ValueInlines.h>
43
#include <math.h>
44
45
namespace JS {
46
47
static inline bool same_type_for_equality(Value const& lhs, Value const& rhs)
48
0
{
49
    // If the top two bytes are identical then either:
50
    // both are NaN boxed Values with the same type
51
    // or they are doubles which happen to have the same top bytes.
52
0
    if ((lhs.encoded() & TAG_EXTRACTION) == (rhs.encoded() & TAG_EXTRACTION))
53
0
        return true;
54
55
0
    if (lhs.is_number() && rhs.is_number())
56
0
        return true;
57
58
    // One of the Values is not a number and they do not have the same tag
59
0
    return false;
60
0
}
61
62
static Crypto::SignedBigInteger const BIGINT_ZERO { 0 };
63
64
ALWAYS_INLINE bool both_number(Value const& lhs, Value const& rhs)
65
0
{
66
0
    return lhs.is_number() && rhs.is_number();
67
0
}
68
69
ALWAYS_INLINE bool both_bigint(Value const& lhs, Value const& rhs)
70
0
{
71
0
    return lhs.is_bigint() && rhs.is_bigint();
72
0
}
73
74
// 6.1.6.1.20 Number::toString ( x ), https://tc39.es/ecma262/#sec-numeric-types-number-tostring
75
// Implementation for radix = 10
76
static void number_to_string_impl(StringBuilder& builder, double d, NumberToStringMode mode)
77
0
{
78
0
    auto convert_to_decimal_digits_array = [](auto x, auto& digits, auto& length) {
79
0
        for (; x; x /= 10)
80
0
            digits[length++] = x % 10 | '0';
81
0
        for (i32 i = 0; 2 * i + 1 < length; ++i)
82
0
            swap(digits[i], digits[length - i - 1]);
83
0
    };
Unexecuted instantiation: Value.cpp:auto JS::number_to_string_impl(AK::StringBuilder&, double, JS::NumberToStringMode)::$_0::operator()<unsigned long, AK::Array<char, 20ul>, int>(unsigned long, AK::Array<char, 20ul>&, int&) const
Unexecuted instantiation: Value.cpp:auto JS::number_to_string_impl(AK::StringBuilder&, double, JS::NumberToStringMode)::$_0::operator()<int, AK::Array<char, 5ul>, int>(int, AK::Array<char, 5ul>&, int&) const
84
85
    // 1. If x is NaN, return "NaN".
86
0
    if (isnan(d)) {
87
0
        builder.append("NaN"sv);
88
0
        return;
89
0
    }
90
91
    // 2. If x is +0𝔽 or -0𝔽, return "0".
92
0
    if (d == +0.0 || d == -0.0) {
93
0
        builder.append("0"sv);
94
0
        return;
95
0
    }
96
97
    // 4. If x is +∞𝔽, return "Infinity".
98
0
    if (isinf(d)) {
99
0
        if (d > 0) {
100
0
            builder.append("Infinity"sv);
101
0
            return;
102
0
        }
103
104
0
        builder.append("-Infinity"sv);
105
0
        return;
106
0
    }
107
108
    // 5. Let n, k, and s be integers such that k ≥ 1, radix ^ (k - 1) ≤ s < radix ^ k,
109
    // 𝔽(s × radix ^ (n - k)) is x, and k is as small as possible. Note that k is the number of
110
    // digits in the representation of s using radix radix, that s is not divisible by radix, and
111
    // that the least significant digit of s is not necessarily uniquely determined by these criteria.
112
    //
113
    // Note: guarantees provided by convert_floating_point_to_decimal_exponential_form satisfy
114
    //       requirements of NOTE 2.
115
0
    auto [sign, mantissa, exponent] = convert_floating_point_to_decimal_exponential_form(d);
116
0
    i32 k = 0;
117
0
    AK::Array<char, 20> mantissa_digits;
118
0
    convert_to_decimal_digits_array(mantissa, mantissa_digits, k);
119
120
0
    i32 n = exponent + k; // s = mantissa
121
122
    // 3. If x < -0𝔽, return the string-concatenation of "-" and Number::toString(-x, radix).
123
0
    if (sign)
124
0
        builder.append('-');
125
126
    // Non-standard: Intl needs number-to-string conversions for extremely large numbers without any
127
    // exponential formatting, as it will handle such formatting itself in a locale-aware way.
128
0
    bool force_no_exponent = mode == NumberToStringMode::WithoutExponent;
129
130
    // 6. If radix ≠ 10 or n is in the inclusive interval from -5 to 21, then
131
0
    if ((n >= -5 && n <= 21) || force_no_exponent) {
132
        // a. If n ≥ k, then
133
0
        if (n >= k) {
134
            // i. Return the string-concatenation of:
135
            // the code units of the k digits of the representation of s using radix radix
136
0
            builder.append(mantissa_digits.data(), k);
137
            // n - k occurrences of the code unit 0x0030 (DIGIT ZERO)
138
0
            builder.append_repeated('0', n - k);
139
            // b. Else if n > 0, then
140
0
        } else if (n > 0) {
141
            // i. Return the string-concatenation of:
142
            // the code units of the most significant n digits of the representation of s using radix radix
143
0
            builder.append(mantissa_digits.data(), n);
144
            // the code unit 0x002E (FULL STOP)
145
0
            builder.append('.');
146
            // the code units of the remaining k - n digits of the representation of s using radix radix
147
0
            builder.append(mantissa_digits.data() + n, k - n);
148
            // c. Else,
149
0
        } else {
150
            // i. Assert: n ≤ 0.
151
0
            VERIFY(n <= 0);
152
            // ii. Return the string-concatenation of:
153
            // the code unit 0x0030 (DIGIT ZERO)
154
0
            builder.append('0');
155
            // the code unit 0x002E (FULL STOP)
156
0
            builder.append('.');
157
            // -n occurrences of the code unit 0x0030 (DIGIT ZERO)
158
0
            builder.append_repeated('0', -n);
159
            // the code units of the k digits of the representation of s using radix radix
160
0
            builder.append(mantissa_digits.data(), k);
161
0
        }
162
163
0
        return;
164
0
    }
165
166
    // 7. NOTE: In this case, the input will be represented using scientific E notation, such as 1.2e+3.
167
168
    // 9. If n < 0, then
169
    //     a. Let exponentSign be the code unit 0x002D (HYPHEN-MINUS).
170
    // 10. Else,
171
    //     a. Let exponentSign be the code unit 0x002B (PLUS SIGN).
172
0
    char exponent_sign = n < 0 ? '-' : '+';
173
174
0
    AK::Array<char, 5> exponent_digits;
175
0
    i32 exponent_length = 0;
176
0
    convert_to_decimal_digits_array(abs(n - 1), exponent_digits, exponent_length);
177
178
    // 11. If k is 1, then
179
0
    if (k == 1) {
180
        // a. Return the string-concatenation of:
181
        // the code unit of the single digit of s
182
0
        builder.append(mantissa_digits[0]);
183
        // the code unit 0x0065 (LATIN SMALL LETTER E)
184
0
        builder.append('e');
185
        // exponentSign
186
0
        builder.append(exponent_sign);
187
        // the code units of the decimal representation of abs(n - 1)
188
0
        builder.append(exponent_digits.data(), exponent_length);
189
190
0
        return;
191
0
    }
192
193
    // 12. Return the string-concatenation of:
194
    // the code unit of the most significant digit of the decimal representation of s
195
0
    builder.append(mantissa_digits[0]);
196
    // the code unit 0x002E (FULL STOP)
197
0
    builder.append('.');
198
    // the code units of the remaining k - 1 digits of the decimal representation of s
199
0
    builder.append(mantissa_digits.data() + 1, k - 1);
200
    // the code unit 0x0065 (LATIN SMALL LETTER E)
201
0
    builder.append('e');
202
    // exponentSign
203
0
    builder.append(exponent_sign);
204
    // the code units of the decimal representation of abs(n - 1)
205
0
    builder.append(exponent_digits.data(), exponent_length);
206
0
}
207
208
String number_to_string(double d, NumberToStringMode mode)
209
0
{
210
0
    StringBuilder builder;
211
0
    number_to_string_impl(builder, d, mode);
212
0
    return builder.to_string().release_value();
213
0
}
214
215
ByteString number_to_byte_string(double d, NumberToStringMode mode)
216
0
{
217
0
    StringBuilder builder;
218
0
    number_to_string_impl(builder, d, mode);
219
0
    return builder.to_byte_string();
220
0
}
221
222
// 7.2.2 IsArray ( argument ), https://tc39.es/ecma262/#sec-isarray
223
ThrowCompletionOr<bool> Value::is_array(VM& vm) const
224
0
{
225
    // 1. If argument is not an Object, return false.
226
0
    if (!is_object())
227
0
        return false;
228
229
0
    auto const& object = as_object();
230
231
    // 2. If argument is an Array exotic object, return true.
232
0
    if (is<Array>(object))
233
0
        return true;
234
235
    // 3. If argument is a Proxy exotic object, then
236
0
    if (is<ProxyObject>(object)) {
237
0
        auto const& proxy = static_cast<ProxyObject const&>(object);
238
239
        // a. If argument.[[ProxyHandler]] is null, throw a TypeError exception.
240
0
        if (proxy.is_revoked())
241
0
            return vm.throw_completion<TypeError>(ErrorType::ProxyRevoked);
242
243
        // b. Let target be argument.[[ProxyTarget]].
244
0
        auto const& target = proxy.target();
245
246
        // c. Return ? IsArray(target).
247
0
        return Value(&target).is_array(vm);
248
0
    }
249
250
    // 4. Return false.
251
0
    return false;
252
0
}
253
254
Array& Value::as_array()
255
0
{
256
0
    VERIFY(is_object() && is<Array>(as_object()));
257
0
    return static_cast<Array&>(as_object());
258
0
}
259
260
// 20.5.8.2 IsError ( argument ), https://tc39.es/proposal-is-error/#sec-iserror
261
bool Value::is_error() const
262
0
{
263
    // 1. If argument is not an Object, return false.
264
    // 2. If argument has an [[ErrorData]] internal slot, return true.
265
    // 3. Return false.
266
0
    return is_object() && is<Error>(as_object());
267
0
}
268
269
// 7.2.3 IsCallable ( argument ), https://tc39.es/ecma262/#sec-iscallable
270
bool Value::is_function() const
271
255
{
272
    // 1. If argument is not an Object, return false.
273
    // 2. If argument has a [[Call]] internal method, return true.
274
    // 3. Return false.
275
255
    return is_object() && as_object().is_function();
276
255
}
277
278
FunctionObject& Value::as_function()
279
255
{
280
255
    VERIFY(is_function());
281
255
    return static_cast<FunctionObject&>(as_object());
282
255
}
283
284
FunctionObject const& Value::as_function() const
285
0
{
286
0
    VERIFY(is_function());
287
0
    return static_cast<FunctionObject const&>(as_object());
288
0
}
289
290
// 7.2.4 IsConstructor ( argument ), https://tc39.es/ecma262/#sec-isconstructor
291
bool Value::is_constructor() const
292
0
{
293
    // 1. If Type(argument) is not Object, return false.
294
0
    if (!is_function())
295
0
        return false;
296
297
    // 2. If argument has a [[Construct]] internal method, return true.
298
0
    if (as_function().has_constructor())
299
0
        return true;
300
301
    // 3. Return false.
302
0
    return false;
303
0
}
304
305
// 7.2.8 IsRegExp ( argument ), https://tc39.es/ecma262/#sec-isregexp
306
ThrowCompletionOr<bool> Value::is_regexp(VM& vm) const
307
0
{
308
    // 1. If argument is not an Object, return false.
309
0
    if (!is_object())
310
0
        return false;
311
312
    // 2. Let matcher be ? Get(argument, @@match).
313
0
    auto matcher = TRY(as_object().get(vm.well_known_symbol_match()));
314
315
    // 3. If matcher is not undefined, return ToBoolean(matcher).
316
0
    if (!matcher.is_undefined())
317
0
        return matcher.to_boolean();
318
319
    // 4. If argument has a [[RegExpMatcher]] internal slot, return true.
320
    // 5. Return false.
321
0
    return is<RegExpObject>(as_object());
322
0
}
323
324
// 13.5.3 The typeof Operator, https://tc39.es/ecma262/#sec-typeof-operator
325
NonnullGCPtr<PrimitiveString> Value::typeof_(VM& vm) const
326
0
{
327
    // 9. If val is a Number, return "number".
328
0
    if (is_number())
329
0
        return *vm.typeof_strings.number;
330
331
0
    switch (m_value.tag) {
332
    // 4. If val is undefined, return "undefined".
333
0
    case UNDEFINED_TAG:
334
0
        return *vm.typeof_strings.undefined;
335
    // 5. If val is null, return "object".
336
0
    case NULL_TAG:
337
0
        return *vm.typeof_strings.object;
338
    // 6. If val is a String, return "string".
339
0
    case STRING_TAG:
340
0
        return *vm.typeof_strings.string;
341
    // 7. If val is a Symbol, return "symbol".
342
0
    case SYMBOL_TAG:
343
0
        return *vm.typeof_strings.symbol;
344
    // 8. If val is a Boolean, return "boolean".
345
0
    case BOOLEAN_TAG:
346
0
        return *vm.typeof_strings.boolean;
347
    // 10. If val is a BigInt, return "bigint".
348
0
    case BIGINT_TAG:
349
0
        return *vm.typeof_strings.bigint;
350
    // 11. Assert: val is an Object.
351
0
    case OBJECT_TAG:
352
        // B.3.6.3 Changes to the typeof Operator, https://tc39.es/ecma262/#sec-IsHTMLDDA-internal-slot-typeof
353
        // 12. If val has an [[IsHTMLDDA]] internal slot, return "undefined".
354
0
        if (as_object().is_htmldda())
355
0
            return *vm.typeof_strings.undefined;
356
        // 13. If val has a [[Call]] internal slot, return "function".
357
0
        if (is_function())
358
0
            return *vm.typeof_strings.function;
359
        // 14. Return "object".
360
0
        return *vm.typeof_strings.object;
361
0
    default:
362
0
        VERIFY_NOT_REACHED();
363
0
    }
364
0
}
365
366
String Value::to_string_without_side_effects() const
367
1
{
368
1
    if (is_double())
369
0
        return number_to_string(m_value.as_double);
370
371
1
    switch (m_value.tag) {
372
0
    case UNDEFINED_TAG:
373
0
        return "undefined"_string;
374
0
    case NULL_TAG:
375
0
        return "null"_string;
376
0
    case BOOLEAN_TAG:
377
0
        return as_bool() ? "true"_string : "false"_string;
378
1
    case INT32_TAG:
379
1
        return String::number(as_i32());
380
0
    case STRING_TAG:
381
0
        return as_string().utf8_string();
382
0
    case SYMBOL_TAG:
383
0
        return as_symbol().descriptive_string().release_value();
384
0
    case BIGINT_TAG:
385
0
        return as_bigint().to_string().release_value();
386
0
    case OBJECT_TAG:
387
0
        return String::formatted("[object {}]", as_object().class_name()).release_value();
388
0
    case ACCESSOR_TAG:
389
0
        return "<accessor>"_string;
390
0
    case EMPTY_TAG:
391
0
        return "<empty>"_string;
392
0
    default:
393
0
        VERIFY_NOT_REACHED();
394
1
    }
395
1
}
396
397
ThrowCompletionOr<NonnullGCPtr<PrimitiveString>> Value::to_primitive_string(VM& vm)
398
0
{
399
0
    if (is_string())
400
0
        return as_string();
401
0
    auto string = TRY(to_string(vm));
402
0
    return PrimitiveString::create(vm, move(string));
403
0
}
404
405
// 7.1.17 ToString ( argument ), https://tc39.es/ecma262/#sec-tostring
406
ThrowCompletionOr<String> Value::to_string(VM& vm) const
407
0
{
408
0
    if (is_double())
409
0
        return number_to_string(m_value.as_double);
410
411
0
    switch (m_value.tag) {
412
    // 1. If argument is a String, return argument.
413
0
    case STRING_TAG:
414
0
        return as_string().utf8_string();
415
    // 2. If argument is a Symbol, throw a TypeError exception.
416
0
    case SYMBOL_TAG:
417
0
        return vm.throw_completion<TypeError>(ErrorType::Convert, "symbol", "string");
418
    // 3. If argument is undefined, return "undefined".
419
0
    case UNDEFINED_TAG:
420
0
        return "undefined"_string;
421
    // 4. If argument is null, return "null".
422
0
    case NULL_TAG:
423
0
        return "null"_string;
424
    // 5. If argument is true, return "true".
425
    // 6. If argument is false, return "false".
426
0
    case BOOLEAN_TAG:
427
0
        return as_bool() ? "true"_string : "false"_string;
428
    // 7. If argument is a Number, return Number::toString(argument, 10).
429
0
    case INT32_TAG:
430
0
        return String::number(as_i32());
431
    // 8. If argument is a BigInt, return BigInt::toString(argument, 10).
432
0
    case BIGINT_TAG:
433
0
        return TRY_OR_THROW_OOM(vm, as_bigint().big_integer().to_base(10));
434
    // 9. Assert: argument is an Object.
435
0
    case OBJECT_TAG: {
436
        // 10. Let primValue be ? ToPrimitive(argument, string).
437
0
        auto primitive_value = TRY(to_primitive(vm, PreferredType::String));
438
439
        // 11. Assert: primValue is not an Object.
440
0
        VERIFY(!primitive_value.is_object());
441
442
        // 12. Return ? ToString(primValue).
443
0
        return primitive_value.to_string(vm);
444
0
    }
445
0
    default:
446
0
        VERIFY_NOT_REACHED();
447
0
    }
448
0
}
449
450
// 7.1.17 ToString ( argument ), https://tc39.es/ecma262/#sec-tostring
451
ThrowCompletionOr<ByteString> Value::to_byte_string(VM& vm) const
452
0
{
453
0
    return TRY(to_string(vm)).to_byte_string();
454
0
}
455
456
ThrowCompletionOr<Utf16String> Value::to_utf16_string(VM& vm) const
457
0
{
458
0
    if (is_string())
459
0
        return as_string().utf16_string();
460
461
0
    auto utf8_string = TRY(to_string(vm));
462
0
    return Utf16String::create(utf8_string.bytes_as_string_view());
463
0
}
464
465
ThrowCompletionOr<String> Value::to_well_formed_string(VM& vm) const
466
0
{
467
0
    return ::JS::to_well_formed_string(TRY(to_utf16_string(vm)));
468
0
}
469
470
// 7.1.2 ToBoolean ( argument ), https://tc39.es/ecma262/#sec-toboolean
471
bool Value::to_boolean_slow_case() const
472
0
{
473
0
    if (is_double()) {
474
0
        if (is_nan())
475
0
            return false;
476
0
        return m_value.as_double != 0;
477
0
    }
478
479
0
    switch (m_value.tag) {
480
    // 1. If argument is a Boolean, return argument.
481
0
    case BOOLEAN_TAG:
482
0
        return as_bool();
483
    // 2. If argument is any of undefined, null, +0𝔽, -0𝔽, NaN, 0ℤ, or the empty String, return false.
484
0
    case UNDEFINED_TAG:
485
0
    case NULL_TAG:
486
0
        return false;
487
0
    case INT32_TAG:
488
0
        return as_i32() != 0;
489
0
    case STRING_TAG:
490
0
        return !as_string().is_empty();
491
0
    case BIGINT_TAG:
492
0
        return as_bigint().big_integer() != BIGINT_ZERO;
493
0
    case OBJECT_TAG:
494
        // B.3.6.1 Changes to ToBoolean, https://tc39.es/ecma262/#sec-IsHTMLDDA-internal-slot-to-boolean
495
        // 3. If argument is an Object and argument has an [[IsHTMLDDA]] internal slot, return false.
496
0
        if (as_object().is_htmldda())
497
0
            return false;
498
        // 4. Return true.
499
0
        return true;
500
0
    case SYMBOL_TAG:
501
0
        return true;
502
0
    default:
503
0
        VERIFY_NOT_REACHED();
504
0
    }
505
0
}
506
507
// 7.1.1 ToPrimitive ( input [ , preferredType ] ), https://tc39.es/ecma262/#sec-toprimitive
508
ThrowCompletionOr<Value> Value::to_primitive_slow_case(VM& vm, PreferredType preferred_type) const
509
0
{
510
    // 1. If input is an Object, then
511
0
    if (is_object()) {
512
        // a. Let exoticToPrim be ? GetMethod(input, @@toPrimitive).
513
0
        auto exotic_to_primitive = TRY(get_method(vm, vm.well_known_symbol_to_primitive()));
514
515
        // b. If exoticToPrim is not undefined, then
516
0
        if (exotic_to_primitive) {
517
0
            auto hint = [&]() -> ByteString {
518
0
                switch (preferred_type) {
519
                // i. If preferredType is not present, let hint be "default".
520
0
                case PreferredType::Default:
521
0
                    return "default";
522
                // ii. Else if preferredType is string, let hint be "string".
523
0
                case PreferredType::String:
524
0
                    return "string";
525
                // iii. Else,
526
                // 1. Assert: preferredType is number.
527
                // 2. Let hint be "number".
528
0
                case PreferredType::Number:
529
0
                    return "number";
530
0
                default:
531
0
                    VERIFY_NOT_REACHED();
532
0
                }
533
0
            }();
534
535
            // iv. Let result be ? Call(exoticToPrim, input, « hint »).
536
0
            auto result = TRY(call(vm, *exotic_to_primitive, *this, PrimitiveString::create(vm, hint)));
537
538
            // v. If result is not an Object, return result.
539
0
            if (!result.is_object())
540
0
                return result;
541
542
            // vi. Throw a TypeError exception.
543
0
            return vm.throw_completion<TypeError>(ErrorType::ToPrimitiveReturnedObject, to_string_without_side_effects(), hint);
544
0
        }
545
546
        // c. If preferredType is not present, let preferredType be number.
547
0
        if (preferred_type == PreferredType::Default)
548
0
            preferred_type = PreferredType::Number;
549
550
        // d. Return ? OrdinaryToPrimitive(input, preferredType).
551
0
        return as_object().ordinary_to_primitive(preferred_type);
552
0
    }
553
554
    // 2. Return input.
555
0
    return *this;
556
0
}
557
558
// 7.1.18 ToObject ( argument ), https://tc39.es/ecma262/#sec-toobject
559
ThrowCompletionOr<NonnullGCPtr<Object>> Value::to_object(VM& vm) const
560
0
{
561
0
    auto& realm = *vm.current_realm();
562
0
    VERIFY(!is_empty());
563
564
    // Number
565
0
    if (is_number()) {
566
        // Return a new Number object whose [[NumberData]] internal slot is set to argument. See 21.1 for a description of Number objects.
567
0
        return NumberObject::create(realm, as_double());
568
0
    }
569
570
0
    switch (m_value.tag) {
571
    // Undefined
572
    // Null
573
0
    case UNDEFINED_TAG:
574
0
    case NULL_TAG:
575
        // Throw a TypeError exception.
576
0
        return vm.throw_completion<TypeError>(ErrorType::ToObjectNullOrUndefined);
577
    // Boolean
578
0
    case BOOLEAN_TAG:
579
        // Return a new Boolean object whose [[BooleanData]] internal slot is set to argument. See 20.3 for a description of Boolean objects.
580
0
        return BooleanObject::create(realm, as_bool());
581
    // String
582
0
    case STRING_TAG:
583
        // Return a new String object whose [[StringData]] internal slot is set to argument. See 22.1 for a description of String objects.
584
0
        return StringObject::create(realm, const_cast<JS::PrimitiveString&>(as_string()), realm.intrinsics().string_prototype());
585
    // Symbol
586
0
    case SYMBOL_TAG:
587
        // Return a new Symbol object whose [[SymbolData]] internal slot is set to argument. See 20.4 for a description of Symbol objects.
588
0
        return SymbolObject::create(realm, const_cast<JS::Symbol&>(as_symbol()));
589
    // BigInt
590
0
    case BIGINT_TAG:
591
        // Return a new BigInt object whose [[BigIntData]] internal slot is set to argument. See 21.2 for a description of BigInt objects.
592
0
        return BigIntObject::create(realm, const_cast<JS::BigInt&>(as_bigint()));
593
    // Object
594
0
    case OBJECT_TAG:
595
        // Return argument.
596
0
        return const_cast<Object&>(as_object());
597
0
    default:
598
0
        VERIFY_NOT_REACHED();
599
0
    }
600
0
}
601
602
// 7.1.3 ToNumeric ( value ), https://tc39.es/ecma262/#sec-tonumeric
603
FLATTEN ThrowCompletionOr<Value> Value::to_numeric_slow_case(VM& vm) const
604
0
{
605
    // 1. Let primValue be ? ToPrimitive(value, number).
606
0
    auto primitive_value = TRY(to_primitive(vm, Value::PreferredType::Number));
607
608
    // 2. If primValue is a BigInt, return primValue.
609
0
    if (primitive_value.is_bigint())
610
0
        return primitive_value;
611
612
    // 3. Return ? ToNumber(primValue).
613
0
    return primitive_value.to_number(vm);
614
0
}
615
616
constexpr bool is_ascii_number(u32 code_point)
617
0
{
618
0
    return is_ascii_digit(code_point) || code_point == '.' || (code_point == 'e' || code_point == 'E') || code_point == '+' || code_point == '-';
619
0
}
620
621
struct NumberParseResult {
622
    StringView literal;
623
    u8 base;
624
};
625
626
static Optional<NumberParseResult> parse_number_text(StringView text)
627
0
{
628
0
    NumberParseResult result {};
629
630
0
    auto check_prefix = [&](auto lower_prefix, auto upper_prefix) {
631
0
        if (text.length() <= 2)
632
0
            return false;
633
0
        if (!text.starts_with(lower_prefix) && !text.starts_with(upper_prefix))
634
0
            return false;
635
0
        return true;
636
0
    };
637
638
    // https://tc39.es/ecma262/#sec-tonumber-applied-to-the-string-type
639
0
    if (check_prefix("0b"sv, "0B"sv)) {
640
0
        if (!all_of(text.substring_view(2), is_ascii_binary_digit))
641
0
            return {};
642
643
0
        result.literal = text.substring_view(2);
644
0
        result.base = 2;
645
0
    } else if (check_prefix("0o"sv, "0O"sv)) {
646
0
        if (!all_of(text.substring_view(2), is_ascii_octal_digit))
647
0
            return {};
648
649
0
        result.literal = text.substring_view(2);
650
0
        result.base = 8;
651
0
    } else if (check_prefix("0x"sv, "0X"sv)) {
652
0
        if (!all_of(text.substring_view(2), is_ascii_hex_digit))
653
0
            return {};
654
655
0
        result.literal = text.substring_view(2);
656
0
        result.base = 16;
657
0
    } else {
658
0
        if (!all_of(text, is_ascii_number))
659
0
            return {};
660
661
0
        result.literal = text;
662
0
        result.base = 10;
663
0
    }
664
665
0
    return result;
666
0
}
667
668
// 7.1.4.1.1 StringToNumber ( str ), https://tc39.es/ecma262/#sec-stringtonumber
669
double string_to_number(StringView string)
670
0
{
671
    // 1. Let text be StringToCodePoints(str).
672
0
    auto text = Utf8View(string).trim(whitespace_characters, AK::TrimMode::Both).as_string();
673
674
    // 2. Let literal be ParseText(text, StringNumericLiteral).
675
0
    if (text.is_empty())
676
0
        return 0;
677
0
    if (text == "Infinity"sv || text == "+Infinity"sv)
678
0
        return INFINITY;
679
0
    if (text == "-Infinity"sv)
680
0
        return -INFINITY;
681
682
0
    auto result = parse_number_text(text);
683
684
    // 3. If literal is a List of errors, return NaN.
685
0
    if (!result.has_value())
686
0
        return NAN;
687
688
    // 4. Return StringNumericValue of literal.
689
0
    if (result->base != 10) {
690
0
        auto bigint = MUST(Crypto::UnsignedBigInteger::from_base(result->base, result->literal));
691
0
        return bigint.to_double();
692
0
    }
693
694
0
    auto maybe_double = text.to_number<double>(AK::TrimWhitespace::No);
695
0
    if (!maybe_double.has_value())
696
0
        return NAN;
697
698
0
    return *maybe_double;
699
0
}
700
701
// 7.1.4 ToNumber ( argument ), https://tc39.es/ecma262/#sec-tonumber
702
ThrowCompletionOr<Value> Value::to_number_slow_case(VM& vm) const
703
0
{
704
0
    VERIFY(!is_empty());
705
706
    // 1. If argument is a Number, return argument.
707
0
    if (is_number())
708
0
        return *this;
709
710
0
    switch (m_value.tag) {
711
    // 2. If argument is either a Symbol or a BigInt, throw a TypeError exception.
712
0
    case SYMBOL_TAG:
713
0
        return vm.throw_completion<TypeError>(ErrorType::Convert, "symbol", "number");
714
0
    case BIGINT_TAG:
715
0
        return vm.throw_completion<TypeError>(ErrorType::Convert, "BigInt", "number");
716
    // 3. If argument is undefined, return NaN.
717
0
    case UNDEFINED_TAG:
718
0
        return js_nan();
719
    // 4. If argument is either null or false, return +0𝔽.
720
0
    case NULL_TAG:
721
0
        return Value(0);
722
    // 5. If argument is true, return 1𝔽.
723
0
    case BOOLEAN_TAG:
724
0
        return Value(as_bool() ? 1 : 0);
725
    // 6. If argument is a String, return StringToNumber(argument).
726
0
    case STRING_TAG:
727
0
        return string_to_number(as_string().byte_string());
728
    // 7. Assert: argument is an Object.
729
0
    case OBJECT_TAG: {
730
        // 8. Let primValue be ? ToPrimitive(argument, number).
731
0
        auto primitive_value = TRY(to_primitive(vm, PreferredType::Number));
732
733
        // 9. Assert: primValue is not an Object.
734
0
        VERIFY(!primitive_value.is_object());
735
736
        // 10. Return ? ToNumber(primValue).
737
0
        return primitive_value.to_number(vm);
738
0
    }
739
0
    default:
740
0
        VERIFY_NOT_REACHED();
741
0
    }
742
0
}
743
744
static Optional<BigInt*> string_to_bigint(VM& vm, StringView string);
745
746
// 7.1.13 ToBigInt ( argument ), https://tc39.es/ecma262/#sec-tobigint
747
ThrowCompletionOr<NonnullGCPtr<BigInt>> Value::to_bigint(VM& vm) const
748
0
{
749
    // 1. Let prim be ? ToPrimitive(argument, number).
750
0
    auto primitive = TRY(to_primitive(vm, PreferredType::Number));
751
752
    // 2. Return the value that prim corresponds to in Table 12.
753
754
    // Number
755
0
    if (primitive.is_number()) {
756
        // Throw a TypeError exception.
757
0
        return vm.throw_completion<TypeError>(ErrorType::Convert, "number", "BigInt");
758
0
    }
759
760
0
    switch (primitive.m_value.tag) {
761
    // Undefined
762
0
    case UNDEFINED_TAG:
763
        // Throw a TypeError exception.
764
0
        return vm.throw_completion<TypeError>(ErrorType::Convert, "undefined", "BigInt");
765
    // Null
766
0
    case NULL_TAG:
767
        // Throw a TypeError exception.
768
0
        return vm.throw_completion<TypeError>(ErrorType::Convert, "null", "BigInt");
769
    // Boolean
770
0
    case BOOLEAN_TAG: {
771
        // Return 1n if prim is true and 0n if prim is false.
772
0
        auto value = primitive.as_bool() ? 1 : 0;
773
0
        return BigInt::create(vm, Crypto::SignedBigInteger { value });
774
0
    }
775
    // BigInt
776
0
    case BIGINT_TAG:
777
        // Return prim.
778
0
        return primitive.as_bigint();
779
0
    case STRING_TAG: {
780
        // 1. Let n be ! StringToBigInt(prim).
781
0
        auto bigint = string_to_bigint(vm, primitive.as_string().byte_string());
782
783
        // 2. If n is undefined, throw a SyntaxError exception.
784
0
        if (!bigint.has_value())
785
0
            return vm.throw_completion<SyntaxError>(ErrorType::BigIntInvalidValue, primitive);
786
787
        // 3. Return n.
788
0
        return *bigint.release_value();
789
0
    }
790
    // Symbol
791
0
    case SYMBOL_TAG:
792
        // Throw a TypeError exception.
793
0
        return vm.throw_completion<TypeError>(ErrorType::Convert, "symbol", "BigInt");
794
0
    default:
795
0
        VERIFY_NOT_REACHED();
796
0
    }
797
0
}
798
799
struct BigIntParseResult {
800
    StringView literal;
801
    u8 base { 10 };
802
    bool is_negative { false };
803
};
804
805
static Optional<BigIntParseResult> parse_bigint_text(StringView text)
806
0
{
807
0
    BigIntParseResult result {};
808
809
0
    auto parse_for_prefixed_base = [&](auto lower_prefix, auto upper_prefix, auto validator) {
810
0
        if (text.length() <= 2)
811
0
            return false;
812
0
        if (!text.starts_with(lower_prefix) && !text.starts_with(upper_prefix))
813
0
            return false;
814
0
        return all_of(text.substring_view(2), validator);
815
0
    };
816
817
0
    if (parse_for_prefixed_base("0b"sv, "0B"sv, is_ascii_binary_digit)) {
818
0
        result.literal = text.substring_view(2);
819
0
        result.base = 2;
820
0
    } else if (parse_for_prefixed_base("0o"sv, "0O"sv, is_ascii_octal_digit)) {
821
0
        result.literal = text.substring_view(2);
822
0
        result.base = 8;
823
0
    } else if (parse_for_prefixed_base("0x"sv, "0X"sv, is_ascii_hex_digit)) {
824
0
        result.literal = text.substring_view(2);
825
0
        result.base = 16;
826
0
    } else {
827
0
        if (text.starts_with('-')) {
828
0
            text = text.substring_view(1);
829
0
            result.is_negative = true;
830
0
        } else if (text.starts_with('+')) {
831
0
            text = text.substring_view(1);
832
0
        }
833
834
0
        if (!all_of(text, is_ascii_digit))
835
0
            return {};
836
837
0
        result.literal = text;
838
0
        result.base = 10;
839
0
    }
840
841
0
    return result;
842
0
}
843
844
// 7.1.14 StringToBigInt ( str ), https://tc39.es/ecma262/#sec-stringtobigint
845
static Optional<BigInt*> string_to_bigint(VM& vm, StringView string)
846
0
{
847
    // 1. Let text be StringToCodePoints(str).
848
0
    auto text = Utf8View(string).trim(whitespace_characters, AK::TrimMode::Both).as_string();
849
850
    // 2. Let literal be ParseText(text, StringIntegerLiteral).
851
0
    auto result = parse_bigint_text(text);
852
853
    // 3. If literal is a List of errors, return undefined.
854
0
    if (!result.has_value())
855
0
        return {};
856
857
    // 4. Let mv be the MV of literal.
858
    // 5. Assert: mv is an integer.
859
0
    auto bigint = MUST(Crypto::SignedBigInteger::from_base(result->base, result->literal));
860
0
    if (result->is_negative && (bigint != BIGINT_ZERO))
861
0
        bigint.negate();
862
863
    // 6. Return ℤ(mv).
864
0
    return BigInt::create(vm, move(bigint));
865
0
}
866
867
// 7.1.15 ToBigInt64 ( argument ), https://tc39.es/ecma262/#sec-tobigint64
868
ThrowCompletionOr<i64> Value::to_bigint_int64(VM& vm) const
869
0
{
870
    // 1. Let n be ? ToBigInt(argument).
871
0
    auto bigint = TRY(to_bigint(vm));
872
873
    // 2. Let int64bit be ℝ(n) modulo 2^64.
874
    // 3. If int64bit ≥ 2^63, return ℤ(int64bit - 2^64); otherwise return ℤ(int64bit).
875
0
    return static_cast<i64>(bigint->big_integer().to_u64());
876
0
}
877
878
// 7.1.16 ToBigUint64 ( argument ), https://tc39.es/ecma262/#sec-tobiguint64
879
ThrowCompletionOr<u64> Value::to_bigint_uint64(VM& vm) const
880
0
{
881
    // 1. Let n be ? ToBigInt(argument).
882
0
    auto bigint = TRY(to_bigint(vm));
883
884
    // 2. Let int64bit be ℝ(n) modulo 2^64.
885
    // 3. Return ℤ(int64bit).
886
0
    return bigint->big_integer().to_u64();
887
0
}
888
889
ThrowCompletionOr<double> Value::to_double(VM& vm) const
890
0
{
891
0
    return TRY(to_number(vm)).as_double();
892
0
}
893
894
// 7.1.19 ToPropertyKey ( argument ), https://tc39.es/ecma262/#sec-topropertykey
895
ThrowCompletionOr<PropertyKey> Value::to_property_key(VM& vm) const
896
0
{
897
    // OPTIMIZATION: Return the value as a numeric PropertyKey, if possible.
898
0
    if (is_int32() && as_i32() >= 0)
899
0
        return PropertyKey { as_i32() };
900
901
    // 1. Let key be ? ToPrimitive(argument, string).
902
0
    auto key = TRY(to_primitive(vm, PreferredType::String));
903
904
    // 2. If key is a Symbol, then
905
0
    if (key.is_symbol()) {
906
        // a. Return key.
907
0
        return &key.as_symbol();
908
0
    }
909
910
    // 3. Return ! ToString(key).
911
0
    return MUST(key.to_byte_string(vm));
912
0
}
913
914
// 7.1.6 ToInt32 ( argument ), https://tc39.es/ecma262/#sec-toint32
915
ThrowCompletionOr<i32> Value::to_i32_slow_case(VM& vm) const
916
0
{
917
0
    VERIFY(!is_int32());
918
919
    // 1. Let number be ? ToNumber(argument).
920
0
    double number = TRY(to_number(vm)).as_double();
921
922
    // 2. If number is not finite or number is either +0𝔽 or -0𝔽, return +0𝔽.
923
0
    if (!isfinite(number) || number == 0)
924
0
        return 0;
925
926
    // 3. Let int be the mathematical value whose sign is the sign of number and whose magnitude is floor(abs(ℝ(number))).
927
0
    auto abs = fabs(number);
928
0
    auto int_val = floor(abs);
929
0
    if (signbit(number))
930
0
        int_val = -int_val;
931
932
    // 4. Let int32bit be int modulo 2^32.
933
0
    auto int32bit = modulo(int_val, NumericLimits<u32>::max() + 1.0);
934
935
    // 5. If int32bit ≥ 2^31, return 𝔽(int32bit - 2^32); otherwise return 𝔽(int32bit).
936
0
    if (int32bit >= 2147483648.0)
937
0
        int32bit -= 4294967296.0;
938
0
    return static_cast<i32>(int32bit);
939
0
}
940
941
// 7.1.6 ToInt32 ( argument ), https://tc39.es/ecma262/#sec-toint32
942
ThrowCompletionOr<i32> Value::to_i32(VM& vm) const
943
0
{
944
0
    if (is_int32())
945
0
        return as_i32();
946
0
    return to_i32_slow_case(vm);
947
0
}
948
949
// 7.1.7 ToUint32 ( argument ), https://tc39.es/ecma262/#sec-touint32
950
ThrowCompletionOr<u32> Value::to_u32(VM& vm) const
951
5
{
952
    // OPTIMIZATION: If this value is encoded as a positive i32, return it directly.
953
5
    if (is_int32() && as_i32() >= 0)
954
5
        return as_i32();
955
956
    // 1. Let number be ? ToNumber(argument).
957
0
    double number = TRY(to_number(vm)).as_double();
958
959
    // 2. If number is not finite or number is either +0𝔽 or -0𝔽, return +0𝔽.
960
0
    if (!isfinite(number) || number == 0)
961
0
        return 0;
962
963
    // 3. Let int be the mathematical value whose sign is the sign of number and whose magnitude is floor(abs(ℝ(number))).
964
0
    auto int_val = floor(fabs(number));
965
0
    if (signbit(number))
966
0
        int_val = -int_val;
967
968
    // 4. Let int32bit be int modulo 2^32.
969
0
    auto int32bit = modulo(int_val, NumericLimits<u32>::max() + 1.0);
970
971
    // 5. Return 𝔽(int32bit).
972
    // Cast to i64 here to ensure that the double --> u32 cast doesn't invoke undefined behavior
973
    // Otherwise, negative numbers cause a UBSAN warning.
974
0
    return static_cast<u32>(static_cast<i64>(int32bit));
975
0
}
976
977
// 7.1.8 ToInt16 ( argument ), https://tc39.es/ecma262/#sec-toint16
978
ThrowCompletionOr<i16> Value::to_i16(VM& vm) const
979
0
{
980
    // 1. Let number be ? ToNumber(argument).
981
0
    double number = TRY(to_number(vm)).as_double();
982
983
    // 2. If number is not finite or number is either +0𝔽 or -0𝔽, return +0𝔽.
984
0
    if (!isfinite(number) || number == 0)
985
0
        return 0;
986
987
    // 3. Let int be the mathematical value whose sign is the sign of number and whose magnitude is floor(abs(ℝ(number))).
988
0
    auto abs = fabs(number);
989
0
    auto int_val = floor(abs);
990
0
    if (signbit(number))
991
0
        int_val = -int_val;
992
993
    // 4. Let int16bit be int modulo 2^16.
994
0
    auto int16bit = modulo(int_val, NumericLimits<u16>::max() + 1.0);
995
996
    // 5. If int16bit ≥ 2^15, return 𝔽(int16bit - 2^16); otherwise return 𝔽(int16bit).
997
0
    if (int16bit >= 32768.0)
998
0
        int16bit -= 65536.0;
999
0
    return static_cast<i16>(int16bit);
1000
0
}
1001
1002
// 7.1.9 ToUint16 ( argument ), https://tc39.es/ecma262/#sec-touint16
1003
ThrowCompletionOr<u16> Value::to_u16(VM& vm) const
1004
0
{
1005
    // 1. Let number be ? ToNumber(argument).
1006
0
    double number = TRY(to_number(vm)).as_double();
1007
1008
    // 2. If number is not finite or number is either +0𝔽 or -0𝔽, return +0𝔽.
1009
0
    if (!isfinite(number) || number == 0)
1010
0
        return 0;
1011
1012
    // 3. Let int be the mathematical value whose sign is the sign of number and whose magnitude is floor(abs(ℝ(number))).
1013
0
    auto int_val = floor(fabs(number));
1014
0
    if (signbit(number))
1015
0
        int_val = -int_val;
1016
1017
    // 4. Let int16bit be int modulo 2^16.
1018
0
    auto int16bit = modulo(int_val, NumericLimits<u16>::max() + 1.0);
1019
1020
    // 5. Return 𝔽(int16bit).
1021
0
    return static_cast<u16>(int16bit);
1022
0
}
1023
1024
// 7.1.10 ToInt8 ( argument ), https://tc39.es/ecma262/#sec-toint8
1025
ThrowCompletionOr<i8> Value::to_i8(VM& vm) const
1026
0
{
1027
    // 1. Let number be ? ToNumber(argument).
1028
0
    double number = TRY(to_number(vm)).as_double();
1029
1030
    // 2. If number is not finite or number is either +0𝔽 or -0𝔽, return +0𝔽.
1031
0
    if (!isfinite(number) || number == 0)
1032
0
        return 0;
1033
1034
    // 3. Let int be the mathematical value whose sign is the sign of number and whose magnitude is floor(abs(ℝ(number))).
1035
0
    auto abs = fabs(number);
1036
0
    auto int_val = floor(abs);
1037
0
    if (signbit(number))
1038
0
        int_val = -int_val;
1039
1040
    // 4. Let int8bit be int modulo 2^8.
1041
0
    auto int8bit = modulo(int_val, NumericLimits<u8>::max() + 1.0);
1042
1043
    // 5. If int8bit ≥ 2^7, return 𝔽(int8bit - 2^8); otherwise return 𝔽(int8bit).
1044
0
    if (int8bit >= 128.0)
1045
0
        int8bit -= 256.0;
1046
0
    return static_cast<i8>(int8bit);
1047
0
}
1048
1049
// 7.1.11 ToUint8 ( argument ), https://tc39.es/ecma262/#sec-touint8
1050
ThrowCompletionOr<u8> Value::to_u8(VM& vm) const
1051
0
{
1052
    // 1. Let number be ? ToNumber(argument).
1053
0
    double number = TRY(to_number(vm)).as_double();
1054
1055
    // 2. If number is not finite or number is either +0𝔽 or -0𝔽, return +0𝔽.
1056
0
    if (!isfinite(number) || number == 0)
1057
0
        return 0;
1058
1059
    // 3. Let int be the mathematical value whose sign is the sign of number and whose magnitude is floor(abs(ℝ(number))).
1060
0
    auto int_val = floor(fabs(number));
1061
0
    if (signbit(number))
1062
0
        int_val = -int_val;
1063
1064
    // 4. Let int8bit be int modulo 2^8.
1065
0
    auto int8bit = modulo(int_val, NumericLimits<u8>::max() + 1.0);
1066
1067
    // 5. Return 𝔽(int8bit).
1068
0
    return static_cast<u8>(int8bit);
1069
0
}
1070
1071
// 7.1.12 ToUint8Clamp ( argument ), https://tc39.es/ecma262/#sec-touint8clamp
1072
ThrowCompletionOr<u8> Value::to_u8_clamp(VM& vm) const
1073
0
{
1074
    // 1. Let number be ? ToNumber(argument).
1075
0
    auto number = TRY(to_number(vm));
1076
1077
    // 2. If number is NaN, return +0𝔽.
1078
0
    if (number.is_nan())
1079
0
        return 0;
1080
1081
0
    double value = number.as_double();
1082
1083
    // 3. If ℝ(number) ≤ 0, return +0𝔽.
1084
0
    if (value <= 0.0)
1085
0
        return 0;
1086
1087
    // 4. If ℝ(number) ≥ 255, return 255𝔽.
1088
0
    if (value >= 255.0)
1089
0
        return 255;
1090
1091
    // 5. Let f be floor(ℝ(number)).
1092
0
    auto int_val = floor(value);
1093
1094
    // 6. If f + 0.5 < ℝ(number), return 𝔽(f + 1).
1095
0
    if (int_val + 0.5 < value)
1096
0
        return static_cast<u8>(int_val + 1.0);
1097
1098
    // 7. If ℝ(number) < f + 0.5, return 𝔽(f).
1099
0
    if (value < int_val + 0.5)
1100
0
        return static_cast<u8>(int_val);
1101
1102
    // 8. If f is odd, return 𝔽(f + 1).
1103
0
    if (fmod(int_val, 2.0) == 1.0)
1104
0
        return static_cast<u8>(int_val + 1.0);
1105
1106
    // 9. Return 𝔽(f).
1107
0
    return static_cast<u8>(int_val);
1108
0
}
1109
1110
// 7.1.20 ToLength ( argument ), https://tc39.es/ecma262/#sec-tolength
1111
ThrowCompletionOr<size_t> Value::to_length(VM& vm) const
1112
0
{
1113
    // 1. Let len be ? ToIntegerOrInfinity(argument).
1114
0
    auto len = TRY(to_integer_or_infinity(vm));
1115
1116
    // 2. If len ≤ 0, return +0𝔽.
1117
0
    if (len <= 0)
1118
0
        return 0;
1119
1120
    // FIXME: The expected output range is 0 - 2^53-1, but we don't want to overflow the size_t on 32-bit platforms.
1121
    //        Convert this to u64 so it works everywhere.
1122
0
    constexpr double length_limit = sizeof(void*) == 4 ? NumericLimits<size_t>::max() : MAX_ARRAY_LIKE_INDEX;
1123
1124
    // 3. Return 𝔽(min(len, 2^53 - 1)).
1125
0
    return min(len, length_limit);
1126
0
}
1127
1128
// 7.1.22 ToIndex ( argument ), https://tc39.es/ecma262/#sec-toindex
1129
ThrowCompletionOr<size_t> Value::to_index(VM& vm) const
1130
0
{
1131
    // 1. If value is undefined, then
1132
0
    if (is_undefined()) {
1133
        // a. Return 0.
1134
0
        return 0;
1135
0
    }
1136
1137
    // 2. Else,
1138
    // a. Let integer be ? ToIntegerOrInfinity(value).
1139
0
    auto integer = TRY(to_integer_or_infinity(vm));
1140
1141
    // OPTIMIZATION: If the value is negative, ToLength normalizes it to 0, and we fail the SameValue comparison below.
1142
    //               Bail out early instead.
1143
0
    if (integer < 0)
1144
0
        return vm.throw_completion<RangeError>(ErrorType::InvalidIndex);
1145
1146
    // b. Let clamped be ! ToLength(𝔽(integer)).
1147
0
    auto clamped = MUST(Value(integer).to_length(vm));
1148
1149
    // c. If SameValue(𝔽(integer), clamped) is false, throw a RangeError exception.
1150
0
    if (integer != clamped)
1151
0
        return vm.throw_completion<RangeError>(ErrorType::InvalidIndex);
1152
1153
    // d. Assert: 0 ≤ integer ≤ 2^53 - 1.
1154
0
    VERIFY(0 <= integer && integer <= MAX_ARRAY_LIKE_INDEX);
1155
1156
    // e. Return integer.
1157
    // NOTE: We return the clamped value here, which already has the right type.
1158
0
    return clamped;
1159
0
}
1160
1161
// 7.1.5 ToIntegerOrInfinity ( argument ), https://tc39.es/ecma262/#sec-tointegerorinfinity
1162
ThrowCompletionOr<double> Value::to_integer_or_infinity(VM& vm) const
1163
0
{
1164
    // 1. Let number be ? ToNumber(argument).
1165
0
    auto number = TRY(to_number(vm));
1166
1167
    // 2. If number is NaN, +0𝔽, or -0𝔽, return 0.
1168
0
    if (number.is_nan() || number.as_double() == 0)
1169
0
        return 0;
1170
1171
    // 3. If number is +∞𝔽, return +∞.
1172
    // 4. If number is -∞𝔽, return -∞.
1173
0
    if (number.is_infinity())
1174
0
        return number.as_double();
1175
1176
    // 5. Let integer be floor(abs(ℝ(number))).
1177
0
    auto integer = floor(fabs(number.as_double()));
1178
1179
    // 6. If number < -0𝔽, set integer to -integer.
1180
    // NOTE: The zero check is required as 'integer' is a double here but an MV in the spec,
1181
    //       which doesn't have negative zero.
1182
0
    if (number.as_double() < 0 && integer != 0)
1183
0
        integer = -integer;
1184
1185
    // 7. Return integer.
1186
0
    return integer;
1187
0
}
1188
1189
// Standalone variant using plain doubles for cases where we already got numbers and know the AO won't throw.
1190
double to_integer_or_infinity(double number)
1191
0
{
1192
    // 1. Let number be ? ToNumber(argument).
1193
1194
    // 2. If number is NaN, +0𝔽, or -0𝔽, return 0.
1195
0
    if (isnan(number) || number == 0)
1196
0
        return 0;
1197
1198
    // 3. If number is +∞𝔽, return +∞.
1199
0
    if (__builtin_isinf_sign(number) > 0)
1200
0
        return static_cast<double>(INFINITY);
1201
1202
    // 4. If number is -∞𝔽, return -∞.
1203
0
    if (__builtin_isinf_sign(number) < 0)
1204
0
        return static_cast<double>(-INFINITY);
1205
1206
    // 5. Let integer be floor(abs(ℝ(number))).
1207
0
    auto integer = floor(fabs(number));
1208
1209
    // 6. If number < -0𝔽, set integer to -integer.
1210
    // NOTE: The zero check is required as 'integer' is a double here but an MV in the spec,
1211
    //       which doesn't have negative zero.
1212
0
    if (number < 0 && integer != 0)
1213
0
        integer = -integer;
1214
1215
    // 7. Return integer.
1216
0
    return integer;
1217
0
}
1218
1219
// 7.3.3 GetV ( V, P ), https://tc39.es/ecma262/#sec-getv
1220
ThrowCompletionOr<Value> Value::get(VM& vm, PropertyKey const& property_key) const
1221
0
{
1222
    // 1. Assert: IsPropertyKey(P) is true.
1223
0
    VERIFY(property_key.is_valid());
1224
1225
    // 2. Let O be ? ToObject(V).
1226
0
    auto object = TRY(to_object(vm));
1227
1228
    // 3. Return ? O.[[Get]](P, V).
1229
0
    return TRY(object->internal_get(property_key, *this));
1230
0
}
1231
1232
// 7.3.11 GetMethod ( V, P ), https://tc39.es/ecma262/#sec-getmethod
1233
ThrowCompletionOr<GCPtr<FunctionObject>> Value::get_method(VM& vm, PropertyKey const& property_key) const
1234
0
{
1235
    // 1. Assert: IsPropertyKey(P) is true.
1236
0
    VERIFY(property_key.is_valid());
1237
1238
    // 2. Let func be ? GetV(V, P).
1239
0
    auto function = TRY(get(vm, property_key));
1240
1241
    // 3. If func is either undefined or null, return undefined.
1242
0
    if (function.is_nullish())
1243
0
        return nullptr;
1244
1245
    // 4. If IsCallable(func) is false, throw a TypeError exception.
1246
0
    if (!function.is_function())
1247
0
        return vm.throw_completion<TypeError>(ErrorType::NotAFunction, function.to_string_without_side_effects());
1248
1249
    // 5. Return func.
1250
0
    return function.as_function();
1251
0
}
1252
1253
// 13.10 Relational Operators, https://tc39.es/ecma262/#sec-relational-operators
1254
// RelationalExpression : RelationalExpression > ShiftExpression
1255
ThrowCompletionOr<Value> greater_than(VM& vm, Value lhs, Value rhs)
1256
0
{
1257
    // 1. Let lref be ? Evaluation of RelationalExpression.
1258
    // 2. Let lval be ? GetValue(lref).
1259
    // 3. Let rref be ? Evaluation of ShiftExpression.
1260
    // 4. Let rval be ? GetValue(rref).
1261
    // NOTE: This is handled in the AST or Bytecode interpreter.
1262
1263
    // OPTIMIZATION: If both values are i32, we can do a direct comparison without calling into IsLessThan.
1264
0
    if (lhs.is_int32() && rhs.is_int32())
1265
0
        return lhs.as_i32() > rhs.as_i32();
1266
1267
    // 5. Let r be ? IsLessThan(rval, lval, false).
1268
0
    auto relation = TRY(is_less_than(vm, lhs, rhs, false));
1269
1270
    // 6. If r is undefined, return false. Otherwise, return r.
1271
0
    if (relation == TriState::Unknown)
1272
0
        return Value(false);
1273
0
    return Value(relation == TriState::True);
1274
0
}
1275
1276
// 13.10 Relational Operators, https://tc39.es/ecma262/#sec-relational-operators
1277
// RelationalExpression : RelationalExpression >= ShiftExpression
1278
ThrowCompletionOr<Value> greater_than_equals(VM& vm, Value lhs, Value rhs)
1279
0
{
1280
    // 1. Let lref be ? Evaluation of RelationalExpression.
1281
    // 2. Let lval be ? GetValue(lref).
1282
    // 3. Let rref be ? Evaluation of ShiftExpression.
1283
    // 4. Let rval be ? GetValue(rref).
1284
    // NOTE: This is handled in the AST or Bytecode interpreter.
1285
1286
    // OPTIMIZATION: If both values are i32, we can do a direct comparison without calling into IsLessThan.
1287
0
    if (lhs.is_int32() && rhs.is_int32())
1288
0
        return lhs.as_i32() >= rhs.as_i32();
1289
1290
    // 5. Let r be ? IsLessThan(lval, rval, true).
1291
0
    auto relation = TRY(is_less_than(vm, lhs, rhs, true));
1292
1293
    // 6. If r is true or undefined, return false. Otherwise, return true.
1294
0
    if (relation == TriState::Unknown || relation == TriState::True)
1295
0
        return Value(false);
1296
0
    return Value(true);
1297
0
}
1298
1299
// 13.10 Relational Operators, https://tc39.es/ecma262/#sec-relational-operators
1300
// RelationalExpression : RelationalExpression < ShiftExpression
1301
ThrowCompletionOr<Value> less_than(VM& vm, Value lhs, Value rhs)
1302
0
{
1303
    // 1. Let lref be ? Evaluation of RelationalExpression.
1304
    // 2. Let lval be ? GetValue(lref).
1305
    // 3. Let rref be ? Evaluation of ShiftExpression.
1306
    // 4. Let rval be ? GetValue(rref).
1307
    // NOTE: This is handled in the AST or Bytecode interpreter.
1308
1309
    // OPTIMIZATION: If both values are i32, we can do a direct comparison without calling into IsLessThan.
1310
0
    if (lhs.is_int32() && rhs.is_int32())
1311
0
        return lhs.as_i32() < rhs.as_i32();
1312
1313
    // 5. Let r be ? IsLessThan(lval, rval, true).
1314
0
    auto relation = TRY(is_less_than(vm, lhs, rhs, true));
1315
1316
    // 6. If r is undefined, return false. Otherwise, return r.
1317
0
    if (relation == TriState::Unknown)
1318
0
        return Value(false);
1319
0
    return Value(relation == TriState::True);
1320
0
}
1321
1322
// 13.10 Relational Operators, https://tc39.es/ecma262/#sec-relational-operators
1323
// RelationalExpression : RelationalExpression <= ShiftExpression
1324
ThrowCompletionOr<Value> less_than_equals(VM& vm, Value lhs, Value rhs)
1325
0
{
1326
    // 1. Let lref be ? Evaluation of RelationalExpression.
1327
    // 2. Let lval be ? GetValue(lref).
1328
    // 3. Let rref be ? Evaluation of ShiftExpression.
1329
    // 4. Let rval be ? GetValue(rref).
1330
    // NOTE: This is handled in the AST or Bytecode interpreter.
1331
1332
    // OPTIMIZATION: If both values are i32, we can do a direct comparison without calling into IsLessThan.
1333
0
    if (lhs.is_int32() && rhs.is_int32())
1334
0
        return lhs.as_i32() <= rhs.as_i32();
1335
1336
    // 5. Let r be ? IsLessThan(rval, lval, false).
1337
0
    auto relation = TRY(is_less_than(vm, lhs, rhs, false));
1338
1339
    // 6. If r is true or undefined, return false. Otherwise, return true.
1340
0
    if (relation == TriState::True || relation == TriState::Unknown)
1341
0
        return Value(false);
1342
0
    return Value(true);
1343
0
}
1344
1345
// 13.12 Binary Bitwise Operators, https://tc39.es/ecma262/#sec-binary-bitwise-operators
1346
// BitwiseANDExpression : BitwiseANDExpression & EqualityExpression
1347
ThrowCompletionOr<Value> bitwise_and(VM& vm, Value lhs, Value rhs)
1348
0
{
1349
    // OPTIMIZATION: Fast path when both values are Int32.
1350
0
    if (lhs.is_int32() && rhs.is_int32())
1351
0
        return Value(lhs.as_i32() & rhs.as_i32());
1352
1353
    // 13.15.3 ApplyStringOrNumericBinaryOperator ( lval, opText, rval ), https://tc39.es/ecma262/#sec-applystringornumericbinaryoperator
1354
    // 1-2, 6. N/A.
1355
1356
    // 3. Let lnum be ? ToNumeric(lval).
1357
0
    auto lhs_numeric = TRY(lhs.to_numeric(vm));
1358
1359
    // 4. Let rnum be ? ToNumeric(rval).
1360
0
    auto rhs_numeric = TRY(rhs.to_numeric(vm));
1361
1362
    // 7. Let operation be the abstract operation associated with opText and Type(lnum) in the following table:
1363
    // [...]
1364
    // 8. Return operation(lnum, rnum).
1365
0
    if (both_number(lhs_numeric, rhs_numeric)) {
1366
        // 6.1.6.1.17 Number::bitwiseAND ( x, y ), https://tc39.es/ecma262/#sec-numeric-types-number-bitwiseAND
1367
        // 1. Return NumberBitwiseOp(&, x, y).
1368
0
        if (!lhs_numeric.is_finite_number() || !rhs_numeric.is_finite_number())
1369
0
            return Value(0);
1370
0
        return Value(TRY(lhs_numeric.to_i32(vm)) & TRY(rhs_numeric.to_i32(vm)));
1371
0
    }
1372
0
    if (both_bigint(lhs_numeric, rhs_numeric)) {
1373
        // 6.1.6.2.18 BigInt::bitwiseAND ( x, y ), https://tc39.es/ecma262/#sec-numeric-types-bigint-bitwiseAND
1374
        // 1. Return BigIntBitwiseOp(&, x, y).
1375
0
        return BigInt::create(vm, lhs_numeric.as_bigint().big_integer().bitwise_and(rhs_numeric.as_bigint().big_integer()));
1376
0
    }
1377
1378
    // 5. If Type(lnum) is different from Type(rnum), throw a TypeError exception.
1379
0
    return vm.throw_completion<TypeError>(ErrorType::BigIntBadOperatorOtherType, "bitwise AND");
1380
0
}
1381
1382
// 13.12 Binary Bitwise Operators, https://tc39.es/ecma262/#sec-binary-bitwise-operators
1383
// BitwiseORExpression : BitwiseORExpression | BitwiseXORExpression
1384
ThrowCompletionOr<Value> bitwise_or(VM& vm, Value lhs, Value rhs)
1385
0
{
1386
    // OPTIMIZATION: Fast path when both values are Int32.
1387
0
    if (lhs.is_int32() && rhs.is_int32())
1388
0
        return Value(lhs.as_i32() | rhs.as_i32());
1389
1390
    // 13.15.3 ApplyStringOrNumericBinaryOperator ( lval, opText, rval ), https://tc39.es/ecma262/#sec-applystringornumericbinaryoperator
1391
    // 1-2, 6. N/A.
1392
1393
    // 3. Let lnum be ? ToNumeric(lval).
1394
0
    auto lhs_numeric = TRY(lhs.to_numeric(vm));
1395
1396
    // 4. Let rnum be ? ToNumeric(rval).
1397
0
    auto rhs_numeric = TRY(rhs.to_numeric(vm));
1398
1399
    // 7. Let operation be the abstract operation associated with opText and Type(lnum) in the following table:
1400
    // [...]
1401
    // 8. Return operation(lnum, rnum).
1402
0
    if (both_number(lhs_numeric, rhs_numeric)) {
1403
        // 6.1.6.1.19 Number::bitwiseOR ( x, y ), https://tc39.es/ecma262/#sec-numeric-types-number-bitwiseOR
1404
        // 1. Return NumberBitwiseOp(|, x, y).
1405
0
        if (!lhs_numeric.is_finite_number() && !rhs_numeric.is_finite_number())
1406
0
            return Value(0);
1407
0
        if (!lhs_numeric.is_finite_number())
1408
0
            return rhs_numeric;
1409
0
        if (!rhs_numeric.is_finite_number())
1410
0
            return lhs_numeric;
1411
0
        return Value(TRY(lhs_numeric.to_i32(vm)) | TRY(rhs_numeric.to_i32(vm)));
1412
0
    }
1413
0
    if (both_bigint(lhs_numeric, rhs_numeric)) {
1414
        // 6.1.6.2.20 BigInt::bitwiseOR ( x, y )
1415
        // 1. Return BigIntBitwiseOp(|, x, y).
1416
0
        return BigInt::create(vm, lhs_numeric.as_bigint().big_integer().bitwise_or(rhs_numeric.as_bigint().big_integer()));
1417
0
    }
1418
1419
    // 5. If Type(lnum) is different from Type(rnum), throw a TypeError exception.
1420
0
    return vm.throw_completion<TypeError>(ErrorType::BigIntBadOperatorOtherType, "bitwise OR");
1421
0
}
1422
1423
// 13.12 Binary Bitwise Operators, https://tc39.es/ecma262/#sec-binary-bitwise-operators
1424
// BitwiseXORExpression : BitwiseXORExpression ^ BitwiseANDExpression
1425
ThrowCompletionOr<Value> bitwise_xor(VM& vm, Value lhs, Value rhs)
1426
0
{
1427
    // OPTIMIZATION: Fast path when both values are Int32.
1428
0
    if (lhs.is_int32() && rhs.is_int32())
1429
0
        return Value(lhs.as_i32() ^ rhs.as_i32());
1430
1431
    // 13.15.3 ApplyStringOrNumericBinaryOperator ( lval, opText, rval ), https://tc39.es/ecma262/#sec-applystringornumericbinaryoperator
1432
    // 1-2, 6. N/A.
1433
1434
    // 3. Let lnum be ? ToNumeric(lval).
1435
0
    auto lhs_numeric = TRY(lhs.to_numeric(vm));
1436
1437
    // 4. Let rnum be ? ToNumeric(rval).
1438
0
    auto rhs_numeric = TRY(rhs.to_numeric(vm));
1439
1440
    // 7. Let operation be the abstract operation associated with opText and Type(lnum) in the following table:
1441
    // [...]
1442
    // 8. Return operation(lnum, rnum).
1443
0
    if (both_number(lhs_numeric, rhs_numeric)) {
1444
        // 6.1.6.1.18 Number::bitwiseXOR ( x, y ), https://tc39.es/ecma262/#sec-numeric-types-number-bitwiseXOR
1445
        // 1. Return NumberBitwiseOp(^, x, y).
1446
0
        if (!lhs_numeric.is_finite_number() && !rhs_numeric.is_finite_number())
1447
0
            return Value(0);
1448
0
        if (!lhs_numeric.is_finite_number())
1449
0
            return rhs_numeric;
1450
0
        if (!rhs_numeric.is_finite_number())
1451
0
            return lhs_numeric;
1452
0
        return Value(TRY(lhs_numeric.to_i32(vm)) ^ TRY(rhs_numeric.to_i32(vm)));
1453
0
    }
1454
0
    if (both_bigint(lhs_numeric, rhs_numeric)) {
1455
        // 6.1.6.2.19 BigInt::bitwiseXOR ( x, y ), https://tc39.es/ecma262/#sec-numeric-types-bigint-bitwiseXOR
1456
        // 1. Return BigIntBitwiseOp(^, x, y).
1457
0
        return BigInt::create(vm, lhs_numeric.as_bigint().big_integer().bitwise_xor(rhs_numeric.as_bigint().big_integer()));
1458
0
    }
1459
1460
    // 5. If Type(lnum) is different from Type(rnum), throw a TypeError exception.
1461
0
    return vm.throw_completion<TypeError>(ErrorType::BigIntBadOperatorOtherType, "bitwise XOR");
1462
0
}
1463
1464
// 13.5.6 Bitwise NOT Operator ( ~ ), https://tc39.es/ecma262/#sec-bitwise-not-operator
1465
// UnaryExpression : ~ UnaryExpression
1466
ThrowCompletionOr<Value> bitwise_not(VM& vm, Value lhs)
1467
0
{
1468
    // 1. Let expr be ? Evaluation of UnaryExpression.
1469
    // NOTE: This is handled in the AST or Bytecode interpreter.
1470
1471
    // 2. Let oldValue be ? ToNumeric(? GetValue(expr)).
1472
1473
0
    auto old_value = TRY(lhs.to_numeric(vm));
1474
1475
    // 3. If oldValue is a Number, then
1476
0
    if (old_value.is_number()) {
1477
        // a. Return Number::bitwiseNOT(oldValue).
1478
1479
        // 6.1.6.1.2 Number::bitwiseNOT ( x ), https://tc39.es/ecma262/#sec-numeric-types-number-bitwiseNOT
1480
        // 1. Let oldValue be ! ToInt32(x).
1481
        // 2. Return the result of applying bitwise complement to oldValue. The mathematical value of the result is
1482
        //    exactly representable as a 32-bit two's complement bit string.
1483
0
        return Value(~TRY(old_value.to_i32(vm)));
1484
0
    }
1485
1486
    // 4. Else,
1487
    // a. Assert: oldValue is a BigInt.
1488
0
    VERIFY(old_value.is_bigint());
1489
1490
    // b. Return BigInt::bitwiseNOT(oldValue).
1491
1492
    // 6.1.6.2.2 BigInt::bitwiseNOT ( x ), https://tc39.es/ecma262/#sec-numeric-types-bigint-bitwiseNOT
1493
    // 1. Return -x - 1ℤ.
1494
0
    return BigInt::create(vm, old_value.as_bigint().big_integer().bitwise_not());
1495
0
}
1496
1497
// 13.5.4 Unary + Operator, https://tc39.es/ecma262/#sec-unary-plus-operator
1498
// UnaryExpression : + UnaryExpression
1499
ThrowCompletionOr<Value> unary_plus(VM& vm, Value lhs)
1500
0
{
1501
    // 1. Let expr be ? Evaluation of UnaryExpression.
1502
    // NOTE: This is handled in the AST or Bytecode interpreter.
1503
1504
    // 2. Return ? ToNumber(? GetValue(expr)).
1505
0
    return TRY(lhs.to_number(vm));
1506
0
}
1507
1508
// 13.5.5 Unary - Operator, https://tc39.es/ecma262/#sec-unary-minus-operator
1509
// UnaryExpression : - UnaryExpression
1510
ThrowCompletionOr<Value> unary_minus(VM& vm, Value lhs)
1511
0
{
1512
    // 1. Let expr be ? Evaluation of UnaryExpression.
1513
    // NOTE: This is handled in the AST or Bytecode interpreter.
1514
1515
    // 2. Let oldValue be ? ToNumeric(? GetValue(expr)).
1516
0
    auto old_value = TRY(lhs.to_numeric(vm));
1517
1518
    // 3. If oldValue is a Number, then
1519
0
    if (old_value.is_number()) {
1520
        // a. Return Number::unaryMinus(oldValue).
1521
1522
        // 6.1.6.1.1 Number::unaryMinus ( x ), https://tc39.es/ecma262/#sec-numeric-types-number-unaryMinus
1523
        // 1. If x is NaN, return NaN.
1524
0
        if (old_value.is_nan())
1525
0
            return js_nan();
1526
1527
        // 2. Return the result of negating x; that is, compute a Number with the same magnitude but opposite sign.
1528
0
        return Value(-old_value.as_double());
1529
0
    }
1530
1531
    // 4. Else,
1532
    // a. Assert: oldValue is a BigInt.
1533
0
    VERIFY(old_value.is_bigint());
1534
1535
    // b. Return BigInt::unaryMinus(oldValue).
1536
1537
    // 6.1.6.2.1 BigInt::unaryMinus ( x ), https://tc39.es/ecma262/#sec-numeric-types-bigint-unaryMinus
1538
    // 1. If x is 0ℤ, return 0ℤ.
1539
0
    if (old_value.as_bigint().big_integer() == BIGINT_ZERO)
1540
0
        return BigInt::create(vm, BIGINT_ZERO);
1541
1542
    // 2. Return the BigInt value that represents the negation of ℝ(x).
1543
0
    auto big_integer_negated = old_value.as_bigint().big_integer();
1544
0
    big_integer_negated.negate();
1545
0
    return BigInt::create(vm, big_integer_negated);
1546
0
}
1547
1548
// 13.9.1 The Left Shift Operator ( << ), https://tc39.es/ecma262/#sec-left-shift-operator
1549
// ShiftExpression : ShiftExpression << AdditiveExpression
1550
ThrowCompletionOr<Value> left_shift(VM& vm, Value lhs, Value rhs)
1551
0
{
1552
    // 13.15.3 ApplyStringOrNumericBinaryOperator ( lval, opText, rval ), https://tc39.es/ecma262/#sec-applystringornumericbinaryoperator
1553
    // 1-2, 6. N/A.
1554
1555
    // 3. Let lnum be ? ToNumeric(lval).
1556
0
    auto lhs_numeric = TRY(lhs.to_numeric(vm));
1557
1558
    // 4. Let rnum be ? ToNumeric(rval).
1559
0
    auto rhs_numeric = TRY(rhs.to_numeric(vm));
1560
1561
    // 7. Let operation be the abstract operation associated with opText and Type(lnum) in the following table:
1562
    // [...]
1563
    // 8. Return operation(lnum, rnum).
1564
0
    if (both_number(lhs_numeric, rhs_numeric)) {
1565
        // 6.1.6.1.9 Number::leftShift ( x, y ), https://tc39.es/ecma262/#sec-numeric-types-number-leftShift
1566
1567
        // OPTIMIZATION: Handle infinite values according to the results returned by ToInt32/ToUint32.
1568
0
        if (!lhs_numeric.is_finite_number())
1569
0
            return Value(0);
1570
0
        if (!rhs_numeric.is_finite_number())
1571
0
            return lhs_numeric;
1572
1573
        // 1. Let lnum be ! ToInt32(x).
1574
0
        auto lhs_i32 = MUST(lhs_numeric.to_i32(vm));
1575
1576
        // 2. Let rnum be ! ToUint32(y).
1577
0
        auto rhs_u32 = MUST(rhs_numeric.to_u32(vm));
1578
1579
        // 3. Let shiftCount be ℝ(rnum) modulo 32.
1580
0
        auto shift_count = rhs_u32 % 32;
1581
1582
        // 4. Return the result of left shifting lnum by shiftCount bits. The mathematical value of the result is
1583
        //    exactly representable as a 32-bit two's complement bit string.
1584
0
        return Value(lhs_i32 << shift_count);
1585
0
    }
1586
0
    if (both_bigint(lhs_numeric, rhs_numeric)) {
1587
        // 6.1.6.2.9 BigInt::leftShift ( x, y ), https://tc39.es/ecma262/#sec-numeric-types-bigint-leftShift
1588
0
        auto multiplier_divisor = Crypto::SignedBigInteger { Crypto::NumberTheory::Power(Crypto::UnsignedBigInteger(2), rhs_numeric.as_bigint().big_integer().unsigned_value()) };
1589
1590
        // 1. If y < 0ℤ, then
1591
0
        if (rhs_numeric.as_bigint().big_integer().is_negative()) {
1592
            // a. Return the BigInt value that represents ℝ(x) / 2^-y, rounding down to the nearest integer, including for negative numbers.
1593
            // NOTE: Since y is negative we can just do ℝ(x) / 2^|y|
1594
0
            auto const& big_integer = lhs_numeric.as_bigint().big_integer();
1595
0
            auto division_result = big_integer.divided_by(multiplier_divisor);
1596
1597
            // For positive initial values and no remainder just return quotient
1598
0
            if (division_result.remainder.is_zero() || !big_integer.is_negative())
1599
0
                return BigInt::create(vm, division_result.quotient);
1600
            // For negative round "down" to the next negative number
1601
0
            return BigInt::create(vm, division_result.quotient.minus(Crypto::SignedBigInteger { 1 }));
1602
0
        }
1603
        // 2. Return the BigInt value that represents ℝ(x) × 2^y.
1604
0
        return Value(BigInt::create(vm, lhs_numeric.as_bigint().big_integer().multiplied_by(multiplier_divisor)));
1605
0
    }
1606
1607
    // 5. If Type(lnum) is different from Type(rnum), throw a TypeError exception.
1608
0
    return vm.throw_completion<TypeError>(ErrorType::BigIntBadOperatorOtherType, "left-shift");
1609
0
}
1610
1611
// 13.9.2 The Signed Right Shift Operator ( >> ), https://tc39.es/ecma262/#sec-signed-right-shift-operator
1612
// ShiftExpression : ShiftExpression >> AdditiveExpression
1613
ThrowCompletionOr<Value> right_shift(VM& vm, Value lhs, Value rhs)
1614
0
{
1615
    // 13.15.3 ApplyStringOrNumericBinaryOperator ( lval, opText, rval ), https://tc39.es/ecma262/#sec-applystringornumericbinaryoperator
1616
    // 1-2, 6. N/A.
1617
1618
    // 3. Let lnum be ? ToNumeric(lval).
1619
0
    auto lhs_numeric = TRY(lhs.to_numeric(vm));
1620
1621
    // 4. Let rnum be ? ToNumeric(rval).
1622
0
    auto rhs_numeric = TRY(rhs.to_numeric(vm));
1623
1624
    // 7. Let operation be the abstract operation associated with opText and Type(lnum) in the following table:
1625
    // [...]
1626
    // 8. Return operation(lnum, rnum).
1627
0
    if (both_number(lhs_numeric, rhs_numeric)) {
1628
        // 6.1.6.1.10 Number::signedRightShift ( x, y ), https://tc39.es/ecma262/#sec-numeric-types-number-signedRightShift
1629
1630
        // OPTIMIZATION: Handle infinite values according to the results returned by ToInt32/ToUint32.
1631
0
        if (!lhs_numeric.is_finite_number())
1632
0
            return Value(0);
1633
0
        if (!rhs_numeric.is_finite_number())
1634
0
            return lhs_numeric;
1635
1636
        // 1. Let lnum be ! ToInt32(x).
1637
0
        auto lhs_i32 = MUST(lhs_numeric.to_i32(vm));
1638
1639
        // 2. Let rnum be ! ToUint32(y).
1640
0
        auto rhs_u32 = MUST(rhs_numeric.to_u32(vm));
1641
1642
        // 3. Let shiftCount be ℝ(rnum) modulo 32.
1643
0
        auto shift_count = rhs_u32 % 32;
1644
1645
        // 4. Return the result of performing a sign-extending right shift of lnum by shiftCount bits.
1646
        //    The most significant bit is propagated. The mathematical value of the result is exactly representable
1647
        //    as a 32-bit two's complement bit string.
1648
0
        return Value(lhs_i32 >> shift_count);
1649
0
    }
1650
0
    if (both_bigint(lhs_numeric, rhs_numeric)) {
1651
        // 6.1.6.2.10 BigInt::signedRightShift ( x, y ), https://tc39.es/ecma262/#sec-numeric-types-bigint-signedRightShift
1652
        // 1. Return BigInt::leftShift(x, -y).
1653
0
        auto rhs_negated = rhs_numeric.as_bigint().big_integer();
1654
0
        rhs_negated.negate();
1655
0
        return left_shift(vm, lhs, BigInt::create(vm, rhs_negated));
1656
0
    }
1657
1658
    // 5. If Type(lnum) is different from Type(rnum), throw a TypeError exception.
1659
0
    return vm.throw_completion<TypeError>(ErrorType::BigIntBadOperatorOtherType, "right-shift");
1660
0
}
1661
1662
// 13.9.3 The Unsigned Right Shift Operator ( >>> ), https://tc39.es/ecma262/#sec-unsigned-right-shift-operator
1663
// ShiftExpression : ShiftExpression >>> AdditiveExpression
1664
ThrowCompletionOr<Value> unsigned_right_shift(VM& vm, Value lhs, Value rhs)
1665
0
{
1666
    // 13.15.3 ApplyStringOrNumericBinaryOperator ( lval, opText, rval ), https://tc39.es/ecma262/#sec-applystringornumericbinaryoperator
1667
    // 1-2, 5-6. N/A.
1668
1669
    // 3. Let lnum be ? ToNumeric(lval).
1670
0
    auto lhs_numeric = TRY(lhs.to_numeric(vm));
1671
1672
    // 4. Let rnum be ? ToNumeric(rval).
1673
0
    auto rhs_numeric = TRY(rhs.to_numeric(vm));
1674
1675
    // 7. Let operation be the abstract operation associated with opText and Type(lnum) in the following table:
1676
    // [...]
1677
    // 8. Return operation(lnum, rnum).
1678
0
    if (both_number(lhs_numeric, rhs_numeric)) {
1679
        // 6.1.6.1.11 Number::unsignedRightShift ( x, y ), https://tc39.es/ecma262/#sec-numeric-types-number-unsignedRightShift
1680
1681
        // OPTIMIZATION: Handle infinite values according to the results returned by ToUint32.
1682
0
        if (!lhs_numeric.is_finite_number())
1683
0
            return Value(0);
1684
0
        if (!rhs_numeric.is_finite_number())
1685
0
            return lhs_numeric;
1686
1687
        // 1. Let lnum be ! ToUint32(x).
1688
0
        auto lhs_u32 = MUST(lhs_numeric.to_u32(vm));
1689
1690
        // 2. Let rnum be ! ToUint32(y).
1691
0
        auto rhs_u32 = MUST(rhs_numeric.to_u32(vm));
1692
1693
        // 3. Let shiftCount be ℝ(rnum) modulo 32.
1694
0
        auto shift_count = rhs_u32 % 32;
1695
1696
        // 4. Return the result of performing a zero-filling right shift of lnum by shiftCount bits.
1697
        //    Vacated bits are filled with zero. The mathematical value of the result is exactly representable
1698
        //    as a 32-bit unsigned bit string.
1699
0
        return Value(lhs_u32 >> shift_count);
1700
0
    }
1701
1702
    // 6. If lnum is a BigInt, then
1703
    // d. If opText is >>>, return ? BigInt::unsignedRightShift(lnum, rnum).
1704
1705
    // 6.1.6.2.11 BigInt::unsignedRightShift ( x, y ), https://tc39.es/ecma262/#sec-numeric-types-bigint-unsignedRightShift
1706
    // 1. Throw a TypeError exception.
1707
0
    return vm.throw_completion<TypeError>(ErrorType::BigIntBadOperator, "unsigned right-shift");
1708
0
}
1709
1710
// 13.8.1 The Addition Operator ( + ), https://tc39.es/ecma262/#sec-addition-operator-plus
1711
// AdditiveExpression : AdditiveExpression + MultiplicativeExpression
1712
ThrowCompletionOr<Value> add(VM& vm, Value lhs, Value rhs)
1713
0
{
1714
    // 13.15.3 ApplyStringOrNumericBinaryOperator ( lval, opText, rval ), https://tc39.es/ecma262/#sec-applystringornumericbinaryoperator
1715
1716
    // 1. If opText is +, then
1717
1718
    // OPTIMIZATION: If both values are i32 or double, we can do a direct addition without the type conversions below.
1719
0
    if (both_number(lhs, rhs)) {
1720
0
        if (lhs.is_int32() && rhs.is_int32()) {
1721
0
            Checked<i32> result;
1722
0
            result = MUST(lhs.to_i32(vm));
1723
0
            result += MUST(rhs.to_i32(vm));
1724
0
            if (!result.has_overflow())
1725
0
                return Value(result.value());
1726
0
        }
1727
0
        return Value(lhs.as_double() + rhs.as_double());
1728
0
    }
1729
1730
    // a. Let lprim be ? ToPrimitive(lval).
1731
0
    auto lhs_primitive = TRY(lhs.to_primitive(vm));
1732
1733
    // b. Let rprim be ? ToPrimitive(rval).
1734
0
    auto rhs_primitive = TRY(rhs.to_primitive(vm));
1735
1736
    // c. If lprim is a String or rprim is a String, then
1737
0
    if (lhs_primitive.is_string() || rhs_primitive.is_string()) {
1738
        // i. Let lstr be ? ToString(lprim).
1739
0
        auto lhs_string = TRY(lhs_primitive.to_primitive_string(vm));
1740
1741
        // ii. Let rstr be ? ToString(rprim).
1742
0
        auto rhs_string = TRY(rhs_primitive.to_primitive_string(vm));
1743
1744
        // iii. Return the string-concatenation of lstr and rstr.
1745
0
        return PrimitiveString::create(vm, lhs_string, rhs_string);
1746
0
    }
1747
1748
    // d. Set lval to lprim.
1749
    // e. Set rval to rprim.
1750
1751
    // 2. NOTE: At this point, it must be a numeric operation.
1752
1753
    // 3. Let lnum be ? ToNumeric(lval).
1754
0
    auto lhs_numeric = TRY(lhs_primitive.to_numeric(vm));
1755
1756
    // 4. Let rnum be ? ToNumeric(rval).
1757
0
    auto rhs_numeric = TRY(rhs_primitive.to_numeric(vm));
1758
1759
    // 6. N/A.
1760
1761
    // 7. Let operation be the abstract operation associated with opText and Type(lnum) in the following table:
1762
    // [...]
1763
    // 8. Return operation(lnum, rnum).
1764
0
    if (both_number(lhs_numeric, rhs_numeric)) {
1765
        // 6.1.6.1.7 Number::add ( x, y ), https://tc39.es/ecma262/#sec-numeric-types-number-add
1766
0
        auto x = lhs_numeric.as_double();
1767
0
        auto y = rhs_numeric.as_double();
1768
0
        return Value(x + y);
1769
0
    }
1770
0
    if (both_bigint(lhs_numeric, rhs_numeric)) {
1771
        // 6.1.6.2.7 BigInt::add ( x, y ), https://tc39.es/ecma262/#sec-numeric-types-bigint-add
1772
0
        auto x = lhs_numeric.as_bigint().big_integer();
1773
0
        auto y = rhs_numeric.as_bigint().big_integer();
1774
0
        return BigInt::create(vm, x.plus(y));
1775
0
    }
1776
1777
    // 5. If Type(lnum) is different from Type(rnum), throw a TypeError exception.
1778
0
    return vm.throw_completion<TypeError>(ErrorType::BigIntBadOperatorOtherType, "addition");
1779
0
}
1780
1781
// 13.8.2 The Subtraction Operator ( - ), https://tc39.es/ecma262/#sec-subtraction-operator-minus
1782
// AdditiveExpression : AdditiveExpression - MultiplicativeExpression
1783
ThrowCompletionOr<Value> sub(VM& vm, Value lhs, Value rhs)
1784
0
{
1785
    // 13.15.3 ApplyStringOrNumericBinaryOperator ( lval, opText, rval ), https://tc39.es/ecma262/#sec-applystringornumericbinaryoperator
1786
    // 1-2, 6. N/A.
1787
1788
    // 3. Let lnum be ? ToNumeric(lval).
1789
0
    auto lhs_numeric = TRY(lhs.to_numeric(vm));
1790
1791
    // 4. Let rnum be ? ToNumeric(rval).
1792
0
    auto rhs_numeric = TRY(rhs.to_numeric(vm));
1793
1794
    // 7. Let operation be the abstract operation associated with opText and Type(lnum) in the following table:
1795
    // [...]
1796
    // 8. Return operation(lnum, rnum).
1797
0
    if (both_number(lhs_numeric, rhs_numeric)) {
1798
        // 6.1.6.1.8 Number::subtract ( x, y ), https://tc39.es/ecma262/#sec-numeric-types-number-subtract
1799
0
        auto x = lhs_numeric.as_double();
1800
0
        auto y = rhs_numeric.as_double();
1801
        // 1. Return Number::add(x, Number::unaryMinus(y)).
1802
0
        return Value(x - y);
1803
0
    }
1804
0
    if (both_bigint(lhs_numeric, rhs_numeric)) {
1805
        // 6.1.6.2.8 BigInt::subtract ( x, y ), https://tc39.es/ecma262/#sec-numeric-types-bigint-subtract
1806
0
        auto x = lhs_numeric.as_bigint().big_integer();
1807
0
        auto y = rhs_numeric.as_bigint().big_integer();
1808
        // 1. Return the BigInt value that represents the difference x minus y.
1809
0
        return BigInt::create(vm, x.minus(y));
1810
0
    }
1811
1812
    // 5. If Type(lnum) is different from Type(rnum), throw a TypeError exception.
1813
0
    return vm.throw_completion<TypeError>(ErrorType::BigIntBadOperatorOtherType, "subtraction");
1814
0
}
1815
1816
// 13.7 Multiplicative Operators, https://tc39.es/ecma262/#sec-multiplicative-operators
1817
// MultiplicativeExpression : MultiplicativeExpression MultiplicativeOperator ExponentiationExpression
1818
ThrowCompletionOr<Value> mul(VM& vm, Value lhs, Value rhs)
1819
0
{
1820
    // OPTIMIZATION: Fast path for multiplication of two Int32 values.
1821
0
    if (lhs.is_int32() && rhs.is_int32()) {
1822
0
        Checked<i32> result = lhs.as_i32();
1823
0
        result *= rhs.as_i32();
1824
0
        if (!result.has_overflow())
1825
0
            return result.value();
1826
0
    }
1827
1828
    // 13.15.3 ApplyStringOrNumericBinaryOperator ( lval, opText, rval ), https://tc39.es/ecma262/#sec-applystringornumericbinaryoperator
1829
    // 1-2, 6. N/A.
1830
1831
    // 3. Let lnum be ? ToNumeric(lval).
1832
0
    auto lhs_numeric = TRY(lhs.to_numeric(vm));
1833
1834
    // 4. Let rnum be ? ToNumeric(rval).
1835
0
    auto rhs_numeric = TRY(rhs.to_numeric(vm));
1836
1837
    // 7. Let operation be the abstract operation associated with opText and Type(lnum) in the following table:
1838
    // [...]
1839
    // 8. Return operation(lnum, rnum).
1840
0
    if (both_number(lhs_numeric, rhs_numeric)) {
1841
        // 6.1.6.1.4 Number::multiply ( x, y ), https://tc39.es/ecma262/#sec-numeric-types-number-multiply
1842
0
        auto x = lhs_numeric.as_double();
1843
0
        auto y = rhs_numeric.as_double();
1844
0
        return Value(x * y);
1845
0
    }
1846
0
    if (both_bigint(lhs_numeric, rhs_numeric)) {
1847
        // 6.1.6.2.4 BigInt::multiply ( x, y ), https://tc39.es/ecma262/#sec-numeric-types-bigint-multiply
1848
0
        auto x = lhs_numeric.as_bigint().big_integer();
1849
0
        auto y = rhs_numeric.as_bigint().big_integer();
1850
        // 1. Return the BigInt value that represents the product of x and y.
1851
0
        return BigInt::create(vm, x.multiplied_by(y));
1852
0
    }
1853
1854
    // 5. If Type(lnum) is different from Type(rnum), throw a TypeError exception.
1855
0
    return vm.throw_completion<TypeError>(ErrorType::BigIntBadOperatorOtherType, "multiplication");
1856
0
}
1857
1858
// 13.7 Multiplicative Operators, https://tc39.es/ecma262/#sec-multiplicative-operators
1859
// MultiplicativeExpression : MultiplicativeExpression MultiplicativeOperator ExponentiationExpression
1860
ThrowCompletionOr<Value> div(VM& vm, Value lhs, Value rhs)
1861
0
{
1862
    // 13.15.3 ApplyStringOrNumericBinaryOperator ( lval, opText, rval ), https://tc39.es/ecma262/#sec-applystringornumericbinaryoperator
1863
    // 1-2, 6. N/A.
1864
1865
    // 3. Let lnum be ? ToNumeric(lval).
1866
0
    auto lhs_numeric = TRY(lhs.to_numeric(vm));
1867
1868
    // 4. Let rnum be ? ToNumeric(rval).
1869
0
    auto rhs_numeric = TRY(rhs.to_numeric(vm));
1870
1871
    // 7. Let operation be the abstract operation associated with opText and Type(lnum) in the following table:
1872
    // [...]
1873
    // 8. Return operation(lnum, rnum).
1874
0
    if (both_number(lhs_numeric, rhs_numeric)) {
1875
        // 6.1.6.1.5 Number::divide ( x, y ), https://tc39.es/ecma262/#sec-numeric-types-number-divide
1876
0
        return Value(lhs_numeric.as_double() / rhs_numeric.as_double());
1877
0
    }
1878
0
    if (both_bigint(lhs_numeric, rhs_numeric)) {
1879
        // 6.1.6.2.5 BigInt::divide ( x, y ), https://tc39.es/ecma262/#sec-numeric-types-bigint-divide
1880
0
        auto x = lhs_numeric.as_bigint().big_integer();
1881
0
        auto y = rhs_numeric.as_bigint().big_integer();
1882
        // 1. If y is 0ℤ, throw a RangeError exception.
1883
0
        if (y == BIGINT_ZERO)
1884
0
            return vm.throw_completion<RangeError>(ErrorType::DivisionByZero);
1885
        // 2. Let quotient be ℝ(x) / ℝ(y).
1886
        // 3. Return the BigInt value that represents quotient rounded towards 0 to the next integer value.
1887
0
        return BigInt::create(vm, x.divided_by(y).quotient);
1888
0
    }
1889
1890
    // 5. If Type(lnum) is different from Type(rnum), throw a TypeError exception.
1891
0
    return vm.throw_completion<TypeError>(ErrorType::BigIntBadOperatorOtherType, "division");
1892
0
}
1893
1894
// 13.7 Multiplicative Operators, https://tc39.es/ecma262/#sec-multiplicative-operators
1895
// MultiplicativeExpression : MultiplicativeExpression MultiplicativeOperator ExponentiationExpression
1896
ThrowCompletionOr<Value> mod(VM& vm, Value lhs, Value rhs)
1897
0
{
1898
    // 13.15.3 ApplyStringOrNumericBinaryOperator ( lval, opText, rval ), https://tc39.es/ecma262/#sec-applystringornumericbinaryoperator
1899
    // 1-2, 6. N/A.
1900
1901
    // 3. Let lnum be ? ToNumeric(lval).
1902
0
    auto lhs_numeric = TRY(lhs.to_numeric(vm));
1903
1904
    // 4. Let rnum be ? ToNumeric(rval).
1905
0
    auto rhs_numeric = TRY(rhs.to_numeric(vm));
1906
1907
    // 7. Let operation be the abstract operation associated with opText and Type(lnum) in the following table:
1908
    // [...]
1909
    // 8. Return operation(lnum, rnum).
1910
0
    if (both_number(lhs_numeric, rhs_numeric)) {
1911
        // 6.1.6.1.6 Number::remainder ( n, d ), https://tc39.es/ecma262/#sec-numeric-types-number-remainder
1912
        // The ECMA specification is describing the mathematical definition of modulus
1913
        // implemented by fmod.
1914
0
        auto n = lhs_numeric.as_double();
1915
0
        auto d = rhs_numeric.as_double();
1916
0
        return Value(fmod(n, d));
1917
0
    }
1918
0
    if (both_bigint(lhs_numeric, rhs_numeric)) {
1919
        // 6.1.6.2.6 BigInt::remainder ( n, d ), https://tc39.es/ecma262/#sec-numeric-types-bigint-remainder
1920
0
        auto n = lhs_numeric.as_bigint().big_integer();
1921
0
        auto d = rhs_numeric.as_bigint().big_integer();
1922
        // 1. If d is 0ℤ, throw a RangeError exception.
1923
0
        if (d == BIGINT_ZERO)
1924
0
            return vm.throw_completion<RangeError>(ErrorType::DivisionByZero);
1925
        // 2. If n is 0ℤ, return 0ℤ.
1926
        // 3. Let quotient be ℝ(n) / ℝ(d).
1927
        // 4. Let q be the BigInt whose sign is the sign of quotient and whose magnitude is floor(abs(quotient)).
1928
        // 5. Return n - (d × q).
1929
0
        return BigInt::create(vm, n.divided_by(d).remainder);
1930
0
    }
1931
1932
    // 5. If Type(lnum) is different from Type(rnum), throw a TypeError exception.
1933
0
    return vm.throw_completion<TypeError>(ErrorType::BigIntBadOperatorOtherType, "modulo");
1934
0
}
1935
1936
// 6.1.6.1.3 Number::exponentiate ( base, exponent ), https://tc39.es/ecma262/#sec-numeric-types-number-exponentiate
1937
static Value exp_double(Value base, Value exponent)
1938
0
{
1939
0
    VERIFY(both_number(base, exponent));
1940
1941
    // 1. If exponent is NaN, return NaN.
1942
0
    if (exponent.is_nan())
1943
0
        return js_nan();
1944
1945
    // 2. If exponent is +0𝔽 or exponent is -0𝔽, return 1𝔽.
1946
0
    if (exponent.is_positive_zero() || exponent.is_negative_zero())
1947
0
        return Value(1);
1948
1949
    // 3. If base is NaN, return NaN.
1950
0
    if (base.is_nan())
1951
0
        return js_nan();
1952
1953
    // 4. If base is +∞𝔽, then
1954
0
    if (base.is_positive_infinity()) {
1955
        // a. If exponent > +0𝔽, return +∞𝔽. Otherwise, return +0𝔽.
1956
0
        return exponent.as_double() > 0 ? js_infinity() : Value(0);
1957
0
    }
1958
1959
    // 5. If base is -∞𝔽, then
1960
0
    if (base.is_negative_infinity()) {
1961
0
        auto is_odd_integral_number = exponent.is_integral_number() && (fmod(exponent.as_double(), 2.0) != 0);
1962
1963
        // a. If exponent > +0𝔽, then
1964
0
        if (exponent.as_double() > 0) {
1965
            // i. If exponent is an odd integral Number, return -∞𝔽. Otherwise, return +∞𝔽.
1966
0
            return is_odd_integral_number ? js_negative_infinity() : js_infinity();
1967
0
        }
1968
        // b. Else,
1969
0
        else {
1970
            // i. If exponent is an odd integral Number, return -0𝔽. Otherwise, return +0𝔽.
1971
0
            return is_odd_integral_number ? Value(-0.0) : Value(0);
1972
0
        }
1973
0
    }
1974
1975
    // 6. If base is +0𝔽, then
1976
0
    if (base.is_positive_zero()) {
1977
        // a. If exponent > +0𝔽, return +0𝔽. Otherwise, return +∞𝔽.
1978
0
        return exponent.as_double() > 0 ? Value(0) : js_infinity();
1979
0
    }
1980
1981
    // 7. If base is -0𝔽, then
1982
0
    if (base.is_negative_zero()) {
1983
0
        auto is_odd_integral_number = exponent.is_integral_number() && (fmod(exponent.as_double(), 2.0) != 0);
1984
1985
        // a. If exponent > +0𝔽, then
1986
0
        if (exponent.as_double() > 0) {
1987
            // i. If exponent is an odd integral Number, return -0𝔽. Otherwise, return +0𝔽.
1988
0
            return is_odd_integral_number ? Value(-0.0) : Value(0);
1989
0
        }
1990
        // b. Else,
1991
0
        else {
1992
            // i. If exponent is an odd integral Number, return -∞𝔽. Otherwise, return +∞𝔽.
1993
0
            return is_odd_integral_number ? js_negative_infinity() : js_infinity();
1994
0
        }
1995
0
    }
1996
1997
    // 8. Assert: base is finite and is neither +0𝔽 nor -0𝔽.
1998
0
    VERIFY(base.is_finite_number() && !base.is_positive_zero() && !base.is_negative_zero());
1999
2000
    // 9. If exponent is +∞𝔽, then
2001
0
    if (exponent.is_positive_infinity()) {
2002
0
        auto absolute_base = fabs(base.as_double());
2003
2004
        // a. If abs(ℝ(base)) > 1, return +∞𝔽.
2005
0
        if (absolute_base > 1)
2006
0
            return js_infinity();
2007
        // b. If abs(ℝ(base)) is 1, return NaN.
2008
0
        else if (absolute_base == 1)
2009
0
            return js_nan();
2010
        // c. If abs(ℝ(base)) < 1, return +0𝔽.
2011
0
        else if (absolute_base < 1)
2012
0
            return Value(0);
2013
0
    }
2014
2015
    // 10. If exponent is -∞𝔽, then
2016
0
    if (exponent.is_negative_infinity()) {
2017
0
        auto absolute_base = fabs(base.as_double());
2018
2019
        // a. If abs(ℝ(base)) > 1, return +0𝔽.
2020
0
        if (absolute_base > 1)
2021
0
            return Value(0);
2022
        // b. If abs(ℝ(base)) is 1, return NaN.
2023
0
        else if (absolute_base == 1)
2024
0
            return js_nan();
2025
        // a. If abs(ℝ(base)) > 1, return +0𝔽.
2026
0
        else if (absolute_base < 1)
2027
0
            return js_infinity();
2028
0
    }
2029
2030
    // 11. Assert: exponent is finite and is neither +0𝔽 nor -0𝔽.
2031
0
    VERIFY(exponent.is_finite_number() && !exponent.is_positive_zero() && !exponent.is_negative_zero());
2032
2033
    // 12. If base < -0𝔽 and exponent is not an integral Number, return NaN.
2034
0
    if (base.as_double() < 0 && !exponent.is_integral_number())
2035
0
        return js_nan();
2036
2037
    // 13. Return an implementation-approximated Number value representing the result of raising ℝ(base) to the ℝ(exponent) power.
2038
0
    return Value(::pow(base.as_double(), exponent.as_double()));
2039
0
}
2040
2041
// 13.6 Exponentiation Operator, https://tc39.es/ecma262/#sec-exp-operator
2042
// ExponentiationExpression : UpdateExpression ** ExponentiationExpression
2043
ThrowCompletionOr<Value> exp(VM& vm, Value lhs, Value rhs)
2044
0
{
2045
    // 3. Let lnum be ? ToNumeric(lval).
2046
0
    auto lhs_numeric = TRY(lhs.to_numeric(vm));
2047
2048
    // 4. Let rnum be ? ToNumeric(rval).
2049
0
    auto rhs_numeric = TRY(rhs.to_numeric(vm));
2050
2051
    // 7. Let operation be the abstract operation associated with opText and Type(lnum) in the following table:
2052
    // [...]
2053
    // 8. Return operation(lnum, rnum).
2054
0
    if (both_number(lhs_numeric, rhs_numeric)) {
2055
0
        return exp_double(lhs_numeric, rhs_numeric);
2056
0
    }
2057
0
    if (both_bigint(lhs_numeric, rhs_numeric)) {
2058
        // 6.1.6.2.3 BigInt::exponentiate ( base, exponent ), https://tc39.es/ecma262/#sec-numeric-types-bigint-exponentiate
2059
0
        auto base = lhs_numeric.as_bigint().big_integer();
2060
0
        auto exponent = rhs_numeric.as_bigint().big_integer();
2061
        // 1. If exponent < 0ℤ, throw a RangeError exception.
2062
0
        if (exponent.is_negative())
2063
0
            return vm.throw_completion<RangeError>(ErrorType::NegativeExponent);
2064
        // 2. If base is 0ℤ and exponent is 0ℤ, return 1ℤ.
2065
        // 3. Return the BigInt value that represents ℝ(base) raised to the power ℝ(exponent).
2066
0
        return BigInt::create(vm, Crypto::NumberTheory::Power(base, exponent));
2067
0
    }
2068
0
    return vm.throw_completion<TypeError>(ErrorType::BigIntBadOperatorOtherType, "exponentiation");
2069
0
}
2070
2071
ThrowCompletionOr<Value> in(VM& vm, Value lhs, Value rhs)
2072
0
{
2073
0
    if (!rhs.is_object())
2074
0
        return vm.throw_completion<TypeError>(ErrorType::InOperatorWithObject);
2075
0
    auto lhs_property_key = TRY(lhs.to_property_key(vm));
2076
0
    return Value(TRY(rhs.as_object().has_property(lhs_property_key)));
2077
0
}
2078
2079
// 13.10.2 InstanceofOperator ( V, target ), https://tc39.es/ecma262/#sec-instanceofoperator
2080
ThrowCompletionOr<Value> instance_of(VM& vm, Value value, Value target)
2081
0
{
2082
    // 1. If target is not an Object, throw a TypeError exception.
2083
0
    if (!target.is_object())
2084
0
        return vm.throw_completion<TypeError>(ErrorType::NotAnObject, target.to_string_without_side_effects());
2085
2086
    // 2. Let instOfHandler be ? GetMethod(target, @@hasInstance).
2087
0
    auto instance_of_handler = TRY(target.get_method(vm, vm.well_known_symbol_has_instance()));
2088
2089
    // 3. If instOfHandler is not undefined, then
2090
0
    if (instance_of_handler) {
2091
        // a. Return ToBoolean(? Call(instOfHandler, target, « V »)).
2092
0
        return Value(TRY(call(vm, *instance_of_handler, target, value)).to_boolean());
2093
0
    }
2094
2095
    // 4. If IsCallable(target) is false, throw a TypeError exception.
2096
0
    if (!target.is_function())
2097
0
        return vm.throw_completion<TypeError>(ErrorType::NotAFunction, target.to_string_without_side_effects());
2098
2099
    // 5. Return ? OrdinaryHasInstance(target, V).
2100
0
    return ordinary_has_instance(vm, target, value);
2101
0
}
2102
2103
// 7.3.22 OrdinaryHasInstance ( C, O ), https://tc39.es/ecma262/#sec-ordinaryhasinstance
2104
ThrowCompletionOr<Value> ordinary_has_instance(VM& vm, Value lhs, Value rhs)
2105
0
{
2106
    // 1. If IsCallable(C) is false, return false.
2107
0
    if (!rhs.is_function())
2108
0
        return Value(false);
2109
2110
0
    auto& rhs_function = rhs.as_function();
2111
2112
    // 2. If C has a [[BoundTargetFunction]] internal slot, then
2113
0
    if (is<BoundFunction>(rhs_function)) {
2114
0
        auto const& bound_target = static_cast<BoundFunction const&>(rhs_function);
2115
2116
        // a. Let BC be C.[[BoundTargetFunction]].
2117
        // b. Return ? InstanceofOperator(O, BC).
2118
0
        return instance_of(vm, lhs, Value(&bound_target.bound_target_function()));
2119
0
    }
2120
2121
    // 3. If O is not an Object, return false.
2122
0
    if (!lhs.is_object())
2123
0
        return Value(false);
2124
2125
0
    auto* lhs_object = &lhs.as_object();
2126
2127
    // 4. Let P be ? Get(C, "prototype").
2128
0
    auto rhs_prototype = TRY(rhs_function.get(vm.names.prototype));
2129
2130
    // 5. If P is not an Object, throw a TypeError exception.
2131
0
    if (!rhs_prototype.is_object())
2132
0
        return vm.throw_completion<TypeError>(ErrorType::InstanceOfOperatorBadPrototype, rhs.to_string_without_side_effects());
2133
2134
    // 6. Repeat,
2135
0
    while (true) {
2136
        // a. Set O to ? O.[[GetPrototypeOf]]().
2137
0
        lhs_object = TRY(lhs_object->internal_get_prototype_of());
2138
2139
        // b. If O is null, return false.
2140
0
        if (!lhs_object)
2141
0
            return Value(false);
2142
2143
        // c. If SameValue(P, O) is true, return true.
2144
0
        if (same_value(rhs_prototype, lhs_object))
2145
0
            return Value(true);
2146
0
    }
2147
0
}
2148
2149
// 7.2.10 SameValue ( x, y ), https://tc39.es/ecma262/#sec-samevalue
2150
bool same_value(Value lhs, Value rhs)
2151
0
{
2152
    // 1. If Type(x) is different from Type(y), return false.
2153
0
    if (!same_type_for_equality(lhs, rhs))
2154
0
        return false;
2155
2156
    // 2. If x is a Number, then
2157
0
    if (lhs.is_number()) {
2158
        // a. Return Number::sameValue(x, y).
2159
2160
        // 6.1.6.1.14 Number::sameValue ( x, y ), https://tc39.es/ecma262/#sec-numeric-types-number-sameValue
2161
        // 1. If x is NaN and y is NaN, return true.
2162
0
        if (lhs.is_nan() && rhs.is_nan())
2163
0
            return true;
2164
        // 2. If x is +0𝔽 and y is -0𝔽, return false.
2165
0
        if (lhs.is_positive_zero() && rhs.is_negative_zero())
2166
0
            return false;
2167
        // 3. If x is -0𝔽 and y is +0𝔽, return false.
2168
0
        if (lhs.is_negative_zero() && rhs.is_positive_zero())
2169
0
            return false;
2170
        // 4. If x is the same Number value as y, return true.
2171
        // 5. Return false.
2172
0
        return lhs.as_double() == rhs.as_double();
2173
0
    }
2174
2175
    // 3. Return SameValueNonNumber(x, y).
2176
0
    return same_value_non_number(lhs, rhs);
2177
0
}
2178
2179
// 7.2.11 SameValueZero ( x, y ), https://tc39.es/ecma262/#sec-samevaluezero
2180
bool same_value_zero(Value lhs, Value rhs)
2181
0
{
2182
    // 1. If Type(x) is different from Type(y), return false.
2183
0
    if (!same_type_for_equality(lhs, rhs))
2184
0
        return false;
2185
2186
    // 2. If x is a Number, then
2187
0
    if (lhs.is_number()) {
2188
        // a. Return Number::sameValueZero(x, y).
2189
0
        if (lhs.is_nan() && rhs.is_nan())
2190
0
            return true;
2191
0
        return lhs.as_double() == rhs.as_double();
2192
0
    }
2193
2194
    // 3. Return SameValueNonNumber(x, y).
2195
0
    return same_value_non_number(lhs, rhs);
2196
0
}
2197
2198
// 7.2.12 SameValueNonNumber ( x, y ), https://tc39.es/ecma262/#sec-samevaluenonnumeric
2199
bool same_value_non_number(Value lhs, Value rhs)
2200
0
{
2201
    // 1. Assert: Type(x) is the same as Type(y).
2202
0
    VERIFY(same_type_for_equality(lhs, rhs));
2203
0
    VERIFY(!lhs.is_number());
2204
2205
    // 2. If x is a BigInt, then
2206
0
    if (lhs.is_bigint()) {
2207
        // a. Return BigInt::equal(x, y).
2208
2209
        // 6.1.6.2.13 BigInt::equal ( x, y ), https://tc39.es/ecma262/#sec-numeric-types-bigint-equal
2210
        // 1. If ℝ(x) = ℝ(y), return true; otherwise return false.
2211
0
        return lhs.as_bigint().big_integer() == rhs.as_bigint().big_integer();
2212
0
    }
2213
2214
    // 5. If x is a String, then
2215
0
    if (lhs.is_string()) {
2216
        // a. If x and y are exactly the same sequence of code units (same length and same code units at corresponding indices), return true; otherwise, return false.
2217
0
        return lhs.as_string().byte_string() == rhs.as_string().byte_string();
2218
0
    }
2219
2220
    // 3. If x is undefined, return true.
2221
    // 4. If x is null, return true.
2222
    // 6. If x is a Boolean, then
2223
    //    a. If x and y are both true or both false, return true; otherwise, return false.
2224
    // 7. If x is a Symbol, then
2225
    //    a. If x and y are both the same Symbol value, return true; otherwise, return false.
2226
    // 8. If x and y are the same Object value, return true. Otherwise, return false.
2227
    // NOTE: All the options above will have the exact same bit representation in Value, so we can directly compare the bits.
2228
0
    return lhs.m_value.encoded == rhs.m_value.encoded;
2229
0
}
2230
2231
// 7.2.15 IsStrictlyEqual ( x, y ), https://tc39.es/ecma262/#sec-isstrictlyequal
2232
bool is_strictly_equal(Value lhs, Value rhs)
2233
0
{
2234
    // 1. If Type(x) is different from Type(y), return false.
2235
0
    if (!same_type_for_equality(lhs, rhs))
2236
0
        return false;
2237
2238
    // 2. If x is a Number, then
2239
0
    if (lhs.is_number()) {
2240
        // a. Return Number::equal(x, y).
2241
2242
        // 6.1.6.1.13 Number::equal ( x, y ), https://tc39.es/ecma262/#sec-numeric-types-number-equal
2243
        // 1. If x is NaN, return false.
2244
        // 2. If y is NaN, return false.
2245
0
        if (lhs.is_nan() || rhs.is_nan())
2246
0
            return false;
2247
        // 3. If x is the same Number value as y, return true.
2248
        // 4. If x is +0𝔽 and y is -0𝔽, return true.
2249
        // 5. If x is -0𝔽 and y is +0𝔽, return true.
2250
0
        if (lhs.as_double() == rhs.as_double())
2251
0
            return true;
2252
        // 6. Return false.
2253
0
        return false;
2254
0
    }
2255
2256
    // 3. Return SameValueNonNumber(x, y).
2257
0
    return same_value_non_number(lhs, rhs);
2258
0
}
2259
2260
// 7.2.14 IsLooselyEqual ( x, y ), https://tc39.es/ecma262/#sec-islooselyequal
2261
ThrowCompletionOr<bool> is_loosely_equal(VM& vm, Value lhs, Value rhs)
2262
0
{
2263
    // 1. If Type(x) is the same as Type(y), then
2264
0
    if (same_type_for_equality(lhs, rhs)) {
2265
        // a. Return IsStrictlyEqual(x, y).
2266
0
        return is_strictly_equal(lhs, rhs);
2267
0
    }
2268
2269
    // 2. If x is null and y is undefined, return true.
2270
    // 3. If x is undefined and y is null, return true.
2271
0
    if (lhs.is_nullish() && rhs.is_nullish())
2272
0
        return true;
2273
2274
    // 4. NOTE: This step is replaced in section B.3.6.2.
2275
    // B.3.6.2 Changes to IsLooselyEqual, https://tc39.es/ecma262/#sec-IsHTMLDDA-internal-slot-aec
2276
    // 4. Perform the following steps:
2277
    // a. If Type(x) is Object and x has an [[IsHTMLDDA]] internal slot and y is either null or undefined, return true.
2278
0
    if (lhs.is_object() && lhs.as_object().is_htmldda() && rhs.is_nullish())
2279
0
        return true;
2280
2281
    // b. If x is either null or undefined and Type(y) is Object and y has an [[IsHTMLDDA]] internal slot, return true.
2282
0
    if (lhs.is_nullish() && rhs.is_object() && rhs.as_object().is_htmldda())
2283
0
        return true;
2284
2285
    // == End of B.3.6.2 ==
2286
2287
    // 5. If Type(x) is Number and Type(y) is String, return ! IsLooselyEqual(x, ! ToNumber(y)).
2288
0
    if (lhs.is_number() && rhs.is_string())
2289
0
        return is_loosely_equal(vm, lhs, MUST(rhs.to_number(vm)));
2290
2291
    // 6. If Type(x) is String and Type(y) is Number, return ! IsLooselyEqual(! ToNumber(x), y).
2292
0
    if (lhs.is_string() && rhs.is_number())
2293
0
        return is_loosely_equal(vm, MUST(lhs.to_number(vm)), rhs);
2294
2295
    // 7. If Type(x) is BigInt and Type(y) is String, then
2296
0
    if (lhs.is_bigint() && rhs.is_string()) {
2297
        // a. Let n be StringToBigInt(y).
2298
0
        auto bigint = string_to_bigint(vm, rhs.as_string().byte_string());
2299
2300
        // b. If n is undefined, return false.
2301
0
        if (!bigint.has_value())
2302
0
            return false;
2303
2304
        // c. Return ! IsLooselyEqual(x, n).
2305
0
        return is_loosely_equal(vm, lhs, *bigint);
2306
0
    }
2307
2308
    // 8. If Type(x) is String and Type(y) is BigInt, return ! IsLooselyEqual(y, x).
2309
0
    if (lhs.is_string() && rhs.is_bigint())
2310
0
        return is_loosely_equal(vm, rhs, lhs);
2311
2312
    // 9. If Type(x) is Boolean, return ! IsLooselyEqual(! ToNumber(x), y).
2313
0
    if (lhs.is_boolean())
2314
0
        return is_loosely_equal(vm, MUST(lhs.to_number(vm)), rhs);
2315
2316
    // 10. If Type(y) is Boolean, return ! IsLooselyEqual(x, ! ToNumber(y)).
2317
0
    if (rhs.is_boolean())
2318
0
        return is_loosely_equal(vm, lhs, MUST(rhs.to_number(vm)));
2319
2320
    // 11. If Type(x) is either String, Number, BigInt, or Symbol and Type(y) is Object, return ! IsLooselyEqual(x, ? ToPrimitive(y)).
2321
0
    if ((lhs.is_string() || lhs.is_number() || lhs.is_bigint() || lhs.is_symbol()) && rhs.is_object()) {
2322
0
        auto rhs_primitive = TRY(rhs.to_primitive(vm));
2323
0
        return is_loosely_equal(vm, lhs, rhs_primitive);
2324
0
    }
2325
2326
    // 12. If Type(x) is Object and Type(y) is either String, Number, BigInt, or Symbol, return ! IsLooselyEqual(? ToPrimitive(x), y).
2327
0
    if (lhs.is_object() && (rhs.is_string() || rhs.is_number() || rhs.is_bigint() || rhs.is_symbol())) {
2328
0
        auto lhs_primitive = TRY(lhs.to_primitive(vm));
2329
0
        return is_loosely_equal(vm, lhs_primitive, rhs);
2330
0
    }
2331
2332
    // 13. If Type(x) is BigInt and Type(y) is Number, or if Type(x) is Number and Type(y) is BigInt, then
2333
0
    if ((lhs.is_bigint() && rhs.is_number()) || (lhs.is_number() && rhs.is_bigint())) {
2334
        // a. If x or y are any of NaN, +∞𝔽, or -∞𝔽, return false.
2335
0
        if (lhs.is_nan() || lhs.is_infinity() || rhs.is_nan() || rhs.is_infinity())
2336
0
            return false;
2337
2338
        // b. If ℝ(x) = ℝ(y), return true; otherwise return false.
2339
0
        if ((lhs.is_number() && !lhs.is_integral_number()) || (rhs.is_number() && !rhs.is_integral_number()))
2340
0
            return false;
2341
2342
0
        VERIFY(!lhs.is_nan() && !rhs.is_nan());
2343
2344
0
        auto& number_side = lhs.is_number() ? lhs : rhs;
2345
0
        auto& bigint_side = lhs.is_number() ? rhs : lhs;
2346
2347
0
        return bigint_side.as_bigint().big_integer().compare_to_double(number_side.as_double()) == Crypto::UnsignedBigInteger::CompareResult::DoubleEqualsBigInt;
2348
0
    }
2349
2350
    // 14. Return false.
2351
0
    return false;
2352
0
}
2353
2354
// 7.2.13 IsLessThan ( x, y, LeftFirst ), https://tc39.es/ecma262/#sec-islessthan
2355
ThrowCompletionOr<TriState> is_less_than(VM& vm, Value lhs, Value rhs, bool left_first)
2356
0
{
2357
0
    Value x_primitive;
2358
0
    Value y_primitive;
2359
2360
    // 1. If the LeftFirst flag is true, then
2361
0
    if (left_first) {
2362
        // a. Let px be ? ToPrimitive(x, number).
2363
0
        x_primitive = TRY(lhs.to_primitive(vm, Value::PreferredType::Number));
2364
2365
        // b. Let py be ? ToPrimitive(y, number).
2366
0
        y_primitive = TRY(rhs.to_primitive(vm, Value::PreferredType::Number));
2367
0
    } else {
2368
        // a. NOTE: The order of evaluation needs to be reversed to preserve left to right evaluation.
2369
2370
        // b. Let py be ? ToPrimitive(y, number).
2371
0
        y_primitive = TRY(lhs.to_primitive(vm, Value::PreferredType::Number));
2372
2373
        // c. Let px be ? ToPrimitive(x, number).
2374
0
        x_primitive = TRY(rhs.to_primitive(vm, Value::PreferredType::Number));
2375
0
    }
2376
2377
    // 3. If px is a String and py is a String, then
2378
0
    if (x_primitive.is_string() && y_primitive.is_string()) {
2379
0
        auto x_string = x_primitive.as_string().byte_string();
2380
0
        auto y_string = y_primitive.as_string().byte_string();
2381
2382
0
        Utf8View x_code_points { x_string };
2383
0
        Utf8View y_code_points { y_string };
2384
2385
        // a. Let lx be the length of px.
2386
        // b. Let ly be the length of py.
2387
        // c. For each integer i such that 0 ≤ i < min(lx, ly), in ascending order, do
2388
0
        for (auto k = x_code_points.begin(), l = y_code_points.begin();
2389
0
            k != x_code_points.end() && l != y_code_points.end();
2390
0
            ++k, ++l) {
2391
            // i. Let cx be the integer that is the numeric value of the code unit at index i within px.
2392
            // ii. Let cy be the integer that is the numeric value of the code unit at index i within py.
2393
0
            if (*k != *l) {
2394
                // iii. If cx < cy, return true.
2395
0
                if (*k < *l) {
2396
0
                    return TriState::True;
2397
0
                }
2398
                // iv. If cx > cy, return false.
2399
0
                else {
2400
0
                    return TriState::False;
2401
0
                }
2402
0
            }
2403
0
        }
2404
2405
        // d. If lx < ly, return true. Otherwise, return false.
2406
0
        return x_code_points.length() < y_code_points.length()
2407
0
            ? TriState::True
2408
0
            : TriState::False;
2409
0
    }
2410
2411
    // 4. Else,
2412
    // a. If px is a BigInt and py is a String, then
2413
0
    if (x_primitive.is_bigint() && y_primitive.is_string()) {
2414
        // i. Let ny be StringToBigInt(py).
2415
0
        auto y_bigint = string_to_bigint(vm, y_primitive.as_string().byte_string());
2416
2417
        // ii. If ny is undefined, return undefined.
2418
0
        if (!y_bigint.has_value())
2419
0
            return TriState::Unknown;
2420
2421
        // iii. Return BigInt::lessThan(px, ny).
2422
0
        if (x_primitive.as_bigint().big_integer() < (*y_bigint)->big_integer())
2423
0
            return TriState::True;
2424
0
        return TriState::False;
2425
0
    }
2426
2427
    // b. If px is a String and py is a BigInt, then
2428
0
    if (x_primitive.is_string() && y_primitive.is_bigint()) {
2429
        // i. Let nx be StringToBigInt(px).
2430
0
        auto x_bigint = string_to_bigint(vm, x_primitive.as_string().byte_string());
2431
2432
        // ii. If nx is undefined, return undefined.
2433
0
        if (!x_bigint.has_value())
2434
0
            return TriState::Unknown;
2435
2436
        // iii. Return BigInt::lessThan(nx, py).
2437
0
        if ((*x_bigint)->big_integer() < y_primitive.as_bigint().big_integer())
2438
0
            return TriState::True;
2439
0
        return TriState::False;
2440
0
    }
2441
2442
    // c. NOTE: Because px and py are primitive values, evaluation order is not important.
2443
2444
    // d. Let nx be ? ToNumeric(px).
2445
0
    auto x_numeric = TRY(x_primitive.to_numeric(vm));
2446
2447
    // e. Let ny be ? ToNumeric(py).
2448
0
    auto y_numeric = TRY(y_primitive.to_numeric(vm));
2449
2450
    // h. If nx or ny is NaN, return undefined.
2451
0
    if (x_numeric.is_nan() || y_numeric.is_nan())
2452
0
        return TriState::Unknown;
2453
2454
    // i. If nx is -∞𝔽 or ny is +∞𝔽, return true.
2455
0
    if (x_numeric.is_positive_infinity() || y_numeric.is_negative_infinity())
2456
0
        return TriState::False;
2457
2458
    // j. If nx is +∞𝔽 or ny is -∞𝔽, return false.
2459
0
    if (x_numeric.is_negative_infinity() || y_numeric.is_positive_infinity())
2460
0
        return TriState::True;
2461
2462
    // f. If Type(nx) is the same as Type(ny), then
2463
2464
    // i. If nx is a Number, then
2465
0
    if (x_numeric.is_number() && y_numeric.is_number()) {
2466
        // 1. Return Number::lessThan(nx, ny).
2467
0
        if (x_numeric.as_double() < y_numeric.as_double())
2468
0
            return TriState::True;
2469
0
        else
2470
0
            return TriState::False;
2471
0
    }
2472
    // ii. Else,
2473
0
    if (x_numeric.is_bigint() && y_numeric.is_bigint()) {
2474
        // 1. Assert: nx is a BigInt.
2475
        // 2. Return BigInt::lessThan(nx, ny).
2476
0
        if (x_numeric.as_bigint().big_integer() < y_numeric.as_bigint().big_integer())
2477
0
            return TriState::True;
2478
0
        else
2479
0
            return TriState::False;
2480
0
    }
2481
2482
    // g. Assert: nx is a BigInt and ny is a Number, or nx is a Number and ny is a BigInt.
2483
0
    VERIFY((x_numeric.is_number() && y_numeric.is_bigint()) || (x_numeric.is_bigint() && y_numeric.is_number()));
2484
2485
    // k. If ℝ(nx) < ℝ(ny), return true; otherwise return false.
2486
0
    bool x_lower_than_y;
2487
0
    VERIFY(!x_numeric.is_nan() && !y_numeric.is_nan());
2488
0
    if (x_numeric.is_number()) {
2489
0
        x_lower_than_y = y_numeric.as_bigint().big_integer().compare_to_double(x_numeric.as_double())
2490
0
            == Crypto::UnsignedBigInteger::CompareResult::DoubleLessThanBigInt;
2491
0
    } else {
2492
0
        x_lower_than_y = x_numeric.as_bigint().big_integer().compare_to_double(y_numeric.as_double())
2493
0
            == Crypto::UnsignedBigInteger::CompareResult::DoubleGreaterThanBigInt;
2494
0
    }
2495
0
    if (x_lower_than_y)
2496
0
        return TriState::True;
2497
0
    else
2498
0
        return TriState::False;
2499
0
}
2500
2501
// 7.3.21 Invoke ( V, P [ , argumentsList ] ), https://tc39.es/ecma262/#sec-invoke
2502
ThrowCompletionOr<Value> Value::invoke_internal(VM& vm, PropertyKey const& property_key, Optional<MarkedVector<Value>> arguments)
2503
0
{
2504
    // 1. If argumentsList is not present, set argumentsList to a new empty List.
2505
2506
    // 2. Let func be ? GetV(V, P).
2507
0
    auto function = TRY(get(vm, property_key));
2508
2509
    // 3. Return ? Call(func, V, argumentsList).
2510
0
    ReadonlySpan<Value> argument_list;
2511
0
    if (arguments.has_value())
2512
0
        argument_list = arguments.value().span();
2513
0
    return call(vm, function, *this, argument_list);
2514
0
}
2515
2516
}