Переглянути джерело

LibWeb: Implement a very basic version of TextDecoder

We had a very basic implementation of TextEncoder, let's add a
TextDecoder next to that :^)
Ali Mohammad Pur 3 роки тому
батько
коміт
16c0646b9d

+ 3 - 0
Userland/Libraries/LibWeb/Bindings/WindowObjectHelper.h

@@ -288,6 +288,8 @@
 #include <LibWeb/Bindings/SubtleCryptoConstructor.h>
 #include <LibWeb/Bindings/SubtleCryptoPrototype.h>
 #include <LibWeb/Bindings/TextConstructor.h>
+#include <LibWeb/Bindings/TextDecoderConstructor.h>
+#include <LibWeb/Bindings/TextDecoderPrototype.h>
 #include <LibWeb/Bindings/TextEncoderConstructor.h>
 #include <LibWeb/Bindings/TextEncoderPrototype.h>
 #include <LibWeb/Bindings/TextMetricsConstructor.h>
@@ -458,6 +460,7 @@
     ADD_WINDOW_OBJECT_INTERFACE(SVGRectElement)            \
     ADD_WINDOW_OBJECT_INTERFACE(SVGSVGElement)             \
     ADD_WINDOW_OBJECT_INTERFACE(Text)                      \
+    ADD_WINDOW_OBJECT_INTERFACE(TextDecoder)               \
     ADD_WINDOW_OBJECT_INTERFACE(TextEncoder)               \
     ADD_WINDOW_OBJECT_INTERFACE(TextMetrics)               \
     ADD_WINDOW_OBJECT_INTERFACE(UIEvent)                   \

+ 2 - 0
Userland/Libraries/LibWeb/CMakeLists.txt

@@ -93,6 +93,7 @@ set(SOURCES
     DOMParsing/InnerHTML.cpp
     DOMTreeModel.cpp
     Dump.cpp
+    Encoding/TextDecoder.cpp
     Encoding/TextEncoder.cpp
     Fetch/AbstractOperations.cpp
     FontCache.cpp
@@ -420,6 +421,7 @@ libweb_js_wrapper(DOM/ProcessingInstruction)
 libweb_js_wrapper(DOM/Range)
 libweb_js_wrapper(DOM/ShadowRoot)
 libweb_js_wrapper(DOM/Text)
+libweb_js_wrapper(Encoding/TextDecoder)
 libweb_js_wrapper(Encoding/TextEncoder)
 libweb_js_wrapper(Geometry/DOMRect)
 libweb_js_wrapper(Geometry/DOMRectList)

+ 27 - 0
Userland/Libraries/LibWeb/Encoding/TextDecoder.cpp

@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2022, Ali Mohammad Pur <mpfard@serenityos.org>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include <AK/FlyString.h>
+#include <LibJS/Runtime/TypedArray.h>
+#include <LibWeb/Bindings/IDLAbstractOperations.h>
+#include <LibWeb/Bindings/Wrapper.h>
+#include <LibWeb/Encoding/TextDecoder.h>
+
+namespace Web::Encoding {
+
+// https://encoding.spec.whatwg.org/#dom-textdecoder-decode
+DOM::ExceptionOr<String> TextDecoder::decode(JS::Handle<JS::Object> const& input) const
+{
+    // FIXME: Implement the streaming stuff.
+
+    auto data_buffer = Bindings::IDL::get_buffer_source_copy(*input.cell());
+    if (!data_buffer.has_value())
+        return DOM::OperationError::create("Failed to copy bytes from ArrayBuffer");
+
+    return m_decoder.to_utf8({ data_buffer->data(), data_buffer->size() });
+}
+
+}

+ 63 - 0
Userland/Libraries/LibWeb/Encoding/TextDecoder.h

@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2022, Ali Mohammad Pur <mpfard@serenityos.org>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#pragma once
+
+#include <AK/Forward.h>
+#include <AK/NonnullRefPtr.h>
+#include <AK/RefCounted.h>
+#include <LibJS/Forward.h>
+#include <LibTextCodec/Decoder.h>
+#include <LibWeb/Bindings/Wrappable.h>
+#include <LibWeb/DOM/ExceptionOr.h>
+#include <LibWeb/Forward.h>
+
+namespace Web::Encoding {
+
+// https://encoding.spec.whatwg.org/#textdecoder
+class TextDecoder
+    : public RefCounted<TextDecoder>
+    , public Bindings::Wrappable {
+public:
+    using WrapperType = Bindings::TextDecoderWrapper;
+
+    static DOM::ExceptionOr<NonnullRefPtr<TextDecoder>> create(FlyString encoding)
+    {
+        auto decoder = TextCodec::decoder_for(encoding);
+        if (!decoder)
+            return DOM::SimpleException { DOM::SimpleExceptionType::TypeError, String::formatted("Invalid encoding {}", encoding) };
+
+        return adopt_ref(*new TextDecoder(*decoder, move(encoding), false, false));
+    }
+
+    static DOM::ExceptionOr<NonnullRefPtr<TextDecoder>> create_with_global_object(Bindings::WindowObject&, FlyString label)
+    {
+        return TextDecoder::create(move(label));
+    }
+
+    DOM::ExceptionOr<String> decode(JS::Handle<JS::Object> const&) const;
+
+    FlyString const& encoding() const { return m_encoding; }
+    bool fatal() const { return m_fatal; }
+    bool ignore_bom() const { return m_ignore_bom; };
+
+protected:
+    // https://encoding.spec.whatwg.org/#dom-textdecoder
+    TextDecoder(TextCodec::Decoder& decoder, FlyString encoding, bool fatal, bool ignore_bom)
+        : m_decoder(decoder)
+        , m_encoding(move(encoding))
+        , m_fatal(fatal)
+        , m_ignore_bom(ignore_bom)
+    {
+    }
+
+    TextCodec::Decoder& m_decoder;
+    FlyString m_encoding;
+    bool m_fatal { false };
+    bool m_ignore_bom { false };
+};
+
+}

+ 13 - 0
Userland/Libraries/LibWeb/Encoding/TextDecoder.idl

@@ -0,0 +1,13 @@
+[Exposed=(Window,Worker)]
+interface TextDecoder {
+    // FIXME: 'optional TextDecoderOptions options = {}'
+    constructor(optional DOMString label = "utf-8");
+
+    // FIXME: [AllowShared] on the first parameter.
+    // FIXME: 'optional TextDecodeOptions options = {}'
+    USVString decode(optional BufferSource input);
+
+    readonly attribute DOMString encoding;
+    readonly attribute boolean fatal;
+    readonly attribute boolean ignoreBOM;
+};

+ 1 - 0
Userland/Libraries/LibWeb/Forward.h

@@ -472,6 +472,7 @@ class SVGPolygonElementWrapper;
 class SVGPolylineElementWrapper;
 class SVGRectElementWrapper;
 class SVGSVGElementWrapper;
+class TextDecoderWrapper;
 class TextEncoderWrapper;
 class TextMetricsWrapper;
 class TextWrapper;