aboutsummaryrefslogtreecommitdiff
path: root/src/bun.js/bindings/BunString.cpp
diff options
context:
space:
mode:
authorGravatar Jarred Sumner <jarred@jarredsumner.com> 2023-07-27 04:27:09 -0700
committerGravatar GitHub <noreply@github.com> 2023-07-27 04:27:09 -0700
commit704ee133923a4e28bd51bc95b56eb54d50424c17 (patch)
tree3f4068d3a0d777a2a712739bf24a7e4e499f5cb0 /src/bun.js/bindings/BunString.cpp
parentd7aebc2222daa293dc41c4fb9e230f1848cea3ad (diff)
downloadbun-704ee133923a4e28bd51bc95b56eb54d50424c17.tar.gz
bun-704ee133923a4e28bd51bc95b56eb54d50424c17.tar.zst
bun-704ee133923a4e28bd51bc95b56eb54d50424c17.zip
Make readdir() async, fix crash in large directory trees (#3838)
* Fix unsafe GC behavior on large arrays returned by fs * Fix crash in large arrays of strings * async readdir * Add tests for large number of files returned by readdir * Move this down * Fix encoding edgecase in path.join * Async stat & lstat * add test --------- Co-authored-by: Jarred Sumner <709451+Jarred-Sumner@users.noreply.github.com>
Diffstat (limited to 'src/bun.js/bindings/BunString.cpp')
-rw-r--r--src/bun.js/bindings/BunString.cpp50
1 files changed, 33 insertions, 17 deletions
diff --git a/src/bun.js/bindings/BunString.cpp b/src/bun.js/bindings/BunString.cpp
index 714f10080..e044730c4 100644
--- a/src/bun.js/bindings/BunString.cpp
+++ b/src/bun.js/bindings/BunString.cpp
@@ -256,31 +256,47 @@ extern "C" EncodedJSValue BunString__createArray(
auto& vm = globalObject->vm();
auto throwScope = DECLARE_THROW_SCOPE(vm);
- // We must do this or Bun.gc(true) in a loop creating large arrays of strings will crash due to GC'ing.
- MarkedArgumentBuffer arguments;
- JSC::ObjectInitializationScope scope(vm);
- GCDeferralContext context(vm);
-
- arguments.fill(length, [&](JSC::JSValue* value) {
- const BunString* end = ptr + length;
- while (ptr != end) {
- *value++ = Bun::toJS(globalObject, *ptr++);
- }
- });
+ if (length < 64) {
+ // We must do this or Bun.gc(true) in a loop creating large arrays of strings will crash due to GC'ing.
+ MarkedArgumentBuffer arguments;
+
+ arguments.fill(length, [&](JSC::JSValue* value) {
+ const BunString* end = ptr + length;
+ while (ptr != end) {
+ *value++ = Bun::toJS(globalObject, *ptr++);
+ }
+ });
+
+ JSC::ObjectInitializationScope scope(vm);
+ GCDeferralContext context(vm);
- if (JSC::JSArray* array = JSC::JSArray::tryCreateUninitializedRestricted(
+ JSC::JSArray* array = JSC::JSArray::tryCreateUninitializedRestricted(
scope,
globalObject->arrayStructureForIndexingTypeDuringAllocation(JSC::ArrayWithContiguous),
- length)) {
+ length);
+
+ if (array) {
+ for (size_t i = 0; i < length; ++i) {
+ array->initializeIndex(scope, i, arguments.at(i));
+ }
+ return JSValue::encode(array);
+ }
+
+ JSC::throwOutOfMemoryError(globalObject, throwScope);
+ RELEASE_AND_RETURN(throwScope, JSValue::encode(JSC::JSValue()));
+ } else {
+ JSC::JSArray* array = constructEmptyArray(globalObject, nullptr, length);
+ if (!array) {
+ JSC::throwOutOfMemoryError(globalObject, throwScope);
+ RELEASE_AND_RETURN(throwScope, JSValue::encode(JSC::JSValue()));
+ }
for (size_t i = 0; i < length; ++i) {
- array->initializeIndex(scope, i, arguments.at(i));
+ array->putDirectIndex(globalObject, i, Bun::toJS(globalObject, *ptr++));
}
+
return JSValue::encode(array);
}
-
- JSC::throwOutOfMemoryError(globalObject, throwScope);
- RELEASE_AND_RETURN(throwScope, JSValue::encode(JSC::JSValue()));
}
extern "C" void BunString__toWTFString(BunString* bunString)