aboutsummaryrefslogtreecommitdiff
path: root/src/bun.js/bindings/JSStringDecoder.cpp
diff options
context:
space:
mode:
authorGravatar Zilin Zhu <zhuzilinallen@gmail.com> 2022-09-02 03:56:41 +0800
committerGravatar GitHub <noreply@github.com> 2022-09-01 12:56:41 -0700
commit700c31dd131bd839c2cf28d6b34915fa111cead4 (patch)
tree9e2efce1a4efeefe62abbf7514e8d125a60ef797 /src/bun.js/bindings/JSStringDecoder.cpp
parentf023b89b732db0aff24445acbbe39c366d13118d (diff)
downloadbun-700c31dd131bd839c2cf28d6b34915fa111cead4.tar.gz
bun-700c31dd131bd839c2cf28d6b34915fa111cead4.tar.zst
bun-700c31dd131bd839c2cf28d6b34915fa111cead4.zip
Add native StringDecoder (#1188)
* Add native StringDecoder * fix upon reviews * add Constructor and use LazyClassStructure
Diffstat (limited to 'src/bun.js/bindings/JSStringDecoder.cpp')
-rw-r--r--src/bun.js/bindings/JSStringDecoder.cpp426
1 files changed, 426 insertions, 0 deletions
diff --git a/src/bun.js/bindings/JSStringDecoder.cpp b/src/bun.js/bindings/JSStringDecoder.cpp
new file mode 100644
index 000000000..d9af6e49e
--- /dev/null
+++ b/src/bun.js/bindings/JSStringDecoder.cpp
@@ -0,0 +1,426 @@
+#include "JSStringDecoder.h"
+#include "JSBuffer.h"
+#include "JavaScriptCore/Lookup.h"
+#include "JavaScriptCore/ObjectConstructor.h"
+#include "ZigGlobalObject.h"
+#include "JSDOMOperation.h"
+#include "JSDOMAttribute.h"
+#include "headers.h"
+#include "JSDOMConvertEnumeration.h"
+
+namespace WebCore {
+
+using namespace JSC;
+
+static JSC_DECLARE_HOST_FUNCTION(jsStringDecoderPrototypeFunction_write);
+static JSC_DECLARE_HOST_FUNCTION(jsStringDecoderPrototypeFunction_end);
+static JSC_DECLARE_HOST_FUNCTION(jsStringDecoderPrototypeFunction_text);
+
+static JSC_DECLARE_CUSTOM_GETTER(jsStringDecoder_lastChar);
+static JSC_DECLARE_CUSTOM_GETTER(jsStringDecoder_lastNeed);
+static JSC_DECLARE_CUSTOM_GETTER(jsStringDecoder_lastTotal);
+
+void JSStringDecoder::finishCreation(JSC::VM& vm, JSC::JSGlobalObject* globalObject)
+{
+ Base::finishCreation(vm);
+}
+
+JSC::JSValue JSStringDecoder::fillLast(JSC::VM& vm, JSC::JSGlobalObject* globalObject, uint8_t* bufPtr, uint32_t length)
+{
+ auto throwScope = DECLARE_THROW_SCOPE(vm);
+
+ if (m_encoding == BufferEncodingType::utf8) {
+ // utf8CheckExtraBytes
+ if ((bufPtr[0] & 0xC0) != 0x80) {
+ m_lastNeed = 0;
+ RELEASE_AND_RETURN(throwScope, JSC::jsString(vm, WTF::String(u"\uFFFD", 1)));
+ }
+ if (m_lastNeed > 1 && length > 1) {
+ if ((bufPtr[1] & 0xC0) != 0x80) {
+ m_lastNeed = 1;
+ RELEASE_AND_RETURN(throwScope, JSC::jsString(vm, WTF::String(u"\uFFFD", 1)));
+ }
+ if (m_lastNeed > 2 && length > 2) {
+ if ((bufPtr[2] & 0xC0) != 0x80) {
+ m_lastNeed = 2;
+ RELEASE_AND_RETURN(throwScope, JSC::jsString(vm, WTF::String(u"\uFFFD", 1)));
+ }
+ }
+ }
+ }
+
+ if (m_lastNeed <= length) {
+ memmove(m_lastChar + m_lastTotal - m_lastNeed, bufPtr, m_lastNeed);
+ RELEASE_AND_RETURN(throwScope, JSC::JSValue::decode(Bun__encoding__toString(m_lastChar, m_lastTotal, globalObject, static_cast<uint8_t>(m_encoding))));
+ }
+ memmove(m_lastChar + m_lastTotal - m_lastNeed, bufPtr, length);
+ m_lastNeed -= length;
+ RELEASE_AND_RETURN(throwScope, JSC::jsEmptyString(vm));
+}
+
+// Checks the type of a UTF-8 byte, whether it's ASCII, a leading byte, or a
+// continuation byte. If an invalid byte is detected, -2 is returned.
+int8_t utf8CheckByte(uint8_t byte) {
+ if (byte <= 0x7F) return 0;
+ else if ((byte >> 5) == 0x06) return 2;
+ else if ((byte >> 4) == 0x0E) return 3;
+ else if ((byte >> 3) == 0x1E) return 4;
+ return (byte >> 6) == 0x02 ? -1 : -2;
+}
+
+// Checks at most 3 bytes at the end of a Buffer in order to detect an
+// incomplete multi-byte UTF-8 character. The total number of bytes (2, 3, or 4)
+// needed to complete the UTF-8 character (if applicable) are returned.
+uint8_t JSStringDecoder::utf8CheckIncomplete(uint8_t* bufPtr, uint32_t length, uint32_t i)
+{
+ uint32_t j = length - 1;
+ if (j < i) return 0;
+ int8_t nb = utf8CheckByte(bufPtr[j]);
+ if (nb >= 0) {
+ if (nb > 0) m_lastNeed = nb - 1;
+ return nb;
+ }
+ if (--j < i || nb == -2) return 0;
+ nb = utf8CheckByte(bufPtr[j]);
+ if (nb >= 0) {
+ if (nb > 0) m_lastNeed = nb - 2;
+ return nb;
+ }
+ if (--j < i || nb == -2) return 0;
+ nb = utf8CheckByte(bufPtr[j]);
+ if (nb >= 0) {
+ if (nb > 0) {
+ if (nb == 2) nb = 0;else m_lastNeed = nb - 3;
+ }
+ return nb;
+ }
+ return 0;
+}
+
+// This is not the exposed text
+JSC::JSValue JSStringDecoder::text(JSC::VM& vm, JSC::JSGlobalObject* globalObject, uint8_t* bufPtr, uint32_t length, uint32_t offset)
+{
+ auto throwScope = DECLARE_THROW_SCOPE(vm);
+
+ switch (m_encoding) {
+ case BufferEncodingType::ucs2:
+ case BufferEncodingType::utf16le: {
+ if (length == offset)
+ RELEASE_AND_RETURN(throwScope, JSC::jsEmptyString(vm));
+ if ((length - offset) % 2 == 0) {
+ UChar c = (static_cast<uint16_t>(bufPtr[length - 1]) << 8) + static_cast<uint16_t>(bufPtr[length - 2]);
+ if (c >= 0xD800 && c <= 0xDBFF) {
+ m_lastNeed = 2;
+ m_lastTotal = 4;
+ m_lastChar[0] = bufPtr[length - 2];
+ m_lastChar[1] = bufPtr[length - 1];
+ RELEASE_AND_RETURN(throwScope, JSC::JSValue::decode(Bun__encoding__toString(bufPtr + offset, length - offset - 2, globalObject, static_cast<uint8_t>(m_encoding))));
+ }
+ RELEASE_AND_RETURN(throwScope, JSC::JSValue::decode(Bun__encoding__toString(bufPtr + offset, length - offset, globalObject, static_cast<uint8_t>(m_encoding))));
+ }
+ m_lastNeed = 1;
+ m_lastTotal = 2;
+ m_lastChar[0] = bufPtr[length - 1];
+ RELEASE_AND_RETURN(throwScope, JSC::JSValue::decode(Bun__encoding__toString(bufPtr + offset, length - offset - 1, globalObject, static_cast<uint8_t>(m_encoding))));
+ }
+ case BufferEncodingType::utf8: {
+ uint32_t total = utf8CheckIncomplete(bufPtr, length, offset);
+ if (!m_lastNeed)
+ RELEASE_AND_RETURN(throwScope, JSC::JSValue::decode(Bun__encoding__toString(bufPtr + offset, length - offset, globalObject, static_cast<uint8_t>(m_encoding))));
+ m_lastTotal = total;
+ uint32_t end = length - (total - m_lastNeed);
+ if (end < length)
+ memmove(m_lastChar, bufPtr + end, std::min(4U, length - end));
+ RELEASE_AND_RETURN(throwScope, JSC::JSValue::decode(Bun__encoding__toString(bufPtr + offset, end - offset, globalObject, static_cast<uint8_t>(m_encoding))));
+ }
+ case BufferEncodingType::base64: {
+ uint32_t n = (length - offset) % 3;
+ if (n == 0)
+ RELEASE_AND_RETURN(throwScope, JSC::JSValue::decode(Bun__encoding__toString(bufPtr + offset, length - offset, globalObject, static_cast<uint8_t>(m_encoding))));
+ m_lastNeed = 3 - n;
+ m_lastTotal = 3;
+ if (n == 1) {
+ m_lastChar[0] = bufPtr[length - 1];
+ } else {
+ m_lastChar[0] = bufPtr[length - 2];
+ m_lastChar[1] = bufPtr[length - 1];
+ }
+ RELEASE_AND_RETURN(throwScope, JSC::JSValue::decode(Bun__encoding__toString(bufPtr + offset, length - offset - n, globalObject, static_cast<uint8_t>(m_encoding))));
+ }
+ default: {
+ // should never reach here.
+ RETURN_IF_EXCEPTION(throwScope, JSC::jsUndefined());
+ }
+ }
+
+}
+
+JSC::JSValue JSStringDecoder::write(JSC::VM& vm, JSC::JSGlobalObject* globalObject, uint8_t* bufPtr, uint32_t length)
+{
+ auto throwScope = DECLARE_THROW_SCOPE(vm);
+ if (length == 0)
+ RELEASE_AND_RETURN(throwScope, JSC::jsEmptyString(vm));
+
+ switch (m_encoding) {
+ case BufferEncodingType::ucs2:
+ case BufferEncodingType::utf16le:
+ case BufferEncodingType::utf8:
+ case BufferEncodingType::base64: {
+ uint32_t offset = 0;
+ if (m_lastNeed) {
+ JSString* firstHalf = fillLast(vm, globalObject, bufPtr, length).toString(globalObject);
+ RETURN_IF_EXCEPTION(throwScope, JSC::jsUndefined());
+ if (firstHalf->length() == 0)
+ RELEASE_AND_RETURN(throwScope, firstHalf);
+ offset = m_lastNeed;
+ m_lastNeed = 0;
+
+ JSString* secondHalf = text(vm, globalObject, bufPtr, length, offset).toString(globalObject);
+ RETURN_IF_EXCEPTION(throwScope, JSC::jsUndefined());
+ if (secondHalf->length() == 0)
+ RELEASE_AND_RETURN(throwScope, firstHalf);
+ RELEASE_AND_RETURN(throwScope, JSC::jsString(globalObject, firstHalf, secondHalf));
+ }
+ JSString* str = text(vm, globalObject, bufPtr, length, offset).toString(globalObject);
+ RETURN_IF_EXCEPTION(throwScope, JSC::jsUndefined());
+ RELEASE_AND_RETURN(throwScope, str);
+ }
+ default: {
+ RELEASE_AND_RETURN(throwScope, JSC::JSValue::decode(Bun__encoding__toString(bufPtr, length, globalObject, static_cast<uint8_t>(m_encoding))));
+ }
+ }
+}
+
+JSC::JSValue JSStringDecoder::end(JSC::VM& vm, JSC::JSGlobalObject* globalObject, uint8_t* bufPtr, uint32_t length)
+{
+ auto throwScope = DECLARE_THROW_SCOPE(vm);
+ switch (m_encoding) {
+ case BufferEncodingType::ucs2:
+ case BufferEncodingType::utf16le: {
+ if (length == 0) {
+ if (m_lastNeed) {
+ RELEASE_AND_RETURN(throwScope, JSC::JSValue::decode(Bun__encoding__toString(m_lastChar, m_lastTotal - m_lastNeed, globalObject, static_cast<uint8_t>(m_encoding))));
+ } else {
+ RELEASE_AND_RETURN(throwScope, JSC::jsEmptyString(vm));
+ }
+ }
+ JSString* firstHalf = write(vm, globalObject, bufPtr, length).toString(globalObject);
+ RETURN_IF_EXCEPTION(throwScope, JSC::jsUndefined());
+ if (m_lastNeed) {
+ JSString* secondHalf = JSC::JSValue::decode(Bun__encoding__toString(m_lastChar, m_lastTotal - m_lastNeed, globalObject, static_cast<uint8_t>(m_encoding))).toString(globalObject);
+ RELEASE_AND_RETURN(throwScope, JSC::jsString(globalObject, firstHalf, secondHalf));
+ } else {
+ RELEASE_AND_RETURN(throwScope, firstHalf);
+ }
+ }
+ case BufferEncodingType::utf8: {
+ if (length == 0) {
+ RELEASE_AND_RETURN(throwScope, m_lastNeed ? JSC::jsString(vm, WTF::String(u"\uFFFD", 1)) : JSC::jsEmptyString(vm));
+ }
+ JSString* firstHalf = write(vm, globalObject, bufPtr, length).toString(globalObject);
+ RETURN_IF_EXCEPTION(throwScope, JSC::jsUndefined());
+ RELEASE_AND_RETURN(throwScope, m_lastNeed ? JSC::jsString(globalObject, firstHalf, WTF::String(u"\uFFFD", 1)) : firstHalf);
+ }
+ case BufferEncodingType::base64: {
+ if (length == 0) {
+ if (m_lastNeed) {
+ RELEASE_AND_RETURN(throwScope, JSC::JSValue::decode(Bun__encoding__toString(m_lastChar, 3 - m_lastNeed, globalObject, static_cast<uint8_t>(m_encoding))));
+ } else {
+ RELEASE_AND_RETURN(throwScope, JSC::jsEmptyString(vm));
+ }
+ }
+ JSString* firstHalf = write(vm, globalObject, bufPtr, length).toString(globalObject);
+ RETURN_IF_EXCEPTION(throwScope, JSC::jsUndefined());
+ if (m_lastNeed) {
+ JSString* secondHalf = JSC::JSValue::decode(Bun__encoding__toString(m_lastChar, 3 - m_lastNeed, globalObject, static_cast<uint8_t>(m_encoding))).toString(globalObject);
+ RETURN_IF_EXCEPTION(throwScope, JSC::jsUndefined());
+ RELEASE_AND_RETURN(throwScope, JSC::jsString(globalObject, firstHalf, secondHalf));
+ } else {
+ RELEASE_AND_RETURN(throwScope, firstHalf);
+ }
+ }
+ default: {
+ if (length == 0) {
+ RELEASE_AND_RETURN(throwScope, JSC::jsEmptyString(vm));
+ }
+ RELEASE_AND_RETURN(throwScope, write(vm, globalObject, bufPtr, length));
+ }
+ }
+}
+
+const JSC::ClassInfo JSStringDecoder::s_info = { "StringDecoder"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSStringDecoder) };
+
+JSC::GCClient::IsoSubspace* JSStringDecoder::subspaceForImpl(JSC::VM& vm)
+{
+ return WebCore::subspaceForImpl<JSStringDecoder, UseCustomHeapCellType::No>(
+ vm,
+ [](auto& spaces) { return spaces.m_clientSubspaceForStringDecoder.get(); },
+ [](auto& spaces, auto&& space) { spaces.m_clientSubspaceForStringDecoder = WTFMove(space); },
+ [](auto& spaces) { return spaces.m_subspaceForStringDecoder.get(); },
+ [](auto& spaces, auto&& space) { spaces.m_subspaceForStringDecoder = WTFMove(space); });
+}
+
+STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(JSStringDecoderPrototype, JSStringDecoderPrototype::Base);
+
+static inline JSC::EncodedJSValue jsStringDecoderPrototypeFunction_writeBody(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame, typename IDLOperation<JSStringDecoder>::ClassParameter castedThis)
+{
+ auto& vm = JSC::getVM(lexicalGlobalObject);
+ auto throwScope = DECLARE_THROW_SCOPE(vm);
+ if (callFrame->argumentCount() < 1) {
+ throwVMError(lexicalGlobalObject, throwScope, createNotEnoughArgumentsError(lexicalGlobalObject));
+ return JSValue::encode(jsUndefined());
+ }
+
+ auto buffer = callFrame->uncheckedArgument(0);
+ JSC::JSUint8Array* view = JSC::jsDynamicCast<JSC::JSUint8Array*>(buffer);
+ if (!view) {
+ throwVMTypeError(lexicalGlobalObject, throwScope, "Expected Uint8Array"_s);
+ return JSValue::encode(jsUndefined());
+ }
+ RELEASE_AND_RETURN(throwScope, JSC::JSValue::encode(castedThis->write(vm, lexicalGlobalObject, view->typedVector(), view->length())));
+}
+static inline JSC::EncodedJSValue jsStringDecoderPrototypeFunction_endBody(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame, typename IDLOperation<JSStringDecoder>::ClassParameter castedThis)
+{
+ auto& vm = JSC::getVM(lexicalGlobalObject);
+ auto throwScope = DECLARE_THROW_SCOPE(vm);
+ if (callFrame->argumentCount() < 1) {
+ RELEASE_AND_RETURN(throwScope, JSC::JSValue::encode(castedThis->end(vm, lexicalGlobalObject, nullptr, 0)));
+ }
+
+ auto buffer = callFrame->uncheckedArgument(0);
+ JSC::JSUint8Array* view = JSC::jsDynamicCast<JSC::JSUint8Array*>(buffer);
+ if (!view) {
+ throwVMTypeError(lexicalGlobalObject, throwScope, "Expected Uint8Array"_s);
+ return JSValue::encode(jsUndefined());
+ }
+ RELEASE_AND_RETURN(throwScope, JSC::JSValue::encode(castedThis->end(vm, lexicalGlobalObject, view->typedVector(), view->length())));
+}
+static inline JSC::EncodedJSValue jsStringDecoderPrototypeFunction_textBody(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame, typename IDLOperation<JSStringDecoder>::ClassParameter castedThis)
+{
+ auto& vm = JSC::getVM(lexicalGlobalObject);
+ auto throwScope = DECLARE_THROW_SCOPE(vm);
+ if (callFrame->argumentCount() < 2) {
+ throwVMError(lexicalGlobalObject, throwScope, createNotEnoughArgumentsError(lexicalGlobalObject));
+ return JSValue::encode(jsUndefined());
+ }
+
+ auto buffer = callFrame->uncheckedArgument(0);
+ JSC::JSUint8Array* view = JSC::jsDynamicCast<JSC::JSUint8Array*>(buffer);
+ if (!view) {
+ throwVMTypeError(lexicalGlobalObject, throwScope, "Expected Uint8Array"_s);
+ return JSValue::encode(jsUndefined());
+ }
+ int32_t offset = callFrame->uncheckedArgument(1).toInt32(lexicalGlobalObject);
+ RETURN_IF_EXCEPTION(throwScope, JSC::JSValue::encode(JSC::jsUndefined()));
+ if (offset > view->length())
+ RELEASE_AND_RETURN(throwScope, JSC::JSValue::encode(JSC::jsEmptyString(vm)));
+ RELEASE_AND_RETURN(throwScope, JSC::JSValue::encode(castedThis->write(vm, lexicalGlobalObject, view->typedVector() + offset, view->length() - offset)));
+}
+
+static JSC_DEFINE_HOST_FUNCTION(jsStringDecoderPrototypeFunction_write,
+ (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callFrame))
+{
+ return IDLOperation<JSStringDecoder>::call<jsStringDecoderPrototypeFunction_writeBody>(*globalObject, *callFrame, "write");
+}
+static JSC_DEFINE_HOST_FUNCTION(jsStringDecoderPrototypeFunction_end,
+ (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callFrame))
+{
+ return IDLOperation<JSStringDecoder>::call<jsStringDecoderPrototypeFunction_endBody>(*globalObject, *callFrame, "end");
+}
+static JSC_DEFINE_HOST_FUNCTION(jsStringDecoderPrototypeFunction_text,
+ (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callFrame))
+{
+ return IDLOperation<JSStringDecoder>::call<jsStringDecoderPrototypeFunction_textBody>(*globalObject, *callFrame, "text");
+}
+
+static JSC_DEFINE_CUSTOM_GETTER(jsStringDecoder_lastChar, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue thisValue, PropertyName attributeName))
+{
+ auto& vm = JSC::getVM(lexicalGlobalObject);
+ auto throwScope = DECLARE_THROW_SCOPE(vm);
+ JSStringDecoder* thisObject = jsCast<JSStringDecoder*>(JSValue::decode(thisValue));
+ auto buffer = ArrayBuffer::createFromBytes(thisObject->m_lastChar, 4, nullptr);
+ JSC::JSUint8Array* uint8Array = JSC::JSUint8Array::create(lexicalGlobalObject, lexicalGlobalObject->typedArrayStructure(JSC::TypeUint8), WTFMove(buffer), 0, 4);
+ toBuffer(lexicalGlobalObject, uint8Array);
+ RELEASE_AND_RETURN(throwScope, JSC::JSValue::encode(uint8Array));
+}
+static JSC_DEFINE_CUSTOM_GETTER(jsStringDecoder_lastNeed, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue thisValue, PropertyName attributeName))
+{
+ auto& vm = JSC::getVM(lexicalGlobalObject);
+ auto throwScope = DECLARE_THROW_SCOPE(vm);
+ JSStringDecoder* thisObject = jsCast<JSStringDecoder*>(JSValue::decode(thisValue));
+ RELEASE_AND_RETURN(throwScope, JSC::JSValue::encode(JSC::jsNumber(thisObject->m_lastNeed)));
+}
+static JSC_DEFINE_CUSTOM_GETTER(jsStringDecoder_lastTotal, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue thisValue, PropertyName attributeName))
+{
+ auto& vm = JSC::getVM(lexicalGlobalObject);
+ auto throwScope = DECLARE_THROW_SCOPE(vm);
+ JSStringDecoder* thisObject = jsCast<JSStringDecoder*>(JSValue::decode(thisValue));
+ RELEASE_AND_RETURN(throwScope, JSC::JSValue::encode(JSC::jsNumber(thisObject->m_lastTotal)));
+}
+
+/* Hash table for prototype */
+static const HashTableValue JSStringDecoderPrototypeTableValues[]
+ = {
+ { "lastChar"_s, static_cast<unsigned>(JSC::PropertyAttribute::DontDelete | JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DOMAttribute), NoIntrinsic, { HashTableValue::GetterSetterType, jsStringDecoder_lastChar, 0 } },
+ { "lastNeed"_s, static_cast<unsigned>(JSC::PropertyAttribute::DontDelete | JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DOMAttribute), NoIntrinsic, { HashTableValue::GetterSetterType, jsStringDecoder_lastNeed, 0 } },
+ { "lastTotal"_s, static_cast<unsigned>(JSC::PropertyAttribute::DontDelete | JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DOMAttribute), NoIntrinsic, { HashTableValue::GetterSetterType, jsStringDecoder_lastTotal, 0 } },
+ { "write"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, jsStringDecoderPrototypeFunction_write, 1 } },
+ { "end"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, jsStringDecoderPrototypeFunction_end, 1 } },
+ { "text"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, jsStringDecoderPrototypeFunction_text, 2 } },
+ };
+
+void JSStringDecoderPrototype::finishCreation(VM& vm, JSC::JSGlobalObject* globalThis)
+{
+ Base::finishCreation(vm);
+ reifyStaticProperties(vm, JSStringDecoder::info(), JSStringDecoderPrototypeTableValues, *this);
+ JSC_TO_STRING_TAG_WITHOUT_TRANSITION();
+}
+
+const ClassInfo JSStringDecoderPrototype::s_info = { "StringDecoder"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSStringDecoderPrototype) };
+
+void JSStringDecoderConstructor::finishCreation(VM& vm, JSC::JSGlobalObject* globalObject, JSStringDecoderPrototype* prototype)
+{
+ Base::finishCreation(vm, 0, "StringDecoder"_s, PropertyAdditionMode::WithoutStructureTransition);
+ putDirectWithoutTransition(vm, vm.propertyNames->prototype, prototype, PropertyAttribute::DontEnum | PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly);
+ ASSERT(inherits(info()));
+}
+
+JSStringDecoderConstructor* JSStringDecoderConstructor::create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure, JSStringDecoderPrototype* prototype) {
+ JSStringDecoderConstructor* ptr = new (NotNull, JSC::allocateCell<JSStringDecoderConstructor>(vm)) JSStringDecoderConstructor(vm, structure, construct);
+ ptr->finishCreation(vm, globalObject, prototype);
+ return ptr;
+}
+
+JSC::EncodedJSValue JSStringDecoderConstructor::construct(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame)
+{
+ JSC::VM& vm = lexicalGlobalObject->vm();
+ auto encoding = BufferEncodingType::utf8;
+ if (callFrame->argumentCount() > 0) {
+ auto encoding_ = callFrame->argument(0).toString(lexicalGlobalObject);
+ std::optional<BufferEncodingType> opt = parseEnumeration<BufferEncodingType>(*lexicalGlobalObject, encoding_);
+ if (opt.has_value()) {
+ encoding = opt.value();
+ }
+ }
+ JSStringDecoder* stringDecoder = JSStringDecoder::create(
+ vm, lexicalGlobalObject, reinterpret_cast<Zig::GlobalObject*>(lexicalGlobalObject)->JSStringDecoderStructure(), encoding);
+ return JSC::JSValue::encode(stringDecoder);
+}
+
+void JSStringDecoderConstructor::initializeProperties(VM& vm, JSC::JSGlobalObject* globalObject, JSStringDecoderPrototype* prototype)
+{
+}
+
+JSC::GCClient::IsoSubspace* JSStringDecoderConstructor::subspaceForImpl(JSC::VM& vm)
+{
+ return WebCore::subspaceForImpl<JSStringDecoderConstructor, UseCustomHeapCellType::No>(
+ vm,
+ [](auto& spaces) { return spaces.m_clientSubspaceForStringDecoderConstructor.get(); },
+ [](auto& spaces, auto&& space) { spaces.m_clientSubspaceForStringDecoderConstructor = WTFMove(space); },
+ [](auto& spaces) { return spaces.m_subspaceForStringDecoderConstructor.get(); },
+ [](auto& spaces, auto&& space) { spaces.m_subspaceForStringDecoderConstructor = WTFMove(space); });
+}
+
+const ClassInfo JSStringDecoderConstructor::s_info = { "StringDecoder"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSStringDecoderConstructor) };
+
+} // namespace Zig