diff options
author | 2023-07-02 08:01:52 +0800 | |
---|---|---|
committer | 2023-07-01 17:01:52 -0700 | |
commit | 4720fa1207d374a2447d457ad478f9f8911b959a (patch) | |
tree | e8268b3c91ea992842682afd94f32747668a136f /src | |
parent | df10252979aa3d87a8d127707a23678b76a15583 (diff) | |
download | bun-4720fa1207d374a2447d457ad478f9f8911b959a.tar.gz bun-4720fa1207d374a2447d457ad478f9f8911b959a.tar.zst bun-4720fa1207d374a2447d457ad478f9f8911b959a.zip |
[WIP]Fix calling `Buffer.toString` with `(offset, length, encoding)` (#3467)
* Allow `toString` to be called with `(offset, length, encoding)`.
Close: #3085
* handle undefined value
* add tests for buffer.xxxSlice
* fix parameters
* fix offset and length
Diffstat (limited to 'src')
-rw-r--r-- | src/bun.js/bindings/JSBuffer.cpp | 67 | ||||
-rw-r--r-- | src/js/builtins/JSBufferPrototype.ts | 32 |
2 files changed, 56 insertions, 43 deletions
diff --git a/src/bun.js/bindings/JSBuffer.cpp b/src/bun.js/bindings/JSBuffer.cpp index 00965da89..4b0e058dd 100644 --- a/src/bun.js/bindings/JSBuffer.cpp +++ b/src/bun.js/bindings/JSBuffer.cpp @@ -1436,43 +1436,56 @@ static inline JSC::EncodedJSValue jsBufferPrototypeFunction_toStringBody(JSC::JS if (length == 0) return JSC::JSValue::encode(JSC::jsEmptyString(vm)); - switch (callFrame->argumentCount()) { - case 0: { - break; - } - case 2: - case 3: - case 1: { - EnsureStillAliveScope arg1 = callFrame->uncheckedArgument(0); - if (!arg1.value().isUndefined()) { - encoding = parseEncoding(lexicalGlobalObject, scope, arg1.value()); + size_t argsCount = callFrame->argumentCount(); + + JSC::JSValue arg1 = callFrame->argument(0); + JSC::JSValue arg2 = callFrame->argument(1); + JSC::JSValue arg3 = callFrame->argument(2); + + // This method could be called in following forms: + // - toString() + // - toString(encoding) + // - toString(encoding, start) + // - toString(encoding, start, end) + // - toString(offset, length) + // - toString(offset, length, encoding) + if (argsCount == 0) + return jsBufferToString(vm, lexicalGlobalObject, castedThis, offset, length, encoding); + + if (arg1.isString()) { + encoding = parseEncoding(lexicalGlobalObject, scope, arg1); RETURN_IF_EXCEPTION(scope, JSC::JSValue::encode(jsUndefined())); - } - if (callFrame->argumentCount() == 1) - break; - } - // any - case 5: { - JSC::JSValue arg2 = callFrame->uncheckedArgument(1); - int32_t ioffset = arg2.toInt32(lexicalGlobalObject); + + if (!arg3.isUndefined()) { + // length is end + length = std::min(byteLength, static_cast<uint32_t>(arg3.toInt32(lexicalGlobalObject))); + } + + int32_t istart = arg2.toInt32(lexicalGlobalObject); + if (istart < 0) { + throwTypeError(lexicalGlobalObject, scope, "Start must be a positive integer"_s); + return JSC::JSValue::encode(jsUndefined()); + } + offset = static_cast<uint32_t>(istart); + length = (length > offset) ? (length - offset) : 0; + } else { + int32_t ioffset = arg1.toInt32(lexicalGlobalObject); if (ioffset < 0) { throwTypeError(lexicalGlobalObject, scope, "Offset must be a positive integer"_s); return JSC::JSValue::encode(jsUndefined()); } offset = static_cast<uint32_t>(ioffset); + length = (length > offset) ? (length - offset) : 0; - if (callFrame->argumentCount() == 2) - break; - } + if (!arg3.isUndefined()) { + encoding = parseEncoding(lexicalGlobalObject, scope, arg3); + RETURN_IF_EXCEPTION(scope, JSC::JSValue::encode(jsUndefined())); + } - default: { - length = std::min(byteLength, static_cast<uint32_t>(callFrame->argument(2).toInt32(lexicalGlobalObject))); - break; - } + if (!arg2.isUndefined()) + length = std::min(length, static_cast<uint32_t>(arg2.toInt32(lexicalGlobalObject))); } - length -= std::min(offset, length); - return jsBufferToString(vm, lexicalGlobalObject, castedThis, offset, length, encoding); } diff --git a/src/js/builtins/JSBufferPrototype.ts b/src/js/builtins/JSBufferPrototype.ts index 97b25b9b2..f5d6a7bfb 100644 --- a/src/js/builtins/JSBufferPrototype.ts +++ b/src/js/builtins/JSBufferPrototype.ts @@ -427,29 +427,29 @@ export function hexWrite(this: BufferExt, text, offset, length) { return this.write(text, offset, length, "hex"); } -export function utf8Slice(this: BufferExt, offset, length) { - return this.toString(offset, length, "utf8"); +export function utf8Slice(this: BufferExt, start, end) { + return this.toString("utf8", start, end); } -export function ucs2Slice(this: BufferExt, offset, length) { - return this.toString(offset, length, "ucs2"); +export function ucs2Slice(this: BufferExt, start, end) { + return this.toString("ucs2", start, end); } -export function utf16leSlice(this: BufferExt, offset, length) { - return this.toString(offset, length, "utf16le"); +export function utf16leSlice(this: BufferExt, start, end) { + return this.toString("utf16le", start, end); } -export function latin1Slice(this: BufferExt, offset, length) { - return this.toString(offset, length, "latin1"); +export function latin1Slice(this: BufferExt, start, end) { + return this.toString("latin1", start, end); } -export function asciiSlice(this: BufferExt, offset, length) { - return this.toString(offset, length, "ascii"); +export function asciiSlice(this: BufferExt, start, end) { + return this.toString("ascii", start, end); } -export function base64Slice(this: BufferExt, offset, length) { - return this.toString(offset, length, "base64"); +export function base64Slice(this: BufferExt, start, end) { + return this.toString("base64", start, end); } -export function base64urlSlice(this: BufferExt, offset, length) { - return this.toString(offset, length, "base64url"); +export function base64urlSlice(this: BufferExt, start, end) { + return this.toString("base64url", start, end); } -export function hexSlice(this: BufferExt, offset, length) { - return this.toString(offset, length, "hex"); +export function hexSlice(this: BufferExt, start, end) { + return this.toString("hex", start, end); } export function toJSON(this: BufferExt) { |