| 
									
										
										
										
											2020-03-07 19:42:11 +01:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * Copyright (c) 2020, Andreas Kling <kling@serenityos.org> | 
					
						
							| 
									
										
										
										
											2021-03-02 19:22:36 +01:00
										 |  |  |  * Copyright (c) 2020-2021, Linus Groh <mail@linusgroh.de> | 
					
						
							| 
									
										
										
										
											2020-03-07 19:42:11 +01:00
										 |  |  |  * All rights reserved. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Redistribution and use in source and binary forms, with or without | 
					
						
							|  |  |  |  * modification, are permitted provided that the following conditions are met: | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * 1. Redistributions of source code must retain the above copyright notice, this | 
					
						
							|  |  |  |  *    list of conditions and the following disclaimer. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * 2. Redistributions in binary form must reproduce the above copyright notice, | 
					
						
							|  |  |  |  *    this list of conditions and the following disclaimer in the documentation | 
					
						
							|  |  |  |  *    and/or other materials provided with the distribution. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | 
					
						
							|  |  |  |  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | 
					
						
							|  |  |  |  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | 
					
						
							|  |  |  |  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE | 
					
						
							|  |  |  |  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | 
					
						
							|  |  |  |  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR | 
					
						
							|  |  |  |  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER | 
					
						
							|  |  |  |  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, | 
					
						
							|  |  |  |  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 
					
						
							|  |  |  |  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-17 11:18:51 +01:00
										 |  |  | #include <AK/AllOf.h>
 | 
					
						
							| 
									
										
										
										
											2020-03-28 16:56:54 +01:00
										 |  |  | #include <AK/FlyString.h>
 | 
					
						
							| 
									
										
										
										
											2020-03-07 19:42:11 +01:00
										 |  |  | #include <AK/String.h>
 | 
					
						
							| 
									
										
										
										
											2020-05-15 13:39:24 +02:00
										 |  |  | #include <AK/StringBuilder.h>
 | 
					
						
							| 
									
										
										
										
											2020-05-28 17:19:59 +02:00
										 |  |  | #include <AK/Utf8View.h>
 | 
					
						
							| 
									
										
										
										
											2020-06-06 01:14:10 +01:00
										 |  |  | #include <LibCrypto/BigInt/SignedBigInteger.h>
 | 
					
						
							|  |  |  | #include <LibCrypto/NumberTheory/ModularFunctions.h>
 | 
					
						
							| 
									
										
										
										
											2020-03-16 14:20:30 +01:00
										 |  |  | #include <LibJS/Heap/Heap.h>
 | 
					
						
							| 
									
										
										
										
											2020-05-21 11:14:23 -07:00
										 |  |  | #include <LibJS/Runtime/Accessor.h>
 | 
					
						
							| 
									
										
										
										
											2020-03-29 15:20:09 +01:00
										 |  |  | #include <LibJS/Runtime/Array.h>
 | 
					
						
							| 
									
										
										
										
											2020-06-06 01:14:10 +01:00
										 |  |  | #include <LibJS/Runtime/BigInt.h>
 | 
					
						
							|  |  |  | #include <LibJS/Runtime/BigIntObject.h>
 | 
					
						
							| 
									
										
										
										
											2020-04-06 22:51:16 -05:00
										 |  |  | #include <LibJS/Runtime/BooleanObject.h>
 | 
					
						
							| 
									
										
										
										
											2020-07-11 15:27:28 -07:00
										 |  |  | #include <LibJS/Runtime/BoundFunction.h>
 | 
					
						
							| 
									
										
										
										
											2020-03-28 22:48:35 +01:00
										 |  |  | #include <LibJS/Runtime/Error.h>
 | 
					
						
							| 
									
										
										
										
											2020-05-06 11:52:53 +01:00
										 |  |  | #include <LibJS/Runtime/Function.h>
 | 
					
						
							| 
									
										
										
										
											2020-09-27 17:24:14 +02:00
										 |  |  | #include <LibJS/Runtime/GlobalObject.h>
 | 
					
						
							| 
									
										
										
										
											2020-04-04 23:13:13 +02:00
										 |  |  | #include <LibJS/Runtime/NumberObject.h>
 | 
					
						
							| 
									
										
										
										
											2020-03-16 14:20:30 +01:00
										 |  |  | #include <LibJS/Runtime/Object.h>
 | 
					
						
							|  |  |  | #include <LibJS/Runtime/PrimitiveString.h>
 | 
					
						
							| 
									
										
										
										
											2021-01-01 17:46:39 +01:00
										 |  |  | #include <LibJS/Runtime/RegExpObject.h>
 | 
					
						
							| 
									
										
										
										
											2020-03-16 14:20:30 +01:00
										 |  |  | #include <LibJS/Runtime/StringObject.h>
 | 
					
						
							| 
									
										
										
										
											2020-05-18 00:28:00 +01:00
										 |  |  | #include <LibJS/Runtime/Symbol.h>
 | 
					
						
							| 
									
										
										
										
											2020-04-29 23:25:21 -07:00
										 |  |  | #include <LibJS/Runtime/SymbolObject.h>
 | 
					
						
							| 
									
										
										
										
											2020-03-16 14:20:30 +01:00
										 |  |  | #include <LibJS/Runtime/Value.h>
 | 
					
						
							| 
									
										
										
										
											2020-06-06 01:14:10 +01:00
										 |  |  | #include <ctype.h>
 | 
					
						
							| 
									
										
										
										
											2020-04-05 13:40:00 +01:00
										 |  |  | #include <math.h>
 | 
					
						
							| 
									
										
										
										
											2020-03-07 19:42:11 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | namespace JS { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-02 13:23:51 +00:00
										 |  |  | // Used in various abstract operations to make it obvious when a non-optional return value must be discarded.
 | 
					
						
							|  |  |  | static const double INVALID { 0 }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-21 18:03:00 +01:00
										 |  |  | static inline bool same_type_for_equality(const Value& lhs, const Value& rhs) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (lhs.type() == rhs.type()) | 
					
						
							|  |  |  |         return true; | 
					
						
							|  |  |  |     if (lhs.is_number() && rhs.is_number()) | 
					
						
							|  |  |  |         return true; | 
					
						
							|  |  |  |     return false; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-06 01:14:10 +01:00
										 |  |  | static const Crypto::SignedBigInteger BIGINT_ZERO { 0 }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-17 11:18:51 +01:00
										 |  |  | static bool is_valid_bigint_value(StringView string) | 
					
						
							| 
									
										
										
										
											2020-06-06 01:14:10 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     string = string.trim_whitespace(); | 
					
						
							|  |  |  |     if (string.length() > 1 && (string[0] == '-' || string[0] == '+')) | 
					
						
							|  |  |  |         string = string.substring_view(1, string.length() - 1); | 
					
						
							| 
									
										
										
										
											2021-02-17 11:18:51 +01:00
										 |  |  |     return all_of(string.begin(), string.end(), [](auto ch) { return isdigit(ch); }); | 
					
						
							| 
									
										
										
										
											2020-06-06 01:14:10 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ALWAYS_INLINE bool both_number(const Value& lhs, const Value& rhs) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return lhs.is_number() && rhs.is_number(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ALWAYS_INLINE bool both_bigint(const Value& lhs, const Value& rhs) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return lhs.is_bigint() && rhs.is_bigint(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-26 11:30:14 +01:00
										 |  |  | static String double_to_string(double d) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     // https://tc39.es/ecma262/#sec-numeric-types-number-tostring
 | 
					
						
							|  |  |  |     if (isnan(d)) | 
					
						
							|  |  |  |         return "NaN"; | 
					
						
							|  |  |  |     if (d == +0.0 || d == -0.0) | 
					
						
							|  |  |  |         return "0"; | 
					
						
							|  |  |  |     if (d < +0.0) { | 
					
						
							|  |  |  |         StringBuilder builder; | 
					
						
							|  |  |  |         builder.append('-'); | 
					
						
							|  |  |  |         builder.append(double_to_string(-d)); | 
					
						
							|  |  |  |         return builder.to_string(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (d == INFINITY) | 
					
						
							|  |  |  |         return "Infinity"; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     StringBuilder number_string_builder; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     size_t start_index = 0; | 
					
						
							|  |  |  |     size_t end_index = 0; | 
					
						
							| 
									
										
										
										
											2021-02-01 20:29:11 +01:00
										 |  |  |     size_t int_part_end = 0; | 
					
						
							| 
									
										
										
										
											2020-12-26 11:30:14 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     // generate integer part (reversed)
 | 
					
						
							| 
									
										
										
										
											2021-02-01 20:29:11 +01:00
										 |  |  |     double int_part; | 
					
						
							| 
									
										
										
										
											2020-12-26 11:30:14 +01:00
										 |  |  |     double frac_part; | 
					
						
							| 
									
										
										
										
											2021-02-01 20:29:11 +01:00
										 |  |  |     frac_part = modf(d, &int_part); | 
					
						
							|  |  |  |     while (int_part > 0) { | 
					
						
							|  |  |  |         number_string_builder.append('0' + (int)fmod(int_part, 10)); | 
					
						
							| 
									
										
										
										
											2020-12-26 11:30:14 +01:00
										 |  |  |         end_index++; | 
					
						
							| 
									
										
										
										
											2021-02-01 20:29:11 +01:00
										 |  |  |         int_part = floor(int_part / 10); | 
					
						
							| 
									
										
										
										
											2020-12-26 11:30:14 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     auto reversed_integer_part = number_string_builder.to_string().reverse(); | 
					
						
							|  |  |  |     number_string_builder.clear(); | 
					
						
							|  |  |  |     number_string_builder.append(reversed_integer_part); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-01 20:29:11 +01:00
										 |  |  |     int_part_end = end_index; | 
					
						
							| 
									
										
										
										
											2020-12-26 11:30:14 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     int exponent = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // generate fractional part
 | 
					
						
							|  |  |  |     while (frac_part > 0) { | 
					
						
							|  |  |  |         double old_frac_part = frac_part; | 
					
						
							|  |  |  |         frac_part *= 10; | 
					
						
							| 
									
										
										
										
											2021-02-01 20:29:11 +01:00
										 |  |  |         frac_part = modf(frac_part, &int_part); | 
					
						
							| 
									
										
										
										
											2020-12-26 11:30:14 +01:00
										 |  |  |         if (old_frac_part == frac_part) | 
					
						
							|  |  |  |             break; | 
					
						
							| 
									
										
										
										
											2021-02-01 20:29:11 +01:00
										 |  |  |         number_string_builder.append('0' + (int)int_part); | 
					
						
							| 
									
										
										
										
											2020-12-26 11:30:14 +01:00
										 |  |  |         end_index++; | 
					
						
							|  |  |  |         exponent--; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     auto number_string = number_string_builder.to_string(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-27 01:27:10 +01:00
										 |  |  |     // FIXME: Remove this hack.
 | 
					
						
							|  |  |  |     // FIXME: Instead find the shortest round-trippable representation.
 | 
					
						
							|  |  |  |     // Remove decimals after the 15th position
 | 
					
						
							| 
									
										
										
										
											2021-02-01 20:29:11 +01:00
										 |  |  |     if (end_index > int_part_end + 15) { | 
					
						
							|  |  |  |         exponent += end_index - int_part_end - 15; | 
					
						
							|  |  |  |         end_index = int_part_end + 15; | 
					
						
							| 
									
										
										
										
											2020-12-26 11:30:14 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // remove leading zeroes
 | 
					
						
							|  |  |  |     while (start_index < end_index && number_string[start_index] == '0') { | 
					
						
							|  |  |  |         start_index++; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // remove trailing zeroes
 | 
					
						
							|  |  |  |     while (end_index > 0 && number_string[end_index - 1] == '0') { | 
					
						
							|  |  |  |         end_index--; | 
					
						
							|  |  |  |         exponent++; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (end_index <= start_index) | 
					
						
							|  |  |  |         return "0"; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     auto digits = number_string.substring_view(start_index, end_index - start_index); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     int number_of_digits = end_index - start_index; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     exponent += number_of_digits; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     StringBuilder builder; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (number_of_digits <= exponent && exponent <= 21) { | 
					
						
							|  |  |  |         builder.append(digits); | 
					
						
							|  |  |  |         builder.append(String::repeated('0', exponent - number_of_digits)); | 
					
						
							|  |  |  |         return builder.to_string(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (0 < exponent && exponent <= 21) { | 
					
						
							|  |  |  |         builder.append(digits.substring_view(0, exponent)); | 
					
						
							|  |  |  |         builder.append('.'); | 
					
						
							|  |  |  |         builder.append(digits.substring_view(exponent)); | 
					
						
							|  |  |  |         return builder.to_string(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (-6 < exponent && exponent <= 0) { | 
					
						
							|  |  |  |         builder.append("0."); | 
					
						
							|  |  |  |         builder.append(String::repeated('0', -exponent)); | 
					
						
							|  |  |  |         builder.append(digits); | 
					
						
							|  |  |  |         return builder.to_string(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (number_of_digits == 1) { | 
					
						
							|  |  |  |         builder.append(digits); | 
					
						
							|  |  |  |         builder.append('e'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (exponent - 1 > 0) | 
					
						
							|  |  |  |             builder.append('+'); | 
					
						
							|  |  |  |         else | 
					
						
							|  |  |  |             builder.append('-'); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-15 11:51:08 +01:00
										 |  |  |         builder.append(String::number(fabs(exponent - 1))); | 
					
						
							| 
									
										
										
										
											2020-12-26 11:30:14 +01:00
										 |  |  |         return builder.to_string(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     builder.append(digits[0]); | 
					
						
							|  |  |  |     builder.append('.'); | 
					
						
							|  |  |  |     builder.append(digits.substring_view(1)); | 
					
						
							|  |  |  |     builder.append('e'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (exponent - 1 > 0) | 
					
						
							|  |  |  |         builder.append('+'); | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |         builder.append('-'); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-15 11:51:08 +01:00
										 |  |  |     builder.append(String::number(fabs(exponent - 1))); | 
					
						
							| 
									
										
										
										
											2020-12-26 11:30:14 +01:00
										 |  |  |     return builder.to_string(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-26 12:02:18 +01:00
										 |  |  | bool Value::is_array() const | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2020-04-01 22:18:47 +02:00
										 |  |  |     return is_object() && as_object().is_array(); | 
					
						
							| 
									
										
										
										
											2020-03-26 12:02:18 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-10 11:01:00 -07:00
										 |  |  | Array& Value::as_array() | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2021-02-23 20:42:32 +01:00
										 |  |  |     VERIFY(is_array()); | 
					
						
							| 
									
										
										
										
											2020-06-10 11:01:00 -07:00
										 |  |  |     return static_cast<Array&>(*m_value.as_object); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-06 11:52:53 +01:00
										 |  |  | bool Value::is_function() const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return is_object() && as_object().is_function(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Function& Value::as_function() | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2021-02-23 20:42:32 +01:00
										 |  |  |     VERIFY(is_function()); | 
					
						
							| 
									
										
										
										
											2020-05-06 11:52:53 +01:00
										 |  |  |     return static_cast<Function&>(as_object()); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-25 12:52:19 +11:00
										 |  |  | bool Value::is_regexp(GlobalObject& global_object) const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     // 7.2.8 IsRegExp, https://tc39.es/ecma262/#sec-isregexp
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!is_object()) | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     auto matcher = as_object().get(global_object.vm().well_known_symbol_match()); | 
					
						
							|  |  |  |     if (global_object.vm().exception()) | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  |     if (!matcher.is_empty() && !matcher.is_undefined()) | 
					
						
							|  |  |  |         return matcher.to_boolean(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-01 17:46:39 +01:00
										 |  |  |     return is<RegExpObject>(as_object()); | 
					
						
							| 
									
										
										
										
											2020-12-25 12:52:19 +11:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-15 13:39:24 +02:00
										 |  |  | String Value::to_string_without_side_effects() const | 
					
						
							| 
									
										
										
										
											2020-03-07 19:42:11 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2020-06-04 21:36:52 +01:00
										 |  |  |     switch (m_type) { | 
					
						
							|  |  |  |     case Type::Undefined: | 
					
						
							| 
									
										
										
										
											2020-03-07 23:11:17 +01:00
										 |  |  |         return "undefined"; | 
					
						
							| 
									
										
										
										
											2020-06-04 21:36:52 +01:00
										 |  |  |     case Type::Null: | 
					
						
							|  |  |  |         return "null"; | 
					
						
							|  |  |  |     case Type::Boolean: | 
					
						
							|  |  |  |         return m_value.as_bool ? "true" : "false"; | 
					
						
							| 
									
										
										
										
											2021-03-21 18:03:00 +01:00
										 |  |  |     case Type::Int32: | 
					
						
							|  |  |  |         return String::number(m_value.as_i32); | 
					
						
							|  |  |  |     case Type::Double: | 
					
						
							| 
									
										
										
										
											2020-12-26 11:30:14 +01:00
										 |  |  |         return double_to_string(m_value.as_double); | 
					
						
							| 
									
										
										
										
											2020-06-04 21:36:52 +01:00
										 |  |  |     case Type::String: | 
					
						
							| 
									
										
										
										
											2020-05-15 13:39:24 +02:00
										 |  |  |         return m_value.as_string->string(); | 
					
						
							| 
									
										
										
										
											2020-06-04 21:36:52 +01:00
										 |  |  |     case Type::Symbol: | 
					
						
							|  |  |  |         return m_value.as_symbol->to_string(); | 
					
						
							| 
									
										
										
										
											2020-06-06 01:14:10 +01:00
										 |  |  |     case Type::BigInt: | 
					
						
							|  |  |  |         return m_value.as_bigint->to_string(); | 
					
						
							| 
									
										
										
										
											2020-06-04 21:36:52 +01:00
										 |  |  |     case Type::Object: | 
					
						
							| 
									
										
										
										
											2020-10-04 15:18:12 +01:00
										 |  |  |         return String::formatted("[object {}]", as_object().class_name()); | 
					
						
							| 
									
										
										
										
											2020-06-04 21:36:52 +01:00
										 |  |  |     case Type::Accessor: | 
					
						
							| 
									
										
										
										
											2020-05-21 11:14:23 -07:00
										 |  |  |         return "<accessor>"; | 
					
						
							| 
									
										
										
										
											2020-06-25 22:22:57 +02:00
										 |  |  |     case Type::NativeProperty: | 
					
						
							|  |  |  |         return "<native-property>"; | 
					
						
							| 
									
										
										
										
											2020-06-04 21:36:52 +01:00
										 |  |  |     default: | 
					
						
							| 
									
										
										
										
											2021-02-23 20:42:32 +01:00
										 |  |  |         VERIFY_NOT_REACHED(); | 
					
						
							| 
									
										
										
										
											2020-06-04 21:36:52 +01:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2020-05-15 13:39:24 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-27 18:36:49 +02:00
										 |  |  | PrimitiveString* Value::to_primitive_string(GlobalObject& global_object) | 
					
						
							| 
									
										
										
										
											2020-05-15 13:39:24 +02:00
										 |  |  | { | 
					
						
							|  |  |  |     if (is_string()) | 
					
						
							|  |  |  |         return &as_string(); | 
					
						
							| 
									
										
										
										
											2020-09-27 18:36:49 +02:00
										 |  |  |     auto string = to_string(global_object); | 
					
						
							|  |  |  |     if (global_object.vm().exception()) | 
					
						
							| 
									
										
										
										
											2020-05-15 13:39:24 +02:00
										 |  |  |         return nullptr; | 
					
						
							| 
									
										
										
										
											2020-09-27 18:36:49 +02:00
										 |  |  |     return js_string(global_object.heap(), string); | 
					
						
							| 
									
										
										
										
											2020-05-15 13:39:24 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-11 09:44:46 +00:00
										 |  |  | String Value::to_string(GlobalObject& global_object, bool legacy_null_to_empty_string) const | 
					
						
							| 
									
										
										
										
											2020-05-15 13:39:24 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2020-06-04 21:36:52 +01:00
										 |  |  |     switch (m_type) { | 
					
						
							|  |  |  |     case Type::Undefined: | 
					
						
							| 
									
										
										
										
											2020-05-15 13:39:24 +02:00
										 |  |  |         return "undefined"; | 
					
						
							| 
									
										
										
										
											2020-06-04 21:36:52 +01:00
										 |  |  |     case Type::Null: | 
					
						
							| 
									
										
										
										
											2020-11-11 09:44:46 +00:00
										 |  |  |         return !legacy_null_to_empty_string ? "null" : String::empty(); | 
					
						
							| 
									
										
										
										
											2020-06-04 21:36:52 +01:00
										 |  |  |     case Type::Boolean: | 
					
						
							|  |  |  |         return m_value.as_bool ? "true" : "false"; | 
					
						
							| 
									
										
										
										
											2021-03-21 18:03:00 +01:00
										 |  |  |     case Type::Int32: | 
					
						
							|  |  |  |         return String::number(m_value.as_i32); | 
					
						
							|  |  |  |     case Type::Double: | 
					
						
							| 
									
										
										
										
											2020-12-26 11:30:14 +01:00
										 |  |  |         return double_to_string(m_value.as_double); | 
					
						
							| 
									
										
										
										
											2020-06-04 21:36:52 +01:00
										 |  |  |     case Type::String: | 
					
						
							|  |  |  |         return m_value.as_string->string(); | 
					
						
							|  |  |  |     case Type::Symbol: | 
					
						
							| 
									
										
										
										
											2020-09-27 18:36:49 +02:00
										 |  |  |         global_object.vm().throw_exception<TypeError>(global_object, ErrorType::Convert, "symbol", "string"); | 
					
						
							| 
									
										
										
										
											2020-04-29 23:25:21 -07:00
										 |  |  |         return {}; | 
					
						
							| 
									
										
										
										
											2020-06-06 01:14:10 +01:00
										 |  |  |     case Type::BigInt: | 
					
						
							|  |  |  |         return m_value.as_bigint->big_integer().to_base10(); | 
					
						
							| 
									
										
										
										
											2020-06-04 21:36:52 +01:00
										 |  |  |     case Type::Object: { | 
					
						
							| 
									
										
										
										
											2021-03-02 19:22:36 +01:00
										 |  |  |         auto primitive_value = to_primitive(global_object, PreferredType::String); | 
					
						
							| 
									
										
										
										
											2020-09-27 18:36:49 +02:00
										 |  |  |         if (global_object.vm().exception()) | 
					
						
							| 
									
										
										
										
											2020-04-29 16:29:26 +01:00
										 |  |  |             return {}; | 
					
						
							| 
									
										
										
										
											2020-09-27 18:36:49 +02:00
										 |  |  |         return primitive_value.to_string(global_object); | 
					
						
							| 
									
										
										
										
											2020-04-29 16:29:26 +01:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2020-06-04 21:36:52 +01:00
										 |  |  |     default: | 
					
						
							| 
									
										
										
										
											2021-02-23 20:42:32 +01:00
										 |  |  |         VERIFY_NOT_REACHED(); | 
					
						
							| 
									
										
										
										
											2020-06-04 21:36:52 +01:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2020-03-07 19:42:11 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-10 08:46:20 +01:00
										 |  |  | bool Value::to_boolean() const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     switch (m_type) { | 
					
						
							| 
									
										
										
										
											2020-06-04 21:36:52 +01:00
										 |  |  |     case Type::Undefined: | 
					
						
							|  |  |  |     case Type::Null: | 
					
						
							|  |  |  |         return false; | 
					
						
							| 
									
										
										
										
											2020-03-10 08:46:20 +01:00
										 |  |  |     case Type::Boolean: | 
					
						
							|  |  |  |         return m_value.as_bool; | 
					
						
							| 
									
										
										
										
											2021-03-21 18:03:00 +01:00
										 |  |  |     case Type::Int32: | 
					
						
							|  |  |  |         return m_value.as_i32 != 0; | 
					
						
							|  |  |  |     case Type::Double: | 
					
						
							| 
									
										
										
										
											2020-06-04 21:36:52 +01:00
										 |  |  |         if (is_nan()) | 
					
						
							| 
									
										
										
										
											2020-04-06 22:48:47 -05:00
										 |  |  |             return false; | 
					
						
							| 
									
										
										
										
											2020-06-04 21:36:52 +01:00
										 |  |  |         return m_value.as_double != 0; | 
					
						
							| 
									
										
										
										
											2020-03-10 08:46:20 +01:00
										 |  |  |     case Type::String: | 
					
						
							| 
									
										
										
										
											2020-06-04 21:36:52 +01:00
										 |  |  |         return !m_value.as_string->string().is_empty(); | 
					
						
							| 
									
										
										
										
											2020-04-29 23:25:21 -07:00
										 |  |  |     case Type::Symbol: | 
					
						
							| 
									
										
										
										
											2020-06-06 01:14:10 +01:00
										 |  |  |         return true; | 
					
						
							|  |  |  |     case Type::BigInt: | 
					
						
							|  |  |  |         return m_value.as_bigint->big_integer() != BIGINT_ZERO; | 
					
						
							| 
									
										
										
										
											2020-06-04 21:36:52 +01:00
										 |  |  |     case Type::Object: | 
					
						
							| 
									
										
										
										
											2020-03-10 08:46:20 +01:00
										 |  |  |         return true; | 
					
						
							|  |  |  |     default: | 
					
						
							| 
									
										
										
										
											2021-02-23 20:42:32 +01:00
										 |  |  |         VERIFY_NOT_REACHED(); | 
					
						
							| 
									
										
										
										
											2020-03-10 08:46:20 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-02 19:22:36 +01:00
										 |  |  | Value Value::to_primitive(GlobalObject& global_object, PreferredType preferred_type) const | 
					
						
							| 
									
										
										
										
											2020-04-15 09:32:44 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2021-03-02 19:22:36 +01:00
										 |  |  |     auto get_hint_for_preferred_type = [&]() -> String { | 
					
						
							|  |  |  |         switch (preferred_type) { | 
					
						
							|  |  |  |         case PreferredType::Default: | 
					
						
							|  |  |  |             return "default"; | 
					
						
							|  |  |  |         case PreferredType::String: | 
					
						
							|  |  |  |             return "string"; | 
					
						
							|  |  |  |         case PreferredType::Number: | 
					
						
							|  |  |  |             return "number"; | 
					
						
							|  |  |  |         default: | 
					
						
							|  |  |  |             VERIFY_NOT_REACHED(); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     }; | 
					
						
							| 
									
										
										
										
											2020-11-03 19:52:21 +00:00
										 |  |  |     if (is_object()) { | 
					
						
							| 
									
										
										
										
											2021-03-02 19:22:36 +01:00
										 |  |  |         auto& vm = global_object.vm(); | 
					
						
							|  |  |  |         auto to_primitive_method = get_method(global_object, *this, vm.well_known_symbol_to_primitive()); | 
					
						
							|  |  |  |         if (vm.exception()) | 
					
						
							|  |  |  |             return {}; | 
					
						
							|  |  |  |         if (to_primitive_method) { | 
					
						
							|  |  |  |             auto hint = get_hint_for_preferred_type(); | 
					
						
							|  |  |  |             auto result = vm.call(*to_primitive_method, *this, js_string(vm, hint)); | 
					
						
							|  |  |  |             if (vm.exception()) | 
					
						
							|  |  |  |                 return {}; | 
					
						
							|  |  |  |             if (!result.is_object()) | 
					
						
							|  |  |  |                 return result; | 
					
						
							|  |  |  |             vm.throw_exception<TypeError>(global_object, ErrorType::ToPrimitiveReturnedObject, to_string_without_side_effects(), hint); | 
					
						
							|  |  |  |             return {}; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2020-11-03 19:52:21 +00:00
										 |  |  |         if (preferred_type == PreferredType::Default) | 
					
						
							|  |  |  |             preferred_type = PreferredType::Number; | 
					
						
							|  |  |  |         return as_object().ordinary_to_primitive(preferred_type); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2020-04-15 09:32:44 +02:00
										 |  |  |     return *this; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-27 18:36:49 +02:00
										 |  |  | Object* Value::to_object(GlobalObject& global_object) const | 
					
						
							| 
									
										
										
										
											2020-03-11 18:58:19 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2020-06-04 21:36:52 +01:00
										 |  |  |     switch (m_type) { | 
					
						
							|  |  |  |     case Type::Undefined: | 
					
						
							|  |  |  |     case Type::Null: | 
					
						
							| 
									
										
										
										
											2021-01-13 20:34:44 +01:00
										 |  |  |         global_object.vm().throw_exception<TypeError>(global_object, ErrorType::ToObjectNullOrUndefined); | 
					
						
							| 
									
										
										
										
											2020-03-28 22:48:35 +01:00
										 |  |  |         return nullptr; | 
					
						
							| 
									
										
										
										
											2020-06-04 21:36:52 +01:00
										 |  |  |     case Type::Boolean: | 
					
						
							| 
									
										
										
										
											2020-06-20 16:40:30 +02:00
										 |  |  |         return BooleanObject::create(global_object, m_value.as_bool); | 
					
						
							| 
									
										
										
										
											2021-03-21 18:03:00 +01:00
										 |  |  |     case Type::Int32: | 
					
						
							|  |  |  |     case Type::Double: | 
					
						
							|  |  |  |         return NumberObject::create(global_object, as_double()); | 
					
						
							| 
									
										
										
										
											2020-06-04 21:36:52 +01:00
										 |  |  |     case Type::String: | 
					
						
							| 
									
										
										
										
											2020-06-20 16:40:30 +02:00
										 |  |  |         return StringObject::create(global_object, *m_value.as_string); | 
					
						
							| 
									
										
										
										
											2020-06-04 21:36:52 +01:00
										 |  |  |     case Type::Symbol: | 
					
						
							| 
									
										
										
										
											2020-06-20 16:40:30 +02:00
										 |  |  |         return SymbolObject::create(global_object, *m_value.as_symbol); | 
					
						
							| 
									
										
										
										
											2020-06-06 01:14:10 +01:00
										 |  |  |     case Type::BigInt: | 
					
						
							| 
									
										
										
										
											2020-06-20 16:40:30 +02:00
										 |  |  |         return BigIntObject::create(global_object, *m_value.as_bigint); | 
					
						
							| 
									
										
										
										
											2020-06-04 21:36:52 +01:00
										 |  |  |     case Type::Object: | 
					
						
							|  |  |  |         return &const_cast<Object&>(as_object()); | 
					
						
							|  |  |  |     default: | 
					
						
							| 
									
										
										
										
											2020-12-06 16:55:19 +00:00
										 |  |  |         dbgln("Dying because I can't to_object() on {}", *this); | 
					
						
							| 
									
										
										
										
											2021-02-23 20:42:32 +01:00
										 |  |  |         VERIFY_NOT_REACHED(); | 
					
						
							| 
									
										
										
										
											2020-03-28 22:48:35 +01:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2020-03-11 18:58:19 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-21 18:13:29 +01:00
										 |  |  | FLATTEN Value Value::to_numeric(GlobalObject& global_object) const | 
					
						
							| 
									
										
										
										
											2020-06-06 01:14:10 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2021-03-02 19:22:36 +01:00
										 |  |  |     auto primitive = to_primitive(global_object, Value::PreferredType::Number); | 
					
						
							| 
									
										
										
										
											2020-09-27 18:36:49 +02:00
										 |  |  |     if (global_object.vm().exception()) | 
					
						
							| 
									
										
										
										
											2020-06-06 01:14:10 +01:00
										 |  |  |         return {}; | 
					
						
							|  |  |  |     if (primitive.is_bigint()) | 
					
						
							|  |  |  |         return primitive; | 
					
						
							| 
									
										
										
										
											2020-09-27 18:36:49 +02:00
										 |  |  |     return primitive.to_number(global_object); | 
					
						
							| 
									
										
										
										
											2020-06-06 01:14:10 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-27 18:36:49 +02:00
										 |  |  | Value Value::to_number(GlobalObject& global_object) const | 
					
						
							| 
									
										
										
										
											2020-03-15 15:00:18 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     switch (m_type) { | 
					
						
							| 
									
										
										
										
											2020-05-07 17:09:00 -07:00
										 |  |  |     case Type::Undefined: | 
					
						
							|  |  |  |         return js_nan(); | 
					
						
							|  |  |  |     case Type::Null: | 
					
						
							|  |  |  |         return Value(0); | 
					
						
							| 
									
										
										
										
											2020-03-15 15:00:18 +01:00
										 |  |  |     case Type::Boolean: | 
					
						
							| 
									
										
										
										
											2020-03-16 00:19:41 +02:00
										 |  |  |         return Value(m_value.as_bool ? 1 : 0); | 
					
						
							| 
									
										
										
										
											2021-03-21 18:03:00 +01:00
										 |  |  |     case Type::Int32: | 
					
						
							|  |  |  |     case Type::Double: | 
					
						
							|  |  |  |         return *this; | 
					
						
							| 
									
										
										
										
											2020-03-16 00:19:41 +02:00
										 |  |  |     case Type::String: { | 
					
						
							| 
									
										
										
										
											2020-05-13 00:28:42 +01:00
										 |  |  |         auto string = as_string().string().trim_whitespace(); | 
					
						
							| 
									
										
										
										
											2020-03-29 14:56:28 +02:00
										 |  |  |         if (string.is_empty()) | 
					
						
							|  |  |  |             return Value(0); | 
					
						
							| 
									
										
										
										
											2020-04-12 13:06:34 +01:00
										 |  |  |         if (string == "Infinity" || string == "+Infinity") | 
					
						
							|  |  |  |             return js_infinity(); | 
					
						
							|  |  |  |         if (string == "-Infinity") | 
					
						
							| 
									
										
										
										
											2020-04-12 13:25:42 +01:00
										 |  |  |             return js_negative_infinity(); | 
					
						
							| 
									
										
										
										
											2020-05-13 00:04:52 +01:00
										 |  |  |         char* endptr; | 
					
						
							|  |  |  |         auto parsed_double = strtod(string.characters(), &endptr); | 
					
						
							|  |  |  |         if (*endptr) | 
					
						
							|  |  |  |             return js_nan(); | 
					
						
							|  |  |  |         return Value(parsed_double); | 
					
						
							| 
									
										
										
										
											2020-03-15 15:00:18 +01:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2020-04-29 23:25:21 -07:00
										 |  |  |     case Type::Symbol: | 
					
						
							| 
									
										
										
										
											2020-09-27 18:36:49 +02:00
										 |  |  |         global_object.vm().throw_exception<TypeError>(global_object, ErrorType::Convert, "symbol", "number"); | 
					
						
							| 
									
										
										
										
											2020-05-18 00:54:10 +01:00
										 |  |  |         return {}; | 
					
						
							| 
									
										
										
										
											2020-06-06 01:14:10 +01:00
										 |  |  |     case Type::BigInt: | 
					
						
							| 
									
										
										
										
											2020-09-27 18:36:49 +02:00
										 |  |  |         global_object.vm().throw_exception<TypeError>(global_object, ErrorType::Convert, "BigInt", "number"); | 
					
						
							| 
									
										
										
										
											2020-06-06 01:14:10 +01:00
										 |  |  |         return {}; | 
					
						
							| 
									
										
										
										
											2020-06-04 21:36:52 +01:00
										 |  |  |     case Type::Object: { | 
					
						
							| 
									
										
										
										
											2021-03-02 19:22:36 +01:00
										 |  |  |         auto primitive = to_primitive(global_object, PreferredType::Number); | 
					
						
							| 
									
										
										
										
											2020-09-27 18:36:49 +02:00
										 |  |  |         if (global_object.vm().exception()) | 
					
						
							| 
									
										
										
										
											2020-05-18 00:28:00 +01:00
										 |  |  |             return {}; | 
					
						
							| 
									
										
										
										
											2020-09-27 18:36:49 +02:00
										 |  |  |         return primitive.to_number(global_object); | 
					
						
							| 
									
										
										
										
											2020-03-16 00:19:41 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2020-06-04 21:36:52 +01:00
										 |  |  |     default: | 
					
						
							| 
									
										
										
										
											2021-02-23 20:42:32 +01:00
										 |  |  |         VERIFY_NOT_REACHED(); | 
					
						
							| 
									
										
										
										
											2020-06-04 21:36:52 +01:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2020-03-16 00:19:41 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-27 17:24:14 +02:00
										 |  |  | BigInt* Value::to_bigint(GlobalObject& global_object) const | 
					
						
							| 
									
										
										
										
											2020-06-06 01:14:10 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2020-09-27 17:24:14 +02:00
										 |  |  |     auto& vm = global_object.vm(); | 
					
						
							| 
									
										
										
										
											2021-03-02 19:22:36 +01:00
										 |  |  |     auto primitive = to_primitive(global_object, PreferredType::Number); | 
					
						
							| 
									
										
										
										
											2020-09-27 17:24:14 +02:00
										 |  |  |     if (vm.exception()) | 
					
						
							| 
									
										
										
										
											2020-06-06 01:14:10 +01:00
										 |  |  |         return nullptr; | 
					
						
							|  |  |  |     switch (primitive.type()) { | 
					
						
							|  |  |  |     case Type::Undefined: | 
					
						
							| 
									
										
										
										
											2020-09-27 17:24:14 +02:00
										 |  |  |         vm.throw_exception<TypeError>(global_object, ErrorType::Convert, "undefined", "BigInt"); | 
					
						
							| 
									
										
										
										
											2020-06-06 01:14:10 +01:00
										 |  |  |         return nullptr; | 
					
						
							|  |  |  |     case Type::Null: | 
					
						
							| 
									
										
										
										
											2020-09-27 17:24:14 +02:00
										 |  |  |         vm.throw_exception<TypeError>(global_object, ErrorType::Convert, "null", "BigInt"); | 
					
						
							| 
									
										
										
										
											2020-06-06 01:14:10 +01:00
										 |  |  |         return nullptr; | 
					
						
							|  |  |  |     case Type::Boolean: { | 
					
						
							|  |  |  |         auto value = primitive.as_bool() ? 1 : 0; | 
					
						
							| 
									
										
										
										
											2020-09-27 17:24:14 +02:00
										 |  |  |         return js_bigint(vm.heap(), Crypto::SignedBigInteger { value }); | 
					
						
							| 
									
										
										
										
											2020-06-06 01:14:10 +01:00
										 |  |  |     } | 
					
						
							|  |  |  |     case Type::BigInt: | 
					
						
							|  |  |  |         return &primitive.as_bigint(); | 
					
						
							| 
									
										
										
										
											2021-03-21 18:03:00 +01:00
										 |  |  |     case Type::Int32: | 
					
						
							|  |  |  |     case Type::Double: | 
					
						
							| 
									
										
										
										
											2020-09-27 17:24:14 +02:00
										 |  |  |         vm.throw_exception<TypeError>(global_object, ErrorType::Convert, "number", "BigInt"); | 
					
						
							| 
									
										
										
										
											2020-06-06 01:14:10 +01:00
										 |  |  |         return {}; | 
					
						
							|  |  |  |     case Type::String: { | 
					
						
							|  |  |  |         auto& string = primitive.as_string().string(); | 
					
						
							|  |  |  |         if (!is_valid_bigint_value(string)) { | 
					
						
							| 
									
										
										
										
											2020-10-04 13:55:20 +01:00
										 |  |  |             vm.throw_exception<SyntaxError>(global_object, ErrorType::BigIntInvalidValue, string); | 
					
						
							| 
									
										
										
										
											2020-06-06 01:14:10 +01:00
										 |  |  |             return {}; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2020-09-27 17:24:14 +02:00
										 |  |  |         return js_bigint(vm.heap(), Crypto::SignedBigInteger::from_base10(string.trim_whitespace())); | 
					
						
							| 
									
										
										
										
											2020-06-06 01:14:10 +01:00
										 |  |  |     } | 
					
						
							|  |  |  |     case Type::Symbol: | 
					
						
							| 
									
										
										
										
											2020-09-27 17:24:14 +02:00
										 |  |  |         vm.throw_exception<TypeError>(global_object, ErrorType::Convert, "symbol", "BigInt"); | 
					
						
							| 
									
										
										
										
											2020-06-06 01:14:10 +01:00
										 |  |  |         return {}; | 
					
						
							|  |  |  |     default: | 
					
						
							| 
									
										
										
										
											2021-02-23 20:42:32 +01:00
										 |  |  |         VERIFY_NOT_REACHED(); | 
					
						
							| 
									
										
										
										
											2020-06-06 01:14:10 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-05 09:11:58 +01:00
										 |  |  | // FIXME: These two conversions are wrong for JS, and seem likely to be footguns
 | 
					
						
							| 
									
										
										
										
											2020-05-18 08:59:35 +01:00
										 |  |  | i32 Value::as_i32() const | 
					
						
							| 
									
										
										
										
											2020-05-18 00:28:00 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2020-05-18 08:59:35 +01:00
										 |  |  |     return static_cast<i32>(as_double()); | 
					
						
							| 
									
										
										
										
											2020-05-18 00:28:00 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-09 21:52:47 +01:00
										 |  |  | u32 Value::as_u32() const | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2021-02-23 20:42:32 +01:00
										 |  |  |     VERIFY(as_double() >= 0); | 
					
						
							| 
									
										
										
										
											2021-01-09 21:52:47 +01:00
										 |  |  |     return min((double)as_i32(), MAX_U32); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-27 18:36:49 +02:00
										 |  |  | double Value::to_double(GlobalObject& global_object) const | 
					
						
							| 
									
										
										
										
											2020-04-08 11:22:20 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2020-09-27 18:36:49 +02:00
										 |  |  |     auto number = to_number(global_object); | 
					
						
							|  |  |  |     if (global_object.vm().exception()) | 
					
						
							| 
									
										
										
										
											2021-01-09 16:32:23 +01:00
										 |  |  |         return INVALID; | 
					
						
							| 
									
										
										
										
											2020-05-18 08:59:35 +01:00
										 |  |  |     return number.as_double(); | 
					
						
							| 
									
										
										
										
											2020-04-08 11:22:20 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-21 18:03:00 +01:00
										 |  |  | i32 Value::to_i32_slow_case(GlobalObject& global_object) const | 
					
						
							| 
									
										
										
										
											2020-05-18 00:28:00 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2021-03-21 18:03:00 +01:00
										 |  |  |     VERIFY(type() != Type::Int32); | 
					
						
							| 
									
										
										
										
											2020-09-27 18:36:49 +02:00
										 |  |  |     auto number = to_number(global_object); | 
					
						
							|  |  |  |     if (global_object.vm().exception()) | 
					
						
							| 
									
										
										
										
											2021-01-09 16:32:23 +01:00
										 |  |  |         return INVALID; | 
					
						
							| 
									
										
										
										
											2021-02-05 09:11:58 +01:00
										 |  |  |     double value = number.as_double(); | 
					
						
							|  |  |  |     if (!isfinite(value) || value == 0) | 
					
						
							| 
									
										
										
										
											2020-05-23 15:02:14 +01:00
										 |  |  |         return 0; | 
					
						
							| 
									
										
										
										
											2021-02-05 09:11:58 +01:00
										 |  |  |     auto abs = fabs(value); | 
					
						
							|  |  |  |     auto int_val = floor(abs); | 
					
						
							|  |  |  |     if (signbit(value)) | 
					
						
							|  |  |  |         int_val = -int_val; | 
					
						
							|  |  |  |     auto int32bit = fmod(int_val, 4294967296.0); | 
					
						
							|  |  |  |     if (int32bit >= 2147483648.0) | 
					
						
							|  |  |  |         int32bit -= 4294967296.0; | 
					
						
							|  |  |  |     return static_cast<i32>(int32bit); | 
					
						
							| 
									
										
										
										
											2020-05-18 00:28:00 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-09 21:52:47 +01:00
										 |  |  | u32 Value::to_u32(GlobalObject& global_object) const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     // 7.1.7 ToUint32, https://tc39.es/ecma262/#sec-touint32
 | 
					
						
							|  |  |  |     auto number = to_number(global_object); | 
					
						
							|  |  |  |     if (global_object.vm().exception()) | 
					
						
							|  |  |  |         return INVALID; | 
					
						
							| 
									
										
										
										
											2021-02-05 09:11:58 +01:00
										 |  |  |     double value = number.as_double(); | 
					
						
							|  |  |  |     if (!isfinite(value) || value == 0) | 
					
						
							| 
									
										
										
										
											2021-01-09 21:52:47 +01:00
										 |  |  |         return 0; | 
					
						
							| 
									
										
										
										
											2021-02-05 09:11:58 +01:00
										 |  |  |     auto int_val = floor(fabs(value)); | 
					
						
							|  |  |  |     if (signbit(value)) | 
					
						
							|  |  |  |         int_val = -int_val; | 
					
						
							|  |  |  |     auto int32bit = fmod(int_val, NumericLimits<u32>::max() + 1.0); | 
					
						
							|  |  |  |     return static_cast<u32>(int32bit); | 
					
						
							| 
									
										
										
										
											2021-01-09 21:52:47 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-02 13:23:51 +00:00
										 |  |  | size_t Value::to_length(GlobalObject& global_object) const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     // 7.1.20 ToLength, https://tc39.es/ecma262/#sec-tolength
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     auto& vm = global_object.vm(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     auto len = to_integer_or_infinity(global_object); | 
					
						
							|  |  |  |     if (vm.exception()) | 
					
						
							|  |  |  |         return INVALID; | 
					
						
							|  |  |  |     if (len <= 0) | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  |     return min(len, MAX_ARRAY_LIKE_INDEX); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | size_t Value::to_index(GlobalObject& global_object) const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     // 7.1.22 ToIndex, https://tc39.es/ecma262/#sec-toindex
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     auto& vm = global_object.vm(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (is_undefined()) | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  |     auto integer_index = to_integer_or_infinity(global_object); | 
					
						
							|  |  |  |     if (vm.exception()) | 
					
						
							|  |  |  |         return INVALID; | 
					
						
							|  |  |  |     if (integer_index < 0) { | 
					
						
							|  |  |  |         vm.throw_exception<RangeError>(global_object, ErrorType::InvalidIndex); | 
					
						
							|  |  |  |         return INVALID; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     auto index = Value(integer_index).to_length(global_object); | 
					
						
							| 
									
										
										
										
											2021-02-23 20:42:32 +01:00
										 |  |  |     VERIFY(!vm.exception()); | 
					
						
							| 
									
										
										
										
											2020-12-02 13:23:51 +00:00
										 |  |  |     if (integer_index != index) { | 
					
						
							|  |  |  |         vm.throw_exception<RangeError>(global_object, ErrorType::InvalidIndex); | 
					
						
							|  |  |  |         return INVALID; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return index; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | double Value::to_integer_or_infinity(GlobalObject& global_object) const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     // 7.1.5 ToIntegerOrInfinity, https://tc39.es/ecma262/#sec-tointegerorinfinity
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     auto& vm = global_object.vm(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     auto number = to_number(global_object); | 
					
						
							|  |  |  |     if (vm.exception()) | 
					
						
							|  |  |  |         return INVALID; | 
					
						
							|  |  |  |     if (number.is_nan() || number.as_double() == 0) | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  |     if (number.is_infinity()) | 
					
						
							|  |  |  |         return number.as_double(); | 
					
						
							| 
									
										
										
										
											2021-02-15 11:51:08 +01:00
										 |  |  |     auto integer = floor(fabs(number.as_double())); | 
					
						
							| 
									
										
										
										
											2020-12-02 13:23:51 +00:00
										 |  |  |     if (number.as_double() < 0) | 
					
						
							|  |  |  |         integer = -integer; | 
					
						
							|  |  |  |     return integer; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-27 19:52:47 +02:00
										 |  |  | Value greater_than(GlobalObject& global_object, Value lhs, Value rhs) | 
					
						
							| 
									
										
										
										
											2020-03-10 11:35:05 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2020-09-27 19:52:47 +02:00
										 |  |  |     TriState relation = abstract_relation(global_object, false, lhs, rhs); | 
					
						
							| 
									
										
										
										
											2020-05-28 17:19:59 +02:00
										 |  |  |     if (relation == TriState::Unknown) | 
					
						
							|  |  |  |         return Value(false); | 
					
						
							|  |  |  |     return Value(relation == TriState::True); | 
					
						
							| 
									
										
										
										
											2020-03-10 11:35:05 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-27 19:52:47 +02:00
										 |  |  | Value greater_than_equals(GlobalObject& global_object, Value lhs, Value rhs) | 
					
						
							| 
									
										
										
										
											2020-03-12 23:07:08 +11:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2020-09-27 19:52:47 +02:00
										 |  |  |     TriState relation = abstract_relation(global_object, true, lhs, rhs); | 
					
						
							| 
									
										
										
										
											2020-05-28 17:19:59 +02:00
										 |  |  |     if (relation == TriState::Unknown || relation == TriState::True) | 
					
						
							|  |  |  |         return Value(false); | 
					
						
							|  |  |  |     return Value(true); | 
					
						
							| 
									
										
										
										
											2020-03-12 23:07:08 +11:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-27 19:52:47 +02:00
										 |  |  | Value less_than(GlobalObject& global_object, Value lhs, Value rhs) | 
					
						
							| 
									
										
										
										
											2020-03-10 11:35:05 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2020-09-27 19:52:47 +02:00
										 |  |  |     TriState relation = abstract_relation(global_object, true, lhs, rhs); | 
					
						
							| 
									
										
										
										
											2020-05-28 17:19:59 +02:00
										 |  |  |     if (relation == TriState::Unknown) | 
					
						
							|  |  |  |         return Value(false); | 
					
						
							|  |  |  |     return Value(relation == TriState::True); | 
					
						
							| 
									
										
										
										
											2020-03-10 11:35:05 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-27 19:52:47 +02:00
										 |  |  | Value less_than_equals(GlobalObject& global_object, Value lhs, Value rhs) | 
					
						
							| 
									
										
										
										
											2020-03-12 23:07:08 +11:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2020-09-27 19:52:47 +02:00
										 |  |  |     TriState relation = abstract_relation(global_object, false, lhs, rhs); | 
					
						
							| 
									
										
										
										
											2020-05-28 17:19:59 +02:00
										 |  |  |     if (relation == TriState::Unknown || relation == TriState::True) | 
					
						
							|  |  |  |         return Value(false); | 
					
						
							|  |  |  |     return Value(true); | 
					
						
							| 
									
										
										
										
											2020-03-12 23:07:08 +11:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-27 19:52:47 +02:00
										 |  |  | Value bitwise_and(GlobalObject& global_object, Value lhs, Value rhs) | 
					
						
							| 
									
										
										
										
											2020-03-10 11:35:05 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2021-03-16 22:00:46 +01:00
										 |  |  |     auto lhs_numeric = lhs.to_numeric(global_object); | 
					
						
							| 
									
										
										
										
											2020-09-27 19:52:47 +02:00
										 |  |  |     if (global_object.vm().exception()) | 
					
						
							| 
									
										
										
										
											2020-05-18 00:28:00 +01:00
										 |  |  |         return {}; | 
					
						
							| 
									
										
										
										
											2021-03-16 22:00:46 +01:00
										 |  |  |     auto rhs_numeric = rhs.to_numeric(global_object); | 
					
						
							| 
									
										
										
										
											2020-09-27 19:52:47 +02:00
										 |  |  |     if (global_object.vm().exception()) | 
					
						
							| 
									
										
										
										
											2020-05-18 00:28:00 +01:00
										 |  |  |         return {}; | 
					
						
							| 
									
										
										
										
											2020-07-22 20:27:32 -04:00
										 |  |  |     if (both_number(lhs_numeric, rhs_numeric)) { | 
					
						
							|  |  |  |         if (!lhs_numeric.is_finite_number() || !rhs_numeric.is_finite_number()) | 
					
						
							|  |  |  |             return Value(0); | 
					
						
							| 
									
										
										
										
											2021-03-16 22:00:46 +01:00
										 |  |  |         return Value(lhs_numeric.to_i32(global_object) & rhs_numeric.to_i32(global_object)); | 
					
						
							| 
									
										
										
										
											2020-07-22 20:27:32 -04:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2020-06-06 01:14:10 +01:00
										 |  |  |     if (both_bigint(lhs_numeric, rhs_numeric)) | 
					
						
							| 
									
										
										
										
											2020-09-27 19:52:47 +02:00
										 |  |  |         return js_bigint(global_object.heap(), lhs_numeric.as_bigint().big_integer().bitwise_and(rhs_numeric.as_bigint().big_integer())); | 
					
						
							| 
									
										
										
										
											2021-03-16 22:00:46 +01:00
										 |  |  |     global_object.vm().throw_exception<TypeError>(global_object, ErrorType::BigIntBadOperatorOtherType, "bitwise AND"); | 
					
						
							| 
									
										
										
										
											2020-06-06 01:14:10 +01:00
										 |  |  |     return {}; | 
					
						
							| 
									
										
										
										
											2020-03-10 11:35:05 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-27 19:52:47 +02:00
										 |  |  | Value bitwise_or(GlobalObject& global_object, Value lhs, Value rhs) | 
					
						
							| 
									
										
										
										
											2020-03-10 11:35:05 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2021-03-16 22:00:46 +01:00
										 |  |  |     auto lhs_numeric = lhs.to_numeric(global_object); | 
					
						
							| 
									
										
										
										
											2020-09-27 19:52:47 +02:00
										 |  |  |     if (global_object.vm().exception()) | 
					
						
							| 
									
										
										
										
											2020-05-18 00:28:00 +01:00
										 |  |  |         return {}; | 
					
						
							| 
									
										
										
										
											2021-03-16 22:00:46 +01:00
										 |  |  |     auto rhs_numeric = rhs.to_numeric(global_object); | 
					
						
							| 
									
										
										
										
											2020-09-27 19:52:47 +02:00
										 |  |  |     if (global_object.vm().exception()) | 
					
						
							| 
									
										
										
										
											2020-05-18 00:28:00 +01:00
										 |  |  |         return {}; | 
					
						
							| 
									
										
										
										
											2020-06-06 01:14:10 +01:00
										 |  |  |     if (both_number(lhs_numeric, rhs_numeric)) { | 
					
						
							|  |  |  |         if (!lhs_numeric.is_finite_number() && !rhs_numeric.is_finite_number()) | 
					
						
							|  |  |  |             return Value(0); | 
					
						
							|  |  |  |         if (!lhs_numeric.is_finite_number()) | 
					
						
							|  |  |  |             return rhs_numeric; | 
					
						
							|  |  |  |         if (!rhs_numeric.is_finite_number()) | 
					
						
							|  |  |  |             return lhs_numeric; | 
					
						
							| 
									
										
										
										
											2021-03-16 22:00:46 +01:00
										 |  |  |         return Value(lhs_numeric.to_i32(global_object) | rhs_numeric.to_i32(global_object)); | 
					
						
							| 
									
										
										
										
											2020-06-06 01:14:10 +01:00
										 |  |  |     } | 
					
						
							|  |  |  |     if (both_bigint(lhs_numeric, rhs_numeric)) | 
					
						
							| 
									
										
										
										
											2020-09-27 19:52:47 +02:00
										 |  |  |         return js_bigint(global_object.heap(), lhs_numeric.as_bigint().big_integer().bitwise_or(rhs_numeric.as_bigint().big_integer())); | 
					
						
							| 
									
										
										
										
											2021-03-16 22:00:46 +01:00
										 |  |  |     global_object.vm().throw_exception<TypeError>(global_object, ErrorType::BigIntBadOperatorOtherType, "bitwise OR"); | 
					
						
							| 
									
										
										
										
											2020-06-06 01:14:10 +01:00
										 |  |  |     return {}; | 
					
						
							| 
									
										
										
										
											2020-03-10 11:35:05 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-27 19:52:47 +02:00
										 |  |  | Value bitwise_xor(GlobalObject& global_object, Value lhs, Value rhs) | 
					
						
							| 
									
										
										
										
											2020-03-10 11:35:05 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2021-03-16 22:00:46 +01:00
										 |  |  |     auto lhs_numeric = lhs.to_numeric(global_object); | 
					
						
							| 
									
										
										
										
											2020-09-27 19:52:47 +02:00
										 |  |  |     if (global_object.vm().exception()) | 
					
						
							| 
									
										
										
										
											2020-05-18 00:28:00 +01:00
										 |  |  |         return {}; | 
					
						
							| 
									
										
										
										
											2021-03-16 22:00:46 +01:00
										 |  |  |     auto rhs_numeric = rhs.to_numeric(global_object); | 
					
						
							| 
									
										
										
										
											2020-09-27 19:52:47 +02:00
										 |  |  |     if (global_object.vm().exception()) | 
					
						
							| 
									
										
										
										
											2020-05-18 00:28:00 +01:00
										 |  |  |         return {}; | 
					
						
							| 
									
										
										
										
											2020-07-22 20:27:32 -04:00
										 |  |  |     if (both_number(lhs_numeric, rhs_numeric)) { | 
					
						
							|  |  |  |         if (!lhs_numeric.is_finite_number() && !rhs_numeric.is_finite_number()) | 
					
						
							|  |  |  |             return Value(0); | 
					
						
							|  |  |  |         if (!lhs_numeric.is_finite_number()) | 
					
						
							|  |  |  |             return rhs_numeric; | 
					
						
							|  |  |  |         if (!rhs_numeric.is_finite_number()) | 
					
						
							|  |  |  |             return lhs_numeric; | 
					
						
							| 
									
										
										
										
											2021-03-16 22:00:46 +01:00
										 |  |  |         return Value(lhs_numeric.to_i32(global_object) ^ rhs_numeric.to_i32(global_object)); | 
					
						
							| 
									
										
										
										
											2020-07-22 20:27:32 -04:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2020-06-06 01:14:10 +01:00
										 |  |  |     if (both_bigint(lhs_numeric, rhs_numeric)) | 
					
						
							| 
									
										
										
										
											2020-09-27 19:52:47 +02:00
										 |  |  |         return js_bigint(global_object.heap(), lhs_numeric.as_bigint().big_integer().bitwise_xor(rhs_numeric.as_bigint().big_integer())); | 
					
						
							| 
									
										
										
										
											2021-03-16 22:00:46 +01:00
										 |  |  |     global_object.vm().throw_exception<TypeError>(global_object, ErrorType::BigIntBadOperatorOtherType, "bitwise XOR"); | 
					
						
							| 
									
										
										
										
											2020-06-06 01:14:10 +01:00
										 |  |  |     return {}; | 
					
						
							| 
									
										
										
										
											2020-03-10 11:35:05 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-27 19:52:47 +02:00
										 |  |  | Value bitwise_not(GlobalObject& global_object, Value lhs) | 
					
						
							| 
									
										
										
										
											2020-03-10 11:35:05 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2021-03-16 22:00:46 +01:00
										 |  |  |     auto lhs_numeric = lhs.to_numeric(global_object); | 
					
						
							| 
									
										
										
										
											2020-09-27 19:52:47 +02:00
										 |  |  |     if (global_object.vm().exception()) | 
					
						
							| 
									
										
										
										
											2020-05-18 00:28:00 +01:00
										 |  |  |         return {}; | 
					
						
							| 
									
										
										
										
											2020-06-06 01:14:10 +01:00
										 |  |  |     if (lhs_numeric.is_number()) | 
					
						
							| 
									
										
										
										
											2021-01-09 16:36:25 +01:00
										 |  |  |         return Value(~lhs_numeric.to_i32(global_object)); | 
					
						
							| 
									
										
										
										
											2020-06-06 01:14:10 +01:00
										 |  |  |     auto big_integer_bitwise_not = lhs_numeric.as_bigint().big_integer(); | 
					
						
							|  |  |  |     big_integer_bitwise_not = big_integer_bitwise_not.plus(Crypto::SignedBigInteger { 1 }); | 
					
						
							|  |  |  |     big_integer_bitwise_not.negate(); | 
					
						
							| 
									
										
										
										
											2020-09-27 19:52:47 +02:00
										 |  |  |     return js_bigint(global_object.heap(), big_integer_bitwise_not); | 
					
						
							| 
									
										
										
										
											2020-03-10 11:35:05 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-27 19:52:47 +02:00
										 |  |  | Value unary_plus(GlobalObject& global_object, Value lhs) | 
					
						
							| 
									
										
										
										
											2020-04-02 17:58:39 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2021-03-16 22:00:46 +01:00
										 |  |  |     return lhs.to_number(global_object); | 
					
						
							| 
									
										
										
										
											2020-04-02 17:58:39 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-27 19:52:47 +02:00
										 |  |  | Value unary_minus(GlobalObject& global_object, Value lhs) | 
					
						
							| 
									
										
										
										
											2020-04-02 17:58:39 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2021-03-16 22:00:46 +01:00
										 |  |  |     auto lhs_numeric = lhs.to_numeric(global_object); | 
					
						
							| 
									
										
										
										
											2020-09-27 19:52:47 +02:00
										 |  |  |     if (global_object.vm().exception()) | 
					
						
							| 
									
										
										
										
											2020-05-18 00:28:00 +01:00
										 |  |  |         return {}; | 
					
						
							| 
									
										
										
										
											2020-06-06 01:14:10 +01:00
										 |  |  |     if (lhs_numeric.is_number()) { | 
					
						
							|  |  |  |         if (lhs_numeric.is_nan()) | 
					
						
							|  |  |  |             return js_nan(); | 
					
						
							|  |  |  |         return Value(-lhs_numeric.as_double()); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (lhs_numeric.as_bigint().big_integer() == BIGINT_ZERO) | 
					
						
							| 
									
										
										
										
											2020-09-27 19:52:47 +02:00
										 |  |  |         return js_bigint(global_object.heap(), BIGINT_ZERO); | 
					
						
							| 
									
										
										
										
											2020-06-06 01:14:10 +01:00
										 |  |  |     auto big_integer_negated = lhs_numeric.as_bigint().big_integer(); | 
					
						
							|  |  |  |     big_integer_negated.negate(); | 
					
						
							| 
									
										
										
										
											2020-09-27 19:52:47 +02:00
										 |  |  |     return js_bigint(global_object.heap(), big_integer_negated); | 
					
						
							| 
									
										
										
										
											2020-04-02 17:58:39 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-27 19:52:47 +02:00
										 |  |  | Value left_shift(GlobalObject& global_object, Value lhs, Value rhs) | 
					
						
							| 
									
										
										
										
											2020-03-10 11:35:05 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2021-02-05 09:11:58 +01:00
										 |  |  |     // 6.1.6.1.9 Number::leftShift
 | 
					
						
							|  |  |  |     // https://tc39.es/ecma262/#sec-numeric-types-number-leftShift
 | 
					
						
							| 
									
										
										
										
											2021-03-16 22:00:46 +01:00
										 |  |  |     auto lhs_numeric = lhs.to_numeric(global_object); | 
					
						
							| 
									
										
										
										
											2020-09-27 19:52:47 +02:00
										 |  |  |     if (global_object.vm().exception()) | 
					
						
							| 
									
										
										
										
											2020-05-18 00:28:00 +01:00
										 |  |  |         return {}; | 
					
						
							| 
									
										
										
										
											2021-03-16 22:00:46 +01:00
										 |  |  |     auto rhs_numeric = rhs.to_numeric(global_object); | 
					
						
							| 
									
										
										
										
											2020-09-27 19:52:47 +02:00
										 |  |  |     if (global_object.vm().exception()) | 
					
						
							| 
									
										
										
										
											2020-05-18 00:28:00 +01:00
										 |  |  |         return {}; | 
					
						
							| 
									
										
										
										
											2020-06-06 01:14:10 +01:00
										 |  |  |     if (both_number(lhs_numeric, rhs_numeric)) { | 
					
						
							|  |  |  |         if (!lhs_numeric.is_finite_number()) | 
					
						
							|  |  |  |             return Value(0); | 
					
						
							|  |  |  |         if (!rhs_numeric.is_finite_number()) | 
					
						
							|  |  |  |             return lhs_numeric; | 
					
						
							| 
									
										
										
										
											2021-02-05 09:11:58 +01:00
										 |  |  |         // Ok, so this performs toNumber() again but that "can't" throw
 | 
					
						
							| 
									
										
										
										
											2021-03-16 22:00:46 +01:00
										 |  |  |         auto lhs_i32 = lhs_numeric.to_i32(global_object); | 
					
						
							|  |  |  |         auto rhs_u32 = rhs_numeric.to_u32(global_object); | 
					
						
							| 
									
										
										
										
											2021-02-05 09:11:58 +01:00
										 |  |  |         return Value(lhs_i32 << rhs_u32); | 
					
						
							| 
									
										
										
										
											2020-06-06 01:14:10 +01:00
										 |  |  |     } | 
					
						
							|  |  |  |     if (both_bigint(lhs_numeric, rhs_numeric)) | 
					
						
							|  |  |  |         TODO(); | 
					
						
							| 
									
										
										
										
											2021-03-16 22:00:46 +01:00
										 |  |  |     global_object.vm().throw_exception<TypeError>(global_object, ErrorType::BigIntBadOperatorOtherType, "left-shift"); | 
					
						
							| 
									
										
										
										
											2020-06-06 01:14:10 +01:00
										 |  |  |     return {}; | 
					
						
							| 
									
										
										
										
											2020-03-10 11:35:05 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-27 19:52:47 +02:00
										 |  |  | Value right_shift(GlobalObject& global_object, Value lhs, Value rhs) | 
					
						
							| 
									
										
										
										
											2020-03-10 11:35:05 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2021-02-05 09:11:58 +01:00
										 |  |  |     // 6.1.6.1.11 Number::signedRightShift
 | 
					
						
							|  |  |  |     // https://tc39.es/ecma262/#sec-numeric-types-number-signedRightShift
 | 
					
						
							| 
									
										
										
										
											2021-03-16 22:00:46 +01:00
										 |  |  |     auto lhs_numeric = lhs.to_numeric(global_object); | 
					
						
							| 
									
										
										
										
											2020-09-27 19:52:47 +02:00
										 |  |  |     if (global_object.vm().exception()) | 
					
						
							| 
									
										
										
										
											2020-05-18 00:28:00 +01:00
										 |  |  |         return {}; | 
					
						
							| 
									
										
										
										
											2021-03-16 22:00:46 +01:00
										 |  |  |     auto rhs_numeric = rhs.to_numeric(global_object); | 
					
						
							| 
									
										
										
										
											2020-09-27 19:52:47 +02:00
										 |  |  |     if (global_object.vm().exception()) | 
					
						
							| 
									
										
										
										
											2020-05-18 00:28:00 +01:00
										 |  |  |         return {}; | 
					
						
							| 
									
										
										
										
											2020-06-06 01:14:10 +01:00
										 |  |  |     if (both_number(lhs_numeric, rhs_numeric)) { | 
					
						
							|  |  |  |         if (!lhs_numeric.is_finite_number()) | 
					
						
							|  |  |  |             return Value(0); | 
					
						
							|  |  |  |         if (!rhs_numeric.is_finite_number()) | 
					
						
							|  |  |  |             return lhs_numeric; | 
					
						
							| 
									
										
										
										
											2021-02-05 09:11:58 +01:00
										 |  |  |         // Ok, so this performs toNumber() again but that "can't" throw
 | 
					
						
							| 
									
										
										
										
											2021-03-16 22:00:46 +01:00
										 |  |  |         auto lhs_i32 = lhs_numeric.to_i32(global_object); | 
					
						
							|  |  |  |         auto rhs_u32 = rhs_numeric.to_u32(global_object); | 
					
						
							| 
									
										
										
										
											2021-02-05 09:11:58 +01:00
										 |  |  |         return Value(lhs_i32 >> rhs_u32); | 
					
						
							| 
									
										
										
										
											2020-06-06 01:14:10 +01:00
										 |  |  |     } | 
					
						
							|  |  |  |     if (both_bigint(lhs_numeric, rhs_numeric)) | 
					
						
							|  |  |  |         TODO(); | 
					
						
							| 
									
										
										
										
											2021-03-16 22:00:46 +01:00
										 |  |  |     global_object.vm().throw_exception<TypeError>(global_object, ErrorType::BigIntBadOperatorOtherType, "right-shift"); | 
					
						
							| 
									
										
										
										
											2020-06-06 01:14:10 +01:00
										 |  |  |     return {}; | 
					
						
							| 
									
										
										
										
											2020-03-10 11:35:05 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-27 19:52:47 +02:00
										 |  |  | Value unsigned_right_shift(GlobalObject& global_object, Value lhs, Value rhs) | 
					
						
							| 
									
										
										
										
											2020-04-23 15:43:10 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2021-02-05 09:11:58 +01:00
										 |  |  |     // 6.1.6.1.11 Number::unsignedRightShift
 | 
					
						
							|  |  |  |     // https://tc39.es/ecma262/#sec-numeric-types-number-unsignedRightShift
 | 
					
						
							| 
									
										
										
										
											2021-03-16 22:00:46 +01:00
										 |  |  |     auto lhs_numeric = lhs.to_numeric(global_object); | 
					
						
							| 
									
										
										
										
											2020-09-27 19:52:47 +02:00
										 |  |  |     if (global_object.vm().exception()) | 
					
						
							| 
									
										
										
										
											2020-05-18 00:28:00 +01:00
										 |  |  |         return {}; | 
					
						
							| 
									
										
										
										
											2021-03-16 22:00:46 +01:00
										 |  |  |     auto rhs_numeric = rhs.to_numeric(global_object); | 
					
						
							| 
									
										
										
										
											2020-09-27 19:52:47 +02:00
										 |  |  |     if (global_object.vm().exception()) | 
					
						
							| 
									
										
										
										
											2020-05-18 00:28:00 +01:00
										 |  |  |         return {}; | 
					
						
							| 
									
										
										
										
											2020-06-06 01:14:10 +01:00
										 |  |  |     if (both_number(lhs_numeric, rhs_numeric)) { | 
					
						
							|  |  |  |         if (!lhs_numeric.is_finite_number()) | 
					
						
							|  |  |  |             return Value(0); | 
					
						
							|  |  |  |         if (!rhs_numeric.is_finite_number()) | 
					
						
							|  |  |  |             return lhs_numeric; | 
					
						
							| 
									
										
										
										
											2021-02-05 09:11:58 +01:00
										 |  |  |         // Ok, so this performs toNumber() again but that "can't" throw
 | 
					
						
							| 
									
										
										
										
											2021-03-16 22:00:46 +01:00
										 |  |  |         auto lhs_u32 = lhs_numeric.to_u32(global_object); | 
					
						
							|  |  |  |         auto rhs_u32 = rhs_numeric.to_u32(global_object) % 32; | 
					
						
							| 
									
										
										
										
											2021-02-05 09:11:58 +01:00
										 |  |  |         return Value(lhs_u32 >> rhs_u32); | 
					
						
							| 
									
										
										
										
											2020-06-06 01:14:10 +01:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-03-16 22:00:46 +01:00
										 |  |  |     global_object.vm().throw_exception<TypeError>(global_object, ErrorType::BigIntBadOperator, "unsigned right-shift"); | 
					
						
							| 
									
										
										
										
											2020-06-06 01:14:10 +01:00
										 |  |  |     return {}; | 
					
						
							| 
									
										
										
										
											2020-04-23 15:43:10 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-27 19:52:47 +02:00
										 |  |  | Value add(GlobalObject& global_object, Value lhs, Value rhs) | 
					
						
							| 
									
										
										
										
											2020-03-11 12:16:26 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2021-03-21 18:13:14 +01:00
										 |  |  |     if (both_number(lhs, rhs)) { | 
					
						
							|  |  |  |         if (lhs.type() == Value::Type::Int32 && rhs.type() == Value::Type::Int32) { | 
					
						
							|  |  |  |             Checked<i32> result; | 
					
						
							|  |  |  |             result = lhs.to_i32(global_object); | 
					
						
							|  |  |  |             result += rhs.to_i32(global_object); | 
					
						
							|  |  |  |             if (!result.has_overflow()) | 
					
						
							|  |  |  |                 return Value(result.value()); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         return Value(lhs.as_double() + rhs.as_double()); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-03-21 18:06:13 +01:00
										 |  |  |     auto& vm = global_object.vm(); | 
					
						
							| 
									
										
										
										
											2021-03-02 19:22:36 +01:00
										 |  |  |     auto lhs_primitive = lhs.to_primitive(global_object); | 
					
						
							| 
									
										
										
										
											2021-03-21 18:06:13 +01:00
										 |  |  |     if (vm.exception()) | 
					
						
							| 
									
										
										
										
											2020-05-15 13:39:24 +02:00
										 |  |  |         return {}; | 
					
						
							| 
									
										
										
										
											2021-03-02 19:22:36 +01:00
										 |  |  |     auto rhs_primitive = rhs.to_primitive(global_object); | 
					
						
							| 
									
										
										
										
											2021-03-21 18:06:13 +01:00
										 |  |  |     if (vm.exception()) | 
					
						
							| 
									
										
										
										
											2020-05-15 13:39:24 +02:00
										 |  |  |         return {}; | 
					
						
							| 
									
										
										
										
											2020-04-15 09:32:44 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-15 13:39:24 +02:00
										 |  |  |     if (lhs_primitive.is_string() || rhs_primitive.is_string()) { | 
					
						
							| 
									
										
										
										
											2021-03-16 22:00:46 +01:00
										 |  |  |         auto lhs_string = lhs_primitive.to_string(global_object); | 
					
						
							| 
									
										
										
										
											2021-03-21 18:06:13 +01:00
										 |  |  |         if (vm.exception()) | 
					
						
							| 
									
										
										
										
											2020-05-15 13:39:24 +02:00
										 |  |  |             return {}; | 
					
						
							| 
									
										
										
										
											2021-03-16 22:00:46 +01:00
										 |  |  |         auto rhs_string = rhs_primitive.to_string(global_object); | 
					
						
							| 
									
										
										
										
											2021-03-21 18:06:13 +01:00
										 |  |  |         if (vm.exception()) | 
					
						
							| 
									
										
										
										
											2020-05-15 13:39:24 +02:00
										 |  |  |             return {}; | 
					
						
							|  |  |  |         StringBuilder builder(lhs_string.length() + rhs_string.length()); | 
					
						
							|  |  |  |         builder.append(lhs_string); | 
					
						
							|  |  |  |         builder.append(rhs_string); | 
					
						
							| 
									
										
										
										
											2021-03-21 18:06:13 +01:00
										 |  |  |         return js_string(vm.heap(), builder.to_string()); | 
					
						
							| 
									
										
										
										
											2020-05-15 13:39:24 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2020-03-16 00:19:41 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-16 22:00:46 +01:00
										 |  |  |     auto lhs_numeric = lhs_primitive.to_numeric(global_object); | 
					
						
							| 
									
										
										
										
											2021-03-21 18:06:13 +01:00
										 |  |  |     if (vm.exception()) | 
					
						
							| 
									
										
										
										
											2020-05-18 00:28:00 +01:00
										 |  |  |         return {}; | 
					
						
							| 
									
										
										
										
											2021-03-16 22:00:46 +01:00
										 |  |  |     auto rhs_numeric = rhs_primitive.to_numeric(global_object); | 
					
						
							| 
									
										
										
										
											2021-03-21 18:06:13 +01:00
										 |  |  |     if (vm.exception()) | 
					
						
							| 
									
										
										
										
											2020-05-18 00:28:00 +01:00
										 |  |  |         return {}; | 
					
						
							| 
									
										
										
										
											2020-06-06 01:14:10 +01:00
										 |  |  |     if (both_number(lhs_numeric, rhs_numeric)) | 
					
						
							|  |  |  |         return Value(lhs_numeric.as_double() + rhs_numeric.as_double()); | 
					
						
							|  |  |  |     if (both_bigint(lhs_numeric, rhs_numeric)) | 
					
						
							| 
									
										
										
										
											2021-03-21 18:06:13 +01:00
										 |  |  |         return js_bigint(vm.heap(), lhs_numeric.as_bigint().big_integer().plus(rhs_numeric.as_bigint().big_integer())); | 
					
						
							|  |  |  |     vm.throw_exception<TypeError>(global_object, ErrorType::BigIntBadOperatorOtherType, "addition"); | 
					
						
							| 
									
										
										
										
											2020-06-06 01:14:10 +01:00
										 |  |  |     return {}; | 
					
						
							| 
									
										
										
										
											2020-03-11 12:16:26 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-27 19:52:47 +02:00
										 |  |  | Value sub(GlobalObject& global_object, Value lhs, Value rhs) | 
					
						
							| 
									
										
										
										
											2020-03-11 12:16:26 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2021-03-16 22:00:46 +01:00
										 |  |  |     auto lhs_numeric = lhs.to_numeric(global_object); | 
					
						
							| 
									
										
										
										
											2020-09-27 19:52:47 +02:00
										 |  |  |     if (global_object.vm().exception()) | 
					
						
							| 
									
										
										
										
											2020-05-18 00:28:00 +01:00
										 |  |  |         return {}; | 
					
						
							| 
									
										
										
										
											2021-03-16 22:00:46 +01:00
										 |  |  |     auto rhs_numeric = rhs.to_numeric(global_object); | 
					
						
							| 
									
										
										
										
											2020-09-27 19:52:47 +02:00
										 |  |  |     if (global_object.vm().exception()) | 
					
						
							| 
									
										
										
										
											2020-05-18 00:28:00 +01:00
										 |  |  |         return {}; | 
					
						
							| 
									
										
										
										
											2020-06-06 01:14:10 +01:00
										 |  |  |     if (both_number(lhs_numeric, rhs_numeric)) | 
					
						
							|  |  |  |         return Value(lhs_numeric.as_double() - rhs_numeric.as_double()); | 
					
						
							|  |  |  |     if (both_bigint(lhs_numeric, rhs_numeric)) | 
					
						
							| 
									
										
										
										
											2020-09-27 19:52:47 +02:00
										 |  |  |         return js_bigint(global_object.heap(), lhs_numeric.as_bigint().big_integer().minus(rhs_numeric.as_bigint().big_integer())); | 
					
						
							| 
									
										
										
										
											2021-03-16 22:00:46 +01:00
										 |  |  |     global_object.vm().throw_exception<TypeError>(global_object, ErrorType::BigIntBadOperatorOtherType, "subtraction"); | 
					
						
							| 
									
										
										
										
											2020-06-06 01:14:10 +01:00
										 |  |  |     return {}; | 
					
						
							| 
									
										
										
										
											2020-03-11 12:16:26 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-27 19:52:47 +02:00
										 |  |  | Value mul(GlobalObject& global_object, Value lhs, Value rhs) | 
					
						
							| 
									
										
										
										
											2020-03-12 23:04:52 +11:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2021-03-16 22:00:46 +01:00
										 |  |  |     auto lhs_numeric = lhs.to_numeric(global_object); | 
					
						
							| 
									
										
										
										
											2020-09-27 19:52:47 +02:00
										 |  |  |     if (global_object.vm().exception()) | 
					
						
							| 
									
										
										
										
											2020-05-18 00:28:00 +01:00
										 |  |  |         return {}; | 
					
						
							| 
									
										
										
										
											2021-03-16 22:00:46 +01:00
										 |  |  |     auto rhs_numeric = rhs.to_numeric(global_object); | 
					
						
							| 
									
										
										
										
											2020-09-27 19:52:47 +02:00
										 |  |  |     if (global_object.vm().exception()) | 
					
						
							| 
									
										
										
										
											2020-05-18 00:28:00 +01:00
										 |  |  |         return {}; | 
					
						
							| 
									
										
										
										
											2020-06-06 01:14:10 +01:00
										 |  |  |     if (both_number(lhs_numeric, rhs_numeric)) | 
					
						
							|  |  |  |         return Value(lhs_numeric.as_double() * rhs_numeric.as_double()); | 
					
						
							|  |  |  |     if (both_bigint(lhs_numeric, rhs_numeric)) | 
					
						
							| 
									
										
										
										
											2020-09-27 19:52:47 +02:00
										 |  |  |         return js_bigint(global_object.heap(), lhs_numeric.as_bigint().big_integer().multiplied_by(rhs_numeric.as_bigint().big_integer())); | 
					
						
							| 
									
										
										
										
											2021-03-16 22:00:46 +01:00
										 |  |  |     global_object.vm().throw_exception<TypeError>(global_object, ErrorType::BigIntBadOperatorOtherType, "multiplication"); | 
					
						
							| 
									
										
										
										
											2020-06-06 01:14:10 +01:00
										 |  |  |     return {}; | 
					
						
							| 
									
										
										
										
											2020-03-12 23:04:52 +11:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-27 19:52:47 +02:00
										 |  |  | Value div(GlobalObject& global_object, Value lhs, Value rhs) | 
					
						
							| 
									
										
										
										
											2020-03-12 23:04:52 +11:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2021-03-16 20:34:40 +01:00
										 |  |  |     auto& vm = global_object.vm(); | 
					
						
							| 
									
										
										
										
											2021-03-16 22:00:46 +01:00
										 |  |  |     auto lhs_numeric = lhs.to_numeric(global_object); | 
					
						
							| 
									
										
										
										
											2021-03-16 20:34:40 +01:00
										 |  |  |     if (vm.exception()) | 
					
						
							| 
									
										
										
										
											2020-05-18 00:28:00 +01:00
										 |  |  |         return {}; | 
					
						
							| 
									
										
										
										
											2021-03-16 22:00:46 +01:00
										 |  |  |     auto rhs_numeric = rhs.to_numeric(global_object); | 
					
						
							| 
									
										
										
										
											2021-03-16 20:34:40 +01:00
										 |  |  |     if (vm.exception()) | 
					
						
							| 
									
										
										
										
											2020-05-18 00:28:00 +01:00
										 |  |  |         return {}; | 
					
						
							| 
									
										
										
										
											2020-06-06 01:14:10 +01:00
										 |  |  |     if (both_number(lhs_numeric, rhs_numeric)) | 
					
						
							|  |  |  |         return Value(lhs_numeric.as_double() / rhs_numeric.as_double()); | 
					
						
							| 
									
										
										
										
											2021-03-16 20:34:40 +01:00
										 |  |  |     if (both_bigint(lhs_numeric, rhs_numeric)) { | 
					
						
							|  |  |  |         if (rhs_numeric.as_bigint().big_integer() == BIGINT_ZERO) { | 
					
						
							|  |  |  |             vm.throw_exception<RangeError>(global_object, ErrorType::DivisionByZero); | 
					
						
							|  |  |  |             return {}; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2020-09-27 19:52:47 +02:00
										 |  |  |         return js_bigint(global_object.heap(), lhs_numeric.as_bigint().big_integer().divided_by(rhs_numeric.as_bigint().big_integer()).quotient); | 
					
						
							| 
									
										
										
										
											2021-03-16 20:34:40 +01:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-03-16 22:00:46 +01:00
										 |  |  |     vm.throw_exception<TypeError>(global_object, ErrorType::BigIntBadOperatorOtherType, "division"); | 
					
						
							| 
									
										
										
										
											2020-06-06 01:14:10 +01:00
										 |  |  |     return {}; | 
					
						
							| 
									
										
										
										
											2020-03-12 23:04:52 +11:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-27 19:52:47 +02:00
										 |  |  | Value mod(GlobalObject& global_object, Value lhs, Value rhs) | 
					
						
							| 
									
										
										
										
											2020-04-04 21:17:34 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2021-03-16 20:34:40 +01:00
										 |  |  |     auto& vm = global_object.vm(); | 
					
						
							| 
									
										
										
										
											2021-03-16 22:00:46 +01:00
										 |  |  |     auto lhs_numeric = lhs.to_numeric(global_object); | 
					
						
							| 
									
										
										
										
											2021-03-16 20:34:40 +01:00
										 |  |  |     if (vm.exception()) | 
					
						
							| 
									
										
										
										
											2020-05-18 00:28:00 +01:00
										 |  |  |         return {}; | 
					
						
							| 
									
										
										
										
											2021-03-16 22:00:46 +01:00
										 |  |  |     auto rhs_numeric = rhs.to_numeric(global_object); | 
					
						
							| 
									
										
										
										
											2021-03-16 20:34:40 +01:00
										 |  |  |     if (vm.exception()) | 
					
						
							| 
									
										
										
										
											2020-05-18 00:28:00 +01:00
										 |  |  |         return {}; | 
					
						
							| 
									
										
										
										
											2020-06-06 01:14:10 +01:00
										 |  |  |     if (both_number(lhs_numeric, rhs_numeric)) { | 
					
						
							|  |  |  |         if (lhs_numeric.is_nan() || rhs_numeric.is_nan()) | 
					
						
							|  |  |  |             return js_nan(); | 
					
						
							|  |  |  |         auto index = lhs_numeric.as_double(); | 
					
						
							|  |  |  |         auto period = rhs_numeric.as_double(); | 
					
						
							|  |  |  |         auto trunc = (double)(i32)(index / period); | 
					
						
							|  |  |  |         return Value(index - trunc * period); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-03-16 20:34:40 +01:00
										 |  |  |     if (both_bigint(lhs_numeric, rhs_numeric)) { | 
					
						
							|  |  |  |         if (rhs_numeric.as_bigint().big_integer() == BIGINT_ZERO) { | 
					
						
							|  |  |  |             vm.throw_exception<RangeError>(global_object, ErrorType::DivisionByZero); | 
					
						
							|  |  |  |             return {}; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2020-09-27 19:52:47 +02:00
										 |  |  |         return js_bigint(global_object.heap(), lhs_numeric.as_bigint().big_integer().divided_by(rhs_numeric.as_bigint().big_integer()).remainder); | 
					
						
							| 
									
										
										
										
											2021-03-16 20:34:40 +01:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-03-16 22:00:46 +01:00
										 |  |  |     vm.throw_exception<TypeError>(global_object, ErrorType::BigIntBadOperatorOtherType, "modulo"); | 
					
						
							| 
									
										
										
										
											2020-06-06 01:14:10 +01:00
										 |  |  |     return {}; | 
					
						
							| 
									
										
										
										
											2020-04-04 21:17:34 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-27 18:36:49 +02:00
										 |  |  | Value exp(GlobalObject& global_object, Value lhs, Value rhs) | 
					
						
							| 
									
										
										
										
											2020-04-05 13:40:00 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2020-09-27 18:36:49 +02:00
										 |  |  |     auto& vm = global_object.vm(); | 
					
						
							|  |  |  |     auto lhs_numeric = lhs.to_numeric(global_object); | 
					
						
							|  |  |  |     if (vm.exception()) | 
					
						
							| 
									
										
										
										
											2020-05-18 00:28:00 +01:00
										 |  |  |         return {}; | 
					
						
							| 
									
										
										
										
											2020-09-27 18:36:49 +02:00
										 |  |  |     auto rhs_numeric = rhs.to_numeric(global_object); | 
					
						
							|  |  |  |     if (vm.exception()) | 
					
						
							| 
									
										
										
										
											2020-05-18 00:28:00 +01:00
										 |  |  |         return {}; | 
					
						
							| 
									
										
										
										
											2020-06-06 01:14:10 +01:00
										 |  |  |     if (both_number(lhs_numeric, rhs_numeric)) | 
					
						
							|  |  |  |         return Value(pow(lhs_numeric.as_double(), rhs_numeric.as_double())); | 
					
						
							| 
									
										
										
										
											2021-03-16 20:35:55 +01:00
										 |  |  |     if (both_bigint(lhs_numeric, rhs_numeric)) { | 
					
						
							|  |  |  |         if (rhs_numeric.as_bigint().big_integer().is_negative()) { | 
					
						
							|  |  |  |             vm.throw_exception<RangeError>(global_object, ErrorType::NegativeExponent); | 
					
						
							|  |  |  |             return {}; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2020-09-27 18:36:49 +02:00
										 |  |  |         return js_bigint(vm.heap(), Crypto::NumberTheory::Power(lhs_numeric.as_bigint().big_integer(), rhs_numeric.as_bigint().big_integer())); | 
					
						
							| 
									
										
										
										
											2021-03-16 20:35:55 +01:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2020-09-27 18:36:49 +02:00
										 |  |  |     vm.throw_exception<TypeError>(global_object, ErrorType::BigIntBadOperatorOtherType, "exponentiation"); | 
					
						
							| 
									
										
										
										
											2020-06-06 01:14:10 +01:00
										 |  |  |     return {}; | 
					
						
							| 
									
										
										
										
											2020-04-05 13:40:00 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-27 19:52:47 +02:00
										 |  |  | Value in(GlobalObject& global_object, Value lhs, Value rhs) | 
					
						
							| 
									
										
										
										
											2020-05-07 17:09:00 -07:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2020-08-25 12:52:32 +02:00
										 |  |  |     if (!rhs.is_object()) { | 
					
						
							| 
									
										
										
										
											2021-03-16 22:00:46 +01:00
										 |  |  |         global_object.vm().throw_exception<TypeError>(global_object, ErrorType::InOperatorWithObject); | 
					
						
							| 
									
										
										
										
											2020-08-25 12:52:32 +02:00
										 |  |  |         return {}; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-03-16 22:00:46 +01:00
										 |  |  |     auto lhs_string = lhs.to_string(global_object); | 
					
						
							| 
									
										
										
										
											2020-09-27 19:52:47 +02:00
										 |  |  |     if (global_object.vm().exception()) | 
					
						
							| 
									
										
										
										
											2020-05-15 13:39:24 +02:00
										 |  |  |         return {}; | 
					
						
							| 
									
										
										
										
											2020-06-03 14:27:01 -07:00
										 |  |  |     return Value(rhs.as_object().has_property(lhs_string)); | 
					
						
							| 
									
										
										
										
											2020-05-07 17:09:00 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-27 18:36:49 +02:00
										 |  |  | Value instance_of(GlobalObject& global_object, Value lhs, Value rhs) | 
					
						
							| 
									
										
										
										
											2020-03-11 12:16:26 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2020-09-27 18:36:49 +02:00
										 |  |  |     auto& vm = global_object.vm(); | 
					
						
							| 
									
										
										
										
											2020-08-25 12:52:32 +02:00
										 |  |  |     if (!rhs.is_object()) { | 
					
						
							| 
									
										
										
										
											2020-10-04 13:55:20 +01:00
										 |  |  |         vm.throw_exception<TypeError>(global_object, ErrorType::NotAnObject, rhs.to_string_without_side_effects()); | 
					
						
							| 
									
										
										
										
											2020-08-25 12:52:32 +02:00
										 |  |  |         return {}; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-03-02 18:06:28 +01:00
										 |  |  |     auto has_instance_method = get_method(global_object, Value(&rhs.as_object()), vm.well_known_symbol_has_instance()); | 
					
						
							|  |  |  |     if (vm.exception()) | 
					
						
							|  |  |  |         return {}; | 
					
						
							|  |  |  |     if (has_instance_method) { | 
					
						
							|  |  |  |         auto has_instance_result = vm.call(*has_instance_method, rhs, lhs); | 
					
						
							| 
									
										
										
										
											2020-11-03 17:54:57 +00:00
										 |  |  |         if (vm.exception()) | 
					
						
							|  |  |  |             return {}; | 
					
						
							|  |  |  |         return Value(has_instance_result.to_boolean()); | 
					
						
							| 
									
										
										
										
											2020-07-11 15:27:28 -07:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2020-08-25 12:52:32 +02:00
										 |  |  |     if (!rhs.is_function()) { | 
					
						
							| 
									
										
										
										
											2020-10-04 13:55:20 +01:00
										 |  |  |         vm.throw_exception<TypeError>(global_object, ErrorType::NotAFunction, rhs.to_string_without_side_effects()); | 
					
						
							| 
									
										
										
										
											2020-08-25 12:52:32 +02:00
										 |  |  |         return {}; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2020-09-27 18:36:49 +02:00
										 |  |  |     return ordinary_has_instance(global_object, lhs, rhs); | 
					
						
							| 
									
										
										
										
											2020-07-11 15:27:28 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-27 18:36:49 +02:00
										 |  |  | Value ordinary_has_instance(GlobalObject& global_object, Value lhs, Value rhs) | 
					
						
							| 
									
										
										
										
											2020-07-11 15:27:28 -07:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2020-09-27 18:36:49 +02:00
										 |  |  |     auto& vm = global_object.vm(); | 
					
						
							| 
									
										
										
										
											2020-07-11 15:27:28 -07:00
										 |  |  |     if (!rhs.is_function()) | 
					
						
							|  |  |  |         return Value(false); | 
					
						
							|  |  |  |     auto& rhs_function = rhs.as_function(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-01 17:46:39 +01:00
										 |  |  |     if (is<BoundFunction>(rhs_function)) { | 
					
						
							|  |  |  |         auto& bound_target = static_cast<const BoundFunction&>(rhs_function); | 
					
						
							| 
									
										
										
										
											2020-09-27 18:36:49 +02:00
										 |  |  |         return instance_of(global_object, lhs, Value(&bound_target.target_function())); | 
					
						
							| 
									
										
										
										
											2020-07-11 15:27:28 -07:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!lhs.is_object()) | 
					
						
							| 
									
										
										
										
											2020-05-07 17:09:00 -07:00
										 |  |  |         return Value(false); | 
					
						
							| 
									
										
										
										
											2020-07-11 15:27:28 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |     Object* lhs_object = &lhs.as_object(); | 
					
						
							| 
									
										
										
										
											2020-10-13 23:49:19 +02:00
										 |  |  |     auto rhs_prototype = rhs_function.get(vm.names.prototype); | 
					
						
							| 
									
										
										
										
											2020-09-27 18:36:49 +02:00
										 |  |  |     if (vm.exception()) | 
					
						
							| 
									
										
										
										
											2020-06-07 10:53:14 -07:00
										 |  |  |         return {}; | 
					
						
							| 
									
										
										
										
											2020-07-11 15:27:28 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-25 12:52:32 +02:00
										 |  |  |     if (!rhs_prototype.is_object()) { | 
					
						
							| 
									
										
										
										
											2020-11-03 17:54:57 +00:00
										 |  |  |         vm.throw_exception<TypeError>(global_object, ErrorType::InstanceOfOperatorBadPrototype, rhs.to_string_without_side_effects()); | 
					
						
							| 
									
										
										
										
											2020-08-25 12:52:32 +02:00
										 |  |  |         return {}; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2020-07-11 15:27:28 -07:00
										 |  |  |     while (true) { | 
					
						
							|  |  |  |         lhs_object = lhs_object->prototype(); | 
					
						
							| 
									
										
										
										
											2020-09-27 18:36:49 +02:00
										 |  |  |         if (vm.exception()) | 
					
						
							| 
									
										
										
										
											2020-07-11 15:27:28 -07:00
										 |  |  |             return {}; | 
					
						
							|  |  |  |         if (!lhs_object) | 
					
						
							|  |  |  |             return Value(false); | 
					
						
							| 
									
										
										
										
											2020-09-27 18:36:49 +02:00
										 |  |  |         if (same_value(rhs_prototype, lhs_object)) | 
					
						
							| 
									
										
										
										
											2020-07-11 15:27:28 -07:00
										 |  |  |             return Value(true); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2020-05-07 17:09:00 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-27 18:36:49 +02:00
										 |  |  | bool same_value(Value lhs, Value rhs) | 
					
						
							| 
									
										
										
										
											2020-05-07 17:09:00 -07:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2021-03-21 18:03:00 +01:00
										 |  |  |     if (!same_type_for_equality(lhs, rhs)) | 
					
						
							| 
									
										
										
										
											2020-05-07 17:09:00 -07:00
										 |  |  |         return false; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (lhs.is_number()) { | 
					
						
							|  |  |  |         if (lhs.is_nan() && rhs.is_nan()) | 
					
						
							|  |  |  |             return true; | 
					
						
							|  |  |  |         if (lhs.is_positive_zero() && rhs.is_negative_zero()) | 
					
						
							|  |  |  |             return false; | 
					
						
							|  |  |  |         if (lhs.is_negative_zero() && rhs.is_positive_zero()) | 
					
						
							|  |  |  |             return false; | 
					
						
							| 
									
										
										
										
											2020-05-18 00:28:00 +01:00
										 |  |  |         return lhs.as_double() == rhs.as_double(); | 
					
						
							| 
									
										
										
										
											2020-05-07 17:09:00 -07:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-06 01:14:10 +01:00
										 |  |  |     if (lhs.is_bigint()) { | 
					
						
							|  |  |  |         auto lhs_big_integer = lhs.as_bigint().big_integer(); | 
					
						
							|  |  |  |         auto rhs_big_integer = rhs.as_bigint().big_integer(); | 
					
						
							|  |  |  |         if (lhs_big_integer == BIGINT_ZERO && rhs_big_integer == BIGINT_ZERO && lhs_big_integer.is_negative() != rhs_big_integer.is_negative()) | 
					
						
							|  |  |  |             return false; | 
					
						
							|  |  |  |         return lhs_big_integer == rhs_big_integer; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-27 18:36:49 +02:00
										 |  |  |     return same_value_non_numeric(lhs, rhs); | 
					
						
							| 
									
										
										
										
											2020-05-07 17:09:00 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-27 18:36:49 +02:00
										 |  |  | bool same_value_zero(Value lhs, Value rhs) | 
					
						
							| 
									
										
										
										
											2020-05-07 17:09:00 -07:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2021-03-21 18:03:00 +01:00
										 |  |  |     if (!same_type_for_equality(lhs, rhs)) | 
					
						
							| 
									
										
										
										
											2020-05-07 17:09:00 -07:00
										 |  |  |         return false; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (lhs.is_number()) { | 
					
						
							|  |  |  |         if (lhs.is_nan() && rhs.is_nan()) | 
					
						
							|  |  |  |             return true; | 
					
						
							| 
									
										
										
										
											2020-05-18 00:28:00 +01:00
										 |  |  |         return lhs.as_double() == rhs.as_double(); | 
					
						
							| 
									
										
										
										
											2020-05-07 17:09:00 -07:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-06 01:14:10 +01:00
										 |  |  |     if (lhs.is_bigint()) | 
					
						
							|  |  |  |         return lhs.as_bigint().big_integer() == rhs.as_bigint().big_integer(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-27 18:36:49 +02:00
										 |  |  |     return same_value_non_numeric(lhs, rhs); | 
					
						
							| 
									
										
										
										
											2020-05-07 17:09:00 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-27 18:36:49 +02:00
										 |  |  | bool same_value_non_numeric(Value lhs, Value rhs) | 
					
						
							| 
									
										
										
										
											2020-05-07 17:09:00 -07:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2021-02-23 20:42:32 +01:00
										 |  |  |     VERIFY(!lhs.is_number() && !lhs.is_bigint()); | 
					
						
							| 
									
										
										
										
											2021-03-21 18:03:00 +01:00
										 |  |  |     VERIFY(same_type_for_equality(lhs, rhs)); | 
					
						
							| 
									
										
										
										
											2020-05-07 17:09:00 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-11 12:16:26 +01:00
										 |  |  |     switch (lhs.type()) { | 
					
						
							|  |  |  |     case Value::Type::Undefined: | 
					
						
							|  |  |  |     case Value::Type::Null: | 
					
						
							| 
									
										
										
										
											2020-05-07 17:09:00 -07:00
										 |  |  |         return true; | 
					
						
							| 
									
										
										
										
											2020-03-11 12:16:26 +01:00
										 |  |  |     case Value::Type::String: | 
					
						
							| 
									
										
										
										
											2020-05-07 17:09:00 -07:00
										 |  |  |         return lhs.as_string().string() == rhs.as_string().string(); | 
					
						
							| 
									
										
										
										
											2020-04-29 23:25:21 -07:00
										 |  |  |     case Value::Type::Symbol: | 
					
						
							|  |  |  |         return &lhs.as_symbol() == &rhs.as_symbol(); | 
					
						
							| 
									
										
										
										
											2020-03-11 12:16:26 +01:00
										 |  |  |     case Value::Type::Boolean: | 
					
						
							| 
									
										
										
										
											2020-05-07 17:09:00 -07:00
										 |  |  |         return lhs.as_bool() == rhs.as_bool(); | 
					
						
							| 
									
										
										
										
											2020-03-11 12:16:26 +01:00
										 |  |  |     case Value::Type::Object: | 
					
						
							| 
									
										
										
										
											2020-05-07 17:09:00 -07:00
										 |  |  |         return &lhs.as_object() == &rhs.as_object(); | 
					
						
							|  |  |  |     default: | 
					
						
							| 
									
										
										
										
											2021-02-23 20:42:32 +01:00
										 |  |  |         VERIFY_NOT_REACHED(); | 
					
						
							| 
									
										
										
										
											2020-03-11 12:16:26 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-27 18:36:49 +02:00
										 |  |  | bool strict_eq(Value lhs, Value rhs) | 
					
						
							| 
									
										
										
										
											2020-03-16 00:23:38 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2021-03-21 18:03:00 +01:00
										 |  |  |     if (!same_type_for_equality(lhs, rhs)) | 
					
						
							| 
									
										
										
										
											2020-05-07 17:09:00 -07:00
										 |  |  |         return false; | 
					
						
							| 
									
										
										
										
											2020-03-16 00:23:38 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-07 17:09:00 -07:00
										 |  |  |     if (lhs.is_number()) { | 
					
						
							|  |  |  |         if (lhs.is_nan() || rhs.is_nan()) | 
					
						
							|  |  |  |             return false; | 
					
						
							| 
									
										
										
										
											2020-05-18 00:28:00 +01:00
										 |  |  |         if (lhs.as_double() == rhs.as_double()) | 
					
						
							| 
									
										
										
										
											2020-05-07 17:09:00 -07:00
										 |  |  |             return true; | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2020-03-16 00:23:38 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-06 01:14:10 +01:00
										 |  |  |     if (lhs.is_bigint()) | 
					
						
							|  |  |  |         return lhs.as_bigint().big_integer() == rhs.as_bigint().big_integer(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-27 18:36:49 +02:00
										 |  |  |     return same_value_non_numeric(lhs, rhs); | 
					
						
							| 
									
										
										
										
											2020-05-07 17:09:00 -07:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2020-03-16 00:23:38 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-27 19:52:47 +02:00
										 |  |  | bool abstract_eq(GlobalObject& global_object, Value lhs, Value rhs) | 
					
						
							| 
									
										
										
										
											2020-05-07 17:09:00 -07:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2021-03-21 18:03:00 +01:00
										 |  |  |     if (same_type_for_equality(lhs, rhs)) | 
					
						
							| 
									
										
										
										
											2020-09-27 18:36:49 +02:00
										 |  |  |         return strict_eq(lhs, rhs); | 
					
						
							| 
									
										
										
										
											2020-03-16 00:23:38 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-02 16:00:15 +02:00
										 |  |  |     if (lhs.is_nullish() && rhs.is_nullish()) | 
					
						
							| 
									
										
										
										
											2020-05-07 17:09:00 -07:00
										 |  |  |         return true; | 
					
						
							| 
									
										
										
										
											2020-03-16 00:23:38 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-07 17:09:00 -07:00
										 |  |  |     if (lhs.is_number() && rhs.is_string()) | 
					
						
							| 
									
										
										
										
											2021-03-16 22:00:46 +01:00
										 |  |  |         return abstract_eq(global_object, lhs, rhs.to_number(global_object)); | 
					
						
							| 
									
										
										
										
											2020-03-16 00:23:38 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-07 17:09:00 -07:00
										 |  |  |     if (lhs.is_string() && rhs.is_number()) | 
					
						
							| 
									
										
										
										
											2021-03-16 22:00:46 +01:00
										 |  |  |         return abstract_eq(global_object, lhs.to_number(global_object), rhs); | 
					
						
							| 
									
										
										
										
											2020-04-23 16:06:01 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-06 01:14:10 +01:00
										 |  |  |     if (lhs.is_bigint() && rhs.is_string()) { | 
					
						
							|  |  |  |         auto& rhs_string = rhs.as_string().string(); | 
					
						
							|  |  |  |         if (!is_valid_bigint_value(rhs_string)) | 
					
						
							|  |  |  |             return false; | 
					
						
							| 
									
										
										
										
											2020-09-27 19:52:47 +02:00
										 |  |  |         return abstract_eq(global_object, lhs, js_bigint(global_object.heap(), Crypto::SignedBigInteger::from_base10(rhs_string))); | 
					
						
							| 
									
										
										
										
											2020-06-06 01:14:10 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (lhs.is_string() && rhs.is_bigint()) | 
					
						
							| 
									
										
										
										
											2020-09-27 19:52:47 +02:00
										 |  |  |         return abstract_eq(global_object, rhs, lhs); | 
					
						
							| 
									
										
										
										
											2020-06-06 01:14:10 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-07 17:09:00 -07:00
										 |  |  |     if (lhs.is_boolean()) | 
					
						
							| 
									
										
										
										
											2021-03-16 22:00:46 +01:00
										 |  |  |         return abstract_eq(global_object, lhs.to_number(global_object), rhs); | 
					
						
							| 
									
										
										
										
											2020-04-23 16:06:01 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-07 17:09:00 -07:00
										 |  |  |     if (rhs.is_boolean()) | 
					
						
							| 
									
										
										
										
											2021-03-16 22:00:46 +01:00
										 |  |  |         return abstract_eq(global_object, lhs, rhs.to_number(global_object)); | 
					
						
							| 
									
										
										
										
											2020-03-28 16:56:54 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-02 19:22:36 +01:00
										 |  |  |     if ((lhs.is_string() || lhs.is_number() || lhs.is_bigint() || lhs.is_symbol()) && rhs.is_object()) { | 
					
						
							|  |  |  |         auto rhs_primitive = rhs.to_primitive(global_object); | 
					
						
							|  |  |  |         if (global_object.vm().exception()) | 
					
						
							|  |  |  |             return false; | 
					
						
							|  |  |  |         return abstract_eq(global_object, lhs, rhs_primitive); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2020-03-28 16:56:54 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-02 19:22:36 +01:00
										 |  |  |     if (lhs.is_object() && (rhs.is_string() || rhs.is_number() || lhs.is_bigint() || rhs.is_symbol())) { | 
					
						
							|  |  |  |         auto lhs_primitive = lhs.to_primitive(global_object); | 
					
						
							|  |  |  |         if (global_object.vm().exception()) | 
					
						
							|  |  |  |             return false; | 
					
						
							|  |  |  |         return abstract_eq(global_object, lhs_primitive, rhs); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2020-03-28 16:56:54 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-06 01:14:10 +01:00
										 |  |  |     if ((lhs.is_bigint() && rhs.is_number()) || (lhs.is_number() && rhs.is_bigint())) { | 
					
						
							|  |  |  |         if (lhs.is_nan() || lhs.is_infinity() || rhs.is_nan() || rhs.is_infinity()) | 
					
						
							|  |  |  |             return false; | 
					
						
							|  |  |  |         if ((lhs.is_number() && !lhs.is_integer()) || (rhs.is_number() && !rhs.is_integer())) | 
					
						
							|  |  |  |             return false; | 
					
						
							|  |  |  |         if (lhs.is_number()) | 
					
						
							| 
									
										
										
										
											2021-03-16 22:00:46 +01:00
										 |  |  |             return Crypto::SignedBigInteger { lhs.to_i32(global_object) } == rhs.as_bigint().big_integer(); | 
					
						
							| 
									
										
										
										
											2020-06-06 01:14:10 +01:00
										 |  |  |         else | 
					
						
							| 
									
										
										
										
											2021-03-16 22:00:46 +01:00
										 |  |  |             return Crypto::SignedBigInteger { rhs.to_i32(global_object) } == lhs.as_bigint().big_integer(); | 
					
						
							| 
									
										
										
										
											2020-06-06 01:14:10 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-07 17:09:00 -07:00
										 |  |  |     return false; | 
					
						
							| 
									
										
										
										
											2020-03-07 21:43:10 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-27 19:52:47 +02:00
										 |  |  | TriState abstract_relation(GlobalObject& global_object, bool left_first, Value lhs, Value rhs) | 
					
						
							| 
									
										
										
										
											2020-05-28 17:19:59 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2020-06-06 01:14:10 +01:00
										 |  |  |     Value x_primitive; | 
					
						
							|  |  |  |     Value y_primitive; | 
					
						
							| 
									
										
										
										
											2020-05-28 17:19:59 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (left_first) { | 
					
						
							| 
									
										
										
										
											2021-03-02 19:22:36 +01:00
										 |  |  |         x_primitive = lhs.to_primitive(global_object, Value::PreferredType::Number); | 
					
						
							| 
									
										
										
										
											2020-09-27 19:52:47 +02:00
										 |  |  |         if (global_object.vm().exception()) | 
					
						
							| 
									
										
										
										
											2020-05-28 17:19:59 +02:00
										 |  |  |             return {}; | 
					
						
							| 
									
										
										
										
											2021-03-02 19:22:36 +01:00
										 |  |  |         y_primitive = rhs.to_primitive(global_object, Value::PreferredType::Number); | 
					
						
							| 
									
										
										
										
											2020-09-27 19:52:47 +02:00
										 |  |  |         if (global_object.vm().exception()) | 
					
						
							| 
									
										
										
										
											2020-05-28 17:19:59 +02:00
										 |  |  |             return {}; | 
					
						
							|  |  |  |     } else { | 
					
						
							| 
									
										
										
										
											2021-03-02 19:22:36 +01:00
										 |  |  |         y_primitive = lhs.to_primitive(global_object, Value::PreferredType::Number); | 
					
						
							| 
									
										
										
										
											2020-09-27 19:52:47 +02:00
										 |  |  |         if (global_object.vm().exception()) | 
					
						
							| 
									
										
										
										
											2020-05-28 17:19:59 +02:00
										 |  |  |             return {}; | 
					
						
							| 
									
										
										
										
											2021-03-02 19:22:36 +01:00
										 |  |  |         x_primitive = rhs.to_primitive(global_object, Value::PreferredType::Number); | 
					
						
							| 
									
										
										
										
											2020-09-27 19:52:47 +02:00
										 |  |  |         if (global_object.vm().exception()) | 
					
						
							| 
									
										
										
										
											2020-05-28 17:19:59 +02:00
										 |  |  |             return {}; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (x_primitive.is_string() && y_primitive.is_string()) { | 
					
						
							|  |  |  |         auto x_string = x_primitive.as_string().string(); | 
					
						
							|  |  |  |         auto y_string = y_primitive.as_string().string(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (x_string.starts_with(y_string)) | 
					
						
							|  |  |  |             return TriState::False; | 
					
						
							|  |  |  |         if (y_string.starts_with(x_string)) | 
					
						
							|  |  |  |             return TriState::True; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-05 16:31:20 -04:00
										 |  |  |         Utf8View x_code_points { x_string }; | 
					
						
							|  |  |  |         Utf8View y_code_points { y_string }; | 
					
						
							|  |  |  |         for (auto k = x_code_points.begin(), l = y_code_points.begin(); | 
					
						
							|  |  |  |              k != x_code_points.end() && l != y_code_points.end(); | 
					
						
							| 
									
										
										
										
											2020-05-28 17:19:59 +02:00
										 |  |  |              ++k, ++l) { | 
					
						
							|  |  |  |             if (*k != *l) { | 
					
						
							|  |  |  |                 if (*k < *l) { | 
					
						
							|  |  |  |                     return TriState::True; | 
					
						
							|  |  |  |                 } else { | 
					
						
							|  |  |  |                     return TriState::False; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2021-02-23 20:42:32 +01:00
										 |  |  |         VERIFY_NOT_REACHED(); | 
					
						
							| 
									
										
										
										
											2020-05-28 17:19:59 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-06 01:14:10 +01:00
										 |  |  |     if (x_primitive.is_bigint() && y_primitive.is_string()) { | 
					
						
							|  |  |  |         auto& y_string = y_primitive.as_string().string(); | 
					
						
							|  |  |  |         if (!is_valid_bigint_value(y_string)) | 
					
						
							|  |  |  |             return TriState::Unknown; | 
					
						
							|  |  |  |         if (x_primitive.as_bigint().big_integer() < Crypto::SignedBigInteger::from_base10(y_string)) | 
					
						
							|  |  |  |             return TriState::True; | 
					
						
							|  |  |  |         else | 
					
						
							|  |  |  |             return TriState::False; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2020-05-28 17:19:59 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-06 01:14:10 +01:00
										 |  |  |     if (x_primitive.is_string() && y_primitive.is_bigint()) { | 
					
						
							|  |  |  |         auto& x_string = x_primitive.as_string().string(); | 
					
						
							|  |  |  |         if (!is_valid_bigint_value(x_string)) | 
					
						
							|  |  |  |             return TriState::Unknown; | 
					
						
							|  |  |  |         if (Crypto::SignedBigInteger::from_base10(x_string) < y_primitive.as_bigint().big_integer()) | 
					
						
							|  |  |  |             return TriState::True; | 
					
						
							|  |  |  |         else | 
					
						
							|  |  |  |             return TriState::False; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-16 22:00:46 +01:00
										 |  |  |     auto x_numeric = x_primitive.to_numeric(global_object); | 
					
						
							| 
									
										
										
										
											2020-09-27 19:52:47 +02:00
										 |  |  |     if (global_object.vm().exception()) | 
					
						
							| 
									
										
										
										
											2020-05-28 17:19:59 +02:00
										 |  |  |         return {}; | 
					
						
							| 
									
										
										
										
											2021-03-16 22:00:46 +01:00
										 |  |  |     auto y_numeric = y_primitive.to_numeric(global_object); | 
					
						
							| 
									
										
										
										
											2020-09-27 19:52:47 +02:00
										 |  |  |     if (global_object.vm().exception()) | 
					
						
							| 
									
										
										
										
											2020-05-28 17:19:59 +02:00
										 |  |  |         return {}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (x_numeric.is_nan() || y_numeric.is_nan()) | 
					
						
							|  |  |  |         return TriState::Unknown; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (x_numeric.is_positive_infinity() || y_numeric.is_negative_infinity()) | 
					
						
							|  |  |  |         return TriState::False; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (x_numeric.is_negative_infinity() || y_numeric.is_positive_infinity()) | 
					
						
							|  |  |  |         return TriState::True; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-06 01:14:10 +01:00
										 |  |  |     if (x_numeric.is_number() && y_numeric.is_number()) { | 
					
						
							|  |  |  |         if (x_numeric.as_double() < y_numeric.as_double()) | 
					
						
							|  |  |  |             return TriState::True; | 
					
						
							|  |  |  |         else | 
					
						
							|  |  |  |             return TriState::False; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2020-05-28 17:19:59 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-06 01:14:10 +01:00
										 |  |  |     if (x_numeric.is_bigint() && y_numeric.is_bigint()) { | 
					
						
							|  |  |  |         if (x_numeric.as_bigint().big_integer() < y_numeric.as_bigint().big_integer()) | 
					
						
							|  |  |  |             return TriState::True; | 
					
						
							|  |  |  |         else | 
					
						
							|  |  |  |             return TriState::False; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-23 20:42:32 +01:00
										 |  |  |     VERIFY((x_numeric.is_number() && y_numeric.is_bigint()) || (x_numeric.is_bigint() && y_numeric.is_number())); | 
					
						
							| 
									
										
										
										
											2020-06-06 01:14:10 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     bool x_lower_than_y; | 
					
						
							|  |  |  |     if (x_numeric.is_number()) { | 
					
						
							|  |  |  |         x_lower_than_y = x_numeric.is_integer() | 
					
						
							| 
									
										
										
										
											2021-03-16 22:00:46 +01:00
										 |  |  |             ? Crypto::SignedBigInteger { x_numeric.to_i32(global_object) } < y_numeric.as_bigint().big_integer() | 
					
						
							|  |  |  |             : (Crypto::SignedBigInteger { x_numeric.to_i32(global_object) } < y_numeric.as_bigint().big_integer() || Crypto::SignedBigInteger { x_numeric.to_i32(global_object) + 1 } < y_numeric.as_bigint().big_integer()); | 
					
						
							| 
									
										
										
										
											2020-06-06 01:14:10 +01:00
										 |  |  |     } else { | 
					
						
							|  |  |  |         x_lower_than_y = y_numeric.is_integer() | 
					
						
							| 
									
										
										
										
											2021-03-16 22:00:46 +01:00
										 |  |  |             ? x_numeric.as_bigint().big_integer() < Crypto::SignedBigInteger { y_numeric.to_i32(global_object) } | 
					
						
							|  |  |  |             : (x_numeric.as_bigint().big_integer() < Crypto::SignedBigInteger { y_numeric.to_i32(global_object) } || x_numeric.as_bigint().big_integer() < Crypto::SignedBigInteger { y_numeric.to_i32(global_object) + 1 }); | 
					
						
							| 
									
										
										
										
											2020-06-06 01:14:10 +01:00
										 |  |  |     } | 
					
						
							|  |  |  |     if (x_lower_than_y) | 
					
						
							| 
									
										
										
										
											2020-05-28 17:19:59 +02:00
										 |  |  |         return TriState::True; | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |         return TriState::False; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-02 18:04:13 +01:00
										 |  |  | Function* get_method(GlobalObject& global_object, Value value, const PropertyName& property_name) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     // 7.3.10 GetMethod, https://tc39.es/ecma262/#sec-getmethod
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     auto& vm = global_object.vm(); | 
					
						
							|  |  |  |     auto* object = value.to_object(global_object); | 
					
						
							|  |  |  |     if (vm.exception()) | 
					
						
							|  |  |  |         return nullptr; | 
					
						
							|  |  |  |     auto property_value = object->get(property_name); | 
					
						
							|  |  |  |     if (vm.exception()) | 
					
						
							|  |  |  |         return nullptr; | 
					
						
							|  |  |  |     if (property_value.is_empty() || property_value.is_nullish()) | 
					
						
							|  |  |  |         return nullptr; | 
					
						
							|  |  |  |     if (!property_value.is_function()) { | 
					
						
							|  |  |  |         vm.throw_exception<TypeError>(global_object, ErrorType::NotAFunction, property_value.to_string_without_side_effects()); | 
					
						
							|  |  |  |         return nullptr; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return &property_value.as_function(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-10 14:08:27 +01:00
										 |  |  | size_t length_of_array_like(GlobalObject& global_object, const Object& object) | 
					
						
							| 
									
										
										
										
											2020-06-10 11:01:00 -07:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2021-01-10 14:08:27 +01:00
										 |  |  |     // 7.3.18 LengthOfArrayLike, https://tc39.es/ecma262/#sec-lengthofarraylike
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-13 23:49:19 +02:00
										 |  |  |     auto& vm = global_object.vm(); | 
					
						
							| 
									
										
										
										
											2021-01-10 14:08:27 +01:00
										 |  |  |     auto result = object.get(vm.names.length).value_or(js_undefined()); | 
					
						
							| 
									
										
										
										
											2020-10-13 23:49:19 +02:00
										 |  |  |     if (vm.exception()) | 
					
						
							| 
									
										
										
										
											2021-01-10 14:08:27 +01:00
										 |  |  |         return INVALID; | 
					
						
							|  |  |  |     return result.to_length(global_object); | 
					
						
							| 
									
										
										
										
											2020-06-10 11:01:00 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-07 19:42:11 +01:00
										 |  |  | } |