From 9be0b664e33653aca30a4234f567928ddc9eb734 Mon Sep 17 00:00:00 2001 From: Linus Groh Date: Sun, 10 Jan 2021 14:08:27 +0100 Subject: [PATCH] LibJS: Make length_of_array_like() take an Object rather than Value The pseudo-code from the spec says "Assert: Type(obj) is Object.", so we can just enforce this at compile time rather than taking it literally and doing "ASSERT(value.is_object())". Also fix an issue where the absence of a "length" property on the object would cause a crash (to_number() on empty value). --- Libraries/LibJS/Runtime/JSONObject.cpp | 6 +++--- Libraries/LibJS/Runtime/Value.cpp | 11 ++++++----- Libraries/LibJS/Runtime/Value.h | 2 +- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/Libraries/LibJS/Runtime/JSONObject.cpp b/Libraries/LibJS/Runtime/JSONObject.cpp index e6a6f27aee..dddd82bfa0 100644 --- a/Libraries/LibJS/Runtime/JSONObject.cpp +++ b/Libraries/LibJS/Runtime/JSONObject.cpp @@ -70,7 +70,7 @@ String JSONObject::stringify_impl(GlobalObject& global_object, Value value, Valu state.replacer_function = &replacer.as_function(); } else if (replacer.is_array()) { auto& replacer_object = replacer.as_object(); - auto replacer_length = length_of_array_like(global_object, replacer); + auto replacer_length = length_of_array_like(global_object, replacer_object); if (vm.exception()) return {}; Vector list; @@ -298,7 +298,7 @@ String JSONObject::serialize_json_array(GlobalObject& global_object, StringifySt state.indent = String::formatted("{}{}", state.indent, state.gap); Vector property_strings; - auto length = length_of_array_like(global_object, Value(&object)); + auto length = length_of_array_like(global_object, object); if (vm.exception()) return {}; for (size_t i = 0; i < length; ++i) { @@ -476,7 +476,7 @@ Value JSONObject::internalize_json_property(GlobalObject& global_object, Object* }; if (value_object.is_array()) { - auto length = length_of_array_like(global_object, value); + auto length = length_of_array_like(global_object, value_object); for (size_t i = 0; i < length; ++i) { process_property(i); if (vm.exception()) diff --git a/Libraries/LibJS/Runtime/Value.cpp b/Libraries/LibJS/Runtime/Value.cpp index f5aea45e7c..194c8bcde6 100644 --- a/Libraries/LibJS/Runtime/Value.cpp +++ b/Libraries/LibJS/Runtime/Value.cpp @@ -1222,14 +1222,15 @@ TriState abstract_relation(GlobalObject& global_object, bool left_first, Value l return TriState::False; } -size_t length_of_array_like(GlobalObject& global_object, Value value) +size_t length_of_array_like(GlobalObject& global_object, const Object& object) { - ASSERT(value.is_object()); + // 7.3.18 LengthOfArrayLike, https://tc39.es/ecma262/#sec-lengthofarraylike + auto& vm = global_object.vm(); - auto result = value.as_object().get(vm.names.length); + auto result = object.get(vm.names.length).value_or(js_undefined()); if (vm.exception()) - return 0; - return result.to_size_t(global_object); + return INVALID; + return result.to_length(global_object); } } diff --git a/Libraries/LibJS/Runtime/Value.h b/Libraries/LibJS/Runtime/Value.h index 5cd209510d..ca2a4e4c73 100644 --- a/Libraries/LibJS/Runtime/Value.h +++ b/Libraries/LibJS/Runtime/Value.h @@ -341,7 +341,7 @@ bool same_value(Value lhs, Value rhs); bool same_value_zero(Value lhs, Value rhs); bool same_value_non_numeric(Value lhs, Value rhs); TriState abstract_relation(GlobalObject&, bool left_first, Value lhs, Value rhs); -size_t length_of_array_like(GlobalObject&, Value); +size_t length_of_array_like(GlobalObject&, const Object&); }