aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar Ai Hoshino <ambiguous404@gmail.com> 2023-07-02 08:01:52 +0800
committerGravatar GitHub <noreply@github.com> 2023-07-01 17:01:52 -0700
commit4720fa1207d374a2447d457ad478f9f8911b959a (patch)
treee8268b3c91ea992842682afd94f32747668a136f /src
parentdf10252979aa3d87a8d127707a23678b76a15583 (diff)
downloadbun-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.cpp67
-rw-r--r--src/js/builtins/JSBufferPrototype.ts32
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) {