aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Jarred Sumner <709451+Jarred-Sumner@users.noreply.github.com> 2023-01-02 15:39:18 -0800
committerGravatar Jarred Sumner <709451+Jarred-Sumner@users.noreply.github.com> 2023-01-02 15:39:44 -0800
commit8989a1883ec500ff460c532944c25cfb6c3d7aaa (patch)
tree280094acb5d8425c953d1a4f6005b19cab11a80a
parent983b747020a644233e8a716798796b71bda01854 (diff)
downloadbun-8989a1883ec500ff460c532944c25cfb6c3d7aaa.tar.gz
bun-8989a1883ec500ff460c532944c25cfb6c3d7aaa.tar.zst
bun-8989a1883ec500ff460c532944c25cfb6c3d7aaa.zip
Support any `ArrayBufferView` in StringDecoder
-rw-r--r--packages/bun-types/string_decoder.d.ts4
-rw-r--r--src/bun.js/bindings/JSStringDecoder.cpp30
2 files changed, 22 insertions, 12 deletions
diff --git a/packages/bun-types/string_decoder.d.ts b/packages/bun-types/string_decoder.d.ts
index a40fa287d..aee1680dc 100644
--- a/packages/bun-types/string_decoder.d.ts
+++ b/packages/bun-types/string_decoder.d.ts
@@ -47,7 +47,7 @@ declare module "string_decoder" {
* returned string and stored in an internal buffer for the next call to`stringDecoder.write()` or `stringDecoder.end()`.
* @param buffer A `Buffer`, or `TypedArray`, or `DataView` containing the bytes to decode.
*/
- write(buffer: Buffer): string;
+ write(buffer: Buffer | ArrayBufferView): string;
/**
* Returns any remaining input stored in the internal buffer as a string. Bytes
* representing incomplete UTF-8 and UTF-16 characters will be replaced with
@@ -57,7 +57,7 @@ declare module "string_decoder" {
* After `end()` is called, the `stringDecoder` object can be reused for new input.
* @param buffer A `Buffer`, or `TypedArray`, or `DataView` containing the bytes to decode.
*/
- end(buffer?: Buffer): string;
+ end(buffer?: Buffer | ArrayBufferView): string;
}
}
declare module "node:string_decoder" {
diff --git a/src/bun.js/bindings/JSStringDecoder.cpp b/src/bun.js/bindings/JSStringDecoder.cpp
index 5d5a66141..a2872b994 100644
--- a/src/bun.js/bindings/JSStringDecoder.cpp
+++ b/src/bun.js/bindings/JSStringDecoder.cpp
@@ -7,6 +7,7 @@
#include "JSDOMAttribute.h"
#include "headers.h"
#include "JSDOMConvertEnumeration.h"
+#include "JavaScriptCore/JSArrayBufferView.h"
namespace WebCore {
@@ -287,12 +288,20 @@ static inline JSC::EncodedJSValue jsStringDecoderPrototypeFunction_writeBody(JSC
}
auto buffer = callFrame->uncheckedArgument(0);
- JSC::JSUint8Array* view = JSC::jsDynamicCast<JSC::JSUint8Array*>(buffer);
- if (!view) {
+ 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, view->typedVector(), view->length())));
+ 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, typename IDLOperation<JSStringDecoder>::ClassParameter castedThis)
{
@@ -303,12 +312,12 @@ static inline JSC::EncodedJSValue jsStringDecoderPrototypeFunction_endBody(JSC::
}
auto buffer = callFrame->uncheckedArgument(0);
- JSC::JSUint8Array* view = JSC::jsDynamicCast<JSC::JSUint8Array*>(buffer);
- if (!view) {
+ 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, view->typedVector(), view->length())));
+ 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, typename IDLOperation<JSStringDecoder>::ClassParameter castedThis)
{
@@ -320,16 +329,17 @@ static inline JSC::EncodedJSValue jsStringDecoderPrototypeFunction_textBody(JSC:
}
auto buffer = callFrame->uncheckedArgument(0);
- JSC::JSUint8Array* view = JSC::jsDynamicCast<JSC::JSUint8Array*>(buffer);
- if (!view) {
+ 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()));
- if (offset > view->length())
+ 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, view->typedVector() + offset, view->length() - offset)));
+ RELEASE_AND_RETURN(throwScope, JSC::JSValue::encode(castedThis->write(vm, lexicalGlobalObject, reinterpret_cast<uint8_t*>(view->vector()) + offset, byteLength - offset)));
}
static JSC_DEFINE_HOST_FUNCTION(jsStringDecoderPrototypeFunction_write,