diff --git a/.cursor/rules/javascriptcore-class.mdc b/.cursor/rules/javascriptcore-class.mdc index e8eab9f0f9..0e1507223f 100644 --- a/.cursor/rules/javascriptcore-class.mdc +++ b/.cursor/rules/javascriptcore-class.mdc @@ -360,9 +360,8 @@ JSC_DEFINE_HOST_FUNCTION(x509CertificateConstructorConstruct, (JSGlobalObject * auto* functionGlobalObject = defaultGlobalObject(getFunctionRealm(globalObject, newTarget.getObject())); RETURN_IF_EXCEPTION(scope, {}); - structure = InternalFunction::createSubclassStructure( - globalObject, newTarget.getObject(), functionGlobalObject->NodeVMScriptStructure()); - scope.release(); + structure = InternalFunction::createSubclassStructure(globalObject, newTarget.getObject(), functionGlobalObject->NodeVMScriptStructure()); + RETURN_IF_EXCEPTION(scope, {}); } return JSValue::encode(createX509Certificate(vm, globalObject, structure, arg)); diff --git a/src/bake/BakeSourceProvider.cpp b/src/bake/BakeSourceProvider.cpp index 15d17d28ba..2a70ceae05 100644 --- a/src/bake/BakeSourceProvider.cpp +++ b/src/bake/BakeSourceProvider.cpp @@ -49,7 +49,7 @@ extern "C" JSC::EncodedJSValue BakeLoadInitialServerCode(GlobalObject* global, B args.append(JSC::jsBoolean(separateSSRGraph)); // separateSSRGraph args.append(Zig::ImportMetaObject::create(global, "bake://server-runtime.js"_s)); // importMeta - return JSC::JSValue::encode(JSC::profiledCall(global, JSC::ProfilingReason::API, fn, callData, JSC::jsUndefined(), args)); + RELEASE_AND_RETURN(scope, JSC::JSValue::encode(JSC::profiledCall(global, JSC::ProfilingReason::API, fn, callData, JSC::jsUndefined(), args))); } extern "C" JSC::JSInternalPromise* BakeLoadModuleByKey(GlobalObject* global, JSC::JSString* key) { diff --git a/src/bake/DevServer.zig b/src/bake/DevServer.zig index 8167f28e8d..a500437dcb 100644 --- a/src/bake/DevServer.zig +++ b/src/bake/DevServer.zig @@ -6595,19 +6595,14 @@ const c = struct { // BakeSourceProvider.cpp extern fn BakeGetDefaultExportFromModule(global: *JSC.JSGlobalObject, module: JSValue) JSValue; - fn BakeLoadServerHmrPatch(global: *JSC.JSGlobalObject, code: bun.String) !JSValue { - const f = @extern( - *const fn (*JSC.JSGlobalObject, bun.String) callconv(.c) JSValue.MaybeException, - .{ .name = "BakeLoadServerHmrPatch" }, - ); - return f(global, code).unwrap(); + fn BakeLoadServerHmrPatch(global: *JSC.JSGlobalObject, code: bun.String) bun.JSError!JSValue { + const f = @extern(*const fn (*JSC.JSGlobalObject, bun.String) callconv(.c) JSValue, .{ .name = "BakeLoadServerHmrPatch" }).*; + return bun.jsc.fromJSHostCall(global, @src(), f, .{ global, code }); } fn BakeLoadInitialServerCode(global: *JSC.JSGlobalObject, code: bun.String, separate_ssr_graph: bool) bun.JSError!JSValue { - const f = @extern(*const fn (*JSC.JSGlobalObject, bun.String, bool) callconv(.c) JSValue.MaybeException, .{ - .name = "BakeLoadInitialServerCode", - }); - return f(global, code, separate_ssr_graph).unwrap(); + const f = @extern(*const fn (*JSC.JSGlobalObject, bun.String, bool) callconv(.c) JSValue, .{ .name = "BakeLoadInitialServerCode" }).*; + return bun.jsc.fromJSHostCall(global, @src(), f, .{ global, code, separate_ssr_graph }); } }; diff --git a/src/bake/FrameworkRouter.zig b/src/bake/FrameworkRouter.zig index 4b42240dbc..097b8b729f 100644 --- a/src/bake/FrameworkRouter.zig +++ b/src/bake/FrameworkRouter.zig @@ -1176,10 +1176,7 @@ pub const JSFrameworkRouter = struct { }), ); } - return global.throwValue(global.createAggregateErrorWithArray( - bun.String.static("Errors scanning routes"), - arr, - )); + return global.throwValue(try global.createAggregateErrorWithArray(.static("Errors scanning routes"), arr)); } return jsfr; diff --git a/src/bun.js/ConsoleObject.zig b/src/bun.js/ConsoleObject.zig index 0db081579a..44c63b0b42 100644 --- a/src/bun.js/ConsoleObject.zig +++ b/src/bun.js/ConsoleObject.zig @@ -554,7 +554,7 @@ pub const TablePrinter = struct { { if (this.is_iterable) { var ctx_: struct { this: *TablePrinter, columns: *@TypeOf(columns), idx: u32 = 0, err: bool = false } = .{ .this = this, .columns = &columns }; - this.tabular_data.forEachWithContext(globalObject, &ctx_, struct { + try this.tabular_data.forEachWithContext(globalObject, &ctx_, struct { fn callback(_: *JSC.VM, _: *JSGlobalObject, ctx: *@TypeOf(ctx_), value: JSValue) callconv(.C) void { updateColumnsForRow(ctx.this, ctx.columns, .{ .num = ctx.idx }, value) catch { ctx.err = true; @@ -628,7 +628,7 @@ pub const TablePrinter = struct { { if (this.is_iterable) { var ctx_: struct { this: *TablePrinter, columns: *@TypeOf(columns), writer: Writer, idx: u32 = 0, err: bool = false } = .{ .this = this, .columns = &columns, .writer = writer }; - this.tabular_data.forEachWithContext(globalObject, &ctx_, struct { + try this.tabular_data.forEachWithContext(globalObject, &ctx_, struct { fn callback(_: *JSC.VM, _: *JSGlobalObject, ctx: *@TypeOf(ctx_), value: JSValue) callconv(.C) void { printRow(ctx.this, Writer, ctx.writer, enable_ansi_colors, ctx.columns, .{ .num = ctx.idx }, value) catch { ctx.err = true; @@ -1882,7 +1882,7 @@ pub const Formatter = struct { always_newline: bool = false, parent: JSValue, const enable_ansi_colors = enable_ansi_colors_; - pub fn handleFirstProperty(this: *@This(), globalThis: *JSC.JSGlobalObject, value: JSValue) void { + pub fn handleFirstProperty(this: *@This(), globalThis: *JSC.JSGlobalObject, value: JSValue) bun.JSError!void { if (value.isCell() and !value.jsType().isFunction()) { var writer = WrappedWriter(Writer){ .ctx = this.writer, @@ -1890,7 +1890,7 @@ pub const Formatter = struct { .estimated_line_length = &this.formatter.estimated_line_length, }; - if (getObjectName(globalThis, value)) |name_str| { + if (try getObjectName(globalThis, value)) |name_str| { writer.print("{} ", .{name_str}); } } @@ -1936,7 +1936,7 @@ pub const Formatter = struct { if (tag.cell.isHidden()) return; if (ctx.i == 0) { - handleFirstProperty(ctx, globalThis, ctx.parent); + handleFirstProperty(ctx, globalThis, ctx.parent) catch return; } else { this.printComma(Writer, writer_, enable_ansi_colors) catch unreachable; } @@ -2034,9 +2034,9 @@ pub const Formatter = struct { }; } - fn getObjectName(globalThis: *JSC.JSGlobalObject, value: JSValue) ?ZigString { + fn getObjectName(globalThis: *JSC.JSGlobalObject, value: JSValue) bun.JSError!?ZigString { var name_str = ZigString.init(""); - value.getClassName(globalThis, &name_str); + try value.getClassName(globalThis, &name_str); if (!name_str.eqlComptime("Object")) { return name_str; } else if (value.getPrototype(globalThis).eqlValue(JSValue.null)) { @@ -2209,7 +2209,7 @@ pub const Formatter = struct { .Double => { if (value.isCell()) { var number_name = ZigString.Empty; - value.getClassName(this.globalThis, &number_name); + try value.getClassName(this.globalThis, &number_name); var number_value = ZigString.Empty; try value.toZigString(&number_value, this.globalThis); @@ -2300,12 +2300,12 @@ pub const Formatter = struct { }, .Class => { var printable = ZigString.init(&name_buf); - value.getClassName(this.globalThis, &printable); + try value.getClassName(this.globalThis, &printable); this.addForNewLine(printable.len); const proto = value.getPrototype(this.globalThis); var printable_proto = ZigString.init(&name_buf); - proto.getClassName(this.globalThis, &printable_proto); + try proto.getClassName(this.globalThis, &printable_proto); this.addForNewLine(printable_proto.len); if (printable.len == 0) { @@ -2633,7 +2633,7 @@ pub const Formatter = struct { } else if (value.as(bun.api.ResolveMessage)) |resolve_log| { resolve_log.msg.writeFormat(writer_, enable_ansi_colors) catch {}; return; - } else if (JestPrettyFormat.printAsymmetricMatcher(this, Format, &writer, writer_, name_buf, value, enable_ansi_colors)) { + } else if (try JestPrettyFormat.printAsymmetricMatcher(this, Format, &writer, writer_, name_buf, value, enable_ansi_colors)) { return; } else if (jsType != .DOMWrapper) { if (value.isCallable()) { @@ -2674,7 +2674,7 @@ pub const Formatter = struct { .Boolean => { if (value.isCell()) { var bool_name = ZigString.Empty; - value.getClassName(this.globalThis, &bool_name); + try value.getClassName(this.globalThis, &bool_name); var bool_value = ZigString.Empty; try value.toZigString(&bool_value, this.globalThis); @@ -2733,7 +2733,7 @@ pub const Formatter = struct { .formatter = this, .writer = writer_, }; - value.forEach(this.globalThis, &iter, @TypeOf(iter).forEach); + try value.forEach(this.globalThis, &iter, @TypeOf(iter).forEach); if (this.failed) return; if (single_line and iter.count > 0) { writer.writeAll(" "); @@ -2763,7 +2763,7 @@ pub const Formatter = struct { .formatter = this, .writer = writer_, }; - value.forEach(this.globalThis, &iter, @TypeOf(iter).forEach); + try value.forEach(this.globalThis, &iter, @TypeOf(iter).forEach); if (this.failed) return; if (iter.count > 0) { if (single_line) { @@ -2797,7 +2797,7 @@ pub const Formatter = struct { .formatter = this, .writer = writer_, }; - value.forEach(this.globalThis, &iter, @TypeOf(iter).forEach); + try value.forEach(this.globalThis, &iter, @TypeOf(iter).forEach); if (this.failed) return; if (iter.count > 0 and !single_line) { writer.writeAll("\n"); @@ -2840,7 +2840,7 @@ pub const Formatter = struct { .formatter = this, .writer = writer_, }; - value.forEach(this.globalThis, &iter, @TypeOf(iter).forEach); + try value.forEach(this.globalThis, &iter, @TypeOf(iter).forEach); if (this.failed) return; if (single_line and !iter.is_first) { writer.writeAll(" "); @@ -3038,7 +3038,7 @@ pub const Formatter = struct { try type_value.toZigString(&tag_name_str, this.globalThis); is_tag_kind_primitive = true; } else if (_tag.cell.isObject() or type_value.isCallable()) { - type_value.getNameProperty(this.globalThis, &tag_name_str); + try type_value.getNameProperty(this.globalThis, &tag_name_str); if (tag_name_str.len == 0) { tag_name_str = ZigString.init("NoName"); } @@ -3316,7 +3316,7 @@ pub const Formatter = struct { else if (value.isCallable()) try this.printAs(.Function, Writer, writer_, value, jsType, enable_ansi_colors) else { - if (getObjectName(this.globalThis, value)) |name_str| { + if (try getObjectName(this.globalThis, value)) |name_str| { writer.print("{} ", .{name_str}); } writer.writeAll("{}"); diff --git a/src/bun.js/ModuleLoader.zig b/src/bun.js/ModuleLoader.zig index 72b7c89f8e..2cee58c7eb 100644 --- a/src/bun.js/ModuleLoader.zig +++ b/src/bun.js/ModuleLoader.zig @@ -449,13 +449,13 @@ pub const AsyncModule = struct { var spec = bun.String.init(ZigString.init(this.specifier).withEncoding()); var ref = bun.String.init(ZigString.init(this.referrer).withEncoding()); - Bun__onFulfillAsyncModule( + bun.jsc.fromJSHostCallGeneric(this.globalThis, @src(), Bun__onFulfillAsyncModule, .{ this.globalThis, this.promise.get().?, &errorable, &spec, &ref, - ); + }) catch {}; this.deinit(); jsc_vm.allocator.destroy(this); } @@ -468,7 +468,7 @@ pub const AsyncModule = struct { specifier_: bun.String, referrer_: bun.String, log: *logger.Log, - ) bun.JSExecutionTerminated!void { + ) bun.JSError!void { JSC.markBinding(@src()); var specifier = specifier_; var referrer = referrer_; @@ -508,14 +508,13 @@ pub const AsyncModule = struct { debug("fulfill: {any}", .{specifier}); - Bun__onFulfillAsyncModule( + try bun.jsc.fromJSHostCallGeneric(globalThis, @src(), Bun__onFulfillAsyncModule, .{ globalThis, promise, &errorable, &specifier, &referrer, - ); - try scope.assertNoExceptionExceptTermination(); + }); } pub fn resolveError(this: *AsyncModule, vm: *VirtualMachine, import_record_id: u32, result: PackageResolveError) !void { @@ -2143,24 +2142,23 @@ pub const RuntimeTranspilerStore = struct { }; } - // This is run at the top of the event loop on the JS thread. - pub fn drain(this: *RuntimeTranspilerStore) bun.JSExecutionTerminated!void { + pub fn runFromJSThread(this: *RuntimeTranspilerStore) void { var batch = this.queue.popBatch(); - var iter = batch.iterator(); - if (iter.next()) |job| { - // we run just one job first to see if there are more - try job.runFromJSThread(); - } else { - return; - } var vm: *VirtualMachine = @fieldParentPtr("transpiler_store", this); const event_loop = vm.eventLoop(); const global = vm.global; const jsc_vm = vm.jsc; + var iter = batch.iterator(); + if (iter.next()) |job| { + // we run just one job first to see if there are more + job.runFromJSThread() catch |err| global.reportUncaughtExceptionFromError(err); + } else { + return; + } while (iter.next()) |job| { // if there are more, we need to drain the microtasks from the previous run - try event_loop.drainMicrotasksWithGlobal(global, jsc_vm); - try job.runFromJSThread(); + event_loop.drainMicrotasksWithGlobal(global, jsc_vm) catch return; + job.runFromJSThread() catch |err| global.reportUncaughtExceptionFromError(err); } // immediately after this is called, the microtasks will be drained again. @@ -2267,7 +2265,7 @@ pub const RuntimeTranspilerStore = struct { this.vm.eventLoop().enqueueTaskConcurrent(JSC.ConcurrentTask.createFrom(&this.vm.transpiler_store)); } - pub fn runFromJSThread(this: *TranspilerJob) bun.JSExecutionTerminated!void { + pub fn runFromJSThread(this: *TranspilerJob) bun.JSError!void { var vm = this.vm; const promise = this.promise.swap(); const globalThis = this.globalThis; diff --git a/src/bun.js/VirtualMachine.zig b/src/bun.js/VirtualMachine.zig index 2351d2c487..8021c023e4 100644 --- a/src/bun.js/VirtualMachine.zig +++ b/src/bun.js/VirtualMachine.zig @@ -567,7 +567,9 @@ pub fn unhandledRejection(this: *JSC.VirtualMachine, globalObject: *JSGlobalObje error.JSExecutionTerminated => {}, // we are returning anyway }; _ = Bun__handleUnhandledRejection(globalObject, reason, promise); - Bun__promises__emitUnhandledRejectionWarning(globalObject, reason, promise); + bun.jsc.fromJSHostCallGeneric(globalObject, @src(), Bun__promises__emitUnhandledRejectionWarning, .{ globalObject, reason, promise }) catch |err| { + _ = globalObject.reportUncaughtException(globalObject.takeException(err).asException(globalObject.vm()).?); + }; return; }, .warn_with_error_code => { @@ -575,7 +577,9 @@ pub fn unhandledRejection(this: *JSC.VirtualMachine, globalObject: *JSGlobalObje error.JSExecutionTerminated => {}, // we are returning anyway }; if (Bun__handleUnhandledRejection(globalObject, reason, promise) > 0) return; - Bun__promises__emitUnhandledRejectionWarning(globalObject, reason, promise); + bun.jsc.fromJSHostCallGeneric(globalObject, @src(), Bun__promises__emitUnhandledRejectionWarning, .{ globalObject, reason, promise }) catch |err| { + _ = globalObject.reportUncaughtException(globalObject.takeException(err).asException(globalObject.vm()).?); + }; this.exit_handler.exit_code = 1; return; }, @@ -586,7 +590,9 @@ pub fn unhandledRejection(this: *JSC.VirtualMachine, globalObject: *JSGlobalObje const wrapped_reason = wrapUnhandledRejectionErrorForUncaughtException(globalObject, reason); _ = this.uncaughtException(globalObject, wrapped_reason, true); if (Bun__handleUnhandledRejection(globalObject, reason, promise) > 0) return; - Bun__promises__emitUnhandledRejectionWarning(globalObject, reason, promise); + bun.jsc.fromJSHostCallGeneric(globalObject, @src(), Bun__promises__emitUnhandledRejectionWarning, .{ globalObject, reason, promise }) catch |err| { + _ = globalObject.reportUncaughtException(globalObject.takeException(err).asException(globalObject.vm()).?); + }; return; }, .throw => { @@ -1870,7 +1876,7 @@ pub fn processFetchLog(globalThis: *JSGlobalObject, specifier: bun.String, refer specifier, }) catch unreachable, ), - ), + ) catch |e| globalThis.takeException(e), ); }, } @@ -1966,15 +1972,13 @@ export fn Bun__logUnhandledException(exception: JSValue) void { get().runErrorHandler(exception, null); } -pub fn clearEntryPoint( - this: *VirtualMachine, -) void { +pub fn clearEntryPoint(this: *VirtualMachine) bun.JSError!void { if (this.main.len == 0) { return; } var str = ZigString.init(main_file_name); - this.global.deleteModuleRegistryEntry(&str); + try this.global.deleteModuleRegistryEntry(&str); } fn loadPreloads(this: *VirtualMachine) !?*JSInternalPromise { @@ -2107,7 +2111,7 @@ pub fn reloadEntryPoint(this: *VirtualMachine, entry_path: []const u8) !*JSInter const promise = if (!this.main_is_html_entrypoint) JSModuleLoader.loadAndEvaluateModule(this.global, &String.init(main_file_name)) orelse return error.JSError else - Bun__loadHTMLEntryPoint(this.global); + try bun.jsc.fromJSHostCallGeneric(this.global, @src(), Bun__loadHTMLEntryPoint, .{this.global}); this.pending_internal_promise = promise; JSValue.fromCell(promise).ensureStillAlive(); @@ -2355,16 +2359,16 @@ pub fn printErrorlikeObject( pub fn iteratorWithOutColor(vm: *VM, globalObject: *JSGlobalObject, ctx: ?*anyopaque, nextValue: JSValue) callconv(.C) void { iterator(vm, globalObject, nextValue, ctx.?, false); } - inline fn iterator(_: *VM, _: *JSGlobalObject, nextValue: JSValue, ctx: ?*anyopaque, comptime color: bool) void { + fn iterator(_: *VM, _: *JSGlobalObject, nextValue: JSValue, ctx: ?*anyopaque, comptime color: bool) void { const this_ = @as(*@This(), @ptrFromInt(@intFromPtr(ctx))); VirtualMachine.get().printErrorlikeObject(nextValue, null, this_.current_exception_list, this_.formatter, Writer, this_.writer, color, allow_side_effects); } }; var iter = AggregateErrorIterator{ .writer = writer, .current_exception_list = exception_list, .formatter = formatter }; if (comptime allow_ansi_color) { - value.getErrorsProperty(this.global).forEach(this.global, &iter, AggregateErrorIterator.iteratorWithColor); + value.getErrorsProperty(this.global).forEach(this.global, &iter, AggregateErrorIterator.iteratorWithColor) catch return; // TODO: properly propagate exception upwards } else { - value.getErrorsProperty(this.global).forEach(this.global, &iter, AggregateErrorIterator.iteratorWithOutColor); + value.getErrorsProperty(this.global).forEach(this.global, &iter, AggregateErrorIterator.iteratorWithOutColor) catch return; // TODO: properly propagate exception upwards } return; } diff --git a/src/bun.js/api/JSBundler.zig b/src/bun.js/api/JSBundler.zig index 1b1c244650..f47fe33ae1 100644 --- a/src/bun.js/api/JSBundler.zig +++ b/src/bun.js/api/JSBundler.zig @@ -1001,18 +1001,18 @@ pub const JSBundler = struct { JSC.markBinding(@src()); const tracer = bun.perf.trace("JSBundler.addPlugin"); defer tracer.end(); - return JSBundlerPlugin__runSetupFunction( + return bun.jsc.fromJSHostCall(globalObject(this), @src(), JSBundlerPlugin__runSetupFunction, .{ this, object, config, onstart_promises_array, JSValue.jsBoolean(is_last), JSValue.jsBoolean(is_bake), - ).unwrap(); + }); } - pub fn drainDeferred(this: *Plugin, rejected: bool) void { - JSBundlerPlugin__drainDeferred(this, rejected); + pub fn drainDeferred(this: *Plugin, rejected: bool) bun.JSError!void { + return bun.jsc.fromJSHostCallGeneric(this.globalObject(), @src(), JSBundlerPlugin__drainDeferred, .{ this, rejected }); } pub fn setConfig(this: *Plugin, config: *anyopaque) void { @@ -1029,7 +1029,7 @@ pub const JSBundler = struct { JSC.JSValue, JSC.JSValue, JSC.JSValue, - ) JSValue.MaybeException; + ) JSValue; pub export fn JSBundlerPlugin__addError( ctx: *anyopaque, diff --git a/src/bun.js/api/JSTranspiler.zig b/src/bun.js/api/JSTranspiler.zig index 298fc15354..68ce03b3ac 100644 --- a/src/bun.js/api/JSTranspiler.zig +++ b/src/bun.js/api/JSTranspiler.zig @@ -188,7 +188,7 @@ pub const TransformTask = struct { } } - break :brk this.log.toJS(this.global, bun.default_allocator, "Transform failed"); + break :brk this.log.toJS(this.global, bun.default_allocator, "Transform failed") catch return; // TODO: properly propagate exception upwards }; promise.reject(this.global, error_value); diff --git a/src/bun.js/api/bun/socket/tls_socket_functions.zig b/src/bun.js/api/bun/socket/tls_socket_functions.zig index 9b09f9b8a8..bc1443f212 100644 --- a/src/bun.js/api/bun/socket/tls_socket_functions.zig +++ b/src/bun.js/api/bun/socket/tls_socket_functions.zig @@ -169,7 +169,7 @@ pub fn getTLSFinishedMessage(this: *This, globalObject: *JSC.JSGlobalObject, _: if (size == 0) return .js_undefined; const buffer_size = @as(usize, @intCast(size)); - var buffer = JSValue.createBufferFromLength(globalObject, buffer_size); + var buffer = try JSValue.createBufferFromLength(globalObject, buffer_size); const buffer_ptr = @as(*anyopaque, @ptrCast(buffer.asArrayBuffer(globalObject).?.ptr)); const result_size = BoringSSL.SSL_get_finished(ssl_ptr, buffer_ptr, buffer_size); @@ -306,7 +306,7 @@ pub fn getTLSPeerFinishedMessage(this: *This, globalObject: *JSC.JSGlobalObject, if (size == 0) return .js_undefined; const buffer_size = @as(usize, @intCast(size)); - var buffer = JSValue.createBufferFromLength(globalObject, buffer_size); + var buffer = try JSValue.createBufferFromLength(globalObject, buffer_size); const buffer_ptr = @as(*anyopaque, @ptrCast(buffer.asArrayBuffer(globalObject).?.ptr)); const result_size = BoringSSL.SSL_get_peer_finished(ssl_ptr, buffer_ptr, buffer_size); @@ -355,7 +355,7 @@ pub fn exportKeyingMaterial(this: *This, globalObject: *JSC.JSGlobalObject, call const context_slice = sb.slice(); const buffer_size = @as(usize, @intCast(length)); - var buffer = JSValue.createBufferFromLength(globalObject, buffer_size); + var buffer = try JSValue.createBufferFromLength(globalObject, buffer_size); const buffer_ptr = @as([*c]u8, @ptrCast(buffer.asArrayBuffer(globalObject).?.ptr)); const result = BoringSSL.SSL_export_keying_material(ssl_ptr, buffer_ptr, buffer_size, @as([*c]const u8, @ptrCast(label_slice.ptr)), label_slice.len, @as([*c]const u8, @ptrCast(context_slice.ptr)), context_slice.len, 1); @@ -368,7 +368,7 @@ pub fn exportKeyingMaterial(this: *This, globalObject: *JSC.JSGlobalObject, call } } else { const buffer_size = @as(usize, @intCast(length)); - var buffer = JSValue.createBufferFromLength(globalObject, buffer_size); + var buffer = try JSValue.createBufferFromLength(globalObject, buffer_size); const buffer_ptr = @as([*c]u8, @ptrCast(buffer.asArrayBuffer(globalObject).?.ptr)); const result = BoringSSL.SSL_export_keying_material(ssl_ptr, buffer_ptr, buffer_size, @as([*c]const u8, @ptrCast(label_slice.ptr)), label_slice.len, null, 0, 0); @@ -468,7 +468,7 @@ pub fn getSession(this: *This, globalObject: *JSC.JSGlobalObject, _: *JSC.CallFr } const buffer_size = @as(usize, @intCast(size)); - var buffer = JSValue.createBufferFromLength(globalObject, buffer_size); + var buffer = try JSValue.createBufferFromLength(globalObject, buffer_size); var buffer_ptr = @as([*c]u8, @ptrCast(buffer.asArrayBuffer(globalObject).?.ptr)); const result_size = BoringSSL.i2d_SSL_SESSION(session, &buffer_ptr); diff --git a/src/bun.js/api/bun/spawn/stdio.zig b/src/bun.js/api/bun/spawn/stdio.zig index f0f1951e20..f3088fa0dc 100644 --- a/src/bun.js/api/bun/spawn/stdio.zig +++ b/src/bun.js/api/bun/spawn/stdio.zig @@ -323,12 +323,9 @@ pub const Stdio = union(enum) { else => unreachable, } - const stream_value = body.toReadableStream(globalThis); - if (globalThis.hasException()) { - return error.JSError; - } + const stream_value = try body.toReadableStream(globalThis); - const stream = JSC.WebCore.ReadableStream.fromJS(stream_value, globalThis) orelse return globalThis.throwInvalidArguments("Failed to create ReadableStream", .{}); + const stream = (try JSC.WebCore.ReadableStream.fromJS(stream_value, globalThis)) orelse return globalThis.throwInvalidArguments("Failed to create ReadableStream", .{}); if (stream.isDisturbed(globalThis)) { return globalThis.ERR(.BODY_ALREADY_USED, "ReadableStream has already been used", .{}).throw(); @@ -409,7 +406,7 @@ pub const Stdio = union(enum) { return extractBodyValue(out_stdio, globalThis, i, res.getBodyValue(), is_sync); } - if (JSC.WebCore.ReadableStream.fromJS(value, globalThis)) |stream_| { + if (try JSC.WebCore.ReadableStream.fromJS(value, globalThis)) |stream_| { var stream = stream_; if (stream.toAnyBlob(globalThis)) |blob| { return out_stdio.extractBlob(globalThis, blob, i); diff --git a/src/bun.js/api/bun/subprocess.zig b/src/bun.js/api/bun/subprocess.zig index bd920d78f5..6999c9a54b 100644 --- a/src/bun.js/api/bun/subprocess.zig +++ b/src/bun.js/api/bun/subprocess.zig @@ -90,15 +90,12 @@ pub const ResourceUsage = struct { rusage: Rusage, - pub fn getCPUTime( - this: *ResourceUsage, - globalObject: *JSGlobalObject, - ) JSValue { + pub fn getCPUTime(this: *ResourceUsage, globalObject: *JSGlobalObject) bun.JSError!JSValue { var cpu = JSC.JSValue.createEmptyObjectWithNullPrototype(globalObject); const rusage = this.rusage; - const usrTime = JSValue.fromTimevalNoTruncate(globalObject, rusage.utime.usec, rusage.utime.sec); - const sysTime = JSValue.fromTimevalNoTruncate(globalObject, rusage.stime.usec, rusage.stime.sec); + const usrTime = try JSValue.fromTimevalNoTruncate(globalObject, rusage.utime.usec, rusage.utime.sec); + const sysTime = try JSValue.fromTimevalNoTruncate(globalObject, rusage.stime.usec, rusage.stime.sec); cpu.put(globalObject, JSC.ZigString.static("user"), usrTime); cpu.put(globalObject, JSC.ZigString.static("system"), sysTime); @@ -107,58 +104,37 @@ pub const ResourceUsage = struct { return cpu; } - pub fn getMaxRSS( - this: *ResourceUsage, - _: *JSGlobalObject, - ) JSValue { + pub fn getMaxRSS(this: *ResourceUsage, _: *JSGlobalObject) JSValue { return JSC.JSValue.jsNumber(this.rusage.maxrss); } - pub fn getSharedMemorySize( - this: *ResourceUsage, - _: *JSGlobalObject, - ) JSValue { + pub fn getSharedMemorySize(this: *ResourceUsage, _: *JSGlobalObject) JSValue { return JSC.JSValue.jsNumber(this.rusage.ixrss); } - pub fn getSwapCount( - this: *ResourceUsage, - _: *JSGlobalObject, - ) JSValue { + pub fn getSwapCount(this: *ResourceUsage, _: *JSGlobalObject) JSValue { return JSC.JSValue.jsNumber(this.rusage.nswap); } - pub fn getOps( - this: *ResourceUsage, - globalObject: *JSGlobalObject, - ) JSValue { + pub fn getOps(this: *ResourceUsage, globalObject: *JSGlobalObject) JSValue { var ops = JSC.JSValue.createEmptyObjectWithNullPrototype(globalObject); ops.put(globalObject, JSC.ZigString.static("in"), JSC.JSValue.jsNumber(this.rusage.inblock)); ops.put(globalObject, JSC.ZigString.static("out"), JSC.JSValue.jsNumber(this.rusage.oublock)); return ops; } - pub fn getMessages( - this: *ResourceUsage, - globalObject: *JSGlobalObject, - ) JSValue { + pub fn getMessages(this: *ResourceUsage, globalObject: *JSGlobalObject) JSValue { var msgs = JSC.JSValue.createEmptyObjectWithNullPrototype(globalObject); msgs.put(globalObject, JSC.ZigString.static("sent"), JSC.JSValue.jsNumber(this.rusage.msgsnd)); msgs.put(globalObject, JSC.ZigString.static("received"), JSC.JSValue.jsNumber(this.rusage.msgrcv)); return msgs; } - pub fn getSignalCount( - this: *ResourceUsage, - _: *JSGlobalObject, - ) JSValue { + pub fn getSignalCount(this: *ResourceUsage, _: *JSGlobalObject) JSValue { return JSC.JSValue.jsNumber(this.rusage.nsignals); } - pub fn getContextSwitches( - this: *ResourceUsage, - globalObject: *JSGlobalObject, - ) JSValue { + pub fn getContextSwitches(this: *ResourceUsage, globalObject: *JSGlobalObject) JSValue { var ctx = JSC.JSValue.createEmptyObjectWithNullPrototype(globalObject); ctx.put(globalObject, JSC.ZigString.static("voluntary"), JSC.JSValue.jsNumber(this.rusage.nvcsw)); ctx.put(globalObject, JSC.ZigString.static("involuntary"), JSC.JSValue.jsNumber(this.rusage.nivcsw)); @@ -495,11 +471,11 @@ const Readable = union(enum) { } } - pub fn toJS(this: *Readable, globalThis: *JSC.JSGlobalObject, exited: bool) JSValue { + pub fn toJS(this: *Readable, globalThis: *JSC.JSGlobalObject, exited: bool) bun.JSError!JSValue { _ = exited; // autofix switch (this.*) { // should only be reachable when the entire output is buffered. - .memfd => return this.toBufferedValue(globalThis) catch .zero, + .memfd => return this.toBufferedValue(globalThis), .fd => |fd| { return fd.toJS(globalThis); @@ -516,9 +492,7 @@ const Readable = union(enum) { return JSC.WebCore.ReadableStream.empty(globalThis); } - const own = buffer.takeSlice(bun.default_allocator) catch { - globalThis.throwOutOfMemory() catch return .zero; - }; + const own = try buffer.takeSlice(bun.default_allocator); return JSC.WebCore.ReadableStream.fromOwnedSlice(globalThis, own, 0); }, else => { @@ -559,26 +533,17 @@ const Readable = union(enum) { } }; -pub fn getStderr( - this: *Subprocess, - globalThis: *JSGlobalObject, -) JSValue { +pub fn getStderr(this: *Subprocess, globalThis: *JSGlobalObject) bun.JSError!JSValue { this.observable_getters.insert(.stderr); return this.stderr.toJS(globalThis, this.hasExited()); } -pub fn getStdin( - this: *Subprocess, - globalThis: *JSGlobalObject, -) JSValue { +pub fn getStdin(this: *Subprocess, globalThis: *JSGlobalObject) bun.JSError!JSValue { this.observable_getters.insert(.stdin); return this.stdin.toJS(globalThis, this); } -pub fn getStdout( - this: *Subprocess, - globalThis: *JSGlobalObject, -) JSValue { +pub fn getStdout(this: *Subprocess, globalThis: *JSGlobalObject) bun.JSError!JSValue { this.observable_getters.insert(.stdout); // NOTE: ownership of internal buffers is transferred to the JSValue, which // gets cached on JSSubprocess (created via bindgen). This makes it @@ -586,11 +551,7 @@ pub fn getStdout( return this.stdout.toJS(globalThis, this.hasExited()); } -pub fn asyncDispose( - this: *Subprocess, - global: *JSGlobalObject, - callframe: *JSC.CallFrame, -) bun.JSError!JSValue { +pub fn asyncDispose(this: *Subprocess, global: *JSGlobalObject, callframe: *JSC.CallFrame) bun.JSError!JSValue { if (this.process.hasExited()) { // rely on GC to clean everything up in this case return .js_undefined; @@ -1110,7 +1071,7 @@ pub const PipeReader = struct { this.reader.watch(); } - pub fn toReadableStream(this: *PipeReader, globalObject: *JSC.JSGlobalObject) JSC.JSValue { + pub fn toReadableStream(this: *PipeReader, globalObject: *JSC.JSGlobalObject) bun.JSError!JSC.JSValue { defer this.detach(); switch (this.state) { @@ -1124,9 +1085,9 @@ pub const PipeReader = struct { return JSC.WebCore.ReadableStream.fromOwnedSlice(globalObject, bytes, 0); }, .err => |err| { - _ = err; // autofix - const empty = JSC.WebCore.ReadableStream.empty(globalObject); - JSC.WebCore.ReadableStream.cancel(&JSC.WebCore.ReadableStream.fromJS(empty, globalObject).?, globalObject); + _ = err; + const empty = try JSC.WebCore.ReadableStream.empty(globalObject); + JSC.WebCore.ReadableStream.cancel(&(try JSC.WebCore.ReadableStream.fromJS(empty, globalObject)).?, globalObject); return empty; }, } diff --git a/src/bun.js/api/html_rewriter.zig b/src/bun.js/api/html_rewriter.zig index a368d0df6f..329dec612d 100644 --- a/src/bun.js/api/html_rewriter.zig +++ b/src/bun.js/api/html_rewriter.zig @@ -168,7 +168,7 @@ pub const HTMLRewriter = struct { this.builder.deinit(); } - pub fn beginTransform(this: *HTMLRewriter, global: *JSGlobalObject, response: *Response) JSValue { + pub fn beginTransform(this: *HTMLRewriter, global: *JSGlobalObject, response: *Response) bun.JSError!JSValue { const new_context = this.context; new_context.ref(); return BufferOutputSink.init(new_context, global, response, this.builder); @@ -179,15 +179,8 @@ pub const HTMLRewriter = struct { if (response.body.value == .Used) { return global.throwInvalidArguments("Response body already used", .{}); } - - const out = this.beginTransform(global, response); - - if (out != .zero) { - if (out.toError()) |err| { - return global.throwValue(err); - } - } - + const out = try this.beginTransform(global, response); + if (out.toError()) |err| return global.throwValue(err); return out; } @@ -203,7 +196,7 @@ pub const HTMLRewriter = struct { if (kind != .other) { { - const body_value = JSC.WebCore.Body.extract(global, response_value) catch return .zero; + const body_value = try JSC.WebCore.Body.extract(global, response_value); const resp = bun.new(Response, Response{ .init = .{ .status_code = 200, @@ -211,7 +204,7 @@ pub const HTMLRewriter = struct { .body = body_value, }); defer resp.finalize(); - const out_response_value = this.beginTransform(global, resp); + const out_response_value = try this.beginTransform(global, resp); out_response_value.ensureStillAlive(); var out_response = out_response_value.as(Response) orelse return out_response_value; var blob = out_response.body.value.useAsAnyBlobAllowNonUTF8String(); @@ -407,7 +400,7 @@ pub const HTMLRewriter = struct { tmp_sync_error: ?*JSC.JSValue = null, // const log = bun.Output.scoped(.BufferOutputSink, false); - pub fn init(context: *LOLHTMLContext, global: *JSGlobalObject, original: *Response, builder: *LOLHTML.HTMLRewriter.Builder) JSC.JSValue { + pub fn init(context: *LOLHTMLContext, global: *JSGlobalObject, original: *Response, builder: *LOLHTML.HTMLRewriter.Builder) bun.JSError!JSC.JSValue { var sink = bun.new(BufferOutputSink, .{ .ref_count = .init(), .global = global, @@ -475,7 +468,7 @@ pub const HTMLRewriter = struct { // https://github.com/oven-sh/bun/issues/3334 if (original.init.headers) |headers| { - result.init.headers = headers.cloneThis(global); + result.init.headers = try headers.cloneThis(global); } // Hold off on cloning until we're actually done. diff --git a/src/bun.js/api/server.zig b/src/bun.js/api/server.zig index bedc7ecf0c..f26f2f72f6 100644 --- a/src/bun.js/api/server.zig +++ b/src/bun.js/api/server.zig @@ -157,7 +157,7 @@ pub const AnyRoute = union(enum) { try builder.appendSlice(relative_path); - const fetch_headers = JSC.WebCore.FetchHeaders.createFromJS(init_ctx.global, try argument.get(init_ctx.global, "headers") orelse return null); + const fetch_headers = try JSC.WebCore.FetchHeaders.createFromJS(init_ctx.global, try argument.get(init_ctx.global, "headers") orelse return null); defer if (fetch_headers) |headers| headers.deref(); if (init_ctx.global.hasException()) return error.JSError; @@ -427,7 +427,7 @@ const ServePlugins = struct { } }; global.bunVM().eventLoop().enter(); - const result = JSBundlerPlugin__loadAndResolvePluginsForServe(plugin, plugin_js_array, bunfig_folder_bunstr); + const result = try bun.jsc.fromJSHostCall(global, @src(), JSBundlerPlugin__loadAndResolvePluginsForServe, .{ plugin, plugin_js_array, bunfig_folder_bunstr }); global.bunVM().eventLoop().exit(); // handle the case where js synchronously throws an error @@ -842,7 +842,7 @@ pub fn NewServer(protocol_enum: enum { http, https }, development_kind: enum { d var fetch_headers_to_use: *WebCore.FetchHeaders = headers_value.as(WebCore.FetchHeaders) orelse brk: { if (headers_value.isObject()) { - if (WebCore.FetchHeaders.createFromJS(globalThis, headers_value)) |fetch_headers| { + if (try WebCore.FetchHeaders.createFromJS(globalThis, headers_value)) |fetch_headers| { fetch_headers_to_deref = fetch_headers; break :brk fetch_headers; } @@ -970,7 +970,7 @@ pub fn NewServer(protocol_enum: enum { http, https }, development_kind: enum { d var fetch_headers_to_use: *WebCore.FetchHeaders = headers_value.as(WebCore.FetchHeaders) orelse brk: { if (headers_value.isObject()) { - if (WebCore.FetchHeaders.createFromJS(globalThis, headers_value)) |fetch_headers| { + if (try WebCore.FetchHeaders.createFromJS(globalThis, headers_value)) |fetch_headers| { fetch_headers_to_deref = fetch_headers; break :brk fetch_headers; } @@ -1231,7 +1231,7 @@ pub fn NewServer(protocol_enum: enum { http, https }, development_kind: enum { d if (try opts.fastGet(ctx, .headers)) |headers_| { if (headers_.as(WebCore.FetchHeaders)) |headers__| { headers = headers__; - } else if (WebCore.FetchHeaders.createFromJS(ctx, headers_)) |headers__| { + } else if (try WebCore.FetchHeaders.createFromJS(ctx, headers_)) |headers__| { headers = headers__; } } @@ -1252,7 +1252,7 @@ pub fn NewServer(protocol_enum: enum { http, https }, development_kind: enum { d method, ); } else if (first_arg.as(Request)) |request_| { - request_.cloneInto( + try request_.cloneInto( &existing_request, bun.default_allocator, ctx, @@ -2076,11 +2076,7 @@ pub fn NewServer(protocol_enum: enum { http, https }, development_kind: enum { d }) orelse return; const server_request_list = js.routeListGetCached(server.jsValueAssertAlive()).?; - var response_value = Bun__ServerRouteList__callRoute(server.globalThis, index, prepared.request_object, server.jsValueAssertAlive(), server_request_list, &prepared.js_request, req); - - if (server.globalThis.tryTakeException()) |exception| { - response_value = exception; - } + const response_value = bun.jsc.fromJSHostCall(server.globalThis, @src(), Bun__ServerRouteList__callRoute, .{ server.globalThis, index, prepared.request_object, server.jsValueAssertAlive(), server_request_list, &prepared.js_request, req }) catch |err| server.globalThis.takeException(err); server.handleRequest(&should_deinit_context, prepared, req, response_value); } @@ -2327,11 +2323,7 @@ pub fn NewServer(protocol_enum: enum { http, https }, development_kind: enum { d var prepared = server.prepareJsRequestContext(req, resp, &should_deinit_context, false, method) orelse return; prepared.ctx.upgrade_context = upgrade_ctx; // set the upgrade context const server_request_list = js.routeListGetCached(server.jsValueAssertAlive()).?; - var response_value = Bun__ServerRouteList__callRoute(server.globalThis, index, prepared.request_object, server.jsValueAssertAlive(), server_request_list, &prepared.js_request, req); - - if (server.globalThis.tryTakeException()) |exception| { - response_value = exception; - } + const response_value = bun.jsc.fromJSHostCall(server.globalThis, @src(), Bun__ServerRouteList__callRoute, .{ server.globalThis, index, prepared.request_object, server.jsValueAssertAlive(), server_request_list, &prepared.js_request, req }) catch |err| server.globalThis.takeException(err); server.handleRequest(&should_deinit_context, prepared, req, response_value); } diff --git a/src/bun.js/api/server/FileRoute.zig b/src/bun.js/api/server/FileRoute.zig index d5c1e55369..65de4f7c13 100644 --- a/src/bun.js/api/server/FileRoute.zig +++ b/src/bun.js/api/server/FileRoute.zig @@ -15,12 +15,12 @@ pub const InitOptions = struct { headers: ?*JSC.WebCore.FetchHeaders = null, }; -pub fn lastModifiedDate(this: *const FileRoute) ?u64 { +pub fn lastModifiedDate(this: *const FileRoute) bun.JSError!?u64 { if (this.has_last_modified_header) { if (this.headers.get("last-modified")) |last_modified| { var string = bun.String.init(last_modified); defer string.deref(); - const date_f64 = bun.String.parseDate(&string, bun.JSC.VirtualMachine.get().global); + const date_f64 = try bun.String.parseDate(&string, bun.JSC.VirtualMachine.get().global); if (!std.math.isNan(date_f64) and std.math.isFinite(date_f64)) { return @intFromFloat(date_f64); } @@ -185,7 +185,7 @@ pub fn on(this: *FileRoute, req: *uws.Request, resp: AnyResponse, method: bun.ht const fd = fd_result.result; - const input_if_modified_since_date: ?u64 = req.dateForHeader("if-modified-since"); + const input_if_modified_since_date: ?u64 = req.dateForHeader("if-modified-since") catch return; // TODO: properly propagate exception upwards const can_serve_file: bool, const size: u64, const file_type: bun.io.FileType, const pollable: bool = brk: { const stat = switch (bun.sys.fstat(fd)) { @@ -226,7 +226,7 @@ pub fn on(this: *FileRoute, req: *uws.Request, resp: AnyResponse, method: bun.ht // ignored, unless the server doesn't support If-None-Match. if (input_if_modified_since_date) |requested_if_modified_since| { if (method == .HEAD or method == .GET) { - if (this.lastModifiedDate()) |actual_last_modified_at| { + if (this.lastModifiedDate() catch return) |actual_last_modified_at| { // TODO: properly propagate exception upwards if (actual_last_modified_at <= requested_if_modified_since) { break :brk 304; } diff --git a/src/bun.js/api/server/NodeHTTPResponse.zig b/src/bun.js/api/server/NodeHTTPResponse.zig index d19c4e7dd5..a59c9e21c7 100644 --- a/src/bun.js/api/server/NodeHTTPResponse.zig +++ b/src/bun.js/api/server/NodeHTTPResponse.zig @@ -729,7 +729,7 @@ fn onDataOrAborted(this: *NodeHTTPResponse, chunk: []const u8, last: bool, event const bytes: JSC.JSValue = brk: { if (chunk.len > 0 and this.buffered_request_body_data_during_pause.len > 0) { - const buffer = JSC.JSValue.createBufferFromLength(globalThis, chunk.len + this.buffered_request_body_data_during_pause.len); + const buffer = JSC.JSValue.createBufferFromLength(globalThis, chunk.len + this.buffered_request_body_data_during_pause.len) catch return; // TODO: properly propagate exception upwards this.buffered_request_body_data_during_pause.deinitWithAllocator(bun.default_allocator); if (buffer.asArrayBuffer(globalThis)) |array_buffer| { var input = array_buffer.slice(); diff --git a/src/bun.js/api/server/RequestContext.zig b/src/bun.js/api/server/RequestContext.zig index c3506bfc5a..0156232c39 100644 --- a/src/bun.js/api/server/RequestContext.zig +++ b/src/bun.js/api/server/RequestContext.zig @@ -1115,7 +1115,7 @@ pub fn NewRequestContext(comptime ssl_enabled: bool, comptime debug_mode: bool, if (assignment_result.toError()) |err_value| { streamLog("returned an error", .{}); - response_stream.detach(); + response_stream.detach(globalThis); this.sink = null; response_stream.sink.destroy(); return this.handleReject(err_value); @@ -1123,7 +1123,7 @@ pub fn NewRequestContext(comptime ssl_enabled: bool, comptime debug_mode: bool, if (resp.hasResponded()) { streamLog("done", .{}); - response_stream.detach(); + response_stream.detach(globalThis); this.sink = null; response_stream.sink.destroy(); stream.done(globalThis); @@ -1191,7 +1191,7 @@ pub fn NewRequestContext(comptime ssl_enabled: bool, comptime debug_mode: bool, } else { // if is not a promise we treat it as Error streamLog("returned an error", .{}); - response_stream.detach(); + response_stream.detach(globalThis); this.sink = null; response_stream.sink.destroy(); return this.handleReject(assignment_result); @@ -1199,7 +1199,7 @@ pub fn NewRequestContext(comptime ssl_enabled: bool, comptime debug_mode: bool, } if (this.isAbortedOrEnded()) { - response_stream.detach(); + response_stream.detach(globalThis); stream.cancel(globalThis); defer this.readable_stream_ref.deinit(); @@ -1217,7 +1217,7 @@ pub fn NewRequestContext(comptime ssl_enabled: bool, comptime debug_mode: bool, response_stream.sink.buffer.len == 0); if (!stream.isLocked(globalThis) and !is_in_progress) { - if (JSC.WebCore.ReadableStream.fromJS(stream.value, globalThis)) |comparator| { + if (JSC.WebCore.ReadableStream.fromJS(stream.value, globalThis) catch null) |comparator| { // TODO: properly propagate exception upwards if (std.meta.activeTag(comparator.ptr) == std.meta.activeTag(stream.ptr)) { streamLog("is not locked", .{}); this.renderMissing(); @@ -1229,7 +1229,7 @@ pub fn NewRequestContext(comptime ssl_enabled: bool, comptime debug_mode: bool, streamLog("is in progress, but did not return a Promise. Finalizing request context", .{}); response_stream.sink.onFirstWrite = null; response_stream.sink.ctx = null; - response_stream.detach(); + response_stream.detach(globalThis); stream.cancel(globalThis); response_stream.sink.markDone(); this.renderMissing(); @@ -1587,7 +1587,7 @@ pub fn NewRequestContext(comptime ssl_enabled: bool, comptime debug_mode: bool, wrote_anything = wrapper.sink.wrote > 0; wrapper.sink.finalize(); - wrapper.detach(); + wrapper.detach(wrapper.sink.globalThis); req.sink = null; wrapper.sink.destroy(); } @@ -1643,7 +1643,7 @@ pub fn NewRequestContext(comptime ssl_enabled: bool, comptime debug_mode: bool, wrapper.sink.done = true; req.flags.aborted = req.flags.aborted or wrapper.sink.aborted; wrapper.sink.finalize(); - wrapper.detach(); + wrapper.detach(wrapper.sink.globalThis); req.sink = null; wrapper.sink.destroy(); } @@ -1790,7 +1790,7 @@ pub fn NewRequestContext(comptime ssl_enabled: bool, comptime debug_mode: bool, if (lock.onReceiveValue != null or lock.task != null) { // someone else is waiting for the stream or waiting for `onStartStreaming` - const readable = value.toReadableStream(globalThis); + const readable = value.toReadableStream(globalThis) catch return; // TODO: properly propagate exception upwards readable.ensureStillAlive(); this.doRenderWithBody(value); return; @@ -2123,7 +2123,7 @@ pub fn NewRequestContext(comptime ssl_enabled: bool, comptime debug_mode: bool, if (this.cookies) |cookies| { this.cookies = null; defer cookies.deref(); - cookies.write(this.server.?.globalThis, ssl_enabled, @ptrCast(this.resp.?)); + cookies.write(this.server.?.globalThis, ssl_enabled, @ptrCast(this.resp.?)) catch return; // TODO: properly propagate exception upwards } if (needs_content_type and diff --git a/src/bun.js/bindings/BindgenCustomEnforceRange.h b/src/bun.js/bindings/BindgenCustomEnforceRange.h index 6e1daa3379..a97f5aeda7 100644 --- a/src/bun.js/bindings/BindgenCustomEnforceRange.h +++ b/src/bun.js/bindings/BindgenCustomEnforceRange.h @@ -44,7 +44,6 @@ struct Converter> static inline NumericType convert(JSC::JSGlobalObject& lexicalGlobalObject, JSC::JSValue value, ExceptionThrower&& exceptionThrower = ExceptionThrower()) { auto scope = DECLARE_THROW_SCOPE(lexicalGlobalObject.vm()); - EXCEPTION_ASSERT(!scope.exception()); double unrestricted; if constexpr (Kind == Bun::BindgenCustomEnforceRangeKind::Node) { // In Node.js, `validateNumber`, `validateInt32`, `validateUint32`, @@ -58,7 +57,6 @@ struct Converter> return 0; } unrestricted = value.asNumber(); - EXCEPTION_ASSERT(!scope.exception()); // Node also validates that integer types are integers if constexpr (std::is_integral_v) { diff --git a/src/bun.js/bindings/BunObject.cpp b/src/bun.js/bindings/BunObject.cpp index 0307e2811a..5c729115f1 100644 --- a/src/bun.js/bindings/BunObject.cpp +++ b/src/bun.js/bindings/BunObject.cpp @@ -304,7 +304,7 @@ static JSValue defaultBunSQLObject(VM& vm, JSObject* bunObject) auto* globalObject = defaultGlobalObject(bunObject->globalObject()); JSValue sqlValue = globalObject->internalModuleRegistry()->requireId(globalObject, vm, InternalModuleRegistry::BunSql); RETURN_IF_EXCEPTION(scope, {}); - return sqlValue.getObject()->get(globalObject, vm.propertyNames->defaultKeyword); + RELEASE_AND_RETURN(scope, sqlValue.getObject()->get(globalObject, vm.propertyNames->defaultKeyword)); } static JSValue constructBunSQLObject(VM& vm, JSObject* bunObject) @@ -314,7 +314,7 @@ static JSValue constructBunSQLObject(VM& vm, JSObject* bunObject) JSValue sqlValue = globalObject->internalModuleRegistry()->requireId(globalObject, vm, InternalModuleRegistry::BunSql); RETURN_IF_EXCEPTION(scope, {}); auto clientData = WebCore::clientData(vm); - return sqlValue.getObject()->get(globalObject, clientData->builtinNames().SQLPublicName()); + RELEASE_AND_RETURN(scope, sqlValue.getObject()->get(globalObject, clientData->builtinNames().SQLPublicName())); } extern "C" JSC::EncodedJSValue JSPasswordObject__create(JSGlobalObject*); @@ -529,8 +529,7 @@ JSC_DEFINE_HOST_FUNCTION(functionBunDeepMatch, (JSGlobalObject * globalObject, J auto scope = DECLARE_THROW_SCOPE(vm); if (callFrame->argumentCount() < 2) { - auto throwScope = DECLARE_THROW_SCOPE(vm); - throwTypeError(globalObject, throwScope, "Expected 2 values to compare"_s); + throwTypeError(globalObject, scope, "Expected 2 values to compare"_s); return {}; } @@ -538,8 +537,7 @@ JSC_DEFINE_HOST_FUNCTION(functionBunDeepMatch, (JSGlobalObject * globalObject, J JSC::JSValue object = callFrame->uncheckedArgument(1); if (!subset.isObject() || !object.isObject()) { - auto throwScope = DECLARE_THROW_SCOPE(vm); - throwTypeError(globalObject, throwScope, "Expected 2 objects to match"_s); + throwTypeError(globalObject, scope, "Expected 2 objects to match"_s); return {}; } @@ -547,7 +545,6 @@ JSC_DEFINE_HOST_FUNCTION(functionBunDeepMatch, (JSGlobalObject * globalObject, J std::set subsetVisited; MarkedArgumentBuffer gcBuffer; bool match = Bun__deepMatch(object, &objVisited, subset, &subsetVisited, globalObject, scope, &gcBuffer, false, false); - RETURN_IF_EXCEPTION(scope, {}); return JSValue::encode(jsBoolean(match)); } diff --git a/src/bun.js/bindings/BunPlugin.cpp b/src/bun.js/bindings/BunPlugin.cpp index 03de1b1d17..3ca7f114f4 100644 --- a/src/bun.js/bindings/BunPlugin.cpp +++ b/src/bun.js/bindings/BunPlugin.cpp @@ -151,6 +151,7 @@ static EncodedJSValue jsFunctionAppendVirtualModulePluginBody(JSC::JSGlobalObjec virtualModules->set(moduleId, JSC::Strong { vm, jsCast(functionValue) }); global->requireMap()->remove(globalObject, moduleIdValue); + RETURN_IF_EXCEPTION(scope, {}); global->esmRegistryMap()->remove(globalObject, moduleIdValue); RETURN_IF_EXCEPTION(scope, {}); @@ -612,7 +613,9 @@ extern "C" JSC_DEFINE_HOST_FUNCTION(JSMock__jsModuleMock, (JSC::JSGlobalObject * bool removeFromESM = false; bool removeFromCJS = false; - if (JSValue entryValue = esm->get(globalObject, specifierString)) { + JSValue entryValue = esm->get(globalObject, specifierString); + RETURN_IF_EXCEPTION(scope, {}); + if (entryValue) { removeFromESM = true; JSObject* entry = entryValue ? entryValue.getObject() : nullptr; if (entry) { @@ -642,15 +645,15 @@ extern "C" JSC_DEFINE_HOST_FUNCTION(JSMock__jsModuleMock, (JSC::JSGlobalObject * value = jsUndefined(); } moduleNamespaceObject->overrideExportValue(globalObject, name, value); + RETURN_IF_EXCEPTION(scope, {}); } } else { // if it's not an object, I guess we just set the default export? moduleNamespaceObject->overrideExportValue(globalObject, vm.propertyNames->defaultKeyword, exportsValue); + RETURN_IF_EXCEPTION(scope, {}); } - RETURN_IF_EXCEPTION(scope, {}); - // TODO: do we need to handle intermediate loading state here? // entry->putDirect(vm, Identifier::fromString(vm, String("evaluated"_s)), jsBoolean(true), 0); // entry->putDirect(vm, Identifier::fromString(vm, String("state"_s)), jsNumber(JSC::JSModuleLoader::Status::Ready), 0); @@ -660,7 +663,9 @@ extern "C" JSC_DEFINE_HOST_FUNCTION(JSMock__jsModuleMock, (JSC::JSGlobalObject * } } - if (auto entryValue = globalObject->requireMap()->get(globalObject, specifierString)) { + entryValue = globalObject->requireMap()->get(globalObject, specifierString); + RETURN_IF_EXCEPTION(scope, {}); + if (entryValue) { removeFromCJS = true; if (auto* moduleObject = entryValue ? jsDynamicCast(entryValue) : nullptr) { JSValue exportsValue = getJSValue(); @@ -674,6 +679,7 @@ extern "C" JSC_DEFINE_HOST_FUNCTION(JSMock__jsModuleMock, (JSC::JSGlobalObject * if (removeFromESM) { esm->remove(globalObject, specifierString); + RETURN_IF_EXCEPTION(scope, {}); } if (removeFromCJS) { diff --git a/src/bun.js/bindings/BunProcess.cpp b/src/bun.js/bindings/BunProcess.cpp index b1f7f74bad..b0ba199878 100644 --- a/src/bun.js/bindings/BunProcess.cpp +++ b/src/bun.js/bindings/BunProcess.cpp @@ -558,8 +558,7 @@ JSC_DEFINE_HOST_FUNCTION(Process_functionDlopen, (JSC::JSGlobalObject * globalOb // TODO(@190n) look for node_register_module_vXYZ according to BuildOptions.reported_nodejs_version // (bun/src/env.zig:36) and the table at https://github.com/nodejs/node/blob/main/doc/abi_version_registry.json - auto napi_register_module_v1 = reinterpret_cast( - dlsym(handle, "napi_register_module_v1")); + auto napi_register_module_v1 = reinterpret_cast(dlsym(handle, "napi_register_module_v1")); auto node_api_module_get_api_version_v1 = reinterpret_cast(dlsym(handle, "node_api_module_get_api_version_v1")); @@ -1114,9 +1113,9 @@ extern "C" JSC::EncodedJSValue Bun__noSideEffectsToString(JSC::VM& vm, JSC::JSGl } if (decodedReason.isInt32()) - return JSC::JSValue::encode(jsString(vm, decodedReason.toWTFString(globalObject))); + RELEASE_AND_RETURN(scope, JSC::JSValue::encode(jsString(vm, decodedReason.toWTFString(globalObject)))); if (decodedReason.isDouble()) - return JSC::JSValue::encode(jsString(vm, decodedReason.toWTFString(globalObject))); + RELEASE_AND_RETURN(scope, JSC::JSValue::encode(jsString(vm, decodedReason.toWTFString(globalObject)))); if (decodedReason.isTrue()) return JSC::JSValue::encode(vm.smallStrings.trueString()); if (decodedReason.isFalse()) @@ -1128,7 +1127,7 @@ extern "C" JSC::EncodedJSValue Bun__noSideEffectsToString(JSC::VM& vm, JSC::JSGl if (decodedReason.isString()) return JSC::JSValue::encode(decodedReason); if (decodedReason.isBigInt()) - return JSC::JSValue::encode(jsString(vm, decodedReason.toWTFString(globalObject))); + RELEASE_AND_RETURN(scope, JSC::JSValue::encode(jsString(vm, decodedReason.toWTFString(globalObject)))); return JSC::JSValue::encode(vm.smallStrings.objectObjectString()); } @@ -2800,7 +2799,7 @@ JSC_DEFINE_HOST_FUNCTION(Process_functionBinding, (JSGlobalObject * jsGlobalObje if (moduleName == "contextify"_s) PROCESS_BINDING_NOT_IMPLEMENTED("contextify"); if (moduleName == "crypto"_s) PROCESS_BINDING_NOT_IMPLEMENTED("crypto"); if (moduleName == "crypto/x509"_s) return JSValue::encode(createCryptoX509Object(globalObject)); - if (moduleName == "fs"_s) return JSValue::encode(globalObject->processBindingFs()); + if (moduleName == "fs"_s) RELEASE_AND_RETURN(throwScope, JSValue::encode(globalObject->processBindingFs())); if (moduleName == "fs_event_wrap"_s) PROCESS_BINDING_NOT_IMPLEMENTED("fs_event_wrap"); if (moduleName == "http_parser"_s) return JSValue::encode(globalObject->processBindingHTTPParser()); if (moduleName == "icu"_s) PROCESS_BINDING_NOT_IMPLEMENTED("icu"); diff --git a/src/bun.js/bindings/BunString.cpp b/src/bun.js/bindings/BunString.cpp index d269d7cd86..6f1bece04f 100644 --- a/src/bun.js/bindings/BunString.cpp +++ b/src/bun.js/bindings/BunString.cpp @@ -101,6 +101,7 @@ extern "C" JSC::EncodedJSValue BunString__createUTF8ForJS(JSC::JSGlobalObject* g throwOutOfMemoryError(globalObject, scope); return {}; } + scope.assertNoException(); return JSValue::encode(jsString(vm, WTFMove(str))); } diff --git a/src/bun.js/bindings/CallSite.cpp b/src/bun.js/bindings/CallSite.cpp index 04470086aa..1dc975265d 100644 --- a/src/bun.js/bindings/CallSite.cpp +++ b/src/bun.js/bindings/CallSite.cpp @@ -90,10 +90,7 @@ void CallSite::visitChildrenImpl(JSCell* cell, Visitor& visitor) } JSC_DEFINE_HOST_FUNCTION(nativeFrameForTesting, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callFrame)) { - auto& vm = JSC::getVM(globalObject); - auto scope = DECLARE_THROW_SCOPE(vm); JSC::JSFunction* function = jsCast(callFrame->argument(0)); - return JSValue::encode(JSC::call(globalObject, function, JSC::ArgList(), "nativeFrameForTesting"_s)); } diff --git a/src/bun.js/bindings/CookieMap.cpp b/src/bun.js/bindings/CookieMap.cpp index 00e030d9af..f2adb476b4 100644 --- a/src/bun.js/bindings/CookieMap.cpp +++ b/src/bun.js/bindings/CookieMap.cpp @@ -12,9 +12,12 @@ namespace WebCore { template void CookieMap__writeFetchHeadersToUWSResponse(CookieMap* cookie_map, JSC::JSGlobalObject* global_this, uWS::HttpResponse* res) { + auto& vm = JSC::getVM(global_this); + auto scope = DECLARE_THROW_SCOPE(vm); // Loop over modified cookies and write Set-Cookie headers to the response for (auto& cookie : cookie_map->getAllChanges()) { auto utf8 = cookie->toString(global_this->vm()).utf8(); + RETURN_IF_EXCEPTION(scope, ); res->writeHeader("Set-Cookie", utf8.data()); } } diff --git a/src/bun.js/bindings/FetchHeaders.zig b/src/bun.js/bindings/FetchHeaders.zig index 9a40666669..91a1747acc 100644 --- a/src/bun.js/bindings/FetchHeaders.zig +++ b/src/bun.js/bindings/FetchHeaders.zig @@ -56,19 +56,16 @@ pub const FetchHeaders = opaque { /// Throws an exception if invalid. /// /// If empty, returns null. - pub fn createFromJS( - global: *JSGlobalObject, - value: JSValue, - ) ?*FetchHeaders { - return WebCore__FetchHeaders__createFromJS(global, value); + pub fn createFromJS(global: *JSGlobalObject, value: JSValue) bun.JSError!?*FetchHeaders { + return bun.jsc.fromJSHostCallGeneric(global, @src(), WebCore__FetchHeaders__createFromJS, .{ global, value }); } - pub fn putDefault(this: *FetchHeaders, name_: HTTPHeaderName, value: []const u8, global: *JSGlobalObject) void { + pub fn putDefault(this: *FetchHeaders, name_: HTTPHeaderName, value: []const u8, global: *JSGlobalObject) bun.JSError!void { if (this.fastHas(name_)) { return; } - this.put(name_, value, global); + try this.put(name_, value, global); } pub fn from( @@ -157,8 +154,8 @@ pub const FetchHeaders = opaque { name_: HTTPHeaderName, value: []const u8, global: *JSGlobalObject, - ) void { - WebCore__FetchHeaders__put(this, name_, &ZigString.init(value), global); + ) bun.JSError!void { + return bun.jsc.fromJSHostCallGeneric(global, @src(), WebCore__FetchHeaders__put, .{ this, name_, &ZigString.init(value), global }); } pub fn get_( @@ -405,11 +402,8 @@ pub const FetchHeaders = opaque { pub fn cloneThis( this: *FetchHeaders, global: *JSGlobalObject, - ) ?*FetchHeaders { - return WebCore__FetchHeaders__cloneThis( - this, - global, - ); + ) bun.JSError!?*FetchHeaders { + return bun.jsc.fromJSHostCallGeneric(global, @src(), WebCore__FetchHeaders__cloneThis, .{ this, global }); } pub fn deref( diff --git a/src/bun.js/bindings/JSBunRequest.cpp b/src/bun.js/bindings/JSBunRequest.cpp index d93c7480c8..1e5fecfb54 100644 --- a/src/bun.js/bindings/JSBunRequest.cpp +++ b/src/bun.js/bindings/JSBunRequest.cpp @@ -71,10 +71,13 @@ extern "C" void* Request__clone(void* internalZigRequestPointer, JSGlobalObject* JSBunRequest* JSBunRequest::clone(JSC::VM& vm, JSGlobalObject* globalObject) { - auto throwScope = DECLARE_THROW_SCOPE(globalObject->vm()); + auto throwScope = DECLARE_THROW_SCOPE(vm); auto* structure = createJSBunRequestStructure(vm, defaultGlobalObject(globalObject)); - auto* clone = this->create(vm, structure, Request__clone(this->wrapped(), globalObject), nullptr); + auto* raw = Request__clone(this->wrapped(), globalObject); + EXCEPTION_ASSERT(!!raw == !throwScope.exception()); + RETURN_IF_EXCEPTION(throwScope, nullptr); + auto* clone = this->create(vm, structure, raw, nullptr); // Cookies and params are deep copied as they can be changed between the clone and original if (auto* params = this->params()) { @@ -85,6 +88,7 @@ JSBunRequest* JSBunRequest::clone(JSC::VM& vm, JSGlobalObject* globalObject) auto propertyNames = PropertyNameArray(vm, JSC::PropertyNameMode::Strings, JSC::PrivateSymbolMode::Exclude); JSObject::getOwnPropertyNames(params, globalObject, propertyNames, JSC::DontEnumPropertiesMode::Exclude); + RETURN_IF_EXCEPTION(throwScope, nullptr); for (auto& property : propertyNames) { auto value = params->get(globalObject, property); @@ -217,8 +221,7 @@ JSC_DEFINE_CUSTOM_GETTER(jsJSBunRequestGetCookies, (JSC::JSGlobalObject * global JSC::JSValue headersValue = request->get(globalObject, names.headersPublicName()); RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); auto* headers = jsDynamicCast(headersValue); - if (!headers) - return JSValue::encode(jsUndefined()); + if (!headers) return JSValue::encode(jsUndefined()); auto& fetchHeaders = headers->wrapped(); @@ -256,8 +259,8 @@ JSC_DEFINE_HOST_FUNCTION(jsJSBunRequestClone, (JSC::JSGlobalObject * globalObjec } auto clone = request->clone(vm, globalObject); - - RELEASE_AND_RETURN(throwScope, JSValue::encode(clone)); + RETURN_IF_EXCEPTION(throwScope, {}); + return JSValue::encode(clone); } Structure* createJSBunRequestStructure(JSC::VM& vm, Zig::GlobalObject* globalObject) diff --git a/src/bun.js/bindings/JSBundlerPlugin.cpp b/src/bun.js/bindings/JSBundlerPlugin.cpp index 799f731ec6..89f287bc91 100644 --- a/src/bun.js/bindings/JSBundlerPlugin.cpp +++ b/src/bun.js/bindings/JSBundlerPlugin.cpp @@ -579,7 +579,7 @@ extern "C" Bun::JSBundlerPlugin* JSBundlerPlugin__create(Zig::GlobalObject* glob extern "C" JSC::EncodedJSValue JSBundlerPlugin__loadAndResolvePluginsForServe(Bun::JSBundlerPlugin* plugin, JSC::EncodedJSValue encodedPlugins, JSC::EncodedJSValue encodedBunfigFolder) { auto& vm = plugin->vm(); - auto scope = DECLARE_CATCH_SCOPE(vm); + auto scope = DECLARE_THROW_SCOPE(vm); auto* loadAndResolvePluginsForServeBuiltinFn = JSC::JSFunction::create(vm, plugin->globalObject(), WebCore::bundlerPluginLoadAndResolvePluginsForServeCodeGenerator(vm), plugin->globalObject()); @@ -594,7 +594,7 @@ extern "C" JSC::EncodedJSValue JSBundlerPlugin__loadAndResolvePluginsForServe(Bu arguments.append(JSValue::decode(encodedBunfigFolder)); arguments.append(runSetupFn); - return JSC::JSValue::encode(JSC::profiledCall(plugin->globalObject(), ProfilingReason::API, loadAndResolvePluginsForServeBuiltinFn, callData, plugin, arguments)); + RELEASE_AND_RETURN(scope, JSC::JSValue::encode(JSC::profiledCall(plugin->globalObject(), ProfilingReason::API, loadAndResolvePluginsForServeBuiltinFn, callData, plugin, arguments))); } extern "C" JSC::EncodedJSValue JSBundlerPlugin__runSetupFunction( @@ -606,7 +606,7 @@ extern "C" JSC::EncodedJSValue JSBundlerPlugin__runSetupFunction( JSC::EncodedJSValue encodedIsBake) { auto& vm = plugin->vm(); - auto scope = DECLARE_CATCH_SCOPE(vm); + auto scope = DECLARE_THROW_SCOPE(vm); auto* setupFunction = jsCast(plugin->setupFunction.get(plugin)); if (!setupFunction) [[unlikely]] @@ -624,7 +624,9 @@ extern "C" JSC::EncodedJSValue JSBundlerPlugin__runSetupFunction( arguments.append(JSValue::decode(encodedIsBake)); auto* lexicalGlobalObject = jsCast(JSValue::decode(encodedSetupFunction))->globalObject(); - return JSC::JSValue::encode(JSC::profiledCall(lexicalGlobalObject, ProfilingReason::API, setupFunction, callData, plugin, arguments)); + auto result = JSC::profiledCall(lexicalGlobalObject, ProfilingReason::API, setupFunction, callData, plugin, arguments); + RETURN_IF_EXCEPTION(scope, {}); // should be able to use RELEASE_AND_RETURN, no? observed it returning undefined with exception active + return JSValue::encode(result); } extern "C" void JSBundlerPlugin__setConfig(Bun::JSBundlerPlugin* plugin, void* config) diff --git a/src/bun.js/bindings/JSCommonJSModule.cpp b/src/bun.js/bindings/JSCommonJSModule.cpp index db249ff9f7..2b469c502f 100644 --- a/src/bun.js/bindings/JSCommonJSModule.cpp +++ b/src/bun.js/bindings/JSCommonJSModule.cpp @@ -977,35 +977,32 @@ void populateESMExports( // it to something that does NOT evaluate to "true" I could find were in // unit tests of build tools. Happy to revisit this if users file an issue. bool needsToAssignDefault = true; + auto scope = DECLARE_THROW_SCOPE(vm); if (auto* exports = result.getObject()) { bool hasESModuleMarker = false; if (!ignoreESModuleAnnotation) { - auto catchScope = DECLARE_CATCH_SCOPE(vm); PropertySlot slot(exports, PropertySlot::InternalMethodType::VMInquiry, &vm); - if (exports->getPropertySlot(globalObject, esModuleMarker, slot)) { + auto has = exports->getPropertySlot(globalObject, esModuleMarker, slot); + scope.assertNoException(); + if (has) { JSValue value = slot.getValue(globalObject, esModuleMarker); + CLEAR_IF_EXCEPTION(scope); if (!value.isUndefinedOrNull()) { if (value.pureToBoolean() == TriState::True) { hasESModuleMarker = true; } } } - if (catchScope.exception()) { - catchScope.clearException(); - } } auto* structure = exports->structure(); + uint32_t size = structure->inlineSize() + structure->outOfLineSize(); exportNames.reserveCapacity(size + 2); exportValues.ensureCapacity(size + 2); - auto catchScope = DECLARE_CATCH_SCOPE(vm); - - if (catchScope.exception()) { - catchScope.clearException(); - } + CLEAR_IF_EXCEPTION(scope); if (hasESModuleMarker) { if (canPerformFastEnumeration(structure)) { @@ -1025,8 +1022,8 @@ void populateESMExports( } else { JSC::PropertyNameArray properties(vm, JSC::PropertyNameMode::Strings, JSC::PrivateSymbolMode::Exclude); exports->methodTable()->getOwnPropertyNames(exports, globalObject, properties, DontEnumPropertiesMode::Exclude); - if (catchScope.exception()) { - catchScope.clearExceptionExceptTermination(); + if (scope.exception()) [[unlikely]] { + if (!vm.hasPendingTerminationException()) scope.clearException(); return; } @@ -1039,8 +1036,9 @@ void populateESMExports( continue; JSC::PropertySlot slot(exports, PropertySlot::InternalMethodType::Get); - if (!exports->getPropertySlot(globalObject, property, slot)) - continue; + auto has = exports->getPropertySlot(globalObject, property, slot); + RETURN_IF_EXCEPTION(scope, ); + if (!has) continue; // Allow DontEnum properties which are not getter/setters // https://github.com/oven-sh/bun/issues/4432 @@ -1056,8 +1054,8 @@ void populateESMExports( // If it throws, we keep them in the exports list, but mark it as undefined // This is consistent with what Node.js does. - if (catchScope.exception()) { - catchScope.clearException(); + if (scope.exception()) [[unlikely]] { + scope.clearException(); getterResult = jsUndefined(); } @@ -1082,8 +1080,8 @@ void populateESMExports( } else { JSC::PropertyNameArray properties(vm, JSC::PropertyNameMode::Strings, JSC::PrivateSymbolMode::Exclude); exports->methodTable()->getOwnPropertyNames(exports, globalObject, properties, DontEnumPropertiesMode::Include); - if (catchScope.exception()) { - catchScope.clearExceptionExceptTermination(); + if (scope.exception()) [[unlikely]] { + if (!vm.hasPendingTerminationException()) scope.clearException(); return; } @@ -1096,8 +1094,9 @@ void populateESMExports( continue; JSC::PropertySlot slot(exports, PropertySlot::InternalMethodType::Get); - if (!exports->getPropertySlot(globalObject, property, slot)) - continue; + auto has = exports->getPropertySlot(globalObject, property, slot); + RETURN_IF_EXCEPTION(scope, ); + if (!has) continue; if (slot.attributes() & PropertyAttribute::DontEnum) { // Allow DontEnum properties which are not getter/setters @@ -1113,8 +1112,8 @@ void populateESMExports( // If it throws, we keep them in the exports list, but mark it as undefined // This is consistent with what Node.js does. - if (catchScope.exception()) { - catchScope.clearException(); + if (scope.exception()) [[unlikely]] { + scope.clearException(); getterResult = jsUndefined(); } @@ -1138,7 +1137,7 @@ void JSCommonJSModule::toSyntheticSource(JSC::JSGlobalObject* globalObject, auto result = this->exportsObject(); RETURN_IF_EXCEPTION(scope, ); - populateESMExports(globalObject, result, exportNames, exportValues, this->ignoreESModuleAnnotation); + RELEASE_AND_RETURN(scope, populateESMExports(globalObject, result, exportNames, exportValues, this->ignoreESModuleAnnotation)); } void JSCommonJSModule::setExportsObject(JSC::JSValue exportsObject) diff --git a/src/bun.js/bindings/JSDOMFile.cpp b/src/bun.js/bindings/JSDOMFile.cpp index a69d1b66d0..f8111c4706 100644 --- a/src/bun.js/bindings/JSDOMFile.cpp +++ b/src/bun.js/bindings/JSDOMFile.cpp @@ -77,10 +77,8 @@ public: // ShadowRealm functions belong to a different global object. getFunctionRealm(lexicalGlobalObject, newTarget)); RETURN_IF_EXCEPTION(scope, {}); - structure = InternalFunction::createSubclassStructure( - lexicalGlobalObject, - newTarget, - functionGlobalObject->JSBlobStructure()); + structure = InternalFunction::createSubclassStructure(lexicalGlobalObject, newTarget, functionGlobalObject->JSBlobStructure()); + RETURN_IF_EXCEPTION(scope, {}); } void* ptr = JSDOMFile__construct(lexicalGlobalObject, callFrame); diff --git a/src/bun.js/bindings/JSEnvironmentVariableMap.cpp b/src/bun.js/bindings/JSEnvironmentVariableMap.cpp index 7c1781298f..f8e469c511 100644 --- a/src/bun.js/bindings/JSEnvironmentVariableMap.cpp +++ b/src/bun.js/bindings/JSEnvironmentVariableMap.cpp @@ -345,6 +345,7 @@ JSValue createEnvironmentVariablesMap(Zig::GlobalObject* globalObject) JSValue value = jsString(vm, Zig::toStringCopy(valueString)); RETURN_IF_EXCEPTION(scope, {}); object->putDirectIndex(globalObject, *index, value, 0, PutDirectIndexLikePutDirect); + RETURN_IF_EXCEPTION(scope, {}); } continue; } diff --git a/src/bun.js/bindings/JSGlobalObject.zig b/src/bun.js/bindings/JSGlobalObject.zig index b7dbeacbe2..68c15cdf50 100644 --- a/src/bun.js/bindings/JSGlobalObject.zig +++ b/src/bun.js/bindings/JSGlobalObject.zig @@ -243,30 +243,15 @@ pub const JSGlobalObject = opaque { pub fn runOnLoadPlugins(this: *JSGlobalObject, namespace_: bun.String, path: bun.String, target: BunPluginTarget) bun.JSError!?JSValue { JSC.markBinding(@src()); - const result = Bun__runOnLoadPlugins(this, if (namespace_.length() > 0) &namespace_ else null, &path, target); - if (this.hasException()) { - return error.JSError; - } - if (result.isEmptyOrUndefinedOrNull()) { - return null; - } - + const result = try bun.jsc.fromJSHostCall(this, @src(), Bun__runOnLoadPlugins, .{ this, if (namespace_.length() > 0) &namespace_ else null, &path, target }); + if (result.isUndefinedOrNull()) return null; return result; } pub fn runOnResolvePlugins(this: *JSGlobalObject, namespace_: bun.String, path: bun.String, source: bun.String, target: BunPluginTarget) bun.JSError!?JSValue { JSC.markBinding(@src()); - - const result = Bun__runOnResolvePlugins(this, if (namespace_.length() > 0) &namespace_ else null, &path, &source, target); - - if (this.hasException()) { - return error.JSError; - } - - if (result.isEmptyOrUndefinedOrNull()) { - return null; - } - + const result = try bun.jsc.fromJSHostCall(this, @src(), Bun__runOnResolvePlugins, .{ this, if (namespace_.length() > 0) &namespace_ else null, &path, &source, target }); + if (result.isUndefinedOrNull()) return null; return result; } @@ -468,8 +453,8 @@ pub const JSGlobalObject = opaque { pub const ctx = ref; extern fn JSC__JSGlobalObject__createAggregateError(*JSGlobalObject, [*]const JSValue, usize, *const ZigString) JSValue; - pub fn createAggregateError(globalObject: *JSGlobalObject, errors: []const JSValue, message: *const ZigString) JSValue { - return JSC__JSGlobalObject__createAggregateError(globalObject, errors.ptr, errors.len, message); + pub fn createAggregateError(globalObject: *JSGlobalObject, errors: []const JSValue, message: *const ZigString) bun.JSError!JSValue { + return bun.jsc.fromJSHostCall(globalObject, @src(), JSC__JSGlobalObject__createAggregateError, .{ globalObject, errors.ptr, errors.len, message }); } extern fn JSC__JSGlobalObject__createAggregateErrorWithArray(*JSGlobalObject, JSValue, bun.String, JSValue) JSValue; @@ -477,9 +462,9 @@ pub const JSGlobalObject = opaque { globalObject: *JSGlobalObject, message: bun.String, error_array: JSValue, - ) JSValue { + ) bun.JSError!JSValue { if (bun.Environment.allow_assert) bun.assert(error_array.isArray()); - return JSC__JSGlobalObject__createAggregateErrorWithArray(globalObject, error_array, message, .js_undefined); + return bun.jsc.fromJSHostCall(globalObject, @src(), JSC__JSGlobalObject__createAggregateErrorWithArray, .{ globalObject, error_array, message, .js_undefined }); } extern fn JSC__JSGlobalObject__generateHeapSnapshot(*JSGlobalObject) JSValue; @@ -559,8 +544,8 @@ pub const JSGlobalObject = opaque { return JSC__JSGlobalObject__vm(this); } - pub fn deleteModuleRegistryEntry(this: *JSGlobalObject, name_: *ZigString) void { - return JSC__JSGlobalObject__deleteModuleRegistryEntry(this, name_); + pub fn deleteModuleRegistryEntry(this: *JSGlobalObject, name_: *ZigString) bun.JSError!void { + return bun.jsc.fromJSHostCallGeneric(this, @src(), JSC__JSGlobalObject__deleteModuleRegistryEntry, .{ this, name_ }); } fn bunVMUnsafe(this: *JSGlobalObject) *anyopaque { @@ -608,7 +593,7 @@ pub const JSGlobalObject = opaque { extern fn JSC__JSGlobalObject__handleRejectedPromises(*JSGlobalObject) void; pub fn handleRejectedPromises(this: *JSGlobalObject) void { - return JSC__JSGlobalObject__handleRejectedPromises(this); + return bun.jsc.fromJSHostCallGeneric(this, @src(), JSC__JSGlobalObject__handleRejectedPromises, .{this}) catch @panic("unreachable"); } extern fn ZigGlobalObject__readableStreamToArrayBuffer(*JSGlobalObject, JSValue) JSValue; @@ -823,6 +808,11 @@ pub const JSGlobalObject = opaque { return JSC.VirtualMachine.reportUncaughtException(global, exception); } + pub fn reportUncaughtExceptionFromError(global: *JSGlobalObject, proof: bun.JSError) void { + JSC.markBinding(@src()); + _ = global.reportUncaughtException(global.takeException(proof).asException(global.vm()).?); + } + pub fn onCrash() callconv(.C) void { JSC.markBinding(@src()); bun.Output.flush(); diff --git a/src/bun.js/bindings/JSMockFunction.cpp b/src/bun.js/bindings/JSMockFunction.cpp index 08ef2a604b..a852d532fe 100644 --- a/src/bun.js/bindings/JSMockFunction.cpp +++ b/src/bun.js/bindings/JSMockFunction.cpp @@ -325,13 +325,20 @@ public: [](const JSC::LazyProperty::Initializer& init) { JSMockFunction* mock = init.owner; Zig::GlobalObject* globalObject = jsCast(mock->globalObject()); + auto& vm = JSC::getVM(globalObject); + auto scope = DECLARE_THROW_SCOPE(vm); JSC::Structure* structure = globalObject->mockModule.mockObjectStructure.getInitializedOnMainThread(globalObject); JSObject* object = JSC::constructEmptyObject(init.vm, structure); object->putDirectOffset(init.vm, 0, mock->getCalls()); + RETURN_IF_EXCEPTION(scope, ); object->putDirectOffset(init.vm, 1, mock->getContexts()); + RETURN_IF_EXCEPTION(scope, ); object->putDirectOffset(init.vm, 2, mock->getInstances()); + RETURN_IF_EXCEPTION(scope, ); object->putDirectOffset(init.vm, 3, mock->getReturnValues()); + RETURN_IF_EXCEPTION(scope, ); object->putDirectOffset(init.vm, 4, mock->getInvocationCallOrder()); + RETURN_IF_EXCEPTION(scope, ); init.set(object); }); } @@ -387,7 +394,8 @@ public: JSArray* val = calls.get(); if (!val) { val = JSC::constructEmptyArray(globalObject(), nullptr, 0); - // RETURN_IF_EXCEPTION + if (!val) ASSERT_PENDING_EXCEPTION(globalObject()); + if (!val) return {}; this->calls.set(vm(), this, val); } return val; @@ -397,7 +405,8 @@ public: JSArray* val = contexts.get(); if (!val) { val = JSC::constructEmptyArray(globalObject(), nullptr, 0); - // RETURN_IF_EXCEPTION + if (!val) ASSERT_PENDING_EXCEPTION(globalObject()); + if (!val) return {}; this->contexts.set(vm(), this, val); } return val; @@ -407,7 +416,8 @@ public: JSArray* val = instances.get(); if (!val) { val = JSC::constructEmptyArray(globalObject(), nullptr, 0); - // RETURN_IF_EXCEPTION + if (!val) ASSERT_PENDING_EXCEPTION(globalObject()); + if (!val) return {}; this->instances.set(vm(), this, val); } return val; @@ -417,7 +427,8 @@ public: JSArray* val = returnValues.get(); if (!val) { val = JSC::constructEmptyArray(globalObject(), nullptr, 0); - // RETURN_IF_EXCEPTION + if (!val) ASSERT_PENDING_EXCEPTION(globalObject()); + if (!val) return {}; this->returnValues.set(vm(), this, val); } return val; @@ -427,7 +438,8 @@ public: JSArray* val = invocationCallOrder.get(); if (!val) { val = JSC::constructEmptyArray(globalObject(), nullptr, 0); - // RETURN_IF_EXCEPTION + if (!val) ASSERT_PENDING_EXCEPTION(globalObject()); + if (!val) return {}; this->invocationCallOrder.set(vm(), this, val); } return val; @@ -839,6 +851,7 @@ JSC_DEFINE_HOST_FUNCTION(jsMockFunctionCall, (JSGlobalObject * lexicalGlobalObje JSC::JSArray* calls = fn->calls.get(); if (calls) { calls->push(globalObject, argumentsArray); + RETURN_IF_EXCEPTION(scope, {}); } else { JSC::ObjectInitializationScope object(vm); calls = JSC::JSArray::tryCreateUninitializedRestricted( @@ -852,6 +865,7 @@ JSC_DEFINE_HOST_FUNCTION(jsMockFunctionCall, (JSGlobalObject * lexicalGlobalObje JSC::JSArray* contexts = fn->contexts.get(); if (contexts) { contexts->push(globalObject, thisValue); + RETURN_IF_EXCEPTION(scope, {}); } else { JSC::ObjectInitializationScope object(vm); contexts = JSC::JSArray::tryCreateUninitializedRestricted( @@ -866,6 +880,7 @@ JSC_DEFINE_HOST_FUNCTION(jsMockFunctionCall, (JSGlobalObject * lexicalGlobalObje JSC::JSArray* invocationCallOrder = fn->invocationCallOrder.get(); if (invocationCallOrder) { invocationCallOrder->push(globalObject, jsNumber(invocationId)); + RETURN_IF_EXCEPTION(scope, {}); } else { JSC::ObjectInitializationScope object(vm); invocationCallOrder = JSC::JSArray::tryCreateUninitializedRestricted( @@ -880,6 +895,7 @@ JSC_DEFINE_HOST_FUNCTION(jsMockFunctionCall, (JSGlobalObject * lexicalGlobalObje auto setReturnValue = [&](JSC::JSValue value) -> void { if (auto* returnValuesArray = fn->returnValues.get()) { returnValuesArray->push(globalObject, value); + RETURN_IF_EXCEPTION(scope, {}); returnValueIndex = returnValuesArray->length() - 1; } else { JSC::ObjectInitializationScope object(vm); @@ -989,7 +1005,7 @@ JSC_DEFINE_CUSTOM_GETTER(jsMockFunctionGetter_mock, (JSC::JSGlobalObject * globa auto scope = DECLARE_THROW_SCOPE(globalObject->vm()); CHECK_IS_MOCK_FUNCTION(JSValue::decode(thisValue)) - return JSValue::encode(thisObject->mock.getInitializedOnMainThread(thisObject)); + RELEASE_AND_RETURN(scope, JSValue::encode(thisObject->mock.getInitializedOnMainThread(thisObject))); } JSC_DEFINE_CUSTOM_GETTER(jsMockFunctionGetter_protoImpl, (JSC::JSGlobalObject * globalObject, JSC::EncodedJSValue thisValue, JSC::PropertyName)) @@ -1015,8 +1031,7 @@ extern "C" JSC::EncodedJSValue JSMockFunction__getCalls(EncodedJSValue encodedVa if (auto* mock = tryJSDynamicCast(value)) { return JSValue::encode(mock->getCalls()); } - - return {}; + return encodedJSUndefined(); } extern "C" JSC::EncodedJSValue JSMockFunction__getReturns(EncodedJSValue encodedValue) { @@ -1024,8 +1039,7 @@ extern "C" JSC::EncodedJSValue JSMockFunction__getReturns(EncodedJSValue encoded if (auto* mock = tryJSDynamicCast(value)) { return JSValue::encode(mock->getReturnValues()); } - - return {}; + return encodedJSUndefined(); } JSC_DEFINE_HOST_FUNCTION(jsMockFunctionGetMockName, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callframe)) @@ -1380,6 +1394,7 @@ JSC_DEFINE_HOST_FUNCTION(jsMockFunctionWithImplementation, (JSC::JSGlobalObject arguments.append(ctx); ASSERT(!arguments.hasOverflowed()); call(globalObject, performPromiseThenFunction, callData, jsUndefined(), arguments); + RETURN_IF_EXCEPTION(scope, {}); return JSC::JSValue::encode(promise); } @@ -1472,6 +1487,7 @@ BUN_DEFINE_HOST_FUNCTION(JSMock__jsSpyOn, (JSC::JSGlobalObject * lexicalGlobalOb JSC::PropertySlot slot(object, JSC::PropertySlot::InternalMethodType::HasProperty); bool hasValue = object->getPropertySlot(globalObject, propertyKey, slot); + RETURN_IF_EXCEPTION(scope, {}); // easymode: regular property or missing property if (!hasValue || slot.isValue()) { diff --git a/src/bun.js/bindings/JSNodePerformanceHooksHistogram.cpp b/src/bun.js/bindings/JSNodePerformanceHooksHistogram.cpp index 39705d7782..4b1077ca57 100644 --- a/src/bun.js/bindings/JSNodePerformanceHooksHistogram.cpp +++ b/src/bun.js/bindings/JSNodePerformanceHooksHistogram.cpp @@ -255,6 +255,7 @@ void JSNodePerformanceHooksHistogram::getPercentiles(JSGlobalObject* globalObjec int64_t value = iter.highest_equivalent_value; JSValue jsKey = jsNumber(percentile); JSValue jsValue = JSBigInt::createFrom(globalObject, value); + RETURN_IF_EXCEPTION(scope, ); map->set(globalObject, jsKey, jsValue); RETURN_IF_EXCEPTION(scope, void()); } @@ -275,6 +276,7 @@ void JSNodePerformanceHooksHistogram::getPercentilesBigInt(JSGlobalObject* globa int64_t value = iter.highest_equivalent_value; JSValue jsKey = jsNumber(percentile); JSValue jsValue = JSBigInt::createFrom(globalObject, value); + RETURN_IF_EXCEPTION(scope, ); map->set(globalObject, jsKey, jsValue); RETURN_IF_EXCEPTION(scope, void()); } diff --git a/src/bun.js/bindings/JSNodePerformanceHooksHistogramPrototype.cpp b/src/bun.js/bindings/JSNodePerformanceHooksHistogramPrototype.cpp index e175fb6ee6..e7363a94b0 100644 --- a/src/bun.js/bindings/JSNodePerformanceHooksHistogramPrototype.cpp +++ b/src/bun.js/bindings/JSNodePerformanceHooksHistogramPrototype.cpp @@ -189,7 +189,7 @@ JSC_DEFINE_HOST_FUNCTION(jsNodePerformanceHooksHistogramProtoFuncPercentileBigIn return {}; } - return JSValue::encode(JSBigInt::createFrom(globalObject, thisObject->getPercentile(percentile))); + RELEASE_AND_RETURN(scope, JSValue::encode(JSBigInt::createFrom(globalObject, thisObject->getPercentile(percentile)))); } JSC_DEFINE_CUSTOM_GETTER(jsNodePerformanceHooksHistogramGetter_count, (JSGlobalObject * globalObject, EncodedJSValue thisValue, PropertyName)) @@ -215,7 +215,7 @@ JSC_DEFINE_CUSTOM_GETTER(jsNodePerformanceHooksHistogramGetter_countBigInt, (JSG WebCore::throwThisTypeError(*globalObject, scope, "Histogram"_s, "countBigInt"_s); return {}; } - return JSValue::encode(JSBigInt::createFrom(globalObject, thisObject->getCount())); + RELEASE_AND_RETURN(scope, JSValue::encode(JSBigInt::createFrom(globalObject, thisObject->getCount()))); } JSC_DEFINE_CUSTOM_GETTER(jsNodePerformanceHooksHistogramGetter_min, (JSGlobalObject * globalObject, EncodedJSValue thisValue, PropertyName)) @@ -251,10 +251,10 @@ JSC_DEFINE_CUSTOM_GETTER(jsNodePerformanceHooksHistogramGetter_minBigInt, (JSGlo // min returns 9223372036854776000 (as double) // minBigInt returns 9223372036854775807n (INT64_MAX) if (thisObject->getCount() == 0) { - return JSValue::encode(JSBigInt::createFrom(globalObject, INT64_MAX)); + RELEASE_AND_RETURN(scope, JSValue::encode(JSBigInt::createFrom(globalObject, INT64_MAX))); } - return JSValue::encode(JSBigInt::createFrom(globalObject, thisObject->getMin())); + RELEASE_AND_RETURN(scope, JSValue::encode(JSBigInt::createFrom(globalObject, thisObject->getMin()))); } JSC_DEFINE_CUSTOM_GETTER(jsNodePerformanceHooksHistogramGetter_max, (JSGlobalObject * globalObject, EncodedJSValue thisValue, PropertyName)) @@ -280,7 +280,7 @@ JSC_DEFINE_CUSTOM_GETTER(jsNodePerformanceHooksHistogramGetter_maxBigInt, (JSGlo WebCore::throwThisTypeError(*globalObject, scope, "Histogram"_s, "maxBigInt"_s); return {}; } - return JSValue::encode(JSBigInt::createFrom(globalObject, thisObject->getMax())); + RELEASE_AND_RETURN(scope, JSValue::encode(JSBigInt::createFrom(globalObject, thisObject->getMax()))); } JSC_DEFINE_CUSTOM_GETTER(jsNodePerformanceHooksHistogramGetter_mean, (JSGlobalObject * globalObject, EncodedJSValue thisValue, PropertyName)) @@ -332,7 +332,7 @@ JSC_DEFINE_CUSTOM_GETTER(jsNodePerformanceHooksHistogramGetter_exceedsBigInt, (J WebCore::throwThisTypeError(*globalObject, scope, "Histogram"_s, "exceedsBigInt"_s); return {}; } - return JSValue::encode(JSBigInt::createFrom(globalObject, static_cast(thisObject->getExceeds()))); + RELEASE_AND_RETURN(scope, JSValue::encode(JSBigInt::createFrom(globalObject, static_cast(thisObject->getExceeds())))); } JSC_DEFINE_CUSTOM_GETTER(jsNodePerformanceHooksHistogramGetter_percentiles, (JSGlobalObject * globalObject, EncodedJSValue thisValue, PropertyName)) diff --git a/src/bun.js/bindings/JSValue.zig b/src/bun.js/bindings/JSValue.zig index bf0019a4eb..0d1d81a9dc 100644 --- a/src/bun.js/bindings/JSValue.zig +++ b/src/bun.js/bindings/JSValue.zig @@ -22,23 +22,6 @@ pub const JSValue = enum(i64) { property_does_not_exist_on_object = 0x4, _, - /// When JavaScriptCore throws something, it returns a null cell (0). The - /// exception is set on the global object. ABI-compatible with EncodedJSValue. - pub const MaybeException = enum(backing_int) { - zero = 0, - _, - - pub fn unwrap(val: JSValue.MaybeException) JSError!JSValue { - return if (val != .zero) @enumFromInt(@intFromEnum(val)) else JSError.JSError; - } - }; - - /// This function is a migration stepping stone to JSError - /// Prefer annotating the type as `JSValue.MaybeException` - pub fn unwrapZeroToJSError(val: JSValue) JSError!JSValue { - return if (val != .zero) val else JSError.JSError; - } - pub const is_pointer = false; pub const JSType = @import("./JSType.zig").JSType; @@ -272,12 +255,12 @@ pub const JSValue = enum(i64) { extern fn Bun__Process__queueNextTick1(*JSGlobalObject, func: JSValue, JSValue) void; extern fn Bun__Process__queueNextTick2(*JSGlobalObject, func: JSValue, JSValue, JSValue) void; - pub inline fn callNextTick(function: JSValue, global: *JSGlobalObject, args: anytype) void { - switch (comptime bun.len(@as(@TypeOf(args), undefined))) { - 1 => Bun__Process__queueNextTick1(@ptrCast(global), function, args[0]), - 2 => Bun__Process__queueNextTick2(@ptrCast(global), function, args[0], args[1]), + pub inline fn callNextTick(function: JSValue, global: *JSGlobalObject, args: anytype) bun.JSError!void { + return switch (comptime bun.len(@as(@TypeOf(args), undefined))) { + 1 => bun.jsc.fromJSHostCallGeneric(global, @src(), Bun__Process__queueNextTick1, .{ global, function, args[0] }), + 2 => bun.jsc.fromJSHostCallGeneric(global, @src(), Bun__Process__queueNextTick2, .{ global, function, args[0], args[1] }), else => @compileError("needs more copy paste"), - } + }; } extern fn JSC__JSValue__jsType(this: JSValue) JSType; /// The value cannot be empty. Check `!this.isEmpty()` before calling this function @@ -529,9 +512,9 @@ pub const JSValue = enum(i64) { return JSC__JSValue__getErrorsProperty(this, globalObject); } - pub fn createBufferFromLength(globalObject: *JSGlobalObject, len: usize) JSValue { + pub fn createBufferFromLength(globalObject: *JSGlobalObject, len: usize) bun.JSError!JSValue { JSC.markBinding(@src()); - return JSBuffer__bufferFromLength(globalObject, @as(i64, @intCast(len))); + return bun.jsc.fromJSHostCall(globalObject, @src(), JSBuffer__bufferFromLength, .{ globalObject, @intCast(len) }); } pub fn jestSnapshotPrettyFormat(this: JSValue, out: *MutableString, globalObject: *JSGlobalObject) !void { @@ -669,9 +652,9 @@ pub const JSValue = enum(i64) { return JSC__JSValue__jsTDZValue(); } - pub fn className(this: JSValue, globalThis: *JSGlobalObject) ZigString { + pub fn className(this: JSValue, globalThis: *JSGlobalObject) bun.JSError!ZigString { var str = ZigString.init(""); - this.getClassName(globalThis, &str); + try this.getClassName(globalThis, &str); return str; } @@ -1040,12 +1023,12 @@ pub const JSValue = enum(i64) { } extern fn JSC__JSValue__getNameProperty(this: JSValue, global: *JSGlobalObject, ret: *ZigString) void; - pub fn getNameProperty(this: JSValue, global: *JSGlobalObject, ret: *ZigString) void { + pub fn getNameProperty(this: JSValue, global: *JSGlobalObject, ret: *ZigString) bun.JSError!void { if (this.isEmptyOrUndefinedOrNull()) { return; } - JSC__JSValue__getNameProperty(this, global, ret); + return bun.jsc.fromJSHostCallGeneric(global, @src(), JSC__JSValue__getNameProperty, .{ this, global, ret }); } extern fn JSC__JSValue__getName(JSC.JSValue, *JSC.JSGlobalObject, *bun.String) void; @@ -1056,8 +1039,9 @@ pub const JSValue = enum(i64) { } extern fn JSC__JSValue__getClassName(this: JSValue, global: *JSGlobalObject, ret: *ZigString) void; - pub fn getClassName(this: JSValue, global: *JSGlobalObject, ret: *ZigString) void { - JSC__JSValue__getClassName(this, global, ret); + // TODO: absorb this into className() + pub fn getClassName(this: JSValue, global: *JSGlobalObject, ret: *ZigString) bun.JSError!void { + return bun.jsc.fromJSHostCallGeneric(global, @src(), JSC__JSValue__getClassName, .{ this, global, ret }); } pub inline fn isCell(this: JSValue) bool { @@ -1160,8 +1144,8 @@ pub const JSValue = enum(i64) { } extern fn JSC__JSValue__fromTimevalNoTruncate(globalObject: *JSGlobalObject, nsec: i64, sec: i64) JSValue; /// This always returns a JS BigInt using std.posix.timeval from std.posix.rusage - pub fn fromTimevalNoTruncate(globalObject: *JSGlobalObject, nsec: i64, sec: i64) JSValue { - return JSC__JSValue__fromTimevalNoTruncate(globalObject, nsec, sec); + pub fn fromTimevalNoTruncate(globalObject: *JSGlobalObject, nsec: i64, sec: i64) bun.JSError!JSValue { + return bun.jsc.fromJSHostCall(globalObject, @src(), JSC__JSValue__fromTimevalNoTruncate, .{ globalObject, nsec, sec }); } extern fn JSC__JSValue__bigIntSum(globalObject: *JSGlobalObject, a: JSValue, b: JSValue) JSValue; /// Sums two JS BigInts @@ -2124,8 +2108,8 @@ pub const JSValue = enum(i64) { globalObject: *JSGlobalObject, ctx: ?*anyopaque, callback: *const fn (vm: *VM, globalObject: *JSGlobalObject, ctx: ?*anyopaque, nextValue: JSValue) callconv(.C) void, - ) void { - return JSC__JSValue__forEach(this, globalObject, ctx, callback); + ) bun.JSError!void { + return bun.jsc.fromJSHostCallGeneric(globalObject, @src(), JSC__JSValue__forEach, .{ this, globalObject, ctx, callback }); } /// Same as `forEach` but accepts a typed context struct without need for @ptrCasts @@ -2134,9 +2118,9 @@ pub const JSValue = enum(i64) { globalObject: *JSGlobalObject, ctx: anytype, callback: *const fn (vm: *VM, globalObject: *JSGlobalObject, ctx: @TypeOf(ctx), nextValue: JSValue) callconv(.C) void, - ) void { + ) bun.JSError!void { const func = @as(*const fn (vm: *VM, globalObject: *JSGlobalObject, ctx: ?*anyopaque, nextValue: JSValue) callconv(.C) void, @ptrCast(callback)); - return JSC__JSValue__forEach(this, globalObject, ctx, func); + return bun.jsc.fromJSHostCallGeneric(globalObject, @src(), JSC__JSValue__forEach, .{ this, globalObject, ctx, func }); } extern fn JSC__JSValue__isIterable(this: JSValue, globalObject: *JSGlobalObject) bool; diff --git a/src/bun.js/bindings/JSX509Certificate.cpp b/src/bun.js/bindings/JSX509Certificate.cpp index 5f343d6512..80babc33f1 100644 --- a/src/bun.js/bindings/JSX509Certificate.cpp +++ b/src/bun.js/bindings/JSX509Certificate.cpp @@ -166,9 +166,8 @@ JSC_DEFINE_HOST_FUNCTION(x509CertificateConstructorConstruct, (JSGlobalObject * auto* functionGlobalObject = defaultGlobalObject(getFunctionRealm(globalObject, newTarget.getObject())); RETURN_IF_EXCEPTION(scope, {}); - structure = InternalFunction::createSubclassStructure( - globalObject, newTarget.getObject(), functionGlobalObject->NodeVMScriptStructure()); - scope.release(); + structure = InternalFunction::createSubclassStructure(globalObject, newTarget.getObject(), functionGlobalObject->NodeVMScriptStructure()); + RETURN_IF_EXCEPTION(scope, {}); } RELEASE_AND_RETURN(scope, JSValue::encode(createX509Certificate(vm, globalObject, structure, arg))); diff --git a/src/bun.js/bindings/ModuleLoader.cpp b/src/bun.js/bindings/ModuleLoader.cpp index 10ee016ce8..d72dc75a82 100644 --- a/src/bun.js/bindings/ModuleLoader.cpp +++ b/src/bun.js/bindings/ModuleLoader.cpp @@ -228,7 +228,6 @@ OnLoadResult handleOnLoadResultNotPromise(Zig::GlobalObject* globalObject, JSC:: JSC::JSObject* object = objectValue.getObject(); if (!object) [[unlikely]] { scope.throwException(globalObject, JSC::createError(globalObject, "Expected module mock to return an object"_s)); - result.value.error = scope.exception(); scope.clearException(); result.type = OnLoadResultTypeError; @@ -246,12 +245,18 @@ OnLoadResult handleOnLoadResultNotPromise(Zig::GlobalObject* globalObject, JSC:: // If a loader is passed, we must validate it loader = BunLoaderTypeNone; - if (JSC::JSString* loaderJSString = loaderValue.toStringOrNull(globalObject)) { + JSC::JSString* loaderJSString = loaderValue.toStringOrNull(globalObject); + if (auto ex = scope.exception()) [[unlikely]] { + result.value.error = ex; + scope.clearException(); + return result; + } + if (loaderJSString) { WTF::String loaderString = loaderJSString->value(globalObject); if (loaderString == "js"_s) { loader = BunLoaderTypeJS; } else if (loaderString == "object"_s) { - return handleOnLoadObjectResult(globalObject, object); + RELEASE_AND_RETURN(scope, handleOnLoadObjectResult(globalObject, object)); } else if (loaderString == "jsx"_s) { loader = BunLoaderTypeJSX; } else if (loaderString == "ts"_s) { @@ -330,9 +335,10 @@ static JSValue handleVirtualModuleResult( bool wasModuleMock = false, JSCommonJSModule* commonJSModule = nullptr) { - auto onLoadResult = handleOnLoadResult(globalObject, virtualModuleResult, specifier, wasModuleMock); auto& vm = JSC::getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(vm); + auto onLoadResult = handleOnLoadResult(globalObject, virtualModuleResult, specifier, wasModuleMock); + RETURN_IF_EXCEPTION(scope, {}); ResolvedSourceCodeHolder sourceCodeHolder(res); const auto reject = [&](JSC::JSValue exception) -> JSValue { @@ -378,14 +384,14 @@ static JSValue handleVirtualModuleResult( case OnLoadResultTypeCode: { Bun__transpileVirtualModule(globalObject, specifier, referrer, &onLoadResult.value.sourceText.string, onLoadResult.value.sourceText.loader, res); if (!res->success) { - return reject(JSValue::decode(res->result.err.value)); + RELEASE_AND_RETURN(scope, reject(JSValue::decode(res->result.err.value))); } auto provider = Zig::SourceProvider::create(globalObject, res->result.value); return resolve(JSC::JSSourceCode::create(vm, JSC::SourceCode(provider))); } case OnLoadResultTypeError: { - return reject(onLoadResult.value.error); + RELEASE_AND_RETURN(scope, reject(onLoadResult.value.error)); } case OnLoadResultTypeObject: { @@ -394,12 +400,12 @@ static JSValue handleVirtualModuleResult( const auto& __esModuleIdentifier = vm.propertyNames->__esModule; auto esModuleValue = object->getIfPropertyExists(globalObject, __esModuleIdentifier); if (scope.exception()) [[unlikely]] { - return reject(scope.exception()); + RELEASE_AND_RETURN(scope, reject(scope.exception())); } if (esModuleValue && esModuleValue.toBoolean(globalObject)) { auto defaultValue = object->getIfPropertyExists(globalObject, vm.propertyNames->defaultKeyword); if (scope.exception()) [[unlikely]] { - return reject(scope.exception()); + RELEASE_AND_RETURN(scope, reject(scope.exception())); } if (defaultValue && !defaultValue.isUndefined()) { commonJSModule->setExportsObject(defaultValue); @@ -437,6 +443,7 @@ static JSValue handleVirtualModuleResult( arguments.append(pendingModule); ASSERT(!arguments.hasOverflowed()); JSC::profiledCall(globalObject, ProfilingReason::Microtask, performPromiseThenFunction, callData, jsUndefined(), arguments); + RETURN_IF_EXCEPTION(scope, {}); return internalPromise; } default: { @@ -458,7 +465,7 @@ extern "C" void Bun__onFulfillAsyncModule( JSC::JSInternalPromise* promise = jsCast(JSC::JSValue::decode(encodedPromiseValue)); if (!res->success) { - return promise->reject(globalObject, JSValue::decode(res->result.err.value)); + RELEASE_AND_RETURN(scope, promise->reject(globalObject, JSValue::decode(res->result.err.value))); } auto specifierValue = Bun::toJS(globalObject, *specifier); @@ -495,6 +502,7 @@ extern "C" void Bun__onFulfillAsyncModule( if (!vm.isTerminationException(exception)) { scope.clearException(); promise->reject(globalObject, exception); + scope.assertNoExceptionExceptTermination(); } } } else { @@ -655,7 +663,9 @@ JSValue fetchCommonJSModule( // When "bun test" is enabled, allow users to override builtin modules // This is important for being able to trivially mock things like the filesystem. if (isBunTest) { - if (JSC::JSValue virtualModuleResult = Bun::runVirtualModule(globalObject, &specifier, wasModuleMock)) { + JSC::JSValue virtualModuleResult = Bun::runVirtualModule(globalObject, &specifier, wasModuleMock); + RETURN_IF_EXCEPTION(scope, {}); + if (virtualModuleResult) { JSValue promiseOrCommonJSModule = handleVirtualModuleResult(globalObject, virtualModuleResult, res, &specifier, referrer, wasModuleMock, target); RETURN_IF_EXCEPTION(scope, {}); @@ -704,7 +714,9 @@ JSValue fetchCommonJSModule( // When "bun test" is NOT enabled, disable users from overriding builtin modules if (!isBunTest) { - if (JSC::JSValue virtualModuleResult = Bun::runVirtualModule(globalObject, &specifier, wasModuleMock)) { + JSC::JSValue virtualModuleResult = Bun::runVirtualModule(globalObject, &specifier, wasModuleMock); + RETURN_IF_EXCEPTION(scope, {}); + if (virtualModuleResult) { JSValue promiseOrCommonJSModule = handleVirtualModuleResult(globalObject, virtualModuleResult, res, &specifier, referrer, wasModuleMock, target); RETURN_IF_EXCEPTION(scope, {}); @@ -922,8 +934,10 @@ static JSValue fetchESMSourceCode( // When "bun test" is enabled, allow users to override builtin modules // This is important for being able to trivially mock things like the filesystem. if (isBunTest) { - if (JSC::JSValue virtualModuleResult = Bun::runVirtualModule(globalObject, specifier, wasModuleMock)) { - return handleVirtualModuleResult(globalObject, virtualModuleResult, res, specifier, referrer, wasModuleMock); + JSC::JSValue virtualModuleResult = Bun::runVirtualModule(globalObject, specifier, wasModuleMock); + RETURN_IF_EXCEPTION(scope, {}); + if (virtualModuleResult) { + RELEASE_AND_RETURN(scope, handleVirtualModuleResult(globalObject, virtualModuleResult, res, specifier, referrer, wasModuleMock)); } } @@ -932,7 +946,7 @@ static JSValue fetchESMSourceCode( throwException(scope, res->result.err, globalObject); auto* exception = scope.exception(); scope.clearException(); - return reject(exception); + RELEASE_AND_RETURN(scope, reject(exception)); } // This can happen if it's a `bun build --compile`'d CommonJS file @@ -986,8 +1000,10 @@ static JSValue fetchESMSourceCode( // When "bun test" is NOT enabled, disable users from overriding builtin modules if (!isBunTest) { - if (JSC::JSValue virtualModuleResult = Bun::runVirtualModule(globalObject, specifier, wasModuleMock)) { - return handleVirtualModuleResult(globalObject, virtualModuleResult, res, specifier, referrer, wasModuleMock); + JSC::JSValue virtualModuleResult = Bun::runVirtualModule(globalObject, specifier, wasModuleMock); + RETURN_IF_EXCEPTION(scope, {}); + if (virtualModuleResult) { + RELEASE_AND_RETURN(scope, handleVirtualModuleResult(globalObject, virtualModuleResult, res, specifier, referrer, wasModuleMock)); } } @@ -1021,7 +1037,7 @@ static JSValue fetchESMSourceCode( throwException(scope, res->result.err, globalObject); auto* exception = scope.exception(); scope.clearException(); - return reject(exception); + RELEASE_AND_RETURN(scope, reject(exception)); } // The JSONForObjectLoader tag is source code returned from Bun that needs @@ -1041,7 +1057,7 @@ static JSValue fetchESMSourceCode( if (scope.exception()) [[unlikely]] { auto* exception = scope.exception(); scope.clearException(); - return reject(exception); + RELEASE_AND_RETURN(scope, reject(exception)); } // JSON can become strings, null, numbers, booleans so we must handle "export default 123" @@ -1058,7 +1074,7 @@ static JSValue fetchESMSourceCode( else if (res->result.value.tag == SyntheticModuleType::ExportsObject) { JSC::JSValue value = JSC::JSValue::decode(res->result.value.jsvalue_for_export); if (!value) { - return reject(JSC::createSyntaxError(globalObject, "Failed to parse Object"_s)); + RELEASE_AND_RETURN(scope, reject(JSC::createSyntaxError(globalObject, "Failed to parse Object"_s))); } // JSON can become strings, null, numbers, booleans so we must handle "export default 123" @@ -1073,7 +1089,7 @@ static JSValue fetchESMSourceCode( } else if (res->result.value.tag == SyntheticModuleType::ExportDefaultObject) { JSC::JSValue value = JSC::JSValue::decode(res->result.value.jsvalue_for_export); if (!value) { - return reject(JSC::createSyntaxError(globalObject, "Failed to parse Object"_s)); + RELEASE_AND_RETURN(scope, reject(JSC::createSyntaxError(globalObject, "Failed to parse Object"_s))); } // JSON can become strings, null, numbers, booleans so we must handle "export default 123" @@ -1136,12 +1152,12 @@ BUN_DEFINE_HOST_FUNCTION(jsFunctionOnLoadObjectResultResolve, (JSC::JSGlobalObje bool wasModuleMock = pendingModule->wasModuleMock; JSC::JSValue result = handleVirtualModuleResult(reinterpret_cast(globalObject), objectResult, &res, &specifier, &referrer, wasModuleMock); + if (scope.exception()) [[unlikely]] { + auto retValue = JSValue::encode(promise->rejectWithCaughtException(globalObject, scope)); + pendingModule->internalField(2).set(vm, pendingModule, JSC::jsUndefined()); + return retValue; + } if (res.success) { - if (scope.exception()) [[unlikely]] { - auto retValue = JSValue::encode(promise->rejectWithCaughtException(globalObject, scope)); - pendingModule->internalField(2).set(vm, pendingModule, JSC::jsUndefined()); - return retValue; - } scope.release(); promise->resolve(globalObject, result); pendingModule->internalField(2).set(vm, pendingModule, JSC::jsUndefined()); diff --git a/src/bun.js/bindings/NodeDirent.cpp b/src/bun.js/bindings/NodeDirent.cpp index 04a339cc14..d4d7fae7a0 100644 --- a/src/bun.js/bindings/NodeDirent.cpp +++ b/src/bun.js/bindings/NodeDirent.cpp @@ -177,9 +177,8 @@ JSC_DEFINE_HOST_FUNCTION(constructDirent, (JSC::JSGlobalObject * globalObject, J auto* functionGlobalObject = defaultGlobalObject(getFunctionRealm(globalObject, newTarget.getObject())); RETURN_IF_EXCEPTION(scope, {}); - structure = InternalFunction::createSubclassStructure( - globalObject, newTarget.getObject(), functionGlobalObject->m_JSDirentClassStructure.get(functionGlobalObject)); - scope.release(); + structure = InternalFunction::createSubclassStructure(globalObject, newTarget.getObject(), functionGlobalObject->m_JSDirentClassStructure.get(functionGlobalObject)); + RETURN_IF_EXCEPTION(scope, {}); } auto* object = JSC::JSFinalObject::create(vm, structure); diff --git a/src/bun.js/bindings/NodeFSStatBinding.cpp b/src/bun.js/bindings/NodeFSStatBinding.cpp index 382bdefc42..3ca16d8abe 100644 --- a/src/bun.js/bindings/NodeFSStatBinding.cpp +++ b/src/bun.js/bindings/NodeFSStatBinding.cpp @@ -826,10 +826,8 @@ inline JSValue constructJSStatsObject(JSC::JSGlobalObject* lexicalGlobalObject, // ShadowRealm functions belong to a different global object. getFunctionRealm(lexicalGlobalObject, newTarget)); RETURN_IF_EXCEPTION(scope, {}); - structure = InternalFunction::createSubclassStructure( - lexicalGlobalObject, - newTarget, - getStructure(functionGlobalObject)); + structure = InternalFunction::createSubclassStructure(lexicalGlobalObject, newTarget, getStructure(functionGlobalObject)); + RETURN_IF_EXCEPTION(scope, {}); } JSValue dev = callFrame->argument(0); diff --git a/src/bun.js/bindings/NodeFSStatFSBinding.cpp b/src/bun.js/bindings/NodeFSStatFSBinding.cpp index d768ed9596..8e3040ea57 100644 --- a/src/bun.js/bindings/NodeFSStatFSBinding.cpp +++ b/src/bun.js/bindings/NodeFSStatFSBinding.cpp @@ -373,10 +373,8 @@ inline JSValue constructJSStatFSObject(JSC::JSGlobalObject* lexicalGlobalObject, // ShadowRealm functions belong to a different global object. getFunctionRealm(lexicalGlobalObject, newTarget)); RETURN_IF_EXCEPTION(scope, {}); - structure = InternalFunction::createSubclassStructure( - lexicalGlobalObject, - newTarget, - getStatFSStructure(functionGlobalObject)); + structure = InternalFunction::createSubclassStructure(lexicalGlobalObject, newTarget, getStatFSStructure(functionGlobalObject)); + RETURN_IF_EXCEPTION(scope, {}); } JSValue type = callFrame->argument(0); diff --git a/src/bun.js/bindings/NodeHTTP.cpp b/src/bun.js/bindings/NodeHTTP.cpp index 710118e86a..963745ed05 100644 --- a/src/bun.js/bindings/NodeHTTP.cpp +++ b/src/bun.js/bindings/NodeHTTP.cpp @@ -1348,7 +1348,7 @@ JSC_DEFINE_HOST_FUNCTION(jsHTTPGetHeader, (JSGlobalObject * globalObject, CallFr const auto name = nameString->view(globalObject); RETURN_IF_EXCEPTION(scope, {}); if (WTF::equalIgnoringASCIICase(name, "set-cookie"_s)) { - return fetchHeadersGetSetCookie(globalObject, vm, impl); + RELEASE_AND_RETURN(scope, fetchHeadersGetSetCookie(globalObject, vm, impl)); } WebCore::ExceptionOr res = impl->get(name); diff --git a/src/bun.js/bindings/NodeVMScript.cpp b/src/bun.js/bindings/NodeVMScript.cpp index 2f76e172f9..e176d30b91 100644 --- a/src/bun.js/bindings/NodeVMScript.cpp +++ b/src/bun.js/bindings/NodeVMScript.cpp @@ -122,9 +122,8 @@ constructScript(JSGlobalObject* globalObject, CallFrame* callFrame, JSValue newT auto* functionGlobalObject = defaultGlobalObject(getFunctionRealm(globalObject, newTarget.getObject())); RETURN_IF_EXCEPTION(scope, {}); - structure = InternalFunction::createSubclassStructure( - globalObject, newTarget.getObject(), functionGlobalObject->NodeVMScriptStructure()); - scope.release(); + structure = InternalFunction::createSubclassStructure(globalObject, newTarget.getObject(), functionGlobalObject->NodeVMScriptStructure()); + RETURN_IF_EXCEPTION(scope, {}); } RefPtr fetcher(NodeVMScriptFetcher::create(vm, importer, jsUndefined())); diff --git a/src/bun.js/bindings/NodeVMSourceTextModule.cpp b/src/bun.js/bindings/NodeVMSourceTextModule.cpp index 977f9c7abc..0f0b2d8893 100644 --- a/src/bun.js/bindings/NodeVMSourceTextModule.cpp +++ b/src/bun.js/bindings/NodeVMSourceTextModule.cpp @@ -386,7 +386,6 @@ RefPtr NodeVMSourceTextModule::bytecode(JSGlobalObject* globalOb ModuleProgramExecutable* executable = ModuleProgramExecutable::tryCreate(globalObject, m_sourceCode); RETURN_IF_EXCEPTION(scope, nullptr); if (!executable) { - EXCEPTION_ASSERT(!scope.exception()); throwSyntaxError(globalObject, scope, "Failed to create cached executable"_s); return nullptr; } diff --git a/src/bun.js/bindings/ObjectBindings.cpp b/src/bun.js/bindings/ObjectBindings.cpp index aca4c7a5fd..87903aa5df 100644 --- a/src/bun.js/bindings/ObjectBindings.cpp +++ b/src/bun.js/bindings/ObjectBindings.cpp @@ -25,8 +25,9 @@ static bool getNonIndexPropertySlotPrototypePollutionMitigation(JSC::VM& vm, JSO while (true) { Structure* structure = object->structureID().decode(); if (!TypeInfo::overridesGetOwnPropertySlot(object->inlineTypeFlags())) [[likely]] { - if (object->getOwnNonIndexPropertySlot(vm, structure, propertyName, slot)) - return true; + auto has = object->getOwnNonIndexPropertySlot(vm, structure, propertyName, slot); + RETURN_IF_EXCEPTION(scope, false); + if (has) return true; } else { bool hasSlot = structure->classInfoForCells()->methodTable.getOwnPropertySlot(object, globalObject, propertyName, slot); RETURN_IF_EXCEPTION(scope, false); @@ -84,12 +85,8 @@ JSC::JSValue getIfPropertyExistsPrototypePollutionMitigation(JSC::VM& vm, JSC::J auto scope = DECLARE_THROW_SCOPE(vm); auto propertySlot = PropertySlot(object, PropertySlot::InternalMethodType::Get); auto isDefined = getNonIndexPropertySlotPrototypePollutionMitigation(vm, object, globalObject, name, propertySlot); - - if (!isDefined) { - return JSC::jsUndefined(); - } - - scope.assertNoException(); + RETURN_IF_EXCEPTION(scope, {}); + if (!isDefined) return JSC::jsUndefined(); JSValue value = propertySlot.getValue(globalObject, name); RETURN_IF_EXCEPTION(scope, {}); return value; diff --git a/src/bun.js/bindings/ProcessBindingFs.cpp b/src/bun.js/bindings/ProcessBindingFs.cpp index be0e396ff5..105ba71543 100644 --- a/src/bun.js/bindings/ProcessBindingFs.cpp +++ b/src/bun.js/bindings/ProcessBindingFs.cpp @@ -178,6 +178,7 @@ Structure* ProcessBindingFs::createStructure(VM& vm, JSGlobalObject* globalObjec void ProcessBindingFs::finishCreation(JSC::VM& vm) { + auto scope = DECLARE_THROW_SCOPE(vm); Base::finishCreation(vm); ASSERT(inherits(info())); @@ -186,9 +187,13 @@ void ProcessBindingFs::finishCreation(JSC::VM& vm) putDirect(vm, Identifier::fromString(vm, "kFsStatsFieldsNumber"_s), jsNumber(18), 0); putDirect(vm, Identifier::fromString(vm, "statValues"_s), zigGlobal->m_statValues.get(zigGlobal), 0); + RETURN_IF_EXCEPTION(scope, ); putDirect(vm, Identifier::fromString(vm, "bigintStatValues"_s), zigGlobal->m_bigintStatValues.get(zigGlobal), 0); + RETURN_IF_EXCEPTION(scope, ); putDirect(vm, Identifier::fromString(vm, "statFsValues"_s), zigGlobal->m_statFsValues.get(zigGlobal), 0); + RETURN_IF_EXCEPTION(scope, ); putDirect(vm, Identifier::fromString(vm, "bigintStatFsValues"_s), zigGlobal->m_bigintStatFsValues.get(zigGlobal), 0); + RETURN_IF_EXCEPTION(scope, ); } template diff --git a/src/bun.js/bindings/ProcessBindingTTYWrap.cpp b/src/bun.js/bindings/ProcessBindingTTYWrap.cpp index 2b13975d21..f97aa42103 100644 --- a/src/bun.js/bindings/ProcessBindingTTYWrap.cpp +++ b/src/bun.js/bindings/ProcessBindingTTYWrap.cpp @@ -221,7 +221,9 @@ JSC_DEFINE_HOST_FUNCTION(jsTTYSetMode, (JSC::JSGlobalObject * globalObject, Call RETURN_IF_EXCEPTION(scope, {}); // Nodejs does not throw when ttySetMode fails. An Error event is emitted instead. - int err = Bun__ttySetMode(fdToUse, mode.toInt32(globalObject)); + int mode_ = mode.toInt32(globalObject); + RETURN_IF_EXCEPTION(scope, {}); + int err = Bun__ttySetMode(fdToUse, mode_); return JSValue::encode(jsNumber(err)); #endif } diff --git a/src/bun.js/bindings/S3Error.cpp b/src/bun.js/bindings/S3Error.cpp index 8f90ab38c3..1485b617ae 100644 --- a/src/bun.js/bindings/S3Error.cpp +++ b/src/bun.js/bindings/S3Error.cpp @@ -27,18 +27,15 @@ SYSV_ABI JSC::EncodedJSValue S3Error__toErrorInstance(const S3Error* arg0, auto& vm = JSC::getVM(globalObject); - auto scope = DECLARE_THROW_SCOPE(vm); - JSC::JSValue message = JSC::jsUndefined(); + WTF::String message; if (err.message.tag != BunStringTag::Empty) { - message = Bun::toJS(globalObject, err.message); + message = err.message.toWTFString(); } auto& names = WebCore::builtinNames(vm); - JSC::JSValue options = JSC::jsUndefined(); auto prototype = defaultGlobalObject(globalObject)->m_S3ErrorStructure.getInitializedOnMainThread(globalObject); - JSC::JSObject* result = JSC::ErrorInstance::create(globalObject, prototype, message, options); - RETURN_IF_EXCEPTION(scope, {}); + JSC::JSObject* result = JSC::ErrorInstance::create(vm, prototype, message, {}); result->putDirect(vm, vm.propertyNames->name, defaultGlobalObject(globalObject)->commonStrings().s3ErrorString(globalObject), JSC::PropertyAttribute::DontEnum | 0); if (err.code.tag != BunStringTag::Empty) { JSC::JSValue code = Bun::toJS(globalObject, err.code); @@ -52,9 +49,6 @@ SYSV_ABI JSC::EncodedJSValue S3Error__toErrorInstance(const S3Error* arg0, JSC::PropertyAttribute::DontDelete | 0); } - RETURN_IF_EXCEPTION(scope, {}); - scope.release(); - return JSC::JSValue::encode(result); } } diff --git a/src/bun.js/bindings/ServerRouteList.cpp b/src/bun.js/bindings/ServerRouteList.cpp index 1061e21bc7..07a8c3557d 100644 --- a/src/bun.js/bindings/ServerRouteList.cpp +++ b/src/bun.js/bindings/ServerRouteList.cpp @@ -244,12 +244,8 @@ JSValue ServerRouteList::callRoute(Zig::GlobalObject* globalObject, uint32_t ind auto* params = paramsObjectForRoute(vm, globalObject, index, req); - JSBunRequest* request = JSBunRequest::create( - vm, - structure, - requestPtr, - params); - EXCEPTION_ASSERT(!scope.exception()); + JSBunRequest* request = JSBunRequest::create(vm, structure, requestPtr, params); + scope.assertNoException(); *requestObject = JSValue::encode(request); JSValue callback = m_routes.at(index).get(); @@ -259,7 +255,9 @@ JSValue ServerRouteList::callRoute(Zig::GlobalObject* globalObject, uint32_t ind args.append(request); args.append(serverValue); - return AsyncContextFrame::call(globalObject, callback, serverValue, args); + auto result = AsyncContextFrame::call(globalObject, callback, serverValue, args); + RETURN_IF_EXCEPTION(scope, {}); + return result; } extern "C" JSC::EncodedJSValue Bun__ServerRouteList__callRoute( diff --git a/src/bun.js/bindings/ZigGlobalObject.cpp b/src/bun.js/bindings/ZigGlobalObject.cpp index 52ad8f6c43..d87299a706 100644 --- a/src/bun.js/bindings/ZigGlobalObject.cpp +++ b/src/bun.js/bindings/ZigGlobalObject.cpp @@ -2059,20 +2059,23 @@ JSC_DEFINE_HOST_FUNCTION(isAbortSignal, (JSGlobalObject*, CallFrame* callFrame)) ASSERT(callFrame->argumentCount() == 1); return JSValue::encode(jsBoolean(callFrame->uncheckedArgument(0).inherits())); } -static inline std::optional invokeReadableStreamFunction(JSC::JSGlobalObject& lexicalGlobalObject, const JSC::Identifier& identifier, JSC::JSValue thisValue, const JSC::MarkedArgumentBuffer& arguments) +static inline std::optional invokeReadableStreamFunction(JSC::JSGlobalObject* lexicalGlobalObject, const JSC::Identifier& identifier, JSC::JSValue thisValue, const JSC::MarkedArgumentBuffer& arguments) { - JSC::VM& vm = lexicalGlobalObject.vm(); + JSC::VM& vm = lexicalGlobalObject->vm(); + auto scope = DECLARE_THROW_SCOPE(vm); JSC::JSLockHolder lock(vm); - auto function = lexicalGlobalObject.get(&lexicalGlobalObject, identifier); + auto function = lexicalGlobalObject->get(lexicalGlobalObject, identifier); + scope.assertNoExceptionExceptTermination(); + if (scope.exception()) [[unlikely]] + return {}; ASSERT(function.isCallable()); - auto scope = DECLARE_CATCH_SCOPE(vm); auto callData = JSC::getCallData(function); - auto result = call(&lexicalGlobalObject, function, callData, thisValue, arguments); + auto result = JSC::call(lexicalGlobalObject, function, callData, thisValue, arguments); #if ASSERT_ENABLED if (scope.exception()) [[unlikely]] { - Bun__reportError(&lexicalGlobalObject, JSValue::encode(scope.exception())); + Bun__reportError(lexicalGlobalObject, JSValue::encode(scope.exception())); } #endif EXCEPTION_ASSERT(!scope.exception() || vm.hasPendingTerminationException()); @@ -2085,19 +2088,22 @@ extern "C" bool ReadableStream__tee(JSC::EncodedJSValue possibleReadableStream, if (!readableStream) [[unlikely]] return false; - auto& lexicalGlobalObject = *globalObject; - auto* clientData = static_cast(lexicalGlobalObject.vm().clientData); + auto lexicalGlobalObject = globalObject; + auto& vm = JSC::getVM(lexicalGlobalObject); + auto* clientData = static_cast(vm.clientData); auto& privateName = clientData->builtinFunctions().readableStreamInternalsBuiltins().readableStreamTeePrivateName(); + auto scope = DECLARE_THROW_SCOPE(vm); MarkedArgumentBuffer arguments; arguments.append(readableStream); arguments.append(JSC::jsBoolean(true)); ASSERT(!arguments.hasOverflowed()); auto returnedValue = invokeReadableStreamFunction(lexicalGlobalObject, privateName, JSC::jsUndefined(), arguments); - if (!returnedValue) - return false; + RETURN_IF_EXCEPTION(scope, false); + if (!returnedValue) return false; - auto results = Detail::SequenceConverter::convert(lexicalGlobalObject, *returnedValue); + auto results = Detail::SequenceConverter::convert(*lexicalGlobalObject, *returnedValue); + RETURN_IF_EXCEPTION(scope, false); ASSERT(results.size() == 2); *possibleReadableStream1 = JSValue::encode(results[0]); diff --git a/src/bun.js/bindings/bindings.cpp b/src/bun.js/bindings/bindings.cpp index 2cf43fc203..03ce32e398 100644 --- a/src/bun.js/bindings/bindings.cpp +++ b/src/bun.js/bindings/bindings.cpp @@ -190,12 +190,6 @@ enum class AsymmetricMatcherConstructorType : int8_t { InstanceOf = 9, }; -#if ASSERT_ENABLED -#define ASSERT_NO_PENDING_EXCEPTION(globalObject) DECLARE_CATCH_SCOPE(globalObject->vm()).assertNoExceptionExceptTermination() -#else -#define ASSERT_NO_PENDING_EXCEPTION(globalObject) void() -#endif - // Ensure we instantiate the true and false variants of this function template bool Bun__deepMatch( JSValue objValue, @@ -1697,9 +1691,9 @@ bool Bun__deepMatch( } } } else { - if (!sameValue(globalObject, prop, subsetProp)) { - return false; - } + auto same = JSC::sameValue(globalObject, prop, subsetProp); + RETURN_IF_EXCEPTION(throwScope, false); + if (!same) return false; } } @@ -2033,8 +2027,7 @@ extern "C" void WebCore__FetchHeaders__put(WebCore::FetchHeaders* headers, HTTPH { auto throwScope = DECLARE_THROW_SCOPE(global->vm()); throwScope.assertNoException(); // can't throw an exception when there's already one. - WebCore::propagateException(*global, throwScope, - headers->set(name, Zig::toStringCopy(*arg2))); + WebCore::propagateException(*global, throwScope, headers->set(name, Zig::toStringCopy(*arg2))); } void WebCore__FetchHeaders__remove(WebCore::FetchHeaders* headers, const ZigString* arg1, JSC::JSGlobalObject* global) { @@ -2560,13 +2553,11 @@ JSC::EncodedJSValue JSC__JSGlobalObject__putCachedObject(JSC::JSGlobalObject* gl void JSC__JSGlobalObject__deleteModuleRegistryEntry(JSC::JSGlobalObject* global, ZigString* arg1) { - JSC::JSMap* map = JSC::jsDynamicCast( - global->moduleLoader()->getDirect(global->vm(), JSC::Identifier::fromString(global->vm(), "registry"_s))); - if (!map) - return; + auto& vm = global->vm(); + JSC::JSMap* map = JSC::jsDynamicCast(global->moduleLoader()->getDirect(vm, JSC::Identifier::fromString(vm, "registry"_s))); + if (!map) return; const JSC::Identifier identifier = Zig::toIdentifier(*arg1, global); - JSC::JSValue val = JSC::identifierToJSValue(global->vm(), identifier); - + JSC::JSValue val = JSC::identifierToJSValue(vm, identifier); map->remove(global, val); } @@ -3249,9 +3240,8 @@ JSC__JSModuleLoader__loadAndEvaluateModule(JSC::JSGlobalObject* globalObject, auto name = makeAtomString(arg1->toWTFString()); auto* promise = JSC::loadAndEvaluateModule(globalObject, name, JSC::jsUndefined(), JSC::jsUndefined()); - if (!promise) { - return nullptr; - } + EXCEPTION_ASSERT(!!promise == !scope.exception()); + if (!promise) return nullptr; JSC::JSNativeStdFunction* resolverFunction = JSC::JSNativeStdFunction::create( vm, globalObject, 1, String(), resolverFunctionCallback); @@ -3724,7 +3714,6 @@ bool JSC__JSValue__isIterable(JSC::EncodedJSValue JSValue, JSC::JSGlobalObject* void JSC__JSValue__forEach(JSC::EncodedJSValue JSValue0, JSC::JSGlobalObject* arg1, void* ctx, void (*ArgFn3)(JSC::VM* arg0, JSC::JSGlobalObject* arg1, void* arg2, JSC::EncodedJSValue JSValue3)) { - JSC::forEachInIterable( arg1, JSC::JSValue::decode(JSValue0), [ArgFn3, ctx](JSC::VM& vm, JSC::JSGlobalObject* global, JSC::JSValue value) -> void { @@ -3887,14 +3876,22 @@ JSC::EncodedJSValue JSC__JSValue__fromInt64NoTruncate(JSC::JSGlobalObject* globa JSC::EncodedJSValue JSC__JSValue__fromTimevalNoTruncate(JSC::JSGlobalObject* globalObject, int64_t nsec, int64_t sec) { + auto& vm = JSC::getVM(globalObject); + auto scope = DECLARE_THROW_SCOPE(vm); auto big_nsec = JSC::JSBigInt::createFrom(globalObject, nsec); + RETURN_IF_EXCEPTION(scope, {}); auto big_sec = JSC::JSBigInt::createFrom(globalObject, sec); + RETURN_IF_EXCEPTION(scope, {}); auto big_1e6 = JSC::JSBigInt::createFrom(globalObject, 1e6); + RETURN_IF_EXCEPTION(scope, {}); auto sec_as_nsec = JSC::JSBigInt::multiply(globalObject, big_1e6, big_sec); + RETURN_IF_EXCEPTION(scope, {}); ASSERT(sec_as_nsec.isHeapBigInt()); auto* big_sec_as_nsec = sec_as_nsec.asHeapBigInt(); ASSERT(big_sec_as_nsec); - return JSC::JSValue::encode(JSC::JSBigInt::add(globalObject, big_sec_as_nsec, big_nsec)); + auto result = JSC::JSBigInt::add(globalObject, big_sec_as_nsec, big_nsec); + RETURN_IF_EXCEPTION(scope, {}); + return JSC::JSValue::encode(result); } JSC::EncodedJSValue JSC__JSValue__bigIntSum(JSC::JSGlobalObject* globalObject, JSC::EncodedJSValue a, JSC::EncodedJSValue b) @@ -4736,8 +4733,9 @@ static void fromErrorInstance(ZigException* except, JSC::JSGlobalObject* global, except->message = Bun::toStringRef(err->sanitizedMessageString(global)); } else if (JSC::JSValue message = obj->getIfPropertyExists(global, vm.propertyNames->message)) { - except->message = Bun::toStringRef(global, message); + if (!scope.clearExceptionExceptTermination()) [[unlikely]] + return; } else { except->message = Bun::toStringRef(err->sanitizedMessageString(global)); @@ -4763,6 +4761,8 @@ static void fromErrorInstance(ZigException* except, JSC::JSGlobalObject* global, if (syscall) { if (syscall.isString()) { except->syscall = Bun::toStringRef(global, syscall); + if (!scope.clearExceptionExceptTermination()) [[unlikely]] + return; } } @@ -4772,6 +4772,8 @@ static void fromErrorInstance(ZigException* except, JSC::JSGlobalObject* global, if (code) { if (code.isString() || code.isNumber()) { except->system_code = Bun::toStringRef(global, code); + if (!scope.clearExceptionExceptTermination()) [[unlikely]] + return; } } @@ -4781,6 +4783,8 @@ static void fromErrorInstance(ZigException* except, JSC::JSGlobalObject* global, if (path) { if (path.isString()) { except->path = Bun::toStringRef(global, path); + if (!scope.clearExceptionExceptTermination()) [[unlikely]] + return; } } @@ -4868,6 +4872,8 @@ static void fromErrorInstance(ZigException* except, JSC::JSGlobalObject* global, if (sourceURL) { if (sourceURL.isString()) { except->stack.frames_ptr[0].source_url = Bun::toStringRef(global, sourceURL); + if (!scope.clearExceptionExceptTermination()) [[unlikely]] + return; // Take care not to make these getter calls observable. @@ -4964,8 +4970,7 @@ void exceptionFromString(ZigException* except, JSC::JSValue value, JSC::JSGlobal } if (message) { if (message.isString()) { - except->message = Bun::toStringRef( - message.toWTFString(global)); + except->message = Bun::toStringRef(message.toWTFString(global)); } } diff --git a/src/bun.js/bindings/headers-handwritten.h b/src/bun.js/bindings/headers-handwritten.h index 972c5f06df..8ebfad9daa 100644 --- a/src/bun.js/bindings/headers-handwritten.h +++ b/src/bun.js/bindings/headers-handwritten.h @@ -475,3 +475,15 @@ ALWAYS_INLINE void BunString::deref() #endif // __cplusplus #endif // HEADERS_HANDWRITTEN + +#if ASSERT_ENABLED +#define ASSERT_NO_PENDING_EXCEPTION(globalObject) DECLARE_CATCH_SCOPE(globalObject->vm()).assertNoExceptionExceptTermination() +#else +#define ASSERT_NO_PENDING_EXCEPTION(globalObject) void() +#endif + +#if ASSERT_ENABLED +#define ASSERT_PENDING_EXCEPTION(globalObject) EXCEPTION_ASSERT(!!DECLARE_CATCH_SCOPE(globalObject->vm()).exception()); +#else +#define ASSERT_PENDING_EXCEPTION(globalObject) void() +#endif diff --git a/src/bun.js/bindings/node/crypto/CryptoDhJob.cpp b/src/bun.js/bindings/node/crypto/CryptoDhJob.cpp index b5f40472d2..e0f0ea144a 100644 --- a/src/bun.js/bindings/node/crypto/CryptoDhJob.cpp +++ b/src/bun.js/bindings/node/crypto/CryptoDhJob.cpp @@ -133,8 +133,8 @@ std::optional DhJobCtx::fromJS(JSGlobalObject* globalObject, ThrowScop JSC_DEFINE_HOST_FUNCTION(jsDiffieHellman, (JSGlobalObject * lexicalGlobalObject, CallFrame* callFrame)) { - VM& vm = lexicalGlobalObject->vm(); - ThrowScope scope = DECLARE_THROW_SCOPE(vm); + auto& vm = lexicalGlobalObject->vm(); + auto scope = DECLARE_THROW_SCOPE(vm); JSValue optionsValue = callFrame->argument(0); V::validateObject(scope, lexicalGlobalObject, optionsValue, "options"_s); @@ -162,7 +162,7 @@ JSC_DEFINE_HOST_FUNCTION(jsDiffieHellman, (JSGlobalObject * lexicalGlobalObject, return ERR::CRYPTO_OPERATION_FAILED(scope, lexicalGlobalObject, "diffieHellman operation failed"_s); } - return JSValue::encode(WebCore::createBuffer(lexicalGlobalObject, ctx->m_result.span())); + RELEASE_AND_RETURN(scope, JSValue::encode(WebCore::createBuffer(lexicalGlobalObject, ctx->m_result.span()))); } } // namespace Bun diff --git a/src/bun.js/bindings/node/crypto/JSDiffieHellmanGroupConstructor.cpp b/src/bun.js/bindings/node/crypto/JSDiffieHellmanGroupConstructor.cpp index d9449c05bb..408dbc82a4 100644 --- a/src/bun.js/bindings/node/crypto/JSDiffieHellmanGroupConstructor.cpp +++ b/src/bun.js/bindings/node/crypto/JSDiffieHellmanGroupConstructor.cpp @@ -57,9 +57,8 @@ JSC_DEFINE_HOST_FUNCTION(constructDiffieHellmanGroup, (JSC::JSGlobalObject * glo auto* functionGlobalObject = defaultGlobalObject(JSC::getFunctionRealm(globalObject, newTarget.getObject())); RETURN_IF_EXCEPTION(scope, {}); - structure = JSC::InternalFunction::createSubclassStructure( - globalObject, newTarget.getObject(), functionGlobalObject->m_JSDiffieHellmanGroupClassStructure.get(functionGlobalObject)); - scope.release(); + structure = JSC::InternalFunction::createSubclassStructure(globalObject, newTarget.getObject(), functionGlobalObject->m_JSDiffieHellmanGroupClassStructure.get(functionGlobalObject)); + RETURN_IF_EXCEPTION(scope, {}); } return JSC::JSValue::encode(JSDiffieHellmanGroup::create(vm, structure, globalObject, WTFMove(dh))); diff --git a/src/bun.js/bindings/node/crypto/JSHash.cpp b/src/bun.js/bindings/node/crypto/JSHash.cpp index f93efd0757..8708a6040e 100644 --- a/src/bun.js/bindings/node/crypto/JSHash.cpp +++ b/src/bun.js/bindings/node/crypto/JSHash.cpp @@ -295,8 +295,7 @@ JSC_DEFINE_HOST_FUNCTION(constructHash, (JSC::JSGlobalObject * globalObject, JSC auto* functionGlobalObject = defaultGlobalObject(getFunctionRealm(globalObject, newTarget.getObject())); RETURN_IF_EXCEPTION(scope, {}); - structure = InternalFunction::createSubclassStructure( - globalObject, newTarget.getObject(), functionGlobalObject->m_JSHashClassStructure.get(functionGlobalObject)); + structure = InternalFunction::createSubclassStructure(globalObject, newTarget.getObject(), functionGlobalObject->m_JSHashClassStructure.get(functionGlobalObject)); RETURN_IF_EXCEPTION(scope, {}); } diff --git a/src/bun.js/bindings/node/crypto/JSHmac.cpp b/src/bun.js/bindings/node/crypto/JSHmac.cpp index 82212b7954..3af1f897c8 100644 --- a/src/bun.js/bindings/node/crypto/JSHmac.cpp +++ b/src/bun.js/bindings/node/crypto/JSHmac.cpp @@ -245,8 +245,7 @@ JSC_DEFINE_HOST_FUNCTION(constructHmac, (JSC::JSGlobalObject * globalObject, JSC auto* functionGlobalObject = defaultGlobalObject(getFunctionRealm(globalObject, newTarget.getObject())); RETURN_IF_EXCEPTION(scope, {}); - structure = InternalFunction::createSubclassStructure( - globalObject, newTarget.getObject(), functionGlobalObject->m_JSHmacClassStructure.get(functionGlobalObject)); + structure = InternalFunction::createSubclassStructure(globalObject, newTarget.getObject(), functionGlobalObject->m_JSHmacClassStructure.get(functionGlobalObject)); RETURN_IF_EXCEPTION(scope, {}); } diff --git a/src/bun.js/bindings/sqlite/JSSQLStatement.cpp b/src/bun.js/bindings/sqlite/JSSQLStatement.cpp index 38cbd9fbb3..8a059c7e66 100644 --- a/src/bun.js/bindings/sqlite/JSSQLStatement.cpp +++ b/src/bun.js/bindings/sqlite/JSSQLStatement.cpp @@ -178,6 +178,7 @@ static inline JSC::JSValue jsBigIntFromSQLite(JSC::JSGlobalObject* globalObject, #define DO_REBIND(param) \ if (param.isObject()) { \ JSC::JSValue reb = castedThis->rebind(lexicalGlobalObject, param, true, castedThis->version_db->db); \ + RETURN_IF_EXCEPTION(scope, {}); \ if (!reb.isNumber()) [[unlikely]] { \ return JSValue::encode(reb); /* this means an error */ \ } \ diff --git a/src/bun.js/bindings/v8/V8Array.cpp b/src/bun.js/bindings/v8/V8Array.cpp index 87b4b36264..9bd46d5d50 100644 --- a/src/bun.js/bindings/v8/V8Array.cpp +++ b/src/bun.js/bindings/v8/V8Array.cpp @@ -136,6 +136,7 @@ Maybe Array::Iterate(Local context, IterationCallback callback, v Local localElement = handleScope.createLocal(vm, element); CallbackResult result = callback(index, localElement, callback_data); + RETURN_IF_EXCEPTION(scope, Nothing()); switch (result) { case CallbackResult::kException: diff --git a/src/bun.js/bindings/webcore/JSCookie.cpp b/src/bun.js/bindings/webcore/JSCookie.cpp index f0873240f6..b542632559 100644 --- a/src/bun.js/bindings/webcore/JSCookie.cpp +++ b/src/bun.js/bindings/webcore/JSCookie.cpp @@ -122,9 +122,9 @@ static std::optional cookieInitFromJS(JSC::VM& vm, JSGlobalObject* l auto valueValue = optionsObj->getIfPropertyExists(lexicalGlobalObject, vm.propertyNames->value); RETURN_IF_EXCEPTION(throwScope, std::nullopt); - RETURN_IF_EXCEPTION(throwScope, std::nullopt); if (valueValue) { value = convert(*lexicalGlobalObject, valueValue); + RETURN_IF_EXCEPTION(throwScope, std::nullopt); } } @@ -198,6 +198,7 @@ static std::optional cookieInitFromJS(JSC::VM& vm, JSGlobalObject* l if (sameSiteValue) { if (!sameSiteValue.isUndefined() && !sameSiteValue.isNull()) { String sameSiteStr = convert(*lexicalGlobalObject, sameSiteValue); + RETURN_IF_EXCEPTION(throwScope, std::nullopt); if (sameSiteStr == "strict"_s) sameSite = CookieSameSite::Strict; diff --git a/src/bun.js/bindings/webcore/JSDOMFormData.cpp b/src/bun.js/bindings/webcore/JSDOMFormData.cpp index 966c990b0c..65d317ecf9 100644 --- a/src/bun.js/bindings/webcore/JSDOMFormData.cpp +++ b/src/bun.js/bindings/webcore/JSDOMFormData.cpp @@ -405,13 +405,15 @@ static inline JSC::EncodedJSValue jsDOMFormDataPrototypeFunction_getAllBody(JSC: for (auto entry : entries) { if (auto string = std::get_if(&entry)) { result->push(lexicalGlobalObject, jsString(vm, *string)); + RETURN_IF_EXCEPTION(throwScope, {}); } else { auto blob = std::get>(entry); result->push(lexicalGlobalObject, toJS(lexicalGlobalObject, castedThis->globalObject(), blob.get())); + RETURN_IF_EXCEPTION(throwScope, {}); } } - RELEASE_AND_RETURN(throwScope, JSValue::encode(result)); + return JSValue::encode(result); } JSC_DEFINE_HOST_FUNCTION(jsDOMFormDataPrototypeFunction_getAll, (JSGlobalObject * lexicalGlobalObject, CallFrame* callFrame)) diff --git a/src/bun.js/bindings/webcore/JSFetchHeaders.cpp b/src/bun.js/bindings/webcore/JSFetchHeaders.cpp index 36d65fb6db..f5d387949e 100644 --- a/src/bun.js/bindings/webcore/JSFetchHeaders.cpp +++ b/src/bun.js/bindings/webcore/JSFetchHeaders.cpp @@ -224,7 +224,7 @@ JSC_DEFINE_HOST_FUNCTION(jsFetchHeadersPrototypeFunction_getAll, (JSGlobalObject auto values = impl.getSetCookieHeaders(); unsigned count = values.size(); if (!count) { - return JSValue::encode(JSC::constructEmptyArray(lexicalGlobalObject, nullptr, 0)); + RELEASE_AND_RETURN(scope, JSValue::encode(JSC::constructEmptyArray(lexicalGlobalObject, nullptr, 0))); } MarkedArgumentBuffer strings; @@ -270,7 +270,7 @@ JSC::EncodedJSValue fetchHeadersGetSetCookie(JSC::JSGlobalObject* lexicalGlobalO unsigned count = values.size(); if (!count) { - return JSValue::encode(JSC::constructEmptyArray(lexicalGlobalObject, nullptr, 0)); + RELEASE_AND_RETURN(scope, JSValue::encode(JSC::constructEmptyArray(lexicalGlobalObject, nullptr, 0))); } JSC::JSArray* array = constructEmptyArray(lexicalGlobalObject, nullptr, count); diff --git a/src/bun.js/bindings/webcore/SerializedScriptValue.cpp b/src/bun.js/bindings/webcore/SerializedScriptValue.cpp index fa401a699e..638464c3f9 100644 --- a/src/bun.js/bindings/webcore/SerializedScriptValue.cpp +++ b/src/bun.js/bindings/webcore/SerializedScriptValue.cpp @@ -1677,7 +1677,7 @@ private: String message; PropertyDescriptor messageDescriptor; if (errorInstance->getOwnPropertyDescriptor(m_lexicalGlobalObject, vm.propertyNames->message, messageDescriptor) && messageDescriptor.isDataDescriptor()) { - EXCEPTION_ASSERT(!scope.exception()); + scope.assertNoException(); message = messageDescriptor.value().toWTFString(m_lexicalGlobalObject); } RETURN_IF_EXCEPTION(scope, false); @@ -1685,7 +1685,7 @@ private: unsigned line = 0; PropertyDescriptor lineDescriptor; if (errorInstance->getOwnPropertyDescriptor(m_lexicalGlobalObject, vm.propertyNames->line, lineDescriptor) && lineDescriptor.isDataDescriptor()) { - EXCEPTION_ASSERT(!scope.exception()); + scope.assertNoException(); line = lineDescriptor.value().toNumber(m_lexicalGlobalObject); } RETURN_IF_EXCEPTION(scope, false); @@ -1693,7 +1693,7 @@ private: unsigned column = 0; PropertyDescriptor columnDescriptor; if (errorInstance->getOwnPropertyDescriptor(m_lexicalGlobalObject, vm.propertyNames->column, columnDescriptor) && columnDescriptor.isDataDescriptor()) { - EXCEPTION_ASSERT(!scope.exception()); + scope.assertNoException(); column = columnDescriptor.value().toNumber(m_lexicalGlobalObject); } RETURN_IF_EXCEPTION(scope, false); @@ -1701,7 +1701,7 @@ private: String sourceURL; PropertyDescriptor sourceURLDescriptor; if (errorInstance->getOwnPropertyDescriptor(m_lexicalGlobalObject, vm.propertyNames->sourceURL, sourceURLDescriptor) && sourceURLDescriptor.isDataDescriptor()) { - EXCEPTION_ASSERT(!scope.exception()); + scope.assertNoException(); sourceURL = sourceURLDescriptor.value().toWTFString(m_lexicalGlobalObject); } RETURN_IF_EXCEPTION(scope, false); @@ -1709,7 +1709,7 @@ private: String stack; PropertyDescriptor stackDescriptor; if (errorInstance->getOwnPropertyDescriptor(m_lexicalGlobalObject, vm.propertyNames->stack, stackDescriptor) && stackDescriptor.isDataDescriptor()) { - EXCEPTION_ASSERT(!scope.exception()); + scope.assertNoException(); stack = stackDescriptor.value().toWTFString(m_lexicalGlobalObject); } RETURN_IF_EXCEPTION(scope, false); diff --git a/src/bun.js/event_loop/Task.zig b/src/bun.js/event_loop/Task.zig index 4e43fe5c94..3e3733d0d8 100644 --- a/src/bun.js/event_loop/Task.zig +++ b/src/bun.js/event_loop/Task.zig @@ -466,7 +466,7 @@ pub fn tickQueueWithCount(this: *EventLoop, virtual_machine: *VirtualMachine) u3 }, @field(Task.Tag, @typeName(RuntimeTranspilerStore)) => { var any: *RuntimeTranspilerStore = task.get(RuntimeTranspilerStore).?; - any.drain() catch {}; + any.runFromJSThread(); }, @field(Task.Tag, @typeName(ServerAllConnectionsClosedTask)) => { var any: *ServerAllConnectionsClosedTask = task.get(ServerAllConnectionsClosedTask).?; diff --git a/src/bun.js/ipc.zig b/src/bun.js/ipc.zig index d51d7b23d2..6702fa9aa4 100644 --- a/src/bun.js/ipc.zig +++ b/src/bun.js/ipc.zig @@ -354,14 +354,14 @@ pub const CallbackList = union(enum) { .ack_nack => {}, .none => {}, .callback => { - self.callback.callNextTick(global, .{.null}); + try self.callback.callNextTick(global, .{.null}); self.callback.unprotect(); self.* = .none; }, .callback_array => { var iter = try self.callback_array.arrayIterator(global); while (try iter.next()) |item| { - item.callNextTick(global, .{.null}); + try item.callNextTick(global, .{.null}); } self.callback_array.unprotect(); self.* = .none; @@ -925,12 +925,12 @@ fn emitProcessErrorEvent(globalThis: *JSGlobalObject, callframe: *JSC.CallFrame) const FromEnum = enum { subprocess_exited, subprocess, process }; fn doSendErr(globalObject: *JSC.JSGlobalObject, callback: JSC.JSValue, ex: JSC.JSValue, from: FromEnum) bun.JSError!JSC.JSValue { if (callback.isCallable()) { - callback.callNextTick(globalObject, .{ex}); + try callback.callNextTick(globalObject, .{ex}); return .false; } if (from == .process) { const target = JSC.JSFunction.create(globalObject, bun.String.empty, emitProcessErrorEvent, 1, .{}); - target.callNextTick(globalObject, .{ex}); + try target.callNextTick(globalObject, .{ex}); return .false; } // Bun.spawn().send() should throw an error (unless callback is passed) diff --git a/src/bun.js/jsc/host_fn.zig b/src/bun.js/jsc/host_fn.zig index caa2556089..7a48bd8b7f 100644 --- a/src/bun.js/jsc/host_fn.zig +++ b/src/bun.js/jsc/host_fn.zig @@ -120,6 +120,7 @@ pub fn fromJSHostCall( defer scope.deinit(); const value = @call(.auto, function, args); + if (@TypeOf(value) != JSValue) @compileError("fromJSHostCall only supports JSValue"); scope.assertExceptionPresenceMatches(value == .zero); return if (value == .zero) error.JSError else value; } diff --git a/src/bun.js/modules/BunJSCModule.h b/src/bun.js/modules/BunJSCModule.h index b84053a6e5..e5aed312d2 100644 --- a/src/bun.js/modules/BunJSCModule.h +++ b/src/bun.js/modules/BunJSCModule.h @@ -644,9 +644,7 @@ JSC_DEFINE_HOST_FUNCTION(functionRunProfiler, (JSGlobalObject * globalObject, Ca auto throwScope = DECLARE_THROW_SCOPE(vm); if (callbackValue.isUndefinedOrNull() || !callbackValue.isCallable()) { - throwException( - globalObject, throwScope, - createTypeError(globalObject, "First argument must be a function."_s)); + throwException(globalObject, throwScope, createTypeError(globalObject, "First argument must be a function."_s)); return JSValue::encode(JSValue {}); } @@ -654,8 +652,7 @@ JSC_DEFINE_HOST_FUNCTION(functionRunProfiler, (JSGlobalObject * globalObject, Ca if (sampleValue.isNumber()) { unsigned sampleInterval = sampleValue.toUInt32(globalObject); - samplingProfiler.setTimingInterval( - Seconds::fromMicroseconds(sampleInterval)); + samplingProfiler.setTimingInterval(Seconds::fromMicroseconds(sampleInterval)); } const auto report = [](JSC::VM& vm, @@ -669,19 +666,15 @@ JSC_DEFINE_HOST_FUNCTION(functionRunProfiler, (JSGlobalObject * globalObject, Ca StringPrintStream byteCodes; samplingProfiler.reportTopBytecodes(byteCodes); - JSValue stackTraces = JSONParse( - globalObject, samplingProfiler.stackTracesAsJSON()->toJSONString()); + JSValue stackTraces = JSONParse(globalObject, samplingProfiler.stackTracesAsJSON()->toJSONString()); samplingProfiler.shutdown(); RETURN_IF_EXCEPTION(throwScope, {}); JSObject* result = constructEmptyObject(globalObject, globalObject->objectPrototype(), 3); - result->putDirect(vm, Identifier::fromString(vm, "functions"_s), - jsString(vm, topFunctions.toString())); - result->putDirect(vm, Identifier::fromString(vm, "bytecodes"_s), - jsString(vm, byteCodes.toString())); - result->putDirect(vm, Identifier::fromString(vm, "stackTraces"_s), - stackTraces); + result->putDirect(vm, Identifier::fromString(vm, "functions"_s), jsString(vm, topFunctions.toString())); + result->putDirect(vm, Identifier::fromString(vm, "bytecodes"_s), jsString(vm, byteCodes.toString())); + result->putDirect(vm, Identifier::fromString(vm, "stackTraces"_s), stackTraces); return result; }; @@ -712,8 +705,7 @@ JSC_DEFINE_HOST_FUNCTION(functionRunProfiler, (JSGlobalObject * globalObject, Ca JSNativeStdFunction* resolve = JSNativeStdFunction::create( vm, globalObject, 0, "resolve"_s, [report](JSGlobalObject* globalObject, CallFrame* callFrame) { - return JSValue::encode(JSPromise::resolvedPromise( - globalObject, report(globalObject->vm(), globalObject))); + return JSValue::encode(JSPromise::resolvedPromise(globalObject, report(globalObject->vm(), globalObject))); }); JSNativeStdFunction* reject = JSNativeStdFunction::create( vm, globalObject, 0, "reject"_s, @@ -724,8 +716,8 @@ JSC_DEFINE_HOST_FUNCTION(functionRunProfiler, (JSGlobalObject * globalObject, Ca throwException(globalObject, scope, error.value()); return JSValue::encode({}); }); - promise->performPromiseThen(globalObject, resolve, reject, - afterOngoingPromiseCapability); + promise->performPromiseThen(globalObject, resolve, reject, afterOngoingPromiseCapability); + RETURN_IF_EXCEPTION(throwScope, {}); return JSValue::encode(afterOngoingPromiseCapability); } diff --git a/src/bun.js/modules/NodeUtilTypesModule.cpp b/src/bun.js/modules/NodeUtilTypesModule.cpp index b81df54226..5dc76db0a0 100644 --- a/src/bun.js/modules/NodeUtilTypesModule.cpp +++ b/src/bun.js/modules/NodeUtilTypesModule.cpp @@ -125,9 +125,9 @@ JSC_DEFINE_HOST_FUNCTION(jsFunctionIsError, // https://github.com/nodejs/node/blob/cf8c6994e0f764af02da4fa70bc5962142181bf3/doc/api/util.md#L2923 // util.isError is deprecated and removed in node 23 PropertySlot slot(object, PropertySlot::InternalMethodType::VMInquiry, &vm); - if (object->getPropertySlot(globalObject, - vm.propertyNames->toStringTagSymbol, slot)) { - EXCEPTION_ASSERT(!scope.exception()); + bool has = object->getPropertySlot(globalObject, vm.propertyNames->toStringTagSymbol, slot); + scope.assertNoException(); + if (has) { if (slot.isValue()) { JSValue value = slot.getValue(globalObject, vm.propertyNames->toStringTagSymbol); if (value.isString()) { diff --git a/src/bun.js/modules/ObjectModule.cpp b/src/bun.js/modules/ObjectModule.cpp index 125cd79481..67a8aa9252 100644 --- a/src/bun.js/modules/ObjectModule.cpp +++ b/src/bun.js/modules/ObjectModule.cpp @@ -45,13 +45,14 @@ generateObjectModuleSourceCodeForJSON(JSC::JSGlobalObject* globalObject, Vector& exportNames, JSC::MarkedArgumentBuffer& exportValues) -> void { auto& vm = JSC::getVM(lexicalGlobalObject); + auto scope = DECLARE_THROW_SCOPE(vm); GlobalObject* globalObject = reinterpret_cast(lexicalGlobalObject); JSC::EnsureStillAliveScope stillAlive(object); PropertyNameArray properties(vm, PropertyNameMode::Strings, PrivateSymbolMode::Exclude); - object->getPropertyNames(globalObject, properties, - DontEnumPropertiesMode::Exclude); + object->getPropertyNames(globalObject, properties, DontEnumPropertiesMode::Exclude); + RETURN_IF_EXCEPTION(scope, {}); gcUnprotectNullTolerant(object); exportNames.append(vm.propertyNames->defaultKeyword); @@ -64,12 +65,8 @@ generateObjectModuleSourceCodeForJSON(JSC::JSGlobalObject* globalObject, exportNames.append(entry); - auto scope = DECLARE_CATCH_SCOPE(vm); JSValue value = object->get(globalObject, entry); - if (scope.exception()) [[unlikely]] { - scope.clearException(); - value = jsUndefined(); - } + RETURN_IF_EXCEPTION(scope, {}); exportValues.append(value); } }; diff --git a/src/bun.js/node/node_cluster_binding.zig b/src/bun.js/node/node_cluster_binding.zig index 8e220584dd..d577610638 100644 --- a/src/bun.js/node/node_cluster_binding.zig +++ b/src/bun.js/node/node_cluster_binding.zig @@ -70,7 +70,7 @@ pub fn sendHelperChild(globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFram const ex = globalThis.createTypeErrorInstance("sendInternal() failed", .{}); ex.put(globalThis, ZigString.static("syscall"), bun.String.static("write").toJS(globalThis)); const fnvalue = JSC.JSFunction.create(globalThis, "", S.impl, 1, .{}); - fnvalue.callNextTick(globalThis, .{ex}); + try fnvalue.callNextTick(globalThis, .{ex}); return .false; } diff --git a/src/bun.js/node/node_crypto_binding.zig b/src/bun.js/node/node_crypto_binding.zig index 45d41b6a59..6576548df9 100644 --- a/src/bun.js/node/node_crypto_binding.zig +++ b/src/bun.js/node/node_crypto_binding.zig @@ -276,7 +276,7 @@ const random = struct { if (!callback.isUndefined()) { callback = callback.withAsyncContextIfNeeded(global); - callback.callNextTick(global, [2]JSValue{ .js_undefined, JSValue.jsNumber(res) }); + try callback.callNextTick(global, [2]JSValue{ .js_undefined, JSValue.jsNumber(res) }); return .js_undefined; } @@ -450,11 +450,7 @@ fn pbkdf2(globalThis: *JSC.JSGlobalObject, callFrame: *JSC.CallFrame) bun.JSErro fn pbkdf2Sync(globalThis: *JSC.JSGlobalObject, callFrame: *JSC.CallFrame) bun.JSError!JSC.JSValue { var data = try PBKDF2.fromJS(globalThis, callFrame, false); defer data.deinit(); - var out_arraybuffer = JSC.JSValue.createBufferFromLength(globalThis, @intCast(data.length)); - if (out_arraybuffer == .zero or globalThis.hasException()) { - data.deinit(); - return .zero; - } + const out_arraybuffer = try JSC.JSValue.createBufferFromLength(globalThis, @intCast(data.length)); const output = out_arraybuffer.asArrayBuffer(globalThis) orelse { data.deinit(); diff --git a/src/bun.js/test/expect.zig b/src/bun.js/test/expect.zig index ae517e0717..768bb36944 100644 --- a/src/bun.js/test/expect.zig +++ b/src/bun.js/test/expect.zig @@ -666,7 +666,7 @@ pub const Expect = struct { .expected = expected, .pass = &pass, }; - list_value.forEach(globalThis, &expected_entry, struct { + try list_value.forEach(globalThis, &expected_entry, struct { pub fn sameValueIterator( _: *JSC.VM, _: *JSGlobalObject, @@ -762,7 +762,7 @@ pub const Expect = struct { .expected = expected, .pass = &pass, }; - value.forEach(globalThis, &expected_entry, struct { + try value.forEach(globalThis, &expected_entry, struct { pub fn sameValueIterator( _: *JSC.VM, _: *JSGlobalObject, @@ -1360,7 +1360,7 @@ pub const Expect = struct { .expected = expected, .pass = &pass, }; - value.forEach(globalThis, &expected_entry, struct { + try value.forEach(globalThis, &expected_entry, struct { pub fn deepEqualsIterator( _: *JSC.VM, _: *JSGlobalObject, @@ -2286,7 +2286,7 @@ pub const Expect = struct { if (!result.isInstanceOf(globalThis, expected_value)) return .js_undefined; var expected_class = ZigString.Empty; - expected_value.getClassName(globalThis, &expected_class); + try expected_value.getClassName(globalThis, &expected_class); const received_message: JSValue = (try result.fastGet(globalThis, .message)) orelse .js_undefined; return this.throw(globalThis, signature, "\n\nExpected constructor: not {s}\n\nReceived message: {any}\n", .{ expected_class, received_message.toFmt(&formatter) }); } @@ -2410,8 +2410,8 @@ pub const Expect = struct { defer formatter.deinit(); var expected_class = ZigString.Empty; var received_class = ZigString.Empty; - expected_value.getClassName(globalThis, &expected_class); - result.getClassName(globalThis, &received_class); + try expected_value.getClassName(globalThis, &expected_class); + try result.getClassName(globalThis, &received_class); const signature = comptime getSignature("toThrow", "expected", false); const fmt = signature ++ "\n\nExpected constructor: {s}\nReceived constructor: {s}\n\n"; @@ -2466,7 +2466,7 @@ pub const Expect = struct { const expected_fmt = "\n\nExpected constructor: {s}\n\n" ++ received_line; var expected_class = ZigString.Empty; - expected_value.getClassName(globalThis, &expected_class); + try expected_value.getClassName(globalThis, &expected_class); return this.throw(globalThis, signature, expected_fmt, .{ expected_class, result.toFmt(&formatter) }); } fn getValueAsToThrow(this: *Expect, globalThis: *JSGlobalObject, value: JSValue) bun.JSError!struct { ?JSValue, JSValue } { @@ -2980,7 +2980,7 @@ pub const Expect = struct { if (value.jsTypeLoose().isObject()) { if (try value.isIterable(globalThis)) { var any_properties_in_iterator = false; - value.forEach(globalThis, &any_properties_in_iterator, struct { + try value.forEach(globalThis, &any_properties_in_iterator, struct { pub fn anythingInIterator( _: *JSC.VM, _: *JSGlobalObject, @@ -3936,7 +3936,7 @@ pub const Expect = struct { const result = predicate.call(globalThis, .js_undefined, &.{value}) catch |e| { const err = globalThis.takeException(e); const fmt = ZigString.init("toSatisfy() predicate threw an exception"); - return globalThis.throwValue(globalThis.createAggregateError(&.{err}, &fmt)); + return globalThis.throwValue(try globalThis.createAggregateError(&.{err}, &fmt)); }; const not = this.flags.not; @@ -4179,10 +4179,9 @@ pub const Expect = struct { const value: JSValue = try this.getValue(globalThis, thisValue, "toHaveBeenCalled", ""); - const calls = JSMockFunction__getCalls(value); + const calls = try bun.jsc.fromJSHostCall(globalThis, @src(), JSMockFunction__getCalls, .{value}); incrementExpectCallCounter(); - - if (calls == .zero or !calls.jsType().isArray()) { + if (!calls.jsType().isArray()) { return globalThis.throw("Expected value must be a mock function: {}", .{value}); } @@ -4212,9 +4211,8 @@ pub const Expect = struct { incrementExpectCallCounter(); - const calls = JSMockFunction__getCalls(value); - - if (calls == .zero or !calls.jsType().isArray()) { + const calls = try bun.jsc.fromJSHostCall(globalThis, @src(), JSMockFunction__getCalls, .{value}); + if (!calls.jsType().isArray()) { return globalThis.throw("Expected value must be a mock function: {}", .{value}); } @@ -4246,9 +4244,8 @@ pub const Expect = struct { incrementExpectCallCounter(); - const calls = JSMockFunction__getCalls(value); - - if (calls == .zero or !calls.jsType().isArray()) { + const calls = try bun.jsc.fromJSHostCall(globalThis, @src(), JSMockFunction__getCalls, .{value}); + if (!calls.jsType().isArray()) { return globalThis.throw("Expected value must be a mock function: {}", .{value}); } @@ -4342,9 +4339,8 @@ pub const Expect = struct { incrementExpectCallCounter(); - const calls = JSMockFunction__getCalls(value); - - if (calls == .zero or !calls.jsType().isArray()) { + const calls = try bun.jsc.fromJSHostCall(globalThis, @src(), JSMockFunction__getCalls, .{value}); + if (!calls.jsType().isArray()) { return globalThis.throw("Expected value must be a mock function: {}", .{value}); } @@ -4401,9 +4397,8 @@ pub const Expect = struct { incrementExpectCallCounter(); - const calls = JSMockFunction__getCalls(value); - - if (calls == .zero or !calls.jsType().isArray()) { + const calls = try bun.jsc.fromJSHostCall(globalThis, @src(), JSMockFunction__getCalls, .{value}); + if (!calls.jsType().isArray()) { return globalThis.throw("Expected value must be a mock function: {}", .{value}); } @@ -4460,9 +4455,8 @@ pub const Expect = struct { incrementExpectCallCounter(); - const calls = JSMockFunction__getCalls(value); - - if (calls == .zero or !calls.jsType().isArray()) { + const calls = try bun.jsc.fromJSHostCall(globalThis, @src(), JSMockFunction__getCalls, .{value}); + if (!calls.jsType().isArray()) { return globalThis.throw("Expected value must be a mock function: {}", .{value}); } @@ -4535,11 +4529,8 @@ pub const Expect = struct { incrementExpectCallCounter(); - const returns = JSMockFunction__getReturns(value); - - if (returns == .zero or !returns.jsType().isArray()) { - return globalThis.throw("Expected value must be a mock function: {}", .{value}); - } + const returns = try bun.jsc.fromJSHostCall(globalThis, @src(), JSMockFunction__getReturns, .{value}); + if (!returns.jsType().isArray()) return globalThis.throw("Expected value must be a mock function: {}", .{value}); const return_count: i32 = if (known_index) |index| index else brk: { if (arguments.len < 1 or !arguments[0].isUInt32AsAnyInt()) { diff --git a/src/bun.js/test/jest.zig b/src/bun.js/test/jest.zig index 7f10371e4a..53e341ed71 100644 --- a/src/bun.js/test/jest.zig +++ b/src/bun.js/test/jest.zig @@ -1814,10 +1814,10 @@ inline fn createScope( } if (description.isClass(globalThis)) { - const name_str = if (description.className(globalThis).toSlice(allocator).length() == 0) + const name_str = if ((try description.className(globalThis)).toSlice(allocator).length() == 0) description.getName(globalThis).toSlice(allocator).slice() else - description.className(globalThis).toSlice(allocator).slice(); + (try description.className(globalThis)).toSlice(allocator).slice(); break :brk try allocator.dupe(u8, name_str); } if (description.isFunction()) { diff --git a/src/bun.js/test/pretty_format.zig b/src/bun.js/test/pretty_format.zig index b544956606..8847307c31 100644 --- a/src/bun.js/test/pretty_format.zig +++ b/src/bun.js/test/pretty_format.zig @@ -737,7 +737,7 @@ pub const JestPrettyFormat = struct { always_newline: bool = false, parent: JSValue, const enable_ansi_colors = enable_ansi_colors_; - pub fn handleFirstProperty(this: *@This(), globalThis: *JSC.JSGlobalObject, value: JSValue) void { + pub fn handleFirstProperty(this: *@This(), globalThis: *JSC.JSGlobalObject, value: JSValue) bun.JSError!void { if (!value.jsType().isFunction()) { var writer = WrappedWriter(Writer){ .ctx = this.writer, @@ -745,11 +745,11 @@ pub const JestPrettyFormat = struct { }; var name_str = ZigString.init(""); - value.getNameProperty(globalThis, &name_str); + try value.getNameProperty(globalThis, &name_str); if (name_str.len > 0 and !name_str.eqlComptime("Object")) { writer.print("{} ", .{name_str}); } else { - value.getPrototype(globalThis).getNameProperty(globalThis, &name_str); + try value.getPrototype(globalThis).getNameProperty(globalThis, &name_str); if (name_str.len > 0 and !name_str.eqlComptime("Object")) { writer.print("{} ", .{name_str}); } @@ -761,7 +761,7 @@ pub const JestPrettyFormat = struct { if (this.formatter.indent == 0) this.writer.writeAll("\n") catch {}; var classname = ZigString.Empty; - value.getClassName(globalThis, &classname); + try value.getClassName(globalThis, &classname); if (!classname.isEmpty() and !classname.eqlComptime("Object")) { this.writer.print("{} ", .{classname}) catch {}; } @@ -798,7 +798,7 @@ pub const JestPrettyFormat = struct { if (tag.cell.isHidden()) return; if (ctx.i == 0) { - handleFirstProperty(ctx, globalThis, ctx.parent); + handleFirstProperty(ctx, globalThis, ctx.parent) catch return; } else { this.printComma(Writer, writer_, enable_ansi_colors) catch return; } @@ -1100,7 +1100,7 @@ pub const JestPrettyFormat = struct { }, .Error => { var classname = ZigString.Empty; - value.getClassName(this.globalThis, &classname); + try value.getClassName(this.globalThis, &classname); var message_string = bun.String.empty; defer message_string.deref(); @@ -1117,7 +1117,7 @@ pub const JestPrettyFormat = struct { }, .Class => { var printable = ZigString.init(&name_buf); - value.getClassName(this.globalThis, &printable); + try value.getClassName(this.globalThis, &printable); this.addForNewLine(printable.len); if (printable.len == 0) { @@ -1128,7 +1128,7 @@ pub const JestPrettyFormat = struct { }, .Function => { var printable = ZigString.init(&name_buf); - value.getNameProperty(this.globalThis, &printable); + try value.getNameProperty(this.globalThis, &printable); if (printable.len == 0) { writer.print(comptime Output.prettyFmt("[Function]", enable_ansi_colors), .{}); @@ -1300,7 +1300,7 @@ pub const JestPrettyFormat = struct { } else if (value.as(bun.api.ResolveMessage)) |resolve_log| { resolve_log.msg.writeFormat(writer_, enable_ansi_colors) catch {}; return; - } else if (printAsymmetricMatcher(this, Format, &writer, writer_, name_buf, value, enable_ansi_colors)) { + } else if (try printAsymmetricMatcher(this, Format, &writer, writer_, name_buf, value, enable_ansi_colors)) { return; } else if (jsType != .DOMWrapper) { if (value.isCallable()) { @@ -1362,7 +1362,7 @@ pub const JestPrettyFormat = struct { .formatter = this, .writer = writer_, }; - value.forEach(this.globalThis, &iter, @TypeOf(iter).forEach); + try value.forEach(this.globalThis, &iter, @TypeOf(iter).forEach); } this.writeIndent(Writer, writer_) catch {}; writer.writeAll("}"); @@ -1392,7 +1392,7 @@ pub const JestPrettyFormat = struct { .formatter = this, .writer = writer_, }; - value.forEach(this.globalThis, &iter, @TypeOf(iter).forEach); + try value.forEach(this.globalThis, &iter, @TypeOf(iter).forEach); } this.writeIndent(Writer, writer_) catch {}; writer.writeAll("}"); @@ -1528,7 +1528,7 @@ pub const JestPrettyFormat = struct { try type_value.toZigString(&tag_name_str, this.globalThis); is_tag_kind_primitive = true; } else if (_tag.cell.isObject() or type_value.isCallable()) { - type_value.getNameProperty(this.globalThis, &tag_name_str); + try type_value.getNameProperty(this.globalThis, &tag_name_str); if (tag_name_str.len == 0) { tag_name_str = ZigString.init("NoName"); } @@ -1768,7 +1768,7 @@ pub const JestPrettyFormat = struct { if (iter.i == 0) { var object_name = ZigString.Empty; - value.getClassName(this.globalThis, &object_name); + try value.getClassName(this.globalThis, &object_name); if (!object_name.eqlComptime("Object")) { writer.print("{s} {{}}", .{object_name}); @@ -1805,7 +1805,7 @@ pub const JestPrettyFormat = struct { if (jsType == .Uint8Array) { var buffer_name = ZigString.Empty; - value.getClassName(this.globalThis, &buffer_name); + try value.getClassName(this.globalThis, &buffer_name); if (strings.eqlComptime(buffer_name.slice(), "Buffer")) { // special formatting for 'Buffer' snapshots only if (slice.len == 0 and this.indent == 0) writer.writeAll("\n"); @@ -2048,7 +2048,7 @@ pub const JestPrettyFormat = struct { name_buf: [512]u8, value: JSValue, comptime enable_ansi_colors: bool, - ) bool { + ) bun.JSError!bool { _ = Format; if (value.as(expect.ExpectAnything)) |matcher| { @@ -2073,7 +2073,7 @@ pub const JestPrettyFormat = struct { } var class_name = ZigString.init(&name_buf); - constructor_value.getClassName(this.globalThis, &class_name); + try constructor_value.getClassName(this.globalThis, &class_name); this.addForNewLine(class_name.len); writer.print(comptime Output.prettyFmt("{}", enable_ansi_colors), .{class_name}); this.addForNewLine(1); @@ -2105,7 +2105,7 @@ pub const JestPrettyFormat = struct { this.addForNewLine("ObjectContaining ".len); writer.writeAll("ObjectContaining "); } - this.printAs(.Object, @TypeOf(writer_), writer_, object_value, .Object, enable_ansi_colors) catch {}; // TODO: + try this.printAs(.Object, @TypeOf(writer_), writer_, object_value, .Object, enable_ansi_colors); } else if (value.as(expect.ExpectStringContaining)) |matcher| { const substring_value = expect.ExpectStringContaining.js.stringValueGetCached(value) orelse return true; @@ -2117,7 +2117,7 @@ pub const JestPrettyFormat = struct { this.addForNewLine("StringContaining ".len); writer.writeAll("StringContaining "); } - this.printAs(.String, @TypeOf(writer_), writer_, substring_value, .String, enable_ansi_colors) catch {}; // TODO: + try this.printAs(.String, @TypeOf(writer_), writer_, substring_value, .String, enable_ansi_colors); } else if (value.as(expect.ExpectStringMatching)) |matcher| { const test_value = expect.ExpectStringMatching.js.testValueGetCached(value) orelse return true; @@ -2132,7 +2132,7 @@ pub const JestPrettyFormat = struct { const original_quote_strings = this.quote_strings; if (test_value.isRegExp()) this.quote_strings = false; - this.printAs(.String, @TypeOf(writer_), writer_, test_value, .String, enable_ansi_colors) catch {}; // TODO: + try this.printAs(.String, @TypeOf(writer_), writer_, test_value, .String, enable_ansi_colors); this.quote_strings = original_quote_strings; } else if (value.as(expect.ExpectCustomAsymmetricMatcher)) |instance| { const printed = instance.customPrint(value, this.globalThis, writer_, true) catch unreachable; @@ -2150,7 +2150,7 @@ pub const JestPrettyFormat = struct { this.addForNewLine(matcher_name.length() + 1); writer.print("{s}", .{matcher_name}); writer.writeAll(" "); - this.printAs(.Array, @TypeOf(writer_), writer_, args_value, .Array, enable_ansi_colors) catch {}; // TODO: + try this.printAs(.Array, @TypeOf(writer_), writer_, args_value, .Array, enable_ansi_colors); } } else { return false; diff --git a/src/bun.js/webcore/Blob.zig b/src/bun.js/webcore/Blob.zig index 4bbe727ce1..baa2cfd2ab 100644 --- a/src/bun.js/webcore/Blob.zig +++ b/src/bun.js/webcore/Blob.zig @@ -1031,7 +1031,7 @@ pub fn writeFileWithSourceDestination(ctx: *JSC.JSGlobalObject, source_blob: *Bl return file_copier.promise.value(); } else if (destination_type == .file and source_type == .s3) { const s3 = &source_store.data.s3; - if (JSC.WebCore.ReadableStream.fromJS(JSC.WebCore.ReadableStream.fromBlobCopyRef( + if (try JSC.WebCore.ReadableStream.fromJS(try JSC.WebCore.ReadableStream.fromBlobCopyRef( ctx, source_blob, @truncate(s3.options.partSize), @@ -1068,7 +1068,7 @@ pub fn writeFileWithSourceDestination(ctx: *JSC.JSGlobalObject, source_blob: *Bl switch (source_store.data) { .bytes => |bytes| { if (bytes.len > S3.MultiPartUploadOptions.MAX_SINGLE_UPLOAD_SIZE) { - if (JSC.WebCore.ReadableStream.fromJS(JSC.WebCore.ReadableStream.fromBlobCopyRef( + if (try JSC.WebCore.ReadableStream.fromJS(try JSC.WebCore.ReadableStream.fromBlobCopyRef( ctx, source_blob, @truncate(s3.options.partSize), @@ -1135,7 +1135,7 @@ pub fn writeFileWithSourceDestination(ctx: *JSC.JSGlobalObject, source_blob: *Bl }, .file, .s3 => { // stream - if (JSC.WebCore.ReadableStream.fromJS(JSC.WebCore.ReadableStream.fromBlobCopyRef( + if (try JSC.WebCore.ReadableStream.fromJS(try JSC.WebCore.ReadableStream.fromBlobCopyRef( ctx, source_blob, @truncate(s3.options.partSize), @@ -1333,7 +1333,7 @@ pub fn writeFileInternal(globalThis: *JSC.JSGlobalObject, path_or_blob_: *PathOr const s3 = &destination_blob.store.?.data.s3; var aws_options = try s3.getCredentialsWithOptions(options.extra_options, globalThis); defer aws_options.deinit(); - _ = response.body.value.toReadableStream(globalThis); + _ = try response.body.value.toReadableStream(globalThis); if (locked.readable.get(globalThis)) |readable| { if (readable.isDisturbed(globalThis)) { destination_blob.detach(); @@ -1394,7 +1394,7 @@ pub fn writeFileInternal(globalThis: *JSC.JSGlobalObject, path_or_blob_: *PathOr const s3 = &destination_blob.store.?.data.s3; var aws_options = try s3.getCredentialsWithOptions(options.extra_options, globalThis); defer aws_options.deinit(); - _ = request.body.value.toReadableStream(globalThis); + _ = try request.body.value.toReadableStream(globalThis); if (locked.readable.get(globalThis)) |readable| { if (readable.isDisturbed(globalThis)) { destination_blob.detach(); @@ -1962,7 +1962,7 @@ pub fn getStream( recommended_chunk_size = @as(SizeType, @intCast(@max(0, @as(i52, @truncate(arguments[0].toInt64()))))); } - const stream = JSC.WebCore.ReadableStream.fromBlobCopyRef( + const stream = try JSC.WebCore.ReadableStream.fromBlobCopyRef( globalThis, this, recommended_chunk_size, diff --git a/src/bun.js/webcore/Body.zig b/src/bun.js/webcore/Body.zig index c77fcecc79..86301c44d9 100644 --- a/src/bun.js/webcore/Body.zig +++ b/src/bun.js/webcore/Body.zig @@ -15,9 +15,9 @@ pub fn use(this: *Body) Blob { return this.value.use(); } -pub fn clone(this: *Body, globalThis: *JSGlobalObject) Body { +pub fn clone(this: *Body, globalThis: *JSGlobalObject) bun.JSError!Body { return Body{ - .value = this.value.clone(globalThis), + .value = try this.value.clone(globalThis), }; } @@ -443,7 +443,7 @@ pub const Value = union(Tag) { // pub const empty = Value{ .Empty = {} }; - pub fn toReadableStream(this: *Value, globalThis: *JSGlobalObject) JSValue { + pub fn toReadableStream(this: *Value, globalThis: *JSGlobalObject) bun.JSError!JSValue { JSC.markBinding(@src()); switch (this.*) { @@ -460,11 +460,11 @@ pub const Value = union(Tag) { var blob = this.use(); defer blob.detach(); blob.resolveSize(); - const value = JSC.WebCore.ReadableStream.fromBlobCopyRef(globalThis, &blob, blob.size); + const value = try JSC.WebCore.ReadableStream.fromBlobCopyRef(globalThis, &blob, blob.size); this.* = .{ .Locked = .{ - .readable = JSC.WebCore.ReadableStream.Strong.init(JSC.WebCore.ReadableStream.fromJS(value, globalThis).?, globalThis), + .readable = JSC.WebCore.ReadableStream.Strong.init((try JSC.WebCore.ReadableStream.fromJS(value, globalThis)).?, globalThis), .global = globalThis, }, }; @@ -509,7 +509,7 @@ pub const Value = union(Tag) { locked.readable = JSC.WebCore.ReadableStream.Strong.init(.{ .ptr = .{ .Bytes = &reader.context }, - .value = reader.toReadableStream(globalThis), + .value = try reader.toReadableStream(globalThis), }, globalThis); if (locked.onReadableStreamAvailable) |onReadableStreamAvailable| { @@ -599,7 +599,7 @@ pub const Value = union(Tag) { value.ensureStillAlive(); - if (JSC.WebCore.ReadableStream.fromJS(value, globalThis)) |readable| { + if (try JSC.WebCore.ReadableStream.fromJS(value, globalThis)) |readable| { if (readable.isDisturbed(globalThis)) { return globalThis.throw("ReadableStream has already been used", .{}); } @@ -964,14 +964,14 @@ pub const Value = union(Tag) { } } - pub fn tee(this: *Value, globalThis: *JSC.JSGlobalObject) Value { + pub fn tee(this: *Value, globalThis: *JSC.JSGlobalObject) bun.JSError!Value { var locked = &this.Locked; if (locked.readable.isDisturbed(globalThis)) { return Value{ .Used = {} }; } - if (locked.readable.tee(globalThis)) |readable| { + if (try locked.readable.tee(globalThis)) |readable| { return Value{ .Locked = .{ .readable = JSC.WebCore.ReadableStream.Strong.init(readable, globalThis), @@ -1014,14 +1014,14 @@ pub const Value = union(Tag) { locked.readable = JSC.WebCore.ReadableStream.Strong.init(.{ .ptr = .{ .Bytes = &reader.context }, - .value = reader.toReadableStream(globalThis), + .value = try reader.toReadableStream(globalThis), }, globalThis); if (locked.onReadableStreamAvailable) |onReadableStreamAvailable| { onReadableStreamAvailable(locked.task.?, globalThis, locked.readable.get(globalThis).?); } - const teed = locked.readable.tee(globalThis) orelse return Value{ .Used = {} }; + const teed = (try locked.readable.tee(globalThis)) orelse return Value{ .Used = {} }; return Value{ .Locked = .{ @@ -1031,7 +1031,7 @@ pub const Value = union(Tag) { }; } - pub fn clone(this: *Value, globalThis: *JSC.JSGlobalObject) Value { + pub fn clone(this: *Value, globalThis: *JSC.JSGlobalObject) bun.JSError!Value { this.toBlobIfPossible(); if (this.* == .Locked) { @@ -1086,11 +1086,7 @@ pub fn extract( pub fn Mixin(comptime Type: type) type { return struct { - pub fn getText( - this: *Type, - globalObject: *JSC.JSGlobalObject, - callframe: *JSC.CallFrame, - ) bun.JSError!JSC.JSValue { + pub fn getText(this: *Type, globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) bun.JSError!JSC.JSValue { var value: *Body.Value = this.getBodyValue(); if (value.* == .Used) { return handleBodyAlreadyUsed(globalObject); @@ -1108,10 +1104,7 @@ pub fn Mixin(comptime Type: type) type { return JSC.JSPromise.wrap(globalObject, lifetimeWrap(AnyBlob.toString, .transfer), .{ &blob, globalObject }); } - pub fn getBody( - this: *Type, - globalThis: *JSC.JSGlobalObject, - ) JSValue { + pub fn getBody(this: *Type, globalThis: *JSC.JSGlobalObject) bun.JSError!JSValue { var body: *Body.Value = this.getBodyValue(); if (body.* == .Used) { @@ -1121,10 +1114,7 @@ pub fn Mixin(comptime Type: type) type { return body.toReadableStream(globalThis); } - pub fn getBodyUsed( - this: *Type, - globalObject: *JSC.JSGlobalObject, - ) JSValue { + pub fn getBodyUsed(this: *Type, globalObject: *JSC.JSGlobalObject) JSValue { return JSValue.jsBoolean( switch (this.getBodyValue().*) { .Used => true, @@ -1152,11 +1142,7 @@ pub fn Mixin(comptime Type: type) type { }.wrap; } - pub fn getJSON( - this: *Type, - globalObject: *JSC.JSGlobalObject, - callframe: *JSC.CallFrame, - ) bun.JSError!JSC.JSValue { + pub fn getJSON(this: *Type, globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) bun.JSError!JSC.JSValue { var value: *Body.Value = this.getBodyValue(); if (value.* == .Used) { return handleBodyAlreadyUsed(globalObject); @@ -1182,11 +1168,7 @@ pub fn Mixin(comptime Type: type) type { return globalObject.ERR(.BODY_ALREADY_USED, "Body already used", .{}).reject(); } - pub fn getArrayBuffer( - this: *Type, - globalObject: *JSC.JSGlobalObject, - callframe: *JSC.CallFrame, - ) bun.JSError!JSC.JSValue { + pub fn getArrayBuffer(this: *Type, globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) bun.JSError!JSC.JSValue { var value: *Body.Value = this.getBodyValue(); if (value.* == .Used) { @@ -1210,11 +1192,7 @@ pub fn Mixin(comptime Type: type) type { return JSC.JSPromise.wrap(globalObject, lifetimeWrap(AnyBlob.toArrayBuffer, .transfer), .{ &blob, globalObject }); } - pub fn getBytes( - this: *Type, - globalObject: *JSC.JSGlobalObject, - callframe: *JSC.CallFrame, - ) bun.JSError!JSC.JSValue { + pub fn getBytes(this: *Type, globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) bun.JSError!JSC.JSValue { var value: *Body.Value = this.getBodyValue(); if (value.* == .Used) { @@ -1236,11 +1214,7 @@ pub fn Mixin(comptime Type: type) type { return JSC.JSPromise.wrap(globalObject, lifetimeWrap(AnyBlob.toUint8Array, .transfer), .{ &blob, globalObject }); } - pub fn getFormData( - this: *Type, - globalObject: *JSC.JSGlobalObject, - callframe: *JSC.CallFrame, - ) bun.JSError!JSC.JSValue { + pub fn getFormData(this: *Type, globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) bun.JSError!JSC.JSValue { var value: *Body.Value = this.getBodyValue(); if (value.* == .Used) { @@ -1287,19 +1261,11 @@ pub fn Mixin(comptime Type: type) type { ); } - pub fn getBlob( - this: *Type, - globalObject: *JSC.JSGlobalObject, - callframe: *JSC.CallFrame, - ) bun.JSError!JSC.JSValue { + pub fn getBlob(this: *Type, globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) bun.JSError!JSC.JSValue { return getBlobWithThisValue(this, globalObject, callframe.this()); } - pub fn getBlobWithThisValue( - this: *Type, - globalObject: *JSC.JSGlobalObject, - this_value: JSValue, - ) bun.JSError!JSC.JSValue { + pub fn getBlobWithThisValue(this: *Type, globalObject: *JSC.JSGlobalObject, this_value: JSValue) bun.JSError!JSC.JSValue { var value: *Body.Value = this.getBodyValue(); if (value.* == .Used) { @@ -1348,10 +1314,7 @@ pub fn Mixin(comptime Type: type) type { return JSC.JSPromise.resolvedPromiseValue(globalObject, blob.toJS(globalObject)); } - pub fn getBlobWithoutCallFrame( - this: *Type, - globalObject: *JSC.JSGlobalObject, - ) bun.JSError!JSC.JSValue { + pub fn getBlobWithoutCallFrame(this: *Type, globalObject: *JSC.JSGlobalObject) bun.JSError!JSC.JSValue { return getBlobWithThisValue(this, globalObject, .zero); } }; @@ -1382,7 +1345,7 @@ pub const ValueBufferer = struct { this.readable_stream_ref.deinit(); if (this.js_sink) |buffer_stream| { - buffer_stream.detach(); + buffer_stream.detach(this.global); buffer_stream.sink.destroy(); this.js_sink = null; } @@ -1510,7 +1473,7 @@ pub const ValueBufferer = struct { fn handleRejectStream(sink: *@This(), err: JSValue, is_async: bool) void { if (sink.js_sink) |wrapper| { - wrapper.detach(); + wrapper.detach(sink.global); sink.js_sink = null; wrapper.sink.destroy(); } @@ -1649,7 +1612,7 @@ pub const ValueBufferer = struct { if (locked.onReceiveValue != null or locked.task != null) { // someone else is waiting for the stream or waiting for `onStartStreaming` - const readable = value.toReadableStream(sink.global); + const readable = try value.toReadableStream(sink.global); readable.ensureStillAlive(); readable.protect(); return try sink.bufferLockedBodyValue(value); diff --git a/src/bun.js/webcore/CookieMap.zig b/src/bun.js/webcore/CookieMap.zig index a3018ecabc..e59c0f84cb 100644 --- a/src/bun.js/webcore/CookieMap.zig +++ b/src/bun.js/webcore/CookieMap.zig @@ -2,9 +2,16 @@ const bun = @import("bun"); pub const CookieMap = opaque { extern fn CookieMap__write(cookie_map: *CookieMap, global_this: *bun.JSC.JSGlobalObject, ssl_enabled: bool, uws_http_response: *anyopaque) void; - pub const write = CookieMap__write; + + pub fn write(cookie_map: *CookieMap, globalThis: *bun.JSC.JSGlobalObject, ssl_enabled: bool, uws_http_response: *anyopaque) bun.JSError!void { + return bun.jsc.fromJSHostCallGeneric(globalThis, @src(), CookieMap__write, .{ cookie_map, globalThis, ssl_enabled, uws_http_response }); + } + extern fn CookieMap__deref(cookie_map: *CookieMap) void; + pub const deref = CookieMap__deref; + extern fn CookieMap__ref(cookie_map: *CookieMap) void; + pub const ref = CookieMap__ref; }; diff --git a/src/bun.js/webcore/ReadableStream.zig b/src/bun.js/webcore/ReadableStream.zig index c902df9e7e..6755f50e5a 100644 --- a/src/bun.js/webcore/ReadableStream.zig +++ b/src/bun.js/webcore/ReadableStream.zig @@ -26,7 +26,7 @@ pub const Strong = struct { pub fn get(this: *const Strong, global: *JSC.JSGlobalObject) ?ReadableStream { if (this.held.get()) |value| { - return ReadableStream.fromJS(value, global); + return ReadableStream.fromJS(value, global) catch null; // TODO: properly propagate exception upwards } return null; } @@ -38,9 +38,9 @@ pub const Strong = struct { this.held.deinit(); } - pub fn tee(this: *Strong, global: *JSGlobalObject) ?ReadableStream { + pub fn tee(this: *Strong, global: *JSGlobalObject) bun.JSError!?ReadableStream { if (this.get(global)) |stream| { - const first, const second = stream.tee(global) orelse return null; + const first, const second = (try stream.tee(global)) orelse return null; this.held.set(global, first.value); return second; } @@ -49,14 +49,14 @@ pub const Strong = struct { }; extern fn ReadableStream__tee(stream: JSValue, globalThis: *JSGlobalObject, out1: *JSC.JSValue, out2: *JSC.JSValue) bool; -pub fn tee(this: *const ReadableStream, globalThis: *JSGlobalObject) ?struct { ReadableStream, ReadableStream } { +pub fn tee(this: *const ReadableStream, globalThis: *JSGlobalObject) bun.JSError!?struct { ReadableStream, ReadableStream } { var out1: JSC.JSValue = .zero; var out2: JSC.JSValue = .zero; - if (!ReadableStream__tee(this.value, globalThis, &out1, &out2)) { + if (!try bun.jsc.fromJSHostCallGeneric(globalThis, @src(), ReadableStream__tee, .{ this.value, globalThis, &out1, &out2 })) { return null; } - const out_stream2 = ReadableStream.fromJS(out2, globalThis) orelse return null; - const out_stream1 = ReadableStream.fromJS(out1, globalThis) orelse return null; + const out_stream2 = try ReadableStream.fromJS(out2, globalThis) orelse return null; + const out_stream1 = try ReadableStream.fromJS(out1, globalThis) orelse return null; return .{ out_stream1, out_stream2 }; } @@ -64,8 +64,8 @@ pub fn toJS(this: *const ReadableStream) JSValue { return this.value; } -pub fn reloadTag(this: *ReadableStream, globalThis: *JSC.JSGlobalObject) void { - if (ReadableStream.fromJS(this.value, globalThis)) |stream| { +pub fn reloadTag(this: *ReadableStream, globalThis: *JSC.JSGlobalObject) bun.JSError!void { + if (try ReadableStream.fromJS(this.value, globalThis)) |stream| { this.* = stream; } else { this.* = .{ .ptr = .{ .Invalid = {} }, .value = .zero }; @@ -80,7 +80,7 @@ pub fn toAnyBlob( return null; } - stream.reloadTag(globalThis); + stream.reloadTag(globalThis) catch {}; // TODO: properly propagate exception upwards switch (stream.ptr) { .Blob => |blobby| { @@ -234,13 +234,13 @@ pub fn isLocked(this: *const ReadableStream, globalObject: *JSGlobalObject) bool return ReadableStream__isLocked(this.value, globalObject); } -pub fn fromJS(value: JSValue, globalThis: *JSGlobalObject) ?ReadableStream { +pub fn fromJS(value: JSValue, globalThis: *JSGlobalObject) bun.JSError!?ReadableStream { JSC.markBinding(@src()); value.ensureStillAlive(); var out = value; var ptr: ?*anyopaque = null; - return switch (ReadableStreamTag__tagged(globalThis, &out, &ptr)) { + return switch (try bun.jsc.fromJSHostCallGeneric(globalThis, @src(), ReadableStreamTag__tagged, .{ globalThis, &out, &ptr })) { .JavaScript => ReadableStream{ .value = out, .ptr = .{ @@ -285,18 +285,18 @@ pub fn fromJS(value: JSValue, globalThis: *JSGlobalObject) ?ReadableStream { extern fn ZigGlobalObject__createNativeReadableStream(*JSGlobalObject, nativePtr: JSValue) JSValue; -pub fn fromNative(globalThis: *JSGlobalObject, native: JSC.JSValue) JSC.JSValue { +pub fn fromNative(globalThis: *JSGlobalObject, native: JSC.JSValue) bun.JSError!JSC.JSValue { JSC.markBinding(@src()); - return ZigGlobalObject__createNativeReadableStream(globalThis, native); + return bun.jsc.fromJSHostCall(globalThis, @src(), ZigGlobalObject__createNativeReadableStream, .{ globalThis, native }); } -pub fn fromOwnedSlice(globalThis: *JSGlobalObject, bytes: []u8, recommended_chunk_size: Blob.SizeType) JSC.JSValue { +pub fn fromOwnedSlice(globalThis: *JSGlobalObject, bytes: []u8, recommended_chunk_size: Blob.SizeType) bun.JSError!JSC.JSValue { var blob = Blob.init(bytes, bun.default_allocator, globalThis); defer blob.deinit(); return fromBlobCopyRef(globalThis, &blob, recommended_chunk_size); } -pub fn fromBlobCopyRef(globalThis: *JSGlobalObject, blob: *const Blob, recommended_chunk_size: Blob.SizeType) JSC.JSValue { +pub fn fromBlobCopyRef(globalThis: *JSGlobalObject, blob: *const Blob, recommended_chunk_size: Blob.SizeType) bun.JSError!JSC.JSValue { JSC.markBinding(@src()); var store = blob.store orelse { return ReadableStream.empty(globalThis); @@ -375,7 +375,7 @@ pub fn fromPipe( globalThis: *JSGlobalObject, parent: anytype, buffered_reader: anytype, -) JSC.JSValue { +) bun.JSError!JSC.JSValue { _ = parent; // autofix JSC.markBinding(@src()); var source = webcore.FileReader.Source.new(.{ @@ -389,10 +389,9 @@ pub fn fromPipe( return source.toReadableStream(globalThis); } -pub fn empty(globalThis: *JSGlobalObject) JSC.JSValue { +pub fn empty(globalThis: *JSGlobalObject) bun.JSError!JSC.JSValue { JSC.markBinding(@src()); - - return ReadableStream__empty(globalThis); + return bun.jsc.fromJSHostCall(globalThis, @src(), ReadableStream__empty, .{globalThis}); } pub fn used(globalThis: *JSGlobalObject) JSC.JSValue { @@ -550,7 +549,7 @@ pub fn NewSource( return .{}; } - pub fn toReadableStream(this: *ReadableStreamSourceType, globalThis: *JSGlobalObject) JSC.JSValue { + pub fn toReadableStream(this: *ReadableStreamSourceType, globalThis: *JSGlobalObject) bun.JSError!JSC.JSValue { const out_value = brk: { if (this.this_jsvalue != .zero) { break :brk this.this_jsvalue; diff --git a/src/bun.js/webcore/Request.zig b/src/bun.js/webcore/Request.zig index ad5ab8d920..e349b7b13e 100644 --- a/src/bun.js/webcore/Request.zig +++ b/src/bun.js/webcore/Request.zig @@ -67,8 +67,8 @@ pub export fn Request__setTimeout(this: *Request, seconds: JSC.JSValue, globalTh this.setTimeout(seconds.to(c_uint)); } -pub export fn Request__clone(this: *Request, globalThis: *JSC.JSGlobalObject) *Request { - return this.clone(bun.default_allocator, globalThis); +pub export fn Request__clone(this: *Request, globalThis: *JSC.JSGlobalObject) ?*Request { + return this.clone(bun.default_allocator, globalThis) catch null; } comptime { @@ -218,7 +218,7 @@ pub fn writeFormat(this: *Request, this_value: JSValue, comptime Formatter: type try formatter.writeIndent(Writer, writer); try writer.writeAll(comptime Output.prettyFmt("headers: ", enable_ansi_colors)); - try formatter.printAs(.Private, Writer, writer, this.getHeaders(formatter.globalThis), .DOMWrapper, enable_ansi_colors); + try formatter.printAs(.Private, Writer, writer, try this.getHeaders(formatter.globalThis), .DOMWrapper, enable_ansi_colors); if (this.body.value == .Blob) { try writer.writeAll("\n"); @@ -571,7 +571,7 @@ pub fn constructInto(globalThis: *JSC.JSGlobalObject, arguments: []const JSC.JSV if (value_type == .DOMWrapper) { if (value.asDirect(Request)) |request| { if (values_to_try.len == 1) { - request.cloneInto(&req, globalThis.allocator(), globalThis, fields.contains(.url)); + try request.cloneInto(&req, globalThis.allocator(), globalThis, fields.contains(.url)); success = true; return req; } @@ -587,7 +587,7 @@ pub fn constructInto(globalThis: *JSC.JSGlobalObject, arguments: []const JSC.JSV } if (!fields.contains(.headers)) { - if (request.cloneHeaders(globalThis)) |headers| { + if (try request.cloneHeaders(globalThis)) |headers| { req._headers = headers; fields.insert(.headers); } @@ -599,8 +599,7 @@ pub fn constructInto(globalThis: *JSC.JSGlobalObject, arguments: []const JSC.JSV switch (request.body.value) { .Null, .Empty, .Used => {}, else => { - req.body.value = request.body.value.clone(globalThis); - if (globalThis.hasException()) return error.JSError; + req.body.value = try request.body.value.clone(globalThis); fields.insert(.body); }, } @@ -615,7 +614,7 @@ pub fn constructInto(globalThis: *JSC.JSGlobalObject, arguments: []const JSC.JSV if (!fields.contains(.headers)) { if (response.init.headers) |headers| { - req._headers = headers.cloneThis(globalThis); + req._headers = try headers.cloneThis(globalThis); fields.insert(.headers); } } @@ -631,7 +630,7 @@ pub fn constructInto(globalThis: *JSC.JSGlobalObject, arguments: []const JSC.JSV switch (response.body.value) { .Null, .Empty, .Used => {}, else => { - req.body.value = response.body.value.clone(globalThis); + req.body.value = try response.body.value.clone(globalThis); fields.insert(.body); }, } @@ -756,7 +755,7 @@ pub fn constructInto(globalThis: *JSC.JSGlobalObject, arguments: []const JSC.JSV req.body.value.Blob.content_type.len > 0 and !req._headers.?.fastHas(.ContentType)) { - req._headers.?.put(.ContentType, req.body.value.Blob.content_type, globalThis); + try req._headers.?.put(.ContentType, req.body.value.Blob.content_type, globalThis); } req.calculateEstimatedByteSize(); @@ -785,12 +784,7 @@ pub fn doClone( callframe: *JSC.CallFrame, ) bun.JSError!JSC.JSValue { const this_value = callframe.this(); - var cloned = this.clone(bun.default_allocator, globalThis); - - if (globalThis.hasException()) { - cloned.finalize(); - return .zero; - } + const cloned = try this.clone(bun.default_allocator, globalThis); const js_wrapper = cloned.toJS(globalThis); if (js_wrapper != .zero) { @@ -835,7 +829,7 @@ pub fn setFetchHeaders( pub fn ensureFetchHeaders( this: *Request, globalThis: *JSC.JSGlobalObject, -) *FetchHeaders { +) bun.JSError!*FetchHeaders { if (this._headers) |headers| { // headers is already set return headers; @@ -857,8 +851,9 @@ pub fn ensureFetchHeaders( }; if (content_type) |content_type_| { - if (content_type_.len > 0) - this._headers.?.put(.ContentType, content_type_, globalThis); + if (content_type_.len > 0) { + try this._headers.?.put(.ContentType, content_type_, globalThis); + } } } @@ -893,11 +888,11 @@ pub fn getFetchHeaders( pub fn getHeaders( this: *Request, globalThis: *JSC.JSGlobalObject, -) JSC.JSValue { - return this.ensureFetchHeaders(globalThis).toJS(globalThis); +) bun.JSError!JSC.JSValue { + return (try this.ensureFetchHeaders(globalThis)).toJS(globalThis); } -pub fn cloneHeaders(this: *Request, globalThis: *JSGlobalObject) ?*FetchHeaders { +pub fn cloneHeaders(this: *Request, globalThis: *JSGlobalObject) bun.JSError!?*FetchHeaders { if (this._headers == null) { if (this.request_context.getRequest()) |uws_req| { this._headers = FetchHeaders.createFromUWS(uws_req); @@ -921,24 +916,24 @@ pub fn cloneInto( allocator: std.mem.Allocator, globalThis: *JSGlobalObject, preserve_url: bool, -) void { +) bun.JSError!void { _ = allocator; this.ensureURL() catch {}; const vm = globalThis.bunVM(); - const body = vm.initRequestBodyValue(this.body.value.clone(globalThis)) catch { - if (!globalThis.hasException()) { - globalThis.throw("Failed to clone request", .{}) catch {}; - } - return; - }; - const original_url = req.url; + var body_ = try this.body.value.clone(globalThis); + errdefer body_.deinit(); + const body = try vm.initRequestBodyValue(body_); + const url = if (preserve_url) req.url else this.url.dupeRef(); + errdefer if (!preserve_url) url.deref(); + const _headers = try this.cloneHeaders(globalThis); + errdefer if (_headers) |_h| _h.deref(); req.* = Request{ .body = body, - .url = if (preserve_url) original_url else this.url.dupeRef(), + .url = url, .method = this.method, .redirect = this.redirect, - ._headers = this.cloneHeaders(globalThis), + ._headers = _headers, }; if (this.signal) |signal| { @@ -946,9 +941,10 @@ pub fn cloneInto( } } -pub fn clone(this: *Request, allocator: std.mem.Allocator, globalThis: *JSGlobalObject) *Request { +pub fn clone(this: *Request, allocator: std.mem.Allocator, globalThis: *JSGlobalObject) bun.JSError!*Request { const req = Request.new(undefined); - this.cloneInto(req, allocator, globalThis, false); + errdefer bun.destroy(req); + try this.cloneInto(req, allocator, globalThis, false); return req; } diff --git a/src/bun.js/webcore/Response.zig b/src/bun.js/webcore/Response.zig index e33fe52ea1..caf4abf360 100644 --- a/src/bun.js/webcore/Response.zig +++ b/src/bun.js/webcore/Response.zig @@ -166,7 +166,7 @@ pub fn writeFormat(this: *Response, comptime Formatter: type, formatter: *Format try formatter.writeIndent(Writer, writer); try writer.writeAll(comptime Output.prettyFmt("headers: ", enable_ansi_colors)); - try formatter.printAs(.Private, Writer, writer, this.getHeaders(formatter.globalThis), .DOMWrapper, enable_ansi_colors); + try formatter.printAs(.Private, Writer, writer, try this.getHeaders(formatter.globalThis), .DOMWrapper, enable_ansi_colors); formatter.printComma(Writer, writer, enable_ansi_colors) catch bun.outOfMemory(); try writer.writeAll("\n"); @@ -232,14 +232,14 @@ pub fn getOK( return JSValue.jsBoolean(this.isOK()); } -fn getOrCreateHeaders(this: *Response, globalThis: *JSC.JSGlobalObject) *FetchHeaders { +fn getOrCreateHeaders(this: *Response, globalThis: *JSC.JSGlobalObject) bun.JSError!*FetchHeaders { if (this.init.headers == null) { this.init.headers = FetchHeaders.createEmpty(); if (this.body.value == .Blob) { const content_type = this.body.value.Blob.content_type; if (content_type.len > 0) { - this.init.headers.?.put(.ContentType, content_type, globalThis); + try this.init.headers.?.put(.ContentType, content_type, globalThis); } } } @@ -250,8 +250,8 @@ fn getOrCreateHeaders(this: *Response, globalThis: *JSC.JSGlobalObject) *FetchHe pub fn getHeaders( this: *Response, globalThis: *JSC.JSGlobalObject, -) JSC.JSValue { - return this.getOrCreateHeaders(globalThis).toJS(globalThis); +) bun.JSError!JSC.JSValue { + return (try this.getOrCreateHeaders(globalThis)).toJS(globalThis); } pub fn doClone( @@ -260,11 +260,7 @@ pub fn doClone( callframe: *JSC.CallFrame, ) bun.JSError!JSValue { const this_value = callframe.this(); - const cloned = this.clone(globalThis); - if (globalThis.hasException()) { - cloned.finalize(); - return .zero; - } + const cloned = try this.clone(globalThis); const js_wrapper = Response.makeMaybePooled(globalThis, cloned); @@ -293,17 +289,21 @@ pub fn makeMaybePooled(globalObject: *JSC.JSGlobalObject, ptr: *Response) JSValu pub fn cloneValue( this: *Response, globalThis: *JSGlobalObject, -) Response { +) bun.JSError!Response { + var body = try this.body.clone(globalThis); + errdefer body.deinit(bun.default_allocator); + var init = try this.init.clone(globalThis); + errdefer init.deinit(bun.default_allocator); return Response{ - .body = this.body.clone(globalThis), - .init = this.init.clone(globalThis), + .body = body, + .init = init, .url = this.url.clone(), .redirected = this.redirected, }; } -pub fn clone(this: *Response, globalThis: *JSGlobalObject) *Response { - return bun.new(Response, this.cloneValue(globalThis)); +pub fn clone(this: *Response, globalThis: *JSGlobalObject) bun.JSError!*Response { + return bun.new(Response, try this.cloneValue(globalThis)); } pub fn getStatus( @@ -421,8 +421,8 @@ pub fn constructJSON( } } - var headers_ref = response.getOrCreateHeaders(globalThis); - headers_ref.putDefault(.ContentType, MimeType.json.value, globalThis); + var headers_ref = try response.getOrCreateHeaders(globalThis); + try headers_ref.putDefault(.ContentType, MimeType.json.value, globalThis); did_succeed = true; return bun.new(Response, response).toJS(globalThis); } @@ -481,9 +481,9 @@ pub fn constructRedirect( break :brk response; }; - response.init.headers = response.getOrCreateHeaders(globalThis); + response.init.headers = try response.getOrCreateHeaders(globalThis); var headers_ref = response.init.headers.?; - headers_ref.put(.Location, url_string_slice.slice(), globalThis); + try headers_ref.put(.Location, url_string_slice.slice(), globalThis); const ptr = bun.new(Response, response); return ptr.toJS(globalThis); @@ -535,10 +535,10 @@ pub fn constructor(globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) b return s3.throwSignError(sign_err, globalThis); }; defer result.deinit(); - response.init.headers = response.getOrCreateHeaders(globalThis); + response.init.headers = try response.getOrCreateHeaders(globalThis); response.redirected = true; var headers_ref = response.init.headers.?; - headers_ref.put(.Location, result.url, globalThis); + try headers_ref.put(.Location, result.url, globalThis); return bun.new(Response, response); } } @@ -588,7 +588,7 @@ pub fn constructor(globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) b response.body.value.Blob.content_type.len > 0 and !response.init.headers.?.fastHas(.ContentType)) { - response.init.headers.?.put(.ContentType, response.body.value.Blob.content_type, globalThis); + try response.init.headers.?.put(.ContentType, response.body.value.Blob.content_type, globalThis); } response.calculateEstimatedByteSize(); @@ -602,11 +602,11 @@ pub const Init = struct { status_text: bun.String = bun.String.empty, method: Method = Method.GET, - pub fn clone(this: Init, ctx: *JSGlobalObject) Init { + pub fn clone(this: Init, ctx: *JSGlobalObject) bun.JSError!Init { var that = this; const headers = this.headers; if (headers) |head| { - that.headers = head.cloneThis(ctx); + that.headers = try head.cloneThis(ctx); } that.status_text = this.status_text.clone(); @@ -627,7 +627,7 @@ pub const Init = struct { // we can skip calling JS getters if (response_init.asDirect(Request)) |req| { if (req.getFetchHeadersUnlessEmpty()) |headers| { - result.headers = headers.cloneThis(globalThis); + result.headers = try headers.cloneThis(globalThis); } result.method = req.method; @@ -635,7 +635,7 @@ pub const Init = struct { } if (response_init.asDirect(Response)) |resp| { - return resp.init.clone(globalThis); + return try resp.init.clone(globalThis); } } @@ -646,10 +646,10 @@ pub const Init = struct { if (try response_init.fastGet(globalThis, .headers)) |headers| { if (headers.as(FetchHeaders)) |orig| { if (!orig.isEmpty()) { - result.headers = orig.cloneThis(globalThis); + result.headers = try orig.cloneThis(globalThis); } } else { - result.headers = FetchHeaders.createFromJS(globalThis, headers); + result.headers = try FetchHeaders.createFromJS(globalThis, headers); } } diff --git a/src/bun.js/webcore/S3File.zig b/src/bun.js/webcore/S3File.zig index 84b99cd8de..95c254a6fc 100644 --- a/src/bun.js/webcore/S3File.zig +++ b/src/bun.js/webcore/S3File.zig @@ -404,13 +404,13 @@ pub const S3BlobStatTask = struct { const globalThis = this.global; switch (result) { .success => |stat_result| { - this.promise.resolve(globalThis, S3Stat.init( + this.promise.resolve(globalThis, (S3Stat.init( stat_result.size, stat_result.etag, stat_result.contentType, stat_result.lastModified, globalThis, - ).toJS(globalThis)); + ) catch return).toJS(globalThis)); // TODO: properly propagate exception upwards }, .not_found, .failure => |err| { this.promise.reject(globalThis, err.toJS(globalThis, this.store.data.s3.path())); diff --git a/src/bun.js/webcore/S3Stat.zig b/src/bun.js/webcore/S3Stat.zig index e657dfb7e6..138412b331 100644 --- a/src/bun.js/webcore/S3Stat.zig +++ b/src/bun.js/webcore/S3Stat.zig @@ -25,10 +25,10 @@ pub const S3Stat = struct { contentType: []const u8, lastModified: []const u8, globalThis: *JSC.JSGlobalObject, - ) *@This() { + ) bun.JSError!*@This() { var date_str = bun.String.init(lastModified); defer date_str.deref(); - const last_modified = date_str.parseDate(globalThis); + const last_modified = try date_str.parseDate(globalThis); return S3Stat.new(.{ .size = size, diff --git a/src/bun.js/webcore/Sink.zig b/src/bun.js/webcore/Sink.zig index 00105bec52..0dcbee10c2 100644 --- a/src/bun.js/webcore/Sink.zig +++ b/src/bun.js/webcore/Sink.zig @@ -251,12 +251,12 @@ pub fn JSSink(comptime SinkType: type, comptime abi_name: []const u8) type { const DetachPtrFn = *const fn (JSValue) callconv(.C) void; const assignToStreamExtern = @extern(AssignToStreamFn, .{ .name = abi_name ++ "__assignToStream" }); - const onCloseExtern = @extern(OnCloseFn, .{ .name = abi_name ++ "__onClose" }); + const onCloseExtern = @extern(OnCloseFn, .{ .name = abi_name ++ "__onClose" }).*; const onReadyExtern = @extern(OnReadyFn, .{ .name = abi_name ++ "__onReady" }); const onStartExtern = @extern(OnStartFn, .{ .name = abi_name ++ "__onStart" }); const createObjectExtern = @extern(CreateObjectFn, .{ .name = abi_name ++ "__createObject" }); const setDestroyCallbackExtern = @extern(SetDestroyCallbackFn, .{ .name = abi_name ++ "__setDestroyCallback" }); - const detachPtrExtern = @extern(DetachPtrFn, .{ .name = abi_name ++ "__detachPtr" }); + const detachPtrExtern = @extern(DetachPtrFn, .{ .name = abi_name ++ "__detachPtr" }).*; pub fn assignToStream(globalThis: *JSGlobalObject, stream: JSValue, ptr: *anyopaque, jsvalue_ptr: **anyopaque) JSValue { return assignToStreamExtern(globalThis, stream, ptr, jsvalue_ptr); @@ -264,7 +264,8 @@ pub fn JSSink(comptime SinkType: type, comptime abi_name: []const u8) type { pub fn onClose(ptr: JSValue, reason: JSValue) void { JSC.markBinding(@src()); - return onCloseExtern(ptr, reason); + const globalThis = bun.jsc.VirtualMachine.get().global; // TODO: this should be got from a parameter + return bun.jsc.fromJSHostCallGeneric(globalThis, @src(), onCloseExtern, .{ ptr, reason }) catch return; // TODO: properly propagate exception upwards } pub fn onReady(ptr: JSValue, amount: JSValue, offset: JSValue) void { @@ -287,8 +288,8 @@ pub fn JSSink(comptime SinkType: type, comptime abi_name: []const u8) type { return setDestroyCallbackExtern(value, callback); } - pub fn detachPtr(ptr: JSValue) void { - return detachPtrExtern(ptr); + pub fn detachPtr(globalThis: *JSGlobalObject, ptr: JSValue) bun.JSError!void { + return bun.jsc.fromJSHostCallGeneric(globalThis, @src(), detachPtrExtern, .{ptr}); } pub fn construct(globalThis: *JSGlobalObject, _: *JSC.CallFrame) bun.JSError!JSC.JSValue { @@ -316,7 +317,7 @@ pub fn JSSink(comptime SinkType: type, comptime abi_name: []const u8) type { this.sink.finalize(); } - pub fn detach(this: *ThisSink) void { + pub fn detach(this: *ThisSink, globalThis: *JSGlobalObject) void { if (comptime !@hasField(SinkType, "signal")) return; @@ -326,7 +327,7 @@ pub fn JSSink(comptime SinkType: type, comptime abi_name: []const u8) type { this.sink.signal.clear(); const value = @as(JSValue, @enumFromInt(@as(JSC.JSValue.backing_int, @bitCast(@intFromPtr(ptr))))); value.unprotect(); - detachPtr(value); + detachPtr(globalThis, value) catch {}; // TODO: properly propagate exception upwards } // The code generator encodes two distinct failure types using 0 and 1 diff --git a/src/bun.js/webcore/fetch.zig b/src/bun.js/webcore/fetch.zig index d91ac40176..22df79df26 100644 --- a/src/bun.js/webcore/fetch.zig +++ b/src/bun.js/webcore/fetch.zig @@ -193,7 +193,7 @@ pub const FetchTasklet = struct { // just grab the ref return FetchTasklet.HTTPRequestBody{ .ReadableStream = body_value.Locked.readable }; } - const readable = body_value.toReadableStream(globalThis); + const readable = try body_value.toReadableStream(globalThis); if (!readable.isEmptyOrUndefinedOrNull() and body_value == .Locked and body_value.Locked.readable.has()) { return FetchTasklet.HTTPRequestBody{ .ReadableStream = body_value.Locked.readable }; } @@ -2073,7 +2073,7 @@ pub fn Bun__fetch_( if (req.body.value.Locked.readable.has()) { break :extract_body FetchTasklet.HTTPRequestBody{ .ReadableStream = JSC.WebCore.ReadableStream.Strong.init(req.body.value.Locked.readable.get(globalThis).?, globalThis) }; } - const readable = req.body.value.toReadableStream(globalThis); + const readable = try req.body.value.toReadableStream(globalThis); if (!readable.isEmptyOrUndefinedOrNull() and req.body.value == .Locked and req.body.value.Locked.readable.has()) { break :extract_body FetchTasklet.HTTPRequestBody{ .ReadableStream = JSC.WebCore.ReadableStream.Strong.init(req.body.value.Locked.readable.get(globalThis).?, globalThis) }; } @@ -2119,7 +2119,7 @@ pub fn Bun__fetch_( break :brk headers__; } - if (FetchHeaders.createFromJS(ctx, headers_value)) |headers__| { + if (try FetchHeaders.createFromJS(ctx, headers_value)) |headers__| { fetch_headers_to_deref = headers__; break :brk headers__; } @@ -2153,7 +2153,7 @@ pub fn Bun__fetch_( break :brk headers__; } - if (FetchHeaders.createFromJS(ctx, headers_value)) |headers__| { + if (try FetchHeaders.createFromJS(ctx, headers_value)) |headers__| { fetch_headers_to_deref = headers__; break :brk headers__; } @@ -2348,7 +2348,7 @@ pub fn Bun__fetch_( prepare_body: { // is a S3 file we can use chunked here - if (JSC.WebCore.ReadableStream.fromJS(JSC.WebCore.ReadableStream.fromBlobCopyRef(globalThis, &body.AnyBlob.Blob, s3.MultiPartUploadOptions.DefaultPartSize), globalThis)) |stream| { + if (try JSC.WebCore.ReadableStream.fromJS(try JSC.WebCore.ReadableStream.fromBlobCopyRef(globalThis, &body.AnyBlob.Blob, s3.MultiPartUploadOptions.DefaultPartSize), globalThis)) |stream| { var old = body; defer old.detach(); body = .{ .ReadableStream = JSC.WebCore.ReadableStream.Strong.init(stream, globalThis) }; diff --git a/src/bundler/DeferredBatchTask.zig b/src/bundler/DeferredBatchTask.zig index 165292262c..3393d48ee3 100644 --- a/src/bundler/DeferredBatchTask.zig +++ b/src/bundler/DeferredBatchTask.zig @@ -40,7 +40,7 @@ pub fn runOnJSThread(this: *DeferredBatchTask) void { completion.result == .err else false, - ); + ) catch return; } const bun = @import("bun"); diff --git a/src/cli/test_command.zig b/src/cli/test_command.zig index 26a22eacd2..a5b3693993 100644 --- a/src/cli/test_command.zig +++ b/src/cli/test_command.zig @@ -1825,7 +1825,7 @@ pub const TestCommand = struct { const file_start = reporter.jest.files.len; const resolution = try vm.transpiler.resolveEntryPoint(file_name); - vm.clearEntryPoint(); + try vm.clearEntryPoint(); const file_path = resolution.path_pair.primary.text; const file_title = bun.path.relative(FileSystem.instance.top_level_dir, file_path); @@ -1925,9 +1925,9 @@ pub const TestCommand = struct { vm.global.handleRejectedPromises(); if (repeat_index > 0) { - vm.clearEntryPoint(); + try vm.clearEntryPoint(); var entry = JSC.ZigString.init(file_path); - vm.global.deleteModuleRegistryEntry(&entry); + try vm.global.deleteModuleRegistryEntry(&entry); } if (Output.is_github_action) { diff --git a/src/codegen/generate-classes.ts b/src/codegen/generate-classes.ts index 08b824b674..5cb5038cb8 100644 --- a/src/codegen/generate-classes.ts +++ b/src/codegen/generate-classes.ts @@ -715,11 +715,8 @@ JSC::EncodedJSValue JSC_HOST_CALL_ATTRIBUTES ${name}::construct(JSC::JSGlobalObj getFunctionRealm(globalObject, newTarget) ); RETURN_IF_EXCEPTION(scope, {}); - structure = InternalFunction::createSubclassStructure( - globalObject, - newTarget, - functionGlobalObject->${className(typeName)}Structure() - ); + structure = InternalFunction::createSubclassStructure(globalObject, newTarget, functionGlobalObject->${className(typeName)}Structure()); + RETURN_IF_EXCEPTION(scope, {}); } ` + diff --git a/src/codegen/generate-jssink.ts b/src/codegen/generate-jssink.ts index 845e8ed854..13d71b6d18 100644 --- a/src/codegen/generate-jssink.ts +++ b/src/codegen/generate-jssink.ts @@ -446,6 +446,7 @@ JSC_DEFINE_HOST_FUNCTION(${controller}__close, (JSC::JSGlobalObject * lexicalGlo } controller->detach(); + RETURN_IF_EXCEPTION(scope, {}); ${name}__close(lexicalGlobalObject, ptr); return JSC::JSValue::encode(JSC::jsUndefined()); } @@ -459,7 +460,7 @@ JSC_DEFINE_HOST_FUNCTION(${controller}__end, (JSC::JSGlobalObject * lexicalGloba WebCore::${controller}* controller = JSC::jsDynamicCast(callFrame->thisValue()); if (!controller) { scope.throwException(globalObject, JSC::createTypeError(globalObject, "Expected ${controller}"_s)); - return JSC::JSValue::encode(JSC::jsUndefined()); + return {}; } void *ptr = controller->wrapped(); @@ -468,6 +469,7 @@ JSC_DEFINE_HOST_FUNCTION(${controller}__end, (JSC::JSGlobalObject * lexicalGloba } controller->detach(); + RETURN_IF_EXCEPTION(scope, {}); return ${name}__endWithSink(ptr, lexicalGlobalObject); } @@ -513,6 +515,7 @@ JSC_DEFINE_HOST_FUNCTION(${name}__doClose, (JSC::JSGlobalObject * lexicalGlobalO } sink->detach(); + RETURN_IF_EXCEPTION(scope, {}); ${name}__close(lexicalGlobalObject, ptr); return JSC::JSValue::encode(JSC::jsUndefined()); } diff --git a/src/deps/uws/Request.zig b/src/deps/uws/Request.zig index 1f614e037a..fe43abd56a 100644 --- a/src/deps/uws/Request.zig +++ b/src/deps/uws/Request.zig @@ -25,12 +25,12 @@ pub const Request = opaque { if (len == 0) return null; return ptr[0..len]; } - pub fn dateForHeader(req: *Request, name: []const u8) ?u64 { + pub fn dateForHeader(req: *Request, name: []const u8) bun.JSError!?u64 { const value = header(req, name); if (value == null) return null; var string = bun.String.init(value.?); defer string.deref(); - const date_f64 = bun.String.parseDate(&string, bun.JSC.VirtualMachine.get().global); + const date_f64 = try bun.String.parseDate(&string, bun.JSC.VirtualMachine.get().global); if (!std.math.isNan(date_f64) and std.math.isFinite(date_f64)) { return @intFromFloat(date_f64); } diff --git a/src/logger.zig b/src/logger.zig index 8fdea0d6ca..ecf8c130a1 100644 --- a/src/logger.zig +++ b/src/logger.zig @@ -742,7 +742,7 @@ pub const Log = struct { } } - pub fn toJS(this: Log, global: *JSC.JSGlobalObject, allocator: std.mem.Allocator, message: string) bun.OOM!JSC.JSValue { + pub fn toJS(this: Log, global: *JSC.JSGlobalObject, allocator: std.mem.Allocator, message: string) bun.JSError!JSC.JSValue { const msgs: []const Msg = this.msgs.items; var errors_stack: [256]JSC.JSValue = undefined; @@ -764,7 +764,7 @@ pub const Log = struct { }; } const out = JSC.ZigString.init(message); - const agg = global.createAggregateError(errors_stack[0..count], &out); + const agg = try global.createAggregateError(errors_stack[0..count], &out); return agg; }, } diff --git a/src/napi/napi.zig b/src/napi/napi.zig index fab894bcde..d99cfcb896 100644 --- a/src/napi/napi.zig +++ b/src/napi/napi.zig @@ -1186,7 +1186,7 @@ pub export fn napi_create_buffer_copy(env_: napi_env, length: usize, data: [*]u8 const result = result_ orelse { return env.invalidArg(); }; - var buffer = JSC.JSValue.createBufferFromLength(env.toJS(), length); + var buffer = JSC.JSValue.createBufferFromLength(env.toJS(), length) catch return env.setLastError(.pending_exception); if (buffer.asArrayBuffer(env.toJS())) |array_buf| { if (length > 0) { @memcpy(array_buf.slice()[0..length], data[0..length]); diff --git a/src/s3/client.zig b/src/s3/client.zig index 65feaa76dd..f7c9baae15 100644 --- a/src/s3/client.zig +++ b/src/s3/client.zig @@ -605,14 +605,14 @@ pub fn readableStream( size: ?usize, proxy_url: ?[]const u8, globalThis: *JSC.JSGlobalObject, -) JSC.JSValue { +) bun.JSError!JSC.JSValue { var reader = JSC.WebCore.ByteStream.Source.new(.{ .context = undefined, .globalThis = globalThis, }); reader.context.setup(); - const readable_value = reader.toReadableStream(globalThis); + const readable_value = try reader.toReadableStream(globalThis); const S3DownloadStreamWrapper = struct { pub const new = bun.TrivialNew(@This()); diff --git a/src/shell/shell.zig b/src/shell/shell.zig index 38b3fb8281..6e65f2d4fb 100644 --- a/src/shell/shell.zig +++ b/src/shell/shell.zig @@ -3781,7 +3781,7 @@ pub fn handleTemplateValue( return; } - if (JSC.WebCore.ReadableStream.fromJS(template_value, globalThis)) |rstream| { + if (try JSC.WebCore.ReadableStream.fromJS(template_value, globalThis)) |rstream| { _ = rstream; const idx = out_jsobjs.items.len; diff --git a/src/shell/states/Cmd.zig b/src/shell/states/Cmd.zig index 4ca8f57a26..b326cc778a 100644 --- a/src/shell/states/Cmd.zig +++ b/src/shell/states/Cmd.zig @@ -512,7 +512,7 @@ fn initSubproc(this: *Cmd) Yield { defer shellio.deref(); this.io.to_subproc_stdio(&spawn_args.stdio, &shellio); - if (this.initRedirections(&spawn_args)) |yield| return yield; + if (this.initRedirections(&spawn_args) catch .failed) |yield| return yield; const buffered_closed = BufferedIoClosed.fromStdio(&spawn_args.stdio); log("cmd ({x}) set buffered closed => {any}", .{ @intFromPtr(this), buffered_closed }); @@ -547,7 +547,7 @@ fn initSubproc(this: *Cmd) Yield { return .suspended; } -fn initRedirections(this: *Cmd, spawn_args: *Subprocess.SpawnArgs) ?Yield { +fn initRedirections(this: *Cmd, spawn_args: *Subprocess.SpawnArgs) bun.JSError!?Yield { if (this.node.redirect_file) |redirect| { const in_cmd_subst = false; @@ -569,30 +569,29 @@ fn initRedirections(this: *Cmd, spawn_args: *Subprocess.SpawnArgs) ?Yield { } else if (this.base.interpreter.jsobjs[val.idx].as(JSC.WebCore.Blob)) |blob__| { const blob = blob__.dupe(); if (this.node.redirect.stdin) { - spawn_args.stdio[stdin_no].extractBlob(global, .{ .Blob = blob }, stdin_no) catch return .failed; + try spawn_args.stdio[stdin_no].extractBlob(global, .{ .Blob = blob }, stdin_no); } else if (this.node.redirect.stdout) { - spawn_args.stdio[stdin_no].extractBlob(global, .{ .Blob = blob }, stdout_no) catch return .failed; + try spawn_args.stdio[stdin_no].extractBlob(global, .{ .Blob = blob }, stdout_no); } else if (this.node.redirect.stderr) { - spawn_args.stdio[stdin_no].extractBlob(global, .{ .Blob = blob }, stderr_no) catch return .failed; + try spawn_args.stdio[stdin_no].extractBlob(global, .{ .Blob = blob }, stderr_no); } - } else if (JSC.WebCore.ReadableStream.fromJS(this.base.interpreter.jsobjs[val.idx], global)) |rstream| { + } else if (try JSC.WebCore.ReadableStream.fromJS(this.base.interpreter.jsobjs[val.idx], global)) |rstream| { _ = rstream; @panic("TODO SHELL READABLE STREAM"); } else if (this.base.interpreter.jsobjs[val.idx].as(JSC.WebCore.Response)) |req| { req.getBodyValue().toBlobIfPossible(); if (this.node.redirect.stdin) { - spawn_args.stdio[stdin_no].extractBlob(global, req.getBodyValue().useAsAnyBlob(), stdin_no) catch return .failed; + try spawn_args.stdio[stdin_no].extractBlob(global, req.getBodyValue().useAsAnyBlob(), stdin_no); } if (this.node.redirect.stdout) { - spawn_args.stdio[stdout_no].extractBlob(global, req.getBodyValue().useAsAnyBlob(), stdout_no) catch return .failed; + try spawn_args.stdio[stdout_no].extractBlob(global, req.getBodyValue().useAsAnyBlob(), stdout_no); } if (this.node.redirect.stderr) { - spawn_args.stdio[stderr_no].extractBlob(global, req.getBodyValue().useAsAnyBlob(), stderr_no) catch return .failed; + try spawn_args.stdio[stderr_no].extractBlob(global, req.getBodyValue().useAsAnyBlob(), stderr_no); } } else { const jsval = this.base.interpreter.jsobjs[val.idx]; - global.throw("Unknown JS value used in shell: {}", .{jsval.fmtString(global)}) catch {}; // TODO: propagate - return .failed; + return global.throw("Unknown JS value used in shell: {}", .{jsval.fmtString(global)}); } }, .atom => { diff --git a/src/shell/subproc.zig b/src/shell/subproc.zig index 595aa298a1..bdd408f9c3 100644 --- a/src/shell/subproc.zig +++ b/src/shell/subproc.zig @@ -1293,7 +1293,7 @@ pub const PipeReader = struct { }, .err => |err| { _ = err; // autofix - const empty = JSC.WebCore.ReadableStream.empty(globalObject); + const empty = try JSC.WebCore.ReadableStream.empty(globalObject); JSC.WebCore.ReadableStream.cancel(&JSC.WebCore.ReadableStream.fromJS(empty, globalObject).?, globalObject); return empty; }, diff --git a/src/sql/postgres/DataCell.zig b/src/sql/postgres/DataCell.zig index 8f62fcc4da..0081e4ce4b 100644 --- a/src/sql/postgres/DataCell.zig +++ b/src/sql/postgres/DataCell.zig @@ -273,7 +273,7 @@ pub const DataCell = extern struct { const date_str = slice[1..current_idx]; var str = bun.String.init(date_str); defer str.deref(); - try array.append(bun.default_allocator, DataCell{ .tag = .date, .value = .{ .date = str.parseDate(globalObject) } }); + try array.append(bun.default_allocator, DataCell{ .tag = .date, .value = .{ .date = try str.parseDate(globalObject) } }); slice = trySlice(slice, current_idx + 1); continue; @@ -370,7 +370,7 @@ pub const DataCell = extern struct { if (arrayType == .date_array) { var str = bun.String.init(element); defer str.deref(); - try array.append(bun.default_allocator, DataCell{ .tag = .date, .value = .{ .date = str.parseDate(globalObject) } }); + try array.append(bun.default_allocator, DataCell{ .tag = .date, .value = .{ .date = try str.parseDate(globalObject) } }); } else { // the only escape sequency possible here is \b if (bun.strings.eqlComptime(element, "\\b")) { @@ -723,7 +723,7 @@ pub const DataCell = extern struct { } else { var str = bun.String.init(bytes); defer str.deref(); - return DataCell{ .tag = .date, .value = .{ .date = str.parseDate(globalObject) } }; + return DataCell{ .tag = .date, .value = .{ .date = try str.parseDate(globalObject) } }; } }, diff --git a/src/sql/postgres/PostgresRequest.zig b/src/sql/postgres/PostgresRequest.zig index c8769f4047..c811f0432a 100644 --- a/src/sql/postgres/PostgresRequest.zig +++ b/src/sql/postgres/PostgresRequest.zig @@ -115,7 +115,7 @@ pub fn writeBind( }, .timestamp, .timestamptz => { const l = try writer.length(); - try writer.int8(types.date.fromJS(globalObject, value)); + try writer.int8(try types.date.fromJS(globalObject, value)); try l.writeExcludingSelf(); }, .bytea => { diff --git a/src/sql/postgres/types/date.zig b/src/sql/postgres/types/date.zig index cdec908240..7dc5ee6eef 100644 --- a/src/sql/postgres/types/date.zig +++ b/src/sql/postgres/types/date.zig @@ -11,7 +11,7 @@ pub fn fromBinary(bytes: []const u8) f64 { return (double_microseconds / std.time.us_per_ms) + POSTGRES_EPOCH_DATE; } -pub fn fromJS(globalObject: *JSC.JSGlobalObject, value: JSValue) i64 { +pub fn fromJS(globalObject: *JSC.JSGlobalObject, value: JSValue) bun.JSError!i64 { const double_value = if (value.isDate()) value.getUnixTimestamp() else if (value.isNumber()) @@ -19,7 +19,7 @@ pub fn fromJS(globalObject: *JSC.JSGlobalObject, value: JSValue) i64 { else if (value.isString()) brk: { var str = value.toBunString(globalObject) catch @panic("unreachable"); defer str.deref(); - break :brk str.parseDate(globalObject); + break :brk try str.parseDate(globalObject); } else return 0; const unix_timestamp: i64 = @intFromFloat(double_value); diff --git a/src/string.zig b/src/string.zig index d0b1195bc4..f469543c45 100644 --- a/src/string.zig +++ b/src/string.zig @@ -854,9 +854,9 @@ pub const String = extern struct { return bun.jsc.fromJSHostCall(globalObject, @src(), BunString__createUTF8ForJS, .{ globalObject, builder.items.ptr, builder.items.len }); } - pub fn parseDate(this: *String, globalObject: *JSC.JSGlobalObject) f64 { + pub fn parseDate(this: *String, globalObject: *JSC.JSGlobalObject) bun.JSError!f64 { JSC.markBinding(@src()); - return Bun__parseDate(globalObject, this); + return bun.jsc.fromJSHostCallGeneric(globalObject, @src(), Bun__parseDate, .{ globalObject, this }); } pub fn ref(this: String) void { diff --git a/src/sys.zig b/src/sys.zig index d372aea12b..b5e8f08c4d 100644 --- a/src/sys.zig +++ b/src/sys.zig @@ -592,7 +592,7 @@ pub const Error = struct { // format taken from Node.js 'exceptions.cc' // search keyword: `Local UVException(Isolate* isolate,` - var message_buf: [4096]u8 = undefined; + var message_buf: [4096]u8 = @splat(0); const message = message: { var stream = std.io.fixedBufferStream(&message_buf); const writer = stream.writer(); diff --git a/test/cli/watch/watch.test.ts b/test/cli/watch/watch.test.ts index a2ecb7c255..7674ea7b1d 100644 --- a/test/cli/watch/watch.test.ts +++ b/test/cli/watch/watch.test.ts @@ -9,7 +9,7 @@ let watchee: Subprocess; for (const dir of ["dir", "©️"]) { it.todoIf(isBroken && isWindows)( - `should watch files ${dir === "dir" ? "" : "(non-ascii path)"}`, + `should watch files${dir === "dir" ? "" : " (non-ascii path)"}`, async () => { const cwd = join(tmpdirSync(), dir); const path = join(cwd, "watchee.js"); diff --git a/test/internal/ban-words.test.ts b/test/internal/ban-words.test.ts index 0943437d52..2b6ff20481 100644 --- a/test/internal/ban-words.test.ts +++ b/test/internal/ban-words.test.ts @@ -41,11 +41,12 @@ const words: Record ".stdFile()": { reason: "Prefer bun.sys + bun.FD instead of std.fs.File. Zig hides 'errno' when Bun wants to match libuv", limit: 18 }, ".stdDir()": { reason: "Prefer bun.sys + bun.FD instead of std.fs.File. Zig hides 'errno' when Bun wants to match libuv", limit: 40 }, ".arguments_old(": { reason: "Please migrate to .argumentsAsArray() or another argument API", limit: 280 }, - "// autofix": { reason: "Evaluate if this variable should be deleted entirely or explicitly discarded.", limit: 173 }, + "// autofix": { reason: "Evaluate if this variable should be deleted entirely or explicitly discarded.", limit: 172 }, "global.hasException": { reason: "Incompatible with strict exception checks. Use a CatchScope instead.", limit: 28 }, "globalObject.hasException": { reason: "Incompatible with strict exception checks. Use a CatchScope instead.", limit: 42 }, - "globalThis.hasException": { reason: "Incompatible with strict exception checks. Use a CatchScope instead.", limit: 140 }, + "globalThis.hasException": { reason: "Incompatible with strict exception checks. Use a CatchScope instead.", limit: 134 }, + "EXCEPTION_ASSERT(!scope.exception())": { reason: "Use scope.assertNoException() instead" }, }; const words_keys = [...Object.keys(words)]; diff --git a/test/js/node/net/double-connect.test.ts b/test/js/node/net/double-connect.test.ts index c14d410c4a..cafd61ae8f 100644 --- a/test/js/node/net/double-connect.test.ts +++ b/test/js/node/net/double-connect.test.ts @@ -1,6 +1,5 @@ import { bunExe } from "harness"; -// TODO: fix double connect test.failing("double connect", () => { const output = Bun.spawnSync({ cmd: [bunExe(), import.meta.dirname + "/double-connect-repro.mjs", "minimal"], diff --git a/test/no-validate-exceptions.txt b/test/no-validate-exceptions.txt index 6e2885312c..979e8fc751 100644 --- a/test/no-validate-exceptions.txt +++ b/test/no-validate-exceptions.txt @@ -1,607 +1,4 @@ # List of tests for which we do NOT set validateExceptionChecks=1 when running in ASan CI -test/bake/dev-and-prod.test.ts -test/bake/dev/plugins.test.ts -test/bake/dev/vfile.test.ts -test/bake/dev/ssg-pages-router.test.ts -test/bake/framework-router.test.ts -test/bundler/bun-build-api.test.ts -test/bundler/bundler_banner.test.ts -test/bundler/bundler_browser.test.ts -test/bundler/bundler_bun.test.ts -test/bundler/bundler_cjs2esm.test.ts -test/bundler/bundler_comments.test.ts -test/bundler/bundler_compile.test.ts -test/bundler/bundler_decorator_metadata.test.ts -test/bundler/bundler_defer.test.ts -test/bundler/bundler_drop.test.ts -test/bundler/bundler_env.test.ts -test/bundler/bundler_footer.test.ts -test/bundler/bundler_html.test.ts -test/bundler/bundler_html_server.test.ts -test/bundler/bundler_jsx.test.ts -test/bundler/bundler_minify.test.ts -test/bundler/bundler_minify_symbol_for.test.ts -test/bundler/bundler_naming.test.ts -test/bundler/bundler_plugin.test.ts -test/bundler/bundler_regressions.test.ts -test/bundler/bundler_splitting.test.ts -test/bundler/bundler_string.test.ts -test/bundler/css/css-modules.test.ts -test/bundler/css/wpt/background-computed.test.ts -test/bundler/css/wpt/color-computed-rgb.test.ts -test/bundler/css/wpt/color-computed.test.ts -test/bundler/css/wpt/relative_color_out_of_gamut.test.ts -test/bundler/esbuild/css.test.ts -test/bundler/esbuild/dce.test.ts -test/bundler/esbuild/extra.test.ts -test/bundler/esbuild/importstar.test.ts -test/cli/install/isolated-install.test.ts -test/bundler/esbuild/importstar_ts.test.ts -test/bundler/esbuild/loader.test.ts -test/bundler/esbuild/lower.test.ts -test/bundler/esbuild/packagejson.test.ts -test/bundler/esbuild/splitting.test.ts -test/bundler/esbuild/ts.test.ts -test/bundler/esbuild/tsconfig.test.ts -test/bundler/html-import-manifest.test.ts -test/bundler/transpiler/bun-pragma.test.ts -test/bundler/transpiler/jsx-production.test.ts -test/bundler/transpiler/macro-test.test.ts -test/bundler/transpiler/runtime-transpiler.test.ts -test/bundler/transpiler/transpiler.test.js -test/cli/init/init.test.ts -test/cli/install/bun-add.test.ts -test/cli/install/bun-audit.test.ts -test/cli/install/bun-create.test.ts -test/cli/install/bun-info.test.ts -test/cli/install/bun-install-dep.test.ts -test/cli/install/bun-install-lifecycle-scripts.test.ts -test/cli/install/bun-install-patch.test.ts -test/cli/install/bun-install-registry.test.ts -test/cli/install/bun-install-retry.test.ts -test/cli/install/bun-link.test.ts -test/cli/install/bun-lock.test.ts -test/cli/install/bun-lockb.test.ts -test/cli/install/bun-pack.test.ts -test/cli/install/bun-patch.test.ts -test/cli/install/bun-pm.test.ts -test/cli/install/bun-pm-version.test.ts -test/cli/install/bun-publish.test.ts -test/cli/install/bun-remove.test.ts -test/cli/install/bun-update.test.ts -test/cli/install/bun-upgrade.test.ts -test/cli/install/bun-workspaces.test.ts -test/cli/install/bunx.test.ts -test/cli/install/catalogs.test.ts -test/cli/install/npmrc.test.ts -test/cli/install/overrides.test.ts -test/cli/run/env.test.ts -test/cli/run/esm-defineProperty.test.ts -test/cli/run/garbage-env.test.ts -test/cli/run/jsx-namespaced-attributes.test.ts -test/cli/run/log-test.test.ts -test/cli/run/require-and-import-trailing.test.ts -test/cli/run/run-autoinstall.test.ts -test/cli/run/run-eval.test.ts -test/cli/run/self-reference.test.ts -test/cli/run/shell-keepalive.test.ts -test/cli/test/bun-test.test.ts -test/cli/watch/watch.test.ts -test/config/bunfig/preload.test.ts -test/integration/bun-types/bun-types.test.ts -test/integration/bun-types/fixture/serve-types.test.ts -test/integration/esbuild/esbuild.test.ts -test/integration/jsdom/jsdom.test.ts -test/integration/mysql2/mysql2.test.ts -test/integration/nest/nest_metadata.test.ts -test/integration/sass/sass.test.ts -test/integration/sharp/sharp.test.ts -test/integration/svelte/client-side.test.ts -test/integration/typegraphql/src/typegraphql.test.ts -test/cli/run/sql-preconnect.test.ts -test/internal/bindgen.test.ts -test/js/bun/bun-object/deep-match.spec.ts -test/js/bun/bun-object/write.spec.ts -test/js/bun/console/bun-inspect-table.test.ts -test/js/bun/console/console-iterator.test.ts -test/js/bun/console/console-table.test.ts -test/js/bun/cookie/cookie-expires-validation.test.ts -test/js/bun/cookie/cookie-map.test.ts -test/js/bun/cookie/cookie.test.ts -test/js/bun/crypto/cipheriv-decipheriv.test.ts -test/js/bun/crypto/wpt-webcrypto.generateKey.test.ts -test/js/bun/dns/resolve-dns.test.ts -test/js/bun/glob/scan.test.ts -test/js/bun/globals.test.js -test/js/bun/http/async-iterator-stream.test.ts -test/js/bun/http/bun-connect-x509.test.ts -test/js/bun/http/bun-serve-args.test.ts -test/js/bun/http/bun-serve-cookies.test.ts -test/js/bun/http/bun-serve-file.test.ts -test/js/bun/http/bun-serve-headers.test.ts -test/js/bun/http/bun-serve-html-entry.test.ts -test/js/bun/http/bun-serve-html-manifest.test.ts -test/js/bun/http/bun-serve-html.test.ts -test/js/bun/http/bun-serve-routes.test.ts -test/js/bun/http/bun-serve-static.test.ts -test/js/bun/http/bun-server.test.ts -test/js/bun/http/decodeURIComponentSIMD.test.ts -test/js/bun/http/fetch-file-upload.test.ts -test/js/bun/http/hspec.test.ts -test/js/bun/http/http-server-chunking.test.ts -test/js/bun/http/http-spec.ts -test/js/bun/http/leaks-test.test.ts -test/js/bun/http/proxy.test.ts -test/js/bun/http/serve-body-leak.test.ts -test/js/bun/http/serve-listen.test.ts -test/js/bun/http/serve.test.ts -test/js/bun/import-attributes/import-attributes.test.ts -test/js/bun/resolve/resolve.test.ts -test/js/bun/ini/ini.test.ts -test/js/bun/io/bun-write.test.js -test/js/bun/jsc/bun-jsc.test.ts -test/js/bun/jsc/domjit.test.ts -test/js/bun/net/socket.test.ts -test/js/bun/net/tcp-server.test.ts -test/js/bun/net/tcp.spec.ts -test/js/bun/net/tcp.test.ts -test/js/bun/patch/patch.test.ts -test/js/bun/perf_hooks/histogram.test.ts -test/js/bun/plugin/plugins.test.ts -test/js/bun/resolve/build-error.test.ts -test/js/bun/resolve/bun-lock.test.ts -test/js/bun/resolve/esModule-annotation.test.js -test/js/bun/resolve/import-custom-condition.test.ts -test/js/bun/resolve/import-empty.test.js -test/js/bun/resolve/import-meta-resolve.test.mjs -test/js/bun/resolve/import-meta.test.js -test/js/bun/resolve/jsonc.test.ts -test/js/bun/resolve/require.test.ts -test/js/bun/resolve/toml/toml.test.js -test/js/bun/s3/s3-insecure.test.ts -test/js/bun/s3/s3-list-objects.test.ts -test/js/bun/s3/s3-storage-class.test.ts -test/js/bun/s3/s3.test.ts -test/js/bun/shell/bunshell-default.test.ts -test/js/bun/shell/bunshell-file.test.ts -test/js/bun/shell/bunshell-instance.test.ts -test/js/bun/shell/commands/basename.test.ts -test/js/bun/shell/commands/dirname.test.ts -test/js/bun/shell/commands/echo.test.ts -test/js/bun/shell/commands/exit.test.ts -test/js/bun/shell/commands/false.test.ts -test/js/bun/shell/commands/ls.test.ts -test/js/bun/shell/commands/mv.test.ts -test/js/bun/shell/commands/rm.test.ts -test/js/bun/shell/commands/seq.test.ts -test/js/bun/shell/commands/true.test.ts -test/js/bun/shell/commands/which.test.ts -test/js/bun/shell/commands/yes.test.ts -test/js/bun/shell/env.positionals.test.ts -test/js/bun/shell/exec.test.ts -test/js/bun/shell/file-io.test.ts -test/js/bun/shell/lazy.test.ts -test/js/bun/shell/leak.test.ts -test/js/bun/shell/lex.test.ts -test/js/bun/shell/shell-hang.test.ts -test/js/bun/shell/shell-load.test.ts -test/js/bun/shell/shelloutput.test.ts -test/js/bun/shell/throw.test.ts -test/js/bun/shell/yield.test.ts -test/js/bun/spawn/bun-ipc-inherit.test.ts -test/js/bun/spawn/job-object-bug.test.ts -test/js/bun/spawn/spawn-empty-arrayBufferOrBlob.test.ts -test/js/bun/spawn/spawn-path.test.ts -test/js/bun/spawn/spawn-stdin-destroy.test.ts -test/js/bun/spawn/spawn-stdin-readable-stream-edge-cases.test.ts -test/js/bun/spawn/spawn-stdin-readable-stream-integration.test.ts -test/js/bun/spawn/spawn-stdin-readable-stream-sync.test.ts -test/js/bun/spawn/spawn-stdin-readable-stream.test.ts -test/js/bun/spawn/spawn-stream-serve.test.ts -test/js/bun/spawn/spawn-streaming-stdout.test.ts -test/js/node/module/sourcemap.test.js -test/js/bun/spawn/spawn-stress.test.ts -test/js/bun/spawn/spawn.ipc.bun-node.test.ts -test/js/bun/spawn/spawn.ipc.node-bun.test.ts -test/js/bun/spawn/spawn.ipc.test.ts -test/js/bun/spawn/spawn_waiter_thread.test.ts -test/js/bun/sqlite/sql-timezone.test.js -test/js/bun/stream/direct-readable-stream.test.tsx -test/js/bun/symbols.test.ts -test/js/bun/test/done-async.test.ts -test/js/bun/test/expect-assertions.test.ts -test/js/bun/test/jest-extended.test.js -test/js/bun/test/mock-fn.test.js -test/js/bun/test/mock/6874/A.test.ts -test/js/bun/test/mock/6874/B.test.ts -test/js/bun/test/mock/6879/6879.test.ts -test/js/bun/test/mock/mock-module.test.ts -test/js/bun/test/snapshot-tests/bun-snapshots.test.ts -test/js/bun/test/snapshot-tests/existing-snapshots.test.ts -test/js/bun/test/snapshot-tests/new-snapshot.test.ts -test/js/bun/test/snapshot-tests/snapshots/more.test.ts -test/js/bun/test/snapshot-tests/snapshots/moremore.test.ts -test/js/bun/test/snapshot-tests/snapshots/snapshot.test.ts -test/js/bun/test/stack.test.ts -test/js/bun/test/test-failing.test.ts -test/js/bun/test/test-only.test.ts -test/js/bun/test/test-test.test.ts -test/js/bun/udp/dgram.test.ts -test/js/bun/udp/udp_socket.test.ts -test/js/bun/util/BunObject.test.ts -test/js/bun/util/arraybuffersink.test.ts -test/js/bun/util/bun-cryptohasher.test.ts -test/js/bun/util/bun-file-exists.test.js -test/js/bun/util/bun-file.test.ts -test/js/bun/util/bun-isMainThread.test.js -test/js/bun/util/concat.test.js -test/js/bun/util/cookie.test.js -test/js/bun/util/error-gc-test.test.js -test/js/bun/util/escapeHTML.test.js -test/js/bun/util/fileUrl.test.js -test/js/bun/util/filesink.test.ts -test/js/bun/util/filesystem_router.test.ts -test/js/bun/util/fuzzy-wuzzy.test.ts -test/js/bun/util/hash.test.js -test/js/bun/util/heap-snapshot.test.ts -test/js/bun/util/index-of-line.test.ts -test/js/bun/util/inspect-error.test.js -test/js/bun/util/inspect.test.js -test/js/bun/util/mmap.test.js -test/js/bun/util/password.test.ts -test/js/bun/util/randomUUIDv5.test.ts -test/js/bun/util/readablestreamtoarraybuffer.test.ts -test/js/bun/util/stringWidth.test.ts -test/js/bun/util/text-loader.test.ts -test/js/bun/util/unsafe.test.js -test/js/bun/util/v8-heap-snapshot.test.ts -test/js/bun/util/which.test.ts -test/js/bun/util/zstd.test.ts -test/js/bun/websocket/websocket-server.test.ts -test/js/deno/abort/abort-controller.test.ts -test/js/deno/crypto/random.test.ts -test/js/deno/crypto/webcrypto.test.ts -test/js/deno/encoding/encoding.test.ts -test/js/deno/event/custom-event.test.ts -test/js/deno/event/event-target.test.ts -test/js/deno/event/event.test.ts -test/js/deno/fetch/blob.test.ts -test/js/deno/fetch/body.test.ts -test/js/deno/fetch/headers.test.ts -test/js/deno/fetch/request.test.ts -test/js/deno/fetch/response.test.ts -test/js/deno/performance/performance.test.ts -test/js/deno/url/url.test.ts -test/js/deno/url/urlsearchparams.test.ts -test/js/deno/v8/error.test.ts -test/js/first_party/undici/undici.test.ts -test/js/junit-reporter/junit.test.js -test/js/node/assert/assert-promise.test.ts -test/js/node/assert/assert.spec.ts -test/js/node/async_hooks/AsyncLocalStorage.test.ts -test/js/node/async_hooks/AsyncLocalStorage-tracking.test.ts -test/js/node/buffer-concat.test.ts -test/js/node/buffer.test.js -test/js/node/child_process/child-process-exec.test.ts -test/js/node/child_process/child-process-stdio.test.js -test/js/node/child_process/child_process-node.test.js -test/js/node/child_process/child_process_ipc.test.js -test/js/node/child_process/child_process_ipc_large_disconnect.test.js -test/js/node/child_process/child_process_send_cb.test.js -test/js/node/cluster.test.ts -test/js/node/cluster/test-docs-http-server.ts -test/js/node/cluster/test-worker-no-exit-http.ts -test/js/node/crypto/crypto-hmac-algorithm.test.ts -test/js/node/crypto/crypto-oneshot.test.ts -test/js/node/crypto/crypto-random.test.ts -test/js/node/crypto/crypto-rsa.test.js -test/js/node/crypto/crypto.hmac.test.ts -test/js/node/crypto/crypto.key-objects.test.ts -test/js/node/crypto/crypto.test.ts -test/js/node/crypto/ecdh.test.ts -test/js/node/crypto/node-crypto.test.js -test/js/node/crypto/pbkdf2.test.ts -test/js/node/diagnostics_channel/diagnostics_channel.test.ts -test/js/node/dns/dns-lookup-keepalive.test.ts -test/js/node/dns/node-dns.test.js -test/js/node/events/event-emitter.test.ts -test/js/node/fs/cp.test.ts -test/js/node/fs/dir.test.ts -test/js/node/fs/fs-leak.test.js -test/js/node/fs/fs-mkdir.test.ts -test/js/node/fs/fs-oom.test.ts -test/js/node/fs/fs-promises-writeFile-async-iterator.test.ts -test/js/node/fs/fs-stats-truncate.test.ts -test/js/node/fs/fs.test.ts -test/js/node/fs/glob.test.ts -test/js/node/fs/promises.test.js -test/js/node/http/client-timeout-error.test.ts -test/js/node/http/node-fetch.test.js -test/js/node/http/node-http-backpressure.test.ts -test/js/node/http/node-http-parser.test.ts -test/js/node/http/node-http-primoridals.test.ts -test/js/node/http/node-http-transfer-encoding.test.ts -test/js/node/http/node-http.test.ts -test/js/node/http/numeric-header.test.ts -test/js/node/module/node-module-module.test.js -test/js/node/module/require-extensions.test.ts -test/js/node/net/double-connect.test.ts -test/js/node/net/node-net-allowHalfOpen.test.js -test/js/node/net/node-net-server.test.ts -test/js/node/net/node-net.test.ts -test/js/node/net/server.spec.ts -test/js/node/no-addons.test.ts -test/js/node/os/os.test.js -test/js/node/path/browserify.test.js -test/js/node/path/matches-glob.test.ts -test/js/node/path/parse-format.test.js -test/js/node/path/to-namespaced-path.test.js -test/js/node/process/call-constructor.test.js -test/js/node/process/process-args.test.js -test/js/node/process/process-nexttick.test.js -test/js/node/process/process-stdin.test.ts -test/js/node/process/process-stdio.test.ts -test/js/node/process/process.test.js -test/js/node/promise/reject-tostring.test.ts -test/js/node/readline/pause_stdin_should_exit.test.ts -test/js/node/readline/readline.node.test.ts -test/js/node/readline/readline_never_unrefs.test.ts -test/js/node/readline/readline_promises.node.test.ts -test/js/node/readline/stdin_fell_asleep.test.ts -test/js/node/stream/node-stream-uint8array.test.ts -test/js/node/stream/node-stream.test.js -test/js/node/string-module.test.js -test/js/node/string_decoder/string-decoder.test.js -test/js/node/stubs.test.js -test/js/node/test_runner/node-test.test.ts -test/js/node/timers.promises/timers.promises.test.ts -test/js/node/timers/node-timers.test.ts -test/js/node/tls/fetch-tls-cert.test.ts -test/js/node/tls/node-tls-cert.test.ts -test/js/node/tls/node-tls-connect.test.ts -test/js/node/tls/node-tls-context.test.ts -test/js/node/tls/node-tls-create-secure-context-args.test.ts -test/js/node/tls/node-tls-no-cipher-match-error.test.ts -test/js/node/tls/node-tls-server.test.ts -test/js/node/tls/node-tls-upgrade.test.ts -test/js/node/tls/renegotiation.test.ts -test/js/node/url/url-parse-format.test.js -test/js/node/url/url-parse-ipv6.test.ts -test/js/node/url/url-relative.test.js -test/js/node/url/url.test.ts -test/js/node/util/bun-inspect.test.ts -test/js/node/util/custom-inspect.test.js -test/js/node/util/mime-api.test.ts -test/js/node/util/node-inspect-tests/parallel/util-inspect.test.js -test/js/node/util/parse_args/default-args.test.mjs -test/js/node/util/util-callbackify.test.js -test/js/node/util/util-promisify.test.js -test/js/node/util/util.test.js -test/js/node/v8/capture-stack-trace.test.js -test/js/node/vm/happy-dom-vm-16277.test.ts -test/js/node/vm/sourcetextmodule-leak.test.ts -test/js/node/vm/vm-sourceUrl.test.ts -test/js/node/vm/vm.test.ts -test/js/node/watch/fs.watchFile.test.ts -test/js/node/worker_threads/15787.test.ts -test/js/node/zlib/zlib.kMaxLength.global.test.js -test/js/node/zlib/zlib.test.js -test/js/sql/local-sql.test.ts -test/js/sql/sql.test.ts -test/js/third_party/@azure/service-bus/azure-service-bus.test.ts -test/js/third_party/@duckdb/node-api/duckdb.test.ts -test/js/third_party/@fastify/websocket/fastity-test-websocket.test.js -test/js/third_party/@napi-rs/canvas/napi-rs-canvas.test.ts -test/js/third_party/body-parser/express-body-parser-test.test.ts -test/js/third_party/body-parser/express-bun-build-compile.test.ts -test/js/third_party/body-parser/express-memory-leak.test.ts -test/js/third_party/comlink/comlink.test.ts -test/js/third_party/duckdb/duckdb-basic-usage.test.ts -test/js/third_party/esbuild/esbuild-child_process.test.ts -test/js/third_party/express/app.router.test.ts -test/cli/test/coverage.test.ts -test/js/third_party/express/express.json.test.ts -test/js/third_party/express/express.test.ts -test/js/third_party/express/express.text.test.ts -test/js/third_party/express/res.json.test.ts -test/js/third_party/express/res.location.test.ts -test/js/third_party/express/res.redirect.test.ts -test/js/third_party/express/res.send.test.ts -test/js/third_party/express/res.sendFile.test.ts -test/js/third_party/grpc-js/test-call-credentials.test.ts -test/js/third_party/grpc-js/test-call-propagation.test.ts -test/js/third_party/grpc-js/test-certificate-provider.test.ts -test/js/third_party/grpc-js/test-channel-credentials.test.ts -test/js/third_party/grpc-js/test-channelz.test.ts -test/js/third_party/grpc-js/test-client.test.ts -test/js/third_party/grpc-js/test-confg-parsing.test.ts -test/js/third_party/grpc-js/test-deadline.test.ts -test/js/third_party/grpc-js/test-duration.test.ts -test/js/third_party/grpc-js/test-end-to-end.test.ts -test/js/third_party/grpc-js/test-global-subchannel-pool.test.ts -test/js/third_party/grpc-js/test-idle-timer.test.ts -test/js/third_party/grpc-js/test-local-subchannel-pool.test.ts -test/js/third_party/grpc-js/test-logging.test.ts -test/js/third_party/grpc-js/test-metadata.test.ts -test/js/third_party/grpc-js/test-outlier-detection.test.ts -test/js/third_party/grpc-js/test-pick-first.test.ts -test/js/third_party/grpc-js/test-prototype-pollution.test.ts -test/js/third_party/grpc-js/test-resolver.test.ts -test/js/third_party/grpc-js/test-retry-config.test.ts -test/js/third_party/grpc-js/test-retry.test.ts -test/js/third_party/grpc-js/test-server-credentials.test.ts -test/js/third_party/grpc-js/test-server-deadlines.test.ts -test/js/third_party/grpc-js/test-server-errors.test.ts -test/js/third_party/grpc-js/test-server-interceptors.test.ts -test/js/third_party/grpc-js/test-server.test.ts -test/js/third_party/grpc-js/test-status-builder.test.ts -test/js/third_party/grpc-js/test-uri-parser.test.ts -test/js/third_party/grpc-js/test-tonic.test.ts -test/js/third_party/http2-wrapper/http2-wrapper.test.ts -test/js/third_party/jsonwebtoken/async_sign.test.js -test/js/third_party/jsonwebtoken/buffer.test.js -test/js/third_party/jsonwebtoken/claim-aud.test.js -test/js/third_party/jsonwebtoken/claim-exp.test.js -test/js/third_party/jsonwebtoken/claim-iat.test.js -test/js/third_party/jsonwebtoken/claim-iss.test.js -test/js/third_party/jsonwebtoken/claim-jti.test.js -test/js/third_party/jsonwebtoken/claim-nbf.test.js -test/js/third_party/jsonwebtoken/claim-private.test.js -test/js/third_party/jsonwebtoken/claim-sub.test.js -test/js/third_party/jsonwebtoken/decoding.test.js -test/js/third_party/jsonwebtoken/encoding.test.js -test/js/third_party/jsonwebtoken/expires_format.test.js -test/js/third_party/jsonwebtoken/header-kid.test.js -test/js/third_party/jsonwebtoken/invalid_exp.test.js -test/js/third_party/jsonwebtoken/issue_147.test.js -test/js/third_party/jsonwebtoken/issue_304.test.js -test/js/third_party/jsonwebtoken/issue_70.test.js -test/js/third_party/jsonwebtoken/jwt.asymmetric_signing.test.js -test/js/third_party/jsonwebtoken/jwt.hs.test.js -test/js/third_party/jsonwebtoken/jwt.malicious.test.js -test/js/third_party/jsonwebtoken/noTimestamp.test.js -test/js/third_party/jsonwebtoken/non_object_values.test.js -test/js/third_party/jsonwebtoken/option-complete.test.js -test/js/third_party/jsonwebtoken/option-maxAge.test.js -test/js/third_party/jsonwebtoken/option-nonce.test.js -test/js/third_party/jsonwebtoken/rsa-public-key.test.js -test/js/third_party/jsonwebtoken/schema.test.js -test/js/third_party/jsonwebtoken/set_headers.test.js -test/js/third_party/jsonwebtoken/undefined_secretOrPublickey.test.js -test/js/third_party/jsonwebtoken/validateAsymmetricKey.test.js -test/js/third_party/jsonwebtoken/verify.test.js -test/js/third_party/jsonwebtoken/wrong_alg.test.js -test/js/third_party/mongodb/mongodb.test.ts -test/js/third_party/msw/msw.test.ts -test/js/third_party/nodemailer/nodemailer.test.ts -test/js/third_party/pg-gateway/pglite.test.ts -test/js/third_party/pg/pg.test.ts -test/js/third_party/pino/pino.test.js -test/js/third_party/postgres/postgres.test.ts -test/js/third_party/prisma/prisma.test.ts -test/js/third_party/prompts/prompts.test.ts -test/js/third_party/remix/remix.test.ts -test/js/third_party/resvg/bbox.test.js -test/js/third_party/rollup-v4/rollup-v4.test.ts -test/js/third_party/socket.io/socket.io-close.test.ts -test/js/third_party/socket.io/socket.io-connection-state-recovery.test.ts -test/js/third_party/socket.io/socket.io-handshake.test.ts -test/js/third_party/socket.io/socket.io-messaging-many.test.ts -test/js/third_party/socket.io/socket.io-middleware.test.ts -test/js/third_party/socket.io/socket.io-namespaces.test.ts -test/js/third_party/socket.io/socket.io-server-attachment.test.ts -test/js/third_party/socket.io/socket.io-socket-middleware.test.ts -test/js/third_party/socket.io/socket.io-socket-timeout.test.ts -test/js/third_party/socket.io/socket.io-utility-methods.test.ts -test/js/third_party/socket.io/socket.io.test.ts -test/js/third_party/solc/solc.test.ts -test/js/third_party/st/st.test.ts -test/js/third_party/stripe/stripe.test.ts -test/js/third_party/svelte/svelte.test.ts -test/js/web/abort/abort.test.ts -test/js/web/broadcastchannel/broadcast-channel.test.ts -test/js/web/console/console-timeLog.test.ts -test/js/web/crypto/web-crypto.test.ts -test/js/web/encoding/encode-bad-chunks.test.ts -test/js/web/encoding/text-decoder-stream.test.ts -test/js/web/encoding/text-decoder.test.js -test/js/web/encoding/text-encoder-stream.test.ts -test/js/web/encoding/text-encoder.test.js -test/js/web/fetch/abort-signal-leak.test.ts -test/js/web/fetch/blob-oom.test.ts -test/js/web/fetch/blob.test.ts -test/js/web/fetch/body-clone.test.ts -test/js/web/fetch/body-stream-excess.test.ts -test/js/web/fetch/body-stream.test.ts -test/js/web/fetch/body.test.ts -test/js/web/fetch/chunked-trailing.test.js -test/js/web/fetch/client-fetch.test.ts -test/js/web/fetch/content-length.test.js -test/js/web/fetch/cookies.test.ts -test/js/web/fetch/fetch-args.test.ts -test/js/web/fetch/fetch-connection-header.test.ts -test/js/web/fetch/fetch-gzip.test.ts -test/js/web/fetch/fetch-preconnect.test.ts -test/js/web/fetch/fetch-redirect.test.ts -test/js/web/fetch/fetch-tcp-stress.test.ts -test/js/web/fetch/fetch-url-after-redirect.test.ts -test/js/web/fetch/fetch.brotli.test.ts -test/js/web/fetch/fetch.stream.test.ts -test/js/web/fetch/fetch.test.ts -test/js/web/fetch/fetch.tls.test.ts -test/js/web/fetch/fetch.unix.test.ts -test/js/web/fetch/fetch_headers.test.js -test/js/web/fetch/headers.test.ts -test/js/web/fetch/headers.undici.test.ts -test/js/web/fetch/stream-fast-path.test.ts -test/js/web/fetch/utf8-bom.test.ts -test/regression/issue/test-21049.test.ts -test/js/web/html/FormData.test.ts -test/js/web/request/request-clone-leak.test.ts -test/js/web/request/request-subclass.test.ts -test/js/web/request/request.test.ts -test/js/web/streams/streams.test.js -test/js/web/timers/microtask.test.js -test/js/web/timers/setInterval.test.js -test/js/web/timers/setTimeout.test.js -test/js/web/websocket/websocket-client-short-read.test.ts -test/js/web/websocket/websocket-client.test.ts -test/js/web/websocket/websocket-permessage-deflate-edge-cases.test.ts -test/js/web/websocket/websocket-permessage-deflate-simple.test.ts -test/js/web/websocket/websocket-permessage-deflate.test.ts -test/js/web/websocket/websocket.test.js -test/js/web/workers/message-channel.test.ts -test/js/web/workers/message-event.test.ts -test/js/web/workers/structured-clone.test.ts -test/js/web/workers/worker.test.ts -test/js/web/workers/worker_blob.test.ts -test/js/workerd/html-rewriter.test.js -test/napi/node-napi.test.ts -test/napi/uv.test.ts -test/napi/uv_stub.test.ts -test/regression/issue/012040.test.ts -test/regression/issue/014187.test.ts -test/regression/issue/01466.test.ts -test/regression/issue/014865.test.ts -test/regression/issue/02368.test.ts -test/regression/issue/02499/02499.test.ts -test/regression/issue/04298/04298.test.ts -test/regression/issue/04947.test.js -test/regression/issue/06946/06946.test.ts -test/regression/issue/07001.test.ts -test/regression/issue/07261.test.ts -test/regression/issue/07827.test.ts -test/regression/issue/07917/7917.test.ts -test/regression/issue/08093.test.ts -test/regression/issue/08794.test.ts -test/regression/issue/09041.test.ts -test/regression/issue/09340.test.ts -test/regression/issue/09469.test.ts -test/regression/issue/09555.test.ts -test/regression/issue/09559.test.ts -test/regression/issue/09778.test.ts -test/regression/issue/10132.test.ts -test/regression/issue/10139.test.ts -test/regression/issue/10170.test.ts -test/regression/issue/11297/11297.test.ts -test/regression/issue/11664.test.ts -test/regression/issue/12910/12910.test.ts -test/regression/issue/14477/14477.test.ts -test/regression/issue/14515.test.tsx -test/regression/issue/14976/14976.test.ts -test/regression/issue/14982/14982.test.ts -test/regression/issue/16312.test.ts -test/regression/issue/16474.test.ts -test/regression/issue/17605.test.ts -test/regression/issue/17766.test.ts -test/regression/issue/18159/18159.test.ts -test/regression/issue/18239/18239.test.ts -test/regression/issue/18547.test.ts -test/regression/issue/18595.test.ts -test/regression/issue/19661.test.ts -test/regression/issue/20144/20144.test.ts -test/regression/issue/crypto-names.test.ts -test/v8/v8.test.ts vendor/elysia/test/a.test.ts vendor/elysia/test/adapter/web-standard/cookie-to-header.test.ts vendor/elysia/test/adapter/web-standard/map-compact-response.test.ts @@ -701,8 +98,8 @@ vendor/elysia/test/ws/message.test.ts # List of tests that potentially throw inside of reifyStaticProperties -test/js/node/test/parallel/test-stream-iterator-helpers-test262-tests.mjs test/js/node/test/parallel/test-stream-some-find-every.mjs +test/js/node/test/parallel/test-stream-iterator-helpers-test262-tests.mjs test/js/node/test/parallel/test-fs-stat-date.mjs test/js/node/test/parallel/test-fs-readSync-position-validation.mjs test/js/node/test/parallel/test-fs-read-promises-position-validation.mjs @@ -723,29 +120,83 @@ test/js/node/test/parallel/test-require-dot.js test/js/node/test/parallel/test-util-promisify-custom-names.mjs test/js/node/test/parallel/test-whatwg-readablestream.mjs test/js/node/test/parallel/test-worker.mjs +test/js/node/events/event-emitter.test.ts +test/js/node/module/node-module-module.test.js +test/js/node/process/call-constructor.test.js +test/js/node/stubs.test.js +test/js/node/timers/node-timers.test.ts +test/bake/dev/vfile.test.ts +test/cli/run/run-eval.test.ts +test/cli/run/self-reference.test.ts +test/js/bun/resolve/import-meta-resolve.test.mjs +test/js/bun/resolve/import-meta.test.js +test/js/bun/util/BunObject.test.ts +test/js/bun/util/fuzzy-wuzzy.test.ts +test/js/third_party/pg-gateway/pglite.test.ts +test/js/web/websocket/websocket.test.js test/js/node/test/parallel/test-vm-module-referrer-realm.mjs - -# uses node:test -test/js/node/test/parallel/test-fs-write-stream-flush.js -test/js/node/test/parallel/test-fs-write-file-flush.js -test/js/node/test/parallel/test-fs-operations-with-surrogate-pairs.js -test/js/node/test/parallel/test-fs-append-file-flush.js -test/js/node/test/parallel/test-file-write-stream5.js -test/js/node/test/parallel/test-assert-checktag.js -test/js/node/test/parallel/test-assert-deep-with-error.js -test/js/node/test/parallel/test-assert-if-error.js -test/js/node/test/parallel/test-assert.js +test/js/bun/resolve/resolve.test.ts # trips asan on my macos test machine test/js/node/test/parallel/test-fs-watch.js test/js/node/test/parallel/test-fs-watch-recursive-watch-file.js +# hit a debug assert +test/bundler/bundler_compile.test.ts # needs https://github.com/oven-sh/WebKit/pull/94 # missing RELEASE_AND_RETURN test/js/node/test/parallel/test-cluster-disconnect-idle-worker.js test/js/node/test/parallel/test-cluster-disconnect-leak.js test/js/node/test/parallel/test-os.js +test/js/node/os/os.test.js +test/js/node/util/util-callbackify.test.js +test/js/node/vm/happy-dom-vm-16277.test.ts +test/bundler/bundler_cjs2esm.test.ts +test/bundler/bundler_html.test.ts +test/bundler/bundler_naming.test.ts +test/bundler/esbuild/css.test.ts +test/bundler/esbuild/dce.test.ts +test/bundler/esbuild/importstar.test.ts +test/bundler/esbuild/loader.test.ts +test/bundler/esbuild/ts.test.ts +test/cli/install/bun-install-registry.test.ts +test/cli/install/bun-workspaces.test.ts +test/cli/install/bunx.test.ts +test/integration/jsdom/jsdom.test.ts +test/integration/svelte/client-side.test.ts +test/js/bun/http/serve-listen.test.ts +test/js/bun/util/filesystem_router.test.ts +test/js/deno/abort/abort-controller.test.ts +test/js/deno/crypto/random.test.ts +test/js/deno/crypto/webcrypto.test.ts +test/js/deno/encoding/encoding.test.ts +test/js/deno/event/custom-event.test.ts +test/js/deno/event/event-target.test.ts +test/js/deno/event/event.test.ts +test/js/deno/fetch/blob.test.ts +test/js/deno/fetch/body.test.ts +test/js/deno/fetch/headers.test.ts +test/js/deno/fetch/request.test.ts +test/js/deno/fetch/response.test.ts +test/js/deno/performance/performance.test.ts +test/js/deno/url/url.test.ts +test/js/deno/url/urlsearchparams.test.ts +test/js/deno/v8/error.test.ts +test/js/third_party/@fastify/websocket/fastity-test-websocket.test.js +test/js/third_party/grpc-js/test-resolver.test.ts +test/js/third_party/grpc-js/test-retry-config.test.ts +test/js/third_party/grpc-js/test-retry.test.ts +test/js/third_party/mongodb/mongodb.test.ts +test/js/third_party/pino/pino.test.js test/js/node/test/parallel/test-util-callbackify.js +test/js/bun/http/serve.test.ts +test/cli/install/catalogs.test.ts +test/cli/install/npmrc.test.ts +test/cli/install/bun-lockb.test.ts +test/cli/install/isolated-install.test.ts +test/cli/install/bun-publish.test.ts +test/cli/install/bun-lock.test.ts +test/cli/install/bun-install-lifecycle-scripts.test.ts # ProgramExecutable::initializeGlobalProperties # missing RELEASE_AND_RETURN test/js/node/test/parallel/test-repl-syntax-error-handling.js @@ -755,19 +206,58 @@ test/js/node/test/parallel/test-vm-module-errors.js # JSModuleNamespaceObject::overrideExportValue # missing RETURN_IF_EXCEPTION test/js/node/test/parallel/test-vm-module-synthetic.js +test/js/bun/test/mock/6874/A.test.ts +test/js/bun/test/mock/6874/B.test.ts +test/js/bun/test/mock/6879/6879.test.ts +test/js/bun/test/mock/mock-module.test.ts +test/regression/issue/11664.test.ts +# ErrorInstance::put +# missing RETURN_IF_EXCEPTION +test/js/node/util/node-inspect-tests/parallel/util-inspect.test.js +test/js/node/vm/vm.test.ts +test/js/third_party/grpc-js/test-call-propagation.test.ts +test/js/third_party/grpc-js/test-channelz.test.ts +test/js/third_party/grpc-js/test-client.test.ts +test/js/third_party/grpc-js/test-deadline.test.ts +test/js/third_party/grpc-js/test-outlier-detection.test.ts +test/js/third_party/grpc-js/test-server-deadlines.test.ts +test/js/third_party/grpc-js/test-server-errors.test.ts +test/js/third_party/grpc-js/test-server-interceptors.test.ts +test/js/third_party/grpc-js/test-server.test.ts +test/js/node/test/parallel/test-assert-if-error.js +# ErrorInstance::defineOwnProperty +# missing RETURN_IF_EXCEPTION +test/js/bun/util/inspect-error.test.js +# moduleLoaderParseModule +# missing RETURN_IF_EXCEPTION +test/bundler/transpiler/bun-pragma.test.ts # llhttp test/js/node/test/parallel/test-http-parser-bad-ref.js test/js/node/test/parallel/test-http-parser.js +test/js/node/http/node-http-parser.test.ts # try again later -test/js/node/test/parallel/test-promises-warning-on-unhandled-rejection.js test/js/node/test/parallel/test-worker-nested-uncaught.js +# 3rd party napi +test/integration/sharp/sharp.test.ts +test/js/third_party/@duckdb/node-api/duckdb.test.ts +test/js/third_party/@napi-rs/canvas/napi-rs-canvas.test.ts +test/js/third_party/duckdb/duckdb-basic-usage.test.ts +test/js/third_party/prisma/prisma.test.ts +test/js/third_party/remix/remix.test.ts +test/js/third_party/resvg/bbox.test.js +test/js/third_party/rollup-v4/rollup-v4.test.ts +test/napi/node-napi.test.ts +test/napi/uv.test.ts +test/napi/uv_stub.test.ts + # normalizeCryptoAlgorithmParameters test/js/node/test/parallel/test-webcrypto-derivekey.js test/js/node/test/parallel/test-webcrypto-digest.js test/js/node/test/parallel/test-webcrypto-encrypt-decrypt-aes.js +test/js/bun/crypto/wpt-webcrypto.generateKey.test.ts test/js/node/test/parallel/test-webcrypto-encrypt-decrypt.js test/js/node/test/parallel/test-webcrypto-sign-verify.js test/js/node/test/parallel/test-webcrypto-cryptokey-workers.js @@ -776,3 +266,7 @@ test/js/node/test/parallel/test-crypto-psychic-signatures.js test/js/node/test/parallel/test-crypto-subtle-zero-length.js test/js/node/test/parallel/test-crypto-worker-thread.js test/js/node/test/parallel/test-crypto-webcrypto-aes-decrypt-tag-too-small.js +test/js/web/crypto/web-crypto.test.ts +test/js/node/crypto/node-crypto.test.js +test/js/third_party/pg/pg.test.ts +test/regression/issue/01466.test.ts