aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Jarred Sumner <709451+Jarred-Sumner@users.noreply.github.com> 2022-11-27 20:21:41 -0800
committerGravatar Jarred Sumner <709451+Jarred-Sumner@users.noreply.github.com> 2022-11-27 20:21:41 -0800
commited152596231975d1d09598b8221f49a10c5aa0b6 (patch)
tree4acb4146bf8428914be3061a6a2efb9c3c2b1fe2
parent427203874355abb4e1b1f97852a9fea2d4a5aa14 (diff)
downloadbun-ed152596231975d1d09598b8221f49a10c5aa0b6.tar.gz
bun-ed152596231975d1d09598b8221f49a10c5aa0b6.tar.zst
bun-ed152596231975d1d09598b8221f49a10c5aa0b6.zip
Fix Buffer.toString("latin1") and make Buffer.toString("utf16le") faster
Fixes #455 Fixes #1016
-rw-r--r--src/bun.js/bindings/JSBuffer.cpp20
-rw-r--r--test/bun.js/buffer.test.js27
2 files changed, 44 insertions, 3 deletions
diff --git a/src/bun.js/bindings/JSBuffer.cpp b/src/bun.js/bindings/JSBuffer.cpp
index 8f9ce2dd2..b3e5f0b4e 100644
--- a/src/bun.js/bindings/JSBuffer.cpp
+++ b/src/bun.js/bindings/JSBuffer.cpp
@@ -1141,14 +1141,28 @@ static inline JSC::EncodedJSValue jsBufferPrototypeFunction_toStringBody(JSC::JS
switch (encoding) {
case WebCore::BufferEncodingType::latin1: {
- ret = JSC::JSValue::encode(JSC::jsString(vm, WTF::StringImpl::create(reinterpret_cast<const UChar*>(castedThis->typedVector() + offset), length)));
+ LChar* data = nullptr;
+ auto str = String::createUninitialized(length, data);
+ memcpy(data, reinterpret_cast<const char*>(castedThis->typedVector() + offset), length);
+ ret = JSC::JSValue::encode(JSC::jsString(vm, WTFMove(str)));
break;
}
+
+ case WebCore::BufferEncodingType::ucs2:
+ case WebCore::BufferEncodingType::utf16le: {
+ UChar* data = nullptr;
+ size_t u16length = length > 1 ? length / 2 : 1;
+ auto str = String::createUninitialized(u16length, data);
+ // always zero out the last byte of the string incase the buffer is not a multiple of 2
+ data[u16length - 1] = 0;
+ memcpy(data, reinterpret_cast<const char*>(castedThis->typedVector() + offset), length);
+ ret = JSC::JSValue::encode(JSC::jsString(vm, WTFMove(str)));
+ break;
+ }
+
case WebCore::BufferEncodingType::buffer:
case WebCore::BufferEncodingType::utf8:
case WebCore::BufferEncodingType::ascii:
- case WebCore::BufferEncodingType::ucs2:
- case WebCore::BufferEncodingType::utf16le:
case WebCore::BufferEncodingType::base64:
case WebCore::BufferEncodingType::base64url:
case WebCore::BufferEncodingType::hex: {
diff --git a/test/bun.js/buffer.test.js b/test/bun.js/buffer.test.js
index 14394bd2a..b8771d5b4 100644
--- a/test/bun.js/buffer.test.js
+++ b/test/bun.js/buffer.test.js
@@ -600,6 +600,33 @@ it("Buffer.from(base64)", () => {
).toBe('console.log("hello world")\n');
});
+it("Buffer.toString regessions", () => {
+ expect(
+ Buffer.from([65, 0])
+ .toString("utf16le")
+ .split("")
+ .map((x) => x.charCodeAt(0)),
+ ).toEqual([65]);
+ expect(Buffer.from([65, 0]).toString("base64")).toBe("QQA=");
+ expect(
+ Buffer.from('{"alg":"RS256","typ":"JWT"}', "latin1").toString("latin1"),
+ ).toBe('{"alg":"RS256","typ":"JWT"}');
+ expect(
+ Buffer.from('{"alg":"RS256","typ":"JWT"}', "utf8").toString("utf8"),
+ ).toBe('{"alg":"RS256","typ":"JWT"}');
+});
+
+it("Buffer.toString(utf16le)", () => {
+ const buf = Buffer.from("hello world", "utf16le");
+ expect(buf.toString("utf16le")).toBe("hello world");
+ expect(buf.toString("utf16le", 0, 5)).toBe("he");
+});
+
+it("Buffer.toString(binary)", () => {
+ var x = Buffer.from("<?xm", "binary");
+ expect(x.toString("binary")).toBe("<?xm");
+});
+
it("Buffer.toString(base64)", () => {
{
const buf = Buffer.from("hello world");