aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/bun.js/api/bun/dns_resolver.zig8
-rw-r--r--src/bun.js/api/bun/socket.zig12
-rw-r--r--src/bun.js/api/ffi.zig6
-rw-r--r--src/bun.js/api/server.zig12
-rw-r--r--src/bun.js/bindings/BunString.cpp48
-rw-r--r--src/bun.js/bindings/bindings.cpp66
-rw-r--r--src/bun.js/bindings/bindings.zig8
-rw-r--r--src/bun.js/bindings/headers-handwritten.h12
-rw-r--r--src/bun.js/bindings/helpers.h4
-rw-r--r--src/bun.js/bindings/napi.cpp29
-rw-r--r--src/bun.js/bindings/webcore/JSCloseEvent.cpp2
-rw-r--r--src/bun.js/node/node_os.zig32
-rw-r--r--src/bun.js/node/syscall.zig8
-rw-r--r--src/bun.js/webcore/blob.zig55
-rw-r--r--src/bun.js/webcore/response.zig14
-rw-r--r--src/bun.js/webcore/streams.zig6
-rw-r--r--src/bundler/bundle_v2.zig16
-rw-r--r--src/http.zig5
-rw-r--r--src/napi/napi.zig11
-rw-r--r--test/js/bun/util/error-gc-test.test.js41
20 files changed, 242 insertions, 153 deletions
diff --git a/src/bun.js/api/bun/dns_resolver.zig b/src/bun.js/api/bun/dns_resolver.zig
index fee834e5e..d0d4f5b7b 100644
--- a/src/bun.js/api/bun/dns_resolver.zig
+++ b/src/bun.js/api/bun/dns_resolver.zig
@@ -1925,8 +1925,8 @@ pub const DNSResolver = struct {
.err => |err| {
const system_error = JSC.SystemError{
.errno = -1,
- .code = JSC.ZigString.init(err.code()),
- .message = JSC.ZigString.init(err.label()),
+ .code = bun.String.static(err.code()),
+ .message = bun.String.static(err.label()),
};
globalThis.throwValue(system_error.toErrorInstance(globalThis));
@@ -1972,8 +1972,8 @@ pub const DNSResolver = struct {
.err => |err| {
const system_error = JSC.SystemError{
.errno = -1,
- .code = JSC.ZigString.init(err.code()),
- .message = JSC.ZigString.init(err.label()),
+ .code = bun.String.static(err.code()),
+ .message = bun.String.static(err.label()),
};
globalThis.throwValue(system_error.toErrorInstance(globalThis));
diff --git a/src/bun.js/api/bun/socket.zig b/src/bun.js/api/bun/socket.zig
index 00e34a77d..69d6611cb 100644
--- a/src/bun.js/api/bun/socket.zig
+++ b/src/bun.js/api/bun/socket.zig
@@ -1022,8 +1022,8 @@ fn NewSocket(comptime ssl: bool) type {
var globalObject = handlers.globalObject;
const err = JSC.SystemError{
.errno = errno,
- .message = ZigString.init("Failed to connect"),
- .syscall = ZigString.init("connect"),
+ .message = bun.String.static("Failed to connect"),
+ .syscall = bun.String.static("connect"),
};
if (callback == .zero) {
@@ -1232,8 +1232,8 @@ fn NewSocket(comptime ssl: bool) type {
const reason = if (ssl_error.reason == null) "" else ssl_error.reason[0..bun.len(ssl_error.reason)];
const fallback = JSC.SystemError{
- .code = ZigString.init(code),
- .message = ZigString.init(reason),
+ .code = bun.String.create(code),
+ .message = bun.String.create(reason),
};
authorization_error = fallback.toErrorInstance(globalObject);
@@ -1409,8 +1409,8 @@ fn NewSocket(comptime ssl: bool) type {
const reason = if (ssl_error.reason == null) "" else ssl_error.reason[0..bun.len(ssl_error.reason)];
const fallback = JSC.SystemError{
- .code = ZigString.init(code),
- .message = ZigString.init(reason),
+ .code = bun.String.create(code),
+ .message = bun.String.create(reason),
};
return fallback.toErrorInstance(globalObject);
diff --git a/src/bun.js/api/ffi.zig b/src/bun.js/api/ffi.zig
index e46e054ec..ba31b67ed 100644
--- a/src/bun.js/api/ffi.zig
+++ b/src/bun.js/api/ffi.zig
@@ -311,9 +311,9 @@ pub const FFI = struct {
break :brk std.DynLib.open(backup_name) catch {
// Then, if that fails, report an error.
const system_error = JSC.SystemError{
- .code = ZigString.init(@tagName(JSC.Node.ErrorCode.ERR_DLOPEN_FAILED)),
- .message = ZigString.init("Failed to open library. This is usually caused by a missing library or an invalid library path."),
- .syscall = ZigString.init("dlopen"),
+ .code = bun.String.create(@tagName(JSC.Node.ErrorCode.ERR_DLOPEN_FAILED)),
+ .message = bun.String.create("Failed to open library. This is usually caused by a missing library or an invalid library path."),
+ .syscall = bun.String.create("dlopen"),
};
return system_error.toErrorInstance(global);
};
diff --git a/src/bun.js/api/server.zig b/src/bun.js/api/server.zig
index 136737069..140e62ce4 100644
--- a/src/bun.js/api/server.zig
+++ b/src/bun.js/api/server.zig
@@ -1796,7 +1796,7 @@ fn NewRequestContext(comptime ssl_enabled: bool, comptime debug_mode: bool, comp
.syscall = .sendfile,
};
var sys = err.withPathLike(file.pathlike).toSystemError();
- sys.message = ZigString.init("MacOS does not support sending non-regular files");
+ sys.message = bun.String.static("MacOS does not support sending non-regular files");
this.runErrorHandler(sys.toErrorInstance(
this.server.globalThis,
));
@@ -1815,7 +1815,7 @@ fn NewRequestContext(comptime ssl_enabled: bool, comptime debug_mode: bool, comp
.syscall = .sendfile,
};
var sys = err.withPathLike(file.pathlike).toSystemError();
- sys.message = ZigString.init("File must be regular or FIFO");
+ sys.message = bun.String.static("File must be regular or FIFO");
this.runErrorHandler(sys.toErrorInstance(
this.server.globalThis,
));
@@ -2375,8 +2375,8 @@ fn NewRequestContext(comptime ssl_enabled: bool, comptime debug_mode: bool, comp
}
const fallback = JSC.SystemError{
- .code = ZigString.init(@as(string, @tagName(JSC.Node.ErrorCode.ERR_UNHANDLED_ERROR))),
- .message = ZigString.init("Unhandled error in ReadableStream"),
+ .code = bun.String.static(@as(string, @tagName(JSC.Node.ErrorCode.ERR_UNHANDLED_ERROR))),
+ .message = bun.String.static("Unhandled error in ReadableStream"),
};
req.handleReject(fallback.toErrorInstance(globalThis));
}
@@ -2422,8 +2422,8 @@ fn NewRequestContext(comptime ssl_enabled: bool, comptime debug_mode: bool, comp
if (stream.isLocked(this.server.globalThis)) {
streamLog("was locked but it shouldn't be", .{});
var err = JSC.SystemError{
- .code = ZigString.init(@as(string, @tagName(JSC.Node.ErrorCode.ERR_STREAM_CANNOT_PIPE))),
- .message = ZigString.init("Stream already used, please create a new one"),
+ .code = bun.String.static(@as(string, @tagName(JSC.Node.ErrorCode.ERR_STREAM_CANNOT_PIPE))),
+ .message = bun.String.static("Stream already used, please create a new one"),
};
stream.value.unprotect();
this.runErrorHandler(err.toErrorInstance(this.server.globalThis));
diff --git a/src/bun.js/bindings/BunString.cpp b/src/bun.js/bindings/BunString.cpp
index f590edd35..4c8ff384e 100644
--- a/src/bun.js/bindings/BunString.cpp
+++ b/src/bun.js/bindings/BunString.cpp
@@ -86,31 +86,69 @@ BunString toString(JSC::JSGlobalObject* globalObject, JSValue value)
return fromJS(globalObject, value);
}
+BunString toStringRef(JSC::JSGlobalObject* globalObject, JSValue value)
+{
+ auto str = value.toWTFString(globalObject);
+ if (str.isEmpty()) {
+ return { BunStringTag::Empty };
+ }
+
+ str.impl()->ref();
+
+ return { BunStringTag::WTFStringImpl, { .wtf = str.impl() } };
+}
+
BunString toString(WTF::String& wtfString)
{
- if (wtfString.length() == 0)
+ if (wtfString.isEmpty())
return { BunStringTag::Empty };
return { BunStringTag::WTFStringImpl, { .wtf = wtfString.impl() } };
}
BunString toString(const WTF::String& wtfString)
{
- if (wtfString.length() == 0)
+ if (wtfString.isEmpty())
return { BunStringTag::Empty };
return { BunStringTag::WTFStringImpl, { .wtf = wtfString.impl() } };
}
BunString toString(WTF::StringImpl* wtfString)
{
- if (wtfString->length() == 0)
+ if (wtfString->isEmpty())
return { BunStringTag::Empty };
return { BunStringTag::WTFStringImpl, { .wtf = wtfString } };
}
+BunString toStringRef(WTF::String& wtfString)
+{
+ if (wtfString.isEmpty())
+ return { BunStringTag::Empty };
+
+ wtfString.impl()->ref();
+ return { BunStringTag::WTFStringImpl, { .wtf = wtfString.impl() } };
+}
+BunString toStringRef(const WTF::String& wtfString)
+{
+ if (wtfString.isEmpty())
+ return { BunStringTag::Empty };
+
+ wtfString.impl()->ref();
+ return { BunStringTag::WTFStringImpl, { .wtf = wtfString.impl() } };
+}
+BunString toStringRef(WTF::StringImpl* wtfString)
+{
+ if (wtfString->isEmpty())
+ return { BunStringTag::Empty };
+
+ wtfString->ref();
+
+ return { BunStringTag::WTFStringImpl, { .wtf = wtfString } };
+}
+
BunString fromString(WTF::String& wtfString)
{
- if (wtfString.length() == 0)
+ if (wtfString.isEmpty())
return { BunStringTag::Empty };
return { BunStringTag::WTFStringImpl, { .wtf = wtfString.impl() } };
@@ -118,7 +156,7 @@ BunString fromString(WTF::String& wtfString)
BunString fromString(WTF::StringImpl* wtfString)
{
- if (wtfString->length() == 0)
+ if (wtfString->isEmpty())
return { BunStringTag::Empty };
return { BunStringTag::WTFStringImpl, { .wtf = wtfString } };
diff --git a/src/bun.js/bindings/bindings.cpp b/src/bun.js/bindings/bindings.cpp
index 96fcde303..9f9b20c1e 100644
--- a/src/bun.js/bindings/bindings.cpp
+++ b/src/bun.js/bindings/bindings.cpp
@@ -1279,15 +1279,14 @@ JSC__JSValue SystemError__toErrorInstance(const SystemError* arg0,
JSC__JSGlobalObject* globalObject)
{
- static const char* system_error_name = "SystemError";
SystemError err = *arg0;
JSC::VM& vm = globalObject->vm();
auto scope = DECLARE_THROW_SCOPE(vm);
JSC::JSValue message = JSC::jsUndefined();
- if (err.message.len > 0) {
- message = Zig::toJSString(err.message, globalObject);
+ if (err.message.tag != BunStringTag::Empty) {
+ message = Bun::toJS(globalObject, err.message);
}
JSC::JSValue options = JSC::jsUndefined();
@@ -1297,8 +1296,8 @@ JSC__JSValue SystemError__toErrorInstance(const SystemError* arg0,
auto clientData = WebCore::clientData(vm);
- if (err.code.len > 0 && !(err.code.len == 1 and err.code.ptr[0] == 0)) {
- JSC::JSValue code = Zig::toJSStringGC(err.code, globalObject);
+ if (err.code.tag != BunStringTag::Empty) {
+ JSC::JSValue code = Bun::toJS(globalObject, err.code);
result->putDirect(vm, clientData->builtinNames().codePublicName(), code,
JSC::PropertyAttribute::DontDelete | 0);
@@ -1307,13 +1306,12 @@ JSC__JSValue SystemError__toErrorInstance(const SystemError* arg0,
result->putDirect(
vm, vm.propertyNames->name,
- JSC::JSValue(JSC::jsOwnedString(
- vm, WTF::String(WTF::StringImpl::createWithoutCopying(system_error_name, 11)))),
+ JSC::JSValue(jsString(vm, String("SystemError"_s))),
JSC::PropertyAttribute::DontEnum | 0);
}
- if (err.path.len > 0) {
- JSC::JSValue path = JSC::JSValue(Zig::toJSStringGC(err.path, globalObject));
+ if (err.path.tag != BunStringTag::Empty) {
+ JSC::JSValue path = Bun::toJS(globalObject, err.path);
result->putDirect(vm, clientData->builtinNames().pathPublicName(), path,
JSC::PropertyAttribute::DontDelete | 0);
}
@@ -1324,8 +1322,8 @@ JSC__JSValue SystemError__toErrorInstance(const SystemError* arg0,
JSC::PropertyAttribute::DontDelete | 0);
}
- if (err.syscall.len > 0) {
- JSC::JSValue syscall = JSC::JSValue(Zig::toJSString(err.syscall, globalObject));
+ if (err.syscall.tag != BunStringTag::Empty) {
+ JSC::JSValue syscall = Bun::toJS(globalObject, err.syscall);
result->putDirect(vm, clientData->builtinNames().syscallPublicName(), syscall,
JSC::PropertyAttribute::DontDelete | 0);
}
@@ -3303,11 +3301,8 @@ bool JSC__JSValue__stringIncludes(JSC__JSValue value, JSC__JSGlobalObject* globa
static void populateStackFrameMetadata(JSC::VM& vm, const JSC::StackFrame* stackFrame, ZigStackFrame* frame)
{
- String str = stackFrame->sourceURL(vm);
- if (!str.isEmpty())
- str.impl()->ref();
- frame->source_url = Bun::toString(str);
+ frame->source_url = Bun::toStringRef(stackFrame->sourceURL(vm));
if (stackFrame->isWasmFrame()) {
frame->code_type = ZigStackFrameCodeWasm;
@@ -3344,10 +3339,7 @@ static void populateStackFrameMetadata(JSC::VM& vm, const JSC::StackFrame* stack
JSC::JSObject* callee = JSC::jsCast<JSC::JSObject*>(calleeCell);
- String displayName = JSC::getCalculatedDisplayName(vm, callee);
- if (!displayName.isEmpty())
- displayName.impl()->ref();
- frame->function_name = Bun::toString(displayName);
+ frame->function_name = Bun::toStringRef(JSC::getCalculatedDisplayName(vm, callee));
}
// Based on
// https://github.com/mceSystems/node-jsc/blob/master/deps/jscshim/src/shim/JSCStackTrace.cpp#L298
@@ -3421,7 +3413,7 @@ static void populateStackFramePosition(const JSC::StackFrame* stackFrame, BunStr
// Most of the time, when you look at a stack trace, you want a couple lines above
- source_lines[0] = Bun::toString(sourceString.substring(lineStart, lineStop - lineStart).toStringWithoutCopying());
+ source_lines[0] = Bun::toStringRef(sourceString.substring(lineStart, lineStop - lineStart).toStringWithoutCopying());
source_line_numbers[0] = line;
if (lineStart > 0) {
@@ -3438,7 +3430,7 @@ static void populateStackFramePosition(const JSC::StackFrame* stackFrame, BunStr
}
// We are at the beginning of the line
- source_lines[source_line_i] = Bun::toString(sourceString.substring(byte_offset_in_source_string, end_of_line_offset - byte_offset_in_source_string + 1).toStringWithoutCopying());
+ source_lines[source_line_i] = Bun::toStringRef(sourceString.substring(byte_offset_in_source_string, end_of_line_offset - byte_offset_in_source_string + 1).toStringWithoutCopying());
source_line_numbers[source_line_i] = line - source_line_i;
source_line_i++;
@@ -3526,30 +3518,32 @@ static void fromErrorInstance(ZigException* except, JSC::JSGlobalObject* global,
except->code = 8;
}
if (except->code == SYNTAX_ERROR_CODE) {
- except->message = Bun::toString(err->sanitizedMessageString(global));
+ except->message = Bun::toStringRef(err->sanitizedMessageString(global));
} else if (JSC::JSValue message = obj->getIfPropertyExists(global, vm.propertyNames->message)) {
- except->message = Bun::toString(global, message);
+ except->message = Bun::toStringRef(global, message);
} else {
- except->message = Bun::toString(err->sanitizedMessageString(global));
+ except->message = Bun::toStringRef(err->sanitizedMessageString(global));
}
- except->name = Bun::toString(err->sanitizedNameString(global));
+
+ except->name = Bun::toStringRef(err->sanitizedNameString(global));
+
except->runtime_type = err->runtimeTypeForCause();
auto clientData = WebCore::clientData(vm);
if (except->code != SYNTAX_ERROR_CODE) {
if (JSC::JSValue syscall = obj->getIfPropertyExists(global, clientData->builtinNames().syscallPublicName())) {
- except->syscall = Bun::toString(global, syscall);
+ except->syscall = Bun::toStringRef(global, syscall);
}
if (JSC::JSValue code = obj->getIfPropertyExists(global, clientData->builtinNames().codePublicName())) {
- except->code_ = Bun::toString(global, code);
+ except->code_ = Bun::toStringRef(global, code);
}
if (JSC::JSValue path = obj->getIfPropertyExists(global, clientData->builtinNames().pathPublicName())) {
- except->path = Bun::toString(global, path);
+ except->path = Bun::toStringRef(global, path);
}
if (JSC::JSValue fd = obj->getIfPropertyExists(global, Identifier::fromString(vm, "fd"_s))) {
@@ -3565,7 +3559,7 @@ static void fromErrorInstance(ZigException* except, JSC::JSGlobalObject* global,
if (getFromSourceURL) {
if (JSC::JSValue sourceURL = obj->getIfPropertyExists(global, vm.propertyNames->sourceURL)) {
- except->stack.frames_ptr[0].source_url = Bun::toString(global, sourceURL);
+ except->stack.frames_ptr[0].source_url = Bun::toStringRef(global, sourceURL);
if (JSC::JSValue column = obj->getIfPropertyExists(global, vm.propertyNames->column)) {
except->stack.frames_ptr[0].position.column_start = column.toInt32(global);
@@ -3577,7 +3571,7 @@ static void fromErrorInstance(ZigException* except, JSC::JSGlobalObject* global,
if (JSC::JSValue lineText = obj->getIfPropertyExists(global, JSC::Identifier::fromString(vm, "lineText"_s))) {
if (JSC::JSString* jsStr = lineText.toStringOrNull(global)) {
auto str = jsStr->value(global);
- except->stack.source_lines_ptr[0] = Bun::toString(str);
+ except->stack.source_lines_ptr[0] = Bun::toStringRef(str);
except->stack.source_lines_numbers[0] = except->stack.frames_ptr[0].position.line;
except->stack.source_lines_len = 1;
except->remapped = true;
@@ -3600,7 +3594,7 @@ void exceptionFromString(ZigException* except, JSC::JSValue value, JSC::JSGlobal
if (JSC::JSObject* obj = JSC::jsDynamicCast<JSC::JSObject*>(value)) {
if (obj->hasProperty(global, global->vm().propertyNames->name)) {
auto name_str = obj->getIfPropertyExists(global, global->vm().propertyNames->name).toWTFString(global);
- except->name = Bun::toString(name_str);
+ except->name = Bun::toStringRef(name_str);
if (name_str == "Error"_s) {
except->code = JSErrorCodeError;
} else if (name_str == "EvalError"_s) {
@@ -3622,14 +3616,14 @@ void exceptionFromString(ZigException* except, JSC::JSValue value, JSC::JSGlobal
if (JSC::JSValue message = obj->getIfPropertyExists(global, global->vm().propertyNames->message)) {
if (message) {
- except->message = Bun::toString(
+ except->message = Bun::toStringRef(
message.toWTFString(global));
}
}
if (JSC::JSValue sourceURL = obj->getIfPropertyExists(global, global->vm().propertyNames->sourceURL)) {
if (sourceURL) {
- except->stack.frames_ptr[0].source_url = Bun::toString(
+ except->stack.frames_ptr[0].source_url = Bun::toStringRef(
sourceURL.toWTFString(global));
except->stack.frames_len = 1;
}
@@ -3658,7 +3652,7 @@ void exceptionFromString(ZigException* except, JSC::JSValue value, JSC::JSGlobal
}
scope.release();
- except->message = Bun::toString(str);
+ except->message = Bun::toStringRef(str);
}
void JSC__VM__releaseWeakRefs(JSC__VM* arg0)
@@ -3768,8 +3762,8 @@ void JSC__JSValue__toZigException(JSC__JSValue JSValue0, JSC__JSGlobalObject* ar
JSC::JSValue value = JSC::JSValue::decode(JSValue0);
if (value == JSC::JSValue {}) {
exception->code = JSErrorCodeError;
- exception->name = Bun::toString("Error"_s);
- exception->message = Bun::toString("Unknown error"_s);
+ exception->name = Bun::toStringRef("Error"_s);
+ exception->message = Bun::toStringRef("Unknown error"_s);
return;
}
diff --git a/src/bun.js/bindings/bindings.zig b/src/bun.js/bindings/bindings.zig
index 1c09378a8..777860d3c 100644
--- a/src/bun.js/bindings/bindings.zig
+++ b/src/bun.js/bindings/bindings.zig
@@ -1561,10 +1561,10 @@ pub const FetchHeaders = opaque {
pub const SystemError = extern struct {
errno: c_int = 0,
/// label for errno
- code: ZigString = ZigString.init(""),
- message: ZigString = ZigString.init(""),
- path: ZigString = ZigString.init(""),
- syscall: ZigString = ZigString.init(""),
+ code: String = String.empty,
+ message: String = String.empty,
+ path: String = String.empty,
+ syscall: String = String.empty,
fd: i32 = -1,
pub fn Maybe(comptime Result: type) type {
diff --git a/src/bun.js/bindings/headers-handwritten.h b/src/bun.js/bindings/headers-handwritten.h
index c7429b633..90c8f86d2 100644
--- a/src/bun.js/bindings/headers-handwritten.h
+++ b/src/bun.js/bindings/headers-handwritten.h
@@ -84,10 +84,10 @@ typedef struct ErrorableResolvedSource {
typedef struct SystemError {
int errno_;
- ZigString code;
- ZigString message;
- ZigString path;
- ZigString syscall;
+ BunString code;
+ BunString message;
+ BunString path;
+ BunString syscall;
int fd;
} SystemError;
@@ -246,6 +246,10 @@ BunString toString(WTF::String& wtfString);
BunString toString(const WTF::String& wtfString);
BunString toString(WTF::StringImpl* wtfString);
+BunString toStringRef(JSC::JSGlobalObject* globalObject, JSC::JSValue value);
+BunString toStringRef(WTF::String& wtfString);
+BunString toStringRef(const WTF::String& wtfString);
+BunString toStringRef(WTF::StringImpl* wtfString);
}
using Uint8Array_alias = JSC::JSUint8Array;
diff --git a/src/bun.js/bindings/helpers.h b/src/bun.js/bindings/helpers.h
index 402807f3d..00777c304 100644
--- a/src/bun.js/bindings/helpers.h
+++ b/src/bun.js/bindings/helpers.h
@@ -342,10 +342,10 @@ static const WTF::String toStringStatic(ZigString str)
}
if (isTaggedUTF16Ptr(str.ptr)) {
- return WTF::String(WTF::ExternalStringImpl::createStatic(reinterpret_cast<const UChar*>(untag(str.ptr)), str.len));
+ return WTF::String(AtomStringImpl::add(reinterpret_cast<const UChar*>(untag(str.ptr)), str.len));
}
- return WTF::String(WTF::ExternalStringImpl::createStatic(
+ return WTF::String(AtomStringImpl::add(
reinterpret_cast<const LChar*>(untag(str.ptr)), str.len));
}
diff --git a/src/bun.js/bindings/napi.cpp b/src/bun.js/bindings/napi.cpp
index a859e3ac5..bb62cb2a0 100644
--- a/src/bun.js/bindings/napi.cpp
+++ b/src/bun.js/bindings/napi.cpp
@@ -554,7 +554,6 @@ extern "C" napi_status napi_wrap(napi_env env,
auto* globalObject = toJS(env);
auto& vm = globalObject->vm();
-
auto* val = jsDynamicCast<NapiPrototype*>(value);
@@ -572,7 +571,7 @@ extern "C" napi_status napi_wrap(napi_env env,
auto clientData = WebCore::clientData(vm);
auto* ref = new NapiRef(globalObject, 1);
- ref->strongRef.set(globalObject->vm(), value.getObject());
+ ref->strongRef.set(globalObject->vm(), value.getObject());
if (finalize_cb) {
ref->finalizer.finalize_cb = finalize_cb;
@@ -816,7 +815,7 @@ extern "C" napi_status napi_create_reference(napi_env env, napi_value value,
}
}
- if(object) {
+ if (object) {
object->napiRef = ref;
}
@@ -1029,7 +1028,26 @@ extern "C" napi_status napi_create_type_error(napi_env env, napi_value code,
auto error = JSC::createTypeError(globalObject, messageValue.toWTFString(globalObject));
if (codeValue) {
- error->putDirect(vm, Identifier::fromString(vm, "code"_s), codeValue, 0);
+ error->putDirect(vm, WebCore::builtinNames(vm).codePublicName(), codeValue, 0);
+ }
+
+ *result = reinterpret_cast<napi_value>(JSC::JSValue::encode(error));
+ return napi_ok;
+}
+
+extern "C" napi_status napi_create_error(napi_env env, napi_value code,
+ napi_value msg,
+ napi_value* result)
+{
+ Zig::GlobalObject* globalObject = toJS(env);
+ JSC::VM& vm = globalObject->vm();
+
+ JSC::JSValue codeValue = JSC::JSValue::decode(reinterpret_cast<JSC::EncodedJSValue>(code));
+ JSC::JSValue messageValue = JSC::JSValue::decode(reinterpret_cast<JSC::EncodedJSValue>(msg));
+
+ auto error = JSC::createError(globalObject, messageValue.toWTFString(globalObject));
+ if (codeValue) {
+ error->putDirect(vm, WebCore::builtinNames(vm).codePublicName(), codeValue, 0);
}
*result = reinterpret_cast<napi_value>(JSC::JSValue::encode(error));
@@ -1474,7 +1492,8 @@ extern "C" napi_status napi_get_property_names(napi_env env, napi_value object,
return napi_ok;
}
-extern "C" napi_status napi_create_object(napi_env env, napi_value* result){
+extern "C" napi_status napi_create_object(napi_env env, napi_value* result)
+{
if (UNLIKELY(result == nullptr)) {
return napi_invalid_arg;
diff --git a/src/bun.js/bindings/webcore/JSCloseEvent.cpp b/src/bun.js/bindings/webcore/JSCloseEvent.cpp
index be07cbcfe..ad7b6ed57 100644
--- a/src/bun.js/bindings/webcore/JSCloseEvent.cpp
+++ b/src/bun.js/bindings/webcore/JSCloseEvent.cpp
@@ -99,7 +99,7 @@ template<> CloseEvent::Init convertDictionary<CloseEvent::Init>(JSGlobalObject&
if (isNullOrUndefined)
codeValue = jsUndefined();
else {
- codeValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "code"_s));
+ codeValue = object->get(&lexicalGlobalObject, WebCore::builtinNames(vm).codePublicName());
RETURN_IF_EXCEPTION(throwScope, {});
}
if (!codeValue.isUndefined()) {
diff --git a/src/bun.js/node/node_os.zig b/src/bun.js/node/node_os.zig
index f71143315..483acb3e2 100644
--- a/src/bun.js/node/node_os.zig
+++ b/src/bun.js/node/node_os.zig
@@ -78,8 +78,8 @@ pub const Os = struct {
return if (comptime Environment.isLinux)
cpusImplLinux(globalThis) catch {
const err = JSC.SystemError{
- .message = JSC.ZigString.init("Failed to get cpu information"),
- .code = JSC.ZigString.init(@as(string, @tagName(JSC.Node.ErrorCode.ERR_SYSTEM_ERROR))),
+ .message = bun.String.static("Failed to get cpu information"),
+ .code = bun.String.static(@as(string, @tagName(JSC.Node.ErrorCode.ERR_SYSTEM_ERROR))),
};
globalThis.vm().throwError(globalThis, err.toErrorInstance(globalThis));
@@ -88,8 +88,8 @@ pub const Os = struct {
else if (comptime Environment.isMac)
cpusImplDarwin(globalThis) catch {
const err = JSC.SystemError{
- .message = JSC.ZigString.init("Failed to get cpu information"),
- .code = JSC.ZigString.init(@as(string, @tagName(JSC.Node.ErrorCode.ERR_SYSTEM_ERROR))),
+ .message = bun.String.static("Failed to get cpu information"),
+ .code = bun.String.static(@as(string, @tagName(JSC.Node.ErrorCode.ERR_SYSTEM_ERROR))),
};
globalThis.vm().throwError(globalThis, err.toErrorInstance(globalThis));
@@ -318,11 +318,11 @@ pub const Os = struct {
//info.put(globalThis, JSC.ZigString.static("syscall"), JSC.ZigString.init("uv_os_getpriority").withEncoding().toValueGC(globalThis));
const err = JSC.SystemError{
- .message = JSC.ZigString.init("A system error occurred: uv_os_getpriority returned ESRCH (no such process)"),
- .code = JSC.ZigString.init(@as(string, @tagName(JSC.Node.ErrorCode.ERR_SYSTEM_ERROR))),
+ .message = bun.String.static("A system error occurred: uv_os_getpriority returned ESRCH (no such process)"),
+ .code = bun.String.static(@as(string, @tagName(JSC.Node.ErrorCode.ERR_SYSTEM_ERROR))),
//.info = info,
.errno = -3,
- .syscall = JSC.ZigString.init("uv_os_getpriority"),
+ .syscall = bun.String.static("uv_os_getpriority"),
};
globalThis.vm().throwError(globalThis, err.toErrorInstance(globalThis));
@@ -377,10 +377,10 @@ pub const Os = struct {
const rc = C.getifaddrs(&interface_start);
if (rc != 0) {
const err = JSC.SystemError{
- .message = JSC.ZigString.init("A system error occurred: getifaddrs returned an error"),
- .code = JSC.ZigString.init(@as(string, @tagName(JSC.Node.ErrorCode.ERR_SYSTEM_ERROR))),
+ .message = bun.String.static("A system error occurred: getifaddrs returned an error"),
+ .code = bun.String.static(@as(string, @tagName(JSC.Node.ErrorCode.ERR_SYSTEM_ERROR))),
.errno = @intFromEnum(std.os.errno(rc)),
- .syscall = JSC.ZigString.init("getifaddrs"),
+ .syscall = bun.String.static("getifaddrs"),
};
globalThis.vm().throwError(globalThis, err.toErrorInstance(globalThis));
@@ -591,11 +591,11 @@ pub const Os = struct {
switch (errcode) {
.SRCH => {
const err = JSC.SystemError{
- .message = JSC.ZigString.init("A system error occurred: uv_os_setpriority returned ESRCH (no such process)"),
- .code = JSC.ZigString.init(@as(string, @tagName(JSC.Node.ErrorCode.ERR_SYSTEM_ERROR))),
+ .message = bun.String.static("A system error occurred: uv_os_setpriority returned ESRCH (no such process)"),
+ .code = bun.String.static(@as(string, @tagName(JSC.Node.ErrorCode.ERR_SYSTEM_ERROR))),
//.info = info,
.errno = -3,
- .syscall = JSC.ZigString.init("uv_os_setpriority"),
+ .syscall = bun.String.static("uv_os_setpriority"),
};
globalThis.vm().throwError(globalThis, err.toErrorInstance(globalThis));
@@ -603,11 +603,11 @@ pub const Os = struct {
},
.ACCES => {
const err = JSC.SystemError{
- .message = JSC.ZigString.init("A system error occurred: uv_os_setpriority returned EACCESS (permission denied)"),
- .code = JSC.ZigString.init(@as(string, @tagName(JSC.Node.ErrorCode.ERR_SYSTEM_ERROR))),
+ .message = bun.String.static("A system error occurred: uv_os_setpriority returned EACCESS (permission denied)"),
+ .code = bun.String.static(@as(string, @tagName(JSC.Node.ErrorCode.ERR_SYSTEM_ERROR))),
//.info = info,
.errno = -13,
- .syscall = JSC.ZigString.init("uv_os_setpriority"),
+ .syscall = bun.String.static("uv_os_setpriority"),
};
globalThis.vm().throwError(globalThis, err.toErrorInstance(globalThis));
diff --git a/src/bun.js/node/syscall.zig b/src/bun.js/node/syscall.zig
index 48c5b1305..5ff0b2f44 100644
--- a/src/bun.js/node/syscall.zig
+++ b/src/bun.js/node/syscall.zig
@@ -873,20 +873,20 @@ pub const Error = struct {
pub fn toSystemError(this: Error) SystemError {
var err = SystemError{
.errno = @as(c_int, this.errno) * -1,
- .syscall = JSC.ZigString.init(@tagName(this.syscall)),
+ .syscall = bun.String.static(@tagName(this.syscall)),
};
// errno label
if (this.errno > 0 and this.errno < C.SystemErrno.max) {
const system_errno = @enumFromInt(C.SystemErrno, this.errno);
- err.code = JSC.ZigString.init(@tagName(system_errno));
+ err.code = bun.String.static(@tagName(system_errno));
if (C.SystemErrno.labels.get(system_errno)) |label| {
- err.message = JSC.ZigString.init(label);
+ err.message = bun.String.static(label);
}
}
if (this.path.len > 0) {
- err.path = JSC.ZigString.init(this.path);
+ err.path = bun.String.create(this.path);
}
if (this.fd != -1) {
diff --git a/src/bun.js/webcore/blob.zig b/src/bun.js/webcore/blob.zig
index faf503a3f..86b5414e3 100644
--- a/src/bun.js/webcore/blob.zig
+++ b/src/bun.js/webcore/blob.zig
@@ -1194,9 +1194,6 @@ pub const Blob = struct {
.syscall = .open,
}).toSystemError();
- // assert we never end up reusing the memory
- std.debug.assert(@intFromPtr(this.system_error.?.path.slice().ptr) != @intFromPtr(path_buffer));
-
callback(this, null_fd);
return;
};
@@ -1359,12 +1356,13 @@ pub const Blob = struct {
return;
} else if (this.store == null) {
bun.default_allocator.destroy(this);
- cb(cb_ctx, ResultType{ .err = SystemError{
- .code = ZigString.init("INTERNAL_ERROR"),
- .path = ZigString.Empty,
- .message = ZigString.init("assertion failure - store should not be null"),
- .syscall = ZigString.init("read"),
- } });
+ cb(cb_ctx, ResultType{
+ .err = SystemError{
+ .code = bun.String.static("INTERNAL_ERROR"),
+ .message = bun.String.static("assertion failure - store should not be null"),
+ .syscall = bun.String.static("read"),
+ },
+ });
return;
}
@@ -1396,12 +1394,12 @@ pub const Blob = struct {
}).toSystemError();
} else {
this.system_error = JSC.SystemError{
- .code = ZigString.init(bun.asByteSlice(@errorName(err))),
+ .code = bun.String.static(bun.asByteSlice(@errorName(err))),
.path = if (this.file_store.pathlike == .path)
- ZigString.init(this.file_store.pathlike.path.slice())
+ bun.String.create(this.file_store.pathlike.path.slice())
else
- ZigString.Empty,
- .syscall = ZigString.init("read"),
+ bun.String.empty,
+ .syscall = bun.String.static("read"),
};
this.errno = err;
@@ -1458,13 +1456,13 @@ pub const Blob = struct {
if (std.os.S.ISDIR(stat.mode)) {
this.errno = error.EISDIR;
this.system_error = JSC.SystemError{
- .code = ZigString.init("EISDIR"),
+ .code = bun.String.static("EISDIR"),
.path = if (this.file_store.pathlike == .path)
- ZigString.init(this.file_store.pathlike.path.slice())
+ bun.String.create(this.file_store.pathlike.path.slice())
else
- ZigString.Empty,
- .message = ZigString.init("Directories cannot be read like files"),
- .syscall = ZigString.init("read"),
+ bun.String.empty,
+ .message = bun.String.static("Directories cannot be read like files"),
+ .syscall = bun.String.static("read"),
};
return;
}
@@ -1643,8 +1641,8 @@ pub const Blob = struct {
this.wrote += @truncate(SizeType, result catch |errno| {
this.errno = errno;
this.system_error = this.system_error orelse JSC.SystemError{
- .code = ZigString.init(bun.asByteSlice(@errorName(errno))),
- .syscall = ZigString.init("write"),
+ .code = bun.String.static(bun.asByteSlice(@errorName(errno))),
+ .syscall = bun.String.static("write"),
};
this.wrote = 0;
@@ -1703,13 +1701,13 @@ pub const Blob = struct {
const unsupported_directory_error = SystemError{
.errno = @intCast(c_int, @intFromEnum(bun.C.SystemErrno.EISDIR)),
- .message = ZigString.init("That doesn't work on folders"),
- .syscall = ZigString.init("fstat"),
+ .message = bun.String.static("That doesn't work on folders"),
+ .syscall = bun.String.static("fstat"),
};
const unsupported_non_regular_file_error = SystemError{
.errno = @intCast(c_int, @intFromEnum(bun.C.SystemErrno.ENOTSUP)),
- .message = ZigString.init("Non-regular files aren't supported yet"),
- .syscall = ZigString.init("fstat"),
+ .message = bun.String.static("Non-regular files aren't supported yet"),
+ .syscall = bun.String.static("fstat"),
};
// blocking, but off the main thread
@@ -1777,13 +1775,12 @@ pub const Blob = struct {
pub fn reject(this: *CopyFile, promise: *JSC.JSPromise) void {
var globalThis = this.globalThis;
var system_error: SystemError = this.system_error orelse SystemError{};
- if (this.source_file_store.pathlike == .path and system_error.path.len == 0) {
- system_error.path = ZigString.init(this.source_file_store.pathlike.path.slice());
- system_error.path.mark();
+ if (this.source_file_store.pathlike == .path and system_error.path.isEmpty()) {
+ system_error.path = bun.String.create(this.source_file_store.pathlike.path.slice());
}
- if (system_error.message.len == 0) {
- system_error.message = ZigString.init("Failed to copy file");
+ if (system_error.message.isEmpty()) {
+ system_error.message = bun.String.static("Failed to copy file");
}
var instance = system_error.toErrorInstance(this.globalThis);
diff --git a/src/bun.js/webcore/response.zig b/src/bun.js/webcore/response.zig
index b4ea08579..e888ffa5a 100644
--- a/src/bun.js/webcore/response.zig
+++ b/src/bun.js/webcore/response.zig
@@ -777,15 +777,15 @@ pub const Fetch = struct {
}
const fetch_error = JSC.SystemError{
- .code = ZigString.init(@errorName(this.result.fail)),
+ .code = bun.String.static(@errorName(this.result.fail)),
.message = switch (this.result.fail) {
- error.ConnectionClosed => ZigString.init("The socket connection was closed unexpectedly. For more information, pass `verbose: true` in the second argument to fetch()"),
- error.FailedToOpenSocket => ZigString.init("Was there a typo in the url or port?"),
- error.TooManyRedirects => ZigString.init("The response redirected too many times. For more information, pass `verbose: true` in the second argument to fetch()"),
- error.ConnectionRefused => ZigString.init("Unable to connect. Is the computer able to access the url?"),
- else => ZigString.init("fetch() failed. For more information, pass `verbose: true` in the second argument to fetch()"),
+ error.ConnectionClosed => bun.String.static("The socket connection was closed unexpectedly. For more information, pass `verbose: true` in the second argument to fetch()"),
+ error.FailedToOpenSocket => bun.String.static("Was there a typo in the url or port?"),
+ error.TooManyRedirects => bun.String.static("The response redirected too many times. For more information, pass `verbose: true` in the second argument to fetch()"),
+ error.ConnectionRefused => bun.String.static("Unable to connect. Is the computer able to access the url?"),
+ else => bun.String.static("fetch() failed. For more information, pass `verbose: true` in the second argument to fetch()"),
},
- .path = ZigString.init(this.http.?.url.href),
+ .path = bun.String.create(this.http.?.url.href),
};
return fetch_error.toErrorInstance(this.global_this);
diff --git a/src/bun.js/webcore/streams.zig b/src/bun.js/webcore/streams.zig
index 5986afac7..343ce37ab 100644
--- a/src/bun.js/webcore/streams.zig
+++ b/src/bun.js/webcore/streams.zig
@@ -1964,10 +1964,10 @@ pub fn NewJSSink(comptime SinkType: type, comptime name_: []const u8) type {
pub const message = std.fmt.comptimePrint("{s} is not constructable", .{SinkType.name});
};
const err = JSC.SystemError{
- .message = ZigString.init(Static.message),
- .code = ZigString.init(@as(string, @tagName(JSC.Node.ErrorCode.ERR_ILLEGAL_CONSTRUCTOR))),
+ .message = bun.String.static(Static.message),
+ .code = bun.String.static(@as(string, @tagName(JSC.Node.ErrorCode.ERR_ILLEGAL_CONSTRUCTOR))),
};
- globalThis.vm().throwError(globalThis, err.toErrorInstance(globalThis));
+ globalThis.throwValue(err.toErrorInstance(globalThis));
return JSC.JSValue.jsUndefined();
}
diff --git a/src/bundler/bundle_v2.zig b/src/bundler/bundle_v2.zig
index 814e49a20..f534e4184 100644
--- a/src/bundler/bundle_v2.zig
+++ b/src/bundler/bundle_v2.zig
@@ -9174,8 +9174,10 @@ const LinkerContext = struct {
},
)) {
.err => |err| {
+ var message = err.toSystemError().message.toUTF8(bun.default_allocator);
+ defer message.deinit();
c.log.addErrorFmt(null, Logger.Loc.Empty, bun.default_allocator, "{} writing sourcemap for chunk {}", .{
- bun.fmt.quote(err.toSystemError().message.slice()),
+ bun.fmt.quote(message.slice()),
bun.fmt.quote(chunk.final_rel_path),
}) catch unreachable;
return error.WriteFailed;
@@ -9242,8 +9244,10 @@ const LinkerContext = struct {
},
)) {
.err => |err| {
+ var message = err.toSystemError().message.toUTF8(bun.default_allocator);
+ defer message.deinit();
c.log.addErrorFmt(null, Logger.Loc.Empty, bun.default_allocator, "{} writing chunk {}", .{
- bun.fmt.quote(err.toSystemError().message.slice()),
+ bun.fmt.quote(message.slice()),
bun.fmt.quote(chunk.final_rel_path),
}) catch unreachable;
return error.WriteFailed;
@@ -9309,8 +9313,10 @@ const LinkerContext = struct {
},
)) {
.err => |err| {
+ const utf8 = err.toSystemError().message.toUTF8(bun.default_allocator);
+ defer utf8.deinit();
c.log.addErrorFmt(null, Logger.Loc.Empty, bun.default_allocator, "{} writing chunk {}", .{
- bun.fmt.quote(err.toSystemError().message.slice()),
+ bun.fmt.quote(utf8.slice()),
bun.fmt.quote(components_manifest_path),
}) catch unreachable;
return error.WriteFailed;
@@ -9383,8 +9389,10 @@ const LinkerContext = struct {
},
)) {
.err => |err| {
+ const utf8 = err.toSystemError().message.toUTF8(bun.default_allocator);
+ defer utf8.deinit();
c.log.addErrorFmt(null, Logger.Loc.Empty, bun.default_allocator, "{} writing file {}", .{
- bun.fmt.quote(err.toSystemError().message.slice()),
+ bun.fmt.quote(utf8.slice()),
bun.fmt.quote(src.src_path.text),
}) catch unreachable;
return error.WriteFailed;
diff --git a/src/http.zig b/src/http.zig
index 80718db2f..b1d97c382 100644
--- a/src/http.zig
+++ b/src/http.zig
@@ -684,8 +684,9 @@ pub const RequestContext = struct {
if (erro == error.EBADF or erro == error.ECONNABORTED or erro == error.ECONNREFUSED) {
return error.SocketClosed;
}
-
- Output.prettyErrorln("send() error: {s}", .{err.toSystemError().message.slice()});
+ const msg = err.toSystemError().message.toUTF8(bun.default_allocator);
+ defer msg.deinit();
+ Output.prettyErrorln("send() error: {s}", .{msg.slice()});
return erro;
},
diff --git a/src/napi/napi.zig b/src/napi/napi.zig
index 0973ca559..439319489 100644
--- a/src/napi/napi.zig
+++ b/src/napi/napi.zig
@@ -303,16 +303,7 @@ pub export fn napi_create_string_utf16(env: napi_env, str: [*]const char16_t, le
return .ok;
}
pub extern fn napi_create_symbol(env: napi_env, description: napi_value, result: *napi_value) napi_status;
-pub export fn napi_create_error(env: napi_env, code: napi_value, msg: napi_value, result: *napi_value) napi_status {
- log("napi_create_error: \"{any}\"", .{msg.getZigString(env)});
- const system_error = JSC.SystemError{
- .code = if (!code.isEmptyOrUndefinedOrNull()) code.getZigString(env) else ZigString.Empty,
- .message = msg.getZigString(env),
- };
- result.* = system_error.toErrorInstance(env);
- return .ok;
-}
-
+pub extern fn napi_create_error(env: napi_env, code: napi_value, msg: napi_value, result: *napi_value) napi_status;
pub extern fn napi_create_type_error(env: napi_env, code: napi_value, msg: napi_value, result: *napi_value) napi_status;
pub extern fn napi_create_range_error(env: napi_env, code: napi_value, msg: napi_value, result: *napi_value) napi_status;
pub extern fn napi_typeof(env: napi_env, value: napi_value, result: *napi_valuetype) napi_status;
diff --git a/test/js/bun/util/error-gc-test.test.js b/test/js/bun/util/error-gc-test.test.js
index 247bd68ef..4a45346b6 100644
--- a/test/js/bun/util/error-gc-test.test.js
+++ b/test/js/bun/util/error-gc-test.test.js
@@ -1,5 +1,5 @@
import { test, expect } from "bun:test";
-
+import { readFileSync } from "fs";
// This test checks that printing stack traces increments and decrements
// reference-counted strings
test("error gc test", () => {
@@ -34,7 +34,7 @@ test("error gc test #2", () => {
}
});
-test("error gc test #2", () => {
+test("error gc test #3", () => {
for (let i = 0; i < 1000; i++) {
var err = new Error();
Error.captureStackTrace(err);
@@ -42,3 +42,40 @@ test("error gc test #2", () => {
Bun.gc();
}
});
+
+// This test fails if:
+// - it crashes
+// - The test failure message gets a non-sensical error
+test("error gc test #4", () => {
+ for (let i = 0; i < 1000; i++) {
+ let path =
+ // Use a long-enough string for it to be obvious if we leak memory
+ "/i/don/t/exist/tmp/i/don/t/exist/tmp/i/don/t/exist/tmp/i/don/t/exist/tmp/i/don/t/exist/tmp/i/don/t/exist/tmp/i/don/t/exist/tmp/ii/don/t/exist/tmp/i/don/t/exist/tmp/i/don/t/exist/tmp/i/don/t/exist/tmp/i/don/t/exist/tmp/i/don/t/exist/tmp/i/don/t/exist/tmp/ii/don/t/exist/tmp/i/don/t/exist/tmp/i/don/t/exist/tmp/i/don/t/exist/tmp/i/don/t/exist/tmp/i/don/t/exist/tmp/i/don/t/exist/tmp/i";
+ try {
+ readFileSync(path);
+ throw new Error("unreachable");
+ } catch (e) {
+ if (e.message === "unreachable") {
+ throw e;
+ }
+
+ const inspected = Bun.inspect(e);
+ Bun.gc(true);
+
+ // Deliberately avoid using .toContain() directly to avoid
+ // BunString shenanigins.
+ //
+ // Only JSC builtin functions to operate on the string after inspecting it.
+ //
+ if (!inspected.includes(path)) {
+ expect(inspected).toContain(path);
+ }
+
+ if (!inspected.includes("ENOENT")) {
+ expect(inspected).toContain("ENOENT");
+ }
+ } finally {
+ Bun.gc(true);
+ }
+ }
+});