diff options
author | 2023-01-02 15:39:18 -0800 | |
---|---|---|
committer | 2023-01-02 15:39:44 -0800 | |
commit | 8989a1883ec500ff460c532944c25cfb6c3d7aaa (patch) | |
tree | 280094acb5d8425c953d1a4f6005b19cab11a80a | |
parent | 983b747020a644233e8a716798796b71bda01854 (diff) | |
download | bun-8989a1883ec500ff460c532944c25cfb6c3d7aaa.tar.gz bun-8989a1883ec500ff460c532944c25cfb6c3d7aaa.tar.zst bun-8989a1883ec500ff460c532944c25cfb6c3d7aaa.zip |
Support any `ArrayBufferView` in StringDecoder
-rw-r--r-- | packages/bun-types/string_decoder.d.ts | 4 | ||||
-rw-r--r-- | src/bun.js/bindings/JSStringDecoder.cpp | 30 |
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, |