diff options
-rw-r--r-- | src/javascript/jsc/base.zig | 2 | ||||
-rw-r--r-- | src/javascript/jsc/bindings/Buffer.h | 2 | ||||
-rw-r--r-- | src/javascript/jsc/bindings/JSBuffer.cpp | 262 | ||||
-rw-r--r-- | src/javascript/jsc/bindings/JSBufferPrototypeBuiltins.cpp | 193 | ||||
-rw-r--r-- | src/javascript/jsc/bindings/JSBufferPrototypeBuiltins.h | 127 | ||||
-rw-r--r-- | src/javascript/jsc/bindings/WebCoreJSBuiltinInternals.cpp | 1 | ||||
-rw-r--r-- | src/javascript/jsc/bindings/WebCoreJSBuiltinInternals.h | 2 | ||||
-rw-r--r-- | src/javascript/jsc/bindings/WebCoreJSBuiltins.h | 1 | ||||
-rw-r--r-- | src/javascript/jsc/bindings/bindings.zig | 9 | ||||
-rw-r--r-- | src/javascript/jsc/bindings/builtins/js/JSBufferPrototype.js | 73 | ||||
-rw-r--r-- | src/javascript/jsc/bindings/headers-cpp.h | 2 | ||||
-rw-r--r-- | src/javascript/jsc/bindings/headers-handwritten.h | 13 | ||||
-rw-r--r-- | src/javascript/jsc/bindings/headers.h | 2 | ||||
-rw-r--r-- | src/javascript/jsc/webcore/encoding.zig | 251 |
14 files changed, 783 insertions, 157 deletions
diff --git a/src/javascript/jsc/base.zig b/src/javascript/jsc/base.zig index 7abbe1343..d9b46f868 100644 --- a/src/javascript/jsc/base.zig +++ b/src/javascript/jsc/base.zig @@ -2511,7 +2511,7 @@ comptime { std.testing.refAllDecls(RefString); } -export fn MarkedArrayBuffer_deallocator(bytes_: *anyopaque, _: *anyopaque) void { +pub export fn MarkedArrayBuffer_deallocator(bytes_: *anyopaque, _: *anyopaque) void { const mimalloc = @import("../../allocators/mimalloc.zig"); // zig's memory allocator interface won't work here // mimalloc knows the size of things diff --git a/src/javascript/jsc/bindings/Buffer.h b/src/javascript/jsc/bindings/Buffer.h index 6babb4e90..eb7ff26a9 100644 --- a/src/javascript/jsc/bindings/Buffer.h +++ b/src/javascript/jsc/bindings/Buffer.h @@ -9,7 +9,9 @@ #include "BufferEncodingType.h" #include "JavaScriptCore/GenericTypedArrayView.h" +#include "JavaScriptCore/JSBase.h" +extern "C" JSC::EncodedJSValue JSBuffer__bufferFromPointerAndLengthAndDeinit(JSC::JSGlobalObject* lexicalGlobalObject, char* ptr, unsigned int length, void* ctx, JSTypedArrayBytesDeallocator bytesDeallocator); extern "C" JSC::EncodedJSValue Bun__encoding__toStringUTF16(const uint8_t* input, size_t len, JSC::JSGlobalObject* globalObject); extern "C" JSC::EncodedJSValue Bun__encoding__toStringUTF8(const uint8_t* input, size_t len, JSC::JSGlobalObject* globalObject); extern "C" JSC::EncodedJSValue Bun__encoding__toStringASCII(const uint8_t* input, size_t len, JSC::JSGlobalObject* globalObject); diff --git a/src/javascript/jsc/bindings/JSBuffer.cpp b/src/javascript/jsc/bindings/JSBuffer.cpp index 2b8fa2088..d0278844d 100644 --- a/src/javascript/jsc/bindings/JSBuffer.cpp +++ b/src/javascript/jsc/bindings/JSBuffer.cpp @@ -50,6 +50,7 @@ static JSC_DECLARE_HOST_FUNCTION(jsBufferConstructorFunction_concat); static JSC_DECLARE_HOST_FUNCTION(jsBufferConstructorFunction_from); static JSC_DECLARE_HOST_FUNCTION(jsBufferConstructorFunction_isBuffer); static JSC_DECLARE_HOST_FUNCTION(jsBufferConstructorFunction_isEncoding); +static JSC_DECLARE_HOST_FUNCTION(jsBufferConstructorFunction_toBuffer); static JSC_DECLARE_HOST_FUNCTION(jsBufferPrototypeFunction_compare); static JSC_DECLARE_HOST_FUNCTION(jsBufferPrototypeFunction_copy); @@ -64,6 +65,29 @@ static JSC_DECLARE_HOST_FUNCTION(jsBufferPrototypeFunction_swap64); static JSC_DECLARE_HOST_FUNCTION(jsBufferPrototypeFunction_toString); static JSC_DECLARE_HOST_FUNCTION(jsBufferPrototypeFunction_write); +static void toBuffer(JSC::JSGlobalObject* lexicalGlobalObject, JSC::JSUint8Array* uint8Array); + +JSC::EncodedJSValue JSBuffer__bufferFromPointerAndLengthAndDeinit(JSC::JSGlobalObject* lexicalGlobalObject, char* ptr, unsigned int length, void* ctx, JSTypedArrayBytesDeallocator bytesDeallocator) +{ + + JSC::JSUint8Array* uint8Array = nullptr; + + if (LIKELY(length > 0)) { + auto buffer = ArrayBuffer::createFromBytes(ptr, length, createSharedTask<void(void*)>([=](void* p) { + if (bytesDeallocator) + bytesDeallocator(p, ctx); + })); + + uint8Array = JSC::JSUint8Array::create(lexicalGlobalObject, lexicalGlobalObject->typedArrayStructure(JSC::TypeUint8), WTFMove(buffer), 0, length); + } else { + uint8Array = JSC::JSUint8Array::create(lexicalGlobalObject, lexicalGlobalObject->typedArrayStructure(JSC::TypeUint8), 0); + } + + toBuffer(lexicalGlobalObject, uint8Array); + + return JSC::JSValue::encode(uint8Array); +} + namespace WebCore { using namespace JSC; @@ -124,10 +148,38 @@ private: }; STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(JSBufferPrototype, JSBufferPrototype::Base); +bool JSBuffer__isBuffer(JSC::JSGlobalObject* lexicalGlobalObject, JSC::EncodedJSValue value) +{ + VM& vm = lexicalGlobalObject->vm(); + auto clientData = WebCore::clientData(vm); + + auto* jsBuffer = JSC::jsDynamicCast<JSUint8Array*>(vm, JSC::JSValue::decode(value)); + if (!jsBuffer) + return false; + + return !!jsBuffer->getIfPropertyExists(lexicalGlobalObject, clientData->builtinNames().dataViewPrivateName()); +} + static inline JSC::EncodedJSValue jsBufferConstructorFunction_allocBody(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame, typename IDLOperation<JSBuffer>::ClassParameter castedThis) { - auto& vm = JSC::getVM(lexicalGlobalObject); - return JSValue::encode(jsUndefined()); + VM& vm = lexicalGlobalObject->vm(); + auto throwScope = DECLARE_THROW_SCOPE(vm); + auto length = callFrame->uncheckedArgument(0).toInt32(lexicalGlobalObject); + if (length < 0) { + throwRangeError(lexicalGlobalObject, throwScope, "Invalid array length"); + return JSValue::encode(jsUndefined()); + } + + auto arrayBuffer = JSC::ArrayBuffer::tryCreate(length, 1); + if (!arrayBuffer) { + throwOutOfMemoryError(lexicalGlobalObject, throwScope); + return JSValue::encode(jsUndefined()); + } + + auto uint8Array = JSC::JSUint8Array::create(lexicalGlobalObject, lexicalGlobalObject->typedArrayStructure(JSC::TypeUint8), WTFMove(arrayBuffer), 0, length); + toBuffer(lexicalGlobalObject, uint8Array); + + RELEASE_AND_RETURN(throwScope, JSC::JSValue::encode(uint8Array)); } JSC_DEFINE_HOST_FUNCTION(jsBufferConstructorFunction_alloc, (JSGlobalObject * lexicalGlobalObject, CallFrame* callFrame)) { @@ -135,8 +187,16 @@ JSC_DEFINE_HOST_FUNCTION(jsBufferConstructorFunction_alloc, (JSGlobalObject * le } static inline JSC::EncodedJSValue jsBufferConstructorFunction_allocUnsafeBody(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame, typename IDLOperation<WebCore::JSBuffer>::ClassParameter castedThis) { - auto& vm = JSC::getVM(lexicalGlobalObject); - return JSValue::encode(jsUndefined()); + + VM& vm = lexicalGlobalObject->vm(); + + auto throwScope = DECLARE_THROW_SCOPE(vm); + + if (callFrame->argumentCount() < 1) + return throwVMError(lexicalGlobalObject, throwScope, createNotEnoughArgumentsError(lexicalGlobalObject)); + + auto length = callFrame->uncheckedArgument(0).toInt32(lexicalGlobalObject); + RELEASE_AND_RETURN(throwScope, JSBuffer__bufferFromLength(lexicalGlobalObject, length)); } JSC_DEFINE_HOST_FUNCTION(jsBufferConstructorFunction_allocUnsafe, (JSGlobalObject * lexicalGlobalObject, CallFrame* callFrame)) { @@ -144,8 +204,7 @@ JSC_DEFINE_HOST_FUNCTION(jsBufferConstructorFunction_allocUnsafe, (JSGlobalObjec } static inline JSC::EncodedJSValue jsBufferConstructorFunction_allocUnsafeSlowBody(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame, typename IDLOperation<WebCore::JSBuffer>::ClassParameter castedThis) { - auto& vm = JSC::getVM(lexicalGlobalObject); - return JSValue::encode(jsUndefined()); + return jsBufferConstructorFunction_allocUnsafeBody(lexicalGlobalObject, callFrame, castedThis); } JSC_DEFINE_HOST_FUNCTION(jsBufferConstructorFunction_allocUnsafeSlow, (JSGlobalObject * lexicalGlobalObject, CallFrame* callFrame)) { @@ -189,8 +248,10 @@ JSC_DEFINE_HOST_FUNCTION(jsBufferConstructorFunction_from, (JSGlobalObject * lex } static inline JSC::EncodedJSValue jsBufferConstructorFunction_isBufferBody(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame, typename IDLOperation<WebCore::JSBuffer>::ClassParameter castedThis) { - auto& vm = JSC::getVM(lexicalGlobalObject); - return JSValue::encode(jsUndefined()); + if (callFrame->argumentCount() < 1) + return JSC::JSValue::encode(JSC::jsBoolean(false)); + + return JSC::JSValue::encode(JSC::jsBoolean(JSBuffer__isBuffer(lexicalGlobalObject, JSC::JSValue::encode(callFrame->uncheckedArgument(0))))); } JSC_DEFINE_HOST_FUNCTION(jsBufferConstructorFunction_isBuffer, (JSGlobalObject * lexicalGlobalObject, CallFrame* callFrame)) { @@ -206,6 +267,34 @@ JSC_DEFINE_HOST_FUNCTION(jsBufferConstructorFunction_isEncoding, (JSGlobalObject return IDLOperation<WebCore::JSBuffer>::call<jsBufferConstructorFunction_isEncodingBody>(*lexicalGlobalObject, *callFrame, "isEncoding"); } +static inline JSC::EncodedJSValue jsBufferConstructorFunction_toBufferBody(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame, typename IDLOperation<JSBuffer>::ClassParameter castedThis) +{ + auto& vm = JSC::getVM(lexicalGlobalObject); + auto throwScope = DECLARE_THROW_SCOPE(vm); + if (UNLIKELY(callFrame->argumentCount() < 1)) { + throwVMError(lexicalGlobalObject, throwScope, createNotEnoughArgumentsError(lexicalGlobalObject)); + return JSValue::encode(jsUndefined()); + } + + auto buffer = callFrame->uncheckedArgument(0); + if (!buffer.isCell() || !JSC::isTypedView(buffer.asCell()->classInfo(vm)->typedArrayStorageType)) { + throwVMTypeError(lexicalGlobalObject, throwScope, "Expected Uint8Array"_s); + } + + JSC::JSUint8Array* view = JSC::jsDynamicCast<JSC::JSUint8Array*>(vm, buffer); + + if (!view) { + throwVMTypeError(lexicalGlobalObject, throwScope, "Expected Uint8Array"_s); + return JSValue::encode(jsUndefined()); + } + toBuffer(lexicalGlobalObject, view); + RELEASE_AND_RETURN(throwScope, JSC::JSValue::encode(view)); +} +JSC_DEFINE_HOST_FUNCTION(jsBufferConstructorFunction_toBuffer, (JSGlobalObject * lexicalGlobalObject, CallFrame* callFrame)) +{ + return IDLOperation<JSBuffer>::call<jsBufferConstructorFunction_toBufferBody>(*lexicalGlobalObject, *callFrame, "toBuffer"); +} + using JSBufferConstructor = JSDOMConstructor<JSBuffer>; /* Hash table for constructor */ @@ -213,7 +302,7 @@ static const HashTableValue JSBufferConstructorTableValues[] = { { "construct", static_cast<unsigned>(JSC::PropertyAttribute::Builtin, JSC::PropertyAttribute::DontEnum, JSC::PropertyAttribute::DontDelete), NoIntrinsic, { (intptr_t) static_cast<BuiltinGenerator>(jsBufferPrototypeBufferConstructorCodeGenerator), (intptr_t)(3) } }, { "alloc", static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { (intptr_t) static_cast<RawNativeFunction>(jsBufferConstructorFunction_alloc), (intptr_t)(3) } }, { "allocUnsafe", static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { (intptr_t) static_cast<RawNativeFunction>(jsBufferConstructorFunction_allocUnsafe), (intptr_t)(1) } }, - { "allocUnsafeSlow", static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { (intptr_t) static_cast<RawNativeFunction>(jsBufferConstructorFunction_allocUnsafeSlow), (intptr_t)(1) } }, + { "allocUnsafeSlow", static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { (intptr_t) static_cast<RawNativeFunction>(jsBufferConstructorFunction_allocUnsafe), (intptr_t)(1) } }, { "byteLength", static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { (intptr_t) static_cast<RawNativeFunction>(jsBufferConstructorFunction_byteLength), (intptr_t)(2) } }, { "compare", static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { (intptr_t) static_cast<RawNativeFunction>(jsBufferConstructorFunction_compare), (intptr_t)(2) } }, { "concat", static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { (intptr_t) static_cast<RawNativeFunction>(jsBufferConstructorFunction_concat), (intptr_t)(2) } }, @@ -223,61 +312,26 @@ static const HashTableValue JSBufferConstructorTableValues[] = { // new Buffer() static inline EncodedJSValue constructBufferEmpty(JSGlobalObject* lexicalGlobalObject, CallFrame* callFrame) { - VM& vm = lexicalGlobalObject->vm(); - auto throwScope = DECLARE_THROW_SCOPE(vm); - auto* castedThis = jsCast<JSBufferConstructor*>(callFrame->jsCallee()); - ASSERT(castedThis); - auto object = Buffer::createEmpty(lexicalGlobalObject); - auto jsValue = toJSNewlyCreated<IDLInterface<Buffer>>(*lexicalGlobalObject, *castedThis->globalObject(), throwScope, WTFMove(object)); - if constexpr (IsExceptionOr<decltype(object)>) - RETURN_IF_EXCEPTION(throwScope, {}); - setSubclassStructureIfNeeded<Buffer>(lexicalGlobalObject, callFrame, asObject(jsValue)); - RETURN_IF_EXCEPTION(throwScope, {}); - return JSValue::encode(jsValue); + return JSBuffer__bufferFromLength(lexicalGlobalObject, 0); } -// new Buffer(array) -static inline EncodedJSValue constructBufferFromArray(JSGlobalObject* lexicalGlobalObject, CallFrame* callFrame) +// new Buffer(size) +static inline EncodedJSValue constructBufferFromLength(JSGlobalObject* lexicalGlobalObject, CallFrame* callFrame) { - VM& vm = lexicalGlobalObject->vm(); - auto throwScope = DECLARE_THROW_SCOPE(vm); - auto* castedThis = jsCast<JSBufferConstructor*>(callFrame->jsCallee()); - ASSERT(castedThis); - EnsureStillAliveScope argument0 = callFrame->uncheckedArgument(0); + return jsBufferConstructorFunction_allocUnsafeBody(lexicalGlobalObject, callFrame, nullptr); } -// new Buffer(arrayBuffer[, byteOffset[, length]]) -static inline EncodedJSValue constructBufferFromArrayBuffer(JSGlobalObject* lexicalGlobalObject, CallFrame* callFrame) +static inline JSC::EncodedJSValue constructBufferFromStringAndEncoding(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame, typename IDLOperation<JSBuffer>::ClassParameter castedThis) { - VM& vm = lexicalGlobalObject->vm(); - auto throwScope = DECLARE_THROW_SCOPE(vm); - auto* castedThis = jsCast<JSBufferConstructor*>(callFrame->jsCallee()); - ASSERT(castedThis); - EnsureStillAliveScope argument0 = callFrame->uncheckedArgument(0); -} + auto& vm = JSC::getVM(lexicalGlobalObject); + uint32_t offset = 0; + uint32_t length = castedThis->length(); + WebCore::BufferEncodingType encoding = WebCore::BufferEncodingType::utf8; -// new Buffer(buffer) -static inline EncodedJSValue constructBufferFromBuffer(JSGlobalObject* lexicalGlobalObject, CallFrame* callFrame) -{ - VM& vm = lexicalGlobalObject->vm(); - auto throwScope = DECLARE_THROW_SCOPE(vm); - auto* castedThis = jsCast<JSBufferConstructor*>(callFrame->jsCallee()); - ASSERT(castedThis); - EnsureStillAliveScope argument0 = callFrame->uncheckedArgument(0); -} + auto scope = DECLARE_THROW_SCOPE(vm); -// new Buffer(size) -static inline EncodedJSValue constructBufferFromLength(JSGlobalObject* lexicalGlobalObject, CallFrame* callFrame) -{ - VM& vm = lexicalGlobalObject->vm(); - auto throwScope = DECLARE_THROW_SCOPE(vm); - auto* castedThis = jsCast<JSBufferConstructor*>(callFrame->jsCallee()); - ASSERT(castedThis); - auto length = callFrame->uncheckedArgument(0).toInt32(lexicalGlobalObject); - if (length < 0) { - throwRangeError(lexicalGlobalObject, throwScope, "Invalid array length"); - return JSValue::encode(jsUndefined()); - } + EnsureStillAliveScope arg0 = callFrame->argument(0); + auto* str = arg0.value().toString(lexicalGlobalObject); auto globalObject = reinterpret_cast<WebCore::JSDOMGlobalObject*>(lexicalGlobalObject); @@ -298,19 +352,36 @@ static inline EncodedJSValue constructBufferFromLength(JSGlobalObject* lexicalGl return JSC::JSValue::encode(buffer); } -// new Buffer(string[, encoding]) -static inline EncodedJSValue constructBufferFromStringAndEncoding(JSGlobalObject* lexicalGlobalObject, CallFrame* callFrame) -{ - VM& vm = lexicalGlobalObject->vm(); - auto throwScope = DECLARE_THROW_SCOPE(vm); - auto* castedThis = jsCast<JSBufferConstructor*>(callFrame->jsCallee()); - ASSERT(castedThis); - EnsureStillAliveScope string = callFrame->uncheckedArgument(0); + case WebCore::BufferEncodingType::base64url: { + if (view.is8Bit()) { + result = Bun__encoding__constructFromLatin1AsURLSafeBase64(lexicalGlobalObject, view.characters8(), view.length()); + } else { + result = Bun__encoding__constructFromUTF16AsURLSafeBase64(lexicalGlobalObject, view.characters16(), view.length()); + } + break; + } - JSC::JSValue optionalEncodingValue = jsUndefined(); - if (callFrame->argumentCount() > 1) { - optionalEncodingValue = callFrame->uncheckedArgument(1); + case WebCore::BufferEncodingType::hex: { + if (view.is8Bit()) { + result = Bun__encoding__constructFromLatin1AsHex(lexicalGlobalObject, view.characters8(), view.length()); + } else { + result = Bun__encoding__constructFromUTF16AsHex(lexicalGlobalObject, view.characters16(), view.length()); + } + break; + } + } + JSC::JSValue decoded = JSC::JSValue::decode(result); + if (UNLIKELY(!result)) { + throwTypeError(lexicalGlobalObject, scope, "An error occurred while decoding the string"_s); + return JSC::JSValue::encode(jsUndefined()); + } + + if (decoded.isCell() && decoded.getObject()->isErrorInstance()) { + scope.throwException(lexicalGlobalObject, decoded); + return JSC::JSValue::encode(jsUndefined()); } + + RELEASE_AND_RETURN(scope, result); } template<> EncodedJSValue JSC_HOST_CALL_ATTRIBUTES JSBufferConstructor::construct(JSGlobalObject* lexicalGlobalObject, CallFrame* callFrame) @@ -325,16 +396,27 @@ template<> EncodedJSValue JSC_HOST_CALL_ATTRIBUTES JSBufferConstructor::construc JSValue distinguishingArg = callFrame->uncheckedArgument(0); if (distinguishingArg.isNumber()) { RELEASE_AND_RETURN(throwScope, (constructBufferFromLength(lexicalGlobalObject, callFrame))); + } else if (distinguishingArg.isString()) { + RELEASE_AND_RETURN(throwScope, (constructBufferFromStringAndEncoding(lexicalGlobalObject, callFrame, nullptr))); } - // if (argsCount == 2) { - // if (distinguishingArg.isUndefined()) - // RELEASE_AND_RETURN(throwScope, (constructJSBuffer1(lexicalGlobalObject, callFrame))); - // if (distinguishingArg.isObject() && asObject(distinguishingArg)->inherits<JSBuffer>(vm)) - // RELEASE_AND_RETURN(throwScope, (constructJSBuffer2(lexicalGlobalObject, callFrame))); - // RELEASE_AND_RETURN(throwScope, (constructJSBuffer1(lexicalGlobalObject, callFrame))); - // } - return argsCount < 1 ? throwVMError(lexicalGlobalObject, throwScope, createNotEnoughArgumentsError(lexicalGlobalObject)) : throwVMTypeError(lexicalGlobalObject, throwScope); + JSC::JSObject* constructor = lexicalGlobalObject->m_typedArrayUint8.constructor(lexicalGlobalObject); + + // TODO: avoid this copy + MarkedArgumentBuffer args; + for (size_t i = 0; i < argsCount; ++i) + args.append(callFrame->uncheckedArgument(i)); + + JSC::JSObject* object = JSC::construct(lexicalGlobalObject, constructor, callFrame->newTarget(), args, "Failed to construct 'Buffer' object"_s); + if (!object) { + return JSC::JSValue::encode(JSC::jsUndefined()); + } + + auto value = JSC::JSValue(object); + + toBuffer(lexicalGlobalObject, JSC::jsCast<JSC::JSUint8Array*>(value)); + + RELEASE_AND_RETURN(throwScope, JSC::JSValue::encode(value)); } JSC_ANNOTATE_HOST_FUNCTION(JSBufferConstructorConstruct, JSBufferConstructor::construct); @@ -708,10 +790,18 @@ JSC_DEFINE_HOST_FUNCTION(jsBufferPrototypeFunction_write, (JSGlobalObject * lexi static const HashTableValue JSBufferPrototypeTableValues[] = { + { "asciiSlice", static_cast<unsigned>(JSC::PropertyAttribute::DontEnum | JSC::PropertyAttribute::Builtin), NoIntrinsic, { (intptr_t) static_cast<BuiltinGenerator>(jsBufferPrototypeAsciiSliceCodeGenerator), (intptr_t)(2) } }, + { "asciiWrite", static_cast<unsigned>(JSC::PropertyAttribute::DontEnum | JSC::PropertyAttribute::Builtin), NoIntrinsic, { (intptr_t) static_cast<BuiltinGenerator>(jsBufferPrototypeAsciiWriteCodeGenerator), (intptr_t)(1) } }, + { "base64Slice", static_cast<unsigned>(JSC::PropertyAttribute::DontEnum | JSC::PropertyAttribute::Builtin), NoIntrinsic, { (intptr_t) static_cast<BuiltinGenerator>(jsBufferPrototypeBase64SliceCodeGenerator), (intptr_t)(2) } }, + { "base64urlSlice", static_cast<unsigned>(JSC::PropertyAttribute::DontEnum | JSC::PropertyAttribute::Builtin), NoIntrinsic, { (intptr_t) static_cast<BuiltinGenerator>(jsBufferPrototypeBase64urlSliceCodeGenerator), (intptr_t)(2) } }, + { "base64urlWrite", static_cast<unsigned>(JSC::PropertyAttribute::DontEnum | JSC::PropertyAttribute::Builtin), NoIntrinsic, { (intptr_t) static_cast<BuiltinGenerator>(jsBufferPrototypeBase64urlWriteCodeGenerator), (intptr_t)(1) } }, + { "base64Write", static_cast<unsigned>(JSC::PropertyAttribute::DontEnum | JSC::PropertyAttribute::Builtin), NoIntrinsic, { (intptr_t) static_cast<BuiltinGenerator>(jsBufferPrototypeBase64WriteCodeGenerator), (intptr_t)(1) } }, { "compare", static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { (intptr_t) static_cast<RawNativeFunction>(jsBufferPrototypeFunction_compare), (intptr_t)(5) } }, { "copy", static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { (intptr_t) static_cast<RawNativeFunction>(jsBufferPrototypeFunction_copy), (intptr_t)(4) } }, { "equals", static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { (intptr_t) static_cast<RawNativeFunction>(jsBufferPrototypeFunction_equals), (intptr_t)(1) } }, { "fill", static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { (intptr_t) static_cast<RawNativeFunction>(jsBufferPrototypeFunction_fill), (intptr_t)(4) } }, + { "hexSlice", static_cast<unsigned>(JSC::PropertyAttribute::DontEnum | JSC::PropertyAttribute::Builtin), NoIntrinsic, { (intptr_t) static_cast<BuiltinGenerator>(jsBufferPrototypeHexSliceCodeGenerator), (intptr_t)(2) } }, + { "hexWrite", static_cast<unsigned>(JSC::PropertyAttribute::DontEnum | JSC::PropertyAttribute::Builtin), NoIntrinsic, { (intptr_t) static_cast<BuiltinGenerator>(jsBufferPrototypeHexWriteCodeGenerator), (intptr_t)(1) } }, { "includes", static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { (intptr_t) static_cast<RawNativeFunction>(jsBufferPrototypeFunction_includes), (intptr_t)(3) } }, { "indexOf", static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { (intptr_t) static_cast<RawNativeFunction>(jsBufferPrototypeFunction_indexOf), (intptr_t)(3) } }, { "lastIndexOf", static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { (intptr_t) static_cast<RawNativeFunction>(jsBufferPrototypeFunction_lastIndexOf), (intptr_t)(3) } }, @@ -719,6 +809,12 @@ static const HashTableValue JSBufferPrototypeTableValues[] { "swap32", static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { (intptr_t) static_cast<RawNativeFunction>(jsBufferPrototypeFunction_swap32), (intptr_t)(0) } }, { "swap64", static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { (intptr_t) static_cast<RawNativeFunction>(jsBufferPrototypeFunction_swap64), (intptr_t)(0) } }, { "toString", static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { (intptr_t) static_cast<RawNativeFunction>(jsBufferPrototypeFunction_toString), (intptr_t)(4) } }, + { "ucs2Slice", static_cast<unsigned>(JSC::PropertyAttribute::DontEnum | JSC::PropertyAttribute::Builtin), NoIntrinsic, { (intptr_t) static_cast<BuiltinGenerator>(jsBufferPrototypeUcs2SliceCodeGenerator), (intptr_t)(2) } }, + { "ucs2Write", static_cast<unsigned>(JSC::PropertyAttribute::DontEnum | JSC::PropertyAttribute::Builtin), NoIntrinsic, { (intptr_t) static_cast<BuiltinGenerator>(jsBufferPrototypeUcs2WriteCodeGenerator), (intptr_t)(1) } }, + { "utf16leSlice", static_cast<unsigned>(JSC::PropertyAttribute::DontEnum | JSC::PropertyAttribute::Builtin), NoIntrinsic, { (intptr_t) static_cast<BuiltinGenerator>(jsBufferPrototypeUtf16leSliceCodeGenerator), (intptr_t)(2) } }, + { "utf16leWrite", static_cast<unsigned>(JSC::PropertyAttribute::DontEnum | JSC::PropertyAttribute::Builtin), NoIntrinsic, { (intptr_t) static_cast<BuiltinGenerator>(jsBufferPrototypeUtf16leWriteCodeGenerator), (intptr_t)(1) } }, + { "utf8Slice", static_cast<unsigned>(JSC::PropertyAttribute::DontEnum | JSC::PropertyAttribute::Builtin), NoIntrinsic, { (intptr_t) static_cast<BuiltinGenerator>(jsBufferPrototypeUtf8SliceCodeGenerator), (intptr_t)(2) } }, + { "utf8Write", static_cast<unsigned>(JSC::PropertyAttribute::DontEnum | JSC::PropertyAttribute::Builtin), NoIntrinsic, { (intptr_t) static_cast<BuiltinGenerator>(jsBufferPrototypeUtf8WriteCodeGenerator), (intptr_t)(1) } }, { "write", static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { (intptr_t) static_cast<RawNativeFunction>(jsBufferPrototypeFunction_write), (intptr_t)(4) } }, { "readBigInt64BE", static_cast<unsigned>(JSC::PropertyAttribute::Builtin), NoIntrinsic, { (intptr_t) static_cast<BuiltinGenerator>(jsBufferPrototypeReadBigInt64BECodeGenerator), (intptr_t)(2) } }, { "readBigInt64LE", static_cast<unsigned>(JSC::PropertyAttribute::Builtin), NoIntrinsic, { (intptr_t) static_cast<BuiltinGenerator>(jsBufferPrototypeReadBigInt64LECodeGenerator), (intptr_t)(2) } }, @@ -880,4 +976,18 @@ Buffer* JSBuffer::toWrapped(JSC::VM& vm, JSC::JSValue value) return nullptr; } -} // namespace WebCore
\ No newline at end of file +} // namespace WebCore + +static void toBuffer(JSC::JSGlobalObject* lexicalGlobalObject, JSC::JSUint8Array* uint8Array) +{ + JSC::VM& vm = lexicalGlobalObject->vm(); + auto clientData = WebCore::clientData(vm); + JSC::JSObject* object = JSC::JSValue(uint8Array).getObject(); + + object->setPrototypeDirect(vm, WebCore::JSBuffer::prototype(vm, *JSC::jsCast<WebCore::JSDOMGlobalObject*>(lexicalGlobalObject))); + + auto* dataView = JSC::JSDataView::create(lexicalGlobalObject, lexicalGlobalObject->typedArrayStructure(JSC::TypeDataView), uint8Array->possiblySharedBuffer(), uint8Array->byteOffset(), uint8Array->length()); + object->putDirectWithoutTransition(vm, clientData->builtinNames().dataViewPublicName(), dataView, JSC::PropertyAttribute::DontEnum | JSC::PropertyAttribute::DontDelete | JSC::PropertyAttribute::ReadOnly); + // Mark it + object->putDirectWithoutTransition(vm, clientData->builtinNames().dataViewPrivateName(), JSC::JSValue(true), JSC::PropertyAttribute::DontEnum | JSC::PropertyAttribute::DontDelete | JSC::PropertyAttribute::ReadOnly); +}
\ No newline at end of file diff --git a/src/javascript/jsc/bindings/JSBufferPrototypeBuiltins.cpp b/src/javascript/jsc/bindings/JSBufferPrototypeBuiltins.cpp index 25dda8bbc..83c790a17 100644 --- a/src/javascript/jsc/bindings/JSBufferPrototypeBuiltins.cpp +++ b/src/javascript/jsc/bindings/JSBufferPrototypeBuiltins.cpp @@ -480,7 +480,7 @@ const char* const s_jsBufferPrototypeWriteBigUInt64BECode = const JSC::ConstructAbility s_jsBufferPrototypeSliceCodeConstructAbility = JSC::ConstructAbility::CannotConstruct; const JSC::ConstructorKind s_jsBufferPrototypeSliceCodeConstructorKind = JSC::ConstructorKind::None; -const int s_jsBufferPrototypeSliceCodeLength = 152; +const int s_jsBufferPrototypeSliceCodeLength = 309; static const JSC::Intrinsic s_jsBufferPrototypeSliceCodeIntrinsic = JSC::NoIntrinsic; const char* const s_jsBufferPrototypeSliceCode = "(function (start, end) {\n" \ @@ -489,24 +489,187 @@ const char* const s_jsBufferPrototypeSliceCode = " return this;\n" \ " }\n" \ "\n" \ - " return this.subarray(start, end);\n" \ + " if (Buffer[Symbol.species] !== Buffer) {\n" \ + " Buffer[Symbol.species] = Buffer;\n" \ + " }\n" \ + "\n" \ + " return new Buffer(this.buffer, this.byteOffset + (start || 0), (end || this.byteLength) - (start || 0));\n" \ "})\n" \ ; -const JSC::ConstructAbility s_jsBufferPrototypeSubarrayCodeConstructAbility = JSC::ConstructAbility::CannotConstruct; -const JSC::ConstructorKind s_jsBufferPrototypeSubarrayCodeConstructorKind = JSC::ConstructorKind::None; -const int s_jsBufferPrototypeSubarrayCodeLength = 247; -static const JSC::Intrinsic s_jsBufferPrototypeSubarrayCodeIntrinsic = JSC::NoIntrinsic; -const char* const s_jsBufferPrototypeSubarrayCode = - "(function (start, end) {\n" \ +const JSC::ConstructAbility s_jsBufferPrototypeUtf8WriteCodeConstructAbility = JSC::ConstructAbility::CannotConstruct; +const JSC::ConstructorKind s_jsBufferPrototypeUtf8WriteCodeConstructorKind = JSC::ConstructorKind::None; +const int s_jsBufferPrototypeUtf8WriteCodeLength = 105; +static const JSC::Intrinsic s_jsBufferPrototypeUtf8WriteCodeIntrinsic = JSC::NoIntrinsic; +const char* const s_jsBufferPrototypeUtf8WriteCode = + "(function (text, offset, length) {\n" \ + " \"use strict\";\n" \ + " return this.write(text, offset, length, \"utf8\");\n" \ + "})\n" \ +; + +const JSC::ConstructAbility s_jsBufferPrototypeUcs2WriteCodeConstructAbility = JSC::ConstructAbility::CannotConstruct; +const JSC::ConstructorKind s_jsBufferPrototypeUcs2WriteCodeConstructorKind = JSC::ConstructorKind::None; +const int s_jsBufferPrototypeUcs2WriteCodeLength = 105; +static const JSC::Intrinsic s_jsBufferPrototypeUcs2WriteCodeIntrinsic = JSC::NoIntrinsic; +const char* const s_jsBufferPrototypeUcs2WriteCode = + "(function (text, offset, length) {\n" \ + " \"use strict\";\n" \ + " return this.write(text, offset, length, \"ucs2\");\n" \ + "})\n" \ +; + +const JSC::ConstructAbility s_jsBufferPrototypeUtf16leWriteCodeConstructAbility = JSC::ConstructAbility::CannotConstruct; +const JSC::ConstructorKind s_jsBufferPrototypeUtf16leWriteCodeConstructorKind = JSC::ConstructorKind::None; +const int s_jsBufferPrototypeUtf16leWriteCodeLength = 108; +static const JSC::Intrinsic s_jsBufferPrototypeUtf16leWriteCodeIntrinsic = JSC::NoIntrinsic; +const char* const s_jsBufferPrototypeUtf16leWriteCode = + "(function (text, offset, length) {\n" \ + " \"use strict\";\n" \ + " return this.write(text, offset, length, \"utf16le\");\n" \ + "})\n" \ +; + +const JSC::ConstructAbility s_jsBufferPrototypeLatin1WriteCodeConstructAbility = JSC::ConstructAbility::CannotConstruct; +const JSC::ConstructorKind s_jsBufferPrototypeLatin1WriteCodeConstructorKind = JSC::ConstructorKind::None; +const int s_jsBufferPrototypeLatin1WriteCodeLength = 107; +static const JSC::Intrinsic s_jsBufferPrototypeLatin1WriteCodeIntrinsic = JSC::NoIntrinsic; +const char* const s_jsBufferPrototypeLatin1WriteCode = + "(function (text, offset, length) {\n" \ + " \"use strict\";\n" \ + " return this.write(text, offset, length, \"latin1\");\n" \ + "})\n" \ +; + +const JSC::ConstructAbility s_jsBufferPrototypeAsciiWriteCodeConstructAbility = JSC::ConstructAbility::CannotConstruct; +const JSC::ConstructorKind s_jsBufferPrototypeAsciiWriteCodeConstructorKind = JSC::ConstructorKind::None; +const int s_jsBufferPrototypeAsciiWriteCodeLength = 106; +static const JSC::Intrinsic s_jsBufferPrototypeAsciiWriteCodeIntrinsic = JSC::NoIntrinsic; +const char* const s_jsBufferPrototypeAsciiWriteCode = + "(function (text, offset, length) {\n" \ + " \"use strict\";\n" \ + " return this.write(text, offset, length, \"ascii\");\n" \ + "})\n" \ +; + +const JSC::ConstructAbility s_jsBufferPrototypeBase64WriteCodeConstructAbility = JSC::ConstructAbility::CannotConstruct; +const JSC::ConstructorKind s_jsBufferPrototypeBase64WriteCodeConstructorKind = JSC::ConstructorKind::None; +const int s_jsBufferPrototypeBase64WriteCodeLength = 107; +static const JSC::Intrinsic s_jsBufferPrototypeBase64WriteCodeIntrinsic = JSC::NoIntrinsic; +const char* const s_jsBufferPrototypeBase64WriteCode = + "(function (text, offset, length) {\n" \ + " \"use strict\";\n" \ + " return this.write(text, offset, length, \"base64\");\n" \ + "})\n" \ +; + +const JSC::ConstructAbility s_jsBufferPrototypeBase64urlWriteCodeConstructAbility = JSC::ConstructAbility::CannotConstruct; +const JSC::ConstructorKind s_jsBufferPrototypeBase64urlWriteCodeConstructorKind = JSC::ConstructorKind::None; +const int s_jsBufferPrototypeBase64urlWriteCodeLength = 110; +static const JSC::Intrinsic s_jsBufferPrototypeBase64urlWriteCodeIntrinsic = JSC::NoIntrinsic; +const char* const s_jsBufferPrototypeBase64urlWriteCode = + "(function (text, offset, length) {\n" \ + " \"use strict\";\n" \ + " return this.write(text, offset, length, \"base64url\");\n" \ + "})\n" \ +; + +const JSC::ConstructAbility s_jsBufferPrototypeHexWriteCodeConstructAbility = JSC::ConstructAbility::CannotConstruct; +const JSC::ConstructorKind s_jsBufferPrototypeHexWriteCodeConstructorKind = JSC::ConstructorKind::None; +const int s_jsBufferPrototypeHexWriteCodeLength = 104; +static const JSC::Intrinsic s_jsBufferPrototypeHexWriteCodeIntrinsic = JSC::NoIntrinsic; +const char* const s_jsBufferPrototypeHexWriteCode = + "(function (text, offset, length) {\n" \ + " \"use strict\";\n" \ + " return this.write(text, offset, length, \"hex\");\n" \ + "})\n" \ +; + +const JSC::ConstructAbility s_jsBufferPrototypeUtf8SliceCodeConstructAbility = JSC::ConstructAbility::CannotConstruct; +const JSC::ConstructorKind s_jsBufferPrototypeUtf8SliceCodeConstructorKind = JSC::ConstructorKind::None; +const int s_jsBufferPrototypeUtf8SliceCodeLength = 96; +static const JSC::Intrinsic s_jsBufferPrototypeUtf8SliceCodeIntrinsic = JSC::NoIntrinsic; +const char* const s_jsBufferPrototypeUtf8SliceCode = + "(function (offset, length) {\n" \ + " \"use strict\";\n" \ + " return this.toString(offset, length, \"utf8\");\n" \ + "})\n" \ +; + +const JSC::ConstructAbility s_jsBufferPrototypeUcs2SliceCodeConstructAbility = JSC::ConstructAbility::CannotConstruct; +const JSC::ConstructorKind s_jsBufferPrototypeUcs2SliceCodeConstructorKind = JSC::ConstructorKind::None; +const int s_jsBufferPrototypeUcs2SliceCodeLength = 96; +static const JSC::Intrinsic s_jsBufferPrototypeUcs2SliceCodeIntrinsic = JSC::NoIntrinsic; +const char* const s_jsBufferPrototypeUcs2SliceCode = + "(function (offset, length) {\n" \ + " \"use strict\";\n" \ + " return this.toString(offset, length, \"ucs2\");\n" \ + "})\n" \ +; + +const JSC::ConstructAbility s_jsBufferPrototypeUtf16leSliceCodeConstructAbility = JSC::ConstructAbility::CannotConstruct; +const JSC::ConstructorKind s_jsBufferPrototypeUtf16leSliceCodeConstructorKind = JSC::ConstructorKind::None; +const int s_jsBufferPrototypeUtf16leSliceCodeLength = 99; +static const JSC::Intrinsic s_jsBufferPrototypeUtf16leSliceCodeIntrinsic = JSC::NoIntrinsic; +const char* const s_jsBufferPrototypeUtf16leSliceCode = + "(function (offset, length) {\n" \ + " \"use strict\";\n" \ + " return this.toString(offset, length, \"utf16le\");\n" \ + "})\n" \ +; + +const JSC::ConstructAbility s_jsBufferPrototypeLatin1SliceCodeConstructAbility = JSC::ConstructAbility::CannotConstruct; +const JSC::ConstructorKind s_jsBufferPrototypeLatin1SliceCodeConstructorKind = JSC::ConstructorKind::None; +const int s_jsBufferPrototypeLatin1SliceCodeLength = 98; +static const JSC::Intrinsic s_jsBufferPrototypeLatin1SliceCodeIntrinsic = JSC::NoIntrinsic; +const char* const s_jsBufferPrototypeLatin1SliceCode = + "(function (offset, length) {\n" \ + " \"use strict\";\n" \ + " return this.toString(offset, length, \"latin1\");\n" \ + "})\n" \ +; + +const JSC::ConstructAbility s_jsBufferPrototypeAsciiSliceCodeConstructAbility = JSC::ConstructAbility::CannotConstruct; +const JSC::ConstructorKind s_jsBufferPrototypeAsciiSliceCodeConstructorKind = JSC::ConstructorKind::None; +const int s_jsBufferPrototypeAsciiSliceCodeLength = 97; +static const JSC::Intrinsic s_jsBufferPrototypeAsciiSliceCodeIntrinsic = JSC::NoIntrinsic; +const char* const s_jsBufferPrototypeAsciiSliceCode = + "(function (offset, length) {\n" \ + " \"use strict\";\n" \ + " return this.toString(offset, length, \"ascii\");\n" \ + "})\n" \ +; + +const JSC::ConstructAbility s_jsBufferPrototypeBase64SliceCodeConstructAbility = JSC::ConstructAbility::CannotConstruct; +const JSC::ConstructorKind s_jsBufferPrototypeBase64SliceCodeConstructorKind = JSC::ConstructorKind::None; +const int s_jsBufferPrototypeBase64SliceCodeLength = 98; +static const JSC::Intrinsic s_jsBufferPrototypeBase64SliceCodeIntrinsic = JSC::NoIntrinsic; +const char* const s_jsBufferPrototypeBase64SliceCode = + "(function (offset, length) {\n" \ + " \"use strict\";\n" \ + " return this.toString(offset, length, \"base64\");\n" \ + "})\n" \ +; + +const JSC::ConstructAbility s_jsBufferPrototypeBase64urlSliceCodeConstructAbility = JSC::ConstructAbility::CannotConstruct; +const JSC::ConstructorKind s_jsBufferPrototypeBase64urlSliceCodeConstructorKind = JSC::ConstructorKind::None; +const int s_jsBufferPrototypeBase64urlSliceCodeLength = 101; +static const JSC::Intrinsic s_jsBufferPrototypeBase64urlSliceCodeIntrinsic = JSC::NoIntrinsic; +const char* const s_jsBufferPrototypeBase64urlSliceCode = + "(function (offset, length) {\n" \ + " \"use strict\";\n" \ + " return this.toString(offset, length, \"base64url\");\n" \ + "})\n" \ +; + +const JSC::ConstructAbility s_jsBufferPrototypeHexSliceCodeConstructAbility = JSC::ConstructAbility::CannotConstruct; +const JSC::ConstructorKind s_jsBufferPrototypeHexSliceCodeConstructorKind = JSC::ConstructorKind::None; +const int s_jsBufferPrototypeHexSliceCodeLength = 95; +static const JSC::Intrinsic s_jsBufferPrototypeHexSliceCodeIntrinsic = JSC::NoIntrinsic; +const char* const s_jsBufferPrototypeHexSliceCode = + "(function (offset, length) {\n" \ " \"use strict\";\n" \ - " \n" \ - " var array = new @Uint8Array(this.buffer, this.byteOffset + (start || 0), (end || this.byteLength) - (start || 0));\n" \ - " @setPrototypeDirect.@call(\n" \ - " array,\n" \ - " Buffer.prototype\n" \ - " );\n" \ - " return array;\n" \ + " return this.toString(offset, length, \"hex\");\n" \ "})\n" \ ; diff --git a/src/javascript/jsc/bindings/JSBufferPrototypeBuiltins.h b/src/javascript/jsc/bindings/JSBufferPrototypeBuiltins.h index 2c7efe0ff..d25ad9b76 100644 --- a/src/javascript/jsc/bindings/JSBufferPrototypeBuiltins.h +++ b/src/javascript/jsc/bindings/JSBufferPrototypeBuiltins.h @@ -1,3 +1,4 @@ +// clang-format off /* * Copyright (c) 2016 Apple Inc. All rights reserved. * Copyright (c) 2022 Codeblog Corp. All rights reserved. @@ -198,10 +199,70 @@ extern const char* const s_jsBufferPrototypeSliceCode; extern const int s_jsBufferPrototypeSliceCodeLength; extern const JSC::ConstructAbility s_jsBufferPrototypeSliceCodeConstructAbility; extern const JSC::ConstructorKind s_jsBufferPrototypeSliceCodeConstructorKind; -extern const char* const s_jsBufferPrototypeSubarrayCode; -extern const int s_jsBufferPrototypeSubarrayCodeLength; -extern const JSC::ConstructAbility s_jsBufferPrototypeSubarrayCodeConstructAbility; -extern const JSC::ConstructorKind s_jsBufferPrototypeSubarrayCodeConstructorKind; +extern const char* const s_jsBufferPrototypeUtf8WriteCode; +extern const int s_jsBufferPrototypeUtf8WriteCodeLength; +extern const JSC::ConstructAbility s_jsBufferPrototypeUtf8WriteCodeConstructAbility; +extern const JSC::ConstructorKind s_jsBufferPrototypeUtf8WriteCodeConstructorKind; +extern const char* const s_jsBufferPrototypeUcs2WriteCode; +extern const int s_jsBufferPrototypeUcs2WriteCodeLength; +extern const JSC::ConstructAbility s_jsBufferPrototypeUcs2WriteCodeConstructAbility; +extern const JSC::ConstructorKind s_jsBufferPrototypeUcs2WriteCodeConstructorKind; +extern const char* const s_jsBufferPrototypeUtf16leWriteCode; +extern const int s_jsBufferPrototypeUtf16leWriteCodeLength; +extern const JSC::ConstructAbility s_jsBufferPrototypeUtf16leWriteCodeConstructAbility; +extern const JSC::ConstructorKind s_jsBufferPrototypeUtf16leWriteCodeConstructorKind; +extern const char* const s_jsBufferPrototypeLatin1WriteCode; +extern const int s_jsBufferPrototypeLatin1WriteCodeLength; +extern const JSC::ConstructAbility s_jsBufferPrototypeLatin1WriteCodeConstructAbility; +extern const JSC::ConstructorKind s_jsBufferPrototypeLatin1WriteCodeConstructorKind; +extern const char* const s_jsBufferPrototypeAsciiWriteCode; +extern const int s_jsBufferPrototypeAsciiWriteCodeLength; +extern const JSC::ConstructAbility s_jsBufferPrototypeAsciiWriteCodeConstructAbility; +extern const JSC::ConstructorKind s_jsBufferPrototypeAsciiWriteCodeConstructorKind; +extern const char* const s_jsBufferPrototypeBase64WriteCode; +extern const int s_jsBufferPrototypeBase64WriteCodeLength; +extern const JSC::ConstructAbility s_jsBufferPrototypeBase64WriteCodeConstructAbility; +extern const JSC::ConstructorKind s_jsBufferPrototypeBase64WriteCodeConstructorKind; +extern const char* const s_jsBufferPrototypeBase64urlWriteCode; +extern const int s_jsBufferPrototypeBase64urlWriteCodeLength; +extern const JSC::ConstructAbility s_jsBufferPrototypeBase64urlWriteCodeConstructAbility; +extern const JSC::ConstructorKind s_jsBufferPrototypeBase64urlWriteCodeConstructorKind; +extern const char* const s_jsBufferPrototypeHexWriteCode; +extern const int s_jsBufferPrototypeHexWriteCodeLength; +extern const JSC::ConstructAbility s_jsBufferPrototypeHexWriteCodeConstructAbility; +extern const JSC::ConstructorKind s_jsBufferPrototypeHexWriteCodeConstructorKind; +extern const char* const s_jsBufferPrototypeUtf8SliceCode; +extern const int s_jsBufferPrototypeUtf8SliceCodeLength; +extern const JSC::ConstructAbility s_jsBufferPrototypeUtf8SliceCodeConstructAbility; +extern const JSC::ConstructorKind s_jsBufferPrototypeUtf8SliceCodeConstructorKind; +extern const char* const s_jsBufferPrototypeUcs2SliceCode; +extern const int s_jsBufferPrototypeUcs2SliceCodeLength; +extern const JSC::ConstructAbility s_jsBufferPrototypeUcs2SliceCodeConstructAbility; +extern const JSC::ConstructorKind s_jsBufferPrototypeUcs2SliceCodeConstructorKind; +extern const char* const s_jsBufferPrototypeUtf16leSliceCode; +extern const int s_jsBufferPrototypeUtf16leSliceCodeLength; +extern const JSC::ConstructAbility s_jsBufferPrototypeUtf16leSliceCodeConstructAbility; +extern const JSC::ConstructorKind s_jsBufferPrototypeUtf16leSliceCodeConstructorKind; +extern const char* const s_jsBufferPrototypeLatin1SliceCode; +extern const int s_jsBufferPrototypeLatin1SliceCodeLength; +extern const JSC::ConstructAbility s_jsBufferPrototypeLatin1SliceCodeConstructAbility; +extern const JSC::ConstructorKind s_jsBufferPrototypeLatin1SliceCodeConstructorKind; +extern const char* const s_jsBufferPrototypeAsciiSliceCode; +extern const int s_jsBufferPrototypeAsciiSliceCodeLength; +extern const JSC::ConstructAbility s_jsBufferPrototypeAsciiSliceCodeConstructAbility; +extern const JSC::ConstructorKind s_jsBufferPrototypeAsciiSliceCodeConstructorKind; +extern const char* const s_jsBufferPrototypeBase64SliceCode; +extern const int s_jsBufferPrototypeBase64SliceCodeLength; +extern const JSC::ConstructAbility s_jsBufferPrototypeBase64SliceCodeConstructAbility; +extern const JSC::ConstructorKind s_jsBufferPrototypeBase64SliceCodeConstructorKind; +extern const char* const s_jsBufferPrototypeBase64urlSliceCode; +extern const int s_jsBufferPrototypeBase64urlSliceCodeLength; +extern const JSC::ConstructAbility s_jsBufferPrototypeBase64urlSliceCodeConstructAbility; +extern const JSC::ConstructorKind s_jsBufferPrototypeBase64urlSliceCodeConstructorKind; +extern const char* const s_jsBufferPrototypeHexSliceCode; +extern const int s_jsBufferPrototypeHexSliceCodeLength; +extern const JSC::ConstructAbility s_jsBufferPrototypeHexSliceCodeConstructAbility; +extern const JSC::ConstructorKind s_jsBufferPrototypeHexSliceCodeConstructorKind; extern const char* const s_jsBufferPrototypeToJSONCode; extern const int s_jsBufferPrototypeToJSONCodeLength; extern const JSC::ConstructAbility s_jsBufferPrototypeToJSONCodeConstructAbility; @@ -247,7 +308,22 @@ extern const JSC::ConstructorKind s_jsBufferPrototypeToJSONCodeConstructorKind; macro(writeBigUInt64LE, jsBufferPrototypeWriteBigUInt64LE, 2) \ macro(writeBigUInt64BE, jsBufferPrototypeWriteBigUInt64BE, 2) \ macro(slice, jsBufferPrototypeSlice, 2) \ - macro(subarray, jsBufferPrototypeSubarray, 2) \ + macro(utf8Write, jsBufferPrototypeUtf8Write, 3) \ + macro(ucs2Write, jsBufferPrototypeUcs2Write, 3) \ + macro(utf16leWrite, jsBufferPrototypeUtf16leWrite, 3) \ + macro(latin1Write, jsBufferPrototypeLatin1Write, 3) \ + macro(asciiWrite, jsBufferPrototypeAsciiWrite, 3) \ + macro(base64Write, jsBufferPrototypeBase64Write, 3) \ + macro(base64urlWrite, jsBufferPrototypeBase64urlWrite, 3) \ + macro(hexWrite, jsBufferPrototypeHexWrite, 3) \ + macro(utf8Slice, jsBufferPrototypeUtf8Slice, 2) \ + macro(ucs2Slice, jsBufferPrototypeUcs2Slice, 2) \ + macro(utf16leSlice, jsBufferPrototypeUtf16leSlice, 2) \ + macro(latin1Slice, jsBufferPrototypeLatin1Slice, 2) \ + macro(asciiSlice, jsBufferPrototypeAsciiSlice, 2) \ + macro(base64Slice, jsBufferPrototypeBase64Slice, 2) \ + macro(base64urlSlice, jsBufferPrototypeBase64urlSlice, 2) \ + macro(hexSlice, jsBufferPrototypeHexSlice, 2) \ macro(toJSON, jsBufferPrototypeToJSON, 0) \ #define WEBCORE_BUILTIN_JSBUFFERPROTOTYPE_BUFFER 1 @@ -289,7 +365,22 @@ extern const JSC::ConstructorKind s_jsBufferPrototypeToJSONCodeConstructorKind; #define WEBCORE_BUILTIN_JSBUFFERPROTOTYPE_WRITEBIGUINT64LE 1 #define WEBCORE_BUILTIN_JSBUFFERPROTOTYPE_WRITEBIGUINT64BE 1 #define WEBCORE_BUILTIN_JSBUFFERPROTOTYPE_SLICE 1 -#define WEBCORE_BUILTIN_JSBUFFERPROTOTYPE_SUBARRAY 1 +#define WEBCORE_BUILTIN_JSBUFFERPROTOTYPE_UTF8WRITE 1 +#define WEBCORE_BUILTIN_JSBUFFERPROTOTYPE_UCS2WRITE 1 +#define WEBCORE_BUILTIN_JSBUFFERPROTOTYPE_UTF16LEWRITE 1 +#define WEBCORE_BUILTIN_JSBUFFERPROTOTYPE_LATIN1WRITE 1 +#define WEBCORE_BUILTIN_JSBUFFERPROTOTYPE_ASCIIWRITE 1 +#define WEBCORE_BUILTIN_JSBUFFERPROTOTYPE_BASE64WRITE 1 +#define WEBCORE_BUILTIN_JSBUFFERPROTOTYPE_BASE64URLWRITE 1 +#define WEBCORE_BUILTIN_JSBUFFERPROTOTYPE_HEXWRITE 1 +#define WEBCORE_BUILTIN_JSBUFFERPROTOTYPE_UTF8SLICE 1 +#define WEBCORE_BUILTIN_JSBUFFERPROTOTYPE_UCS2SLICE 1 +#define WEBCORE_BUILTIN_JSBUFFERPROTOTYPE_UTF16LESLICE 1 +#define WEBCORE_BUILTIN_JSBUFFERPROTOTYPE_LATIN1SLICE 1 +#define WEBCORE_BUILTIN_JSBUFFERPROTOTYPE_ASCIISLICE 1 +#define WEBCORE_BUILTIN_JSBUFFERPROTOTYPE_BASE64SLICE 1 +#define WEBCORE_BUILTIN_JSBUFFERPROTOTYPE_BASE64URLSLICE 1 +#define WEBCORE_BUILTIN_JSBUFFERPROTOTYPE_HEXSLICE 1 #define WEBCORE_BUILTIN_JSBUFFERPROTOTYPE_TOJSON 1 #define WEBCORE_FOREACH_JSBUFFERPROTOTYPE_BUILTIN_CODE(macro) \ @@ -332,7 +423,22 @@ extern const JSC::ConstructorKind s_jsBufferPrototypeToJSONCodeConstructorKind; macro(jsBufferPrototypeWriteBigUInt64LECode, writeBigUInt64LE, static_cast<const char*>(nullptr), s_jsBufferPrototypeWriteBigUInt64LECodeLength) \ macro(jsBufferPrototypeWriteBigUInt64BECode, writeBigUInt64BE, static_cast<const char*>(nullptr), s_jsBufferPrototypeWriteBigUInt64BECodeLength) \ macro(jsBufferPrototypeSliceCode, slice, static_cast<const char*>(nullptr), s_jsBufferPrototypeSliceCodeLength) \ - macro(jsBufferPrototypeSubarrayCode, subarray, static_cast<const char*>(nullptr), s_jsBufferPrototypeSubarrayCodeLength) \ + macro(jsBufferPrototypeUtf8WriteCode, utf8Write, static_cast<const char*>(nullptr), s_jsBufferPrototypeUtf8WriteCodeLength) \ + macro(jsBufferPrototypeUcs2WriteCode, ucs2Write, static_cast<const char*>(nullptr), s_jsBufferPrototypeUcs2WriteCodeLength) \ + macro(jsBufferPrototypeUtf16leWriteCode, utf16leWrite, static_cast<const char*>(nullptr), s_jsBufferPrototypeUtf16leWriteCodeLength) \ + macro(jsBufferPrototypeLatin1WriteCode, latin1Write, static_cast<const char*>(nullptr), s_jsBufferPrototypeLatin1WriteCodeLength) \ + macro(jsBufferPrototypeAsciiWriteCode, asciiWrite, static_cast<const char*>(nullptr), s_jsBufferPrototypeAsciiWriteCodeLength) \ + macro(jsBufferPrototypeBase64WriteCode, base64Write, static_cast<const char*>(nullptr), s_jsBufferPrototypeBase64WriteCodeLength) \ + macro(jsBufferPrototypeBase64urlWriteCode, base64urlWrite, static_cast<const char*>(nullptr), s_jsBufferPrototypeBase64urlWriteCodeLength) \ + macro(jsBufferPrototypeHexWriteCode, hexWrite, static_cast<const char*>(nullptr), s_jsBufferPrototypeHexWriteCodeLength) \ + macro(jsBufferPrototypeUtf8SliceCode, utf8Slice, static_cast<const char*>(nullptr), s_jsBufferPrototypeUtf8SliceCodeLength) \ + macro(jsBufferPrototypeUcs2SliceCode, ucs2Slice, static_cast<const char*>(nullptr), s_jsBufferPrototypeUcs2SliceCodeLength) \ + macro(jsBufferPrototypeUtf16leSliceCode, utf16leSlice, static_cast<const char*>(nullptr), s_jsBufferPrototypeUtf16leSliceCodeLength) \ + macro(jsBufferPrototypeLatin1SliceCode, latin1Slice, static_cast<const char*>(nullptr), s_jsBufferPrototypeLatin1SliceCodeLength) \ + macro(jsBufferPrototypeAsciiSliceCode, asciiSlice, static_cast<const char*>(nullptr), s_jsBufferPrototypeAsciiSliceCodeLength) \ + macro(jsBufferPrototypeBase64SliceCode, base64Slice, static_cast<const char*>(nullptr), s_jsBufferPrototypeBase64SliceCodeLength) \ + macro(jsBufferPrototypeBase64urlSliceCode, base64urlSlice, static_cast<const char*>(nullptr), s_jsBufferPrototypeBase64urlSliceCodeLength) \ + macro(jsBufferPrototypeHexSliceCode, hexSlice, static_cast<const char*>(nullptr), s_jsBufferPrototypeHexSliceCodeLength) \ macro(jsBufferPrototypeToJSONCode, toJSON, static_cast<const char*>(nullptr), s_jsBufferPrototypeToJSONCodeLength) \ #define WEBCORE_FOREACH_JSBUFFERPROTOTYPE_BUILTIN_FUNCTION_NAME(macro) \ @@ -357,8 +463,13 @@ extern const JSC::ConstructorKind s_jsBufferPrototypeToJSONCodeConstructorKind; macro(readUInt8) \ macro(setBigUint64) \ macro(slice) \ - macro(subarray) \ macro(toJSON) \ + macro(ucs2Slice) \ + macro(ucs2Write) \ + macro(utf16leSlice) \ + macro(utf16leWrite) \ + macro(utf8Slice) \ + macro(utf8Write) \ macro(writeBigInt64BE) \ macro(writeBigInt64LE) \ macro(writeBigUInt64BE) \ diff --git a/src/javascript/jsc/bindings/WebCoreJSBuiltinInternals.cpp b/src/javascript/jsc/bindings/WebCoreJSBuiltinInternals.cpp index bf85a29ef..310df6a35 100644 --- a/src/javascript/jsc/bindings/WebCoreJSBuiltinInternals.cpp +++ b/src/javascript/jsc/bindings/WebCoreJSBuiltinInternals.cpp @@ -1,5 +1,6 @@ /* * Copyright (c) 2016 Apple Inc. All rights reserved. + * Copyright (c) 2022 Codeblog Corp. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff --git a/src/javascript/jsc/bindings/WebCoreJSBuiltinInternals.h b/src/javascript/jsc/bindings/WebCoreJSBuiltinInternals.h index 86fb9b3c6..bb7b79d89 100644 --- a/src/javascript/jsc/bindings/WebCoreJSBuiltinInternals.h +++ b/src/javascript/jsc/bindings/WebCoreJSBuiltinInternals.h @@ -1,6 +1,8 @@ +//clang-format off namespace Zig { class GlobalObject; } /* * Copyright (c) 2016 Apple Inc. All rights reserved. + * Copyright (c) 2022 Codeblog Corp. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff --git a/src/javascript/jsc/bindings/WebCoreJSBuiltins.h b/src/javascript/jsc/bindings/WebCoreJSBuiltins.h index f2fd32881..a06c8bfcf 100644 --- a/src/javascript/jsc/bindings/WebCoreJSBuiltins.h +++ b/src/javascript/jsc/bindings/WebCoreJSBuiltins.h @@ -1,5 +1,6 @@ /* * Copyright (c) 2016 Apple Inc. All rights reserved. + * Copyright (c) 2022 Codeblog Corp. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff --git a/src/javascript/jsc/bindings/bindings.zig b/src/javascript/jsc/bindings/bindings.zig index 63848164a..4d769642d 100644 --- a/src/javascript/jsc/bindings/bindings.zig +++ b/src/javascript/jsc/bindings/bindings.zig @@ -2305,6 +2305,15 @@ pub const JSValue = enum(u64) { return cppFn("makeWithNameAndPrototype", .{ globalObject, class, instance, name_ }); } + /// Must come from globally-allocated memory! + pub fn createBuffer(globalObject: *JSGlobalObject, slice: []u8, allocator: std.mem.Allocator) JSValue { + if (comptime JSC.is_bindgen) unreachable; + @setRuntimeSafety(false); + return JSBuffer__bufferFromPointerAndLengthAndDeinit(globalObject, slice.ptr, slice.len, allocator.ptr, JSC.MarkedArrayBuffer_deallocator); + } + + extern fn JSBuffer__bufferFromPointerAndLengthAndDeinit(*JSGlobalObject, [*]u8, usize, ?*anyopaque, JSC.C.JSTypedArrayBytesDeallocator) JSValue; + pub fn jsNumberWithType(comptime Number: type, number: Number) JSValue { return switch (comptime Number) { JSValue => number, diff --git a/src/javascript/jsc/bindings/builtins/js/JSBufferPrototype.js b/src/javascript/jsc/bindings/builtins/js/JSBufferPrototype.js index 2c4519c0f..b7563580d 100644 --- a/src/javascript/jsc/bindings/builtins/js/JSBufferPrototype.js +++ b/src/javascript/jsc/bindings/builtins/js/JSBufferPrototype.js @@ -30,8 +30,8 @@ -// note: the _view inline getter is structured this way for performance -// using a getter +// The fastest way as of April 2022 is to use DataView. +// DataView has intrinsics that cause inlining function setBigUint64(offset, value, le) { "use strict"; @@ -214,10 +214,75 @@ function slice(start, end) { return this; } - return this.subarray(start, end); + Buffer[Symbol.species] ||= Buffer; + + return new Buffer(this.buffer, this.byteOffset + (start || 0), (end || this.byteLength) - (start || 0)); +} + + + +function utf8Write(text, offset, length) { + "use strict"; + return this.write(text, offset, length, "utf8"); +} +function ucs2Write(text, offset, length) { + "use strict"; + return this.write(text, offset, length, "ucs2"); +} +function utf16leWrite(text, offset, length) { + "use strict"; + return this.write(text, offset, length, "utf16le"); +} +function latin1Write(text, offset, length) { + "use strict"; + return this.write(text, offset, length, "latin1"); +} +function asciiWrite(text, offset, length) { + "use strict"; + return this.write(text, offset, length, "ascii"); +} +function base64Write(text, offset, length) { + "use strict"; + return this.write(text, offset, length, "base64"); +} +function base64urlWrite(text, offset, length) { + "use strict"; + return this.write(text, offset, length, "base64url"); +} +function hexWrite(text, offset, length) { + "use strict"; + return this.write(text, offset, length, "hex"); } -function subarray(start, end) { +function utf8Slice(offset, length) { + "use strict"; + return this.toString(offset, length, "utf8"); +} +function ucs2Slice(offset, length) { + "use strict"; + return this.toString(offset, length, "ucs2"); +} +function utf16leSlice(offset, length) { + "use strict"; + return this.toString(offset, length, "utf16le"); +} +function latin1Slice(offset, length) { + "use strict"; + return this.toString(offset, length, "latin1"); +} +function asciiSlice(offset, length) { + "use strict"; + return this.toString(offset, length, "ascii"); +} +function base64Slice(offset, length) { + "use strict"; + return this.toString(offset, length, "base64"); +} +function base64urlSlice(offset, length) { + "use strict"; + return this.toString(offset, length, "base64url"); +} +function hexSlice(offset, length) { "use strict"; var array = new @Uint8Array(this.buffer, this.byteOffset + (start || 0), (end || this.byteLength) - (start || 0)); diff --git a/src/javascript/jsc/bindings/headers-cpp.h b/src/javascript/jsc/bindings/headers-cpp.h index a0393e454..87e7e3afe 100644 --- a/src/javascript/jsc/bindings/headers-cpp.h +++ b/src/javascript/jsc/bindings/headers-cpp.h @@ -1,4 +1,4 @@ -//-- AUTOGENERATED FILE -- 1650803913 +//-- AUTOGENERATED FILE -- 1651208705 // clang-format off #pragma once diff --git a/src/javascript/jsc/bindings/headers-handwritten.h b/src/javascript/jsc/bindings/headers-handwritten.h index 3d03187b7..e285d5ffc 100644 --- a/src/javascript/jsc/bindings/headers-handwritten.h +++ b/src/javascript/jsc/bindings/headers-handwritten.h @@ -218,4 +218,17 @@ extern "C" int64_t Bun__encoding__writeUTF16AsUTF8(const UChar* ptr, size_t len, extern "C" int64_t Bun__encoding__writeLatin1AsASCII(const unsigned char* ptr, size_t len, unsigned char* to, size_t other_len); extern "C" int64_t Bun__encoding__writeUTF16AsASCII(const UChar* ptr, size_t len, unsigned char* to, size_t other_len); +extern "C" int64_t Bun__encoding__constructFromLatin1AsHex(void*, const unsigned char* ptr, size_t len); +extern "C" int64_t Bun__encoding__constructFromUTF16AsHex(void*, const UChar* ptr, size_t len); +extern "C" int64_t Bun__encoding__constructFromLatin1AsURLSafeBase64(void*, const unsigned char* ptr, size_t len); +extern "C" int64_t Bun__encoding__constructFromUTF16AsURLSafeBase64(void*, const UChar* ptr, size_t len); +extern "C" int64_t Bun__encoding__constructFromLatin1AsBase64(void*, const unsigned char* ptr, size_t len); +extern "C" int64_t Bun__encoding__constructFromUTF16AsBase64(void*, const UChar* ptr, size_t len); +extern "C" int64_t Bun__encoding__constructFromLatin1AsUTF16(void*, const unsigned char* ptr, size_t len); +extern "C" int64_t Bun__encoding__constructFromUTF16AsUTF16(void*, const UChar* ptr, size_t len); +extern "C" int64_t Bun__encoding__constructFromLatin1AsUTF8(void*, const unsigned char* ptr, size_t len); +extern "C" int64_t Bun__encoding__constructFromUTF16AsUTF8(void*, const UChar* ptr, size_t len); +extern "C" int64_t Bun__encoding__constructFromLatin1AsASCII(void*, const unsigned char* ptr, size_t len); +extern "C" int64_t Bun__encoding__constructFromUTF16AsASCII(void*, const UChar* ptr, size_t len); + #endif diff --git a/src/javascript/jsc/bindings/headers.h b/src/javascript/jsc/bindings/headers.h index aad13bc5b..b6158690c 100644 --- a/src/javascript/jsc/bindings/headers.h +++ b/src/javascript/jsc/bindings/headers.h @@ -1,5 +1,5 @@ // clang-format: off -//-- AUTOGENERATED FILE -- 1650803913 +//-- AUTOGENERATED FILE -- 1651208705 #pragma once #include <stddef.h> diff --git a/src/javascript/jsc/webcore/encoding.zig b/src/javascript/jsc/webcore/encoding.zig index b4ac59fa8..2e7e41c27 100644 --- a/src/javascript/jsc/webcore/encoding.zig +++ b/src/javascript/jsc/webcore/encoding.zig @@ -650,6 +650,10 @@ pub const TextDecoder = struct { } }; +/// This code is incredibly redundant +/// We have different paths for creaitng a new buffer versus writing into an existing one +/// That's mostly why all the duplication +/// The majority of the business logic here is just shooting it off to the optimized functions pub const Encoder = struct { export fn Bun__encoding__writeLatin1AsHex(input: [*]const u8, len: usize, to: [*]u8, to_len: usize) i64 { return writeU8(input, len, to, to_len, .hex); @@ -688,6 +692,55 @@ pub const Encoder = struct { return writeU8(input, len, to, to_len, .ascii); } + export fn Bun__encoding__constructFromLatin1AsHex(globalObject: *JSGlobalObject, input: [*]const u8, len: usize) JSValue { + var slice = constructFromU8(input, len, .hex); + return JSC.JSValue.createBuffer(globalObject, slice, VirtualMachine.vm.allocator); + } + export fn Bun__encoding__constructFromLatin1AsASCII(globalObject: *JSGlobalObject, input: [*]const u8, len: usize) JSValue { + var slice = constructFromU8(input, len, .ascii); + return JSC.JSValue.createBuffer(globalObject, slice, VirtualMachine.vm.allocator); + } + export fn Bun__encoding__constructFromLatin1AsURLSafeBase64(globalObject: *JSGlobalObject, input: [*]const u8, len: usize) JSValue { + var slice = constructFromU8(input, len, .base64url); + return JSC.JSValue.createBuffer(globalObject, slice, VirtualMachine.vm.allocator); + } + export fn Bun__encoding__constructFromLatin1AsUTF16(globalObject: *JSGlobalObject, input: [*]const u8, len: usize) JSValue { + var slice = constructFromU8(input, len, .utf16le); + return JSC.JSValue.createBuffer(globalObject, slice, VirtualMachine.vm.allocator); + } + export fn Bun__encoding__constructFromLatin1AsUTF8(globalObject: *JSGlobalObject, input: [*]const u8, len: usize) JSValue { + var slice = constructFromU8(input, len, JSC.Node.Encoding.utf8); + return JSC.JSValue.createBuffer(globalObject, slice, VirtualMachine.vm.allocator); + } + export fn Bun__encoding__constructFromLatin1AsBase64(globalObject: *JSGlobalObject, input: [*]const u8, len: usize) JSValue { + var slice = constructFromU8(input, len, .base64); + return JSC.JSValue.createBuffer(globalObject, slice, VirtualMachine.vm.allocator); + } + export fn Bun__encoding__constructFromUTF16AsBase64(globalObject: *JSGlobalObject, input: [*]const u16, len: usize) JSValue { + var slice = constructFromU16(input, len, .base64); + return JSC.JSValue.createBuffer(globalObject, slice, VirtualMachine.vm.allocator); + } + export fn Bun__encoding__constructFromUTF16AsHex(globalObject: *JSGlobalObject, input: [*]const u16, len: usize) JSValue { + var slice = constructFromU16(input, len, .hex); + return JSC.JSValue.createBuffer(globalObject, slice, VirtualMachine.vm.allocator); + } + export fn Bun__encoding__constructFromUTF16AsURLSafeBase64(globalObject: *JSGlobalObject, input: [*]const u16, len: usize) JSValue { + var slice = constructFromU16(input, len, .base64url); + return JSC.JSValue.createBuffer(globalObject, slice, VirtualMachine.vm.allocator); + } + export fn Bun__encoding__constructFromUTF16AsUTF16(globalObject: *JSGlobalObject, input: [*]const u16, len: usize) JSValue { + var slice = constructFromU16(input, len, JSC.Node.Encoding.utf16le); + return JSC.JSValue.createBuffer(globalObject, slice, VirtualMachine.vm.allocator); + } + export fn Bun__encoding__constructFromUTF16AsUTF8(globalObject: *JSGlobalObject, input: [*]const u16, len: usize) JSValue { + var slice = constructFromU16(input, len, .utf8); + return JSC.JSValue.createBuffer(globalObject, slice, VirtualMachine.vm.allocator); + } + export fn Bun__encoding__constructFromUTF16AsASCII(globalObject: *JSGlobalObject, input: [*]const u16, len: usize) JSValue { + var slice = constructFromU16(input, len, .utf8); + return JSC.JSValue.createBuffer(globalObject, slice, VirtualMachine.vm.allocator); + } + export fn Bun__encoding__toStringUTF16(input: [*]const u8, len: usize, globalObject: *JSC.JSGlobalObject) JSValue { return toString(input, len, globalObject, JSC.Node.Encoding.utf16le); } @@ -867,7 +920,8 @@ pub const Encoder = struct { } pub fn writeU16(input: [*]const u16, len: usize, to: [*]u8, to_len: usize, comptime encoding: JSC.Node.Encoding) i64 { - + if (len == 0) + return 0; // TODO: increase temporary buffer size for larger amounts of data // defer { // if (comptime encoding.isBinaryToText()) {} @@ -880,7 +934,7 @@ pub const Encoder = struct { return @intCast(i32, strings.copyUTF16IntoUTF8(to[0..to_len], []const u16, input[0..len]).written); }, // string is already encoded, just need to copy the data - JSC.Node.Encoding.ascii, JSC.Node.Encoding.ucs2, JSC.Node.Encoding.buffer, JSC.Node.Encoding.utf16le => { + .latin1, JSC.Node.Encoding.ascii, JSC.Node.Encoding.ucs2, JSC.Node.Encoding.buffer, JSC.Node.Encoding.utf16le => { strings.copyU16IntoU8(to[0..to_len], []const u16, input[0..len]); return @intCast(i64, @minimum(len, to_len)); @@ -900,60 +954,142 @@ pub const Encoder = struct { defer bun.default_allocator.free(transcoded); return writeU8(transcoded.ptr, transcoded.len, to, to_len, encoding); }, - else => return 0, + // else => return &[_]u8{}; } } - // pub fn writeU8(input: [*]const u8, len: usize, to: [*]u8, to_len: usize, comptime encoding: JSC.Node.Encoding) callconv(.C) i32 {} - - // pub fn toUTF8FromU16(comptime Slice: type, slice: Slice, out_ptr: *[*]u8) i32 { - // var out = strings.toUTF8AllocWithType( - // default_allocator, - // Slice, - // slice, - // ) catch { - // return -1; - // }; - // out_ptr.* = out.ptr; - // return @intCast(isize, out.len); - // } - // pub fn toUTF8FromLatin1(comptime Slice: type, slice: Slice, out_ptr: *[*]u8) i32 { - // var latin1 = strings.allocateLatin1IntoUTF8(default_allocator, Slice, slice) catch return -1; - // out_ptr.* = latin1.ptr; - // return @intCast(isize, latin1.len); - // } + pub fn constructFromU8(input: [*]const u8, len: usize, comptime encoding: JSC.Node.Encoding) []u8 { + if (len == 0) + return &[_]u8{}; - // pub fn toUTF16FromLatin1(comptime Slice: type, slice: Slice, out_ptr: *[*]u8) i32 { - // var latin1 = strings.toUTF(default_allocator, Slice, slice) catch return -1; - // out_ptr.* = latin1.ptr; - // return @intCast(isize, latin1.len); - // } + const allocator = VirtualMachine.vm.allocator; + + switch (comptime encoding) { + JSC.Node.Encoding.buffer => { + var to = allocator.alloc(u8, len) catch return &[_]u8{}; + @memcpy(to.ptr, input, len); + + return to; + }, + .latin1, .ascii => { + var to = allocator.alloc(u8, len) catch return &[_]u8{}; + @memcpy(to.ptr, input, len); + + // Hoping this gets auto vectorized + for (to[0..len]) |c, i| { + to[i] = @as(u8, @truncate(u7, c)); + } + + return to; + }, + .utf8 => { + // need to encode + return strings.allocateLatin1IntoUTF8(allocator, []const u8, input[0..len]) catch return &[_]u8{}; + }, + // encode latin1 into UTF16 + // return as bytes + JSC.Node.Encoding.ucs2, JSC.Node.Encoding.utf16le => { + var to = allocator.alloc(u16, len) catch return &[_]u8{}; + _ = strings.copyLatin1IntoUTF16([]u16, to, []const u8, input[0..len]); + return std.mem.sliceAsBytes(to[0..len]); + }, + + JSC.Node.Encoding.hex => { + if (len < 2) + return &[_]u8{}; + + var to = allocator.alloc(u8, len / 2) catch return &[_]u8{}; + return to[0..strings.decodeHexToBytes(to, u8, input[0..len])]; + }, + + JSC.Node.Encoding.base64url => { + var slice = strings.trim(input[0..len], "\r\n\t " ++ [_]u8{std.ascii.control_code.VT}); + if (slice.len == 0) + return &[_]u8{}; + + if (strings.eqlComptime(slice[slice.len - 2 ..][0..2], "==")) { + slice = slice[0 .. slice.len - 2]; + } else if (slice[slice.len - 1] == '=') { + slice = slice[0 .. slice.len - 1]; + } + + const to_len = bun.base64.urlsafe.decoder.calcSizeForSlice(slice) catch unreachable; + var to = allocator.alloc(u8, to_len) catch return &[_]u8{}; + + const wrote = bun.base64.urlsafe.decode(to[0..to_len], slice) catch |err| brk: { + if (err == error.NoSpaceLeft) { + break :brk to_len; + } + + return &[_]u8{}; + }; + return to[0..wrote]; + }, + + JSC.Node.Encoding.base64 => { + var slice = strings.trim(input[0..len], "\r\n\t " ++ [_]u8{std.ascii.control_code.VT}); + var outlen = bun.base64.decodeLen(slice); + + var to = allocator.alloc(u8, outlen) catch return &[_]u8{}; + const written = bun.base64.decode(to[0..outlen], slice).written; + return to[0..written]; + }, + // else => return 0, + } + } + + pub fn constructFromU16(input: [*]const u16, len: usize, comptime encoding: JSC.Node.Encoding) []u8 { + if (len == 0) + return &[_]u8{}; + + const allocator = VirtualMachine.vm.allocator; + + switch (comptime encoding) { + .utf8 => { + return strings.toUTF8AllocWithType(allocator, []const u16, input[0..len]) catch return &[_]u8{}; + }, + JSC.Node.Encoding.latin1, JSC.Node.Encoding.buffer, JSC.Node.Encoding.ascii => { + var to = allocator.alloc(u8, len) catch return &[_]u8{}; + @memcpy(to.ptr, input, len); + for (to[0..len]) |c, i| { + to[i] = @as(u8, @truncate(u7, c)); + } + + return to; + }, + // string is already encoded, just need to copy the data + JSC.Node.Encoding.ucs2, JSC.Node.Encoding.utf16le => { + var to = std.mem.sliceAsBytes(allocator.alloc(u16, len * 2) catch return &[_]u8{}); + @memcpy(to.ptr, std.mem.sliceAsBytes(input[0..len]).ptr, std.mem.sliceAsBytes(input[0..len]).len); + return to; + }, + + JSC.Node.Encoding.hex => { + var to = allocator.alloc(u8, len * 2) catch return &[_]u8{}; + return to[0..strings.decodeHexToBytes(to, u16, input[0..len])]; + }, + + JSC.Node.Encoding.base64 => { + + // very very slow case! + // shouldn't really happen though + var transcoded = strings.toUTF8Alloc(allocator, input[0..len]) catch return &[_]u8{}; + defer allocator.free(transcoded); + return constructFromU8(transcoded.ptr, transcoded.len, .base64); + }, + + JSC.Node.Encoding.base64url => { + + // very very slow case! + // shouldn't really happen though + var transcoded = strings.toUTF8Alloc(allocator, input[0..len]) catch return &[_]u8{}; + defer allocator.free(transcoded); + return constructFromU8(transcoded.ptr, transcoded.len, .base64url); + }, + // else => return 0, + } + } - // pub fn toUTF16FromU8(slice: []const u8, out_ptr: *[*]u16) i32 { - // if (strings.toUTF16Alloc(default_allocator, slice, true)) |result_| { - // if (result_) |result| { - // out_ptr.* = result.ptr; - // return @intCast(isize, result.len); - // } - // } else |err| { - // switch (err) { - // error.InvalidByteSequence => { - // return -2; - // }, - // error.OutOfMemory => { - // return -1; - // }, - // else => { - // return -3; - // }, - // } - // } - - // var out = default_allocator.alloc(u16, slice.len) catch return -1; - // strings.copyU8IntoU16(out, slice); - // out_ptr.* = out.ptr; - // return @intCast(isize, out.len); - // } comptime { if (!JSC.is_bindgen) { _ = Bun__encoding__writeLatin1AsHex; @@ -976,6 +1112,19 @@ pub const Encoder = struct { _ = Bun__encoding__toStringHex; _ = Bun__encoding__toStringBase64; _ = Bun__encoding__toStringURLSafeBase64; + + _ = Bun__encoding__constructFromLatin1AsHex; + _ = Bun__encoding__constructFromLatin1AsASCII; + _ = Bun__encoding__constructFromLatin1AsURLSafeBase64; + _ = Bun__encoding__constructFromLatin1AsUTF16; + _ = Bun__encoding__constructFromLatin1AsUTF8; + _ = Bun__encoding__constructFromLatin1AsBase64; + _ = Bun__encoding__constructFromUTF16AsBase64; + _ = Bun__encoding__constructFromUTF16AsHex; + _ = Bun__encoding__constructFromUTF16AsURLSafeBase64; + _ = Bun__encoding__constructFromUTF16AsUTF16; + _ = Bun__encoding__constructFromUTF16AsUTF8; + _ = Bun__encoding__constructFromUTF16AsASCII; } } }; |