diff options
author | 2022-05-01 03:43:52 -0700 | |
---|---|---|
committer | 2022-05-01 03:43:52 -0700 | |
commit | b6aa9887169f3cb7b7e866d8ea5544bc168dec86 (patch) | |
tree | e7cbaadd575ee7da7dd3f96a286cfa93d9f42099 | |
parent | a3b48b3229b4dcdaa7c51762ceb2641d219e9a1c (diff) | |
download | bun-b6aa9887169f3cb7b7e866d8ea5544bc168dec86.tar.gz bun-b6aa9887169f3cb7b7e866d8ea5544bc168dec86.tar.zst bun-b6aa9887169f3cb7b7e866d8ea5544bc168dec86.zip |
[bun.js] Improve `Buffer` creation perf a little
-rw-r--r-- | integration/bunjs-only-snippets/buffer.test.js | 42 | ||||
-rw-r--r-- | src/javascript/jsc/bindings/JSBuffer.cpp | 11 |
2 files changed, 45 insertions, 8 deletions
diff --git a/integration/bunjs-only-snippets/buffer.test.js b/integration/bunjs-only-snippets/buffer.test.js index 19502b285..c934f872d 100644 --- a/integration/bunjs-only-snippets/buffer.test.js +++ b/integration/bunjs-only-snippets/buffer.test.js @@ -1,22 +1,32 @@ +import { gc } from "bun"; import { describe, it, expect } from "bun:test"; it("buffer", () => { var buf = new Buffer(20); + gc(); // if this fails or infinitely loops, it means there is a memory issue with the JSC::Structure object expect(Object.keys(buf).length > 0).toBe(true); - + gc(); expect(buf.write("hello world ")).toBe(12); + gc(); expect(buf.toString("utf8", 0, "hello world ".length)).toBe("hello world "); + gc(); expect(buf.toString("base64url", 0, "hello world ".length)).toBe( btoa("hello world ") ); - + gc(); expect(buf instanceof Uint8Array).toBe(true); + gc(); expect(buf instanceof Buffer).toBe(true); + gc(); expect(buf.slice() instanceof Uint8Array).toBe(true); + gc(); expect(buf.slice(0, 1) instanceof Buffer).toBe(true); + gc(); expect(buf.slice(0, 1) instanceof Uint8Array).toBe(true); + gc(); expect(buf.slice(0, 1) instanceof Buffer).toBe(true); + gc(); }); it("Buffer", () => { @@ -29,10 +39,31 @@ it("Buffer", () => { for (let i = 0; i < inputs.length; i++) { var input = inputs[i]; expect(new Buffer(input).toString("utf8")).toBe(inputs[i]); + gc(); expect(Array.from(new Buffer(input)).join(",")).toBe(good[i].join(",")); + gc(); } }); +it("Buffer.isBuffer", () => { + expect(Buffer.isBuffer(new Buffer(1))).toBe(true); + gc(); + expect(Buffer.isBuffer(new Buffer(0))).toBe(true); + gc(); + expect(Buffer.isBuffer(new Uint8Array(0))).toBe(false); + gc(); + expect(Buffer.isBuffer(new Uint8Array(1))).toBe(false); + gc(); + var a = new Uint8Array(1); + gc(); + expect(Buffer.isBuffer(a)).toBe(false); + gc(); + Buffer.toBuffer(a); + gc(); + expect(Buffer.isBuffer(a)).toBe(true); + gc(); +}); + it("Buffer.toBuffer throws", () => { const checks = [ [], @@ -61,10 +92,13 @@ it("Buffer.toBuffer works", () => { expect(Object.keys(buf).length > 0).toBe(true); expect(buf.write("hello world ")).toBe(12); + gc(); expect(buf.toString("utf8", 0, "hello world ".length)).toBe("hello world "); + gc(); expect(buf.toString("base64url", 0, "hello world ".length)).toBe( btoa("hello world ") ); + gc(); expect(buf instanceof Uint8Array).toBe(true); expect(buf instanceof Buffer).toBe(true); @@ -96,6 +130,7 @@ it("Buffer.from", () => { expect(Buffer.from("hello world", "latin1").toString("utf8")).toBe( "hello world" ); + gc(); expect(Buffer.from([254]).join(",")).toBe("254"); expect(Buffer.from(123).join(",")).toBe(Uint8Array.from(123).join(",")); expect(Buffer.from({ length: 124 }).join(",")).toBe( @@ -109,6 +144,7 @@ it("Buffer.from", () => { expect(Buffer.from(new Buffer(new ArrayBuffer(1024), 0, 512)).join(",")).toBe( new Uint8Array(512).join(",") ); + gc(); }); it("Buffer.copy", () => { @@ -120,6 +156,7 @@ it("Buffer.copy", () => { Buffer.toBuffer(array2); var array3 = new Uint8Array(128); Buffer.toBuffer(array3); + gc(); expect(array1.copy(array2)).toBe(128); expect(array1.join("")).toBe(array2.join("")); }); @@ -131,6 +168,7 @@ it("Buffer.concat", () => { array2.fill(200); var array3 = new Uint8Array(128); array3.fill(300); + gc(); expect(Buffer.concat([array1, array2, array3]).join("")).toBe( array1.join("") + array2.join("") + array3.join("") ); diff --git a/src/javascript/jsc/bindings/JSBuffer.cpp b/src/javascript/jsc/bindings/JSBuffer.cpp index 7a5ea8c7b..eab0a7734 100644 --- a/src/javascript/jsc/bindings/JSBuffer.cpp +++ b/src/javascript/jsc/bindings/JSBuffer.cpp @@ -376,10 +376,7 @@ static inline JSC::EncodedJSValue jsBufferConstructorFunction_concatBody(JSC::JS for (size_t i = 0; i < arrayLength; i++) { auto element = array->getIndex(lexicalGlobalObject, i); RETURN_IF_EXCEPTION(throwScope, {}); - if (!element.isObject()) { - throwTypeError(lexicalGlobalObject, throwScope, "Buffer.concat expects Uint8Array"_s); - return JSValue::encode(jsUndefined()); - } + auto* typedArray = JSC::jsDynamicCast<JSC::JSUint8Array*>(vm, element); if (!typedArray) { throwTypeError(lexicalGlobalObject, throwScope, "Buffer.concat expects Uint8Array"_s); @@ -1123,6 +1120,9 @@ void JSBufferPrototype::finishCreation(VM& vm, JSC::JSGlobalObject* globalThis) reifyStaticProperties(vm, JSBuffer::info(), JSBufferPrototypeTableValues, *this); JSC_TO_STRING_TAG_WITHOUT_TRANSITION(); this->setPrototypeDirect(vm, globalThis->m_typedArrayUint8.prototype(globalThis)); + auto clientData = WebCore::clientData(vm); + this->putDirect(vm, clientData->builtinNames().dataViewPublicName(), JSC::jsUndefined(), JSC::PropertyAttribute::DontEnum | JSC::PropertyAttribute::DontDelete | JSC::PropertyAttribute::ReadOnly); + this->putDirect(vm, clientData->builtinNames().dataViewPrivateName(), JSC::JSValue(true), JSC::PropertyAttribute::DontEnum | JSC::PropertyAttribute::DontDelete | JSC::PropertyAttribute::ReadOnly); } const ClassInfo JSBufferPrototype::s_info = { "Buffer"_s, nullptr, nullptr, nullptr, CREATE_METHOD_TABLE(JSBufferPrototype) }; @@ -1249,6 +1249,5 @@ static void toBuffer(JSC::JSGlobalObject* lexicalGlobalObject, JSC::JSUint8Array auto* dataView = JSC::JSDataView::create(lexicalGlobalObject, lexicalGlobalObject->typedArrayStructure(JSC::TypeDataView), uint8Array->possiblySharedBuffer(), uint8Array->byteOffset(), uint8Array->length()); // putDirectWithTransition doesn't work here - object->putDirect(vm, clientData->builtinNames().dataViewPublicName(), dataView, JSC::PropertyAttribute::DontEnum | JSC::PropertyAttribute::DontDelete | JSC::PropertyAttribute::ReadOnly); - object->putDirect(vm, clientData->builtinNames().dataViewPrivateName(), JSC::JSValue(true), JSC::PropertyAttribute::DontEnum | JSC::PropertyAttribute::DontDelete | JSC::PropertyAttribute::ReadOnly); + object->putDirectWithoutTransition(vm, clientData->builtinNames().dataViewPublicName(), dataView, JSC::PropertyAttribute::DontEnum | JSC::PropertyAttribute::DontDelete | JSC::PropertyAttribute::ReadOnly); }
\ No newline at end of file |