aboutsummaryrefslogtreecommitdiff
path: root/src/bun.js/bindings/BunString.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/bun.js/bindings/BunString.cpp')
-rw-r--r--src/bun.js/bindings/BunString.cpp57
1 files changed, 55 insertions, 2 deletions
diff --git a/src/bun.js/bindings/BunString.cpp b/src/bun.js/bindings/BunString.cpp
index 249f68435..f737342f4 100644
--- a/src/bun.js/bindings/BunString.cpp
+++ b/src/bun.js/bindings/BunString.cpp
@@ -4,6 +4,7 @@
#include "helpers.h"
#include "simdutf.h"
#include "wtf/text/ExternalStringImpl.h"
+#include "GCDefferalContext.h"
using namespace JSC;
extern "C" void Bun__WTFStringImpl__deref(WTF::StringImpl* impl)
@@ -125,6 +126,22 @@ extern "C" JSC::EncodedJSValue BunString__toJS(JSC::JSGlobalObject* globalObject
return JSValue::encode(Bun::toJS(globalObject, *bunString));
}
+extern "C" BunString BunString__fromUTF8(const char* bytes, size_t length)
+{
+ if (simdutf::validate_utf8(bytes, length)) {
+ size_t u16Length = simdutf::utf16_length_from_utf8(bytes, length);
+ UChar* ptr;
+ auto impl = WTF::StringImpl::createUninitialized(static_cast<unsigned int>(u16Length), ptr);
+ RELEASE_ASSERT(simdutf::convert_utf8_to_utf16(bytes, length, ptr) == u16Length);
+ impl->ref();
+ return { BunStringTag::WTFStringImpl, { .wtf = &impl.leakRef() } };
+ }
+
+ auto str = WTF::String::fromUTF8ReplacingInvalidSequences(reinterpret_cast<const LChar*>(bytes), length);
+ str.impl()->ref();
+ return Bun::fromString(str);
+}
+
extern "C" BunString BunString__fromLatin1(const char* bytes, size_t length)
{
return { BunStringTag::WTFStringImpl, { .wtf = &WTF::StringImpl::create(bytes, length).leakRef() } };
@@ -136,8 +153,7 @@ extern "C" BunString BunString__fromBytes(const char* bytes, size_t length)
return BunString__fromLatin1(bytes, length);
}
- auto str = WTF::String::fromUTF8ReplacingInvalidSequences(reinterpret_cast<const LChar*>(bytes), length);
- return Bun::fromString(str);
+ return BunString__fromUTF8(bytes, length);
}
extern "C" BunString BunString__createExternal(const char* bytes, size_t length, bool isLatin1, void* ctx, void (*callback)(void* arg0, void* arg1, size_t arg2))
@@ -149,6 +165,43 @@ extern "C" BunString BunString__createExternal(const char* bytes, size_t length,
return { BunStringTag::WTFStringImpl, { .wtf = &impl.leakRef() } };
}
+extern "C" EncodedJSValue BunString__createArray(
+ JSC::JSGlobalObject* globalObject,
+ const BunString* ptr, size_t length)
+{
+ if (length == 0)
+ return JSValue::encode(JSC::constructEmptyArray(globalObject, nullptr));
+
+ 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 (JSC::JSArray* array = JSC::JSArray::tryCreateUninitializedRestricted(
+ scope,
+ globalObject->arrayStructureForIndexingTypeDuringAllocation(JSC::ArrayWithContiguous),
+ length)) {
+
+ 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()));
+}
+
extern "C" void BunString__toWTFString(BunString* bunString)
{
if (bunString->tag == BunStringTag::ZigString) {