diff options
-rw-r--r-- | src/bun.js/bindings/JSBuffer.cpp | 115 |
1 files changed, 81 insertions, 34 deletions
diff --git a/src/bun.js/bindings/JSBuffer.cpp b/src/bun.js/bindings/JSBuffer.cpp index 25bd888d2..e87d2bd48 100644 --- a/src/bun.js/bindings/JSBuffer.cpp +++ b/src/bun.js/bindings/JSBuffer.cpp @@ -82,20 +82,6 @@ static JSC_DECLARE_HOST_FUNCTION(jsBufferPrototypeFunction_swap64); static JSC_DECLARE_HOST_FUNCTION(jsBufferPrototypeFunction_toString); static JSC_DECLARE_HOST_FUNCTION(jsBufferPrototypeFunction_write); -#define ENCODING_FROM_VALUE(identifier) \ - if (identifier.isString()) { \ - std::optional<BufferEncodingType> encoded = parseEnumeration<BufferEncodingType>(*lexicalGlobalObject, identifier); \ - if (!encoded) { \ - throwTypeError(lexicalGlobalObject, scope, "Invalid encoding"_s); \ - return JSC::JSValue::encode(jsUndefined()); \ - } \ - \ - encoding = encoded.value(); \ - } - -#define ENCODING_FROM_CALLFRAME(argumentIndex) \ - ENCODING_FROM_VALUE(callFrame->uncheckedArgument(argumentIndex)) - static JSUint8Array* allocBuffer(JSC::JSGlobalObject* lexicalGlobalObject, size_t byteLength) { JSC::VM& vm = JSC::getVM(lexicalGlobalObject); @@ -264,7 +250,7 @@ EncodedJSValue JSBuffer__bufferFromPointerAndLength(JSC::JSGlobalObject* lexical } // new Buffer() -static inline EncodedJSValue constructBufferEmpty(JSGlobalObject* lexicalGlobalObject, CallFrame* callFrame) +static inline EncodedJSValue constructBufferEmpty(JSGlobalObject* lexicalGlobalObject) { return JSBuffer__bufferFromLength(lexicalGlobalObject, 0); } @@ -333,7 +319,7 @@ static EncodedJSValue constructFromEncoding(JSGlobalObject* lexicalGlobalObject, return result; } -static inline JSC::EncodedJSValue constructBufferFromStringAndEncoding(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame) +static inline JSC::EncodedJSValue constructBufferFromStringAndEncoding(JSC::JSGlobalObject* lexicalGlobalObject, JSValue arg0, JSValue arg1) { auto& vm = JSC::getVM(lexicalGlobalObject); uint32_t offset = 0; @@ -341,18 +327,21 @@ static inline JSC::EncodedJSValue constructBufferFromStringAndEncoding(JSC::JSGl auto scope = DECLARE_THROW_SCOPE(vm); - EnsureStillAliveScope arg0 = callFrame->argument(0); - auto* str = arg0.value().toString(lexicalGlobalObject); + auto* str = arg0.toString(lexicalGlobalObject); RETURN_IF_EXCEPTION(scope, JSC::JSValue::encode(jsUndefined())); - EnsureStillAliveScope arg1 = callFrame->argument(1); - if (str->length() == 0) - return constructBufferEmpty(lexicalGlobalObject, callFrame); + return constructBufferEmpty(lexicalGlobalObject); - if (callFrame->argumentCount() > 1) { - ENCODING_FROM_CALLFRAME(1) + if (arg1 && arg1.isString()) { + std::optional<BufferEncodingType> encoded = parseEnumeration<BufferEncodingType>(*lexicalGlobalObject, arg1); + if (!encoded) { + throwTypeError(lexicalGlobalObject, scope, "Invalid encoding"_s); + return JSC::JSValue::encode(jsUndefined()); + } + + encoding = encoded.value(); } JSC::EncodedJSValue result = constructFromEncoding(lexicalGlobalObject, str, encoding); @@ -401,7 +390,16 @@ static inline JSC::EncodedJSValue jsBufferConstructorFunction_allocBody(JSC::JSG size_t end = length; WebCore::BufferEncodingType encoding = WebCore::BufferEncodingType::utf8; if (callFrame->argumentCount() > 2) { - ENCODING_FROM_CALLFRAME(2) + EnsureStillAliveScope arg2 = callFrame->uncheckedArgument(2); + if (arg2.value().isString()) { + std::optional<BufferEncodingType> encoded = parseEnumeration<BufferEncodingType>(*lexicalGlobalObject, arg2.value()); + if (!encoded) { + throwTypeError(lexicalGlobalObject, scope, "Invalid encoding"_s); + return JSC::JSValue::encode(jsUndefined()); + } + + encoding = encoded.value(); + } } auto startPtr = uint8Array->typedVector() + start; auto str_ = value.toWTFString(lexicalGlobalObject); @@ -464,7 +462,16 @@ static inline JSC::EncodedJSValue jsBufferConstructorFunction_byteLengthBody(JSC return JSC::JSValue::encode(JSC::jsNumber(0)); if (callFrame->argumentCount() > 1) { - ENCODING_FROM_CALLFRAME(1) + + if (arg1.value().isString()) { + std::optional<BufferEncodingType> encoded = parseEnumeration<BufferEncodingType>(*lexicalGlobalObject, arg1.value()); + if (!encoded) { + throwTypeError(lexicalGlobalObject, scope, "Invalid encoding"_s); + return JSC::JSValue::encode(jsUndefined()); + } + + encoding = encoded.value(); + } } auto view = str->tryGetValue(lexicalGlobalObject); @@ -591,7 +598,7 @@ static inline JSC::EncodedJSValue jsBufferConstructorFunction_concatBody(JSC::JS auto throwScope = DECLARE_THROW_SCOPE(vm); if (callFrame->argumentCount() < 1) { - return constructBufferEmpty(lexicalGlobalObject, callFrame); + return constructBufferEmpty(lexicalGlobalObject); } auto arrayValue = callFrame->uncheckedArgument(0); @@ -603,7 +610,7 @@ static inline JSC::EncodedJSValue jsBufferConstructorFunction_concatBody(JSC::JS size_t arrayLength = array->length(); if (arrayLength < 1) { - RELEASE_AND_RETURN(throwScope, constructBufferEmpty(lexicalGlobalObject, callFrame)); + RELEASE_AND_RETURN(throwScope, constructBufferEmpty(lexicalGlobalObject)); } size_t byteLength = 0; @@ -627,7 +634,7 @@ static inline JSC::EncodedJSValue jsBufferConstructorFunction_concatBody(JSC::JS } if (byteLength == 0) { - RELEASE_AND_RETURN(throwScope, constructBufferEmpty(lexicalGlobalObject, callFrame)); + RELEASE_AND_RETURN(throwScope, constructBufferEmpty(lexicalGlobalObject)); } JSC::JSUint8Array* outBuffer = JSBuffer__bufferFromLengthAsArray(lexicalGlobalObject, byteLength); @@ -954,6 +961,7 @@ static inline JSC::EncodedJSValue jsBufferPrototypeFunction_fillBody(JSC::JSGlob size_t start = 0; size_t end = length; WebCore::BufferEncodingType encoding = WebCore::BufferEncodingType::utf8; + if (callFrame->argumentCount() > 1) { if (auto start_ = callFrame->uncheckedArgument(1).tryGetAsUint32Index()) { start = start_.value(); @@ -971,7 +979,16 @@ static inline JSC::EncodedJSValue jsBufferPrototypeFunction_fillBody(JSC::JSGlob } if (callFrame->argumentCount() > 3) { - ENCODING_FROM_CALLFRAME(3) + EnsureStillAliveScope encodingValue = callFrame->uncheckedArgument(3); + if (encodingValue.value().isString()) { + std::optional<BufferEncodingType> encoded = parseEnumeration<BufferEncodingType>(*lexicalGlobalObject, encodingValue.value()); + if (!encoded) { + throwTypeError(lexicalGlobalObject, scope, "Invalid encoding"_s); + return JSC::JSValue::encode(jsUndefined()); + } + + encoding = encoded.value(); + } } } if (start > end) { @@ -1060,7 +1077,17 @@ static int64_t indexOf(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* } if (callFrame->argumentCount() > 2) { - ENCODING_FROM_CALLFRAME(3) + EnsureStillAliveScope encodingValue = callFrame->uncheckedArgument(2); + + if (encodingValue.value().isString()) { + std::optional<BufferEncodingType> encoded = parseEnumeration<BufferEncodingType>(*lexicalGlobalObject, encodingValue.value()); + if (!encoded) { + throwTypeError(lexicalGlobalObject, scope, "Invalid encoding"_s); + return JSC::JSValue::encode(jsUndefined()); + } + + encoding = encoded.value(); + } } } @@ -1243,7 +1270,16 @@ static inline JSC::EncodedJSValue jsBufferPrototypeFunction_toStringBody(JSC::JS case 2: case 3: case 1: { - ENCODING_FROM_CALLFRAME(1) + EnsureStillAliveScope arg1 = callFrame->uncheckedArgument(0); + if (arg1.value().isString()) { + std::optional<BufferEncodingType> encoded = parseEnumeration<BufferEncodingType>(*lexicalGlobalObject, arg1.value()); + if (!encoded) { + throwTypeError(lexicalGlobalObject, scope, "Invalid encoding"_s); + return JSC::JSValue::encode(jsUndefined()); + } + + encoding = encoded.value(); + } if (callFrame->argumentCount() == 1) break; @@ -1381,7 +1417,16 @@ static inline JSC::EncodedJSValue jsBufferPrototypeFunction_writeBody(JSC::JSGlo length = std::min(arg_len, length); if (callFrame->argumentCount() > 3) { - ENCODING_FROM_CALLFRAME(3) + EnsureStillAliveScope arg3 = callFrame->argument(3); + if (arg3.value().isString()) { + std::optional<BufferEncodingType> encoded = parseEnumeration<BufferEncodingType>(*lexicalGlobalObject, arg3.value()); + if (!encoded) { + throwTypeError(lexicalGlobalObject, scope, "Invalid encoding"_s); + return JSC::JSValue::encode(jsUndefined()); + } + + encoding = encoded.value(); + } } } else if (arg2.value().isString()) { std::optional<BufferEncodingType> encoded = parseEnumeration<BufferEncodingType>(*lexicalGlobalObject, arg2.value()); @@ -1816,9 +1861,10 @@ JSC_DEFINE_HOST_FUNCTION(constructJSBuffer, (JSC::JSGlobalObject * lexicalGlobal auto throwScope = DECLARE_THROW_SCOPE(vm); size_t argsCount = callFrame->argumentCount(); if (argsCount == 0) { - RELEASE_AND_RETURN(throwScope, constructBufferEmpty(lexicalGlobalObject, callFrame)); + RELEASE_AND_RETURN(throwScope, constructBufferEmpty(lexicalGlobalObject)); } JSValue distinguishingArg = callFrame->uncheckedArgument(0); + JSValue encodingArg = argsCount > 1 ? callFrame->uncheckedArgument(1) : JSValue(); auto* globalObject = reinterpret_cast<Zig::GlobalObject*>(lexicalGlobalObject); if (distinguishingArg.isAnyInt()) { @@ -1832,7 +1878,7 @@ JSC_DEFINE_HOST_FUNCTION(constructJSBuffer, (JSC::JSGlobalObject * lexicalGlobal case StringObjectType: case DerivedStringObjectType: { throwScope.release(); - return constructBufferFromStringAndEncoding(lexicalGlobalObject, callFrame); + return constructBufferFromStringAndEncoding(lexicalGlobalObject, distinguishingArg, encodingArg); } case Uint8ArrayType: @@ -1942,6 +1988,7 @@ JSC_DEFINE_HOST_FUNCTION(constructJSBuffer, (JSC::JSGlobalObject * lexicalGlobal if (!target) { target = globalObject->JSBufferConstructor(); } + JSC::JSObject* object = JSC::construct(lexicalGlobalObject, constructor, target, args, "Buffer failed to construct"_s); if (!object) { return JSC::JSValue::encode({}); |