Files
bun.sh/src/bun.js/bindings/JSStringDecoder.cpp
Jarred Sumner 7485c7c7cb feat: Windows + CMake Build System (#4410)
* Prepare for windows event loop

* More progress

* Update libuv.zig

* wip

* Make compiling each dependency a shell script

* Bump mimalloc

* Add the build scripts

* Update settings.json

* Fix a bunch of compiler warnings

* Remove more warnings

* more warnings

* cmake works

* Update JSSQLStatement.h

* put it in the zig file

* Fix usockets warnings

* Fixup

* Fix one of the compiler errors

* chunk

* draw the rest of the owl

* theres more

* Rename Process -> BunProcess

Works around a Windows issue

* Add musl polyfill for memmem on Windows

* More

* 12 mb

* Fix getenvZ

* fix variosu issues

* Add fast-ish path for bun install on Windows

* Update windows.zig

* Update windows.zig

* Fix build issue

* it works

* hmmm

* Rename file

* Fixups

* Update wtf-bindings.cpp

* Update src/bun.js/bindings/headers-handwritten.h

Co-authored-by: Dylan Conway <35280289+dylan-conway@users.noreply.github.com>

* further!

* more

* Update .gitignore

* hm

* quite a lot of fixes

* Update CMakeLists.txt

* zig fmt

* Many more things are starting to work.

* reb

* regenaret

* Update JSSink.h

* fixup

* fetch works

* Bun.serve() and much of the event loop works now

* Make require() work

* bun install progress

* more things work

* use less std.os

* Fixes

* small fixes

* Bump

* Bummp

* Undo that change

* We have to bump the version of Debian because libarchive has a higher minimum requirement

* ok

* some clenaup

* windows

* Update bun.zig

* fixup

* avoid duplicate symbols

* avoid undefined symbols

* bump

* Remove issue template for install

It's not used, and use the bug issue instead.

* Add types for cp and cpSync

* Add types for watchFile and unwatchFile

* Add bun-types to 'bun fmt' script

* Update nodejs compat docs cp/cpSync/watchFile/unwatchFile (#4525)

* feat(fetch) rejectUnauthorized and checkServerIdentity (#4514)

* enable root certs on fetch

* rebase

* fix lookup

* some fixes and improvements

* fmt

* more fixes

* more fixes

* check detached onHandshake

* fix promise case

* fix cert non-Native

* add fetch tls tests

* more one test

* churn

* Update feature_flags.zig

* Update response.zig

* Revert "avoid undefined symbols"

This reverts commit ca835b726f.

* Revert "avoid duplicate symbols"

This reverts commit 4ac6ca8700.

* Update feature_flags.zig

* Set permissions

* more

* Update mimalloc

* Fix sqlite test failures

* Fix some test failures

* Make sure we remove libusockets is removed

* hm

* [dave]: fix webcrypto crash

* bump

* Update index.ts

* windows zig compiles

* cmake on mac works

* progress

* yay

* bun run build

* fix

* ok

* oops

* asdfasfdafdsafda

* fghjkl

* git ignore

* wow

* Process -> BunProcess

* hmm

* blah

* finalize merge

* now it only has linker errors on mac

* sdfadsf

* g

* getting farther

* sxdcvbnmk,

* adfhjskfjdhkas

* a

* fgh

* update build dot zig

* asdfg

* theoretical -DCANARY flag we can use

* asdf

* cool

* okay

* colorterm

* New build workflow

* Fix script

* Use sudo

* More sudo

* Tweak dependencies

* Another sudo attempt

* Tweak script

* 16.0 -> 16

* Tweak script

* Tweak script

* Tweak script

* Tweak script

* Tweak script

* bun install

* ssh into github actions

* add more to ssh

* Fix postinstal

* Skip llvm

* New dockerfile

* Build

* More changes to Dockerfile

* chaos chaos chaos

* okay

* a

* more cmake nonsense

* add unified sources code (does not work)

* stuff

* prepare for CI builds

* ok

* yay

* yeah

* make this more stable simply by trying again if it fails, 5 times, then lose. it fixes the stability issue i was running into L O L

* messing with ci

* x

* a

* clean dependencies before build

* oops

* this is not going to work but its closer

* not gonna work either

* a

* a

* did i do it

* a

* a

* work around weird fs+Bun.build issues

* properly pass debug flag correctly

* idk im sorry

* lose

* maybe

* run the tests please

* a

* fix zlib script

* a

* hi

* prevent stupid ci issue

* i totally didnt leave in a syntax error on cmakelists

* a

* lol

* relax

* 😭

* a

* SO SILLY

* 😡 one line mistake

* one character diff

* fix linking symbols missing

* work on dependency scripts

* does this work now?

* fix mac build

* a

* bump!

* woops

* add macos baseline build

* .

* fix sqlite and also enable $assert/$debug support in builtin functions

* okay

* oops

* zig upgrade lol

* Merge

* Fix spawn test issue

* Set a timeout

* yeah

* etc

* mi

---------

Co-authored-by: Jarred Sumner <709451+Jarred-Sumner@users.noreply.github.com>
Co-authored-by: Dylan Conway <dylan.conway567@gmail.com>
Co-authored-by: Dylan Conway <35280289+dylan-conway@users.noreply.github.com>
Co-authored-by: Ashcon Partovi <ashcon@partovi.net>
Co-authored-by: Birk Skyum <74932975+birkskyum@users.noreply.github.com>
Co-authored-by: dave caruso <me@paperdave.net>
2023-10-27 01:51:56 -07:00

565 lines
26 KiB
C++

#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"
#include <JavaScriptCore/JSArrayBufferView.h>
#include "BunClientData.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);
static inline JSC::EncodedJSValue jsStringDecoderCast(JSGlobalObject* globalObject, JSValue stringDecoderValue)
{
if (LIKELY(jsDynamicCast<JSStringDecoder*>(stringDecoderValue)))
return JSValue::encode(stringDecoderValue);
auto& vm = globalObject->vm();
auto throwScope = DECLARE_THROW_SCOPE(vm);
if (stringDecoderValue.isEmpty() || stringDecoderValue.isUndefinedOrNull()) {
return JSC::JSValue::encode(jsUndefined());
}
if (!stringDecoderValue.isObject()) {
return throwThisTypeError(*globalObject, throwScope, JSStringDecoder::info()->className, "write");
}
JSC::JSObject* thisObject = JSC::asObject(stringDecoderValue);
JSStringDecoder* castedThis = nullptr;
auto clientData = WebCore::clientData(vm);
if (JSValue existingDecoderValue = thisObject->getIfPropertyExists(globalObject, clientData->builtinNames().decodePrivateName())) {
castedThis = jsDynamicCast<JSStringDecoder*>(existingDecoderValue);
}
if (!castedThis) {
BufferEncodingType encoding = BufferEncodingType::utf8;
if (JSValue encodingValue = thisObject->getIfPropertyExists(globalObject, clientData->builtinNames().encodingPrivateName())) {
if (encodingValue.isString()) {
std::optional<BufferEncodingType> opt = parseEnumeration<BufferEncodingType>(*globalObject, encodingValue);
if (opt.has_value()) {
encoding = opt.value();
}
}
}
castedThis = JSStringDecoder::create(globalObject->vm(), globalObject, reinterpret_cast<Zig::GlobalObject*>(globalObject)->JSStringDecoderStructure(), encoding);
thisObject->putDirect(vm, clientData->builtinNames().decodePrivateName(), castedThis, 0);
}
return JSValue::encode(castedThis);
}
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 == 0 || --j < i || nb == -2)
return 0;
nb = utf8CheckByte(bufPtr[j]);
if (nb >= 0) {
if (nb > 0)
m_lastNeed = nb - 2;
return nb;
}
if (j == 0 || --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:
case BufferEncodingType::base64url: {
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.
RELEASE_AND_RETURN(throwScope, JSC::jsUndefined());
break;
}
}
__builtin_unreachable();
}
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:
case BufferEncodingType::base64url: {
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))));
}
}
__builtin_unreachable();
}
class ResetScope final {
public:
ResetScope(JSStringDecoder* decoder);
~ResetScope();
JSStringDecoder* m_decoder;
};
ResetScope::ResetScope(JSStringDecoder* decoder)
{
m_decoder = decoder;
}
ResetScope::~ResetScope()
{
m_decoder->m_lastTotal = 0;
m_decoder->m_lastNeed = 0;
memset(m_decoder->m_lastChar, 0, 4);
}
JSC::JSValue
JSStringDecoder::end(JSC::VM& vm, JSC::JSGlobalObject* globalObject, uint8_t* bufPtr, uint32_t length)
{
auto throwScope = DECLARE_THROW_SCOPE(vm);
auto resetScope = ResetScope(this);
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:
case BufferEncodingType::base64url: {
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 = std::forward<decltype(space)>(space); },
[](auto& spaces) { return spaces.m_subspaceForStringDecoder.get(); },
[](auto& spaces, auto&& space) { spaces.m_subspaceForStringDecoder = std::forward<decltype(space)>(space); });
}
STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(JSStringDecoderPrototype, JSStringDecoderPrototype::Base);
static inline JSC::EncodedJSValue jsStringDecoderPrototypeFunction_writeBody(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame, JSStringDecoder* 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::JSArrayBufferView* view = JSC::jsDynamicCast<JSC::JSArrayBufferView*>(buffer);
if (UNLIKELY(!view || view->isDetached())) {
// What node does:
// StringDecoder.prototype.write = function write(buf) {
// if (typeof buf === 'string')
// return buf;
if (buffer.isString()) {
return JSC::JSValue::encode(buffer);
}
throwVMTypeError(lexicalGlobalObject, throwScope, "Expected Uint8Array"_s);
return JSValue::encode(jsUndefined());
}
RELEASE_AND_RETURN(throwScope, JSC::JSValue::encode(castedThis->write(vm, lexicalGlobalObject, reinterpret_cast<uint8_t*>(view->vector()), view->byteLength())));
}
static inline JSC::EncodedJSValue jsStringDecoderPrototypeFunction_endBody(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame, JSStringDecoder* 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::JSArrayBufferView* view = JSC::jsDynamicCast<JSC::JSArrayBufferView*>(buffer);
if (UNLIKELY(!view || view->isDetached())) {
throwVMTypeError(lexicalGlobalObject, throwScope, "Expected Uint8Array"_s);
return JSValue::encode(jsUndefined());
}
RELEASE_AND_RETURN(throwScope, JSC::JSValue::encode(castedThis->end(vm, lexicalGlobalObject, reinterpret_cast<uint8_t*>(view->vector()), view->byteLength())));
}
static inline JSC::EncodedJSValue jsStringDecoderPrototypeFunction_textBody(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame, JSStringDecoder* 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::JSArrayBufferView* view = JSC::jsDynamicCast<JSC::JSArrayBufferView*>(buffer);
if (UNLIKELY(!view || view->isDetached())) {
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()));
uint32_t byteLength = view->byteLength();
if (offset > byteLength)
RELEASE_AND_RETURN(throwScope, JSC::JSValue::encode(JSC::jsEmptyString(vm)));
RELEASE_AND_RETURN(throwScope, JSC::JSValue::encode(castedThis->write(vm, lexicalGlobalObject, reinterpret_cast<uint8_t*>(view->vector()) + offset, byteLength - offset)));
}
JSC_DEFINE_HOST_FUNCTION(jsStringDecoderPrototypeFunction_write,
(JSC::JSGlobalObject * globalObject, JSC::CallFrame* callFrame))
{
JSValue stringDecoderValue = JSValue::decode(jsStringDecoderCast(globalObject, callFrame->thisValue()));
if (stringDecoderValue.isEmpty() || !stringDecoderValue.isCell()) {
return JSValue::encode(stringDecoderValue);
}
JSStringDecoder* castedThis = jsCast<JSStringDecoder*>(stringDecoderValue);
return jsStringDecoderPrototypeFunction_writeBody(globalObject, callFrame, castedThis);
}
JSC_DEFINE_HOST_FUNCTION(jsStringDecoderPrototypeFunction_end,
(JSC::JSGlobalObject * globalObject, JSC::CallFrame* callFrame))
{
JSValue stringDecoderValue = JSValue::decode(jsStringDecoderCast(globalObject, callFrame->thisValue()));
if (stringDecoderValue.isEmpty() || !stringDecoderValue.isCell()) {
return JSValue::encode(stringDecoderValue);
}
JSStringDecoder* castedThis = jsCast<JSStringDecoder*>(stringDecoderValue);
return jsStringDecoderPrototypeFunction_endBody(globalObject, callFrame, castedThis);
}
JSC_DEFINE_HOST_FUNCTION(jsStringDecoderPrototypeFunction_text,
(JSC::JSGlobalObject * globalObject, JSC::CallFrame* callFrame))
{
JSValue stringDecoderValue = JSValue::decode(jsStringDecoderCast(globalObject, callFrame->thisValue()));
if (stringDecoderValue.isEmpty() || !stringDecoderValue.isCell()) {
return JSValue::encode(stringDecoderValue);
}
JSStringDecoder* castedThis = jsCast<JSStringDecoder*>(stringDecoderValue);
return jsStringDecoderPrototypeFunction_textBody(globalObject, callFrame, castedThis);
}
static JSC_DEFINE_CUSTOM_GETTER(jsStringDecoder_lastChar, (JSGlobalObject * lexicalGlobalObject, JSC::EncodedJSValue thisValue, PropertyName attributeName))
{
auto& vm = JSC::getVM(lexicalGlobalObject);
JSValue stringDecoderValue = JSValue::decode(jsStringDecoderCast(lexicalGlobalObject, JSValue::decode(thisValue)));
if (stringDecoderValue.isEmpty() || !stringDecoderValue.isCell()) {
return JSValue::encode(stringDecoderValue);
}
JSStringDecoder* thisObject = jsCast<JSStringDecoder*>(stringDecoderValue);
auto throwScope = DECLARE_THROW_SCOPE(vm);
auto buffer = ArrayBuffer::createFromBytes(thisObject->m_lastChar, 4, nullptr);
auto* globalObject = reinterpret_cast<Zig::GlobalObject*>(lexicalGlobalObject);
JSC::JSUint8Array* uint8Array = JSC::JSUint8Array::create(lexicalGlobalObject, globalObject->JSBufferSubclassStructure(), WTFMove(buffer), 0, 4);
RELEASE_AND_RETURN(throwScope, JSC::JSValue::encode(uint8Array));
}
static JSC_DEFINE_CUSTOM_GETTER(jsStringDecoder_lastNeed, (JSGlobalObject * lexicalGlobalObject, JSC::EncodedJSValue thisValue, PropertyName attributeName))
{
auto& vm = JSC::getVM(lexicalGlobalObject);
JSValue stringDecoderValue = JSValue::decode(jsStringDecoderCast(lexicalGlobalObject, JSValue::decode(thisValue)));
if (stringDecoderValue.isEmpty() || !stringDecoderValue.isCell()) {
return JSValue::encode(stringDecoderValue);
}
JSStringDecoder* thisObject = jsCast<JSStringDecoder*>(stringDecoderValue);
auto throwScope = DECLARE_THROW_SCOPE(vm);
RELEASE_AND_RETURN(throwScope, JSC::JSValue::encode(JSC::jsNumber(thisObject->m_lastNeed)));
}
static JSC_DEFINE_CUSTOM_GETTER(jsStringDecoder_lastTotal, (JSGlobalObject * lexicalGlobalObject, JSC::EncodedJSValue thisValue, PropertyName attributeName))
{
auto& vm = JSC::getVM(lexicalGlobalObject);
JSValue stringDecoderValue = JSValue::decode(jsStringDecoderCast(lexicalGlobalObject, JSValue::decode(thisValue)));
if (stringDecoderValue.isEmpty() || !stringDecoderValue.isCell()) {
return JSValue::encode(stringDecoderValue);
}
JSStringDecoder* thisObject = jsCast<JSStringDecoder*>(stringDecoderValue);
auto throwScope = DECLARE_THROW_SCOPE(vm);
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);
if (encoding_.isString()) {
std::optional<BufferEncodingType> opt = parseEnumeration<BufferEncodingType>(*lexicalGlobalObject, encoding_);
if (opt.has_value()) {
encoding = opt.value();
}
}
}
JSValue thisValue = callFrame->newTarget();
auto* globalObject = JSC::jsCast<Zig::GlobalObject*>(lexicalGlobalObject);
JSObject* newTarget = asObject(thisValue);
auto* constructor = globalObject->JSStringDecoder();
Structure* structure = globalObject->JSStringDecoderStructure();
JSStringDecoder* jsObject = JSStringDecoder::create(
vm, lexicalGlobalObject, structure, encoding);
// StringDecodeer is a Weird one
// This is a hack to make express' body-parser work
// It does something weird with the prototype
// Not exactly a subclass
if (constructor != newTarget && callFrame->thisValue().isObject()) {
auto clientData = WebCore::clientData(vm);
JSObject* thisObject = asObject(callFrame->thisValue());
thisObject->putDirect(vm, clientData->builtinNames().decodePrivateName(), jsObject, JSC::PropertyAttribute::DontEnum | 0);
return JSC::JSValue::encode(thisObject);
}
return JSC::JSValue::encode(jsObject);
}
void JSStringDecoderConstructor::initializeProperties(VM& vm, JSC::JSGlobalObject* globalObject, JSStringDecoderPrototype* prototype)
{
putDirect(vm, vm.propertyNames->length, jsNumber(1), JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::DontEnum);
JSString* nameString = jsNontrivialString(vm, "StringDecoder"_s);
m_originalName.set(vm, this, nameString);
putDirect(vm, vm.propertyNames->name, nameString, JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::DontEnum);
putDirect(vm, vm.propertyNames->prototype, prototype, JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::DontEnum | JSC::PropertyAttribute::DontDelete);
}
const ClassInfo JSStringDecoderConstructor::s_info = { "StringDecoder"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSStringDecoderConstructor) };
} // namespace Zig