diff --git a/Libraries/LibJS/Runtime/ArrayPrototype.cpp b/Libraries/LibJS/Runtime/ArrayPrototype.cpp index fab8073fd7b..8b155e9a95e 100644 --- a/Libraries/LibJS/Runtime/ArrayPrototype.cpp +++ b/Libraries/LibJS/Runtime/ArrayPrototype.cpp @@ -107,21 +107,13 @@ static Function* callback_from_args(GlobalObject& global_object, const String& n return &callback.as_function(); } -static size_t get_length(VM& vm, Object& object) -{ - auto length_property = object.get(vm.names.length); - if (vm.exception()) - return 0; - return length_property.to_size_t(object.global_object()); -} - static void for_each_item(VM& vm, GlobalObject& global_object, const String& name, AK::Function callback, bool skip_empty = true) { auto* this_object = vm.this_value(global_object).to_object(global_object); if (!this_object) return; - auto initial_length = get_length(vm, *this_object); + auto initial_length = length_of_array_like(global_object, *this_object); if (vm.exception()) return; @@ -174,7 +166,7 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::map) auto* this_object = vm.this_value(global_object).to_object(global_object); if (!this_object) return {}; - auto initial_length = get_length(vm, *this_object); + auto initial_length = length_of_array_like(global_object, *this_object); if (vm.exception()) return {}; auto* new_array = Array::create(global_object); @@ -199,7 +191,7 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::push) array->indexed_properties().append(vm.argument(i)); return Value(static_cast(array->indexed_properties().array_like_size())); } - auto length = get_length(vm, *this_object); + auto length = length_of_array_like(global_object, *this_object); if (vm.exception()) return {}; auto argument_count = vm.argument_count(); @@ -241,7 +233,9 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::pop) return js_undefined(); return array->indexed_properties().take_last(array).value.value_or(js_undefined()); } - auto length = get_length(vm, *this_object); + auto length = length_of_array_like(global_object, *this_object); + if (vm.exception()) + return {}; if (length == 0) { this_object->put(vm.names.length, Value(0)); return js_undefined(); @@ -298,7 +292,7 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::to_locale_string) s_array_join_seen_objects.remove(this_object); }; - auto length = get_length(vm, *this_object); + auto length = length_of_array_like(global_object, *this_object); if (vm.exception()) return {}; @@ -342,7 +336,7 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::join) s_array_join_seen_objects.remove(this_object); }; - auto length = get_length(vm, *this_object); + auto length = length_of_array_like(global_object, *this_object); if (vm.exception()) return {}; String separator = ","; @@ -445,7 +439,7 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::index_of) auto* this_object = vm.this_value(global_object).to_object(global_object); if (!this_object) return {}; - i32 length = get_length(vm, *this_object); + i32 length = length_of_array_like(global_object, *this_object); if (vm.exception()) return {}; if (length == 0) @@ -477,7 +471,7 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::reduce) if (!this_object) return {}; - auto initial_length = get_length(vm, *this_object); + auto initial_length = length_of_array_like(global_object, *this_object); if (vm.exception()) return {}; @@ -530,7 +524,7 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::reduce_right) if (!this_object) return {}; - auto initial_length = get_length(vm, *this_object); + auto initial_length = length_of_array_like(global_object, *this_object); if (vm.exception()) return {}; @@ -720,7 +714,7 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::sort) return {}; } - auto original_length = get_length(vm, *array); + auto original_length = length_of_array_like(global_object, *array); if (vm.exception()) return {}; @@ -767,7 +761,7 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::last_index_of) auto* this_object = vm.this_value(global_object).to_object(global_object); if (!this_object) return {}; - i32 length = get_length(vm, *this_object); + i32 length = length_of_array_like(global_object, *this_object); if (vm.exception()) return {}; if (length == 0) @@ -798,7 +792,7 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::includes) auto* this_object = vm.this_value(global_object).to_object(global_object); if (!this_object) return {}; - i32 length = get_length(vm, *this_object); + i32 length = length_of_array_like(global_object, *this_object); if (vm.exception()) return {}; if (length == 0) @@ -886,7 +880,7 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::splice) if (!this_object) return {}; - auto initial_length = get_length(vm, *this_object); + auto initial_length = length_of_array_like(global_object, *this_object); if (vm.exception()) return {}; @@ -991,7 +985,7 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::fill) if (!this_object) return {}; - ssize_t length = get_length(vm, *this_object); + ssize_t length = length_of_array_like(global_object, *this_object); if (vm.exception()) return {}; diff --git a/Libraries/LibJS/Runtime/FunctionPrototype.cpp b/Libraries/LibJS/Runtime/FunctionPrototype.cpp index 515b7fcc416..972c5021ead 100644 --- a/Libraries/LibJS/Runtime/FunctionPrototype.cpp +++ b/Libraries/LibJS/Runtime/FunctionPrototype.cpp @@ -80,10 +80,7 @@ JS_DEFINE_NATIVE_FUNCTION(FunctionPrototype::apply) vm.throw_exception(global_object, ErrorType::FunctionArgsNotObject); return {}; } - auto length_property = arg_array.as_object().get(vm.names.length); - if (vm.exception()) - return {}; - auto length = length_property.to_size_t(global_object); + auto length = length_of_array_like(global_object, arg_array.as_object()); if (vm.exception()) return {}; MarkedValueList arguments(vm.heap()); diff --git a/Libraries/LibJS/Runtime/ReflectObject.cpp b/Libraries/LibJS/Runtime/ReflectObject.cpp index 0ee99be2df2..1b7865cc8e1 100644 --- a/Libraries/LibJS/Runtime/ReflectObject.cpp +++ b/Libraries/LibJS/Runtime/ReflectObject.cpp @@ -63,10 +63,7 @@ static void prepare_arguments_list(GlobalObject& global_object, Value value, Mar return; } auto& arguments_list = value.as_object(); - auto length_property = arguments_list.get(vm.names.length); - if (vm.exception()) - return; - auto length = length_property.to_size_t(global_object); + auto length = length_of_array_like(global_object, arguments_list); if (vm.exception()) return; for (size_t i = 0; i < length; ++i) { diff --git a/Libraries/LibJS/Runtime/StringPrototype.cpp b/Libraries/LibJS/Runtime/StringPrototype.cpp index 7fa5292e895..640a9626627 100644 --- a/Libraries/LibJS/Runtime/StringPrototype.cpp +++ b/Libraries/LibJS/Runtime/StringPrototype.cpp @@ -152,20 +152,17 @@ JS_DEFINE_NATIVE_FUNCTION(StringPrototype::repeat) return {}; if (!vm.argument_count()) return js_string(vm, String::empty()); - auto count_value = vm.argument(0).to_number(global_object); + auto count = vm.argument(0).to_integer_or_infinity(global_object); if (vm.exception()) return {}; - if (count_value.as_double() < 0) { + if (count < 0) { vm.throw_exception(global_object, ErrorType::StringRepeatCountMustBe, "positive"); return {}; } - if (count_value.is_infinity()) { + if (Value(count).is_infinity()) { vm.throw_exception(global_object, ErrorType::StringRepeatCountMustBe, "finite"); return {}; } - auto count = count_value.to_size_t(global_object); - if (vm.exception()) - return {}; StringBuilder builder; for (size_t i = 0; i < count; ++i) builder.append(string); @@ -185,12 +182,11 @@ JS_DEFINE_NATIVE_FUNCTION(StringPrototype::starts_with) auto string_length = string.length(); auto search_string_length = search_string.length(); size_t start = 0; - if (vm.argument_count() > 1) { - auto number = vm.argument(1).to_number(global_object); + if (!vm.argument(1).is_undefined()) { + auto position = vm.argument(1).to_integer_or_infinity(global_object); if (vm.exception()) return {}; - if (!number.is_nan()) - start = min(number.to_size_t(global_object), string_length); + start = clamp(position, static_cast(0), static_cast(string_length)); } if (start + search_string_length > string_length) return Value(false); @@ -226,10 +222,7 @@ JS_DEFINE_NATIVE_FUNCTION(StringPrototype::ends_with) auto end_position_value = vm.argument(1); if (!end_position_value.is_undefined()) { - auto number = end_position_value.to_number(global_object); - if (vm.exception()) - return {}; - double pos_as_double = number.to_integer_or_infinity(global_object); + double pos_as_double = end_position_value.to_integer_or_infinity(global_object); if (vm.exception()) return {}; pos = clamp(pos_as_double, static_cast(0), static_cast(string_length)); @@ -295,7 +288,7 @@ enum class PadPlacement { static Value pad_string(GlobalObject& global_object, const String& string, PadPlacement placement) { auto& vm = global_object.vm(); - auto max_length = vm.argument(0).to_size_t(global_object); + auto max_length = vm.argument(0).to_length(global_object); if (vm.exception()) return {}; if (max_length <= string.length()) @@ -389,15 +382,17 @@ JS_DEFINE_NATIVE_FUNCTION(StringPrototype::substring) // FIXME: index_start and index_end should index a UTF-16 code_point view of the string. auto string_length = string.length(); - auto index_start = min(vm.argument(0).to_size_t(global_object), string_length); + auto start = vm.argument(0).to_integer_or_infinity(global_object); if (vm.exception()) return {}; - auto index_end = string_length; - if (vm.argument_count() >= 2) { - index_end = min(vm.argument(1).to_size_t(global_object), string_length); + auto end = (double)string_length; + if (!vm.argument(1).is_undefined()) { + end = vm.argument(1).to_integer_or_infinity(global_object); if (vm.exception()) return {}; } + size_t index_start = clamp(start, static_cast(0), static_cast(string_length)); + size_t index_end = clamp(end, static_cast(0), static_cast(string_length)); if (index_start == index_end) return js_string(vm, String("")); @@ -457,22 +452,19 @@ JS_DEFINE_NATIVE_FUNCTION(StringPrototype::includes) auto search_string = vm.argument(0).to_string(global_object); if (vm.exception()) return {}; - - // FIXME: position should index a UTF-16 code_point view of the string. - size_t position = 0; - if (vm.argument_count() >= 2) { - position = vm.argument(1).to_size_t(global_object); + auto string_length = string.length(); + // FIXME: start should index a UTF-16 code_point view of the string. + size_t start = 0; + if (!vm.argument(1).is_undefined()) { + auto position = vm.argument(1).to_integer_or_infinity(global_object); if (vm.exception()) return {}; - if (position >= string.length()) - return Value(false); + start = clamp(position, static_cast(0), static_cast(string_length)); } - - if (position == 0) + if (start == 0) return Value(string.contains(search_string)); - - auto substring_length = string.length() - position; - auto substring_search = string.substring(position, substring_length); + auto substring_length = string_length - start; + auto substring_search = string.substring(start, substring_length); return Value(substring_search.contains(search_string)); } @@ -593,22 +585,22 @@ JS_DEFINE_NATIVE_FUNCTION(StringPrototype::last_index_of) auto string = ak_string_from(vm, global_object); if (string.is_null()) return {}; - - if (vm.argument_count() == 0) - return Value(-1); - auto search_string = vm.argument(0).to_string(global_object); + if (vm.exception()) + return {}; + auto position = vm.argument(1).to_number(global_object); if (vm.exception()) return {}; if (search_string.length() > string.length()) return Value(-1); auto max_index = string.length() - search_string.length(); auto from_index = max_index; - if (vm.argument_count() >= 2) { + if (!position.is_nan()) { // FIXME: from_index should index a UTF-16 code_point view of the string. - from_index = min(vm.argument(1).to_size_t(global_object), max_index); + auto p = position.to_integer_or_infinity(global_object); if (vm.exception()) return {}; + from_index = clamp(p, static_cast(0), static_cast(max_index)); } for (i32 i = from_index; i >= 0; --i) { diff --git a/Libraries/LibJS/Runtime/Value.cpp b/Libraries/LibJS/Runtime/Value.cpp index 194c8bcde6f..1d397c95366 100644 --- a/Libraries/LibJS/Runtime/Value.cpp +++ b/Libraries/LibJS/Runtime/Value.cpp @@ -513,21 +513,6 @@ u32 Value::to_u32(GlobalObject& global_object) const return number.as_u32(); } -size_t Value::to_size_t(GlobalObject& global_object) const -{ - // FIXME: Replace uses of this function with to_length/to_index for correct behaviour and remove this eventually. - if (is_empty()) - return 0; - auto number = to_number(global_object); - if (global_object.vm().exception()) - return INVALID; - if (number.is_nan()) - return 0; - if (number.as_double() <= 0) - return 0; - return number.as_size_t(); -} - size_t Value::to_length(GlobalObject& global_object) const { // 7.1.20 ToLength, https://tc39.es/ecma262/#sec-tolength diff --git a/Libraries/LibJS/Runtime/Value.h b/Libraries/LibJS/Runtime/Value.h index ca2a4e4c73d..a24db800573 100644 --- a/Libraries/LibJS/Runtime/Value.h +++ b/Libraries/LibJS/Runtime/Value.h @@ -256,7 +256,6 @@ public: double to_double(GlobalObject&) const; i32 to_i32(GlobalObject&) const; u32 to_u32(GlobalObject&) const; - size_t to_size_t(GlobalObject&) const; size_t to_length(GlobalObject&) const; size_t to_index(GlobalObject&) const; double to_integer_or_infinity(GlobalObject&) const;