diff options
author | Idan Horowitz <idan.horowitz@gmail.com> | 2021-06-28 13:14:41 +0300 |
---|---|---|
committer | Linus Groh <mail@linusgroh.de> | 2021-06-28 13:27:13 +0100 |
commit | 596324ae9ccebea07304c1175d07943736ec2b73 (patch) | |
tree | 9572217a4c569624d2d99cc187ed53e4ed6294a3 /Userland/Libraries/LibJS/Runtime | |
parent | d1ffeaf66dc1bac23eec8144e7c963ca1ada76cb (diff) | |
download | serenity-596324ae9ccebea07304c1175d07943736ec2b73.zip |
LibJS: Rewrite String.raw() closer to the specification
This includes not throwing a custom exception and using the
length_of_array_like abstract operation where required.
Diffstat (limited to 'Userland/Libraries/LibJS/Runtime')
-rw-r--r-- | Userland/Libraries/LibJS/Runtime/ErrorTypes.h | 1 | ||||
-rw-r--r-- | Userland/Libraries/LibJS/Runtime/StringConstructor.cpp | 46 |
2 files changed, 28 insertions, 19 deletions
diff --git a/Userland/Libraries/LibJS/Runtime/ErrorTypes.h b/Userland/Libraries/LibJS/Runtime/ErrorTypes.h index 93434515ba..fd8477593e 100644 --- a/Userland/Libraries/LibJS/Runtime/ErrorTypes.h +++ b/Userland/Libraries/LibJS/Runtime/ErrorTypes.h @@ -150,7 +150,6 @@ M(SpeciesConstructorDidNotCreate, "Species constructor did not create {}") \ M(SpeciesConstructorReturned, "Species constructor returned {}") \ M(StringMatchAllNonGlobalRegExp, "RegExp argument is non-global") \ - M(StringRawCannotConvert, "Cannot convert property 'raw' to object from {}") \ M(StringRepeatCountMustBe, "repeat count must be a {} number") \ M(ThisHasNotBeenInitialized, "|this| has not been initialized") \ M(ThisIsAlreadyInitialized, "|this| is already initialized") \ diff --git a/Userland/Libraries/LibJS/Runtime/StringConstructor.cpp b/Userland/Libraries/LibJS/Runtime/StringConstructor.cpp index 7762f8c69e..c89bdd22af 100644 --- a/Userland/Libraries/LibJS/Runtime/StringConstructor.cpp +++ b/Userland/Libraries/LibJS/Runtime/StringConstructor.cpp @@ -6,6 +6,7 @@ #include <AK/StringBuilder.h> #include <AK/Utf32View.h> +#include <LibJS/Runtime/AbstractOperations.h> #include <LibJS/Runtime/Array.h> #include <LibJS/Runtime/Error.h> #include <LibJS/Runtime/GlobalObject.h> @@ -68,41 +69,50 @@ Value StringConstructor::construct(FunctionObject&) // 22.1.2.4 String.raw ( template, ...substitutions ), https://tc39.es/ecma262/#sec-string.raw JS_DEFINE_NATIVE_FUNCTION(StringConstructor::raw) { - auto* template_object = vm.argument(0).to_object(global_object); + auto* cooked = vm.argument(0).to_object(global_object); if (vm.exception()) return {}; - auto raw = template_object->get(vm.names.raw); + auto raw_value = cooked->get(vm.names.raw).value_or(js_undefined()); if (vm.exception()) return {}; - if (raw.is_empty() || raw.is_nullish()) { - vm.throw_exception<TypeError>(global_object, ErrorType::StringRawCannotConvert, raw.is_null() ? "null" : "undefined"); + + auto* raw = raw_value.to_object(global_object); + if (vm.exception()) return {}; - } - // FIXME: This should use length_of_array_like() and work with any object - if (!raw.is_object() || !raw.as_object().is_array()) + + auto literal_segments = length_of_array_like(global_object, *raw); + if (vm.exception()) + return {}; + + if (literal_segments == 0) return js_string(vm, ""); - auto* array = static_cast<Array*>(raw.to_object(global_object)); - auto& raw_array_elements = array->indexed_properties(); - StringBuilder builder; + const auto number_of_substituions = vm.argument_count() - 1; - for (size_t i = 0; i < raw_array_elements.array_like_size(); ++i) { - auto result = raw_array_elements.get(array, i); + StringBuilder builder; + for (size_t i = 0; i < literal_segments; ++i) { + auto next_key = String::number(i); + auto next_segment_value = raw->get(next_key).value_or(js_undefined()); if (vm.exception()) return {}; - if (!result.has_value()) - continue; - builder.append(result.value().value.to_string(global_object)); + auto next_segment = next_segment_value.to_string(global_object); if (vm.exception()) return {}; - if (i + 1 < vm.argument_count() && i < raw_array_elements.array_like_size() - 1) { - builder.append(vm.argument(i + 1).to_string(global_object)); + + builder.append(next_segment); + + if (i + 1 == literal_segments) + break; + + if (i < number_of_substituions) { + auto next = vm.argument(i + 1); + auto next_sub = next.to_string(global_object); if (vm.exception()) return {}; + builder.append(next_sub); } } - return js_string(vm, builder.build()); } |