diff --git a/client/src/classes/TextDecoder.cpp b/client/src/classes/TextDecoder.cpp new file mode 100644 index 000000000..cc0bea2d0 --- /dev/null +++ b/client/src/classes/TextDecoder.cpp @@ -0,0 +1,5 @@ +#include "Class.h" + +extern js::Class textDecoderClass("TextDecoder", [](js::ClassTemplate& tpl) +{ +}); diff --git a/client/src/classes/TextEncoder.cpp b/client/src/classes/TextEncoder.cpp new file mode 100644 index 000000000..7dd1ed933 --- /dev/null +++ b/client/src/classes/TextEncoder.cpp @@ -0,0 +1,57 @@ +#include "Class.h" + +static void EncodingGetter(js::LazyPropertyContext& ctx) +{ + ctx.Return(std::string("utf-8")); +} + + +static void Encode(js::FunctionContext& ctx) +{ + if (!ctx.CheckArgCount(1)) return; + + std::string str; + if (!ctx.GetArg(0, str)) return; + + size_t size = str.size(); + v8::Local buffer = v8::ArrayBuffer::New(ctx.GetIsolate(), size); + std::shared_ptr backingStore = buffer->GetBackingStore(); + memcpy(backingStore->Data(), str.data(), size); + + ctx.Return(v8::Uint8Array::New(buffer, 0, size)); +} + +static void EncodeInto(js::FunctionContext& ctx) +{ + if (!ctx.CheckArgCount(2)) return; + + v8::Local value; + if (!ctx.GetArg(0, value)) return; + if (!ctx.Check(value->IsString(), "Argument 0 must be a string")) return; + + v8::Local arr; + if (!ctx.GetArg(1, arr)) return; + if (!ctx.Check(arr->IsUint8Array(), "Argument 1 must be a Uint8Array")) return; + + v8::Local str = value.As(); + v8::Local uint8Array = arr.As(); + + v8::Local buffer = uint8Array->Buffer(); + char* data = (char*)((uintptr_t)buffer->GetBackingStore()->Data() + uint8Array->ByteOffset()); + + size_t length = uint8Array->ByteLength(); + size_t writeSize = str->WriteUtf8(ctx.GetIsolate(), data, length, nullptr, v8::String::NO_NULL_TERMINATION | v8::String::REPLACE_INVALID_UTF8); + + js::Object result; + result.Set("read", writeSize); + result.Set("written", writeSize); + ctx.Return(result); +} + +extern js::Class textEncoderClass("TextEncoder", [](js::ClassTemplate& tpl) +{ + tpl.LazyProperty("encoding", EncodingGetter); + + tpl.Method("encode", Encode); + tpl.Method("encodeInto", EncodeInto); +}); diff --git a/client/src/modules/AltModule.cpp b/client/src/modules/AltModule.cpp index ede8578f9..23c96c17c 100644 --- a/client/src/modules/AltModule.cpp +++ b/client/src/modules/AltModule.cpp @@ -500,7 +500,8 @@ extern js::Class playerClass, localPlayerClass, vehicleClass, pedClass, objectCl audioClass, audioFilterClass, blipClass, markerClass, textLabelClass, checkpointClass, webViewClass, fontClass, localPedClass, localVehicleClass, rmlDocumentClass, rmlElementClass, localObjectClass, webSocketClientClass, mapZoomDataClass, virtualEntityClass, virtualEntityGroupClass, weaponDataClass, handlingClass, handlingDataClass, - httpClientClass, audioOutputClass, audioOutputAttachedClass, audioOutputFrontendClass, audioOutputWorldClass, audioCategoryClass; + httpClientClass, audioOutputClass, audioOutputAttachedClass, audioOutputFrontendClass, audioOutputWorldClass, audioCategoryClass, + textEncoderClass, textDecoderClass; extern js::Namespace eventsNamespace, discordNamespace, voiceNamespace, localStorageNamespace, statsNamespace, focusDataNamespace, gxtNamespace, cursorNamespace, camNamespace, streamingNamespace, configFlagNamespace; static js::Module altModule("@altv/client", "@altv/shared", @@ -508,7 +509,7 @@ static js::Module altModule("@altv/client", "@altv/shared", &audioClass, &audioFilterClass, &blipClass, &markerClass, &textLabelClass, &checkpointClass, &webViewClass, &fontClass, &localPedClass, &localVehicleClass, &rmlDocumentClass, &rmlElementClass, &localObjectClass, &webSocketClientClass, &mapZoomDataClass, &virtualEntityClass, &virtualEntityGroupClass, &weaponDataClass, &handlingClass, &handlingDataClass, - &httpClientClass, &audioOutputClass, &audioOutputAttachedClass, &audioOutputFrontendClass, &audioOutputWorldClass, &audioCategoryClass }, + &httpClientClass, &audioOutputClass, &audioOutputAttachedClass, &audioOutputFrontendClass, &audioOutputWorldClass, &audioCategoryClass, &textEncoderClass/*, &textDecoderClass*/ }, [](js::ModuleTemplate& module) { module.StaticProperty("isClient", true); module.StaticProperty("isServer", false);