aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Jarred Sumner <709451+Jarred-Sumner@users.noreply.github.com> 2022-06-09 05:09:48 -0700
committerGravatar Jarred Sumner <709451+Jarred-Sumner@users.noreply.github.com> 2022-06-09 05:09:48 -0700
commitb8eea5cc4a1f9b6dd1a6a08d531e8e096c60cb5b (patch)
tree6f8f363e8084add4e6eb311347912b64ed2ad5dc
parentc88dd2c52c7a48d846b4ee3d9d8e113a0ec9b0b6 (diff)
downloadbun-b8eea5cc4a1f9b6dd1a6a08d531e8e096c60cb5b.tar.gz
bun-b8eea5cc4a1f9b6dd1a6a08d531e8e096c60cb5b.tar.zst
bun-b8eea5cc4a1f9b6dd1a6a08d531e8e096c60cb5b.zip
fix some memory leaks with strings
-rw-r--r--src/javascript/jsc/base.zig21
-rw-r--r--src/javascript/jsc/bindings/bindings.cpp15
-rw-r--r--src/javascript/jsc/bindings/bindings.zig2
-rw-r--r--src/javascript/jsc/bindings/helpers.h35
4 files changed, 45 insertions, 28 deletions
diff --git a/src/javascript/jsc/base.zig b/src/javascript/jsc/base.zig
index 777a5d6ef..0d128c0f3 100644
--- a/src/javascript/jsc/base.zig
+++ b/src/javascript/jsc/base.zig
@@ -2151,21 +2151,26 @@ pub fn JSError(
ctx: js.JSContextRef,
exception: ExceptionValueRef,
) void {
- var error_args: [1]js.JSValueRef = undefined;
@setCold(true);
if (comptime std.meta.fields(@TypeOf(args)).len == 0) {
var zig_str = JSC.ZigString.init(fmt);
- zig_str.detectEncoding();
- error_args[0] = zig_str.toValueAuto(ctx.ptr()).asObjectRef();
- exception.* = js.JSObjectMakeError(ctx, 1, &error_args, null);
+ if (comptime !strings.isAllASCII(fmt)) {
+ zig_str.markUTF16();
+ }
+
+ exception.* = zig_str.toErrorInstance(ctx).asObjectRef();
} else {
- var buf = std.fmt.allocPrint(default_allocator, fmt, args) catch unreachable;
+ var fallback = std.heap.stackFallback(256, default_allocator);
+ var allocator = fallback.get();
+
+ var buf = std.fmt.allocPrint(allocator, fmt, args) catch unreachable;
var zig_str = JSC.ZigString.init(buf);
zig_str.detectEncoding();
-
- error_args[0] = zig_str.toValueGC(ctx.ptr()).asObjectRef();
- exception.* = js.JSObjectMakeError(ctx, 1, &error_args, null);
+ zig_str.mark();
+ // it alwayas clones
+ exception.* = zig_str.toErrorInstance(ctx).asObjectRef();
+ allocator.free(buf);
}
}
diff --git a/src/javascript/jsc/bindings/bindings.cpp b/src/javascript/jsc/bindings/bindings.cpp
index f289f40c9..a8770005a 100644
--- a/src/javascript/jsc/bindings/bindings.cpp
+++ b/src/javascript/jsc/bindings/bindings.cpp
@@ -1078,18 +1078,9 @@ JSC__JSValue ZigString__to16BitValue(const ZigString* arg0, JSC__JSGlobalObject*
return JSC::JSValue::encode(JSC::JSValue(JSC::jsString(arg1->vm(), str)));
}
-static void free_global_string(void* str, void* ptr, unsigned len)
-{
- // i don't understand why this happens
- if (ptr == nullptr)
- return;
-
- ZigString__free_global(reinterpret_cast<const unsigned char*>(ptr), len);
-}
-
JSC__JSValue ZigString__toExternalU16(const uint16_t* arg0, size_t len, JSC__JSGlobalObject* global)
{
- auto ref = String(ExternalStringImpl::create(reinterpret_cast<const UChar*>(arg0), len, nullptr, free_global_string));
+ auto ref = String(ExternalStringImpl::create(reinterpret_cast<const UChar*>(arg0), len, reinterpret_cast<void*>(const_cast<uint16_t*>(arg0)), free_global_string));
return JSC::JSValue::encode(JSC::JSValue(JSC::jsString(
global->vm(), WTFMove(ref))));
@@ -1099,12 +1090,12 @@ JSC__JSValue ZigString__toExternalValue(const ZigString* arg0, JSC__JSGlobalObje
{
ZigString str = *arg0;
if (Zig::isTaggedUTF16Ptr(str.ptr)) {
- auto ref = String(ExternalStringImpl::create(reinterpret_cast<const UChar*>(Zig::untag(str.ptr)), str.len, nullptr, free_global_string));
+ auto ref = String(ExternalStringImpl::create(reinterpret_cast<const UChar*>(Zig::untag(str.ptr)), str.len, Zig::untagVoid(str.ptr), free_global_string));
return JSC::JSValue::encode(JSC::JSValue(JSC::jsString(
arg1->vm(), WTFMove(ref))));
} else {
- auto ref = String(ExternalStringImpl::create(Zig::untag(str.ptr), str.len, nullptr, free_global_string));
+ auto ref = String(ExternalStringImpl::create(Zig::untag(str.ptr), str.len, Zig::untagVoid(str.ptr), free_global_string));
return JSC::JSValue::encode(JSC::JSValue(JSC::jsString(
arg1->vm(),
WTFMove(ref))));
diff --git a/src/javascript/jsc/bindings/bindings.zig b/src/javascript/jsc/bindings/bindings.zig
index f20fa2253..4a01c702f 100644
--- a/src/javascript/jsc/bindings/bindings.zig
+++ b/src/javascript/jsc/bindings/bindings.zig
@@ -2723,7 +2723,7 @@ pub const JSValue = enum(i64) {
/// This algorithm differs from the IsStrictlyEqual Algorithm by treating all NaN values as equivalent and by differentiating +0𝔽 from -0𝔽.
/// https://tc39.es/ecma262/#sec-samevalue
pub fn isSameValue(this: JSValue, other: JSValue, global: *JSGlobalObject) bool {
- return cppFn("isSameValue", .{ this, other, global });
+ return @enumToInt(this) == @enumToInt(other) or cppFn("isSameValue", .{ this, other, global });
}
pub fn asString(this: JSValue) *JSString {
diff --git a/src/javascript/jsc/bindings/helpers.h b/src/javascript/jsc/bindings/helpers.h
index 8523aadbf..5b5fb5fd2 100644
--- a/src/javascript/jsc/bindings/helpers.h
+++ b/src/javascript/jsc/bindings/helpers.h
@@ -81,6 +81,16 @@ static const unsigned char* untag(const unsigned char* ptr)
((reinterpret_cast<uintptr_t>(ptr) & ~(static_cast<uint64_t>(1) << 63) & ~(static_cast<uint64_t>(1) << 62)) & ~(static_cast<uint64_t>(1) << 61)));
}
+static void* untagVoid(const unsigned char* ptr)
+{
+ return const_cast<void*>(reinterpret_cast<const void*>(untag(ptr)));
+}
+
+static void* untagVoid(const char16_t* ptr)
+{
+ return untagVoid(reinterpret_cast<const unsigned char*>(ptr));
+}
+
static const JSC::Identifier toIdentifier(ZigString str, JSC::JSGlobalObject* global)
{
if (str.len == 0 || str.ptr == nullptr) {
@@ -106,6 +116,15 @@ static bool isTaggedExternalPtr(const unsigned char* ptr)
return (reinterpret_cast<uintptr_t>(ptr) & (static_cast<uint64_t>(1) << 62)) != 0;
}
+static void free_global_string(void* str, void* ptr, unsigned len)
+{
+ // i don't understand why this happens
+ if (ptr == nullptr)
+ return;
+
+ ZigString__free_global(reinterpret_cast<const unsigned char*>(ptr), len);
+}
+
// Switching to AtomString doesn't yield a perf benefit because we're recreating it each time.
static const WTF::String toString(ZigString str)
{
@@ -116,6 +135,13 @@ static const WTF::String toString(ZigString str)
return WTF::String::fromUTF8(untag(str.ptr), str.len);
}
+ if (UNLIKELY(isTaggedExternalPtr(str.ptr))) {
+ return !isTaggedUTF16Ptr(str.ptr)
+ ? WTF::String(WTF::ExternalStringImpl::create(untag(str.ptr), str.len, untagVoid(str.ptr), free_global_string))
+ : WTF::String(WTF::ExternalStringImpl::create(
+ reinterpret_cast<const UChar*>(untag(str.ptr)), str.len, untagVoid(str.ptr), free_global_string));
+ }
+
return !isTaggedUTF16Ptr(str.ptr)
? WTF::String(WTF::StringImpl::createWithoutCopying(untag(str.ptr), str.len))
: WTF::String(WTF::StringImpl::createWithoutCopying(
@@ -280,13 +306,8 @@ static JSC::JSValue getErrorInstance(const ZigString* str, JSC__JSGlobalObject*
{
JSC::VM& vm = globalObject->vm();
- auto scope = DECLARE_THROW_SCOPE(vm);
- JSC::JSValue message = Zig::toJSString(*str, globalObject);
- JSC::JSValue options = JSC::jsUndefined();
- JSC::Structure* errorStructure = globalObject->errorStructure();
- JSC::JSObject* result = JSC::ErrorInstance::create(globalObject, errorStructure, message, options);
- RETURN_IF_EXCEPTION(scope, JSC::JSValue());
- scope.release();
+ JSC::JSObject* result = JSC::createError(globalObject, toString(*str));
+ JSC::EnsureStillAliveScope ensureAlive(result);
return JSC::JSValue(result);
}