From 30609289b5ce62009f9d5d9de1dd30d5710f65f6 Mon Sep 17 00:00:00 2001 From: Simon Wanner Date: Thu, 30 May 2024 20:44:41 +0200 Subject: [PATCH] LibWeb: Bring TextDecoder constructor closer to spec (cherry picked from commit 987910ad0f9978a9a618d13b3e1d299a81ce4906) --- .../Libraries/LibWeb/Encoding/TextDecoder.cpp | 30 +++++++++++++++---- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/Userland/Libraries/LibWeb/Encoding/TextDecoder.cpp b/Userland/Libraries/LibWeb/Encoding/TextDecoder.cpp index 071bf9b3b1..3fa46ff918 100644 --- a/Userland/Libraries/LibWeb/Encoding/TextDecoder.cpp +++ b/Userland/Libraries/LibWeb/Encoding/TextDecoder.cpp @@ -1,5 +1,6 @@ /* * Copyright (c) 2022, Ali Mohammad Pur + * Copyright (c) 2024, Simon Wanner * * SPDX-License-Identifier: BSD-2-Clause */ @@ -16,15 +17,34 @@ namespace Web::Encoding { JS_DEFINE_ALLOCATOR(TextDecoder); -WebIDL::ExceptionOr> TextDecoder::construct_impl(JS::Realm& realm, FlyString encoding, Optional const& options) +// https://encoding.spec.whatwg.org/#dom-textdecoder +WebIDL::ExceptionOr> TextDecoder::construct_impl(JS::Realm& realm, FlyString label, Optional const& options) { auto& vm = realm.vm(); - auto decoder = TextCodec::decoder_for(encoding); - if (!decoder.has_value()) - return WebIDL::SimpleException { WebIDL::SimpleExceptionType::TypeError, TRY_OR_THROW_OOM(vm, String::formatted("Invalid encoding {}", encoding)) }; + // 1. Let encoding be the result of getting an encoding from label. + auto encoding = TextCodec::get_standardized_encoding(label); - return realm.heap().allocate(realm, realm, *decoder, move(encoding), options.value_or({}).fatal, options.value_or({}).ignore_bom); + // 2. If encoding is failure or replacement, then throw a RangeError. + if (!encoding.has_value() || encoding->equals_ignoring_ascii_case("replacement"sv)) + return WebIDL::SimpleException { WebIDL::SimpleExceptionType::RangeError, TRY_OR_THROW_OOM(vm, String::formatted("Invalid encoding {}", label)) }; + + // 3. Set this’s encoding to encoding. + // https://encoding.spec.whatwg.org/#dom-textdecoder-encoding + // The encoding getter steps are to return this’s encoding’s name, ASCII lowercased. + auto lowercase_encoding_name = MUST(String::from_byte_string(encoding.value().to_lowercase_string())); + + // 4. If options["fatal"] is true, then set this’s error mode to "fatal". + auto fatal = options.value_or({}).fatal; + + // 5. Set this’s ignore BOM to options["ignoreBOM"]. + auto ignore_bom = options.value_or({}).ignore_bom; + + // NOTE: This should happen in decode(), but we don't support streaming yet and share decoders across calls. + auto decoder = TextCodec::decoder_for(encoding.value()); + VERIFY(decoder.has_value()); + + return realm.heap().allocate(realm, realm, *decoder, lowercase_encoding_name, fatal, ignore_bom); } // https://encoding.spec.whatwg.org/#dom-textdecoder