diff --git a/scripts/runner.node.mjs b/scripts/runner.node.mjs index 8a320d5612..d4c5545115 100755 --- a/scripts/runner.node.mjs +++ b/scripts/runner.node.mjs @@ -236,26 +236,24 @@ function getTestExpectations() { return expectations; } +const skipArray = (() => { + const path = join(cwd, "test/no-validate-exceptions.txt"); + if (!existsSync(path)) { + return []; + } + return readFileSync(path, "utf-8") + .split("\n") + .filter(line => !line.startsWith("#") && line.length > 0); +})(); + /** * Returns whether we should validate exception checks running the given test * @param {string} test * @returns {boolean} */ -const shouldValidateExceptions = (() => { - let skipArray; - return test => { - if (!skipArray) { - const path = join(cwd, "test/no-validate-exceptions.txt"); - if (!existsSync(path)) { - skipArray = []; - } - skipArray = readFileSync(path, "utf-8") - .split("\n") - .filter(line => !line.startsWith("#") && line.length > 0); - } - return !(skipArray.includes(test) || skipArray.includes("test/" + test)); - }; -})(); +const shouldValidateExceptions = test => { + return !(skipArray.includes(test) || skipArray.includes("test/" + test)); +}; /** * @param {string} testPath @@ -448,7 +446,7 @@ async function runTests() { NO_COLOR: "1", BUN_DEBUG_QUIET_LOGS: "1", }; - if (basename(execPath).includes("asan") && shouldValidateExceptions(testPath)) { + if ((basename(execPath).includes("asan") || !isCI) && shouldValidateExceptions(testPath)) { env.BUN_JSC_validateExceptionChecks = "1"; } await runTest(title, async () => { diff --git a/src/bake/DevServer.zig b/src/bake/DevServer.zig index 71acfebac7..48e5038f12 100644 --- a/src/bake/DevServer.zig +++ b/src/bake/DevServer.zig @@ -1600,7 +1600,7 @@ fn onFrameworkRequestWithBundle( // routerTypeMain router_type.server_file_string.get() orelse str: { const name = dev.server_graph.bundled_files.keys()[fromOpaqueFileId(.server, router_type.server_file).get()]; - const str = bun.String.createUTF8ForJS(dev.vm.global, dev.relativePath(name)); + const str = try bun.String.createUTF8ForJS(dev.vm.global, dev.relativePath(name)); dev.releaseRelativePathBuf(); router_type.server_file_string = .create(str, dev.vm.global); break :str str; diff --git a/src/bake/production.zig b/src/bake/production.zig index a0eaa75494..37dbb5ef1b 100644 --- a/src/bake/production.zig +++ b/src/bake/production.zig @@ -525,7 +525,7 @@ pub fn buildWithVm(ctx: bun.CLI.Command.Context, cwd: []const u8, vm: *VirtualMa if (params_buf.items.len > 0) { const param_info_array = try JSValue.createEmptyArray(global, params_buf.items.len); for (params_buf.items, 0..) |param, i| { - try param_info_array.putIndex(global, @intCast(params_buf.items.len - i - 1), bun.String.createUTF8ForJS(global, param)); + try param_info_array.putIndex(global, @intCast(params_buf.items.len - i - 1), try bun.String.createUTF8ForJS(global, param)); } try route_param_info.putIndex(global, @intCast(nav_index), param_info_array); } else { diff --git a/src/bun.js/ModuleLoader.zig b/src/bun.js/ModuleLoader.zig index 40e3783866..77fc7d328f 100644 --- a/src/bun.js/ModuleLoader.zig +++ b/src/bun.js/ModuleLoader.zig @@ -1522,10 +1522,10 @@ pub fn transpileSourceCode( defer buf.deinit(); var writer = buf.writer(); JSC.API.Bun.getPublicPath(specifier, jsc_vm.origin, @TypeOf(&writer), &writer); - break :brk bun.String.createUTF8ForJS(globalObject.?, buf.slice()); + break :brk try bun.String.createUTF8ForJS(globalObject.?, buf.slice()); } - break :brk bun.String.createUTF8ForJS(globalObject.?, path.text); + break :brk try bun.String.createUTF8ForJS(globalObject.?, path.text); }; return ResolvedSource{ diff --git a/src/bun.js/VirtualMachine.zig b/src/bun.js/VirtualMachine.zig index adad143990..b2dc00d0d2 100644 --- a/src/bun.js/VirtualMachine.zig +++ b/src/bun.js/VirtualMachine.zig @@ -513,18 +513,21 @@ extern fn Bun__promises__emitUnhandledRejectionWarning(*JSGlobalObject, reason: extern fn Bun__noSideEffectsToString(vm: *JSC.VM, globalObject: *JSGlobalObject, reason: JSValue) JSValue; fn isErrorLike(globalObject: *JSGlobalObject, reason: JSValue) bun.JSError!bool { - const result = Bun__promises__isErrorLike(globalObject, reason); - if (globalObject.hasException()) return error.JSError; - return result; + return bun.jsc.fromJSHostCallGeneric(globalObject, @src(), Bun__promises__isErrorLike, .{ globalObject, reason }); } fn wrapUnhandledRejectionErrorForUncaughtException(globalObject: *JSGlobalObject, reason: JSValue) JSValue { if (isErrorLike(globalObject, reason) catch blk: { - if (globalObject.hasException()) globalObject.clearException(); + globalObject.clearException(); break :blk false; }) return reason; - const reasonStr = Bun__noSideEffectsToString(globalObject.vm(), globalObject, reason); - if (globalObject.hasException()) globalObject.clearException(); + const reasonStr = blk: { + var scope: bun.jsc.CatchScope = undefined; + scope.init(globalObject, @src()); + defer scope.deinit(); + defer if (scope.exception()) |_| scope.clearException(); + break :blk Bun__noSideEffectsToString(globalObject.vm(), globalObject, reason); + }; const msg = "This error originated either by throwing inside of an async function without a catch block, " ++ "or by rejecting a promise which was not handled with .catch(). The promise rejected with the reason \"" ++ "{s}" ++ @@ -621,7 +624,6 @@ pub fn handledPromise(this: *JSC.VirtualMachine, globalObject: *JSGlobalObject, pub fn uncaughtException(this: *JSC.VirtualMachine, globalObject: *JSGlobalObject, err: JSValue, is_rejection: bool) bool { if (this.isShuttingDown()) { - Output.debugWarn("uncaughtException during shutdown.", .{}); return true; } @@ -2093,7 +2095,7 @@ pub fn reloadEntryPoint(this: *VirtualMachine, entry_path: []const u8) !*JSInter if (this.has_patched_run_main) { @branchHint(.cold); this.pending_internal_promise = null; - const ret = NodeModuleModule__callOverriddenRunMain(this.global, bun.String.createUTF8ForJS(this.global, main_file_name)); + const ret = try bun.jsc.fromJSHostCall(this.global, @src(), NodeModuleModule__callOverriddenRunMain, .{ this.global, try bun.String.createUTF8ForJS(this.global, main_file_name) }); if (this.pending_internal_promise == prev or this.pending_internal_promise == null) { this.pending_internal_promise = JSInternalPromise.resolvedPromise(this.global, ret); return this.pending_internal_promise.?; diff --git a/src/bun.js/api/BunObject.zig b/src/bun.js/api/BunObject.zig index 6f1d6e5897..2f37b996a8 100644 --- a/src/bun.js/api/BunObject.zig +++ b/src/bun.js/api/BunObject.zig @@ -1252,11 +1252,12 @@ pub fn mmapFile(globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) bun. }, }; - return JSC.C.JSObjectMakeTypedArrayWithBytesNoCopy(globalThis, JSC.C.JSTypedArrayType.kJSTypedArrayTypeUint8Array, @as(?*anyopaque, @ptrCast(map.ptr)), map.len, struct { + const S = struct { pub fn x(ptr: ?*anyopaque, size: ?*anyopaque) callconv(.C) void { - _ = bun.sys.munmap(@as([*]align(std.heap.page_size_min) u8, @ptrCast(@alignCast(ptr)))[0..@intFromPtr(size)]); + _ = bun.sys.munmap(@as([*]align(std.heap.page_size_min) const u8, @ptrCast(@alignCast(ptr)))[0..@intFromPtr(size)]); } - }.x, @as(?*anyopaque, @ptrFromInt(map.len)), null).?.value(); + }; + return bun.jsc.array_buffer.makeTypedArrayWithBytesNoCopy(globalThis, .TypeUint8, map.ptr, map.len, S.x, @ptrFromInt(map.len)); } pub fn getTranspilerConstructor(globalThis: *JSC.JSGlobalObject, _: *JSC.JSObject) JSC.JSValue { @@ -1579,7 +1580,7 @@ pub const JSZlib = struct { reader.list_ptr = &reader.list; var array_buffer = JSC.ArrayBuffer.fromBytes(reader.list.items, .Uint8Array); - return array_buffer.toJSWithContext(globalThis, reader, reader_deallocator, null); + return array_buffer.toJSWithContext(globalThis, reader, reader_deallocator); }, .libdeflate => { var decompressor: *bun.libdeflate.Decompressor = bun.libdeflate.Decompressor.alloc() orelse { @@ -1615,7 +1616,7 @@ pub const JSZlib = struct { } var array_buffer = JSC.ArrayBuffer.fromBytes(list.items, .Uint8Array); - return array_buffer.toJSWithContext(globalThis, list.items.ptr, global_deallocator, null); + return array_buffer.toJSWithContext(globalThis, list.items.ptr, global_deallocator); }, } } @@ -1686,7 +1687,7 @@ pub const JSZlib = struct { reader.list_ptr = &reader.list; var array_buffer = JSC.ArrayBuffer.fromBytes(reader.list.items, .Uint8Array); - return array_buffer.toJSWithContext(globalThis, reader, reader_deallocator, null); + return array_buffer.toJSWithContext(globalThis, reader, reader_deallocator); }, .libdeflate => { var compressor: *bun.libdeflate.Compressor = bun.libdeflate.Compressor.alloc(level orelse 6) orelse { @@ -1716,7 +1717,7 @@ pub const JSZlib = struct { } var array_buffer = JSC.ArrayBuffer.fromBytes(list.items, .Uint8Array); - return array_buffer.toJSWithContext(globalThis, list.items.ptr, global_deallocator, null); + return array_buffer.toJSWithContext(globalThis, list.items.ptr, global_deallocator); }, } } diff --git a/src/bun.js/api/FFIObject.zig b/src/bun.js/api/FFIObject.zig index 0f32dab42b..d77c8d2cbb 100644 --- a/src/bun.js/api/FFIObject.zig +++ b/src/bun.js/api/FFIObject.zig @@ -1,4 +1,4 @@ -pub fn newCString(globalThis: *JSGlobalObject, value: JSValue, byteOffset: ?JSValue, lengthValue: ?JSValue) JSC.JSValue { +pub fn newCString(globalThis: *JSGlobalObject, value: JSValue, byteOffset: ?JSValue, lengthValue: ?JSValue) bun.JSError!JSC.JSValue { switch (FFIObject.getPtrSlice(globalThis, value, byteOffset, lengthValue)) { .err => |err| { return err; @@ -504,7 +504,7 @@ pub fn toArrayBuffer( valueLength: ?JSValue, finalizationCtxOrPtr: ?JSValue, finalizationCallback: ?JSValue, -) JSC.JSValue { +) bun.JSError!JSC.JSValue { switch (getPtrSlice(globalThis, value, byteOffset, valueLength)) { .err => |erro| { return erro; @@ -534,7 +534,7 @@ pub fn toArrayBuffer( } } - return JSC.ArrayBuffer.fromBytes(slice, JSC.JSValue.JSType.ArrayBuffer).toJSWithContext(globalThis, ctx, callback, null); + return JSC.ArrayBuffer.fromBytes(slice, JSC.JSValue.JSType.ArrayBuffer).toJSWithContext(globalThis, ctx, callback); }, } } diff --git a/src/bun.js/api/bun/h2_frame_parser.zig b/src/bun.js/api/bun/h2_frame_parser.zig index d022fff6f7..7270371f5f 100644 --- a/src/bun.js/api/bun/h2_frame_parser.zig +++ b/src/bun.js/api/bun/h2_frame_parser.zig @@ -1920,7 +1920,7 @@ pub const H2FrameParser = struct { if (getHTTP2CommonString(globalObject, header.well_know)) |js_header_name| { try headers.push(globalObject, js_header_name); - try headers.push(globalObject, bun.String.createUTF8ForJS(globalObject, header.value)); + try headers.push(globalObject, try bun.String.createUTF8ForJS(globalObject, header.value)); if (header.never_index) { if (sensitiveHeaders.isUndefined()) { sensitiveHeaders = try JSC.JSValue.createEmptyArray(globalObject, 0); @@ -1929,8 +1929,8 @@ pub const H2FrameParser = struct { try sensitiveHeaders.push(globalObject, js_header_name); } } else { - const js_header_name = bun.String.createUTF8ForJS(globalObject, header.name); - const js_header_value = bun.String.createUTF8ForJS(globalObject, header.value); + const js_header_name = try bun.String.createUTF8ForJS(globalObject, header.name); + const js_header_value = try bun.String.createUTF8ForJS(globalObject, header.value); if (header.never_index) { if (sensitiveHeaders.isUndefined()) { @@ -2061,7 +2061,7 @@ pub const H2FrameParser = struct { return data.len; } - fn stringOrEmptyToJS(this: *H2FrameParser, payload: []const u8) JSC.JSValue { + fn stringOrEmptyToJS(this: *H2FrameParser, payload: []const u8) bun.JSError!JSC.JSValue { if (payload.len == 0) { return bun.String.empty.toJS(this.handlers.globalObject); } @@ -2099,18 +2099,18 @@ pub const H2FrameParser = struct { } origin_str = origin_str[0..origin_length]; if (count == 0) { - originValue = this.stringOrEmptyToJS(origin_str); + originValue = try this.stringOrEmptyToJS(origin_str); originValue.ensureStillAlive(); } else if (count == 1) { // need to create an array const array = try JSC.JSValue.createEmptyArray(this.handlers.globalObject, 0); array.ensureStillAlive(); try array.push(this.handlers.globalObject, originValue); - try array.push(this.handlers.globalObject, this.stringOrEmptyToJS(origin_str)); + try array.push(this.handlers.globalObject, try this.stringOrEmptyToJS(origin_str)); originValue = array; } else { // we already have an array, just add the origin to it - try originValue.push(this.handlers.globalObject, this.stringOrEmptyToJS(origin_str)); + try originValue.push(this.handlers.globalObject, try this.stringOrEmptyToJS(origin_str)); } count += 1; payload = payload[origin_length + 2 ..]; @@ -2121,7 +2121,7 @@ pub const H2FrameParser = struct { } return data.len; } - pub fn handleAltsvcFrame(this: *H2FrameParser, frame: FrameHeader, data: []const u8, stream_: ?*Stream) usize { + pub fn handleAltsvcFrame(this: *H2FrameParser, frame: FrameHeader, data: []const u8, stream_: ?*Stream) bun.JSError!usize { log("handleAltsvcFrame {s}", .{data}); if (this.isServer) { // client should not send ALTSVC frame @@ -2150,7 +2150,7 @@ pub const H2FrameParser = struct { return content.end; } - this.dispatchWith2Extra(.onAltSvc, this.stringOrEmptyToJS(origin_and_value[0..origin_length]), this.stringOrEmptyToJS(origin_and_value[origin_length..]), JSC.JSValue.jsNumber(frame.streamIdentifier)); + this.dispatchWith2Extra(.onAltSvc, try this.stringOrEmptyToJS(origin_and_value[0..origin_length]), try this.stringOrEmptyToJS(origin_and_value[origin_length..]), JSC.JSValue.jsNumber(frame.streamIdentifier)); return content.end; } return data.len; @@ -2549,7 +2549,7 @@ pub const H2FrameParser = struct { @intFromEnum(FrameType.HTTP_FRAME_PING) => this.handlePingFrame(header, bytes[needed..], stream) + needed, @intFromEnum(FrameType.HTTP_FRAME_GOAWAY) => this.handleGoAwayFrame(header, bytes[needed..], stream) + needed, @intFromEnum(FrameType.HTTP_FRAME_RST_STREAM) => this.handleRSTStreamFrame(header, bytes[needed..], stream) + needed, - @intFromEnum(FrameType.HTTP_FRAME_ALTSVC) => this.handleAltsvcFrame(header, bytes[needed..], stream) + needed, + @intFromEnum(FrameType.HTTP_FRAME_ALTSVC) => (try this.handleAltsvcFrame(header, bytes[needed..], stream)) + needed, @intFromEnum(FrameType.HTTP_FRAME_ORIGIN) => (try this.handleOriginFrame(header, bytes[needed..], stream)) + needed, else => { this.sendGoAway(header.streamIdentifier, ErrorCode.PROTOCOL_ERROR, "Unknown frame type", this.lastStreamID, true); @@ -2582,7 +2582,7 @@ pub const H2FrameParser = struct { @intFromEnum(FrameType.HTTP_FRAME_PING) => this.handlePingFrame(header, bytes[FrameHeader.byteSize..], stream) + FrameHeader.byteSize, @intFromEnum(FrameType.HTTP_FRAME_GOAWAY) => this.handleGoAwayFrame(header, bytes[FrameHeader.byteSize..], stream) + FrameHeader.byteSize, @intFromEnum(FrameType.HTTP_FRAME_RST_STREAM) => this.handleRSTStreamFrame(header, bytes[FrameHeader.byteSize..], stream) + FrameHeader.byteSize, - @intFromEnum(FrameType.HTTP_FRAME_ALTSVC) => this.handleAltsvcFrame(header, bytes[FrameHeader.byteSize..], stream) + FrameHeader.byteSize, + @intFromEnum(FrameType.HTTP_FRAME_ALTSVC) => (try this.handleAltsvcFrame(header, bytes[FrameHeader.byteSize..], stream)) + FrameHeader.byteSize, @intFromEnum(FrameType.HTTP_FRAME_ORIGIN) => (try this.handleOriginFrame(header, bytes[FrameHeader.byteSize..], stream)) + FrameHeader.byteSize, else => { this.sendGoAway(header.streamIdentifier, ErrorCode.PROTOCOL_ERROR, "Unknown frame type", this.lastStreamID, true); diff --git a/src/bun.js/api/bun/socket/Listener.zig b/src/bun.js/api/bun/socket/Listener.zig index 2be8e5791d..8597375dd1 100644 --- a/src/bun.js/api/bun/socket/Listener.zig +++ b/src/bun.js/api/bun/socket/Listener.zig @@ -284,7 +284,7 @@ pub fn listen(globalObject: *JSC.JSGlobalObject, opts: JSValue) bun.JSError!JSVa const err = globalObject.createErrorInstance("Failed to listen at {s}", .{bun.span(hostname_or_unix.slice())}); log("Failed to listen {d}", .{errno}); if (errno != 0) { - err.put(globalObject, ZigString.static("syscall"), bun.String.createUTF8ForJS(globalObject, "listen")); + err.put(globalObject, ZigString.static("syscall"), try bun.String.createUTF8ForJS(globalObject, "listen")); err.put(globalObject, ZigString.static("errno"), JSValue.jsNumber(errno)); err.put(globalObject, ZigString.static("address"), hostname_or_unix.toZigString().toJS(globalObject)); if (port) |p| err.put(globalObject, ZigString.static("port"), .jsNumber(p)); diff --git a/src/bun.js/api/bun/socket/SocketAddress.zig b/src/bun.js/api/bun/socket/SocketAddress.zig index 71cd9a4fe4..68505f5995 100644 --- a/src/bun.js/api/bun/socket/SocketAddress.zig +++ b/src/bun.js/api/bun/socket/SocketAddress.zig @@ -336,12 +336,12 @@ pub fn intoDTO(this: *SocketAddress, global: *JSC.JSGlobalObject) JSC.JSValue { /// /// - The address string is assumed to be ASCII and a valid IP address (either v4 or v6). /// - Port is a valid `in_port_t` (between 0 and 2^16) in host byte order. -pub fn createDTO(globalObject: *JSC.JSGlobalObject, addr_: []const u8, port_: u16, is_ipv6: bool) JSC.JSValue { +pub fn createDTO(globalObject: *JSC.JSGlobalObject, addr_: []const u8, port_: u16, is_ipv6: bool) bun.JSError!JSC.JSValue { if (comptime bun.Environment.isDebug) { bun.assertWithLocation(addr_.len > 0, @src()); } - return JSSocketAddressDTO__create(globalObject, bun.String.createUTF8ForJS(globalObject, addr_), port_, is_ipv6); + return JSSocketAddressDTO__create(globalObject, try bun.String.createUTF8ForJS(globalObject, addr_), port_, is_ipv6); } extern "c" fn JSSocketAddressDTO__create(globalObject: *JSC.JSGlobalObject, address_: JSC.JSValue, port_: u16, is_ipv6: bool) JSC.JSValue; diff --git a/src/bun.js/api/bun/udp_socket.zig b/src/bun.js/api/bun/udp_socket.zig index d4ae3e6d8a..03b0a59ca0 100644 --- a/src/bun.js/api/bun/udp_socket.zig +++ b/src/bun.js/api/bun/udp_socket.zig @@ -339,7 +339,7 @@ pub const UDPSocket = struct { .message = bun.String.createFormat("bind {s} {s}", .{ code, config.hostname }) catch bun.outOfMemory(), }; const error_value = sys_err.toErrorInstance(globalThis); - error_value.put(globalThis, "address", bun.String.createUTF8ForJS(globalThis, config.hostname)); + error_value.put(globalThis, "address", try bun.String.createUTF8ForJS(globalThis, config.hostname)); return globalThis.throwValue(error_value); } return globalThis.throw("Failed to bind socket", .{}); diff --git a/src/bun.js/api/crypto/CryptoHasher.zig b/src/bun.js/api/crypto/CryptoHasher.zig index 3f4e97e898..c08d6b25f4 100644 --- a/src/bun.js/api/crypto/CryptoHasher.zig +++ b/src/bun.js/api/crypto/CryptoHasher.zig @@ -720,7 +720,7 @@ fn StaticCryptoHasher(comptime Hasher: type, comptime name: [:0]const u8) type { return output_buf.value; } else { var array_buffer_out = JSC.ArrayBuffer.fromBytes(bun.default_allocator.dupe(u8, output_digest_slice) catch unreachable, .Uint8Array); - return array_buffer_out.toJSUnchecked(globalThis, null); + return array_buffer_out.toJSUnchecked(globalThis); } } @@ -835,7 +835,7 @@ fn StaticCryptoHasher(comptime Hasher: type, comptime name: [:0]const u8) type { return output_buf.value; } else { var array_buffer_out = JSC.ArrayBuffer.fromBytes(bun.default_allocator.dupe(u8, &output_digest_buf) catch unreachable, .Uint8Array); - return array_buffer_out.toJSUnchecked(globalThis, null); + return array_buffer_out.toJSUnchecked(globalThis); } } diff --git a/src/bun.js/api/html_rewriter.zig b/src/bun.js/api/html_rewriter.zig index 67fd3d3b8c..337649cd95 100644 --- a/src/bun.js/api/html_rewriter.zig +++ b/src/bun.js/api/html_rewriter.zig @@ -1856,11 +1856,7 @@ pub const Element = struct { pub const setInnerContent = host_fn.wrapInstanceMethod(Element, "setInnerContent_", false); /// Removes the element with all its content. - pub fn remove( - this: *Element, - _: *JSGlobalObject, - callFrame: *JSC.CallFrame, - ) bun.JSError!JSValue { + pub fn remove(this: *Element, _: *JSGlobalObject, callFrame: *JSC.CallFrame) bun.JSError!JSValue { if (this.element == null) return .js_undefined; @@ -1869,17 +1865,14 @@ pub const Element = struct { } /// Removes the start tag and end tag of the element but keeps its inner content intact. - pub fn removeAndKeepContent( - this: *Element, - _: *JSGlobalObject, - callFrame: *JSC.CallFrame, - ) bun.JSError!JSValue { + pub fn removeAndKeepContent(this: *Element, _: *JSGlobalObject, callFrame: *JSC.CallFrame) bun.JSError!JSValue { if (this.element == null) return .js_undefined; this.element.?.removeAndKeepContent(); return callFrame.this(); } + pub fn getTagName(this: *Element, globalObject: *JSGlobalObject) JSValue { if (this.element == null) return .js_undefined; @@ -1887,11 +1880,7 @@ pub const Element = struct { return htmlStringValue(this.element.?.tagName(), globalObject); } - pub fn setTagName( - this: *Element, - global: *JSGlobalObject, - value: JSValue, - ) JSError!void { + pub fn setTagName(this: *Element, global: *JSGlobalObject, value: JSValue) JSError!void { if (this.element == null) return; var text = try value.toSlice(global, bun.default_allocator); @@ -1902,46 +1891,31 @@ pub const Element = struct { }; } - pub fn getRemoved( - this: *Element, - _: *JSGlobalObject, - ) JSValue { + pub fn getRemoved(this: *Element, _: *JSGlobalObject) JSValue { if (this.element == null) return .js_undefined; return JSValue.jsBoolean(this.element.?.isRemoved()); } - pub fn getSelfClosing( - this: *Element, - _: *JSGlobalObject, - ) JSValue { + pub fn getSelfClosing(this: *Element, _: *JSGlobalObject) JSValue { if (this.element == null) return .js_undefined; return JSValue.jsBoolean(this.element.?.isSelfClosing()); } - pub fn getCanHaveContent( - this: *Element, - _: *JSGlobalObject, - ) JSValue { + pub fn getCanHaveContent(this: *Element, _: *JSGlobalObject) JSValue { if (this.element == null) return .js_undefined; return JSValue.jsBoolean(this.element.?.canHaveContent()); } - pub fn getNamespaceURI( - this: *Element, - globalObject: *JSGlobalObject, - ) JSValue { + pub fn getNamespaceURI(this: *Element, globalObject: *JSGlobalObject) JSError!JSValue { if (this.element == null) return .js_undefined; return bun.String.createUTF8ForJS(globalObject, std.mem.span(this.element.?.namespaceURI())); } - pub fn getAttributes( - this: *Element, - globalObject: *JSGlobalObject, - ) JSValue { + pub fn getAttributes(this: *Element, globalObject: *JSGlobalObject) JSValue { if (this.element == null) return .js_undefined; diff --git a/src/bun.js/api/server.zig b/src/bun.js/api/server.zig index 5e3d78dbb5..120aeb248a 100644 --- a/src/bun.js/api/server.zig +++ b/src/bun.js/api/server.zig @@ -417,7 +417,7 @@ const ServePlugins = struct { out.* = bun.String.init(raw_plugin); } const plugin_js_array = try bun.String.toJSArray(global, bunstring_array); - const bunfig_folder_bunstr = bun.String.createUTF8ForJS(global, bunfig_folder); + const bunfig_folder_bunstr = try bun.String.createUTF8ForJS(global, bunfig_folder); this.state = .{ .pending = .{ .promise = JSC.JSPromise.Strong.init(global), @@ -676,7 +676,7 @@ pub fn NewServer(protocol_enum: enum { http, https }, development_kind: enum { d }; } - pub fn requestIP(this: *ThisServer, request: *JSC.WebCore.Request) JSC.JSValue { + pub fn requestIP(this: *ThisServer, request: *JSC.WebCore.Request) bun.JSError!JSC.JSValue { if (this.config.address == .unix) return JSValue.jsNull(); const info = request.request_context.getRemoteSocketInfo() orelse return JSValue.jsNull(); return SocketAddress.createDTO(this.globalThis, info.ip, @intCast(info.port), info.is_ipv6); @@ -1332,24 +1332,15 @@ pub fn NewServer(protocol_enum: enum { http, https }, development_kind: enum { d return JSC.JSValue.jsNumber(listener.getLocalPort()); } - pub fn getId( - this: *ThisServer, - globalThis: *JSC.JSGlobalObject, - ) JSC.JSValue { + pub fn getId(this: *ThisServer, globalThis: *JSC.JSGlobalObject) bun.JSError!JSC.JSValue { return bun.String.createUTF8ForJS(globalThis, this.config.id); } - pub fn getPendingRequests( - this: *ThisServer, - _: *JSC.JSGlobalObject, - ) JSC.JSValue { + pub fn getPendingRequests(this: *ThisServer, _: *JSC.JSGlobalObject) JSC.JSValue { return JSC.JSValue.jsNumber(@as(i32, @intCast(@as(u31, @truncate(this.pending_requests))))); } - pub fn getPendingWebSockets( - this: *ThisServer, - _: *JSC.JSGlobalObject, - ) JSC.JSValue { + pub fn getPendingWebSockets(this: *ThisServer, _: *JSC.JSGlobalObject) JSC.JSValue { return JSC.JSValue.jsNumber(@as(i32, @intCast(@as(u31, @truncate(this.activeSocketsCount()))))); } @@ -2905,10 +2896,8 @@ pub fn NewServer(protocol_enum: enum { http, https }, development_kind: enum { d pub fn onClientErrorCallback(this: *ThisServer, socket: *uws.Socket, error_code: u8, raw_packet: []const u8) void { if (this.on_clienterror.get()) |callback| { const is_ssl = protocol_enum == .https; - const node_socket = Bun__createNodeHTTPServerSocket(is_ssl, socket, this.globalThis); - if (node_socket.isEmptyOrUndefinedOrNull()) { - return; - } + const node_socket = bun.jsc.fromJSHostCall(this.globalThis, @src(), Bun__createNodeHTTPServerSocket, .{ is_ssl, socket, this.globalThis }) catch return; + if (node_socket.isUndefinedOrNull()) return; const error_code_value = JSValue.jsNumber(error_code); const raw_packet_value = JSC.ArrayBuffer.createBuffer(this.globalThis, raw_packet) catch return; // TODO: properly propagate exception upwards diff --git a/src/bun.js/api/server/HTMLBundle.zig b/src/bun.js/api/server/HTMLBundle.zig index 7f4201103f..1aeb0aa626 100644 --- a/src/bun.js/api/server/HTMLBundle.zig +++ b/src/bun.js/api/server/HTMLBundle.zig @@ -34,7 +34,7 @@ fn deinit(this: *HTMLBundle) void { bun.destroy(this); } -pub fn getIndex(this: *HTMLBundle, globalObject: *JSGlobalObject) JSValue { +pub fn getIndex(this: *HTMLBundle, globalObject: *JSGlobalObject) bun.JSError!JSValue { return bun.String.createUTF8ForJS(globalObject, this.path); } diff --git a/src/bun.js/api/server/ServerWebSocket.zig b/src/bun.js/api/server/ServerWebSocket.zig index c956735fa1..5a41fa9282 100644 --- a/src/bun.js/api/server/ServerWebSocket.zig +++ b/src/bun.js/api/server/ServerWebSocket.zig @@ -142,7 +142,7 @@ pub fn onMessage( const arguments = [_]JSValue{ this.getThisValue(), switch (opcode) { - .text => bun.String.createUTF8ForJS(globalObject, message), + .text => bun.String.createUTF8ForJS(globalObject, message) catch .zero, // TODO: properly propagate exception upwards .binary => this.binaryToJS(globalObject, message) catch .zero, // TODO: properly propagate exception upwards else => unreachable, }, @@ -322,14 +322,18 @@ pub fn onClose(this: *ServerWebSocket, _: uws.AnyWebSocket, code: i32, message: } } - _ = handler.onClose.call( - globalObject, - .js_undefined, - &[_]JSC.JSValue{ this.getThisValue(), JSValue.jsNumber(code), bun.String.createUTF8ForJS(globalObject, message) }, - ) catch |e| { + const message_js = bun.String.createUTF8ForJS(globalObject, message) catch |e| { const err = globalObject.takeException(e); log("onClose error", .{}); handler.runErrorCallback(vm, globalObject, err); + return; + }; + + _ = handler.onClose.call(globalObject, .js_undefined, &[_]JSC.JSValue{ this.getThisValue(), JSValue.jsNumber(code), message_js }) catch |e| { + const err = globalObject.takeException(e); + log("onClose error", .{}); + handler.runErrorCallback(vm, globalObject, err); + return; }; } else if (signal) |sig| { const loop = vm.eventLoop(); @@ -1242,7 +1246,7 @@ pub fn isSubscribed( pub fn getRemoteAddress( this: *ServerWebSocket, globalThis: *JSC.JSGlobalObject, -) JSValue { +) bun.JSError!JSValue { if (this.isClosed()) { return .js_undefined; } diff --git a/src/bun.js/bindings/BindgenCustomEnforceRange.h b/src/bun.js/bindings/BindgenCustomEnforceRange.h index a207b4e67a..6e1daa3379 100644 --- a/src/bun.js/bindings/BindgenCustomEnforceRange.h +++ b/src/bun.js/bindings/BindgenCustomEnforceRange.h @@ -44,7 +44,7 @@ struct Converter> static inline NumericType convert(JSC::JSGlobalObject& lexicalGlobalObject, JSC::JSValue value, ExceptionThrower&& exceptionThrower = ExceptionThrower()) { auto scope = DECLARE_THROW_SCOPE(lexicalGlobalObject.vm()); - ASSERT(!scope.exception()); + EXCEPTION_ASSERT(!scope.exception()); double unrestricted; if constexpr (Kind == Bun::BindgenCustomEnforceRangeKind::Node) { // In Node.js, `validateNumber`, `validateInt32`, `validateUint32`, @@ -58,7 +58,7 @@ struct Converter> return 0; } unrestricted = value.asNumber(); - ASSERT(!scope.exception()); + 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/BunDebugger.cpp b/src/bun.js/bindings/BunDebugger.cpp index ed686b308d..0cfc8066a7 100644 --- a/src/bun.js/bindings/BunDebugger.cpp +++ b/src/bun.js/bindings/BunDebugger.cpp @@ -578,7 +578,7 @@ extern "C" void Bun__startJSDebuggerThread(Zig::GlobalObject* debuggerGlobalObje debuggerScriptExecutionContext = debuggerGlobalObject->scriptExecutionContext(); JSC::VM& vm = debuggerGlobalObject->vm(); - auto scope = DECLARE_THROW_SCOPE(vm); + auto scope = DECLARE_CATCH_SCOPE(vm); JSValue defaultValue = debuggerGlobalObject->internalModuleRegistry()->requireId(debuggerGlobalObject, vm, InternalModuleRegistry::Field::InternalDebugger); scope.assertNoException(); JSFunction* debuggerDefaultFn = jsCast(defaultValue.asCell()); diff --git a/src/bun.js/bindings/BunObject.cpp b/src/bun.js/bindings/BunObject.cpp index f45743b2b4..0307e2811a 100644 --- a/src/bun.js/bindings/BunObject.cpp +++ b/src/bun.js/bindings/BunObject.cpp @@ -511,11 +511,11 @@ JSC_DEFINE_HOST_FUNCTION(functionBunDeepEquals, (JSGlobalObject * globalObject, if (strict.isBoolean() && strict.asBoolean()) { - bool isEqual = Bun__deepEquals(globalObject, arg1, arg2, gcBuffer, stack, &scope, true); + bool isEqual = Bun__deepEquals(globalObject, arg1, arg2, gcBuffer, stack, scope, true); RETURN_IF_EXCEPTION(scope, {}); return JSValue::encode(jsBoolean(isEqual)); } else { - bool isEqual = Bun__deepEquals(globalObject, arg1, arg2, gcBuffer, stack, &scope, true); + bool isEqual = Bun__deepEquals(globalObject, arg1, arg2, gcBuffer, stack, scope, true); RETURN_IF_EXCEPTION(scope, {}); return JSValue::encode(jsBoolean(isEqual)); } @@ -546,7 +546,7 @@ JSC_DEFINE_HOST_FUNCTION(functionBunDeepMatch, (JSGlobalObject * globalObject, J std::set objVisited; std::set subsetVisited; MarkedArgumentBuffer gcBuffer; - bool match = Bun__deepMatch(object, &objVisited, subset, &subsetVisited, globalObject, &scope, &gcBuffer, false, false); + 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/BunProcess.cpp b/src/bun.js/bindings/BunProcess.cpp index 5f9ae19505..874c6cbadf 100644 --- a/src/bun.js/bindings/BunProcess.cpp +++ b/src/bun.js/bindings/BunProcess.cpp @@ -1102,8 +1102,7 @@ extern "C" bool Bun__promises__isErrorLike(JSC::JSGlobalObject* globalObject, JS if (!obj.isObject()) return false; auto* object = JSC::jsCast(obj); - const bool result = JSC::objectPrototypeHasOwnProperty(globalObject, object, vm.propertyNames->stack); - RELEASE_AND_RETURN(scope, result); + RELEASE_AND_RETURN(scope, JSC::objectPrototypeHasOwnProperty(globalObject, object, vm.propertyNames->stack)); } extern "C" JSC::EncodedJSValue Bun__noSideEffectsToString(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::EncodedJSValue reason) @@ -1145,25 +1144,23 @@ extern "C" void Bun__promises__emitUnhandledRejectionWarning(JSC::JSGlobalObject warning->putDirect(vm, Identifier::fromString(vm, "name"_s), jsString(vm, "UnhandledPromiseRejectionWarning"_str), JSC::PropertyAttribute::DontEnum | 0); JSValue reasonStack {}; - if (Bun__promises__isErrorLike(globalObject, JSValue::decode(reason))) { + auto is_errorlike = Bun__promises__isErrorLike(globalObject, JSValue::decode(reason)); + CLEAR_IF_EXCEPTION(scope); + if (is_errorlike) { reasonStack = JSValue::decode(reason).get(globalObject, vm.propertyNames->stack); - if (scope.exception()) [[unlikely]] - scope.clearException(); + CLEAR_IF_EXCEPTION(scope); warning->putDirect(vm, vm.propertyNames->stack, reasonStack); } if (!reasonStack) { reasonStack = JSValue::decode(Bun__noSideEffectsToString(vm, globalObject, reason)); - if (scope.exception()) [[unlikely]] - scope.clearException(); + CLEAR_IF_EXCEPTION(scope); } if (!reasonStack) reasonStack = jsUndefined(); Process::emitWarning(globalObject, reasonStack, jsString(globalObject->vm(), "UnhandledPromiseRejectionWarning"_str), jsUndefined(), jsUndefined()); - if (scope.exception()) [[unlikely]] - scope.clearException(); + CLEAR_IF_EXCEPTION(scope); Process::emitWarningErrorInstance(globalObject, warning); - if (scope.exception()) [[unlikely]] - scope.clearException(); + CLEAR_IF_EXCEPTION(scope); } extern "C" int Bun__handleUnhandledRejection(JSC::JSGlobalObject* lexicalGlobalObject, JSC::JSValue reason, JSC::JSValue promise) @@ -1200,6 +1197,7 @@ extern "C" bool Bun__emitHandledPromiseEvent(JSC::JSGlobalObject* lexicalGlobalO if (Bun__VM__allowRejectionHandledWarning(globalObject->bunVM())) { Process::emitWarning(globalObject, jsString(globalObject->vm(), String("Promise rejection was handled asynchronously"_s)), jsString(globalObject->vm(), String("PromiseRejectionHandledWarning"_s)), jsUndefined(), jsUndefined()); + CLEAR_IF_EXCEPTION(scope); } auto& wrapped = process->wrapped(); if (wrapped.listenerCount(eventType) > 0) { @@ -1622,6 +1620,7 @@ bool setProcessExitCodeInner(JSC::JSGlobalObject* lexicalGlobalObject, Process* if (!code.isUndefinedOrNull()) { if (code.isString() && !code.getString(lexicalGlobalObject).isEmpty()) { auto num = code.toNumber(lexicalGlobalObject); + RETURN_IF_EXCEPTION(throwScope, {}); if (!std::isnan(num)) { code = jsDoubleNumber(num); } @@ -1645,7 +1644,7 @@ JSC_DEFINE_CUSTOM_SETTER(setProcessExitCode, (JSC::JSGlobalObject * lexicalGloba auto throwScope = DECLARE_THROW_SCOPE(process->vm()); auto code = JSValue::decode(value); - return setProcessExitCodeInner(lexicalGlobalObject, process, code); + RELEASE_AND_RETURN(throwScope, setProcessExitCodeInner(lexicalGlobalObject, process, code)); } JSC_DEFINE_CUSTOM_GETTER(processConnected, (JSC::JSGlobalObject * lexicalGlobalObject, JSC::EncodedJSValue thisValue, JSC::PropertyName name)) @@ -2777,7 +2776,6 @@ inline JSValue processBindingConfig(Zig::GlobalObject* globalObject, JSC::VM& vm JSValue createCryptoX509Object(JSGlobalObject* globalObject) { auto& vm = JSC::getVM(globalObject); - auto scope = DECLARE_THROW_SCOPE(vm); auto cryptoX509 = JSC::constructEmptyObject(globalObject, globalObject->objectPrototype(), 1); cryptoX509->putDirect(vm, JSC::Identifier::fromString(vm, "isX509Certificate"_s), JSC::JSFunction::create(vm, globalObject, 1, String("isX509Certificate"_s), jsIsX509Certificate, ImplementationVisibility::Public), 0); return cryptoX509; @@ -2818,7 +2816,7 @@ JSC_DEFINE_HOST_FUNCTION(Process_functionBinding, (JSGlobalObject * jsGlobalObje if (moduleName == "tty_wrap"_s) return JSValue::encode(Bun::createNodeTTYWrapObject(globalObject)); if (moduleName == "udp_wrap"_s) PROCESS_BINDING_NOT_IMPLEMENTED("udp_wrap"); if (moduleName == "url"_s) PROCESS_BINDING_NOT_IMPLEMENTED("url"); - if (moduleName == "util"_s) return JSValue::encode(processBindingUtil(globalObject, vm)); + if (moduleName == "util"_s) RELEASE_AND_RETURN(throwScope, JSValue::encode(processBindingUtil(globalObject, vm))); if (moduleName == "uv"_s) return JSValue::encode(process->bindingUV()); if (moduleName == "v8"_s) PROCESS_BINDING_NOT_IMPLEMENTED("v8"); if (moduleName == "zlib"_s) PROCESS_BINDING_NOT_IMPLEMENTED("zlib"); @@ -3046,7 +3044,9 @@ JSC_DEFINE_HOST_FUNCTION(Process_functionCpuUsage, (JSC::JSGlobalObject * global RETURN_IF_EXCEPTION(throwScope, {}); double userComparator = userValue.toNumber(globalObject); + RETURN_IF_EXCEPTION(throwScope, {}); double systemComparator = systemValue.toNumber(globalObject); + RETURN_IF_EXCEPTION(throwScope, {}); if (!(userComparator >= 0 && userComparator <= JSC::maxSafeInteger())) { return Bun::ERR::INVALID_ARG_VALUE_RangeError(throwScope, globalObject, "prevValue.user"_s, userValue, "is invalid"_s); @@ -3663,7 +3663,9 @@ JSC_DEFINE_HOST_FUNCTION(Process_functionKill, (JSC::JSGlobalObject * globalObje // this is mimicking `if (pid != (pid | 0)) {` int pid = pid_value.toInt32(globalObject); RETURN_IF_EXCEPTION(scope, {}); - if (!JSC::JSValue::equal(globalObject, pid_value, jsNumber(pid))) { + auto eql = JSC::JSValue::equal(globalObject, pid_value, jsNumber(pid)); + RETURN_IF_EXCEPTION(scope, {}); + if (!eql) { return Bun::ERR::INVALID_ARG_TYPE(scope, globalObject, "pid"_s, "number"_s, pid_value); } @@ -3703,6 +3705,7 @@ JSC_DEFINE_HOST_FUNCTION(Process_functionKill, (JSC::JSGlobalObject * globalObje RETURN_IF_EXCEPTION(scope, {}); auto err = result.toInt32(globalObject); + RETURN_IF_EXCEPTION(scope, {}); if (err) { throwSystemError(scope, globalObject, "kill"_s, err); return {}; diff --git a/src/bun.js/bindings/BunString.cpp b/src/bun.js/bindings/BunString.cpp index 68cf63cbbb..d269d7cd86 100644 --- a/src/bun.js/bindings/BunString.cpp +++ b/src/bun.js/bindings/BunString.cpp @@ -96,9 +96,10 @@ extern "C" JSC::EncodedJSValue BunString__createUTF8ForJS(JSC::JSGlobalObject* g } auto str = WTF::String::fromUTF8ReplacingInvalidSequences(std::span { reinterpret_cast(ptr), length }); + EXCEPTION_ASSERT(str.isNull() == !!scope.exception()); if (str.isNull()) [[unlikely]] { throwOutOfMemoryError(globalObject, scope); - return JSC::EncodedJSValue(); + return {}; } return JSValue::encode(jsString(vm, WTFMove(str))); } diff --git a/src/bun.js/bindings/CatchScope.zig b/src/bun.js/bindings/CatchScope.zig index dca41bd0d1..c05cdb6511 100644 --- a/src/bun.js/bindings/CatchScope.zig +++ b/src/bun.js/bindings/CatchScope.zig @@ -64,6 +64,11 @@ pub const CatchScope = struct { return CatchScope__pureException(&self.bytes); } + pub fn clearException(self: *CatchScope) void { + if (comptime Environment.ci_assert) bun.assert(self.location == &self.bytes[0]); + return CatchScope__clearException(&self.bytes); + } + /// Get the thrown exception if it exists, or if an unhandled trap causes an exception to be thrown pub fn exceptionIncludingTraps(self: *CatchScope) ?*jsc.Exception { if (comptime Environment.ci_assert) bun.assert(self.location == &self.bytes[0]); @@ -190,6 +195,7 @@ extern fn CatchScope__construct( ) void; /// only returns exceptions that have already been thrown. does not check traps extern fn CatchScope__pureException(ptr: *align(alignment) [size]u8) ?*jsc.Exception; +extern fn CatchScope__clearException(ptr: *align(alignment) [size]u8) void; /// returns if an exception was already thrown, or if a trap (like another thread requesting /// termination) causes an exception to be thrown extern fn CatchScope__exceptionIncludingTraps(ptr: *align(alignment) [size]u8) ?*jsc.Exception; diff --git a/src/bun.js/bindings/CatchScopeBinding.cpp b/src/bun.js/bindings/CatchScopeBinding.cpp index 46b9a5458d..6abf1e75b3 100644 --- a/src/bun.js/bindings/CatchScopeBinding.cpp +++ b/src/bun.js/bindings/CatchScopeBinding.cpp @@ -44,6 +44,13 @@ extern "C" JSC::Exception* CatchScope__exceptionIncludingTraps(void* ptr) return nullptr; } +extern "C" void CatchScope__clearException(void* ptr) +{ + ASSERT((uintptr_t)ptr % alignof(CatchScope) == 0); + auto* scope = static_cast(ptr); + scope->clearException(); +} + extern "C" void CatchScope__destruct(void* ptr) { ASSERT((uintptr_t)ptr % alignof(CatchScope) == 0); diff --git a/src/bun.js/bindings/JSBuffer.cpp b/src/bun.js/bindings/JSBuffer.cpp index eeb0500ee6..ed80d82c6a 100644 --- a/src/bun.js/bindings/JSBuffer.cpp +++ b/src/bun.js/bindings/JSBuffer.cpp @@ -227,7 +227,7 @@ static JSUint8Array* allocBuffer(JSC::JSGlobalObject* lexicalGlobalObject, size_ auto* uint8Array = JSC::JSUint8Array::create(lexicalGlobalObject, subclassStructure, byteLength); // it should have thrown an exception already - ASSERT(!!throwScope.exception() == !uint8Array); + EXCEPTION_ASSERT(!!throwScope.exception() == !uint8Array); return uint8Array; } @@ -241,7 +241,7 @@ static JSUint8Array* allocBufferUnsafe(JSC::JSGlobalObject* lexicalGlobalObject, auto* result = createUninitializedBuffer(lexicalGlobalObject, byteLength); // it should have thrown an exception already - ASSERT(!!throwScope.exception() == !result); + EXCEPTION_ASSERT(!!throwScope.exception() == !result); return result; } diff --git a/src/bun.js/bindings/JSCommonJSModule.cpp b/src/bun.js/bindings/JSCommonJSModule.cpp index 36d0e03cb6..db249ff9f7 100644 --- a/src/bun.js/bindings/JSCommonJSModule.cpp +++ b/src/bun.js/bindings/JSCommonJSModule.cpp @@ -312,7 +312,7 @@ JSC_DEFINE_HOST_FUNCTION(requireResolvePathsFunction, (JSGlobalObject * globalOb } RETURN_IF_EXCEPTION(scope, {}); Bun::PathResolveModule parent = { .paths = nullptr, .filename = filename, .pathsArrayLazy = true }; - return JSValue::encode(Bun::resolveLookupPaths(globalObject, requestStr, parent)); + RELEASE_AND_RETURN(scope, JSValue::encode(Bun::resolveLookupPaths(globalObject, requestStr, parent))); } JSC_DEFINE_CUSTOM_GETTER(jsRequireCacheGetter, (JSC::JSGlobalObject * globalObject, JSC::EncodedJSValue thisValue, JSC::PropertyName)) diff --git a/src/bun.js/bindings/JSGlobalObject.zig b/src/bun.js/bindings/JSGlobalObject.zig index 1380682452..b7dbeacbe2 100644 --- a/src/bun.js/bindings/JSGlobalObject.zig +++ b/src/bun.js/bindings/JSGlobalObject.zig @@ -419,8 +419,7 @@ pub const JSGlobalObject = opaque { extern fn Bun__Process__emitWarning(globalObject: *JSGlobalObject, warning: JSValue, @"type": JSValue, code: JSValue, ctor: JSValue) void; pub fn emitWarning(globalObject: *JSGlobalObject, warning: JSValue, @"type": JSValue, code: JSValue, ctor: JSValue) JSError!void { - Bun__Process__emitWarning(globalObject, warning, @"type", code, ctor); - if (globalObject.hasException()) return error.JSError; + return bun.jsc.fromJSHostCallGeneric(globalObject, @src(), Bun__Process__emitWarning, .{ globalObject, warning, @"type", code, ctor }); } extern fn JSC__JSGlobalObject__queueMicrotaskJob(JSC__JSGlobalObject__ptr: *JSGlobalObject, JSValue, JSValue, JSValue) void; @@ -429,8 +428,7 @@ pub const JSGlobalObject = opaque { } pub fn throwValue(this: *JSGlobalObject, value: JSC.JSValue) JSError { - this.vm().throwError(this, value); - return error.JSError; + return this.vm().throwError(this, value); } pub fn throwTypeError(this: *JSGlobalObject, comptime fmt: [:0]const u8, args: anytype) bun.JSError { @@ -460,8 +458,7 @@ pub const JSGlobalObject = opaque { defer allocator_.free(buffer); const str = ZigString.initUTF8(buffer); const err_value = str.toErrorInstance(this); - this.vm().throwError(this, err_value); - return error.JSError; + return this.vm().throwError(this, err_value); } // TODO: delete these two fns diff --git a/src/bun.js/bindings/JSType.zig b/src/bun.js/bindings/JSType.zig index 59d9690e6c..dd8c878d66 100644 --- a/src/bun.js/bindings/JSType.zig +++ b/src/bun.js/bindings/JSType.zig @@ -648,22 +648,22 @@ pub const JSType = enum(u8) { }; } - pub fn toC(this: JSType) C_API.JSTypedArrayType { + pub fn toTypedArrayType(this: JSType) bun.jsc.ArrayBuffer.TypedArrayType { return switch (this) { - .Int8Array => .kJSTypedArrayTypeInt8Array, - .Int16Array => .kJSTypedArrayTypeInt16Array, - .Int32Array => .kJSTypedArrayTypeInt32Array, - .Uint8Array => .kJSTypedArrayTypeUint8Array, - .Uint8ClampedArray => .kJSTypedArrayTypeUint8ClampedArray, - .Uint16Array => .kJSTypedArrayTypeUint16Array, - .Uint32Array => .kJSTypedArrayTypeUint32Array, - .Float32Array => .kJSTypedArrayTypeFloat32Array, - .Float64Array => .kJSTypedArrayTypeFloat64Array, - .ArrayBuffer => .kJSTypedArrayTypeArrayBuffer, - .BigInt64Array => .kJSTypedArrayTypeBigInt64Array, - .BigUint64Array => .kJSTypedArrayTypeBigUint64Array, - // .DataView => .kJSTypedArrayTypeDataView, - else => .kJSTypedArrayTypeNone, + .Int8Array => .TypeInt8, + .Int16Array => .TypeInt16, + .Int32Array => .TypeInt32, + .Uint8Array => .TypeUint8, + .Uint8ClampedArray => .TypeUint8Clamped, + .Uint16Array => .TypeUint16, + .Uint32Array => .TypeUint32, + .Float16Array => .TypeFloat16, + .Float32Array => .TypeFloat32, + .Float64Array => .TypeFloat64, + .BigInt64Array => .TypeBigInt64, + .BigUint64Array => .TypeBigUint64, + .DataView => .TypeDataView, + else => .TypeNone, }; } @@ -797,4 +797,3 @@ pub const JSType = enum(u8) { }; const bun = @import("bun"); -const C_API = bun.JSC.C; diff --git a/src/bun.js/bindings/JSValue.zig b/src/bun.js/bindings/JSValue.zig index 8c4fddb8a2..bf0019a4eb 100644 --- a/src/bun.js/bindings/JSValue.zig +++ b/src/bun.js/bindings/JSValue.zig @@ -1489,11 +1489,10 @@ pub const JSValue = enum(i64) { /// /// If you know that the property name is not an integer index, use `get` instead. /// - pub inline fn getPropertyValue(target: JSValue, global: *JSGlobalObject, property_name: []const u8) bun.JSError!?JSValue { + pub fn getPropertyValue(target: JSValue, global: *JSGlobalObject, property_name: []const u8) bun.JSError!?JSValue { if (bun.Environment.isDebug) bun.assert(target.isObject()); - return switch (JSC__JSValue__getPropertyValue(target, global, property_name.ptr, @intCast(property_name.len))) { - .zero => error.JSError, + return switch (try bun.jsc.fromJSHostCall(global, @src(), JSC__JSValue__getPropertyValue, .{ target, global, property_name.ptr, @intCast(property_name.len) })) { .property_does_not_exist_on_object => null, .js_undefined => null, else => |val| val, diff --git a/src/bun.js/bindings/JSX509Certificate.cpp b/src/bun.js/bindings/JSX509Certificate.cpp index 0dc8938161..5f343d6512 100644 --- a/src/bun.js/bindings/JSX509Certificate.cpp +++ b/src/bun.js/bindings/JSX509Certificate.cpp @@ -171,7 +171,7 @@ JSC_DEFINE_HOST_FUNCTION(x509CertificateConstructorConstruct, (JSGlobalObject * scope.release(); } - return JSValue::encode(createX509Certificate(vm, globalObject, structure, arg)); + RELEASE_AND_RETURN(scope, JSValue::encode(createX509Certificate(vm, globalObject, structure, arg))); } const ClassInfo JSX509Certificate::s_info = { "X509Certificate"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSX509Certificate) }; @@ -271,9 +271,6 @@ JSX509Certificate* JSX509Certificate::create(JSC::VM& vm, JSC::Structure* struct String JSX509Certificate::toPEMString() const { - VM& vm = globalObject()->vm(); - auto scope = DECLARE_THROW_SCOPE(vm); - auto bio = view().toPEM(); if (!bio) { return String(); diff --git a/src/bun.js/bindings/JSX509CertificatePrototype.cpp b/src/bun.js/bindings/JSX509CertificatePrototype.cpp index 2883aabe9e..e7bd02bef8 100644 --- a/src/bun.js/bindings/JSX509CertificatePrototype.cpp +++ b/src/bun.js/bindings/JSX509CertificatePrototype.cpp @@ -271,8 +271,9 @@ JSC_DEFINE_HOST_FUNCTION(jsX509CertificateProtoFuncCheckEmail, (JSGlobalObject * Bun::UTF8View emailView(view); - if (!thisObject->checkEmail(globalObject, emailView.span(), flags)) - return JSValue::encode(jsUndefined()); + auto check = thisObject->checkEmail(globalObject, emailView.span(), flags); + RETURN_IF_EXCEPTION(scope, {}); + if (!check) return JSValue::encode(jsUndefined()); return JSValue::encode(emailString); } @@ -305,8 +306,9 @@ JSC_DEFINE_HOST_FUNCTION(jsX509CertificateProtoFuncCheckHost, (JSGlobalObject * Bun::UTF8View hostView(view); - if (!thisObject->checkHost(globalObject, hostView.span(), flags)) - return JSValue::encode(jsUndefined()); + auto check = thisObject->checkHost(globalObject, hostView.span(), flags); + RETURN_IF_EXCEPTION(scope, {}); + if (!check) return JSValue::encode(jsUndefined()); return JSValue::encode(hostString); } @@ -339,8 +341,9 @@ JSC_DEFINE_HOST_FUNCTION(jsX509CertificateProtoFuncCheckIP, (JSGlobalObject * gl // uint32_t flags = getFlags(vm, globalObject, scope, callFrame->argument(1)); // RETURN_IF_EXCEPTION(scope, {}); - if (!thisObject->checkIP(globalObject, ip.data())) - return JSValue::encode(jsUndefined()); + auto check = thisObject->checkIP(globalObject, ip.data()); + RETURN_IF_EXCEPTION(scope, {}); + if (!check) return JSValue::encode(jsUndefined()); return JSValue::encode(ipString); } @@ -359,8 +362,9 @@ JSC_DEFINE_HOST_FUNCTION(jsX509CertificateProtoFuncCheckIssued, (JSGlobalObject return {}; } - if (!thisObject->checkIssued(globalObject, issuer)) - return JSValue::encode(jsUndefined()); + auto check = thisObject->checkIssued(globalObject, issuer); + RETURN_IF_EXCEPTION(scope, {}); + if (!check) return JSValue::encode(jsUndefined()); return JSValue::encode(issuer); } @@ -413,7 +417,7 @@ JSC_DEFINE_HOST_FUNCTION(jsX509CertificateProtoFuncToLegacyObject, (JSGlobalObje return {}; } - return JSValue::encode(thisObject->toLegacyObject(globalObject)); + RELEASE_AND_RETURN(scope, JSValue::encode(thisObject->toLegacyObject(globalObject))); } static JSValue undefinedIfEmpty(JSString* value) @@ -481,7 +485,7 @@ JSC_DEFINE_CUSTOM_GETTER(jsX509CertificateGetter_fingerprint, (JSGlobalObject * return {}; } - return JSValue::encode(thisObject->fingerprint()); + RELEASE_AND_RETURN(scope, JSValue::encode(thisObject->fingerprint())); } JSC_DEFINE_CUSTOM_GETTER(jsX509CertificateGetter_fingerprint256, (JSGlobalObject * globalObject, EncodedJSValue thisValue, PropertyName)) @@ -495,7 +499,7 @@ JSC_DEFINE_CUSTOM_GETTER(jsX509CertificateGetter_fingerprint256, (JSGlobalObject return {}; } - return JSValue::encode(thisObject->fingerprint256()); + RELEASE_AND_RETURN(scope, JSValue::encode(thisObject->fingerprint256())); } JSC_DEFINE_CUSTOM_GETTER(jsX509CertificateGetter_fingerprint512, (JSGlobalObject * globalObject, EncodedJSValue thisValue, PropertyName)) @@ -509,7 +513,7 @@ JSC_DEFINE_CUSTOM_GETTER(jsX509CertificateGetter_fingerprint512, (JSGlobalObject return {}; } - return JSValue::encode(thisObject->fingerprint512()); + RELEASE_AND_RETURN(scope, JSValue::encode(thisObject->fingerprint512())); } JSC_DEFINE_CUSTOM_GETTER(jsX509CertificateGetter_subject, (JSGlobalObject * globalObject, EncodedJSValue thisValue, PropertyName)) @@ -523,7 +527,7 @@ JSC_DEFINE_CUSTOM_GETTER(jsX509CertificateGetter_subject, (JSGlobalObject * glob return {}; } - return JSValue::encode(undefinedIfEmpty(thisObject->subject())); + RELEASE_AND_RETURN(scope, JSValue::encode(undefinedIfEmpty(thisObject->subject()))); } JSC_DEFINE_CUSTOM_GETTER(jsX509CertificateGetter_subjectAltName, (JSGlobalObject * globalObject, EncodedJSValue thisValue, PropertyName)) @@ -537,7 +541,7 @@ JSC_DEFINE_CUSTOM_GETTER(jsX509CertificateGetter_subjectAltName, (JSGlobalObject return {}; } - return JSValue::encode(undefinedIfEmpty(thisObject->subjectAltName())); + RELEASE_AND_RETURN(scope, JSValue::encode(undefinedIfEmpty(thisObject->subjectAltName()))); } JSC_DEFINE_CUSTOM_GETTER(jsX509CertificateGetter_infoAccess, (JSGlobalObject * globalObject, EncodedJSValue thisValue, PropertyName)) @@ -570,7 +574,7 @@ JSC_DEFINE_CUSTOM_GETTER(jsX509CertificateGetter_keyUsage, (JSGlobalObject * glo return {}; } - return JSValue::encode(thisObject->getKeyUsage(globalObject)); + RELEASE_AND_RETURN(scope, JSValue::encode(thisObject->getKeyUsage(globalObject))); } JSC_DEFINE_CUSTOM_GETTER(jsX509CertificateGetter_issuer, (JSGlobalObject * globalObject, EncodedJSValue thisValue, PropertyName)) @@ -584,7 +588,7 @@ JSC_DEFINE_CUSTOM_GETTER(jsX509CertificateGetter_issuer, (JSGlobalObject * globa return {}; } - return JSValue::encode(undefinedIfEmpty(thisObject->issuer())); + RELEASE_AND_RETURN(scope, JSValue::encode(undefinedIfEmpty(thisObject->issuer()))); } JSC_DEFINE_CUSTOM_GETTER(jsX509CertificateGetter_issuerCertificate, (JSGlobalObject * globalObject, EncodedJSValue thisValue, PropertyName)) @@ -625,7 +629,7 @@ JSC_DEFINE_CUSTOM_GETTER(jsX509CertificateGetter_publicKey, (JSGlobalObject * gl return {}; } - return JSValue::encode(thisObject->publicKey()); + RELEASE_AND_RETURN(scope, JSValue::encode(thisObject->publicKey())); } JSC_DEFINE_CUSTOM_GETTER(jsX509CertificateGetter_raw, (JSGlobalObject * globalObject, EncodedJSValue thisValue, PropertyName)) @@ -639,7 +643,7 @@ JSC_DEFINE_CUSTOM_GETTER(jsX509CertificateGetter_raw, (JSGlobalObject * globalOb return {}; } - return JSValue::encode(undefinedIfEmpty(thisObject->raw())); + RELEASE_AND_RETURN(scope, JSValue::encode(undefinedIfEmpty(thisObject->raw()))); } JSC_DEFINE_CUSTOM_GETTER(jsX509CertificateGetter_serialNumber, (JSGlobalObject * globalObject, EncodedJSValue thisValue, PropertyName)) @@ -653,7 +657,7 @@ JSC_DEFINE_CUSTOM_GETTER(jsX509CertificateGetter_serialNumber, (JSGlobalObject * return {}; } - return JSValue::encode(undefinedIfEmpty(thisObject->serialNumber())); + RELEASE_AND_RETURN(scope, JSValue::encode(undefinedIfEmpty(thisObject->serialNumber()))); } JSC_DEFINE_CUSTOM_GETTER(jsX509CertificateGetter_validFrom, (JSGlobalObject * globalObject, EncodedJSValue thisValue, PropertyName)) @@ -667,7 +671,7 @@ JSC_DEFINE_CUSTOM_GETTER(jsX509CertificateGetter_validFrom, (JSGlobalObject * gl return {}; } - return JSValue::encode(undefinedIfEmpty(thisObject->validFrom())); + RELEASE_AND_RETURN(scope, JSValue::encode(undefinedIfEmpty(thisObject->validFrom()))); } JSC_DEFINE_CUSTOM_GETTER(jsX509CertificateGetter_validTo, (JSGlobalObject * globalObject, EncodedJSValue thisValue, PropertyName)) @@ -681,7 +685,7 @@ JSC_DEFINE_CUSTOM_GETTER(jsX509CertificateGetter_validTo, (JSGlobalObject * glob return {}; } - return JSValue::encode(undefinedIfEmpty(thisObject->validTo())); + RELEASE_AND_RETURN(scope, JSValue::encode(undefinedIfEmpty(thisObject->validTo()))); } JSC_DEFINE_CUSTOM_GETTER(jsX509CertificateGetter_validToDate, (JSGlobalObject * globalObject, EncodedJSValue thisValue, PropertyName)) diff --git a/src/bun.js/bindings/ModuleLoader.cpp b/src/bun.js/bindings/ModuleLoader.cpp index 03284445d4..10ee016ce8 100644 --- a/src/bun.js/bindings/ModuleLoader.cpp +++ b/src/bun.js/bindings/ModuleLoader.cpp @@ -358,7 +358,7 @@ static JSValue handleVirtualModuleResult( if (auto* exception = scope.exception()) { if constexpr (allowPromise) { scope.clearException(); - return rejectedInternalPromise(globalObject, exception); + RELEASE_AND_RETURN(scope, rejectedInternalPromise(globalObject, exception)); } else { return exception; } @@ -417,7 +417,7 @@ static JSValue handleVirtualModuleResult( JSC::SyntheticSourceProvider::create(WTFMove(function), JSC::SourceOrigin(), specifier->toWTFString(BunString::ZeroCopy))); JSC::ensureStillAliveHere(object); - return rejectOrResolve(JSSourceCode::create(globalObject->vm(), WTFMove(source))); + RELEASE_AND_RETURN(scope, rejectOrResolve(JSSourceCode::create(globalObject->vm(), WTFMove(source)))); } case OnLoadResultTypePromise: { @@ -485,9 +485,11 @@ extern "C" void Bun__onFulfillAsyncModule( if (res->result.value.isCommonJSModule) { auto created = Bun::createCommonJSModule(jsCast(globalObject), specifierValue, res->result.value); + EXCEPTION_ASSERT(created.has_value() == !scope.exception()); if (created.has_value()) { JSSourceCode* code = JSSourceCode::create(vm, WTFMove(created.value())); promise->resolve(globalObject, code); + scope.assertNoExceptionExceptTermination(); } else { auto* exception = scope.exception(); if (!vm.isTerminationException(exception)) { @@ -888,7 +890,7 @@ static JSValue fetchESMSourceCode( const auto reject = [&](JSC::JSValue exception) -> JSValue { if constexpr (allowPromise) { - return rejectedInternalPromise(globalObject, exception); + RELEASE_AND_RETURN(scope, rejectedInternalPromise(globalObject, exception)); } else { throwException(globalObject, scope, exception); return {}; @@ -903,7 +905,7 @@ static JSValue fetchESMSourceCode( } scope.clearException(); - return rejectedInternalPromise(globalObject, exception); + RELEASE_AND_RETURN(scope, rejectedInternalPromise(globalObject, exception)); } if constexpr (allowPromise) { @@ -936,15 +938,15 @@ static JSValue fetchESMSourceCode( // This can happen if it's a `bun build --compile`'d CommonJS file if (res->result.value.isCommonJSModule) { auto created = Bun::createCommonJSModule(globalObject, specifierJS, res->result.value); - + EXCEPTION_ASSERT(created.has_value() == !scope.exception()); if (created.has_value()) { - return rejectOrResolve(JSSourceCode::create(vm, WTFMove(created.value()))); + RELEASE_AND_RETURN(scope, rejectOrResolve(JSSourceCode::create(vm, WTFMove(created.value())))); } if constexpr (allowPromise) { auto* exception = scope.exception(); scope.clearException(); - return rejectedInternalPromise(globalObject, exception); + RELEASE_AND_RETURN(scope, rejectedInternalPromise(globalObject, exception)); } else { scope.release(); return {}; @@ -957,13 +959,13 @@ static JSValue fetchESMSourceCode( switch (tag) { case SyntheticModuleType::ESM: { auto&& provider = Zig::SourceProvider::create(globalObject, res->result.value, JSC::SourceProviderSourceType::Module, true); - return rejectOrResolve(JSSourceCode::create(vm, JSC::SourceCode(provider))); + RELEASE_AND_RETURN(scope, rejectOrResolve(JSSourceCode::create(vm, JSC::SourceCode(provider)))); } #define CASE(str, name) \ case (SyntheticModuleType::name): { \ auto source = JSC::SourceCode(JSC::SyntheticSourceProvider::create(generateNativeModule_##name, JSC::SourceOrigin(), WTFMove(moduleKey))); \ - return rejectOrResolve(JSSourceCode::create(vm, WTFMove(source))); \ + RELEASE_AND_RETURN(scope, rejectOrResolve(JSSourceCode::create(vm, WTFMove(source)))); \ } BUN_FOREACH_ESM_NATIVE_MODULE(CASE) #undef CASE @@ -973,10 +975,10 @@ static JSValue fetchESMSourceCode( if (tag & SyntheticModuleType::InternalModuleRegistryFlag) { constexpr auto mask = (SyntheticModuleType::InternalModuleRegistryFlag - 1); auto source = JSC::SourceCode(JSC::SyntheticSourceProvider::create(generateInternalModuleSourceCode(globalObject, static_cast(tag & mask)), JSC::SourceOrigin(URL(makeString("builtins://"_s, moduleKey))), moduleKey)); - return rejectOrResolve(JSSourceCode::create(vm, WTFMove(source))); + RELEASE_AND_RETURN(scope, rejectOrResolve(JSSourceCode::create(vm, WTFMove(source)))); } else { auto&& provider = Zig::SourceProvider::create(globalObject, res->result.value, JSC::SourceProviderSourceType::Module, true); - return rejectOrResolve(JSC::JSSourceCode::create(vm, JSC::SourceCode(provider))); + RELEASE_AND_RETURN(scope, rejectOrResolve(JSC::JSSourceCode::create(vm, JSC::SourceCode(provider)))); } } } @@ -1000,15 +1002,15 @@ static JSValue fetchESMSourceCode( if (res->success && res->result.value.isCommonJSModule) { auto created = Bun::createCommonJSModule(globalObject, specifierJS, res->result.value); - + EXCEPTION_ASSERT(created.has_value() == !scope.exception()); if (created.has_value()) { - return rejectOrResolve(JSSourceCode::create(vm, WTFMove(created.value()))); + RELEASE_AND_RETURN(scope, rejectOrResolve(JSSourceCode::create(vm, WTFMove(created.value())))); } if constexpr (allowPromise) { auto* exception = scope.exception(); scope.clearException(); - return rejectedInternalPromise(globalObject, exception); + RELEASE_AND_RETURN(scope, rejectedInternalPromise(globalObject, exception)); } else { scope.release(); return {}; @@ -1050,7 +1052,7 @@ static JSValue fetchESMSourceCode( JSC::SyntheticSourceProvider::create(WTFMove(function), JSC::SourceOrigin(), specifier->toWTFString(BunString::ZeroCopy))); JSC::ensureStillAliveHere(value); - return rejectOrResolve(JSSourceCode::create(globalObject->vm(), WTFMove(source))); + RELEASE_AND_RETURN(scope, rejectOrResolve(JSSourceCode::create(globalObject->vm(), WTFMove(source)))); } // TOML and JSONC may go through here else if (res->result.value.tag == SyntheticModuleType::ExportsObject) { @@ -1067,7 +1069,7 @@ static JSValue fetchESMSourceCode( JSC::SyntheticSourceProvider::create(WTFMove(function), JSC::SourceOrigin(), specifier->toWTFString(BunString::ZeroCopy))); JSC::ensureStillAliveHere(value); - return rejectOrResolve(JSSourceCode::create(globalObject->vm(), WTFMove(source))); + RELEASE_AND_RETURN(scope, rejectOrResolve(JSSourceCode::create(globalObject->vm(), WTFMove(source)))); } else if (res->result.value.tag == SyntheticModuleType::ExportDefaultObject) { JSC::JSValue value = JSC::JSValue::decode(res->result.value.jsvalue_for_export); if (!value) { @@ -1082,11 +1084,10 @@ static JSValue fetchESMSourceCode( JSC::SyntheticSourceProvider::create(WTFMove(function), JSC::SourceOrigin(), specifier->toWTFString(BunString::ZeroCopy))); JSC::ensureStillAliveHere(value); - return rejectOrResolve(JSSourceCode::create(globalObject->vm(), WTFMove(source))); + RELEASE_AND_RETURN(scope, rejectOrResolve(JSSourceCode::create(globalObject->vm(), WTFMove(source)))); } - return rejectOrResolve(JSC::JSSourceCode::create(vm, - JSC::SourceCode(Zig::SourceProvider::create(globalObject, res->result.value)))); + RELEASE_AND_RETURN(scope, rejectOrResolve(JSC::JSSourceCode::create(vm, JSC::SourceCode(Zig::SourceProvider::create(globalObject, res->result.value))))); } JSValue fetchESMSourceCodeSync( diff --git a/src/bun.js/bindings/NodeHTTP.cpp b/src/bun.js/bindings/NodeHTTP.cpp index b0ce4653ee..710118e86a 100644 --- a/src/bun.js/bindings/NodeHTTP.cpp +++ b/src/bun.js/bindings/NodeHTTP.cpp @@ -1088,9 +1088,7 @@ static void NodeHTTPServer__writeHead( String key = entry.key(); String value = headerValue.toWTFString(globalObject); - if (scope.exception()) [[unlikely]] { - return false; - } + RETURN_IF_EXCEPTION(scope, false); writeResponseHeader(response, key, value); @@ -1396,9 +1394,7 @@ JSC_DEFINE_HOST_FUNCTION(jsHTTPSetHeader, (JSGlobalObject * globalObject, CallFr unsigned length = array->length(); if (length > 0) { JSValue item = array->getIndex(globalObject, 0); - if (scope.exception()) [[unlikely]] - return JSValue::encode(jsUndefined()); - + RETURN_IF_EXCEPTION(scope, {}); auto value = item.toWTFString(globalObject); RETURN_IF_EXCEPTION(scope, {}); impl->set(name, value); @@ -1406,8 +1402,7 @@ JSC_DEFINE_HOST_FUNCTION(jsHTTPSetHeader, (JSGlobalObject * globalObject, CallFr } for (unsigned i = 1; i < length; ++i) { JSValue value = array->getIndex(globalObject, i); - if (scope.exception()) [[unlikely]] - return JSValue::encode(jsUndefined()); + RETURN_IF_EXCEPTION(scope, {}); auto string = value.toWTFString(globalObject); RETURN_IF_EXCEPTION(scope, {}); impl->append(name, string); diff --git a/src/bun.js/bindings/NodeVM.cpp b/src/bun.js/bindings/NodeVM.cpp index 8d91cc4a4b..bcf870de11 100644 --- a/src/bun.js/bindings/NodeVM.cpp +++ b/src/bun.js/bindings/NodeVM.cpp @@ -134,7 +134,6 @@ JSC::JSFunction* constructAnonymousFunction(JSC::JSGlobalObject* globalObject, c if (actuallyValid) { auto exception = error.toErrorObject(globalObject, sourceCode, -1); RETURN_IF_EXCEPTION(throwScope, nullptr); - throwException(globalObject, throwScope, exception); return nullptr; } @@ -837,14 +836,10 @@ bool NodeVMGlobalObject::put(JSCell* cell, JSGlobalObject* globalObject, Propert } slot.setThisValue(sandbox); + bool result = sandbox->methodTable()->put(sandbox, globalObject, propertyName, value, slot); RETURN_IF_EXCEPTION(scope, false); - - if (!result) { - return false; - } - - RETURN_IF_EXCEPTION(scope, false); + if (!result) return false; if (isDeclaredOnSandbox && getter.isAccessor() and (getter.attributes() & PropertyAttribute::DontEnum) == 0) { return true; @@ -968,9 +963,7 @@ bool NodeVMGlobalObject::getOwnPropertySlot(JSObject* cell, JSGlobalObject* glob if (!notContextified) { bool result = contextifiedObject->getPropertySlot(globalObject, propertyName, slot); RETURN_IF_EXCEPTION(scope, false); - if (result) { - return true; - } + if (result) return true; } try_from_global: @@ -1000,7 +993,7 @@ bool NodeVMGlobalObject::defineOwnProperty(JSObject* cell, JSGlobalObject* globa auto scope = DECLARE_THROW_SCOPE(vm); auto* thisObject = jsCast(cell); - if (!thisObject->m_sandbox) { + if (!thisObject->m_sandbox) [[likely]] { RELEASE_AND_RETURN(scope, Base::defineOwnProperty(cell, globalObject, propertyName, descriptor, shouldThrow)); } @@ -1016,22 +1009,19 @@ bool NodeVMGlobalObject::defineOwnProperty(JSObject* cell, JSGlobalObject* globa } if (descriptor.isAccessorDescriptor()) { - RELEASE_AND_RETURN(scope, JSObject::defineOwnProperty(contextifiedObject, contextifiedObject->globalObject(), propertyName, descriptor, shouldThrow)); + RELEASE_AND_RETURN(scope, contextifiedObject->defineOwnProperty(contextifiedObject, contextifiedObject->globalObject(), propertyName, descriptor, shouldThrow)); } bool isDeclaredOnSandbox = contextifiedObject->getPropertySlot(globalObject, propertyName, slot); RETURN_IF_EXCEPTION(scope, false); if (isDeclaredOnSandbox && !isDeclaredOnGlobalProxy) { - RELEASE_AND_RETURN(scope, JSObject::defineOwnProperty(contextifiedObject, contextifiedObject->globalObject(), propertyName, descriptor, shouldThrow)); + RELEASE_AND_RETURN(scope, contextifiedObject->defineOwnProperty(contextifiedObject, contextifiedObject->globalObject(), propertyName, descriptor, shouldThrow)); } - bool result = JSObject::defineOwnProperty(contextifiedObject, contextifiedObject->globalObject(), propertyName, descriptor, shouldThrow); + auto did = contextifiedObject->defineOwnProperty(contextifiedObject, contextifiedObject->globalObject(), propertyName, descriptor, shouldThrow); RETURN_IF_EXCEPTION(scope, false); - - if (!result) { - return false; - } + if (!did) return false; RELEASE_AND_RETURN(scope, Base::defineOwnProperty(cell, globalObject, propertyName, descriptor, shouldThrow)); } @@ -1414,12 +1404,11 @@ JSInternalPromise* NodeVMGlobalObject::moduleLoaderImportModule(JSGlobalObject* void NodeVMGlobalObject::getOwnPropertyNames(JSObject* cell, JSGlobalObject* globalObject, JSC::PropertyNameArray& propertyNames, JSC::DontEnumPropertiesMode mode) { + auto& vm = JSC::getVM(globalObject); + auto scope = DECLARE_THROW_SCOPE(vm); auto* thisObject = jsCast(cell); - VM& vm = JSC::getVM(globalObject); - auto scope = DECLARE_THROW_SCOPE(vm); - - if (thisObject->m_sandbox) [[likely]] { + if (thisObject->m_sandbox) { thisObject->m_sandbox->getOwnPropertyNames(thisObject->m_sandbox.get(), globalObject, propertyNames, mode); RETURN_IF_EXCEPTION(scope, ); } diff --git a/src/bun.js/bindings/NodeVMModule.cpp b/src/bun.js/bindings/NodeVMModule.cpp index 14097cac21..4149b7dc41 100644 --- a/src/bun.js/bindings/NodeVMModule.cpp +++ b/src/bun.js/bindings/NodeVMModule.cpp @@ -66,9 +66,19 @@ JSValue NodeVMModule::evaluate(JSGlobalObject* globalObject, uint32_t timeout, b auto* sourceTextThis = jsDynamicCast(this); auto* syntheticThis = jsDynamicCast(this); +#define VM_RETURN_IF_EXCEPTION(scope__, value__) \ + do { \ + if (JSC::Exception* exception = scope__.exception()) { \ + status(Status::Errored); \ + if (sourceTextThis) sourceTextThis->m_evaluationException.set(vm, this, exception); \ + return value__; \ + } \ + } while (false); + AbstractModuleRecord* record {}; if (sourceTextThis) { record = sourceTextThis->moduleRecord(globalObject); + VM_RETURN_IF_EXCEPTION(scope, {}); } else if (syntheticThis) { record = syntheticThis->moduleRecord(globalObject); } else { @@ -78,11 +88,8 @@ JSValue NodeVMModule::evaluate(JSGlobalObject* globalObject, uint32_t timeout, b JSValue result {}; NodeVMGlobalObject* nodeVmGlobalObject = NodeVM::getGlobalObjectFromContext(globalObject, m_context.get(), false); - RETURN_IF_EXCEPTION(scope, {}); - - if (nodeVmGlobalObject) { - globalObject = nodeVmGlobalObject; - } + VM_RETURN_IF_EXCEPTION(scope, {}); + if (nodeVmGlobalObject) globalObject = nodeVmGlobalObject; auto run = [&] { if (sourceTextThis) { @@ -90,11 +97,13 @@ JSValue NodeVMModule::evaluate(JSGlobalObject* globalObject, uint32_t timeout, b evaluateDependencies(globalObject, record, timeout, breakOnSigint); RETURN_IF_EXCEPTION(scope, ); sourceTextThis->initializeImportMeta(globalObject); + RETURN_IF_EXCEPTION(scope, ); } else if (syntheticThis) { syntheticThis->evaluate(globalObject); + RETURN_IF_EXCEPTION(scope, ); } - RETURN_IF_EXCEPTION(scope, ); result = record->evaluate(globalObject, jsUndefined(), jsNumber(static_cast(JSGenerator::ResumeMode::NormalMode))); + RETURN_IF_EXCEPTION(scope, ); }; setSigintReceived(false); @@ -131,17 +140,12 @@ JSValue NodeVMModule::evaluate(JSGlobalObject* globalObject, uint32_t timeout, b setSigintReceived(false); } - if (JSC::Exception* exception = scope.exception()) { - status(Status::Errored); - if (sourceTextThis) { - sourceTextThis->m_evaluationException.set(vm, this, exception); - } - return {}; - } + VM_RETURN_IF_EXCEPTION(scope, {}); status(Status::Evaluated); m_evaluationResult.set(vm, this, result); return result; +#undef VM_RETURN_IF_EXCEPTION } NodeVMModule::NodeVMModule(JSC::VM& vm, JSC::Structure* structure, WTF::String identifier, JSValue context, JSValue moduleWrapper) @@ -224,17 +228,17 @@ NodeVMModule* NodeVMModule::create(JSC::VM& vm, JSC::JSGlobalObject* globalObjec JSModuleNamespaceObject* NodeVMModule::namespaceObject(JSC::JSGlobalObject* globalObject) { + auto& vm = JSC::getVM(globalObject); + auto scope = DECLARE_THROW_SCOPE(vm); JSModuleNamespaceObject* object = m_namespaceObject.get(); if (object) { return object; } if (auto* thisObject = jsDynamicCast(this)) { - VM& vm = globalObject->vm(); - auto scope = DECLARE_THROW_SCOPE(vm); - AbstractModuleRecord* record = thisObject->moduleRecord(globalObject); + AbstractModuleRecord* amr = thisObject->moduleRecord(globalObject); RETURN_IF_EXCEPTION(scope, {}); - object = record->getModuleNamespace(globalObject); + object = amr->getModuleNamespace(globalObject); RETURN_IF_EXCEPTION(scope, {}); if (object) { namespaceObject(vm, object); @@ -518,14 +522,9 @@ DEFINE_VISIT_CHILDREN(NodeVMModule); static EncodedJSValue constructModule(JSGlobalObject* globalObject, CallFrame* callFrame, JSValue newTarget = {}) { - VM& vm = globalObject->vm(); - auto scope = DECLARE_THROW_SCOPE(vm); + auto& vm = globalObject->vm(); ArgList args(callFrame); - - NodeVMModule* module = NodeVMModule::create(vm, globalObject, args); - RETURN_IF_EXCEPTION(scope, {}); - - return JSValue::encode(module); + return JSValue::encode(NodeVMModule::create(vm, globalObject, args)); } JSC_DEFINE_HOST_FUNCTION(moduleConstructorCall, (JSGlobalObject * globalObject, CallFrame* callFrame)) diff --git a/src/bun.js/bindings/NodeVMScript.cpp b/src/bun.js/bindings/NodeVMScript.cpp index 077629b910..2f76e172f9 100644 --- a/src/bun.js/bindings/NodeVMScript.cpp +++ b/src/bun.js/bindings/NodeVMScript.cpp @@ -332,9 +332,12 @@ static JSC::EncodedJSValue runInContext(NodeVMGlobalObject* globalObject, NodeVM if (allowStringInPlaceOfOptions && optionsArg.isString()) { options.filename = optionsArg.toWTFString(globalObject); RETURN_IF_EXCEPTION(scope, {}); - } else if (!options.fromJS(globalObject, vm, scope, optionsArg)) { + } else { + auto from = options.fromJS(globalObject, vm, scope, optionsArg); RETURN_IF_EXCEPTION(scope, {}); - options = {}; + if (!from) { + options = {}; + } } // Set the contextified object before evaluating @@ -477,11 +480,11 @@ JSC_DEFINE_CUSTOM_GETTER(scriptGetCachedData, (JSGlobalObject * globalObject, JS return ERR::INVALID_ARG_VALUE(scope, globalObject, "this"_s, thisValue, "must be a Script"_s); } - if (auto* buffer = script->getBytecodeBuffer()) { - RELEASE_AND_RETURN(scope, JSValue::encode(buffer)); - } - - RELEASE_AND_RETURN(scope, JSValue::encode(jsUndefined())); + scope.assertNoExceptionExceptTermination(); + auto* buffer = script->getBytecodeBuffer(); + RETURN_IF_EXCEPTION(scope, {}); + if (!buffer) return JSValue::encode(jsUndefined()); + return JSValue::encode(buffer); } JSC_DEFINE_CUSTOM_GETTER(scriptGetCachedDataProduced, (JSGlobalObject * globalObject, JSC::EncodedJSValue thisValueEncoded, PropertyName)) @@ -494,7 +497,8 @@ JSC_DEFINE_CUSTOM_GETTER(scriptGetCachedDataProduced, (JSGlobalObject * globalOb return ERR::INVALID_ARG_VALUE(scope, globalObject, "this"_s, thisValue, "must be a Script"_s); } - RELEASE_AND_RETURN(scope, JSValue::encode(jsBoolean(script->cachedDataProduced()))); + scope.assertNoExceptionExceptTermination(); + return JSValue::encode(jsBoolean(script->cachedDataProduced())); } JSC_DEFINE_CUSTOM_GETTER(scriptGetCachedDataRejected, (JSGlobalObject * globalObject, JSC::EncodedJSValue thisValueEncoded, PropertyName)) diff --git a/src/bun.js/bindings/NodeVMSourceTextModule.cpp b/src/bun.js/bindings/NodeVMSourceTextModule.cpp index 8af22d59a5..977f9c7abc 100644 --- a/src/bun.js/bindings/NodeVMSourceTextModule.cpp +++ b/src/bun.js/bindings/NodeVMSourceTextModule.cpp @@ -118,12 +118,9 @@ NodeVMSourceTextModule* NodeVMSourceTextModule::create(VM& vm, JSGlobalObject* g } ModuleProgramExecutable* executable = ModuleProgramExecutable::tryCreate(globalObject, ptr->sourceCode()); + RETURN_IF_EXCEPTION(scope, {}); if (!executable) { - // If an exception is already being thrown, don't throw another one. - // ModuleProgramExecutable::tryCreate() sometimes throws on failure, but sometimes it doesn't. - if (!scope.exception()) { - throwSyntaxError(globalObject, scope, "Failed to create cached executable"_s); - } + throwSyntaxError(globalObject, scope, "Failed to create cached executable"_s); return nullptr; } @@ -208,9 +205,7 @@ JSValue NodeVMSourceTextModule::createModuleRecord(JSGlobalObject* globalObject) const auto& requests = moduleRecord->requestedModules(); if (requests.isEmpty()) { - JSArray* requestsArray = constructEmptyArray(globalObject, nullptr, 0); - RETURN_IF_EXCEPTION(scope, {}); - return requestsArray; + RELEASE_AND_RETURN(scope, constructEmptyArray(globalObject, nullptr, 0)); } JSArray* requestsArray = constructEmptyArray(globalObject, nullptr, requests.size()); @@ -361,7 +356,6 @@ JSValue NodeVMSourceTextModule::link(JSGlobalObject* globalObject, JSArray* spec NodeVMGlobalObject* nodeVmGlobalObject = getGlobalObjectFromContext(globalObject, m_context.get(), false); RETURN_IF_EXCEPTION(scope, {}); - if (nodeVmGlobalObject) { globalObject = nodeVmGlobalObject; } @@ -392,9 +386,8 @@ RefPtr NodeVMSourceTextModule::bytecode(JSGlobalObject* globalOb ModuleProgramExecutable* executable = ModuleProgramExecutable::tryCreate(globalObject, m_sourceCode); RETURN_IF_EXCEPTION(scope, nullptr); if (!executable) { - if (!scope.exception()) { - throwSyntaxError(globalObject, scope, "Failed to create cached executable"_s); - } + EXCEPTION_ASSERT(!scope.exception()); + throwSyntaxError(globalObject, scope, "Failed to create cached executable"_s); return nullptr; } m_cachedExecutable.set(vm, this, executable); @@ -408,7 +401,7 @@ RefPtr NodeVMSourceTextModule::bytecode(JSGlobalObject* globalOb JSUint8Array* NodeVMSourceTextModule::cachedData(JSGlobalObject* globalObject) { - VM& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(vm); if (!m_cachedBytecodeBuffer) { @@ -429,13 +422,13 @@ void NodeVMSourceTextModule::initializeImportMeta(JSGlobalObject* globalObject) return; } + auto& vm = JSC::getVM(globalObject); + auto scope = DECLARE_THROW_SCOPE(vm); JSModuleEnvironment* moduleEnvironment = m_moduleRecord->moduleEnvironmentMayBeNull(); ASSERT(moduleEnvironment != nullptr); - VM& vm = globalObject->vm(); - auto scope = DECLARE_THROW_SCOPE(vm); - JSValue metaValue = moduleEnvironment->get(globalObject, globalObject->vm().propertyNames->builtinNames().metaPrivateName()); + scope.assertNoExceptionExceptTermination(); RETURN_IF_EXCEPTION(scope, ); ASSERT(metaValue); ASSERT(metaValue.isObject()); @@ -447,7 +440,7 @@ void NodeVMSourceTextModule::initializeImportMeta(JSGlobalObject* globalObject) args.append(m_moduleWrapper.get()); JSC::call(globalObject, m_initializeImportMeta.get(), callData, jsUndefined(), args); - RETURN_IF_EXCEPTION(scope, ); + scope.release(); } JSObject* NodeVMSourceTextModule::createPrototype(VM& vm, JSGlobalObject* globalObject) diff --git a/src/bun.js/bindings/NodeValidator.cpp b/src/bun.js/bindings/NodeValidator.cpp index 18e84e503e..01a0fba293 100644 --- a/src/bun.js/bindings/NodeValidator.cpp +++ b/src/bun.js/bindings/NodeValidator.cpp @@ -641,7 +641,9 @@ JSC_DEFINE_HOST_FUNCTION(jsFunction_validateOneOf, (JSC::JSGlobalObject * global for (size_t i = 0; i < length; i++) { JSValue element = array->getIndex(globalObject, i); RETURN_IF_EXCEPTION(scope, {}); - if (JSC::sameValue(globalObject, value, element)) { + auto same = JSC::sameValue(globalObject, value, element); + RETURN_IF_EXCEPTION(scope, {}); + if (same) { return JSValue::encode(jsUndefined()); } } diff --git a/src/bun.js/bindings/ServerRouteList.cpp b/src/bun.js/bindings/ServerRouteList.cpp index 6e3bbd9965..1061e21bc7 100644 --- a/src/bun.js/bindings/ServerRouteList.cpp +++ b/src/bun.js/bindings/ServerRouteList.cpp @@ -249,7 +249,7 @@ JSValue ServerRouteList::callRoute(Zig::GlobalObject* globalObject, uint32_t ind structure, requestPtr, params); - ASSERT(!scope.exception()); + EXCEPTION_ASSERT(!scope.exception()); *requestObject = JSValue::encode(request); JSValue callback = m_routes.at(index).get(); diff --git a/src/bun.js/bindings/VM.zig b/src/bun.js/bindings/VM.zig index 1cde8a7e13..8f721fb8ee 100644 --- a/src/bun.js/bindings/VM.zig +++ b/src/bun.js/bindings/VM.zig @@ -162,8 +162,14 @@ pub const VM = opaque { } extern fn JSC__VM__throwError(*VM, *JSGlobalObject, JSValue) void; - pub fn throwError(vm: *VM, global_object: *JSGlobalObject, value: JSValue) void { + pub fn throwError(vm: *VM, global_object: *JSGlobalObject, value: JSValue) error{JSError} { + var scope: bun.jsc.ExceptionValidationScope = undefined; + scope.init(global_object, @src()); + defer scope.deinit(); + scope.assertNoException(); JSC__VM__throwError(vm, global_object, value); + scope.assertExceptionPresenceMatches(true); + return error.JSError; } extern fn JSC__VM__releaseWeakRefs(vm: *VM) void; diff --git a/src/bun.js/bindings/ZigGlobalObject.cpp b/src/bun.js/bindings/ZigGlobalObject.cpp index e518145214..ffc360eaad 100644 --- a/src/bun.js/bindings/ZigGlobalObject.cpp +++ b/src/bun.js/bindings/ZigGlobalObject.cpp @@ -429,9 +429,7 @@ static JSValue formatStackTraceToJSValueWithoutPrepareStackTrace(JSC::VM& vm, Zi auto* errorConstructor = lexicalGlobalObject->m_errorStructure.constructor(globalObject); prepareStackTrace = errorConstructor->getIfPropertyExists(lexicalGlobalObject, JSC::Identifier::fromString(vm, "prepareStackTrace"_s)); - if (scope.exception()) [[unlikely]] { - scope.clearException(); - } + CLEAR_IF_EXCEPTION(scope); } return formatStackTraceToJSValue(vm, globalObject, lexicalGlobalObject, errorObject, callSites, prepareStackTrace); @@ -1790,6 +1788,53 @@ extern "C" JSC::EncodedJSValue Bun__createUint8ArrayForCopy(JSC::JSGlobalObject* RELEASE_AND_RETURN(scope, JSValue::encode(array)); } +extern "C" JSC::EncodedJSValue Bun__makeArrayBufferWithBytesNoCopy(JSC::JSGlobalObject* globalObject, const void* ptr, size_t len, JSTypedArrayBytesDeallocator deallocator, void* deallocatorContext) +{ + auto& vm = JSC::getVM(globalObject); + auto scope = DECLARE_THROW_SCOPE(vm); + + auto buffer = ArrayBuffer::createFromBytes({ static_cast(ptr), len }, createSharedTask([=](void* p) { + if (deallocator) deallocator(p, deallocatorContext); + })); + + JSArrayBuffer* jsBuffer = JSArrayBuffer::create(vm, globalObject->arrayBufferStructure(ArrayBufferSharingMode::Default), WTFMove(buffer)); + RETURN_IF_EXCEPTION(scope, {}); + return JSValue::encode(jsBuffer); +} + +extern "C" JSC::EncodedJSValue Bun__makeTypedArrayWithBytesNoCopy(JSC::JSGlobalObject* globalObject, TypedArrayType ty, const void* ptr, size_t len, JSTypedArrayBytesDeallocator deallocator, void* deallocatorContext) +{ + auto& vm = JSC::getVM(globalObject); + auto scope = DECLARE_THROW_SCOPE(vm); + + auto buffer_ = ArrayBuffer::createFromBytes({ static_cast(ptr), len }, createSharedTask([=](void* p) { + if (deallocator) deallocator(p, deallocatorContext); + })); + RefPtr&& buffer = WTFMove(buffer_); + if (!buffer) { + throwOutOfMemoryError(globalObject, scope); + return {}; + } + + unsigned elementByteSize = elementSize(ty); + size_t offset = 0; + size_t length = len / elementByteSize; + bool isResizableOrGrowableShared = buffer->isResizableOrGrowableShared(); + + switch (ty) { +#define JSC_TYPED_ARRAY_FACTORY(type) \ + case Type##type: \ + RELEASE_AND_RETURN(scope, JSValue::encode(JS##type##Array::create(globalObject, globalObject->typedArrayStructure(Type##type, isResizableOrGrowableShared), WTFMove(buffer), offset, length))); +#undef JSC_TYPED_ARRAY_CHECK + FOR_EACH_TYPED_ARRAY_TYPE_EXCLUDING_DATA_VIEW(JSC_TYPED_ARRAY_FACTORY) + case NotTypedArray: + case TypeDataView: + ASSERT_NOT_REACHED(); + } + + return {}; +} + JSC_DECLARE_HOST_FUNCTION(functionCreateUninitializedArrayBuffer); JSC_DEFINE_HOST_FUNCTION(functionCreateUninitializedArrayBuffer, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callFrame)) @@ -2023,8 +2068,7 @@ static inline std::optional invokeReadableStreamFunction(JSC::JSGl } #endif EXCEPTION_ASSERT(!scope.exception() || vm.hasPendingTerminationException()); - if (scope.exception()) [[unlikely]] - return {}; + RETURN_IF_EXCEPTION(scope, {}); return result; } extern "C" bool ReadableStream__tee(JSC::EncodedJSValue possibleReadableStream, Zig::GlobalObject* globalObject, JSC::EncodedJSValue* possibleReadableStream1, JSC::EncodedJSValue* possibleReadableStream2) @@ -3972,6 +4016,7 @@ extern "C" void Bun__handleRejectedPromise(Zig::GlobalObject* JSGlobalObject, JS void GlobalObject::handleRejectedPromises() { JSC::VM& virtual_machine = vm(); + auto scope = DECLARE_CATCH_SCOPE(virtual_machine); do { auto unhandledRejections = WTFMove(m_aboutToBeNotifiedRejectedPromises); for (auto& promise : unhandledRejections) { @@ -3979,6 +4024,7 @@ void GlobalObject::handleRejectedPromises() continue; Bun__handleRejectedPromise(this, promise.get()); + if (auto ex = scope.exception()) this->reportUncaughtExceptionAtEventLoop(this, ex); } } while (!m_aboutToBeNotifiedRejectedPromises.isEmpty()); } diff --git a/src/bun.js/bindings/bindings.cpp b/src/bun.js/bindings/bindings.cpp index a731fd7857..9e5fa2b705 100644 --- a/src/bun.js/bindings/bindings.cpp +++ b/src/bun.js/bindings/bindings.cpp @@ -203,7 +203,7 @@ template bool Bun__deepMatch( JSValue subsetValue, std::set* seenSubsetProperties, JSGlobalObject* globalObject, - ThrowScope* throwScope, + ThrowScope& throwScope, MarkedArgumentBuffer* gcBuffer, bool replacePropsWithAsymmetricMatchers, bool isMatchingObjectContaining); @@ -214,7 +214,7 @@ template bool Bun__deepMatch( JSValue subsetValue, std::set* seenSubsetProperties, JSGlobalObject* globalObject, - ThrowScope* throwScope, + ThrowScope& throwScope, MarkedArgumentBuffer* gcBuffer, bool replacePropsWithAsymmetricMatchers, bool isMatchingObjectContaining); @@ -288,7 +288,7 @@ bool readFlagsAndProcessPromise(JSValue& instanceValue, ExpectFlags& flags, JSGl return false; } -AsymmetricMatcherResult matchAsymmetricMatcherAndGetFlags(JSGlobalObject* globalObject, JSValue matcherProp, JSValue otherProp, ThrowScope* throwScope, ExpectFlags& flags) +AsymmetricMatcherResult matchAsymmetricMatcherAndGetFlags(JSGlobalObject* globalObject, JSValue matcherProp, JSValue otherProp, ThrowScope& throwScope, ExpectFlags& flags) { JSCell* matcherPropCell = matcherProp.asCell(); AsymmetricMatcherConstructorType constructorType = AsymmetricMatcherConstructorType::none; @@ -396,7 +396,7 @@ AsymmetricMatcherResult matchAsymmetricMatcherAndGetFlags(JSGlobalObject* global } bool hasInstance = constructorObject->hasInstance(globalObject, otherProp); - RETURN_IF_EXCEPTION(*throwScope, AsymmetricMatcherResult::FAIL); + RETURN_IF_EXCEPTION(throwScope, AsymmetricMatcherResult::FAIL); if (hasInstance) { return AsymmetricMatcherResult::PASS; } @@ -410,10 +410,10 @@ AsymmetricMatcherResult matchAsymmetricMatcherAndGetFlags(JSGlobalObject* global if (otherProp.isString()) { String otherString = otherProp.toWTFString(globalObject); - RETURN_IF_EXCEPTION(*throwScope, AsymmetricMatcherResult::FAIL); + RETURN_IF_EXCEPTION(throwScope, AsymmetricMatcherResult::FAIL); String substring = expectedSubstring.toWTFString(globalObject); - RETURN_IF_EXCEPTION(*throwScope, AsymmetricMatcherResult::FAIL); + RETURN_IF_EXCEPTION(throwScope, AsymmetricMatcherResult::FAIL); if (otherString.find(substring) != WTF::notFound) { return AsymmetricMatcherResult::PASS; @@ -430,10 +430,10 @@ AsymmetricMatcherResult matchAsymmetricMatcherAndGetFlags(JSGlobalObject* global if (otherProp.isString()) { if (expectedTestValue.isString()) { String otherString = otherProp.toWTFString(globalObject); - RETURN_IF_EXCEPTION(*throwScope, AsymmetricMatcherResult::FAIL); + RETURN_IF_EXCEPTION(throwScope, AsymmetricMatcherResult::FAIL); String substring = expectedTestValue.toWTFString(globalObject); - RETURN_IF_EXCEPTION(*throwScope, AsymmetricMatcherResult::FAIL); + RETURN_IF_EXCEPTION(throwScope, AsymmetricMatcherResult::FAIL); if (otherString.find(substring) != WTF::notFound) { return AsymmetricMatcherResult::PASS; @@ -478,7 +478,7 @@ AsymmetricMatcherResult matchAsymmetricMatcherAndGetFlags(JSGlobalObject* global Vector, 16> stack; MarkedArgumentBuffer gcBuffer; bool foundNow = Bun__deepEquals(globalObject, expectedValue, otherValue, gcBuffer, stack, throwScope, true); - RETURN_IF_EXCEPTION(*throwScope, AsymmetricMatcherResult::FAIL); + RETURN_IF_EXCEPTION(throwScope, AsymmetricMatcherResult::FAIL); if (foundNow) { found = true; break; @@ -506,7 +506,7 @@ AsymmetricMatcherResult matchAsymmetricMatcherAndGetFlags(JSGlobalObject* global // `enableAsymmetricMatchers` and `isMatchingObjectContaining` // are both true bool match = Bun__deepMatch(otherProp, nullptr, patternObject, nullptr, globalObject, throwScope, nullptr, false, true); - RETURN_IF_EXCEPTION(*throwScope, AsymmetricMatcherResult::FAIL); + RETURN_IF_EXCEPTION(throwScope, AsymmetricMatcherResult::FAIL); if (match) { return AsymmetricMatcherResult::PASS; } @@ -557,7 +557,7 @@ AsymmetricMatcherResult matchAsymmetricMatcherAndGetFlags(JSGlobalObject* global return AsymmetricMatcherResult::NOT_MATCHER; } -AsymmetricMatcherResult matchAsymmetricMatcher(JSGlobalObject* globalObject, JSValue matcherProp, JSValue otherProp, ThrowScope* throwScope) +AsymmetricMatcherResult matchAsymmetricMatcher(JSGlobalObject* globalObject, JSValue matcherProp, JSValue otherProp, ThrowScope& throwScope) { ExpectFlags flags = ExpectFlags(); AsymmetricMatcherResult result = matchAsymmetricMatcherAndGetFlags(globalObject, matcherProp, otherProp, throwScope, flags); @@ -632,14 +632,14 @@ JSValue getIndexWithoutAccessors(JSGlobalObject* globalObject, JSObject* obj, ui } template -std::optional specialObjectsDequal(JSC::JSGlobalObject* globalObject, MarkedArgumentBuffer& gcBuffer, Vector, 16>& stack, ThrowScope* scope, JSCell* _Nonnull c1, JSCell* _Nonnull c2); +std::optional specialObjectsDequal(JSC::JSGlobalObject* globalObject, MarkedArgumentBuffer& gcBuffer, Vector, 16>& stack, ThrowScope& scope, JSCell* _Nonnull c1, JSCell* _Nonnull c2); template -bool Bun__deepEquals(JSC::JSGlobalObject* globalObject, JSValue v1, JSValue v2, MarkedArgumentBuffer& gcBuffer, Vector, 16>& stack, ThrowScope* scope, bool addToStack) +bool Bun__deepEquals(JSC::JSGlobalObject* globalObject, JSValue v1, JSValue v2, MarkedArgumentBuffer& gcBuffer, Vector, 16>& stack, ThrowScope& scope, bool addToStack) { VM& vm = globalObject->vm(); if (!vm.isSafeToRecurse()) [[unlikely]] { - throwStackOverflowError(globalObject, *scope); + throwStackOverflowError(globalObject, scope); return false; } @@ -669,8 +669,12 @@ bool Bun__deepEquals(JSC::JSGlobalObject* globalObject, JSValue v1, JSValue v2, } } - if (!v1.isEmpty() && !v2.isEmpty() && JSC::sameValue(globalObject, v1, v2)) { - return true; + if (!v1.isEmpty() && !v2.isEmpty()) { + auto same = JSC::sameValue(globalObject, v1, v2); + RETURN_IF_EXCEPTION(scope, false); + if (same) { + return true; + } } if (v1.isEmpty() || v2.isEmpty()) @@ -710,7 +714,7 @@ bool Bun__deepEquals(JSC::JSGlobalObject* globalObject, JSValue v1, JSValue v2, ASSERT(c1); ASSERT(c2); std::optional isSpecialEqual = specialObjectsDequal(globalObject, gcBuffer, stack, scope, c1, c2); - RETURN_IF_EXCEPTION(*scope, false); + RETURN_IF_EXCEPTION(scope, false); if (isSpecialEqual.has_value()) return std::move(*isSpecialEqual); isSpecialEqual = specialObjectsDequal(globalObject, gcBuffer, stack, scope, c2, c1); if (isSpecialEqual.has_value()) return std::move(*isSpecialEqual); @@ -718,9 +722,9 @@ bool Bun__deepEquals(JSC::JSGlobalObject* globalObject, JSValue v1, JSValue v2, JSObject* o2 = v2.getObject(); bool v1Array = isArray(globalObject, v1); - RETURN_IF_EXCEPTION(*scope, false); + RETURN_IF_EXCEPTION(scope, false); bool v2Array = isArray(globalObject, v2); - RETURN_IF_EXCEPTION(*scope, false); + RETURN_IF_EXCEPTION(scope, false); if (v1Array != v2Array) return false; @@ -740,9 +744,9 @@ bool Bun__deepEquals(JSC::JSGlobalObject* globalObject, JSValue v1, JSValue v2, uint64_t i = 0; for (; i < array1Length; i++) { JSValue left = getIndexWithoutAccessors(globalObject, o1, i); - RETURN_IF_EXCEPTION(*scope, false); + RETURN_IF_EXCEPTION(scope, false); JSValue right = getIndexWithoutAccessors(globalObject, o2, i); - RETURN_IF_EXCEPTION(*scope, false); + RETURN_IF_EXCEPTION(scope, false); if constexpr (isStrict) { if (left.isEmpty() && right.isEmpty()) { @@ -759,16 +763,14 @@ bool Bun__deepEquals(JSC::JSGlobalObject* globalObject, JSValue v1, JSValue v2, } } - if (!Bun__deepEquals(globalObject, left, right, gcBuffer, stack, scope, true)) { - return false; - } - - RETURN_IF_EXCEPTION(*scope, false); + auto eql = Bun__deepEquals(globalObject, left, right, gcBuffer, stack, scope, true); + RETURN_IF_EXCEPTION(scope, false); + if (!eql) return false; } for (; i < array2Length; i++) { JSValue right = getIndexWithoutAccessors(globalObject, o2, i); - RETURN_IF_EXCEPTION(*scope, false); + RETURN_IF_EXCEPTION(scope, false); if (((right.isEmpty() || right.isUndefined()))) { continue; @@ -780,9 +782,9 @@ bool Bun__deepEquals(JSC::JSGlobalObject* globalObject, JSValue v1, JSValue v2, JSC::PropertyNameArray a1(vm, PropertyNameMode::Symbols, PrivateSymbolMode::Exclude); JSC::PropertyNameArray a2(vm, PropertyNameMode::Symbols, PrivateSymbolMode::Exclude); JSObject::getOwnPropertyNames(o1, globalObject, a1, DontEnumPropertiesMode::Exclude); - RETURN_IF_EXCEPTION(*scope, false); + RETURN_IF_EXCEPTION(scope, false); JSObject::getOwnPropertyNames(o2, globalObject, a2, DontEnumPropertiesMode::Exclude); - RETURN_IF_EXCEPTION(*scope, false); + RETURN_IF_EXCEPTION(scope, false); size_t propertyLength = a1.size(); if constexpr (isStrict) { @@ -797,14 +799,14 @@ bool Bun__deepEquals(JSC::JSGlobalObject* globalObject, JSValue v1, JSValue v2, PropertyName propertyName1 = PropertyName(i1); JSValue prop1 = o1->get(globalObject, propertyName1); - RETURN_IF_EXCEPTION(*scope, false); + RETURN_IF_EXCEPTION(scope, false); if (!prop1) [[unlikely]] { return false; } JSValue prop2 = o2->getIfPropertyExists(globalObject, propertyName1); - RETURN_IF_EXCEPTION(*scope, false); + RETURN_IF_EXCEPTION(scope, false); if constexpr (!isStrict) { if (prop1.isUndefined() && prop2.isEmpty()) { @@ -816,14 +818,12 @@ bool Bun__deepEquals(JSC::JSGlobalObject* globalObject, JSValue v1, JSValue v2, return false; } - if (!Bun__deepEquals(globalObject, prop1, prop2, gcBuffer, stack, scope, true)) { - return false; - } - - RETURN_IF_EXCEPTION(*scope, false); + auto eql = Bun__deepEquals(globalObject, prop1, prop2, gcBuffer, stack, scope, true); + RETURN_IF_EXCEPTION(scope, false); + if (!eql) return false; } - RETURN_IF_EXCEPTION(*scope, false); + RETURN_IF_EXCEPTION(scope, false); return true; } @@ -861,11 +861,14 @@ bool Bun__deepEquals(JSC::JSGlobalObject* globalObject, JSValue v1, JSValue v2, return false; } - if (left == right || JSC::sameValue(globalObject, left, right)) { - return true; - } + if (left == right) return true; + auto same = JSC::sameValue(globalObject, left, right); + RETURN_IF_EXCEPTION(scope, false); + if (same) return true; - if (!Bun__deepEquals(globalObject, left, right, gcBuffer, stack, scope, true)) { + auto eql = Bun__deepEquals(globalObject, left, right, gcBuffer, stack, scope, true); + RETURN_IF_EXCEPTION(scope, false); + if (!eql) { result = false; return false; } @@ -894,11 +897,14 @@ bool Bun__deepEquals(JSC::JSGlobalObject* globalObject, JSValue v1, JSValue v2, return false; } - if (left == right || JSC::sameValue(globalObject, left, right)) { - return true; - } + if (left == right) return true; + auto same = JSC::sameValue(globalObject, left, right); + RETURN_IF_EXCEPTION(scope, false); + if (same) return true; - if (!Bun__deepEquals(globalObject, left, right, gcBuffer, stack, scope, true)) { + auto eql = Bun__deepEquals(globalObject, left, right, gcBuffer, stack, scope, true); + RETURN_IF_EXCEPTION(scope, false); + if (!eql) { result = false; return false; } @@ -946,9 +952,9 @@ bool Bun__deepEquals(JSC::JSGlobalObject* globalObject, JSValue v1, JSValue v2, JSC::PropertyNameArray a1(vm, PropertyNameMode::StringsAndSymbols, PrivateSymbolMode::Exclude); JSC::PropertyNameArray a2(vm, PropertyNameMode::StringsAndSymbols, PrivateSymbolMode::Exclude); o1->getPropertyNames(globalObject, a1, DontEnumPropertiesMode::Exclude); - RETURN_IF_EXCEPTION(*scope, false); + RETURN_IF_EXCEPTION(scope, false); o2->getPropertyNames(globalObject, a2, DontEnumPropertiesMode::Exclude); - RETURN_IF_EXCEPTION(*scope, false); + RETURN_IF_EXCEPTION(scope, false); const size_t propertyArrayLength1 = a1.size(); const size_t propertyArrayLength2 = a2.size(); @@ -965,14 +971,14 @@ bool Bun__deepEquals(JSC::JSGlobalObject* globalObject, JSValue v1, JSValue v2, PropertyName propertyName1 = PropertyName(i1); JSValue prop1 = o1->get(globalObject, propertyName1); - RETURN_IF_EXCEPTION(*scope, false); + RETURN_IF_EXCEPTION(scope, false); if (!prop1) [[unlikely]] { return false; } JSValue prop2 = o2->getIfPropertyExists(globalObject, propertyName1); - RETURN_IF_EXCEPTION(*scope, false); + RETURN_IF_EXCEPTION(scope, false); if constexpr (!isStrict) { if (prop1.isUndefined() && prop2.isEmpty()) { @@ -984,11 +990,9 @@ bool Bun__deepEquals(JSC::JSGlobalObject* globalObject, JSValue v1, JSValue v2, return false; } - if (!Bun__deepEquals(globalObject, prop1, prop2, gcBuffer, stack, scope, true)) { - return false; - } - - RETURN_IF_EXCEPTION(*scope, false); + auto eql = Bun__deepEquals(globalObject, prop1, prop2, gcBuffer, stack, scope, true); + RETURN_IF_EXCEPTION(scope, false); + if (!eql) return false; } // for the remaining properties in the other object, make sure they are undefined @@ -997,7 +1001,7 @@ bool Bun__deepEquals(JSC::JSGlobalObject* globalObject, JSValue v1, JSValue v2, PropertyName propertyName2 = PropertyName(i2); JSValue prop2 = o2->getIfPropertyExists(globalObject, propertyName2); - RETURN_IF_EXCEPTION(*scope, false); + RETURN_IF_EXCEPTION(scope, false); if (!prop2.isUndefined()) { return false; @@ -1008,7 +1012,7 @@ bool Bun__deepEquals(JSC::JSGlobalObject* globalObject, JSValue v1, JSValue v2, } template -std::optional specialObjectsDequal(JSC::JSGlobalObject* globalObject, MarkedArgumentBuffer& gcBuffer, Vector, 16>& stack, ThrowScope* scope, JSCell* _Nonnull c1, JSCell* _Nonnull c2) +std::optional specialObjectsDequal(JSC::JSGlobalObject* globalObject, MarkedArgumentBuffer& gcBuffer, Vector, 16>& stack, ThrowScope& scope, JSCell* _Nonnull c1, JSCell* _Nonnull c2) { uint8_t c1Type = c1->type(); uint8_t c2Type = c2->type(); @@ -1027,11 +1031,11 @@ std::optional specialObjectsDequal(JSC::JSGlobalObject* globalObject, Mark } auto iter1 = JSSetIterator::create(globalObject, globalObject->setIteratorStructure(), set1, IterationKind::Keys); - RETURN_IF_EXCEPTION(*scope, {}); + RETURN_IF_EXCEPTION(scope, {}); JSValue key1; while (iter1->next(globalObject, key1)) { bool has = set2->has(globalObject, key1); - RETURN_IF_EXCEPTION(*scope, {}); + RETURN_IF_EXCEPTION(scope, {}); if (has) { continue; } @@ -1039,12 +1043,12 @@ std::optional specialObjectsDequal(JSC::JSGlobalObject* globalObject, Mark // We couldn't find the key in the second set. This may be a false positive due to how // JSValues are represented in JSC, so we need to fall back to a linear search to be sure. auto iter2 = JSSetIterator::create(globalObject, globalObject->setIteratorStructure(), set2, IterationKind::Keys); - RETURN_IF_EXCEPTION(*scope, {}); + RETURN_IF_EXCEPTION(scope, {}); JSValue key2; bool foundMatchingKey = false; while (iter2->next(globalObject, key2)) { bool equal = Bun__deepEquals(globalObject, key1, key2, gcBuffer, stack, scope, false); - RETURN_IF_EXCEPTION(*scope, {}); + RETURN_IF_EXCEPTION(scope, {}); if (equal) { foundMatchingKey = true; break; @@ -1072,22 +1076,22 @@ std::optional specialObjectsDequal(JSC::JSGlobalObject* globalObject, Mark } auto iter1 = JSMapIterator::create(globalObject, globalObject->mapIteratorStructure(), map1, IterationKind::Entries); - RETURN_IF_EXCEPTION(*scope, {}); + RETURN_IF_EXCEPTION(scope, {}); JSValue key1, value1; while (iter1->nextKeyValue(globalObject, key1, value1)) { JSValue value2 = map2->get(globalObject, key1); - RETURN_IF_EXCEPTION(*scope, {}); + RETURN_IF_EXCEPTION(scope, {}); if (value2.isUndefined()) { // We couldn't find the key in the second map. This may be a false positive due to // how JSValues are represented in JSC, so we need to fall back to a linear search // to be sure. auto iter2 = JSMapIterator::create(globalObject, globalObject->mapIteratorStructure(), map2, IterationKind::Entries); - RETURN_IF_EXCEPTION(*scope, {}); + RETURN_IF_EXCEPTION(scope, {}); JSValue key2; bool foundMatchingKey = false; while (iter2->nextKeyValue(globalObject, key2, value2)) { bool keysEqual = Bun__deepEquals(globalObject, key1, key2, gcBuffer, stack, scope, false); - RETURN_IF_EXCEPTION(*scope, {}); + RETURN_IF_EXCEPTION(scope, {}); if (keysEqual) { foundMatchingKey = true; break; @@ -1102,7 +1106,7 @@ std::optional specialObjectsDequal(JSC::JSGlobalObject* globalObject, Mark } bool valuesEqual = Bun__deepEquals(globalObject, value1, value2, gcBuffer, stack, scope, false); - RETURN_IF_EXCEPTION(*scope, {}); + RETURN_IF_EXCEPTION(scope, {}); if (!valuesEqual) { return false; } @@ -1191,18 +1195,18 @@ std::optional specialObjectsDequal(JSC::JSGlobalObject* globalObject, Mark } auto leftName = left->sanitizedNameString(globalObject); - RETURN_IF_EXCEPTION(*scope, {}); + RETURN_IF_EXCEPTION(scope, {}); auto rightName = right->sanitizedNameString(globalObject); - RETURN_IF_EXCEPTION(*scope, {}); + RETURN_IF_EXCEPTION(scope, {}); if (leftName != rightName) { // manual `.name` changes (usually in subclasses) return false; } auto leftMessage = left->sanitizedMessageString(globalObject); - RETURN_IF_EXCEPTION(*scope, {}); + RETURN_IF_EXCEPTION(scope, {}); auto rightMessage = right->sanitizedMessageString(globalObject); - RETURN_IF_EXCEPTION(*scope, {}); + RETURN_IF_EXCEPTION(scope, {}); if (leftMessage != rightMessage) { // `.message` return false; @@ -1222,32 +1226,34 @@ std::optional specialObjectsDequal(JSC::JSGlobalObject* globalObject, Mark const PropertyName cause(vm.propertyNames->cause); if constexpr (isStrict) { bool leftHasCause = left->hasProperty(globalObject, cause); - RETURN_IF_EXCEPTION(*scope, {}); + RETURN_IF_EXCEPTION(scope, {}); bool rightHasCause = right->hasProperty(globalObject, cause); - RETURN_IF_EXCEPTION(*scope, {}); + RETURN_IF_EXCEPTION(scope, {}); if (leftHasCause != rightHasCause) { return false; } } auto leftCause = left->get(globalObject, cause); - RETURN_IF_EXCEPTION(*scope, {}); + RETURN_IF_EXCEPTION(scope, {}); auto rightCause = right->get(globalObject, cause); - RETURN_IF_EXCEPTION(*scope, {}); + RETURN_IF_EXCEPTION(scope, {}); bool causesEqual = Bun__deepEquals(globalObject, leftCause, rightCause, gcBuffer, stack, scope, true); - RETURN_IF_EXCEPTION(*scope, {}); + RETURN_IF_EXCEPTION(scope, {}); if (!causesEqual) { return false; } // check arbitrary enumerable properties. `.stack` is not checked. left->materializeErrorInfoIfNeeded(vm); + RETURN_IF_EXCEPTION(scope, {}); right->materializeErrorInfoIfNeeded(vm); + RETURN_IF_EXCEPTION(scope, {}); JSC::PropertyNameArray a1(vm, PropertyNameMode::StringsAndSymbols, PrivateSymbolMode::Exclude); JSC::PropertyNameArray a2(vm, PropertyNameMode::StringsAndSymbols, PrivateSymbolMode::Exclude); left->getPropertyNames(globalObject, a1, DontEnumPropertiesMode::Exclude); - RETURN_IF_EXCEPTION(*scope, {}); + RETURN_IF_EXCEPTION(scope, {}); right->getPropertyNames(globalObject, a2, DontEnumPropertiesMode::Exclude); - RETURN_IF_EXCEPTION(*scope, {}); + RETURN_IF_EXCEPTION(scope, {}); const size_t propertyArrayLength1 = a1.size(); const size_t propertyArrayLength2 = a2.size(); @@ -1265,11 +1271,11 @@ std::optional specialObjectsDequal(JSC::JSGlobalObject* globalObject, Mark PropertyName propertyName1 = PropertyName(i1); JSValue prop1 = left->get(globalObject, propertyName1); - RETURN_IF_EXCEPTION(*scope, {}); + RETURN_IF_EXCEPTION(scope, {}); ASSERT(prop1); JSValue prop2 = right->getIfPropertyExists(globalObject, propertyName1); - RETURN_IF_EXCEPTION(*scope, {}); + RETURN_IF_EXCEPTION(scope, {}); if constexpr (!isStrict) { if (prop1.isUndefined() && prop2.isEmpty()) { @@ -1282,7 +1288,7 @@ std::optional specialObjectsDequal(JSC::JSGlobalObject* globalObject, Mark } bool propertiesEqual = Bun__deepEquals(globalObject, prop1, prop2, gcBuffer, stack, scope, true); - RETURN_IF_EXCEPTION(*scope, {}); + RETURN_IF_EXCEPTION(scope, {}); if (!propertiesEqual) { return false; } @@ -1295,7 +1301,7 @@ std::optional specialObjectsDequal(JSC::JSGlobalObject* globalObject, Mark PropertyName propertyName2 = PropertyName(i2); JSValue prop2 = right->getIfPropertyExists(globalObject, propertyName2); - RETURN_IF_EXCEPTION(*scope, {}); + RETURN_IF_EXCEPTION(scope, {}); if (!prop2.isUndefined()) { return false; @@ -1402,12 +1408,12 @@ std::optional specialObjectsDequal(JSC::JSGlobalObject* globalObject, Mark } JSString* s1 = c1->toStringInline(globalObject); - RETURN_IF_EXCEPTION(*scope, {}); + RETURN_IF_EXCEPTION(scope, {}); JSString* s2 = c2->toStringInline(globalObject); - RETURN_IF_EXCEPTION(*scope, {}); + RETURN_IF_EXCEPTION(scope, {}); bool stringsEqual = s1->equal(globalObject, s2); - RETURN_IF_EXCEPTION(*scope, {}); + RETURN_IF_EXCEPTION(scope, {}); return stringsEqual; } case JSFunctionType: { @@ -1584,7 +1590,7 @@ bool Bun__deepMatch( JSValue subsetValue, std::set* seenSubsetProperties, JSGlobalObject* globalObject, - ThrowScope* throwScope, + ThrowScope& throwScope, MarkedArgumentBuffer* gcBuffer, bool replacePropsWithAsymmetricMatchers, bool isMatchingObjectContaining) @@ -1601,7 +1607,7 @@ bool Bun__deepMatch( PropertyNameArray subsetProps(vm, PropertyNameMode::StringsAndSymbols, PrivateSymbolMode::Include); subsetObj->getPropertyNames(globalObject, subsetProps, DontEnumPropertiesMode::Exclude); - RETURN_IF_EXCEPTION(*throwScope, false); + RETURN_IF_EXCEPTION(throwScope, false); // TODO: add fast paths for: // - two "simple" objects (using ->forEachProperty in both) @@ -1615,7 +1621,7 @@ bool Bun__deepMatch( } PropertyNameArray objProps(vm, PropertyNameMode::StringsAndSymbols, PrivateSymbolMode::Include); obj->getPropertyNames(globalObject, objProps, DontEnumPropertiesMode::Exclude); - RETURN_IF_EXCEPTION(*throwScope, false); + RETURN_IF_EXCEPTION(throwScope, false); if (objProps.size() != subsetProps.size()) { return false; } @@ -1623,13 +1629,13 @@ bool Bun__deepMatch( for (const auto& property : subsetProps) { JSValue prop = obj->getIfPropertyExists(globalObject, property); - RETURN_IF_EXCEPTION(*throwScope, false); + RETURN_IF_EXCEPTION(throwScope, false); if (prop.isEmpty()) { return false; } JSValue subsetProp = subsetObj->get(globalObject, property); - RETURN_IF_EXCEPTION(*throwScope, false); + RETURN_IF_EXCEPTION(throwScope, false); JSCell* subsetPropCell = !subsetProp.isEmpty() && subsetProp.isCell() ? subsetProp.asCell() : nullptr; JSCell* propCell = prop.isCell() ? prop.asCell() : nullptr; @@ -1642,7 +1648,7 @@ bool Bun__deepMatch( case AsymmetricMatcherResult::PASS: if (replacePropsWithAsymmetricMatchers) { obj->putDirectMayBeIndex(globalObject, property, subsetProp); - RETURN_IF_EXCEPTION(*throwScope, false); + RETURN_IF_EXCEPTION(throwScope, false); } // continue to next subset prop continue; @@ -1656,7 +1662,7 @@ bool Bun__deepMatch( case AsymmetricMatcherResult::PASS: if (replacePropsWithAsymmetricMatchers) { subsetObj->putDirectMayBeIndex(globalObject, property, prop); - RETURN_IF_EXCEPTION(*throwScope, false); + RETURN_IF_EXCEPTION(throwScope, false); } // continue to next subset prop continue; @@ -1673,9 +1679,9 @@ bool Bun__deepMatch( if (enableAsymmetricMatchers && isMatchingObjectContaining) { Vector, 16> stack; MarkedArgumentBuffer gcBuffer; - if (!Bun__deepEquals(globalObject, prop, subsetProp, gcBuffer, stack, throwScope, true)) { - return false; - } + auto eql = Bun__deepEquals(globalObject, prop, subsetProp, gcBuffer, stack, throwScope, true); + RETURN_IF_EXCEPTION(throwScope, false); + if (!eql) return false; } else { ASSERT(seenObjProperties != nullptr); ASSERT(seenSubsetProperties != nullptr); @@ -1709,7 +1715,7 @@ inline bool deepEqualsWrapperImpl(JSC::EncodedJSValue a, JSC::EncodedJSValue b, auto scope = DECLARE_THROW_SCOPE(vm); Vector, 16> stack; MarkedArgumentBuffer args; - bool result = Bun__deepEquals(global, JSC::JSValue::decode(a), JSC::JSValue::decode(b), args, stack, &scope, true); + bool result = Bun__deepEquals(global, JSC::JSValue::decode(a), JSC::JSValue::decode(b), args, stack, scope, true); RELEASE_AND_RETURN(scope, result); } } @@ -2203,8 +2209,6 @@ JSC::EncodedJSValue SystemError__toErrorInstanceWithInfoObject(const SystemError auto& vm = JSC::getVM(globalObject); - auto scope = DECLARE_THROW_SCOPE(vm); - auto codeString = err.code.toWTFString(); auto syscallString = err.syscall.toWTFString(); auto messageString = err.message.toWTFString(); @@ -2233,7 +2237,8 @@ JSC::EncodedJSValue SystemError__toErrorInstanceWithInfoObject(const SystemError info->putDirect(vm, clientData->builtinNames().errnoPublicName(), jsNumber(err.errno_), JSC::PropertyAttribute::DontDelete | 0); result->putDirect(vm, clientData->builtinNames().errnoPublicName(), jsNumber(err.errno_), JSC::PropertyAttribute::DontDelete | 0); - RELEASE_AND_RETURN(scope, JSC::JSValue::encode(result)); + ASSERT_NO_PENDING_EXCEPTION(globalObject); + return JSC::JSValue::encode(result); } JSC::EncodedJSValue @@ -2626,7 +2631,7 @@ bool JSC__JSValue__jestDeepMatch(JSC::EncodedJSValue JSValue0, JSC::EncodedJSVal std::set objVisited; std::set subsetVisited; MarkedArgumentBuffer gcBuffer; - RELEASE_AND_RETURN(scope, Bun__deepMatch(obj, &objVisited, subset, &subsetVisited, globalObject, &scope, &gcBuffer, replacePropsWithAsymmetricMatchers, false)); + RELEASE_AND_RETURN(scope, Bun__deepMatch(obj, &objVisited, subset, &subsetVisited, globalObject, scope, &gcBuffer, replacePropsWithAsymmetricMatchers, false)); } extern "C" bool Bun__JSValue__isAsyncContextFrame(JSC::EncodedJSValue value) @@ -5150,8 +5155,7 @@ extern "C" void JSC__JSValue__getName(JSC::EncodedJSValue JSValue0, JSC::JSGloba } } } - if (scope.exception()) [[unlikely]] - scope.clearException(); + CLEAR_IF_EXCEPTION(scope); *arg2 = Bun::toStringRef(displayName); } @@ -5680,8 +5684,7 @@ restart: } // Ignore exceptions due to getters. - if (scope.exception()) [[unlikely]] - scope.clearException(); + CLEAR_IF_EXCEPTION(scope); if (!propertyValue) return true; @@ -5696,16 +5699,12 @@ restart: iter(globalObject, arg2, &key, JSC::JSValue::encode(propertyValue), prop->isSymbol(), isPrivate); // Propagate exceptions from callbacks. - if (scope.exception()) [[unlikely]] { - return false; - } + RETURN_IF_EXCEPTION(scope, false); return true; }); // Propagate exceptions from callbacks. - if (scope.exception()) [[unlikely]] { - return; - } + RETURN_IF_EXCEPTION(scope, ); if (anyHits) { if (prototypeCount++ < 5) { @@ -5720,9 +5719,7 @@ restart: } } // Ignore exceptions from Proxy "getPrototype" trap. - if (scope.exception()) [[unlikely]] { - scope.clearException(); - } + CLEAR_IF_EXCEPTION(scope); } return; } @@ -5760,9 +5757,7 @@ restart: if (!object->getPropertySlot(globalObject, property, slot)) continue; // Ignore exceptions from "Get" proxy traps. - if (scope.exception()) [[unlikely]] { - scope.clearException(); - } + CLEAR_IF_EXCEPTION(scope); if ((slot.attributes() & PropertyAttribute::DontEnum) != 0) { if (property == propertyNames->underscoreProto diff --git a/src/bun.js/bindings/headers-handwritten.h b/src/bun.js/bindings/headers-handwritten.h index 7a2a364ef0..972c5f06df 100644 --- a/src/bun.js/bindings/headers-handwritten.h +++ b/src/bun.js/bindings/headers-handwritten.h @@ -404,7 +404,7 @@ extern "C" void Bun__EventLoop__runCallback3(JSC::JSGlobalObject* global, JSC::E /// @note throws a JS exception and returns false if a stack overflow occurs template -bool Bun__deepEquals(JSC::JSGlobalObject* globalObject, JSC::JSValue v1, JSC::JSValue v2, JSC::MarkedArgumentBuffer&, Vector, 16>& stack, JSC::ThrowScope* scope, bool addToStack); +bool Bun__deepEquals(JSC::JSGlobalObject* globalObject, JSC::JSValue v1, JSC::JSValue v2, JSC::MarkedArgumentBuffer&, Vector, 16>& stack, JSC::ThrowScope& scope, bool addToStack); /** * @brief `Bun.deepMatch(a, b)` @@ -445,7 +445,7 @@ bool Bun__deepMatch( JSC::JSValue subset, std::set* seenSubsetProperties, JSC::JSGlobalObject* globalObject, - JSC::ThrowScope* throwScope, + JSC::ThrowScope& throwScope, JSC::MarkedArgumentBuffer* gcBuffer, bool replacePropsWithAsymmetricMatchers, bool isMatchingObjectContaining); @@ -471,5 +471,7 @@ ALWAYS_INLINE void BunString::deref() } } +#define CLEAR_IF_EXCEPTION(scope__) scope__.clearException(); + #endif // __cplusplus #endif // HEADERS_HANDWRITTEN diff --git a/src/bun.js/bindings/node/crypto/CryptoDhJob.cpp b/src/bun.js/bindings/node/crypto/CryptoDhJob.cpp index 11ea6c6ce5..b5f40472d2 100644 --- a/src/bun.js/bindings/node/crypto/CryptoDhJob.cpp +++ b/src/bun.js/bindings/node/crypto/CryptoDhJob.cpp @@ -148,7 +148,7 @@ JSC_DEFINE_HOST_FUNCTION(jsDiffieHellman, (JSGlobalObject * lexicalGlobalObject, } std::optional ctx = DhJobCtx::fromJS(lexicalGlobalObject, scope, options); - ASSERT(ctx.has_value() == !scope.exception()); + EXCEPTION_ASSERT(ctx.has_value() == !scope.exception()); RETURN_IF_EXCEPTION(scope, {}); if (!callbackValue.isUndefined()) { diff --git a/src/bun.js/bindings/node/crypto/CryptoGenKeyPair.cpp b/src/bun.js/bindings/node/crypto/CryptoGenKeyPair.cpp index ef8c2415ff..004168bad7 100644 --- a/src/bun.js/bindings/node/crypto/CryptoGenKeyPair.cpp +++ b/src/bun.js/bindings/node/crypto/CryptoGenKeyPair.cpp @@ -148,21 +148,21 @@ JSC_DEFINE_HOST_FUNCTION(jsGenerateKeyPair, (JSC::JSGlobalObject * globalObject, if (typeView == "rsa"_s || typeView == "rsa-pss"_s) { std::optional ctx = RsaKeyPairJobCtx::fromJS(globalObject, scope, typeView, optionsValue, config); - ASSERT(ctx.has_value() == !scope.exception()); + EXCEPTION_ASSERT(ctx.has_value() == !scope.exception()); RETURN_IF_EXCEPTION(scope, {}); RsaKeyPairJob::createAndSchedule(globalObject, WTFMove(*ctx), callbackValue); return JSValue::encode(jsUndefined()); } if (typeView == "dsa"_s) { std::optional ctx = DsaKeyPairJobCtx::fromJS(globalObject, scope, typeView, optionsValue, config); - ASSERT(ctx.has_value() == !scope.exception()); + EXCEPTION_ASSERT(ctx.has_value() == !scope.exception()); RETURN_IF_EXCEPTION(scope, {}); DsaKeyPairJob::createAndSchedule(globalObject, WTFMove(*ctx), callbackValue); return JSValue::encode(jsUndefined()); } if (typeView == "ec"_s) { std::optional ctx = EcKeyPairJobCtx::fromJS(globalObject, scope, typeView, optionsValue, config); - ASSERT(ctx.has_value() == !scope.exception()); + EXCEPTION_ASSERT(ctx.has_value() == !scope.exception()); RETURN_IF_EXCEPTION(scope, {}); EcKeyPairJob::createAndSchedule(globalObject, WTFMove(*ctx), callbackValue); return JSValue::encode(jsUndefined()); @@ -170,14 +170,14 @@ JSC_DEFINE_HOST_FUNCTION(jsGenerateKeyPair, (JSC::JSGlobalObject * globalObject, // TODO: should just get `id` here if (typeView == "ed25519"_s || typeView == "ed448"_s || typeView == "x25519"_s || typeView == "x448"_s) { std::optional ctx = NidKeyPairJobCtx::fromJS(globalObject, scope, typeView, optionsValue, config); - ASSERT(ctx.has_value() == !scope.exception()); + EXCEPTION_ASSERT(ctx.has_value() == !scope.exception()); RETURN_IF_EXCEPTION(scope, {}); NidKeyPairJob::createAndSchedule(globalObject, WTFMove(*ctx), callbackValue); return JSValue::encode(jsUndefined()); } if (typeView == "dh"_s) { std::optional ctx = DhKeyPairJobCtx::fromJS(globalObject, scope, typeView, optionsValue, config); - ASSERT(ctx.has_value() == !scope.exception()); + EXCEPTION_ASSERT(ctx.has_value() == !scope.exception()); RETURN_IF_EXCEPTION(scope, {}); DhKeyPairJob::createAndSchedule(globalObject, WTFMove(*ctx), callbackValue); return JSValue::encode(jsUndefined()); @@ -216,7 +216,7 @@ JSC_DEFINE_HOST_FUNCTION(jsGenerateKeyPairSync, (JSGlobalObject * globalObject, if (typeView == "rsa"_s || typeView == "rsa-pss"_s) { std::optional ctx = RsaKeyPairJobCtx::fromJS(globalObject, scope, typeView, optionsValue, config); - ASSERT(ctx.has_value() == !scope.exception()); + EXCEPTION_ASSERT(ctx.has_value() == !scope.exception()); RETURN_IF_EXCEPTION(scope, {}); ncrypto::EVPKeyCtxPointer keyCtx = ctx->setup(); if (!keyCtx) { @@ -234,7 +234,7 @@ JSC_DEFINE_HOST_FUNCTION(jsGenerateKeyPairSync, (JSGlobalObject * globalObject, RETURN_IF_EXCEPTION(scope, {}); } else if (typeView == "dsa"_s) { auto ctx = DsaKeyPairJobCtx::fromJS(globalObject, scope, typeView, optionsValue, config); - ASSERT(ctx.has_value() == !scope.exception()); + EXCEPTION_ASSERT(ctx.has_value() == !scope.exception()); RETURN_IF_EXCEPTION(scope, {}); ncrypto::EVPKeyCtxPointer keyCtx = ctx->setup(); if (!keyCtx) { @@ -252,7 +252,7 @@ JSC_DEFINE_HOST_FUNCTION(jsGenerateKeyPairSync, (JSGlobalObject * globalObject, RETURN_IF_EXCEPTION(scope, {}); } else if (typeView == "ec"_s) { auto ctx = EcKeyPairJobCtx::fromJS(globalObject, scope, typeView, optionsValue, config); - ASSERT(ctx.has_value() == !scope.exception()); + EXCEPTION_ASSERT(ctx.has_value() == !scope.exception()); RETURN_IF_EXCEPTION(scope, {}); ncrypto::EVPKeyCtxPointer keyCtx = ctx->setup(); if (!keyCtx) { @@ -270,7 +270,7 @@ JSC_DEFINE_HOST_FUNCTION(jsGenerateKeyPairSync, (JSGlobalObject * globalObject, RETURN_IF_EXCEPTION(scope, {}); } else if (typeView == "ed25519"_s || typeView == "ed448"_s || typeView == "x25519"_s || typeView == "x448"_s) { auto ctx = NidKeyPairJobCtx::fromJS(globalObject, scope, typeView, optionsValue, config); - ASSERT(ctx.has_value() == !scope.exception()); + EXCEPTION_ASSERT(ctx.has_value() == !scope.exception()); RETURN_IF_EXCEPTION(scope, {}); ncrypto::EVPKeyCtxPointer keyCtx = ctx->setup(); if (!keyCtx) { @@ -288,7 +288,7 @@ JSC_DEFINE_HOST_FUNCTION(jsGenerateKeyPairSync, (JSGlobalObject * globalObject, RETURN_IF_EXCEPTION(scope, {}); } else if (typeView == "dh"_s) { auto ctx = DhKeyPairJobCtx::fromJS(globalObject, scope, typeView, optionsValue, config); - ASSERT(ctx.has_value() == !scope.exception()); + EXCEPTION_ASSERT(ctx.has_value() == !scope.exception()); RETURN_IF_EXCEPTION(scope, {}); ncrypto::EVPKeyCtxPointer keyCtx = ctx->setup(); if (!keyCtx) { diff --git a/src/bun.js/bindings/node/crypto/CryptoGenRsaKeyPair.cpp b/src/bun.js/bindings/node/crypto/CryptoGenRsaKeyPair.cpp index c09a531fda..49a683ad9b 100644 --- a/src/bun.js/bindings/node/crypto/CryptoGenRsaKeyPair.cpp +++ b/src/bun.js/bindings/node/crypto/CryptoGenRsaKeyPair.cpp @@ -171,6 +171,7 @@ std::optional RsaKeyPairJobCtx::fromJS(JSC::JSGlobalObject* gl } if (!hashValue.isUndefined()) { Bun::Process::emitWarning(globalObject, jsString(vm, makeString("\"options.hash\" is deprecated, use \"options.hashAlgorithm\" instead."_s)), jsString(vm, makeString("DeprecationWarning"_s)), jsString(vm, makeString("DEP0154"_s)), jsUndefined()); + CLEAR_IF_EXCEPTION(scope); V::validateString(scope, globalObject, hashValue, "options.hash"_s); RETURN_IF_EXCEPTION(scope, std::nullopt); hashString = hashValue.toString(globalObject); @@ -184,6 +185,7 @@ std::optional RsaKeyPairJobCtx::fromJS(JSC::JSGlobalObject* gl } if (!mgf1HashValue.isUndefined()) { Bun::Process::emitWarning(globalObject, jsString(vm, makeString("\"options.mgf1Hash\" is deprecated, use \"options.mgf1HashAlgorithm\" instead."_s)), jsString(vm, makeString("DeprecationWarning"_s)), jsString(vm, makeString("DEP0154"_s)), jsUndefined()); + CLEAR_IF_EXCEPTION(scope); V::validateString(scope, globalObject, mgf1HashValue, "options.mgf1Hash"_s); RETURN_IF_EXCEPTION(scope, std::nullopt); mgf1HashString = mgf1HashValue.toString(globalObject); diff --git a/src/bun.js/bindings/node/crypto/CryptoKeygen.cpp b/src/bun.js/bindings/node/crypto/CryptoKeygen.cpp index 87b6243e13..6c49a5c6c9 100644 --- a/src/bun.js/bindings/node/crypto/CryptoKeygen.cpp +++ b/src/bun.js/bindings/node/crypto/CryptoKeygen.cpp @@ -147,7 +147,7 @@ JSC_DEFINE_HOST_FUNCTION(jsGenerateKey, (JSC::JSGlobalObject * lexicalGlobalObje RETURN_IF_EXCEPTION(scope, {}); std::optional ctx = SecretKeyJobCtx::fromJS(lexicalGlobalObject, scope, typeValue, optionsValue); - ASSERT(ctx.has_value() == !scope.exception()); + EXCEPTION_ASSERT(ctx.has_value() == !scope.exception()); RETURN_IF_EXCEPTION(scope, {}); SecretKeyJob::createAndSchedule(lexicalGlobalObject, WTFMove(ctx.value()), callbackValue); @@ -164,7 +164,7 @@ JSC_DEFINE_HOST_FUNCTION(jsGenerateKeySync, (JSC::JSGlobalObject * lexicalGlobal JSValue optionsValue = callFrame->argument(1); std::optional ctx = SecretKeyJobCtx::fromJS(lexicalGlobalObject, scope, typeValue, optionsValue); - ASSERT(ctx.has_value() == !scope.exception()); + EXCEPTION_ASSERT(ctx.has_value() == !scope.exception()); RETURN_IF_EXCEPTION(scope, {}); ctx->runTask(lexicalGlobalObject); diff --git a/src/bun.js/bindings/node/crypto/CryptoPrimes.cpp b/src/bun.js/bindings/node/crypto/CryptoPrimes.cpp index 10159a63ec..39f6ac8a67 100644 --- a/src/bun.js/bindings/node/crypto/CryptoPrimes.cpp +++ b/src/bun.js/bindings/node/crypto/CryptoPrimes.cpp @@ -206,7 +206,7 @@ void GeneratePrimeJobCtx::runFromJS(JSGlobalObject* globalObject, JSValue callba auto scope = DECLARE_THROW_SCOPE(vm); JSValue result = GeneratePrimeJob::result(globalObject, scope, m_prime, m_bigint); - ASSERT(result.isEmpty() == !!scope.exception()); + EXCEPTION_ASSERT(result.isEmpty() == !!scope.exception()); if (scope.exception()) [[unlikely]] { auto* err = scope.exception(); scope.clearException(); diff --git a/src/bun.js/bindings/node/crypto/CryptoSignJob.cpp b/src/bun.js/bindings/node/crypto/CryptoSignJob.cpp index ee7e6bdd00..8aee6cf381 100644 --- a/src/bun.js/bindings/node/crypto/CryptoSignJob.cpp +++ b/src/bun.js/bindings/node/crypto/CryptoSignJob.cpp @@ -199,8 +199,8 @@ extern "C" void Bun__SignJobCtx__runFromJS(SignJobCtx* ctx, JSGlobalObject* glob } void SignJobCtx::runFromJS(JSGlobalObject* lexicalGlobalObject, JSValue callback) { - VM& vm = lexicalGlobalObject->vm(); - ThrowScope scope = DECLARE_THROW_SCOPE(vm); + auto& vm = lexicalGlobalObject->vm(); + auto scope = DECLARE_THROW_SCOPE(vm); switch (m_mode) { case Mode::Sign: { diff --git a/src/bun.js/bindings/node/crypto/DiffieHellmanFunctions.h b/src/bun.js/bindings/node/crypto/DiffieHellmanFunctions.h index 4e7f78850b..feb50dae6d 100644 --- a/src/bun.js/bindings/node/crypto/DiffieHellmanFunctions.h +++ b/src/bun.js/bindings/node/crypto/DiffieHellmanFunctions.h @@ -38,7 +38,7 @@ JSC::EncodedJSValue jsDiffieHellmanProtoFuncGenerateKeysTemplate(JSC::JSGlobalOb auto encodingType = getEncodingDefaultBuffer(globalObject, scope, callFrame->argument(0)); RETURN_IF_EXCEPTION(scope, {}); - return StringBytes::encode(globalObject, scope, keys.span(), encodingType); + RELEASE_AND_RETURN(scope, StringBytes::encode(globalObject, scope, keys.span(), encodingType)); } template @@ -116,7 +116,7 @@ JSC::EncodedJSValue jsDiffieHellmanProtoFuncComputeSecretTemplate(JSC::JSGlobalO RETURN_IF_EXCEPTION(scope, {}); // If output encoding is specified and not "buffer", return a string - return StringBytes::encode(globalObject, scope, secret.span(), outputEncodingType); + RELEASE_AND_RETURN(scope, StringBytes::encode(globalObject, scope, secret.span(), outputEncodingType)); } template @@ -142,7 +142,7 @@ JSC::EncodedJSValue jsDiffieHellmanProtoFuncGetPrimeTemplate(JSC::JSGlobalObject BufferEncodingType encodingType = getEncodingDefaultBuffer(globalObject, scope, callFrame->argument(0)); RETURN_IF_EXCEPTION(scope, {}); - return StringBytes::encode(globalObject, scope, prime.span(), encodingType); + RELEASE_AND_RETURN(scope, StringBytes::encode(globalObject, scope, prime.span(), encodingType)); } template @@ -168,7 +168,7 @@ JSC::EncodedJSValue jsDiffieHellmanProtoFuncGetGeneratorTemplate(JSC::JSGlobalOb BufferEncodingType encodingType = getEncodingDefaultBuffer(globalObject, scope, callFrame->argument(0)); RETURN_IF_EXCEPTION(scope, {}); - return StringBytes::encode(globalObject, scope, gen.span(), encodingType); + RELEASE_AND_RETURN(scope, StringBytes::encode(globalObject, scope, gen.span(), encodingType)); } template @@ -194,7 +194,7 @@ JSC::EncodedJSValue jsDiffieHellmanProtoFuncGetPublicKeyTemplate(JSC::JSGlobalOb BufferEncodingType encodingType = getEncodingDefaultBuffer(globalObject, scope, callFrame->argument(0)); RETURN_IF_EXCEPTION(scope, {}); - return StringBytes::encode(globalObject, scope, key.span(), encodingType); + RELEASE_AND_RETURN(scope, StringBytes::encode(globalObject, scope, key.span(), encodingType)); } template @@ -219,7 +219,7 @@ JSC::EncodedJSValue jsDiffieHellmanProtoFuncGetPrivateKeyTemplate(JSC::JSGlobalO auto encoding = getEncodingDefaultBuffer(globalObject, scope, callFrame->argument(0)); RETURN_IF_EXCEPTION(scope, {}); - return StringBytes::encode(globalObject, scope, key.span(), encoding); + RELEASE_AND_RETURN(scope, StringBytes::encode(globalObject, scope, key.span(), encoding)); } template diff --git a/src/bun.js/bindings/node/crypto/JSCipherConstructor.cpp b/src/bun.js/bindings/node/crypto/JSCipherConstructor.cpp index 9c8fe5d21c..063e95407d 100644 --- a/src/bun.js/bindings/node/crypto/JSCipherConstructor.cpp +++ b/src/bun.js/bindings/node/crypto/JSCipherConstructor.cpp @@ -31,6 +31,7 @@ JSC_DEFINE_HOST_FUNCTION(callCipher, (JSC::JSGlobalObject * lexicalGlobalObject, ArgList args = ArgList(callFrame); auto callData = JSC::getConstructData(constructor); JSC::JSValue result = JSC::construct(globalObject, constructor, callData, args); + RETURN_IF_EXCEPTION(scope, {}); return JSValue::encode(result); } diff --git a/src/bun.js/bindings/node/crypto/JSCipherPrototype.cpp b/src/bun.js/bindings/node/crypto/JSCipherPrototype.cpp index 676afd1542..bc9f5276ca 100644 --- a/src/bun.js/bindings/node/crypto/JSCipherPrototype.cpp +++ b/src/bun.js/bindings/node/crypto/JSCipherPrototype.cpp @@ -293,6 +293,7 @@ JSC_DEFINE_HOST_FUNCTION(jsCipherSetAuthTag, (JSC::JSGlobalObject * globalObject if (cipher->m_ctx.isGcmMode() && !cipher->m_authTagLen.has_value() && tagLen != 16 && !Bun__Node__ProcessNoDeprecation) { Bun::Process::emitWarning(globalObject, jsString(vm, makeString("Using AES-GCM authentication tags of less than 128 bits without specifying the authTagLength option when initializing decryption is deprecated."_s)), jsString(vm, makeString("DeprecationWarning"_s)), jsString(vm, makeString("DEP0182"_s)), jsUndefined()); + CLEAR_IF_EXCEPTION(scope); } cipher->m_authTagLen = tagLen; diff --git a/src/bun.js/bindings/node/crypto/JSDiffieHellmanConstructor.cpp b/src/bun.js/bindings/node/crypto/JSDiffieHellmanConstructor.cpp index 7aef773fc4..2dba02a437 100644 --- a/src/bun.js/bindings/node/crypto/JSDiffieHellmanConstructor.cpp +++ b/src/bun.js/bindings/node/crypto/JSDiffieHellmanConstructor.cpp @@ -25,6 +25,7 @@ JSC_DEFINE_HOST_FUNCTION(callDiffieHellman, (JSC::JSGlobalObject * lexicalGlobal ArgList args = ArgList(callFrame); auto callData = JSC::getConstructData(constructor); JSC::JSValue result = JSC::construct(globalObject, constructor, callData, args); + RETURN_IF_EXCEPTION(scope, {}); return JSValue::encode(result); } diff --git a/src/bun.js/bindings/node/crypto/JSDiffieHellmanGroupConstructor.cpp b/src/bun.js/bindings/node/crypto/JSDiffieHellmanGroupConstructor.cpp index d6bd665276..d9449c05bb 100644 --- a/src/bun.js/bindings/node/crypto/JSDiffieHellmanGroupConstructor.cpp +++ b/src/bun.js/bindings/node/crypto/JSDiffieHellmanGroupConstructor.cpp @@ -22,6 +22,7 @@ JSC_DEFINE_HOST_FUNCTION(callDiffieHellmanGroup, (JSC::JSGlobalObject * lexicalG ArgList args = ArgList(callFrame); auto callData = JSC::getConstructData(constructor); JSC::JSValue result = JSC::construct(globalObject, constructor, callData, args); + RETURN_IF_EXCEPTION(scope, {}); return JSC::JSValue::encode(result); } diff --git a/src/bun.js/bindings/node/crypto/JSECDH.cpp b/src/bun.js/bindings/node/crypto/JSECDH.cpp index 191ca0947a..cfbcafdffe 100644 --- a/src/bun.js/bindings/node/crypto/JSECDH.cpp +++ b/src/bun.js/bindings/node/crypto/JSECDH.cpp @@ -91,7 +91,7 @@ EncodedJSValue JSECDH::getPublicKey(JSGlobalObject* globalObject, ThrowScope& sc std::span resultSpan(static_cast(result->data()), bufLen); // Return the encoded result - return StringBytes::encode(globalObject, scope, resultSpan, encodingType); + RELEASE_AND_RETURN(scope, StringBytes::encode(globalObject, scope, resultSpan, encodingType)); } DEFINE_VISIT_CHILDREN(JSECDH); diff --git a/src/bun.js/bindings/node/crypto/JSECDHConstructor.cpp b/src/bun.js/bindings/node/crypto/JSECDHConstructor.cpp index 3d2a8be7af..2e0d80edcc 100644 --- a/src/bun.js/bindings/node/crypto/JSECDHConstructor.cpp +++ b/src/bun.js/bindings/node/crypto/JSECDHConstructor.cpp @@ -39,6 +39,7 @@ JSC_DEFINE_HOST_FUNCTION(callECDH, (JSC::JSGlobalObject * lexicalGlobalObject, J ArgList args = ArgList(callFrame); auto callData = JSC::getConstructData(constructor); JSC::JSValue result = JSC::construct(globalObject, constructor, callData, args); + RETURN_IF_EXCEPTION(scope, {}); return JSValue::encode(result); } @@ -136,7 +137,7 @@ JSC_DEFINE_HOST_FUNCTION(jsECDHConvertKey, (JSC::JSGlobalObject * lexicalGlobalO BufferEncodingType outEnc = getEncodingDefaultBuffer(lexicalGlobalObject, scope, outEncValue); RETURN_IF_EXCEPTION(scope, {}); - return StringBytes::encode(lexicalGlobalObject, scope, buf.span(), outEnc); + RELEASE_AND_RETURN(scope, StringBytes::encode(lexicalGlobalObject, scope, buf.span(), outEnc)); } } // namespace Bun diff --git a/src/bun.js/bindings/node/crypto/JSECDHPrototype.cpp b/src/bun.js/bindings/node/crypto/JSECDHPrototype.cpp index 331ed43a1e..4441e85219 100644 --- a/src/bun.js/bindings/node/crypto/JSECDHPrototype.cpp +++ b/src/bun.js/bindings/node/crypto/JSECDHPrototype.cpp @@ -136,7 +136,7 @@ JSC_DEFINE_HOST_FUNCTION(jsECDHProtoFuncComputeSecret, (JSC::JSGlobalObject * gl RETURN_IF_EXCEPTION(scope, {}); // Return the encoded result - return StringBytes::encode(globalObject, scope, secret.span(), outputEncodingType); + RELEASE_AND_RETURN(scope, StringBytes::encode(globalObject, scope, secret.span(), outputEncodingType)); } JSC_DEFINE_HOST_FUNCTION(jsECDHProtoFuncGetPublicKey, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callFrame)) @@ -203,7 +203,7 @@ JSC_DEFINE_HOST_FUNCTION(jsECDHProtoFuncGetPrivateKey, (JSC::JSGlobalObject * gl std::span resultSpan(static_cast(result->data()), byteLength); // Return the encoded result - return StringBytes::encode(globalObject, scope, resultSpan, encodingType); + RELEASE_AND_RETURN(scope, StringBytes::encode(globalObject, scope, resultSpan, encodingType)); } JSC_DEFINE_HOST_FUNCTION(jsECDHProtoFuncSetPublicKey, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callFrame)) diff --git a/src/bun.js/bindings/node/crypto/JSHash.cpp b/src/bun.js/bindings/node/crypto/JSHash.cpp index 1216f28895..f93efd0757 100644 --- a/src/bun.js/bindings/node/crypto/JSHash.cpp +++ b/src/bun.js/bindings/node/crypto/JSHash.cpp @@ -232,11 +232,7 @@ JSC_DEFINE_HOST_FUNCTION(jsHashProtoFuncDigest, (JSC::JSGlobalObject * lexicalGl if (hash->m_zigHasher) { if (hash->m_digestBuffer.size() > 0 || len == 0) { - return StringBytes::encode( - lexicalGlobalObject, - scope, - hash->m_digestBuffer.span().subspan(0, hash->m_mdLen), - encoding); + RELEASE_AND_RETURN(scope, StringBytes::encode(lexicalGlobalObject, scope, hash->m_digestBuffer.span().subspan(0, hash->m_mdLen), encoding)); } uint32_t maxDigestLen = std::max((uint32_t)EVP_MAX_MD_SIZE, len); @@ -250,13 +246,7 @@ JSC_DEFINE_HOST_FUNCTION(jsHashProtoFuncDigest, (JSC::JSGlobalObject * lexicalGl hash->m_finalized = finalized; hash->m_mdLen = std::min(len, totalDigestLen); - auto result = StringBytes::encode( - lexicalGlobalObject, - scope, - hash->m_digestBuffer.span().subspan(0, hash->m_mdLen), - encoding); - - return result; + RELEASE_AND_RETURN(scope, StringBytes::encode(lexicalGlobalObject, scope, hash->m_digestBuffer.span().subspan(0, hash->m_mdLen), encoding)); } // Only compute the digest if it hasn't been cached yet diff --git a/src/bun.js/bindings/node/crypto/JSSecretKeyObjectPrototype.cpp b/src/bun.js/bindings/node/crypto/JSSecretKeyObjectPrototype.cpp index 57dac4bf87..59180b34c5 100644 --- a/src/bun.js/bindings/node/crypto/JSSecretKeyObjectPrototype.cpp +++ b/src/bun.js/bindings/node/crypto/JSSecretKeyObjectPrototype.cpp @@ -48,7 +48,7 @@ JSC_DEFINE_HOST_FUNCTION(jsSecretKeyObjectExport, (JSGlobalObject * globalObject KeyObject& handle = secretKeyObject->handle(); JSValue optionsValue = callFrame->argument(0); - return JSValue::encode(handle.exportSecret(globalObject, scope, optionsValue)); + RELEASE_AND_RETURN(scope, JSValue::encode(handle.exportSecret(globalObject, scope, optionsValue))); } JSC_DEFINE_CUSTOM_GETTER(jsSecretKeyObjectSymmetricKeySize, (JSGlobalObject*, JSC::EncodedJSValue thisValue, PropertyName propertyName)) diff --git a/src/bun.js/bindings/node/crypto/JSSign.cpp b/src/bun.js/bindings/node/crypto/JSSign.cpp index 977bd2646d..e94be2fa93 100644 --- a/src/bun.js/bindings/node/crypto/JSSign.cpp +++ b/src/bun.js/bindings/node/crypto/JSSign.cpp @@ -452,9 +452,8 @@ JSC_DEFINE_HOST_FUNCTION(jsSignProtoFuncSign, (JSC::JSGlobalObject * lexicalGlob // Use the signWithKey function to perform the signing operation JSUint8Array* signature = signWithKey(lexicalGlobalObject, thisObject, keyPtr, dsaSigEnc, padding, saltLen); - if (!signature) { - return {}; - } + EXCEPTION_ASSERT(!!signature == !scope.exception()); + RETURN_IF_EXCEPTION(scope, {}); // If output encoding is not buffer, convert the signature to the requested encoding if (outputEncoding != BufferEncodingType::buffer) { diff --git a/src/bun.js/bindings/node/crypto/KeyObject.cpp b/src/bun.js/bindings/node/crypto/KeyObject.cpp index aff9e9deaf..0a1d9658b6 100644 --- a/src/bun.js/bindings/node/crypto/KeyObject.cpp +++ b/src/bun.js/bindings/node/crypto/KeyObject.cpp @@ -393,13 +393,13 @@ JSValue KeyObject::exportAsymmetric(JSGlobalObject* globalObject, ThrowScope& sc ncrypto::EVPKeyPointer::PublicKeyEncodingConfig config; parsePublicKeyEncoding(globalObject, scope, options, keyType, WTF::nullStringView(), config); RETURN_IF_EXCEPTION(scope, {}); - return exportPublic(globalObject, scope, config); + RELEASE_AND_RETURN(scope, exportPublic(globalObject, scope, config)); } ncrypto::EVPKeyPointer::PrivateKeyEncodingConfig config; parsePrivateKeyEncoding(globalObject, scope, options, keyType, WTF::nullStringView(), config); RETURN_IF_EXCEPTION(scope, {}); - return exportPrivate(globalObject, scope, config); + RELEASE_AND_RETURN(scope, exportPrivate(globalObject, scope, config)); } // This would hit validateObject in `parseKeyEncoding` diff --git a/src/bun.js/bindings/node/crypto/node_crypto_binding.cpp b/src/bun.js/bindings/node/crypto/node_crypto_binding.cpp index e9fd3535de..06cb1c4671 100644 --- a/src/bun.js/bindings/node/crypto/node_crypto_binding.cpp +++ b/src/bun.js/bindings/node/crypto/node_crypto_binding.cpp @@ -99,7 +99,7 @@ JSC_DEFINE_HOST_FUNCTION(jsGetCiphers, (JSC::JSGlobalObject * lexicalGlobalObjec JSC::JSArray* array; int index; JSC::VM& vm; - bool hasException; + JSC::ThrowScope& scope; }; CipherPushContext ctx = { @@ -107,23 +107,19 @@ JSC_DEFINE_HOST_FUNCTION(jsGetCiphers, (JSC::JSGlobalObject * lexicalGlobalObjec result, 0, vm, - false + scope, }; auto callback = [](const EVP_CIPHER* cipher, const char* name, const char* /*unused*/, void* arg) { auto* ctx = static_cast(arg); - if (ctx->hasException) - return; - + RETURN_IF_EXCEPTION(ctx->scope, ); auto cipherStr = JSC::jsString(ctx->vm, String::fromUTF8(name)); - if (!ctx->array->putDirectIndex(ctx->globalObject, ctx->index++, cipherStr)) - ctx->hasException = true; + ctx->array->putDirectIndex(ctx->globalObject, ctx->index++, cipherStr); + RETURN_IF_EXCEPTION(ctx->scope, ); }; EVP_CIPHER_do_all_sorted(callback, &ctx); - - if (ctx.hasException) - return {}; + RETURN_IF_EXCEPTION(scope, {}); return JSValue::encode(result); } diff --git a/src/bun.js/bindings/node/http/JSHTTPParserPrototype.cpp b/src/bun.js/bindings/node/http/JSHTTPParserPrototype.cpp index 2a87bf947e..d4a350f70a 100644 --- a/src/bun.js/bindings/node/http/JSHTTPParserPrototype.cpp +++ b/src/bun.js/bindings/node/http/JSHTTPParserPrototype.cpp @@ -125,7 +125,7 @@ JSC_DEFINE_HOST_FUNCTION(jsHTTPParser_execute, (JSGlobalObject * globalObject, C if (auto* buffer = jsDynamicCast(bufferValue)) { if (buffer->isDetached()) { throwTypeError(globalObject, scope, "Buffer is detached"_s); - return JSValue::encode(jsUndefined()); + return {}; } JSValue result = parser->impl()->execute(globalObject, reinterpret_cast(buffer->vector()), buffer->byteLength()); diff --git a/src/bun.js/bindings/node/http/NodeHTTPParser.cpp b/src/bun.js/bindings/node/http/NodeHTTPParser.cpp index 2320ca1655..30d5744b9f 100644 --- a/src/bun.js/bindings/node/http/NodeHTTPParser.cpp +++ b/src/bun.js/bindings/node/http/NodeHTTPParser.cpp @@ -124,8 +124,10 @@ JSValue HTTPParser::execute(JSGlobalObject* globalObject, const char* data, size if (data == nullptr) { err = llhttp_finish(&m_parserData); + RETURN_IF_EXCEPTION(scope, {}); } else { err = llhttp_execute(&m_parserData, data, len); + RETURN_IF_EXCEPTION(scope, {}); save(); } @@ -476,7 +478,9 @@ int HTTPParser::onHeadersComplete() flush(); RETURN_IF_EXCEPTION(scope, -1); } else { - args.set(A_HEADERS, createHeaders(globalObject)); + auto headers = createHeaders(globalObject); + RETURN_IF_EXCEPTION(scope, -1); + args.set(A_HEADERS, headers); if (m_parserData.type == HTTP_REQUEST) { args.set(A_URL, m_url.toString(globalObject)); } @@ -583,9 +587,7 @@ int HTTPParser::onMessageComplete() MarkedArgumentBuffer args; JSC::profiledCall(globalObject, ProfilingReason::API, onMessageCompleteCallback, callData, thisParser, args); - if (scope.exception()) [[unlikely]] { - return -1; - } + RETURN_IF_EXCEPTION(scope, -1); return 0; } diff --git a/src/bun.js/bindings/webcore/InternalWritableStream.cpp b/src/bun.js/bindings/webcore/InternalWritableStream.cpp index e227ac6167..ab2a8ec27b 100644 --- a/src/bun.js/bindings/webcore/InternalWritableStream.cpp +++ b/src/bun.js/bindings/webcore/InternalWritableStream.cpp @@ -89,9 +89,7 @@ bool InternalWritableStream::locked() const ASSERT(!arguments.hasOverflowed()); auto result = invokeWritableStreamFunction(*globalObject, privateName, arguments); - if (scope.exception()) [[unlikely]] - scope.clearException(); - + CLEAR_IF_EXCEPTION(scope); return result.hasException() ? false : result.returnValue().isTrue(); } @@ -111,8 +109,7 @@ void InternalWritableStream::lock() ASSERT(!arguments.hasOverflowed()); auto result = invokeWritableStreamFunction(*globalObject, privateName, arguments); - if (scope.exception()) [[unlikely]] - scope.clearException(); + CLEAR_IF_EXCEPTION(scope); } JSC::JSValue InternalWritableStream::abort(JSC::JSGlobalObject& globalObject, JSC::JSValue reason) diff --git a/src/bun.js/bindings/webcore/JSDOMConvertSequences.h b/src/bun.js/bindings/webcore/JSDOMConvertSequences.h index fdc14839c8..36818b187a 100644 --- a/src/bun.js/bindings/webcore/JSDOMConvertSequences.h +++ b/src/bun.js/bindings/webcore/JSDOMConvertSequences.h @@ -53,8 +53,7 @@ struct GenericSequenceConverter { auto scope = DECLARE_THROW_SCOPE(vm); auto convertedValue = Converter::convert(*lexicalGlobalObject, nextValue); - if (scope.exception()) [[unlikely]] - return; + RETURN_IF_EXCEPTION(scope, ); result.append(WTFMove(convertedValue)); }); return WTFMove(result); @@ -68,8 +67,7 @@ struct GenericSequenceConverter { auto scope = DECLARE_THROW_SCOPE(vm); auto convertedValue = Converter::convert(*lexicalGlobalObject, nextValue, std::forward(exceptionThrower)); - if (scope.exception()) [[unlikely]] - return; + RETURN_IF_EXCEPTION(scope, ); result.append(WTFMove(convertedValue)); }); return WTFMove(result); @@ -86,8 +84,7 @@ struct GenericSequenceConverter { auto scope = DECLARE_THROW_SCOPE(vm); auto convertedValue = Converter::convert(lexicalGlobalObject, nextValue); - if (scope.exception()) [[unlikely]] - return; + RETURN_IF_EXCEPTION(scope, ); result.append(WTFMove(convertedValue)); }); return WTFMove(result); diff --git a/src/bun.js/bindings/webcore/JSDOMConvertVariadic.h b/src/bun.js/bindings/webcore/JSDOMConvertVariadic.h index 3dce23bec6..b3f075e5fc 100644 --- a/src/bun.js/bindings/webcore/JSDOMConvertVariadic.h +++ b/src/bun.js/bindings/webcore/JSDOMConvertVariadic.h @@ -61,7 +61,7 @@ template FixedVector::Item size_t resultIndex = 0; for (size_t i = startIndex; i < length; ++i) { auto value = VariadicConverter::convert(lexicalGlobalObject, callFrame.uncheckedArgument(i)); - EXCEPTION_ASSERT_UNUSED(scope, !!scope.exception() == !value); + ASSERT_UNUSED(scope, !!scope.exception() == !value); if (!value) return {}; result[resultIndex] = WTFMove(*value); diff --git a/src/bun.js/bindings/webcore/JSDOMIterator.h b/src/bun.js/bindings/webcore/JSDOMIterator.h index a870e64d83..6651153f69 100644 --- a/src/bun.js/bindings/webcore/JSDOMIterator.h +++ b/src/bun.js/bindings/webcore/JSDOMIterator.h @@ -266,7 +266,7 @@ JSC::EncodedJSValue JSC_HOST_CALL_ATTRIBUTES JSDOMIteratorPrototypenext(*globalObject)); + RELEASE_AND_RETURN(scope, JSC::JSValue::encode(iterator->next(*globalObject))); } template diff --git a/src/bun.js/bindings/webcore/JSDOMPromise.cpp b/src/bun.js/bindings/webcore/JSDOMPromise.cpp index fbcf8cc54e..1403399c48 100644 --- a/src/bun.js/bindings/webcore/JSDOMPromise.cpp +++ b/src/bun.js/bindings/webcore/JSDOMPromise.cpp @@ -58,8 +58,7 @@ auto DOMPromise::whenPromiseIsSettled(JSDOMGlobalObject* globalObject, JSC::JSOb auto thenFunction = promise->get(&lexicalGlobalObject, privateName); EXCEPTION_ASSERT(!scope.exception() || vm.hasPendingTerminationException()); - if (scope.exception()) [[unlikely]] - return IsCallbackRegistered::No; + RETURN_IF_EXCEPTION(scope, IsCallbackRegistered::No); ASSERT(thenFunction.isCallable()); diff --git a/src/bun.js/bindings/webcore/JSDOMPromiseDeferred.h b/src/bun.js/bindings/webcore/JSDOMPromiseDeferred.h index f7fbd4c02c..0cb1a98a11 100644 --- a/src/bun.js/bindings/webcore/JSDOMPromiseDeferred.h +++ b/src/bun.js/bindings/webcore/JSDOMPromiseDeferred.h @@ -68,7 +68,12 @@ public: ASSERT(globalObject()); JSC::JSGlobalObject* lexicalGlobalObject = globalObject(); JSC::JSLockHolder locker(lexicalGlobalObject); - resolve(*lexicalGlobalObject, toJS(*lexicalGlobalObject, *globalObject(), std::forward(value))); + auto& vm = JSC::getVM(lexicalGlobalObject); + auto scope = DECLARE_THROW_SCOPE(vm); + auto value_js = toJS(*lexicalGlobalObject, *globalObject(), std::forward(value)); + RETURN_IF_EXCEPTION(scope, ); + resolve(*lexicalGlobalObject, value_js); + RETURN_IF_EXCEPTION(scope, ); } void resolveWithJSValue(JSC::JSValue resolution) diff --git a/src/bun.js/bindings/webcore/JSEventTarget.cpp b/src/bun.js/bindings/webcore/JSEventTarget.cpp index 32ae670f65..d1fed97ce7 100644 --- a/src/bun.js/bindings/webcore/JSEventTarget.cpp +++ b/src/bun.js/bindings/webcore/JSEventTarget.cpp @@ -240,7 +240,8 @@ static inline JSC::EncodedJSValue jsEventTargetPrototypeFunction_addEventListene RETURN_IF_EXCEPTION(throwScope, {}); errorInstance->putDirect(vm, vm.propertyNames->type, jsString(vm, WTFMove(type))); Bun::Process::emitWarningErrorInstance(lexicalGlobalObject, errorInstance); - RETURN_IF_EXCEPTION(throwScope, {}); + if (throwScope.exception()) [[unlikely]] + throwScope.clearException(); } auto result = JSValue::encode(toJS(*lexicalGlobalObject, throwScope, [&]() -> decltype(auto) { return impl.addEventListenerForBindings(WTFMove(type), WTFMove(listener), WTFMove(options)); })); RETURN_IF_EXCEPTION(throwScope, {}); diff --git a/src/bun.js/bindings/webcore/JSMIMEParams.cpp b/src/bun.js/bindings/webcore/JSMIMEParams.cpp index f368a9145b..93be29485e 100644 --- a/src/bun.js/bindings/webcore/JSMIMEParams.cpp +++ b/src/bun.js/bindings/webcore/JSMIMEParams.cpp @@ -310,7 +310,9 @@ bool parseMIMEParamsString(JSGlobalObject* globalObject, JSMap* map, StringView // Add to map only if the name doesn't exist yet (first one wins) JSValue nameJS = jsString(vm, name); - if (!map->has(globalObject, nameJS)) { + auto has = map->has(globalObject, nameJS); + RETURN_IF_EXCEPTION(scope, {}); + if (!has) { map->set(globalObject, nameJS, jsString(vm, valueStr)); RETURN_IF_EXCEPTION(scope, false); } @@ -404,7 +406,9 @@ JSC_DEFINE_HOST_FUNCTION(jsMIMEParamsProtoFuncGet, (JSGlobalObject * globalObjec // 3. Perform operation on the map JSMap* map = thisObject->jsMap(); - if (!map->has(globalObject, jsString(vm, name))) { + auto has = map->has(globalObject, jsString(vm, name)); + RETURN_IF_EXCEPTION(scope, {}); + if (!has) { return JSValue::encode(jsNull()); } JSValue result = map->get(globalObject, jsString(vm, name)); @@ -561,7 +565,7 @@ JSC_DEFINE_HOST_FUNCTION(jsMIMEParamsProtoFuncEntries, (JSGlobalObject * globalO scope.throwException(globalObject, Bun::createInvalidThisError(globalObject, thisObject, "MIMEParams")); RETURN_IF_EXCEPTION(scope, {}); } - return JSValue::encode(JSMapIterator::create(globalObject, globalObject->mapIteratorStructure(), thisObject->jsMap(), IterationKind::Entries)); + RELEASE_AND_RETURN(scope, JSValue::encode(JSMapIterator::create(globalObject, globalObject->mapIteratorStructure(), thisObject->jsMap(), IterationKind::Entries))); } JSC_DEFINE_HOST_FUNCTION(jsMIMEParamsProtoFuncKeys, (JSGlobalObject * globalObject, CallFrame* callFrame)) @@ -572,7 +576,7 @@ JSC_DEFINE_HOST_FUNCTION(jsMIMEParamsProtoFuncKeys, (JSGlobalObject * globalObje scope.throwException(globalObject, Bun::createInvalidThisError(globalObject, thisObject, "MIMEParams")); RETURN_IF_EXCEPTION(scope, {}); } - return JSValue::encode(JSMapIterator::create(globalObject, globalObject->mapIteratorStructure(), thisObject->jsMap(), IterationKind::Keys)); + RELEASE_AND_RETURN(scope, JSValue::encode(JSMapIterator::create(globalObject, globalObject->mapIteratorStructure(), thisObject->jsMap(), IterationKind::Keys))); } JSC_DEFINE_HOST_FUNCTION(jsMIMEParamsProtoFuncValues, (JSGlobalObject * globalObject, CallFrame* callFrame)) @@ -583,7 +587,7 @@ JSC_DEFINE_HOST_FUNCTION(jsMIMEParamsProtoFuncValues, (JSGlobalObject * globalOb scope.throwException(globalObject, Bun::createInvalidThisError(globalObject, thisObject, "MIMEParams")); RETURN_IF_EXCEPTION(scope, {}); } - return JSValue::encode(JSMapIterator::create(globalObject, globalObject->mapIteratorStructure(), thisObject->jsMap(), IterationKind::Values)); + RELEASE_AND_RETURN(scope, JSValue::encode(JSMapIterator::create(globalObject, globalObject->mapIteratorStructure(), thisObject->jsMap(), IterationKind::Values))); } // Forward declare constructor functions diff --git a/src/bun.js/bindings/webcore/JSWorker.cpp b/src/bun.js/bindings/webcore/JSWorker.cpp index d7b52f90cd..dfef1c89ff 100644 --- a/src/bun.js/bindings/webcore/JSWorker.cpp +++ b/src/bun.js/bindings/webcore/JSWorker.cpp @@ -287,6 +287,7 @@ template<> JSC::EncodedJSValue JSC_HOST_CALL_ATTRIBUTES JSWorkerDOMConstructor:: RETURN_IF_EXCEPTION(scope, ); options.argv.append(str); }); + RETURN_IF_EXCEPTION(throwScope, {}); } JSValue execArgvValue = optionsObject->getIfPropertyExists(lexicalGlobalObject, Identifier::fromString(vm, "execArgv"_s)); diff --git a/src/bun.js/bindings/webcore/ReadableStream.cpp b/src/bun.js/bindings/webcore/ReadableStream.cpp index 90f1ebd756..0150f441d0 100644 --- a/src/bun.js/bindings/webcore/ReadableStream.cpp +++ b/src/bun.js/bindings/webcore/ReadableStream.cpp @@ -56,7 +56,7 @@ static inline ExceptionOr invokeConstructor(JSC::JSGlobalObject& lexi ASSERT(!args.hasOverflowed()); JSObject* object = JSC::construct(&lexicalGlobalObject, constructor, constructData, args); - ASSERT(!!scope.exception() == !object); + EXCEPTION_ASSERT(!!scope.exception() == !object); EXCEPTION_ASSERT(!scope.exception() || vm.hasPendingTerminationException()); RETURN_IF_EXCEPTION(scope, Exception { ExistingExceptionError }); @@ -107,8 +107,7 @@ static inline std::optional invokeReadableStreamFunction(JSC::JSGl auto callData = JSC::getCallData(function); auto result = call(&lexicalGlobalObject, function, callData, thisValue, arguments); EXCEPTION_ASSERT(!scope.exception() || vm.hasPendingTerminationException()); - if (scope.exception()) [[unlikely]] - return {}; + RETURN_IF_EXCEPTION(scope, {}); return result; } diff --git a/src/bun.js/bindings/webcore/SerializedScriptValue.cpp b/src/bun.js/bindings/webcore/SerializedScriptValue.cpp index 681c16c4d9..fa401a699e 100644 --- a/src/bun.js/bindings/webcore/SerializedScriptValue.cpp +++ b/src/bun.js/bindings/webcore/SerializedScriptValue.cpp @@ -1575,6 +1575,8 @@ private: } VM& vm = m_lexicalGlobalObject->vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + if (isArray(value)) return false; @@ -1667,7 +1669,6 @@ private: } if (auto* errorInstance = jsDynamicCast(obj)) { auto& vm = m_lexicalGlobalObject->vm(); - auto scope = DECLARE_THROW_SCOPE(vm); auto errorTypeValue = errorInstance->get(m_lexicalGlobalObject, vm.propertyNames->name); RETURN_IF_EXCEPTION(scope, false); auto errorTypeString = errorTypeValue.toWTFString(m_lexicalGlobalObject); @@ -1783,6 +1784,7 @@ private: if (checkForDuplicate(obj)) return true; bool success = dumpArrayBufferView(obj, code); + RETURN_IF_EXCEPTION(scope, false); recordObject(obj); return success; } @@ -1997,7 +1999,6 @@ private: return true; } case CryptoKeyType::Public: { - auto scope = DECLARE_THROW_SCOPE(vm); auto* pkey = handle.asymmetricKey().get(); BIO* bio = BIO_new(BIO_s_mem()); @@ -2015,7 +2016,6 @@ private: return true; } case CryptoKeyType::Private: { - auto scope = DECLARE_THROW_SCOPE(vm); auto* pkey = handle.asymmetricKey().get(); BIO* bio = BIO_new(BIO_s_mem()); @@ -2608,8 +2608,7 @@ SerializationReturnCode CloneSerializer::serialize(JSValue in) propertyStack.append(PropertyNameArray(vm, PropertyNameMode::Strings, PrivateSymbolMode::Exclude)); array->getOwnNonIndexPropertyNames(m_lexicalGlobalObject, propertyStack.last(), DontEnumPropertiesMode::Exclude); - if (scope.exception()) [[unlikely]] - return SerializationReturnCode::ExistingExceptionError; + RETURN_IF_EXCEPTION(scope, SerializationReturnCode::ExistingExceptionError); if (propertyStack.last().size()) { write(NonIndexPropertiesTag); indexStack.append(0); @@ -2622,8 +2621,7 @@ SerializationReturnCode CloneSerializer::serialize(JSValue in) break; } inValue = array->getDirectIndex(m_lexicalGlobalObject, index); - if (scope.exception()) [[unlikely]] - return SerializationReturnCode::ExistingExceptionError; + RETURN_IF_EXCEPTION(scope, SerializationReturnCode::ExistingExceptionError); if (!inValue) { indexStack.last()++; goto arrayStartVisitMember; @@ -2631,7 +2629,9 @@ SerializationReturnCode CloneSerializer::serialize(JSValue in) write(index); auto terminalCode = SerializationReturnCode::SuccessfullyCompleted; - if (dumpIfTerminal(inValue, terminalCode)) { + auto dumped = dumpIfTerminal(inValue, terminalCode); + RETURN_IF_EXCEPTION(scope, SerializationReturnCode::ExistingExceptionError); + if (dumped) { if (terminalCode != SerializationReturnCode::SuccessfullyCompleted) return terminalCode; indexStack.last()++; @@ -2662,8 +2662,7 @@ SerializationReturnCode CloneSerializer::serialize(JSValue in) indexStack.append(0); propertyStack.append(PropertyNameArray(vm, PropertyNameMode::Strings, PrivateSymbolMode::Exclude)); inObject->methodTable()->getOwnPropertyNames(inObject, m_lexicalGlobalObject, propertyStack.last(), DontEnumPropertiesMode::Exclude); - if (scope.exception()) [[unlikely]] - return SerializationReturnCode::ExistingExceptionError; + RETURN_IF_EXCEPTION(scope, SerializationReturnCode::ExistingExceptionError); } objectStartVisitMember: [[fallthrough]]; @@ -2679,8 +2678,7 @@ SerializationReturnCode CloneSerializer::serialize(JSValue in) break; } inValue = getProperty(object, properties[index]); - if (scope.exception()) [[unlikely]] - return SerializationReturnCode::ExistingExceptionError; + RETURN_IF_EXCEPTION(scope, SerializationReturnCode::ExistingExceptionError); if (!inValue) { // Property was removed during serialisation @@ -2689,11 +2687,12 @@ SerializationReturnCode CloneSerializer::serialize(JSValue in) } write(properties[index]); - if (scope.exception()) [[unlikely]] - return SerializationReturnCode::ExistingExceptionError; + RETURN_IF_EXCEPTION(scope, SerializationReturnCode::ExistingExceptionError); auto terminalCode = SerializationReturnCode::SuccessfullyCompleted; - if (!dumpIfTerminal(inValue, terminalCode)) { + auto dumped = dumpIfTerminal(inValue, terminalCode); + RETURN_IF_EXCEPTION(scope, SerializationReturnCode::ExistingExceptionError); + if (!dumped) { stateStack.append(ObjectEndVisitMember); goto stateUnknown; } @@ -2702,8 +2701,7 @@ SerializationReturnCode CloneSerializer::serialize(JSValue in) [[fallthrough]]; } case ObjectEndVisitMember: { - if (scope.exception()) [[unlikely]] - return SerializationReturnCode::ExistingExceptionError; + RETURN_IF_EXCEPTION(scope, SerializationReturnCode::ExistingExceptionError); indexStack.last()++; goto objectStartVisitMember; @@ -2716,8 +2714,7 @@ SerializationReturnCode CloneSerializer::serialize(JSValue in) if (!startMap(inMap)) break; JSMapIterator* iterator = JSMapIterator::create(m_lexicalGlobalObject, m_lexicalGlobalObject->mapIteratorStructure(), inMap, IterationKind::Entries); - if (scope.exception()) [[unlikely]] - return SerializationReturnCode::ExistingExceptionError; + RETURN_IF_EXCEPTION(scope, SerializationReturnCode::ExistingExceptionError); m_gcBuffer.appendWithCrashOnOverflow(inMap); m_gcBuffer.appendWithCrashOnOverflow(iterator); mapIteratorStack.append(iterator); @@ -2734,8 +2731,7 @@ SerializationReturnCode CloneSerializer::serialize(JSValue in) ASSERT(jsDynamicCast(object)); propertyStack.append(PropertyNameArray(vm, PropertyNameMode::Strings, PrivateSymbolMode::Exclude)); object->methodTable()->getOwnPropertyNames(object, m_lexicalGlobalObject, propertyStack.last(), DontEnumPropertiesMode::Exclude); - if (scope.exception()) [[unlikely]] - return SerializationReturnCode::ExistingExceptionError; + RETURN_IF_EXCEPTION(scope, SerializationReturnCode::ExistingExceptionError); write(NonMapPropertiesTag); indexStack.append(0); goto objectStartVisitMember; @@ -2764,8 +2760,7 @@ SerializationReturnCode CloneSerializer::serialize(JSValue in) if (!startSet(inSet)) break; JSSetIterator* iterator = JSSetIterator::create(m_lexicalGlobalObject, m_lexicalGlobalObject->setIteratorStructure(), inSet, IterationKind::Keys); - if (scope.exception()) [[unlikely]] - return SerializationReturnCode::ExistingExceptionError; + RETURN_IF_EXCEPTION(scope, SerializationReturnCode::ExistingExceptionError); m_gcBuffer.appendWithCrashOnOverflow(inSet); m_gcBuffer.appendWithCrashOnOverflow(iterator); setIteratorStack.append(iterator); @@ -2782,8 +2777,7 @@ SerializationReturnCode CloneSerializer::serialize(JSValue in) ASSERT(jsDynamicCast(object)); propertyStack.append(PropertyNameArray(vm, PropertyNameMode::Strings, PrivateSymbolMode::Exclude)); object->methodTable()->getOwnPropertyNames(object, m_lexicalGlobalObject, propertyStack.last(), DontEnumPropertiesMode::Exclude); - if (scope.exception()) [[unlikely]] - return SerializationReturnCode::ExistingExceptionError; + RETURN_IF_EXCEPTION(scope, SerializationReturnCode::ExistingExceptionError); write(NonSetPropertiesTag); indexStack.append(0); goto objectStartVisitMember; @@ -2799,7 +2793,9 @@ SerializationReturnCode CloneSerializer::serialize(JSValue in) stateUnknown: case StateUnknown: { auto terminalCode = SerializationReturnCode::SuccessfullyCompleted; - if (dumpIfTerminal(inValue, terminalCode)) { + auto dumped = dumpIfTerminal(inValue, terminalCode); + RETURN_IF_EXCEPTION(scope, SerializationReturnCode::ExistingExceptionError); + if (dumped) { if (terminalCode != SerializationReturnCode::SuccessfullyCompleted) return terminalCode; break; @@ -5270,7 +5266,6 @@ DeserializationResult CloneDeserializer::deserialize() case ArrayStartState: { uint32_t length; if (!read(length)) { - fail(); goto error; } JSArray* outArray = constructEmptyArray(m_globalObject, static_cast(nullptr), length); @@ -5284,7 +5279,6 @@ DeserializationResult CloneDeserializer::deserialize() case ArrayStartVisitMember: { uint32_t index; if (!read(index)) { - fail(); goto error; } if (index == TerminatorTag) { @@ -5296,10 +5290,14 @@ DeserializationResult CloneDeserializer::deserialize() goto objectStartVisitMember; } - if (JSValue terminal = readTerminal()) { + JSValue terminal = readTerminal(); + if (scope.exception()) [[unlikely]] + goto error; + if (m_failed) + goto error; + if (terminal) { putProperty(outputObjectStack.last(), index, terminal); if (scope.exception()) [[unlikely]] { - fail(); goto error; } goto arrayStartVisitMember; @@ -5314,7 +5312,6 @@ DeserializationResult CloneDeserializer::deserialize() JSObject* outArray = outputObjectStack.last(); putProperty(outArray, indexStack.last(), outValue); if (scope.exception()) [[unlikely]] { - fail(); goto error; } indexStack.removeLast(); @@ -5343,10 +5340,14 @@ DeserializationResult CloneDeserializer::deserialize() break; } - if (JSValue terminal = readTerminal()) { + JSValue terminal = readTerminal(); + if (scope.exception()) [[unlikely]] + goto error; + if (m_failed) + goto error; + if (terminal) { putProperty(outputObjectStack.last(), cachedString->identifier(vm), terminal); if (scope.exception()) [[unlikely]] { - fail(); goto error; } goto objectStartVisitMember; @@ -5386,7 +5387,6 @@ DeserializationResult CloneDeserializer::deserialize() case MapDataEndVisitValue: { mapStack.last()->set(m_lexicalGlobalObject, mapKeyStack.last(), outValue); if (scope.exception()) [[unlikely]] { - fail(); goto error; } mapKeyStack.removeLast(); @@ -5415,7 +5415,6 @@ DeserializationResult CloneDeserializer::deserialize() JSSet* set = setStack.last(); set->add(m_lexicalGlobalObject, outValue); if (scope.exception()) [[unlikely]] { - fail(); goto error; } goto setDataStartVisitEntry; @@ -5423,7 +5422,12 @@ DeserializationResult CloneDeserializer::deserialize() stateUnknown: case StateUnknown: - if (JSValue terminal = readTerminal()) { + JSValue terminal = readTerminal(); + if (scope.exception()) [[unlikely]] + goto error; + if (m_failed) + goto error; + if (terminal) { outValue = terminal; break; } @@ -5641,13 +5645,13 @@ static void maybeThrowExceptionIfSerializationFailed(JSGlobalObject& lexicalGlob break; case SerializationReturnCode::StackOverflowError: throwException(&lexicalGlobalObject, scope, createStackOverflowError(&lexicalGlobalObject)); - RELEASE_AND_RETURN(scope, ); + break; case SerializationReturnCode::ValidationError: throwTypeError(&lexicalGlobalObject, scope, "Unable to deserialize data."_s); - RELEASE_AND_RETURN(scope, ); + break; case SerializationReturnCode::DataCloneError: throwDataCloneError(lexicalGlobalObject, scope); - RELEASE_AND_RETURN(scope, ); + break; case SerializationReturnCode::ExistingExceptionError: case SerializationReturnCode::UnspecifiedError: break; @@ -6005,7 +6009,8 @@ Ref SerializedScriptValue::toArrayBuffer() JSC::JSValue SerializedScriptValue::fromArrayBuffer(JSC::JSGlobalObject& domGlobal, JSC::JSGlobalObject* globalObject, JSC::ArrayBuffer* arrayBuffer, size_t byteOffset, size_t maxByteLength, SerializationErrorMode throwExceptions, bool* didFail) { - auto throwScope = DECLARE_THROW_SCOPE(globalObject->vm()); + auto& vm = JSC::getVM(globalObject); + auto throwScope = DECLARE_THROW_SCOPE(vm); if (!arrayBuffer || arrayBuffer->isDetached()) { if (didFail) @@ -6046,8 +6051,9 @@ JSC::JSValue SerializedScriptValue::fromArrayBuffer(JSC::JSGlobalObject& domGlob if (didFail) { *didFail = result.second != SerializationReturnCode::SuccessfullyCompleted; } - if (throwExceptions == SerializationErrorMode::Throwing) + if (throwScope.exception() || throwExceptions == SerializationErrorMode::Throwing) [[unlikely]] maybeThrowExceptionIfSerializationFailed(*globalObject, result.second); + RETURN_IF_EXCEPTION(throwScope, {}); return result.first ? result.first : jsNull(); } diff --git a/src/bun.js/bindings/webcore/Worker.cpp b/src/bun.js/bindings/webcore/Worker.cpp index c2bd4deeef..1eb0cec609 100644 --- a/src/bun.js/bindings/webcore/Worker.cpp +++ b/src/bun.js/bindings/webcore/Worker.cpp @@ -545,7 +545,7 @@ JSC_DEFINE_HOST_FUNCTION(jsReceiveMessageOnPort, (JSGlobalObject * lexicalGlobal } if (auto* messagePort = jsDynamicCast(port)) { - return JSC::JSValue::encode(messagePort->wrapped().tryTakeMessage(lexicalGlobalObject)); + RELEASE_AND_RETURN(scope, JSC::JSValue::encode(messagePort->wrapped().tryTakeMessage(lexicalGlobalObject))); } else if (jsDynamicCast(port)) { // TODO: support broadcast channels return JSC::JSValue::encode(jsUndefined()); @@ -627,11 +627,13 @@ JSC_DEFINE_HOST_FUNCTION(jsFunctionPostMessage, if (options.isObject()) { JSC::JSObject* optionsObject = options.getObject(); JSC::JSValue transferListValue = optionsObject->get(globalObject, vm.propertyNames->transfer); + RETURN_IF_EXCEPTION(scope, {}); if (transferListValue.isObject()) { JSC::JSObject* transferListObject = transferListValue.getObject(); if (auto* transferListArray = jsDynamicCast(transferListObject)) { for (unsigned i = 0; i < transferListArray->length(); i++) { JSC::JSValue transferListValue = transferListArray->get(globalObject, i); + RETURN_IF_EXCEPTION(scope, {}); if (transferListValue.isObject()) { JSC::JSObject* transferListObject = transferListValue.getObject(); transferList.append(JSC::Strong(vm, transferListObject)); diff --git a/src/bun.js/bindings/webcrypto/SubtleCrypto.cpp b/src/bun.js/bindings/webcrypto/SubtleCrypto.cpp index 1ae4f278ee..eddda7a9a8 100644 --- a/src/bun.js/bindings/webcrypto/SubtleCrypto.cpp +++ b/src/bun.js/bindings/webcrypto/SubtleCrypto.cpp @@ -115,7 +115,7 @@ static ExceptionOr> normalizeCryptoAl auto newParams = Strong(vm, constructEmptyObject(&state)); newParams->putDirect(vm, vm.propertyNames->name, jsString(vm, std::get(algorithmIdentifier))); - return normalizeCryptoAlgorithmParameters(state, newParams, operation); + RELEASE_AND_RETURN(scope, normalizeCryptoAlgorithmParameters(state, newParams, operation)); } auto& value = std::get>(algorithmIdentifier); @@ -181,8 +181,8 @@ static ExceptionOr> normalizeCryptoAl auto params = convertDictionary(state, value.get()); RETURN_IF_EXCEPTION(scope, Exception { ExistingExceptionError }); auto hashIdentifier = toHashIdentifier(state, params.hash); - if (hashIdentifier.hasException()) - return hashIdentifier.releaseException(); + RETURN_IF_EXCEPTION(scope, Exception { ExistingExceptionError }); + if (hashIdentifier.hasException()) return hashIdentifier.releaseException(); params.hashIdentifier = hashIdentifier.releaseReturnValue(); result = makeUnique(params); break; @@ -226,8 +226,8 @@ static ExceptionOr> normalizeCryptoAl auto params = convertDictionary(state, value.get()); RETURN_IF_EXCEPTION(scope, Exception { ExistingExceptionError }); auto hashIdentifier = toHashIdentifier(state, params.hash); - if (hashIdentifier.hasException()) - return hashIdentifier.releaseException(); + RETURN_IF_EXCEPTION(scope, Exception { ExistingExceptionError }); + if (hashIdentifier.hasException()) return hashIdentifier.releaseException(); params.hashIdentifier = hashIdentifier.releaseReturnValue(); result = makeUnique(params); break; @@ -246,8 +246,8 @@ static ExceptionOr> normalizeCryptoAl auto params = convertDictionary(state, value.get()); RETURN_IF_EXCEPTION(scope, Exception { ExistingExceptionError }); auto hashIdentifier = toHashIdentifier(state, params.hash); - if (hashIdentifier.hasException()) - return hashIdentifier.releaseException(); + RETURN_IF_EXCEPTION(scope, Exception { ExistingExceptionError }); + if (hashIdentifier.hasException()) return hashIdentifier.releaseException(); params.hashIdentifier = hashIdentifier.releaseReturnValue(); result = makeUnique(params); break; @@ -301,8 +301,8 @@ static ExceptionOr> normalizeCryptoAl auto params = convertDictionary(state, value.get()); RETURN_IF_EXCEPTION(scope, Exception { ExistingExceptionError }); auto hashIdentifier = toHashIdentifier(state, params.hash); - if (hashIdentifier.hasException()) - return hashIdentifier.releaseException(); + RETURN_IF_EXCEPTION(scope, Exception { ExistingExceptionError }); + if (hashIdentifier.hasException()) return hashIdentifier.releaseException(); params.hashIdentifier = hashIdentifier.releaseReturnValue(); result = makeUnique(params); break; @@ -311,8 +311,8 @@ static ExceptionOr> normalizeCryptoAl auto params = convertDictionary(state, value.get()); RETURN_IF_EXCEPTION(scope, Exception { ExistingExceptionError }); auto hashIdentifier = toHashIdentifier(state, params.hash); - if (hashIdentifier.hasException()) - return hashIdentifier.releaseException(); + RETURN_IF_EXCEPTION(scope, Exception { ExistingExceptionError }); + if (hashIdentifier.hasException()) return hashIdentifier.releaseException(); params.hashIdentifier = hashIdentifier.releaseReturnValue(); result = makeUnique(params); break; @@ -334,8 +334,8 @@ static ExceptionOr> normalizeCryptoAl auto params = convertDictionary(state, value.get()); RETURN_IF_EXCEPTION(scope, Exception { ExistingExceptionError }); auto hashIdentifier = toHashIdentifier(state, params.hash); - if (hashIdentifier.hasException()) - return hashIdentifier.releaseException(); + RETURN_IF_EXCEPTION(scope, Exception { ExistingExceptionError }); + if (hashIdentifier.hasException()) return hashIdentifier.releaseException(); params.hashIdentifier = hashIdentifier.releaseReturnValue(); result = makeUnique(params); break; @@ -353,8 +353,8 @@ static ExceptionOr> normalizeCryptoAl auto params = convertDictionary(state, value.get()); RETURN_IF_EXCEPTION(scope, Exception { ExistingExceptionError }); auto hashIdentifier = toHashIdentifier(state, params.hash); - if (hashIdentifier.hasException()) - return hashIdentifier.releaseException(); + RETURN_IF_EXCEPTION(scope, Exception { ExistingExceptionError }); + if (hashIdentifier.hasException()) return hashIdentifier.releaseException(); params.hashIdentifier = hashIdentifier.releaseReturnValue(); result = makeUnique(params); break; @@ -407,8 +407,8 @@ static ExceptionOr> normalizeCryptoAl auto params = convertDictionary(state, value.get()); RETURN_IF_EXCEPTION(scope, Exception { ExistingExceptionError }); auto hashIdentifier = toHashIdentifier(state, params.hash); - if (hashIdentifier.hasException()) - return hashIdentifier.releaseException(); + RETURN_IF_EXCEPTION(scope, Exception { ExistingExceptionError }); + if (hashIdentifier.hasException()) return hashIdentifier.releaseException(); params.hashIdentifier = hashIdentifier.releaseReturnValue(); result = makeUnique(params); break; @@ -647,6 +647,9 @@ void SubtleCrypto::encrypt(JSC::JSGlobalObject& state, AlgorithmIdentifier&& alg void SubtleCrypto::decrypt(JSC::JSGlobalObject& state, AlgorithmIdentifier&& algorithmIdentifier, CryptoKey& key, BufferSource&& dataBufferSource, Ref&& promise) { + auto& vm = state.vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + addAuthenticatedEncryptionWarningIfNecessary(key.algorithmIdentifier()); auto paramsOrException = normalizeCryptoAlgorithmParameters(state, WTFMove(algorithmIdentifier), Operations::Decrypt); @@ -764,6 +767,8 @@ void SubtleCrypto::verify(JSC::JSGlobalObject& state, AlgorithmIdentifier&& algo void SubtleCrypto::digest(JSC::JSGlobalObject& state, AlgorithmIdentifier&& algorithmIdentifier, BufferSource&& dataBufferSource, Ref&& promise) { + auto& vm = state.vm(); + auto scope = DECLARE_THROW_SCOPE(vm); auto paramsOrException = normalizeCryptoAlgorithmParameters(state, WTFMove(algorithmIdentifier), Operations::Digest); if (paramsOrException.hasException()) { promise->reject(paramsOrException.releaseException().code(), "Unrecognized algorithm name"_s); @@ -792,6 +797,8 @@ void SubtleCrypto::digest(JSC::JSGlobalObject& state, AlgorithmIdentifier&& algo void SubtleCrypto::generateKey(JSC::JSGlobalObject& state, AlgorithmIdentifier&& algorithmIdentifier, bool extractable, Vector&& keyUsages, Ref&& promise) { + auto& vm = state.vm(); + auto scope = DECLARE_THROW_SCOPE(vm); auto paramsOrException = normalizeCryptoAlgorithmParameters(state, WTFMove(algorithmIdentifier), Operations::GenerateKey); if (paramsOrException.hasException()) { promise->reject(paramsOrException.releaseException()); @@ -834,7 +841,7 @@ void SubtleCrypto::generateKey(JSC::JSGlobalObject& state, AlgorithmIdentifier&& // The 26 January 2017 version of the specification suggests we should perform the following task asynchronously // regardless what kind of keys it produces: https://www.w3.org/TR/WebCryptoAPI/#SubtleCrypto-method-generateKey // That's simply not efficient for AES, HMAC and EC keys. Therefore, we perform it as an async task only for RSA keys. - algorithm->generateKey(*params, extractable, keyUsagesBitmap, WTFMove(callback), WTFMove(exceptionCallback), *scriptExecutionContext()); + RELEASE_AND_RETURN(scope, algorithm->generateKey(*params, extractable, keyUsagesBitmap, WTFMove(callback), WTFMove(exceptionCallback), *scriptExecutionContext())); } void SubtleCrypto::deriveKey(JSC::JSGlobalObject& state, AlgorithmIdentifier&& algorithmIdentifier, CryptoKey& baseKey, AlgorithmIdentifier&& derivedKeyType, bool extractable, Vector&& keyUsages, Ref&& promise) @@ -952,6 +959,8 @@ void SubtleCrypto::deriveBits(JSC::JSGlobalObject& state, AlgorithmIdentifier&& void SubtleCrypto::importKey(JSC::JSGlobalObject& state, KeyFormat format, KeyDataVariant&& keyDataVariant, AlgorithmIdentifier&& algorithmIdentifier, bool extractable, Vector&& keyUsages, Ref&& promise) { + auto& vm = state.vm(); + auto scope = DECLARE_THROW_SCOPE(vm); auto paramsOrException = normalizeCryptoAlgorithmParameters(state, WTFMove(algorithmIdentifier), Operations::ImportKey); if (paramsOrException.hasException()) { promise->reject(paramsOrException.releaseException()); @@ -990,7 +999,7 @@ void SubtleCrypto::importKey(JSC::JSGlobalObject& state, KeyFormat format, KeyDa // The 11 December 2014 version of the specification suggests we should perform the following task asynchronously: // https://www.w3.org/TR/WebCryptoAPI/#SubtleCrypto-method-importKey // It is not beneficial for less time consuming operations. Therefore, we perform it synchronously. - algorithm->importKey(format, WTFMove(keyData), *params, extractable, keyUsagesBitmap, WTFMove(callback), WTFMove(exceptionCallback)); + RELEASE_AND_RETURN(scope, algorithm->importKey(format, WTFMove(keyData), *params, extractable, keyUsagesBitmap, WTFMove(callback), WTFMove(exceptionCallback))); } void SubtleCrypto::exportKey(KeyFormat format, CryptoKey& key, Ref&& promise) diff --git a/src/bun.js/event_loop/CppTask.zig b/src/bun.js/event_loop/CppTask.zig index 494da262fa..daf2b5a7bd 100644 --- a/src/bun.js/event_loop/CppTask.zig +++ b/src/bun.js/event_loop/CppTask.zig @@ -3,7 +3,9 @@ pub const CppTask = opaque { extern fn Bun__performTask(globalObject: *JSC.JSGlobalObject, task: *CppTask) void; pub fn run(this: *CppTask, global: *JSC.JSGlobalObject) void { JSC.markBinding(@src()); - Bun__performTask(global, this); + bun.jsc.fromJSHostCallGeneric(global, @src(), Bun__performTask, .{ global, this }) catch |err| { + _ = global.reportUncaughtException(global.takeException(err).asException(global.vm()).?); + }; } }; diff --git a/src/bun.js/javascript_core_c_api.zig b/src/bun.js/javascript_core_c_api.zig index a7bc6c6223..3510a2123e 100644 --- a/src/bun.js/javascript_core_c_api.zig +++ b/src/bun.js/javascript_core_c_api.zig @@ -117,7 +117,6 @@ pub extern "c" fn JSObjectCallAsConstructor(ctx: *JSC.JSGlobalObject, object: JS pub extern "c" fn JSObjectMakeDate(ctx: *JSC.JSGlobalObject, argumentCount: usize, arguments: [*c]const JSValueRef, exception: ExceptionRef) JSObjectRef; pub const JSChar = u16; pub extern fn JSObjectMakeTypedArray(ctx: *JSC.JSGlobalObject, arrayType: JSTypedArrayType, length: usize, exception: ExceptionRef) JSObjectRef; -pub extern fn JSObjectMakeTypedArrayWithBytesNoCopy(ctx: *JSC.JSGlobalObject, arrayType: JSTypedArrayType, bytes: ?*anyopaque, byteLength: usize, bytesDeallocator: JSTypedArrayBytesDeallocator, deallocatorContext: ?*anyopaque, exception: ExceptionRef) JSObjectRef; pub extern fn JSObjectMakeTypedArrayWithArrayBuffer(ctx: *JSC.JSGlobalObject, arrayType: JSTypedArrayType, buffer: JSObjectRef, exception: ExceptionRef) JSObjectRef; pub extern fn JSObjectMakeTypedArrayWithArrayBufferAndOffset(ctx: *JSC.JSGlobalObject, arrayType: JSTypedArrayType, buffer: JSObjectRef, byteOffset: usize, length: usize, exception: ExceptionRef) JSObjectRef; pub extern fn JSObjectGetTypedArrayBytesPtr(ctx: *JSC.JSGlobalObject, object: JSObjectRef, exception: ExceptionRef) ?*anyopaque; @@ -125,7 +124,6 @@ pub extern fn JSObjectGetTypedArrayLength(ctx: *JSC.JSGlobalObject, object: JSOb pub extern fn JSObjectGetTypedArrayByteLength(ctx: *JSC.JSGlobalObject, object: JSObjectRef, exception: ExceptionRef) usize; pub extern fn JSObjectGetTypedArrayByteOffset(ctx: *JSC.JSGlobalObject, object: JSObjectRef, exception: ExceptionRef) usize; pub extern fn JSObjectGetTypedArrayBuffer(ctx: *JSC.JSGlobalObject, object: JSObjectRef, exception: ExceptionRef) JSObjectRef; -pub extern fn JSObjectMakeArrayBufferWithBytesNoCopy(ctx: *JSC.JSGlobalObject, bytes: ?*anyopaque, byteLength: usize, bytesDeallocator: JSTypedArrayBytesDeallocator, deallocatorContext: ?*anyopaque, exception: ExceptionRef) JSObjectRef; pub extern fn JSObjectGetArrayBufferBytesPtr(ctx: *JSC.JSGlobalObject, object: JSObjectRef, exception: ExceptionRef) ?*anyopaque; pub extern fn JSObjectGetArrayBufferByteLength(ctx: *JSC.JSGlobalObject, object: JSObjectRef, exception: ExceptionRef) usize; pub const OpaqueJSContextGroup = struct_OpaqueJSContextGroup; diff --git a/src/bun.js/jsc/array_buffer.zig b/src/bun.js/jsc/array_buffer.zig index aafb6a04ea..2b9d47fffe 100644 --- a/src/bun.js/jsc/array_buffer.zig +++ b/src/bun.js/jsc/array_buffer.zig @@ -210,8 +210,7 @@ pub const ArrayBuffer = extern struct { return ArrayBuffer{ .offset = 0, .len = @as(u32, @intCast(bytes.len)), .byte_len = @as(u32, @intCast(bytes.len)), .typed_array_type = typed_array_type, .ptr = bytes.ptr }; } - pub fn toJSUnchecked(this: ArrayBuffer, ctx: *JSC.JSGlobalObject, exception: JSC.C.ExceptionRef) bun.JSError!JSC.JSValue { - + pub fn toJSUnchecked(this: ArrayBuffer, ctx: *JSC.JSGlobalObject) bun.JSError!JSC.JSValue { // The reason for this is // JSC C API returns a detached arraybuffer // if you pass it a zero-length TypedArray @@ -230,30 +229,28 @@ pub const ArrayBuffer = extern struct { } if (this.typed_array_type == .ArrayBuffer) { - return JSC.JSValue.fromRef(JSC.C.JSObjectMakeArrayBufferWithBytesNoCopy( + return makeArrayBufferWithBytesNoCopy( ctx, this.ptr, this.byte_len, MarkedArrayBuffer_deallocator, @as(*anyopaque, @ptrFromInt(@intFromPtr(&bun.default_allocator))), - exception, - )); + ); } - return JSC.JSValue.fromRef(JSC.C.JSObjectMakeTypedArrayWithBytesNoCopy( + return makeTypedArrayWithBytesNoCopy( ctx, - this.typed_array_type.toC(), + this.typed_array_type.toTypedArrayType(), this.ptr, this.byte_len, MarkedArrayBuffer_deallocator, @as(*anyopaque, @ptrFromInt(@intFromPtr(&bun.default_allocator))), - exception, - )); + ); } const log = Output.scoped(.ArrayBuffer, false); - pub fn toJS(this: ArrayBuffer, ctx: *JSC.JSGlobalObject, exception: JSC.C.ExceptionRef) bun.JSError!JSC.JSValue { + pub fn toJS(this: ArrayBuffer, ctx: *JSC.JSGlobalObject) bun.JSError!JSC.JSValue { if (this.value != .zero) { return this.value; } @@ -263,28 +260,26 @@ pub const ArrayBuffer = extern struct { log("toJS but will never free: {d} bytes", .{this.len}); if (this.typed_array_type == .ArrayBuffer) { - return JSC.JSValue.fromRef(JSC.C.JSObjectMakeArrayBufferWithBytesNoCopy( + return makeArrayBufferWithBytesNoCopy( ctx, this.ptr, this.byte_len, null, null, - exception, - )); + ); } - return JSC.JSValue.fromRef(JSC.C.JSObjectMakeTypedArrayWithBytesNoCopy( + return makeTypedArrayWithBytesNoCopy( ctx, - this.typed_array_type.toC(), + this.typed_array_type.toTypedArrayType(), this.ptr, this.byte_len, null, null, - exception, - )); + ); } - return this.toJSUnchecked(ctx, exception); + return this.toJSUnchecked(ctx); } pub fn toJSWithContext( @@ -292,32 +287,29 @@ pub const ArrayBuffer = extern struct { ctx: *JSC.JSGlobalObject, deallocator: ?*anyopaque, callback: JSC.C.JSTypedArrayBytesDeallocator, - exception: JSC.C.ExceptionRef, - ) JSC.JSValue { + ) bun.JSError!JSC.JSValue { if (this.value != .zero) { return this.value; } if (this.typed_array_type == .ArrayBuffer) { - return JSC.JSValue.fromRef(JSC.C.JSObjectMakeArrayBufferWithBytesNoCopy( + return makeArrayBufferWithBytesNoCopy( ctx, this.ptr, this.byte_len, callback, deallocator, - exception, - )); + ); } - return JSC.JSValue.fromRef(JSC.C.JSObjectMakeTypedArrayWithBytesNoCopy( + return makeTypedArrayWithBytesNoCopy( ctx, - this.typed_array_type.toC(), + this.typed_array_type.toTypedArrayType(), this.ptr, this.byte_len, callback, deallocator, - exception, - )); + ); } pub const fromArrayBuffer = fromTypedArray; @@ -354,6 +346,7 @@ pub const ArrayBuffer = extern struct { Buffer, ArrayBuffer, Uint8Array, + Uint8ClampedArray, Uint16Array, Uint32Array, Int8Array, @@ -362,6 +355,8 @@ pub const ArrayBuffer = extern struct { Float16Array, Float32Array, Float64Array, + BigInt64Array, + BigUint64Array, // DataView, pub fn toJSType(this: BinaryType) JSC.JSValue.JSType { @@ -378,11 +373,29 @@ pub const ArrayBuffer = extern struct { .Uint16Array => .Uint16Array, .Uint32Array => .Uint32Array, .Uint8Array => .Uint8Array, + .Uint8ClampedArray => .Uint8ClampedArray, + .BigInt64Array => .BigInt64Array, + .BigUint64Array => .BigUint64Array, }; } - pub fn toTypedArrayType(this: BinaryType) JSC.C.JSTypedArrayType { - return this.toJSType().toC(); + pub fn toTypedArrayType(this: BinaryType) TypedArrayType { + return switch (this) { + .Buffer => .TypeNone, + .ArrayBuffer => .TypeNone, + .Int8Array => .TypeInt8, + .Int16Array => .TypeInt16, + .Int32Array => .TypeInt32, + .Uint8Array => .TypeUint8, + .Uint8ClampedArray => .TypeUint8Clamped, + .Uint16Array => .TypeUint16, + .Uint32Array => .TypeUint32, + .Float16Array => .TypeFloat16, + .Float32Array => .TypeFloat32, + .Float64Array => .TypeFloat64, + .BigInt64Array => .TypeBigInt64, + .BigUint64Array => .TypeBigUint64, + }; } pub const Map = bun.ComptimeStringMap( @@ -436,13 +449,80 @@ pub const ArrayBuffer = extern struct { .Uint8Array => return JSC.ArrayBuffer.create(globalThis, bytes, .Uint8Array), // These aren't documented, but they are supported - .Uint16Array, .Uint32Array, .Int8Array, .Int16Array, .Int32Array, .Float16Array, .Float32Array, .Float64Array => { + .Uint8ClampedArray, + .Uint16Array, + .Uint32Array, + .Int8Array, + .Int16Array, + .Int32Array, + .Float16Array, + .Float32Array, + .Float64Array, + .BigInt64Array, + .BigUint64Array, + => { const buffer = try JSC.ArrayBuffer.create(globalThis, bytes, .ArrayBuffer); - return JSC.JSValue.c(JSC.C.JSObjectMakeTypedArrayWithArrayBuffer(globalThis, this.toTypedArrayType(), buffer.asObjectRef(), null)); + return JSC.JSValue.c(JSC.C.JSObjectMakeTypedArrayWithArrayBuffer(globalThis, this.toTypedArrayType().toC(), buffer.asObjectRef(), null)); }, } } }; + + // Note: keep in sync wih + pub const TypedArrayType = enum(u8) { + TypeNone, + TypeInt8, + TypeUint8, + TypeUint8Clamped, + TypeInt16, + TypeUint16, + TypeInt32, + TypeUint32, + TypeFloat16, + TypeFloat32, + TypeFloat64, + TypeBigInt64, + TypeBigUint64, + TypeDataView, + + pub fn toC(this: TypedArrayType) JSC.C.JSTypedArrayType { + return switch (this) { + .TypeNone => .kJSTypedArrayTypeNone, + .TypeInt8 => .kJSTypedArrayTypeInt8Array, + .TypeInt16 => .kJSTypedArrayTypeInt16Array, + .TypeInt32 => .kJSTypedArrayTypeInt32Array, + .TypeUint8 => .kJSTypedArrayTypeUint8Array, + .TypeUint8Clamped => .kJSTypedArrayTypeUint8ClampedArray, + .TypeUint16 => .kJSTypedArrayTypeUint16Array, + .TypeUint32 => .kJSTypedArrayTypeUint32Array, + .TypeFloat16 => .kJSTypedArrayTypeNone, + .TypeFloat32 => .kJSTypedArrayTypeFloat32Array, + .TypeFloat64 => .kJSTypedArrayTypeFloat64Array, + .TypeBigInt64 => .kJSTypedArrayTypeBigInt64Array, + .TypeBigUint64 => .kJSTypedArrayTypeBigUint64Array, + .TypeDataView => .kJSTypedArrayTypeNone, + }; + } + + pub fn toNapi(this: TypedArrayType) ?bun.api.napi.napi_typedarray_type { + return switch (this) { + .TypeNone => null, + .TypeInt8 => .int8_array, + .TypeInt16 => .int16_array, + .TypeInt32 => .int32_array, + .TypeUint8 => .uint8_array, + .TypeUint8Clamped => .uint8_clamped_array, + .TypeUint16 => .uint16_array, + .TypeUint32 => .uint32_array, + .TypeFloat16 => null, + .TypeFloat32 => .float32_array, + .TypeFloat64 => .float64_array, + .TypeBigInt64 => .bigint64_array, + .TypeBigUint64 => .biguint64_array, + .TypeDataView => null, + }; + } + }; }; pub const MarkedArrayBuffer = struct { @@ -513,42 +593,29 @@ pub const MarkedArrayBuffer = struct { return JSC.JSValue.createBufferWithCtx(ctx, this.buffer.byteSlice(), this.buffer.ptr, MarkedArrayBuffer_deallocator); } - pub fn toJSObjectRef(this: *const MarkedArrayBuffer, ctx: *JSC.JSGlobalObject, exception: JSC.C.ExceptionRef) bun.JSC.C.JSObjectRef { + pub fn toJS(this: *const MarkedArrayBuffer, globalObject: *JSC.JSGlobalObject) bun.JSError!JSC.JSValue { if (!this.buffer.value.isEmptyOrUndefinedOrNull()) { - return this.buffer.value.asObjectRef(); + return this.buffer.value; } if (this.buffer.byte_len == 0) { - return JSC.C.JSObjectMakeTypedArray( - ctx, - this.buffer.typed_array_type.toC(), + return makeTypedArrayWithBytesNoCopy( + globalObject, + this.buffer.typed_array_type.toTypedArrayType(), + null, 0, - exception, + null, + null, ); } - - return JSC.C.JSObjectMakeTypedArrayWithBytesNoCopy( - ctx, - this.buffer.typed_array_type.toC(), + return makeTypedArrayWithBytesNoCopy( + globalObject, + this.buffer.typed_array_type.toTypedArrayType(), this.buffer.ptr, - this.buffer.byte_len, MarkedArrayBuffer_deallocator, this.buffer.ptr, - exception, ); } - - // TODO: refactor this - pub fn toJS(this: *const MarkedArrayBuffer, globalObject: *JSC.JSGlobalObject) JSC.JSValue { - var exception = [_]JSC.C.JSValueRef{null}; - const obj = this.toJSObjectRef(globalObject, &exception); - - if (exception[0] != null) { - return globalObject.throwValue(JSC.JSValue.c(exception[0])) catch return .zero; - } - - return JSC.JSValue.c(obj); - } }; pub export fn MarkedArrayBuffer_deallocator(bytes_: *anyopaque, _: *anyopaque) void { @@ -578,3 +645,14 @@ const Output = bun.Output; const JSError = bun.JSError; const std = @import("std"); + +extern fn Bun__makeArrayBufferWithBytesNoCopy(*JSC.JSGlobalObject, ?*anyopaque, usize, JSC.C.JSTypedArrayBytesDeallocator, ?*anyopaque) JSC.JSValue; +extern fn Bun__makeTypedArrayWithBytesNoCopy(*JSC.JSGlobalObject, ArrayBuffer.TypedArrayType, ?*anyopaque, usize, JSC.C.JSTypedArrayBytesDeallocator, ?*anyopaque) JSC.JSValue; + +pub fn makeArrayBufferWithBytesNoCopy(globalObject: *JSC.JSGlobalObject, ptr: ?*anyopaque, len: usize, deallocator: JSC.C.JSTypedArrayBytesDeallocator, deallocatorContext: ?*anyopaque) bun.JSError!JSC.JSValue { + return bun.jsc.fromJSHostCall(globalObject, @src(), Bun__makeArrayBufferWithBytesNoCopy, .{ globalObject, ptr, len, deallocator, deallocatorContext }); +} + +pub fn makeTypedArrayWithBytesNoCopy(globalObject: *JSC.JSGlobalObject, arrayType: ArrayBuffer.TypedArrayType, ptr: ?*anyopaque, len: usize, deallocator: JSC.C.JSTypedArrayBytesDeallocator, deallocatorContext: ?*anyopaque) bun.JSError!JSC.JSValue { + return bun.jsc.fromJSHostCall(globalObject, @src(), Bun__makeTypedArrayWithBytesNoCopy, .{ globalObject, arrayType, ptr, len, deallocator, deallocatorContext }); +} diff --git a/src/bun.js/jsc/host_fn.zig b/src/bun.js/jsc/host_fn.zig index 3b8677944b..caa2556089 100644 --- a/src/bun.js/jsc/host_fn.zig +++ b/src/bun.js/jsc/host_fn.zig @@ -238,6 +238,20 @@ fn checkWrapParams(comptime func: anytype, comptime N: u8) []const std.builtin.T return params; } +/// Uses .SysV callconv on Windows. Use to satisfy SYSV_ABI requirement in JSC APIs. +/// Otherwise (when the C++ counterpart has no explicit calling convention) use wrap4. +pub fn wrap4v(comptime func: anytype) @"return": { + const p = checkWrapParams(func, 4); + break :@"return" fn (p[0].type.?, p[1].type.?, p[2].type.?, p[3].type.?) callconv(jsc.conv) JSValue; +} { + const p = @typeInfo(@TypeOf(func)).@"fn".params; + return struct { + pub fn wrapped(arg0: p[0].type.?, arg1: p[1].type.?, arg2: p[2].type.?, arg3: p[3].type.?) callconv(jsc.conv) JSValue { + return toJSHostCall(arg0, @src(), func, .{ arg0, arg1, arg2, arg3 }); + } + }.wrapped; +} + const private = struct { pub extern fn Bun__CreateFFIFunctionWithDataValue( *JSGlobalObject, diff --git a/src/bun.js/modules/BunJSCModule.h b/src/bun.js/modules/BunJSCModule.h index 7465263605..b84053a6e5 100644 --- a/src/bun.js/modules/BunJSCModule.h +++ b/src/bun.js/modules/BunJSCModule.h @@ -786,7 +786,7 @@ JSC_DEFINE_HOST_FUNCTION(functionSerialize, Vector> transferList; Vector> dummyPorts; ExceptionOr> serialized = SerializedScriptValue::create(*globalObject, value, WTFMove(transferList), dummyPorts); - + EXCEPTION_ASSERT(serialized.hasException() == !!throwScope.exception()); if (serialized.hasException()) { WebCore::propagateException(*globalObject, throwScope, serialized.releaseException()); RELEASE_AND_RETURN(throwScope, {}); @@ -804,15 +804,10 @@ JSC_DEFINE_HOST_FUNCTION(functionSerialize, } if (arrayBuffer->isShared()) { - return JSValue::encode( - JSArrayBuffer::create(vm, - globalObject->arrayBufferStructureWithSharingMode< - ArrayBufferSharingMode::Shared>(), - WTFMove(arrayBuffer))); + return JSValue::encode(JSArrayBuffer::create(vm, globalObject->arrayBufferStructureWithSharingMode(), WTFMove(arrayBuffer))); } - return JSValue::encode(JSArrayBuffer::create( - vm, globalObject->arrayBufferStructure(), WTFMove(arrayBuffer))); + return JSValue::encode(JSArrayBuffer::create(vm, globalObject->arrayBufferStructure(), WTFMove(arrayBuffer))); } JSC_DEFINE_HOST_FUNCTION(functionDeserialize, (JSGlobalObject * globalObject, CallFrame* callFrame)) { @@ -823,17 +818,12 @@ JSC_DEFINE_HOST_FUNCTION(functionDeserialize, (JSGlobalObject * globalObject, Ca JSValue result; if (auto* jsArrayBuffer = jsDynamicCast(value)) { - result = SerializedScriptValue::fromArrayBuffer( - *globalObject, globalObject, jsArrayBuffer->impl(), 0, - jsArrayBuffer->impl()->byteLength()); + result = SerializedScriptValue::fromArrayBuffer(*globalObject, globalObject, jsArrayBuffer->impl(), 0, jsArrayBuffer->impl()->byteLength()); } else if (auto* view = jsDynamicCast(value)) { auto arrayBuffer = view->possiblySharedImpl()->possiblySharedBuffer(); - result = SerializedScriptValue::fromArrayBuffer( - *globalObject, globalObject, arrayBuffer.get(), view->byteOffset(), - view->byteLength()); + result = SerializedScriptValue::fromArrayBuffer(*globalObject, globalObject, arrayBuffer.get(), view->byteOffset(), view->byteLength()); } else { - throwTypeError(globalObject, throwScope, - "First argument must be an ArrayBuffer"_s); + throwTypeError(globalObject, throwScope, "First argument must be an ArrayBuffer"_s); return {}; } diff --git a/src/bun.js/modules/NodeModuleModule.cpp b/src/bun.js/modules/NodeModuleModule.cpp index ffafec3306..67c8de6780 100644 --- a/src/bun.js/modules/NodeModuleModule.cpp +++ b/src/bun.js/modules/NodeModuleModule.cpp @@ -721,10 +721,10 @@ JSC_DEFINE_HOST_FUNCTION(jsFunctionRunMain, (JSGlobalObject * globalObject, JSC: auto* promise = JSC::loadAndEvaluateModule(globalObject, name, JSC::jsUndefined(), JSC::jsUndefined()); RETURN_IF_EXCEPTION(scope, {}); - JSC::JSNativeStdFunction* resolverFunction = JSC::JSNativeStdFunction::create( - vm, globalObject, 1, String(), resolverFunctionCallback); + JSC::JSNativeStdFunction* resolverFunction = JSC::JSNativeStdFunction::create(vm, globalObject, 1, String(), resolverFunctionCallback); auto result = promise->then(globalObject, resolverFunction, nullptr); + RETURN_IF_EXCEPTION(scope, {}); Bun__VirtualMachine__setOverrideModuleRunMainPromise(defaultGlobalObject(globalObject)->bunVM(), result); return JSC::JSValue::encode(JSC::jsUndefined()); diff --git a/src/bun.js/modules/NodeProcessModule.h b/src/bun.js/modules/NodeProcessModule.h index 7022433828..1f74843ac8 100644 --- a/src/bun.js/modules/NodeProcessModule.h +++ b/src/bun.js/modules/NodeProcessModule.h @@ -15,14 +15,12 @@ DEFINE_NATIVE_MODULE(NodeProcess) Bun::Process* process = globalObject->processObject(); if (!process->staticPropertiesReified()) { process->reifyAllStaticProperties(globalObject); - if (scope.exception()) [[unlikely]] - return; + RETURN_IF_EXCEPTION(scope, ); } PropertyNameArray properties(vm, PropertyNameMode::Strings, PrivateSymbolMode::Exclude); process->getPropertyNames(globalObject, properties, DontEnumPropertiesMode::Exclude); - if (scope.exception()) [[unlikely]] - return; + RETURN_IF_EXCEPTION(scope, ); exportNames.append(vm.propertyNames->defaultKeyword); exportValues.append(process); diff --git a/src/bun.js/modules/NodeUtilTypesModule.cpp b/src/bun.js/modules/NodeUtilTypesModule.cpp index f89b9cc808..f932a7c966 100644 --- a/src/bun.js/modules/NodeUtilTypesModule.cpp +++ b/src/bun.js/modules/NodeUtilTypesModule.cpp @@ -132,8 +132,7 @@ JSC_DEFINE_HOST_FUNCTION(jsFunctionIsError, JSValue value = slot.getValue(globalObject, vm.propertyNames->toStringTagSymbol); if (value.isString()) { String tag = asString(value)->value(globalObject); - if (scope.exception()) [[unlikely]] - scope.clearException(); + CLEAR_IF_EXCEPTION(scope); if (tag == "Error"_s) return JSValue::encode(jsBoolean(true)); } diff --git a/src/bun.js/node.zig b/src/bun.js/node.zig index 83cde3e878..9fda22ac8a 100644 --- a/src/bun.js/node.zig +++ b/src/bun.js/node.zig @@ -201,8 +201,8 @@ pub fn Maybe(comptime ReturnTypeT: type, comptime ErrorTypeT: type) type { void => .js_undefined, bool => JSC.JSValue.jsBoolean(r), - JSC.ArrayBuffer => r.toJS(globalObject, null), - []u8 => JSC.ArrayBuffer.fromBytes(r, .ArrayBuffer).toJS(globalObject, null), + JSC.ArrayBuffer => r.toJS(globalObject), + []u8 => JSC.ArrayBuffer.fromBytes(r, .ArrayBuffer).toJS(globalObject), else => switch (@typeInfo(ReturnType)) { .int, .float, .comptime_int, .comptime_float => JSC.JSValue.jsNumber(r), diff --git a/src/bun.js/node/net/BlockList.zig b/src/bun.js/node/net/BlockList.zig index f14da10a81..fa606c21c9 100644 --- a/src/bun.js/node/net/BlockList.zig +++ b/src/bun.js/node/net/BlockList.zig @@ -170,16 +170,16 @@ pub fn rules(this: *@This(), globalThis: *JSC.JSGlobalObject) bun.JSError!JSC.JS switch (rule) { .addr => |a| { var buf: [SocketAddress.inet.INET6_ADDRSTRLEN]u8 = @splat(0); - list.appendAssumeCapacity(bun.String.createFormatForJS(globalThis, "Address: {s} {s}", .{ a.family().upper(), a.fmt(&buf) })); + list.appendAssumeCapacity(try bun.String.createFormatForJS(globalThis, "Address: {s} {s}", .{ a.family().upper(), a.fmt(&buf) })); }, .range => |r| { var buf_s: [SocketAddress.inet.INET6_ADDRSTRLEN]u8 = @splat(0); var buf_e: [SocketAddress.inet.INET6_ADDRSTRLEN]u8 = @splat(0); - list.appendAssumeCapacity(bun.String.createFormatForJS(globalThis, "Range: {s} {s}-{s}", .{ r.start.family().upper(), r.start.fmt(&buf_s), r.end.fmt(&buf_e) })); + list.appendAssumeCapacity(try bun.String.createFormatForJS(globalThis, "Range: {s} {s}-{s}", .{ r.start.family().upper(), r.start.fmt(&buf_s), r.end.fmt(&buf_e) })); }, .subnet => |s| { var buf: [SocketAddress.inet.INET6_ADDRSTRLEN]u8 = @splat(0); - list.appendAssumeCapacity(bun.String.createFormatForJS(globalThis, "Subnet: {s} {s}/{d}", .{ s.network.family().upper(), s.network.fmt(&buf), s.prefix })); + list.appendAssumeCapacity(try bun.String.createFormatForJS(globalThis, "Subnet: {s} {s}/{d}", .{ s.network.family().upper(), s.network.fmt(&buf), s.prefix })); }, } } diff --git a/src/bun.js/node/node_crypto_binding.zig b/src/bun.js/node/node_crypto_binding.zig index df0f5313cf..45d41b6a59 100644 --- a/src/bun.js/node/node_crypto_binding.zig +++ b/src/bun.js/node/node_crypto_binding.zig @@ -27,8 +27,14 @@ fn ExternCryptoJob(comptime name: []const u8) type { const Ctx = opaque { const ctx_name = name ++ "Ctx"; + pub const runTask = @extern(*const fn (*Ctx, *JSGlobalObject) callconv(.c) void, .{ .name = "Bun__" ++ ctx_name ++ "__runTask" }).*; - pub const runFromJS = @extern(*const fn (*Ctx, *JSGlobalObject, JSValue) callconv(.c) void, .{ .name = "Bun__" ++ ctx_name ++ "__runFromJS" }).*; + + pub fn runFromJS(self: *Ctx, global: *JSGlobalObject, callback: JSValue) bun.JSError!void { + const __runFromJS = @extern(*const fn (*Ctx, *JSGlobalObject, JSValue) callconv(.c) void, .{ .name = "Bun__" ++ ctx_name ++ "__runFromJS" }).*; + return bun.jsc.fromJSHostCallGeneric(global, @src(), __runFromJS, .{ self, global, callback }); + } + pub const deinit = @extern(*const fn (*Ctx) callconv(.c) void, .{ .name = "Bun__" ++ ctx_name ++ "__deinit" }).*; }; @@ -72,7 +78,9 @@ fn ExternCryptoJob(comptime name: []const u8) type { return; }; - this.ctx.runFromJS(vm.global, callback); + this.ctx.runFromJS(vm.global, callback) catch |err| { + _ = vm.global.reportUncaughtException(vm.global.takeException(err).asException(vm.global.vm()).?); + }; } fn deinit(this: *@This()) void { @@ -514,7 +522,7 @@ fn getHashes(global: *JSGlobalObject, _: *JSC.CallFrame) JSError!JSValue { const array = try JSValue.createEmptyArray(global, hashes.count()); for (hashes.keys(), 0..) |hash, i| { - const str = String.createUTF8ForJS(global, hash); + const str = try String.createUTF8ForJS(global, hash); try array.putIndex(global, @intCast(i), str); } diff --git a/src/bun.js/node/node_util_binding.zig b/src/bun.js/node/node_util_binding.zig index 78e0791b8d..4b33e4f7aa 100644 --- a/src/bun.js/node/node_util_binding.zig +++ b/src/bun.js/node/node_util_binding.zig @@ -229,7 +229,7 @@ pub fn parseEnv(globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) bun. var obj = JSC.JSValue.createEmptyObject(globalThis, map.map.count()); for (map.map.keys(), map.map.values()) |k, v| { - obj.put(globalThis, JSC.ZigString.initUTF8(k), bun.String.createUTF8ForJS(globalThis, v.value)); + obj.put(globalThis, JSC.ZigString.initUTF8(k), try bun.String.createUTF8ForJS(globalThis, v.value)); } return obj; } diff --git a/src/bun.js/node/path.zig b/src/bun.js/node/path.zig index fe7fe3966d..dbbf45682b 100644 --- a/src/bun.js/node/path.zig +++ b/src/bun.js/node/path.zig @@ -83,13 +83,13 @@ fn PathParsed(comptime T: type) type { ext: []const T = "", name: []const T = "", - pub fn toJSObject(this: @This(), globalObject: *JSC.JSGlobalObject) JSC.JSValue { + pub fn toJSObject(this: @This(), globalObject: *JSC.JSGlobalObject) bun.JSError!JSC.JSValue { var jsObject = JSC.JSValue.createEmptyObject(globalObject, 5); - jsObject.put(globalObject, JSC.ZigString.static("root"), bun.String.createUTF8ForJS(globalObject, this.root)); - jsObject.put(globalObject, JSC.ZigString.static("dir"), bun.String.createUTF8ForJS(globalObject, this.dir)); - jsObject.put(globalObject, JSC.ZigString.static("base"), bun.String.createUTF8ForJS(globalObject, this.base)); - jsObject.put(globalObject, JSC.ZigString.static("ext"), bun.String.createUTF8ForJS(globalObject, this.ext)); - jsObject.put(globalObject, JSC.ZigString.static("name"), bun.String.createUTF8ForJS(globalObject, this.name)); + jsObject.put(globalObject, JSC.ZigString.static("root"), try bun.String.createUTF8ForJS(globalObject, this.root)); + jsObject.put(globalObject, JSC.ZigString.static("dir"), try bun.String.createUTF8ForJS(globalObject, this.dir)); + jsObject.put(globalObject, JSC.ZigString.static("base"), try bun.String.createUTF8ForJS(globalObject, this.base)); + jsObject.put(globalObject, JSC.ZigString.static("ext"), try bun.String.createUTF8ForJS(globalObject, this.ext)); + jsObject.put(globalObject, JSC.ZigString.static("name"), try bun.String.createUTF8ForJS(globalObject, this.name)); return jsObject; } }; @@ -417,39 +417,34 @@ pub fn basenameWindowsT(comptime T: type, path: []const T, suffix: ?[]const T) [ &.{}; } -pub inline fn basenamePosixJS_T(comptime T: type, globalObject: *JSC.JSGlobalObject, path: []const T, suffix: ?[]const T) JSC.JSValue { +pub fn basenamePosixJS_T(comptime T: type, globalObject: *JSC.JSGlobalObject, path: []const T, suffix: ?[]const T) bun.JSError!JSC.JSValue { return bun.String.createUTF8ForJS(globalObject, basenamePosixT(T, path, suffix)); } -pub inline fn basenameWindowsJS_T(comptime T: type, globalObject: *JSC.JSGlobalObject, path: []const T, suffix: ?[]const T) JSC.JSValue { +pub fn basenameWindowsJS_T(comptime T: type, globalObject: *JSC.JSGlobalObject, path: []const T, suffix: ?[]const T) bun.JSError!JSC.JSValue { return bun.String.createUTF8ForJS(globalObject, basenameWindowsT(T, path, suffix)); } -pub inline fn basenameJS_T(comptime T: type, globalObject: *JSC.JSGlobalObject, isWindows: bool, path: []const T, suffix: ?[]const T) JSC.JSValue { +pub fn basenameJS_T(comptime T: type, globalObject: *JSC.JSGlobalObject, isWindows: bool, path: []const T, suffix: ?[]const T) bun.JSError!JSC.JSValue { return if (isWindows) basenameWindowsJS_T(T, globalObject, path, suffix) else basenamePosixJS_T(T, globalObject, path, suffix); } -pub fn basename(globalObject: *JSC.JSGlobalObject, isWindows: bool, args_ptr: [*]JSC.JSValue, args_len: u16) callconv(JSC.conv) JSC.JSValue { +pub fn basename(globalObject: *JSC.JSGlobalObject, isWindows: bool, args_ptr: [*]JSC.JSValue, args_len: u16) bun.JSError!JSC.JSValue { const suffix_ptr: ?JSC.JSValue = if (args_len > 1 and !args_ptr[1].isUndefined()) args_ptr[1] else null; if (suffix_ptr) |_suffix_ptr| { // Supress exeption in zig. It does globalThis.vm().throwError() in JS land. - validateString(globalObject, _suffix_ptr, "ext", .{}) catch { - // Returning .zero translates to a nullprt JSC.JSValue. - return .zero; - }; + try validateString(globalObject, _suffix_ptr, "ext", .{}); } const path_ptr: JSC.JSValue = if (args_len > 0) args_ptr[0] else .js_undefined; // Supress exeption in zig. It does globalThis.vm().throwError() in JS land. - validateString(globalObject, path_ptr, "path", .{}) catch { - return .zero; - }; + try validateString(globalObject, path_ptr, "path", .{}); - const pathZStr = path_ptr.getZigString(globalObject) catch return .zero; + const pathZStr = try path_ptr.getZigString(globalObject); if (pathZStr.len == 0) return path_ptr; var stack_fallback = std.heap.stackFallback(stack_fallback_size_small, bun.default_allocator); @@ -460,7 +455,7 @@ pub fn basename(globalObject: *JSC.JSGlobalObject, isWindows: bool, args_ptr: [* var suffixZSlice: ?JSC.ZigString.Slice = null; if (suffix_ptr) |_suffix_ptr| { - const suffixZStr = _suffix_ptr.getZigString(globalObject) catch return .zero; + const suffixZStr = try _suffix_ptr.getZigString(globalObject); if (suffixZStr.len > 0 and suffixZStr.len <= pathZStr.len) { suffixZSlice = suffixZStr.toSlice(allocator); } @@ -618,30 +613,27 @@ pub fn dirnameWindowsT(comptime T: type, path: []const T) []const T { comptime L(T, CHAR_STR_DOT); } -pub inline fn dirnamePosixJS_T(comptime T: type, globalObject: *JSC.JSGlobalObject, path: []const T) JSC.JSValue { +pub fn dirnamePosixJS_T(comptime T: type, globalObject: *JSC.JSGlobalObject, path: []const T) bun.JSError!JSC.JSValue { return bun.String.createUTF8ForJS(globalObject, dirnamePosixT(T, path)); } -pub inline fn dirnameWindowsJS_T(comptime T: type, globalObject: *JSC.JSGlobalObject, path: []const T) JSC.JSValue { +pub fn dirnameWindowsJS_T(comptime T: type, globalObject: *JSC.JSGlobalObject, path: []const T) bun.JSError!JSC.JSValue { return bun.String.createUTF8ForJS(globalObject, dirnameWindowsT(T, path)); } -pub inline fn dirnameJS_T(comptime T: type, globalObject: *JSC.JSGlobalObject, isWindows: bool, path: []const T) JSC.JSValue { +pub fn dirnameJS_T(comptime T: type, globalObject: *JSC.JSGlobalObject, isWindows: bool, path: []const T) bun.JSError!JSC.JSValue { return if (isWindows) dirnameWindowsJS_T(T, globalObject, path) else dirnamePosixJS_T(T, globalObject, path); } -pub fn dirname(globalObject: *JSC.JSGlobalObject, isWindows: bool, args_ptr: [*]JSC.JSValue, args_len: u16) callconv(JSC.conv) JSC.JSValue { +pub fn dirname(globalObject: *JSC.JSGlobalObject, isWindows: bool, args_ptr: [*]JSC.JSValue, args_len: u16) bun.JSError!JSC.JSValue { const path_ptr: JSC.JSValue = if (args_len > 0) args_ptr[0] else .js_undefined; // Supress exeption in zig. It does globalThis.vm().throwError() in JS land. - validateString(globalObject, path_ptr, "path", .{}) catch { - // Returning .zero translates to a nullprt JSC.JSValue. - return .zero; - }; + try validateString(globalObject, path_ptr, "path", .{}); - const pathZStr = path_ptr.getZigString(globalObject) catch return .zero; + const pathZStr = try path_ptr.getZigString(globalObject); if (pathZStr.len == 0) return bun.String.createUTF8ForJS(globalObject, CHAR_STR_DOT); var stack_fallback = std.heap.stackFallback(stack_fallback_size_small, bun.default_allocator); @@ -817,30 +809,27 @@ pub fn extnameWindowsT(comptime T: type, path: []const T) []const T { return path[_startDot.._end]; } -pub inline fn extnamePosixJS_T(comptime T: type, globalObject: *JSC.JSGlobalObject, path: []const T) JSC.JSValue { +pub fn extnamePosixJS_T(comptime T: type, globalObject: *JSC.JSGlobalObject, path: []const T) bun.JSError!JSC.JSValue { return bun.String.createUTF8ForJS(globalObject, extnamePosixT(T, path)); } -pub inline fn extnameWindowsJS_T(comptime T: type, globalObject: *JSC.JSGlobalObject, path: []const T) JSC.JSValue { +pub fn extnameWindowsJS_T(comptime T: type, globalObject: *JSC.JSGlobalObject, path: []const T) bun.JSError!JSC.JSValue { return bun.String.createUTF8ForJS(globalObject, extnameWindowsT(T, path)); } -pub inline fn extnameJS_T(comptime T: type, globalObject: *JSC.JSGlobalObject, isWindows: bool, path: []const T) JSC.JSValue { +pub fn extnameJS_T(comptime T: type, globalObject: *JSC.JSGlobalObject, isWindows: bool, path: []const T) bun.JSError!JSC.JSValue { return if (isWindows) extnameWindowsJS_T(T, globalObject, path) else extnamePosixJS_T(T, globalObject, path); } -pub fn extname(globalObject: *JSC.JSGlobalObject, isWindows: bool, args_ptr: [*]JSC.JSValue, args_len: u16) callconv(JSC.conv) JSC.JSValue { +pub fn extname(globalObject: *JSC.JSGlobalObject, isWindows: bool, args_ptr: [*]JSC.JSValue, args_len: u16) bun.JSError!JSC.JSValue { const path_ptr: JSC.JSValue = if (args_len > 0) args_ptr[0] else .js_undefined; // Supress exeption in zig. It does globalThis.vm().throwError() in JS land. - validateString(globalObject, path_ptr, "path", .{}) catch { - // Returning .zero translates to a nullprt JSC.JSValue. - return .zero; - }; + try validateString(globalObject, path_ptr, "path", .{}); - const pathZStr = path_ptr.getZigString(globalObject) catch return .zero; + const pathZStr = try path_ptr.getZigString(globalObject); if (pathZStr.len == 0) return path_ptr; var stack_fallback = std.heap.stackFallback(stack_fallback_size_small, bun.default_allocator); @@ -926,15 +915,15 @@ fn _formatT(comptime T: type, pathObject: PathParsed(T), sep: T, buf: []T) []con return buf[0..bufSize]; } -pub inline fn formatPosixJS_T(comptime T: type, globalObject: *JSC.JSGlobalObject, pathObject: PathParsed(T), buf: []T) JSC.JSValue { +pub fn formatPosixJS_T(comptime T: type, globalObject: *JSC.JSGlobalObject, pathObject: PathParsed(T), buf: []T) bun.JSError!JSC.JSValue { return bun.String.createUTF8ForJS(globalObject, _formatT(T, pathObject, CHAR_FORWARD_SLASH, buf)); } -pub inline fn formatWindowsJS_T(comptime T: type, globalObject: *JSC.JSGlobalObject, pathObject: PathParsed(T), buf: []T) JSC.JSValue { +pub fn formatWindowsJS_T(comptime T: type, globalObject: *JSC.JSGlobalObject, pathObject: PathParsed(T), buf: []T) bun.JSError!JSC.JSValue { return bun.String.createUTF8ForJS(globalObject, _formatT(T, pathObject, CHAR_BACKWARD_SLASH, buf)); } -pub fn formatJS_T(comptime T: type, globalObject: *JSC.JSGlobalObject, allocator: std.mem.Allocator, isWindows: bool, pathObject: PathParsed(T)) JSC.JSValue { +pub fn formatJS_T(comptime T: type, globalObject: *JSC.JSGlobalObject, allocator: std.mem.Allocator, isWindows: bool, pathObject: PathParsed(T)) bun.JSError!JSC.JSValue { const baseLen = pathObject.base.len; const dirLen = pathObject.dir.len; // Add one for the possible separator. @@ -949,10 +938,7 @@ pub fn formatJS_T(comptime T: type, globalObject: *JSC.JSGlobalObject, allocator pub fn format(globalObject: *JSC.JSGlobalObject, isWindows: bool, args_ptr: [*]JSC.JSValue, args_len: u16) bun.JSError!JSC.JSValue { const pathObject_ptr: JSC.JSValue = if (args_len > 0) args_ptr[0] else .js_undefined; // Supress exeption in zig. It does globalThis.vm().throwError() in JS land. - validateObject(globalObject, pathObject_ptr, "pathObject", .{}, .{}) catch { - // Returning .zero translates to a nullprt JSC.JSValue. - return .zero; - }; + try validateObject(globalObject, pathObject_ptr, "pathObject", .{}, .{}); var stack_fallback = std.heap.stackFallback(stack_fallback_size_small, bun.default_allocator); const allocator = stack_fallback.get(); @@ -1002,7 +988,7 @@ pub fn format(globalObject: *JSC.JSGlobalObject, isWindows: bool, args_ptr: [*]J /// Based on Node v21.6.1 path.posix.isAbsolute: /// https://github.com/nodejs/node/blob/6ae20aa63de78294b18d5015481485b7cd8fbb60/lib/path.js#L1159 -pub inline fn isAbsolutePosixT(comptime T: type, path: []const T) bool { +pub fn isAbsolutePosixT(comptime T: type, path: []const T) bool { // validateString of `path` is performed in pub fn isAbsolute. return path.len > 0 and path[0] == CHAR_FORWARD_SLASH; } @@ -1039,37 +1025,34 @@ pub fn isAbsoluteWindowsZigString(pathZStr: JSC.ZigString) bool { isAbsoluteWindowsT(u8, pathZStr.slice()); } -pub fn isAbsolute(globalObject: *JSC.JSGlobalObject, isWindows: bool, args_ptr: [*]JSC.JSValue, args_len: u16) callconv(JSC.conv) JSC.JSValue { +pub fn isAbsolute(globalObject: *JSC.JSGlobalObject, isWindows: bool, args_ptr: [*]JSC.JSValue, args_len: u16) bun.JSError!JSC.JSValue { const path_ptr: JSC.JSValue = if (args_len > 0) args_ptr[0] else .js_undefined; // Supress exeption in zig. It does globalThis.vm().throwError() in JS land. - validateString(globalObject, path_ptr, "path", .{}) catch { - // Returning .zero translates to a nullprt JSC.JSValue. - return .zero; - }; + try validateString(globalObject, path_ptr, "path", .{}); - const pathZStr = path_ptr.getZigString(globalObject) catch return .zero; + const pathZStr = try path_ptr.getZigString(globalObject); if (pathZStr.len == 0) return JSC.JSValue.jsBoolean(false); if (isWindows) return JSC.JSValue.jsBoolean(isAbsoluteWindowsZigString(pathZStr)); return JSC.JSValue.jsBoolean(isAbsolutePosixZigString(pathZStr)); } -pub inline fn isSepPosixT(comptime T: type, byte: T) bool { +pub fn isSepPosixT(comptime T: type, byte: T) bool { return byte == CHAR_FORWARD_SLASH; } -pub inline fn isSepWindowsT(comptime T: type, byte: T) bool { +pub fn isSepWindowsT(comptime T: type, byte: T) bool { return byte == CHAR_FORWARD_SLASH or byte == CHAR_BACKWARD_SLASH; } /// Based on Node v21.6.1 private helper isWindowsDeviceRoot: /// https://github.com/nodejs/node/blob/6ae20aa63de78294b18d5015481485b7cd8fbb60/lib/path.js#L60C10-L60C29 -pub inline fn isWindowsDeviceRootT(comptime T: type, byte: T) bool { +pub fn isWindowsDeviceRootT(comptime T: type, byte: T) bool { return (byte >= 'A' and byte <= 'Z') or (byte >= 'a' and byte <= 'z'); } /// Based on Node v21.6.1 path.posix.join: /// https://github.com/nodejs/node/blob/6ae20aa63de78294b18d5015481485b7cd8fbb60/lib/path.js#L1169 -pub inline fn joinPosixT(comptime T: type, paths: []const []const T, buf: []T, buf2: []T) []const T { +pub fn joinPosixT(comptime T: type, paths: []const []const T, buf: []T, buf2: []T) []const T { comptime validatePathT(T, "joinPosixT"); if (paths.len == 0) { @@ -1233,15 +1216,15 @@ pub fn joinWindowsT(comptime T: type, paths: []const []const T, buf: []T, buf2: return normalizeWindowsT(T, joined, buf); } -pub inline fn joinPosixJS_T(comptime T: type, globalObject: *JSC.JSGlobalObject, paths: []const []const T, buf: []T, buf2: []T) JSC.JSValue { +pub fn joinPosixJS_T(comptime T: type, globalObject: *JSC.JSGlobalObject, paths: []const []const T, buf: []T, buf2: []T) bun.JSError!JSC.JSValue { return bun.String.createUTF8ForJS(globalObject, joinPosixT(T, paths, buf, buf2)); } -pub inline fn joinWindowsJS_T(comptime T: type, globalObject: *JSC.JSGlobalObject, paths: []const []const T, buf: []T, buf2: []T) JSC.JSValue { +pub fn joinWindowsJS_T(comptime T: type, globalObject: *JSC.JSGlobalObject, paths: []const []const T, buf: []T, buf2: []T) bun.JSError!JSC.JSValue { return bun.String.createUTF8ForJS(globalObject, joinWindowsT(T, paths, buf, buf2)); } -pub fn joinJS_T(comptime T: type, globalObject: *JSC.JSGlobalObject, allocator: std.mem.Allocator, isWindows: bool, paths: []const []const T) JSC.JSValue { +pub fn joinJS_T(comptime T: type, globalObject: *JSC.JSGlobalObject, allocator: std.mem.Allocator, isWindows: bool, paths: []const []const T) bun.JSError!JSC.JSValue { // Adding 8 bytes when Windows for the possible UNC root. var bufLen: usize = if (isWindows) 8 else 0; for (paths) |path| bufLen += if (path.len > 0) path.len + 1 else path.len; @@ -1253,7 +1236,7 @@ pub fn joinJS_T(comptime T: type, globalObject: *JSC.JSGlobalObject, allocator: return if (isWindows) joinWindowsJS_T(T, globalObject, paths, buf, buf2) else joinPosixJS_T(T, globalObject, paths, buf, buf2); } -pub fn join(globalObject: *JSC.JSGlobalObject, isWindows: bool, args_ptr: [*]JSC.JSValue, args_len: u16) callconv(JSC.conv) JSC.JSValue { +pub fn join(globalObject: *JSC.JSGlobalObject, isWindows: bool, args_ptr: [*]JSC.JSValue, args_len: u16) bun.JSError!JSC.JSValue { if (args_len == 0) return bun.String.createUTF8ForJS(globalObject, CHAR_STR_DOT); var arena = bun.ArenaAllocator.init(bun.default_allocator); @@ -1267,11 +1250,8 @@ pub fn join(globalObject: *JSC.JSGlobalObject, isWindows: bool, args_ptr: [*]JSC for (0..args_len, args_ptr) |i, path_ptr| { // Supress exeption in zig. It does globalThis.vm().throwError() in JS land. - validateString(globalObject, path_ptr, "paths[{d}]", .{i}) catch { - // Returning .zero translates to a nullprt JSC.JSValue. - return .zero; - }; - const pathZStr = path_ptr.getZigString(globalObject) catch return .zero; + try validateString(globalObject, path_ptr, "paths[{d}]", .{i}); + const pathZStr = try path_ptr.getZigString(globalObject); paths[i] = if (pathZStr.len > 0) pathZStr.toSlice(allocator).slice() else ""; } return joinJS_T(u8, globalObject, allocator, isWindows, paths); @@ -1648,29 +1628,26 @@ pub fn normalizeT(comptime T: type, path: []const T, buf: []T) []const T { }; } -pub inline fn normalizePosixJS_T(comptime T: type, globalObject: *JSC.JSGlobalObject, path: []const T, buf: []T) JSC.JSValue { +pub fn normalizePosixJS_T(comptime T: type, globalObject: *JSC.JSGlobalObject, path: []const T, buf: []T) bun.JSError!JSC.JSValue { return bun.String.createUTF8ForJS(globalObject, normalizePosixT(T, path, buf)); } -pub inline fn normalizeWindowsJS_T(comptime T: type, globalObject: *JSC.JSGlobalObject, path: []const T, buf: []T) JSC.JSValue { +pub fn normalizeWindowsJS_T(comptime T: type, globalObject: *JSC.JSGlobalObject, path: []const T, buf: []T) bun.JSError!JSC.JSValue { return bun.String.createUTF8ForJS(globalObject, normalizeWindowsT(T, path, buf)); } -pub fn normalizeJS_T(comptime T: type, globalObject: *JSC.JSGlobalObject, allocator: std.mem.Allocator, isWindows: bool, path: []const T) JSC.JSValue { +pub fn normalizeJS_T(comptime T: type, globalObject: *JSC.JSGlobalObject, allocator: std.mem.Allocator, isWindows: bool, path: []const T) bun.JSError!JSC.JSValue { const bufLen = @max(path.len, PATH_SIZE(T)); const buf = allocator.alloc(T, bufLen) catch bun.outOfMemory(); defer allocator.free(buf); return if (isWindows) normalizeWindowsJS_T(T, globalObject, path, buf) else normalizePosixJS_T(T, globalObject, path, buf); } -pub fn normalize(globalObject: *JSC.JSGlobalObject, isWindows: bool, args_ptr: [*]JSC.JSValue, args_len: u16) callconv(JSC.conv) JSC.JSValue { +pub fn normalize(globalObject: *JSC.JSGlobalObject, isWindows: bool, args_ptr: [*]JSC.JSValue, args_len: u16) bun.JSError!JSC.JSValue { const path_ptr: JSC.JSValue = if (args_len > 0) args_ptr[0] else .js_undefined; // Supress exeption in zig. It does globalThis.vm().throwError() in JS land. - validateString(globalObject, path_ptr, "path", .{}) catch { - // Returning .zero translates to a nullprt JSC.JSValue. - return .zero; - }; - const pathZStr = path_ptr.getZigString(globalObject) catch return .zero; + try validateString(globalObject, path_ptr, "path", .{}); + const pathZStr = try path_ptr.getZigString(globalObject); const len = pathZStr.len; if (len == 0) return bun.String.createUTF8ForJS(globalObject, CHAR_STR_DOT); @@ -1974,27 +1951,24 @@ pub fn parseWindowsT(comptime T: type, path: []const T) PathParsed(T) { return .{ .root = root, .dir = dir, .base = base, .ext = ext, .name = _name }; } -pub inline fn parsePosixJS_T(comptime T: type, globalObject: *JSC.JSGlobalObject, path: []const T) JSC.JSValue { +pub fn parsePosixJS_T(comptime T: type, globalObject: *JSC.JSGlobalObject, path: []const T) bun.JSError!JSC.JSValue { return parsePosixT(T, path).toJSObject(globalObject); } -pub inline fn parseWindowsJS_T(comptime T: type, globalObject: *JSC.JSGlobalObject, path: []const T) JSC.JSValue { +pub fn parseWindowsJS_T(comptime T: type, globalObject: *JSC.JSGlobalObject, path: []const T) bun.JSError!JSC.JSValue { return parseWindowsT(T, path).toJSObject(globalObject); } -pub inline fn parseJS_T(comptime T: type, globalObject: *JSC.JSGlobalObject, isWindows: bool, path: []const T) JSC.JSValue { +pub fn parseJS_T(comptime T: type, globalObject: *JSC.JSGlobalObject, isWindows: bool, path: []const T) bun.JSError!JSC.JSValue { return if (isWindows) parseWindowsJS_T(T, globalObject, path) else parsePosixJS_T(T, globalObject, path); } -pub fn parse(globalObject: *JSC.JSGlobalObject, isWindows: bool, args_ptr: [*]JSC.JSValue, args_len: u16) callconv(JSC.conv) JSC.JSValue { +pub fn parse(globalObject: *JSC.JSGlobalObject, isWindows: bool, args_ptr: [*]JSC.JSValue, args_len: u16) bun.JSError!JSC.JSValue { const path_ptr: JSC.JSValue = if (args_len > 0) args_ptr[0] else .js_undefined; // Supress exeption in zig. It does globalThis.vm().throwError() in JS land. - validateString(globalObject, path_ptr, "path", .{}) catch { - // Returning .zero translates to a nullprt JSC.JSValue. - return .zero; - }; + try validateString(globalObject, path_ptr, "path", .{}); - const pathZStr = path_ptr.getZigString(globalObject) catch return .zero; + const pathZStr = try path_ptr.getZigString(globalObject); if (pathZStr.len == 0) return (PathParsed(u8){}).toJSObject(globalObject); var stack_fallback = std.heap.stackFallback(stack_fallback_size_small, bun.default_allocator); @@ -2322,21 +2296,21 @@ pub fn relativeWindowsT(comptime T: type, from: []const T, to: []const T, buf: [ return MaybeSlice(T){ .result = toOrig[toStart..toEnd :0] }; } -pub inline fn relativePosixJS_T(comptime T: type, globalObject: *JSC.JSGlobalObject, from: []const T, to: []const T, buf: []T, buf2: []T, buf3: []T) JSC.JSValue { +pub fn relativePosixJS_T(comptime T: type, globalObject: *JSC.JSGlobalObject, from: []const T, to: []const T, buf: []T, buf2: []T, buf3: []T) bun.JSError!JSC.JSValue { return switch (relativePosixT(T, from, to, buf, buf2, buf3)) { .result => |r| bun.String.createUTF8ForJS(globalObject, r), .err => |e| e.toJS(globalObject), }; } -pub inline fn relativeWindowsJS_T(comptime T: type, globalObject: *JSC.JSGlobalObject, from: []const T, to: []const T, buf: []T, buf2: []T, buf3: []T) JSC.JSValue { +pub fn relativeWindowsJS_T(comptime T: type, globalObject: *JSC.JSGlobalObject, from: []const T, to: []const T, buf: []T, buf2: []T, buf3: []T) bun.JSError!JSC.JSValue { return switch (relativeWindowsT(T, from, to, buf, buf2, buf3)) { .result => |r| bun.String.createUTF8ForJS(globalObject, r), .err => |e| e.toJS(globalObject), }; } -pub fn relativeJS_T(comptime T: type, globalObject: *JSC.JSGlobalObject, allocator: std.mem.Allocator, isWindows: bool, from: []const T, to: []const T) JSC.JSValue { +pub fn relativeJS_T(comptime T: type, globalObject: *JSC.JSGlobalObject, allocator: std.mem.Allocator, isWindows: bool, from: []const T, to: []const T) bun.JSError!JSC.JSValue { const bufLen = @max(from.len + to.len, PATH_SIZE(T)); const buf = allocator.alloc(T, bufLen) catch bun.outOfMemory(); defer allocator.free(buf); @@ -2347,21 +2321,16 @@ pub fn relativeJS_T(comptime T: type, globalObject: *JSC.JSGlobalObject, allocat return if (isWindows) relativeWindowsJS_T(T, globalObject, from, to, buf, buf2, buf3) else relativePosixJS_T(T, globalObject, from, to, buf, buf2, buf3); } -pub fn relative(globalObject: *JSC.JSGlobalObject, isWindows: bool, args_ptr: [*]JSC.JSValue, args_len: u16) callconv(JSC.conv) JSC.JSValue { +pub fn relative(globalObject: *JSC.JSGlobalObject, isWindows: bool, args_ptr: [*]JSC.JSValue, args_len: u16) bun.JSError!JSC.JSValue { const from_ptr: JSC.JSValue = if (args_len > 0) args_ptr[0] else .js_undefined; // Supress exeption in zig. It does globalThis.vm().throwError() in JS land. - validateString(globalObject, from_ptr, "from", .{}) catch { - // Returning .zero translates to a nullprt JSC.JSValue. - return .zero; - }; + try validateString(globalObject, from_ptr, "from", .{}); const to_ptr: JSC.JSValue = if (args_len > 1) args_ptr[1] else .js_undefined; // Supress exeption in zig. It does globalThis.vm().throwError() in JS land. - validateString(globalObject, to_ptr, "to", .{}) catch { - return .zero; - }; + try validateString(globalObject, to_ptr, "to", .{}); - const fromZigStr = from_ptr.getZigString(globalObject) catch return .zero; - const toZigStr = to_ptr.getZigString(globalObject) catch return .zero; + const fromZigStr = try from_ptr.getZigString(globalObject); + const toZigStr = try to_ptr.getZigString(globalObject); if ((fromZigStr.len + toZigStr.len) == 0) return from_ptr; var stack_fallback = std.heap.stackFallback(stack_fallback_size_small, bun.default_allocator); @@ -2776,21 +2745,21 @@ pub fn resolveWindowsT(comptime T: type, paths: []const []const T, buf: []T, buf return MaybeSlice(T){ .result = comptime L(T, CHAR_STR_DOT) }; } -pub inline fn resolvePosixJS_T(comptime T: type, globalObject: *JSC.JSGlobalObject, paths: []const []const T, buf: []T, buf2: []T) JSC.JSValue { +pub fn resolvePosixJS_T(comptime T: type, globalObject: *JSC.JSGlobalObject, paths: []const []const T, buf: []T, buf2: []T) bun.JSError!JSC.JSValue { return switch (resolvePosixT(T, paths, buf, buf2)) { .result => |r| bun.String.createUTF8ForJS(globalObject, r), .err => |e| e.toJS(globalObject), }; } -pub inline fn resolveWindowsJS_T(comptime T: type, globalObject: *JSC.JSGlobalObject, paths: []const []const T, buf: []T, buf2: []T) JSC.JSValue { +pub fn resolveWindowsJS_T(comptime T: type, globalObject: *JSC.JSGlobalObject, paths: []const []const T, buf: []T, buf2: []T) bun.JSError!JSC.JSValue { return switch (resolveWindowsT(T, paths, buf, buf2)) { .result => |r| bun.String.createUTF8ForJS(globalObject, r), .err => |e| e.toJS(globalObject), }; } -pub fn resolveJS_T(comptime T: type, globalObject: *JSC.JSGlobalObject, allocator: std.mem.Allocator, isWindows: bool, paths: []const []const T) JSC.JSValue { +pub fn resolveJS_T(comptime T: type, globalObject: *JSC.JSGlobalObject, allocator: std.mem.Allocator, isWindows: bool, paths: []const []const T) bun.JSError!JSC.JSValue { // Adding 8 bytes when Windows for the possible UNC root. var bufLen: usize = if (isWindows) 8 else 0; for (paths) |path| bufLen += if (bufLen > 0 and path.len > 0) path.len + 1 else path.len; @@ -2804,7 +2773,7 @@ pub fn resolveJS_T(comptime T: type, globalObject: *JSC.JSGlobalObject, allocato extern "c" fn Process__getCachedCwd(*JSC.JSGlobalObject) JSC.JSValue; -pub fn resolve(globalObject: *JSC.JSGlobalObject, isWindows: bool, args_ptr: [*]JSC.JSValue, args_len: u16) callconv(JSC.conv) JSC.JSValue { +pub fn resolve(globalObject: *JSC.JSGlobalObject, isWindows: bool, args_ptr: [*]JSC.JSValue, args_len: u16) bun.JSError!JSC.JSValue { var arena = bun.ArenaAllocator.init(bun.default_allocator); defer arena.deinit(); @@ -2817,11 +2786,8 @@ pub fn resolve(globalObject: *JSC.JSGlobalObject, isWindows: bool, args_ptr: [*] for (0..args_len, args_ptr) |i, path_ptr| { // Supress exeption in zig. It does globalThis.vm().throwError() in JS land. - validateString(globalObject, path_ptr, "paths[{d}]", .{i}) catch { - // Returning .zero translates to a nullprt JSC.JSValue. - return .zero; - }; - const pathZStr = path_ptr.getZigString(globalObject) catch return .zero; + try validateString(globalObject, path_ptr, "paths[{d}]", .{i}); + const pathZStr = try path_ptr.getZigString(globalObject); if (pathZStr.len > 0) { paths[path_count] = pathZStr.toSlice(allocator).slice(); path_count += 1; @@ -2922,14 +2888,14 @@ pub fn toNamespacedPathWindowsT(comptime T: type, path: []const T, buf: []T, buf return MaybeSlice(T){ .result = resolvedPath }; } -pub inline fn toNamespacedPathWindowsJS_T(comptime T: type, globalObject: *JSC.JSGlobalObject, path: []const T, buf: []T, buf2: []T) JSC.JSValue { +pub fn toNamespacedPathWindowsJS_T(comptime T: type, globalObject: *JSC.JSGlobalObject, path: []const T, buf: []T, buf2: []T) bun.JSError!JSC.JSValue { return switch (toNamespacedPathWindowsT(T, path, buf, buf2)) { .result => |r| bun.String.createUTF8ForJS(globalObject, r), .err => |e| e.toJS(globalObject), }; } -pub fn toNamespacedPathJS_T(comptime T: type, globalObject: *JSC.JSGlobalObject, allocator: std.mem.Allocator, isWindows: bool, path: []const T) JSC.JSValue { +pub fn toNamespacedPathJS_T(comptime T: type, globalObject: *JSC.JSGlobalObject, allocator: std.mem.Allocator, isWindows: bool, path: []const T) bun.JSError!JSC.JSValue { if (!isWindows or path.len == 0) return bun.String.createUTF8ForJS(globalObject, path); const bufLen = @max(path.len, PATH_SIZE(T)); const buf = allocator.alloc(T, bufLen) catch bun.outOfMemory(); @@ -2939,7 +2905,7 @@ pub fn toNamespacedPathJS_T(comptime T: type, globalObject: *JSC.JSGlobalObject, return toNamespacedPathWindowsJS_T(T, globalObject, path, buf, buf2); } -pub fn toNamespacedPath(globalObject: *JSC.JSGlobalObject, isWindows: bool, args_ptr: [*]JSC.JSValue, args_len: u16) callconv(JSC.conv) JSC.JSValue { +pub fn toNamespacedPath(globalObject: *JSC.JSGlobalObject, isWindows: bool, args_ptr: [*]JSC.JSValue, args_len: u16) bun.JSError!JSC.JSValue { if (args_len == 0) return .js_undefined; var path_ptr = args_ptr[0]; @@ -2949,7 +2915,7 @@ pub fn toNamespacedPath(globalObject: *JSC.JSGlobalObject, isWindows: bool, args // // Act as an identity function for non-string values and non-Windows platforms. if (!isWindows or !path_ptr.isString()) return path_ptr; - const pathZStr = path_ptr.getZigString(globalObject) catch return .zero; + const pathZStr = try path_ptr.getZigString(globalObject); const len = pathZStr.len; if (len == 0) return path_ptr; @@ -2962,22 +2928,15 @@ pub fn toNamespacedPath(globalObject: *JSC.JSGlobalObject, isWindows: bool, args } comptime { - @export(&Path.basename, .{ .name = "Bun__Path__basename" }); - @export(&Path.dirname, .{ .name = "Bun__Path__dirname" }); - @export(&Path.extname, .{ .name = "Bun__Path__extname" }); - @export(&path_format, .{ .name = "Bun__Path__format" }); - @export(&Path.isAbsolute, .{ .name = "Bun__Path__isAbsolute" }); - @export(&Path.join, .{ .name = "Bun__Path__join" }); - @export(&Path.normalize, .{ .name = "Bun__Path__normalize" }); - @export(&Path.parse, .{ .name = "Bun__Path__parse" }); - @export(&Path.relative, .{ .name = "Bun__Path__relative" }); - @export(&Path.resolve, .{ .name = "Bun__Path__resolve" }); - @export(&Path.toNamespacedPath, .{ .name = "Bun__Path__toNamespacedPath" }); -} - -fn path_format(globalObject: *JSC.JSGlobalObject, isWindows: bool, args_ptr: [*]JSC.JSValue, args_len: u16) callconv(JSC.conv) JSC.JSValue { - return Path.format(globalObject, isWindows, args_ptr, args_len) catch |err| switch (err) { - error.JSError => .zero, - error.OutOfMemory => globalObject.throwOutOfMemoryValue(), - }; + @export(&bun.jsc.host_fn.wrap4v(Path.basename), .{ .name = "Bun__Path__basename" }); + @export(&bun.jsc.host_fn.wrap4v(Path.dirname), .{ .name = "Bun__Path__dirname" }); + @export(&bun.jsc.host_fn.wrap4v(Path.extname), .{ .name = "Bun__Path__extname" }); + @export(&bun.jsc.host_fn.wrap4v(Path.format), .{ .name = "Bun__Path__format" }); + @export(&bun.jsc.host_fn.wrap4v(Path.isAbsolute), .{ .name = "Bun__Path__isAbsolute" }); + @export(&bun.jsc.host_fn.wrap4v(Path.join), .{ .name = "Bun__Path__join" }); + @export(&bun.jsc.host_fn.wrap4v(Path.normalize), .{ .name = "Bun__Path__normalize" }); + @export(&bun.jsc.host_fn.wrap4v(Path.parse), .{ .name = "Bun__Path__parse" }); + @export(&bun.jsc.host_fn.wrap4v(Path.relative), .{ .name = "Bun__Path__relative" }); + @export(&bun.jsc.host_fn.wrap4v(Path.resolve), .{ .name = "Bun__Path__resolve" }); + @export(&bun.jsc.host_fn.wrap4v(Path.toNamespacedPath), .{ .name = "Bun__Path__toNamespacedPath" }); } diff --git a/src/bun.js/node/types.zig b/src/bun.js/node/types.zig index 4ff5a6c332..835d7f9f88 100644 --- a/src/bun.js/node/types.zig +++ b/src/bun.js/node/types.zig @@ -173,7 +173,7 @@ pub const StringOrBuffer = union(enum) { return result; } - pub fn toJS(this: *StringOrBuffer, ctx: *JSC.JSGlobalObject) JSC.JSValue { + pub fn toJS(this: *StringOrBuffer, ctx: *JSC.JSGlobalObject) bun.JSError!JSC.JSValue { return switch (this.*) { inline .threadsafe_string, .string => |*str| { return str.transferToJS(ctx); diff --git a/src/bun.js/web_worker.zig b/src/bun.js/web_worker.zig index b8fea6e31b..f545a8bc3d 100644 --- a/src/bun.js/web_worker.zig +++ b/src/bun.js/web_worker.zig @@ -374,7 +374,9 @@ fn flushLogs(this: *WebWorker) void { const err = vm.log.toJS(vm.global, bun.default_allocator, "Error in worker") catch bun.outOfMemory(); const str = err.toBunString(vm.global) catch @panic("unexpected exception"); defer str.deref(); - WebWorker__dispatchError(vm.global, this.cpp_worker, str, err); + bun.jsc.fromJSHostCallGeneric(vm.global, @src(), WebWorker__dispatchError, .{ vm.global, this.cpp_worker, str, err }) catch |e| { + _ = vm.global.reportUncaughtException(vm.global.takeException(e).asException(vm.global.vm()).?); + }; } fn onUnhandledRejection(vm: *jsc.VirtualMachine, globalObject: *jsc.JSGlobalObject, error_instance_or_exception: jsc.JSValue) void { @@ -433,10 +435,6 @@ fn setStatus(this: *WebWorker, status: Status) void { this.status.store(status, .release); } -fn unhandledError(this: *WebWorker, _: anyerror) void { - this.flushLogs(); -} - fn spin(this: *WebWorker) void { log("[{d}] spin start", .{this.execution_context_id}); diff --git a/src/bun.js/webcore/Blob.zig b/src/bun.js/webcore/Blob.zig index 0a71a36479..b935de14bb 100644 --- a/src/bun.js/webcore/Blob.zig +++ b/src/bun.js/webcore/Blob.zig @@ -3634,7 +3634,6 @@ pub fn toArrayBufferViewWithBytes(this: *Blob, global: *JSGlobalObject, buf: []u global, store, JSC.array_buffer.BlobArrayBuffer_deallocator, - null, ); }, .temporary => { @@ -3643,10 +3642,7 @@ pub fn toArrayBufferViewWithBytes(this: *Blob, global: *JSGlobalObject, buf: []u return global.throwOutOfMemory(); } - return JSC.ArrayBuffer.fromBytes(buf, TypedArrayView).toJS( - global, - null, - ); + return JSC.ArrayBuffer.fromBytes(buf, TypedArrayView).toJS(global); }, } } diff --git a/src/bun.js/webcore/FileReader.zig b/src/bun.js/webcore/FileReader.zig index 74fac23c40..6931fb88d7 100644 --- a/src/bun.js/webcore/FileReader.zig +++ b/src/bun.js/webcore/FileReader.zig @@ -613,7 +613,7 @@ pub fn onReaderDone(this: *FileReader) void { globalThis, .js_undefined, &.{ - JSC.ArrayBuffer.fromBytes(buffered.items, .Uint8Array).toJS(globalThis, null) catch |err| { + JSC.ArrayBuffer.fromBytes(buffered.items, .Uint8Array).toJS(globalThis) catch |err| { this.pending.result = .{ .err = .{ .WeakJSValue = globalThis.takeException(err) } }; return; }, diff --git a/src/bun.js/webcore/ReadableStream.zig b/src/bun.js/webcore/ReadableStream.zig index df32ec91d2..c902df9e7e 100644 --- a/src/bun.js/webcore/ReadableStream.zig +++ b/src/bun.js/webcore/ReadableStream.zig @@ -766,7 +766,7 @@ pub fn NewSource( this.this_jsvalue = callFrame.this(); var list = this.drain(); if (list.len > 0) { - return JSC.ArrayBuffer.fromBytes(list.slice(), .Uint8Array).toJS(globalThis, null); + return JSC.ArrayBuffer.fromBytes(list.slice(), .Uint8Array).toJS(globalThis); } return .js_undefined; } diff --git a/src/bun.js/webcore/S3File.zig b/src/bun.js/webcore/S3File.zig index 12fd263ac8..84b99cd8de 100644 --- a/src/bun.js/webcore/S3File.zig +++ b/src/bun.js/webcore/S3File.zig @@ -540,7 +540,7 @@ pub fn getBucketName( pub fn getBucket(this: *Blob, globalThis: *JSC.JSGlobalObject) callconv(JSC.conv) JSValue { if (getBucketName(this)) |name| { - return bun.String.createUTF8ForJS(globalThis, name); + return bun.String.createUTF8ForJS(globalThis, name) catch .zero; } return .js_undefined; } diff --git a/src/bun.js/webcore/TextEncoder.zig b/src/bun.js/webcore/TextEncoder.zig index e7f867e3cf..1c86ec0926 100644 --- a/src/bun.js/webcore/TextEncoder.zig +++ b/src/bun.js/webcore/TextEncoder.zig @@ -28,7 +28,7 @@ pub export fn TextEncoder__encode8( return globalThis.throwOutOfMemoryValue(); }; bun.assert(bytes.len >= slice.len); - return ArrayBuffer.fromBytes(bytes, .Uint8Array).toJSUnchecked(globalThis, null) catch .zero; + return ArrayBuffer.fromBytes(bytes, .Uint8Array).toJSUnchecked(globalThis) catch .zero; } } @@ -74,7 +74,7 @@ pub export fn TextEncoder__encode16( ) catch { return globalThis.toInvalidArguments("Out of memory", .{}); }; - return ArrayBuffer.fromBytes(bytes, .Uint8Array).toJSUnchecked(globalThis, null) catch .zero; + return ArrayBuffer.fromBytes(bytes, .Uint8Array).toJSUnchecked(globalThis) catch .zero; } } @@ -120,7 +120,7 @@ pub export fn c( ) catch { return globalThis.throwOutOfMemoryValue(); }; - return ArrayBuffer.fromBytes(bytes, .Uint8Array).toJSUnchecked(globalThis, null) catch .zero; + return ArrayBuffer.fromBytes(bytes, .Uint8Array).toJSUnchecked(globalThis) catch .zero; } } diff --git a/src/bun.js/webcore/streams.zig b/src/bun.js/webcore/streams.zig index a500f6dcb5..b279dcaa61 100644 --- a/src/bun.js/webcore/streams.zig +++ b/src/bun.js/webcore/streams.zig @@ -41,7 +41,7 @@ pub const Start = union(Tag) { return globalThis.throwValue(err.toJS(globalThis)); }, .owned_and_done => |list| { - return JSC.ArrayBuffer.fromBytes(list.slice(), .Uint8Array).toJS(globalThis, null); + return JSC.ArrayBuffer.fromBytes(list.slice(), .Uint8Array).toJS(globalThis); }, .done => |list| { return JSC.ArrayBuffer.create(globalThis, list.slice(), .Uint8Array); @@ -565,10 +565,10 @@ pub const Result = union(Tag) { switch (this.*) { .owned => |list| { - return JSC.ArrayBuffer.fromBytes(list.slice(), .Uint8Array).toJS(globalThis, null); + return JSC.ArrayBuffer.fromBytes(list.slice(), .Uint8Array).toJS(globalThis); }, .owned_and_done => |list| { - return JSC.ArrayBuffer.fromBytes(list.slice(), .Uint8Array).toJS(globalThis, null); + return JSC.ArrayBuffer.fromBytes(list.slice(), .Uint8Array).toJS(globalThis); }, .temporary => |temp| { var array = try JSC.JSValue.createUninitializedUint8Array(globalThis, temp.len); diff --git a/src/codegen/bindgen.ts b/src/codegen/bindgen.ts index 193c949eeb..a96dcd0ccd 100644 --- a/src/codegen/bindgen.ts +++ b/src/codegen/bindgen.ts @@ -498,10 +498,9 @@ function emitConvertValue( if (decl === "declare") { cpp.line(`${type.cppName()} ${storageLocation};`); } - cpp.line(`if (!convert${type.cppInternalName()}(&${storageLocation}, global, ${jsValueRef}))`); - cpp.indent(); - cpp.line(`return {};`); - cpp.dedent(); + cpp.line(`auto did_convert = convert${type.cppInternalName()}(&${storageLocation}, global, ${jsValueRef});`); + cpp.line(`RETURN_IF_EXCEPTION(throwScope, {});`); + cpp.line(`if (!did_convert) return {};`); break; } default: @@ -1017,7 +1016,9 @@ function emitCppVariationSelector(fn: Func, namespaceVar: string) { } if (variants.length === 1) { - cpp.line(`return ${extInternalDispatchVariant(namespaceVar, fn.name, variants[0].suffix)}(global, callFrame);`); + cpp.line( + `RELEASE_AND_RETURN(throwScope, ${extInternalDispatchVariant(namespaceVar, fn.name, variants[0].suffix)}(global, callFrame));`, + ); } else { let argIndex = 0; let strategies: DistinguishStrategy[] | null = null; @@ -1053,7 +1054,9 @@ function emitCppVariationSelector(fn: Func, namespaceVar: string) { const { condition, canThrow } = getDistinguishCode(s, arg.type, "distinguishingValue"); cpp.line(`if (${condition}) {`); cpp.indent(); - cpp.line(`return ${extInternalDispatchVariant(namespaceVar, fn.name, v.suffix)}(global, callFrame);`); + cpp.line( + `RELEASE_AND_RETURN(throwScope, ${extInternalDispatchVariant(namespaceVar, fn.name, v.suffix)}(global, callFrame));`, + ); cpp.dedent(); cpp.line(`}`); if (canThrow) { diff --git a/src/install/dependency.zig b/src/install/dependency.zig index 4ea40ac399..ea7346f809 100644 --- a/src/install/dependency.zig +++ b/src/install/dependency.zig @@ -336,42 +336,42 @@ pub const Version = struct { switch (dep.tag) { .dist_tag => { - object.put(globalThis, "name", dep.value.dist_tag.name.toJS(buf, globalThis)); - object.put(globalThis, "tag", dep.value.dist_tag.tag.toJS(buf, globalThis)); + object.put(globalThis, "name", try dep.value.dist_tag.name.toJS(buf, globalThis)); + object.put(globalThis, "tag", try dep.value.dist_tag.tag.toJS(buf, globalThis)); }, .folder => { - object.put(globalThis, "folder", dep.value.folder.toJS(buf, globalThis)); + object.put(globalThis, "folder", try dep.value.folder.toJS(buf, globalThis)); }, .git => { - object.put(globalThis, "owner", dep.value.git.owner.toJS(buf, globalThis)); - object.put(globalThis, "repo", dep.value.git.repo.toJS(buf, globalThis)); - object.put(globalThis, "ref", dep.value.git.committish.toJS(buf, globalThis)); + object.put(globalThis, "owner", try dep.value.git.owner.toJS(buf, globalThis)); + object.put(globalThis, "repo", try dep.value.git.repo.toJS(buf, globalThis)); + object.put(globalThis, "ref", try dep.value.git.committish.toJS(buf, globalThis)); }, .github => { - object.put(globalThis, "owner", dep.value.github.owner.toJS(buf, globalThis)); - object.put(globalThis, "repo", dep.value.github.repo.toJS(buf, globalThis)); - object.put(globalThis, "ref", dep.value.github.committish.toJS(buf, globalThis)); + object.put(globalThis, "owner", try dep.value.github.owner.toJS(buf, globalThis)); + object.put(globalThis, "repo", try dep.value.github.repo.toJS(buf, globalThis)); + object.put(globalThis, "ref", try dep.value.github.committish.toJS(buf, globalThis)); }, .npm => { - object.put(globalThis, "name", dep.value.npm.name.toJS(buf, globalThis)); + object.put(globalThis, "name", try dep.value.npm.name.toJS(buf, globalThis)); var version_str = try bun.String.createFormat("{}", .{dep.value.npm.version.fmt(buf)}); object.put(globalThis, "version", version_str.transferToJS(globalThis)); object.put(globalThis, "alias", JSC.JSValue.jsBoolean(dep.value.npm.is_alias)); }, .symlink => { - object.put(globalThis, "path", dep.value.symlink.toJS(buf, globalThis)); + object.put(globalThis, "path", try dep.value.symlink.toJS(buf, globalThis)); }, .workspace => { - object.put(globalThis, "name", dep.value.workspace.toJS(buf, globalThis)); + object.put(globalThis, "name", try dep.value.workspace.toJS(buf, globalThis)); }, .tarball => { - object.put(globalThis, "name", dep.value.tarball.package_name.toJS(buf, globalThis)); + object.put(globalThis, "name", try dep.value.tarball.package_name.toJS(buf, globalThis)); switch (dep.value.tarball.uri) { .local => |*local| { - object.put(globalThis, "path", local.toJS(buf, globalThis)); + object.put(globalThis, "path", try local.toJS(buf, globalThis)); }, .remote => |*remote| { - object.put(globalThis, "url", remote.toJS(buf, globalThis)); + object.put(globalThis, "url", try remote.toJS(buf, globalThis)); }, } }, diff --git a/src/napi/napi.zig b/src/napi/napi.zig index e6cf797d08..6f59ecd791 100644 --- a/src/napi/napi.zig +++ b/src/napi/napi.zig @@ -436,10 +436,7 @@ pub export fn napi_create_string_utf8(env_: napi_env, str: ?[*]const u8, length: log("napi_create_string_utf8: {s}", .{slice}); const globalObject = env.toJS(); - const string = bun.String.createUTF8ForJS(globalObject, slice); - if (globalObject.hasException()) { - return env.setLastError(.pending_exception); - } + const string = bun.String.createUTF8ForJS(globalObject, slice) catch return env.setLastError(.pending_exception); result.set(env, string); return env.ok(); } @@ -844,7 +841,7 @@ pub export fn napi_get_typedarray_info( const array_buffer = typedarray.asArrayBuffer(env.toJS()) orelse return env.invalidArg(); if (maybe_type) |@"type"| - @"type".* = napi_typedarray_type.fromJSType(array_buffer.typed_array_type) orelse return env.invalidArg(); + @"type".* = array_buffer.typed_array_type.toTypedArrayType().toNapi() orelse return env.invalidArg(); // TODO: handle detached if (maybe_data) |data| diff --git a/src/s3/list_objects.zig b/src/s3/list_objects.zig index 317e6d4c19..298c80dee2 100644 --- a/src/s3/list_objects.zig +++ b/src/s3/list_objects.zig @@ -78,30 +78,30 @@ pub const S3ListObjectsV2Result = struct { const jsResult = JSValue.createEmptyObject(globalObject, 12); if (this.name) |name| { - jsResult.put(globalObject, JSC.ZigString.static("name"), bun.String.createUTF8ForJS(globalObject, name)); + jsResult.put(globalObject, JSC.ZigString.static("name"), try bun.String.createUTF8ForJS(globalObject, name)); } if (this.prefix) |prefix| { - jsResult.put(globalObject, JSC.ZigString.static("prefix"), bun.String.createUTF8ForJS(globalObject, prefix)); + jsResult.put(globalObject, JSC.ZigString.static("prefix"), try bun.String.createUTF8ForJS(globalObject, prefix)); } if (this.delimiter) |delimiter| { - jsResult.put(globalObject, JSC.ZigString.static("delimiter"), bun.String.createUTF8ForJS(globalObject, delimiter)); + jsResult.put(globalObject, JSC.ZigString.static("delimiter"), try bun.String.createUTF8ForJS(globalObject, delimiter)); } if (this.start_after) |start_after| { - jsResult.put(globalObject, JSC.ZigString.static("startAfter"), bun.String.createUTF8ForJS(globalObject, start_after)); + jsResult.put(globalObject, JSC.ZigString.static("startAfter"), try bun.String.createUTF8ForJS(globalObject, start_after)); } if (this.encoding_type) |encoding_type| { - jsResult.put(globalObject, JSC.ZigString.static("encodingType"), bun.String.createUTF8ForJS(globalObject, encoding_type)); + jsResult.put(globalObject, JSC.ZigString.static("encodingType"), try bun.String.createUTF8ForJS(globalObject, encoding_type)); } if (this.continuation_token) |continuation_token| { - jsResult.put(globalObject, JSC.ZigString.static("continuationToken"), bun.String.createUTF8ForJS(globalObject, continuation_token)); + jsResult.put(globalObject, JSC.ZigString.static("continuationToken"), try bun.String.createUTF8ForJS(globalObject, continuation_token)); } if (this.next_continuation_token) |next_continuation_token| { - jsResult.put(globalObject, JSC.ZigString.static("nextContinuationToken"), bun.String.createUTF8ForJS(globalObject, next_continuation_token)); + jsResult.put(globalObject, JSC.ZigString.static("nextContinuationToken"), try bun.String.createUTF8ForJS(globalObject, next_continuation_token)); } if (this.is_truncated) |is_truncated| { @@ -121,22 +121,22 @@ pub const S3ListObjectsV2Result = struct { for (contents.items, 0..) |item, i| { const objectInfo = JSValue.createEmptyObject(globalObject, 1); - objectInfo.put(globalObject, JSC.ZigString.static("key"), bun.String.createUTF8ForJS(globalObject, item.key)); + objectInfo.put(globalObject, JSC.ZigString.static("key"), try bun.String.createUTF8ForJS(globalObject, item.key)); if (item.etag) |etag| { - objectInfo.put(globalObject, JSC.ZigString.static("eTag"), bun.String.createUTF8ForJS(globalObject, etag)); + objectInfo.put(globalObject, JSC.ZigString.static("eTag"), try bun.String.createUTF8ForJS(globalObject, etag)); } if (item.checksum_algorithme) |checksum_algorithme| { - objectInfo.put(globalObject, JSC.ZigString.static("checksumAlgorithme"), bun.String.createUTF8ForJS(globalObject, checksum_algorithme)); + objectInfo.put(globalObject, JSC.ZigString.static("checksumAlgorithme"), try bun.String.createUTF8ForJS(globalObject, checksum_algorithme)); } if (item.checksum_type) |checksum_type| { - objectInfo.put(globalObject, JSC.ZigString.static("checksumType"), bun.String.createUTF8ForJS(globalObject, checksum_type)); + objectInfo.put(globalObject, JSC.ZigString.static("checksumType"), try bun.String.createUTF8ForJS(globalObject, checksum_type)); } if (item.last_modified) |last_modified| { - objectInfo.put(globalObject, JSC.ZigString.static("lastModified"), bun.String.createUTF8ForJS(globalObject, last_modified)); + objectInfo.put(globalObject, JSC.ZigString.static("lastModified"), try bun.String.createUTF8ForJS(globalObject, last_modified)); } if (item.object_size) |object_size| { @@ -144,17 +144,17 @@ pub const S3ListObjectsV2Result = struct { } if (item.storage_class) |storage_class| { - objectInfo.put(globalObject, JSC.ZigString.static("storageClass"), bun.String.createUTF8ForJS(globalObject, storage_class)); + objectInfo.put(globalObject, JSC.ZigString.static("storageClass"), try bun.String.createUTF8ForJS(globalObject, storage_class)); } if (item.owner) |owner| { const jsOwner = JSValue.createEmptyObject(globalObject, 2); if (owner.id) |id| { - jsOwner.put(globalObject, JSC.ZigString.static("id"), bun.String.createUTF8ForJS(globalObject, id)); + jsOwner.put(globalObject, JSC.ZigString.static("id"), try bun.String.createUTF8ForJS(globalObject, id)); } if (owner.display_name) |display_name| { - jsOwner.put(globalObject, JSC.ZigString.static("displayName"), bun.String.createUTF8ForJS(globalObject, display_name)); + jsOwner.put(globalObject, JSC.ZigString.static("displayName"), try bun.String.createUTF8ForJS(globalObject, display_name)); } objectInfo.put(globalObject, JSC.ZigString.static("owner"), jsOwner); @@ -171,7 +171,7 @@ pub const S3ListObjectsV2Result = struct { for (common_prefixes.items, 0..) |prefix, i| { const jsPrefix = JSValue.createEmptyObject(globalObject, 1); - jsPrefix.put(globalObject, JSC.ZigString.static("prefix"), bun.String.createUTF8ForJS(globalObject, prefix)); + jsPrefix.put(globalObject, JSC.ZigString.static("prefix"), try bun.String.createUTF8ForJS(globalObject, prefix)); try jsCommonPrefixes.putIndex(globalObject, @intCast(i), jsPrefix); } diff --git a/src/semver/SemverString.zig b/src/semver/SemverString.zig index ee30c31e1a..5bb7ca60f1 100644 --- a/src/semver/SemverString.zig +++ b/src/semver/SemverString.zig @@ -451,7 +451,7 @@ pub const String = extern struct { return @as(Pointer, @bitCast(@as(u64, @as(u63, @truncate(@as(u64, @bitCast(this))))))); } - pub fn toJS(this: *const String, buffer: []const u8, globalThis: *JSC.JSGlobalObject) JSC.JSValue { + pub fn toJS(this: *const String, buffer: []const u8, globalThis: *JSC.JSGlobalObject) bun.JSError!JSC.JSValue { return bun.String.createUTF8ForJS(globalThis, this.slice(buffer)); } diff --git a/src/sourcemap/CodeCoverage.zig b/src/sourcemap/CodeCoverage.zig index d920ba42ac..96ffcd9a12 100644 --- a/src/sourcemap/CodeCoverage.zig +++ b/src/sourcemap/CodeCoverage.zig @@ -692,7 +692,7 @@ pub const ByteRangeMapping = struct { return globalThis.throwOutOfMemoryValue(); }; - return bun.String.createUTF8ForJS(globalThis, mutable_str.slice()); + return bun.String.createUTF8ForJS(globalThis, mutable_str.slice()) catch return .zero; } pub fn compute(source_contents: []const u8, source_id: i32, source_url: bun.JSC.ZigString.Slice) ByteRangeMapping { diff --git a/src/string.zig b/src/string.zig index 4c95e61b68..2a257fed2e 100644 --- a/src/string.zig +++ b/src/string.zig @@ -841,17 +841,17 @@ pub const String = extern struct { extern fn BunString__toWTFString(this: *String) void; extern fn BunString__createUTF8ForJS(globalObject: *JSC.JSGlobalObject, ptr: [*]const u8, len: usize) JSC.JSValue; - pub fn createUTF8ForJS(globalObject: *JSC.JSGlobalObject, utf8_slice: []const u8) JSC.JSValue { + pub fn createUTF8ForJS(globalObject: *JSC.JSGlobalObject, utf8_slice: []const u8) bun.JSError!JSC.JSValue { JSC.markBinding(@src()); - return BunString__createUTF8ForJS(globalObject, utf8_slice.ptr, utf8_slice.len); + return bun.jsc.fromJSHostCall(globalObject, @src(), BunString__createUTF8ForJS, .{ globalObject, utf8_slice.ptr, utf8_slice.len }); } - pub fn createFormatForJS(globalObject: *JSC.JSGlobalObject, comptime fmt: [:0]const u8, args: anytype) JSC.JSValue { + pub fn createFormatForJS(globalObject: *JSC.JSGlobalObject, comptime fmt: [:0]const u8, args: anytype) bun.JSError!JSC.JSValue { JSC.markBinding(@src()); var builder = std.ArrayList(u8).init(bun.default_allocator); defer builder.deinit(); builder.writer().print(fmt, args) catch bun.outOfMemory(); - return BunString__createUTF8ForJS(globalObject, builder.items.ptr, builder.items.len); + return bun.jsc.fromJSHostCall(globalObject, @src(), BunString__createUTF8ForJS, .{ globalObject, builder.items.ptr, builder.items.len }); } pub fn parseDate(this: *String, globalObject: *JSC.JSGlobalObject) f64 { @@ -1217,15 +1217,15 @@ pub const SliceWithUnderlyingString = struct { try writer.writeAll(self.utf8.slice()); } - pub fn toJS(this: *SliceWithUnderlyingString, globalObject: *JSC.JSGlobalObject) JSC.JSValue { + pub fn toJS(this: *SliceWithUnderlyingString, globalObject: *JSC.JSGlobalObject) bun.JSError!JSC.JSValue { return this.toJSWithOptions(globalObject, false); } - pub fn transferToJS(this: *SliceWithUnderlyingString, globalObject: *JSC.JSGlobalObject) JSC.JSValue { + pub fn transferToJS(this: *SliceWithUnderlyingString, globalObject: *JSC.JSGlobalObject) bun.JSError!JSC.JSValue { return this.toJSWithOptions(globalObject, true); } - fn toJSWithOptions(this: *SliceWithUnderlyingString, globalObject: *JSC.JSGlobalObject, transfer: bool) JSC.JSValue { + fn toJSWithOptions(this: *SliceWithUnderlyingString, globalObject: *JSC.JSGlobalObject, transfer: bool) bun.JSError!JSC.JSValue { if ((this.underlying.tag == .Dead or this.underlying.tag == .Empty) and this.utf8.length() > 0) { if (comptime bun.Environment.allow_assert) { if (this.utf8.allocator.get()) |allocator| { diff --git a/src/valkey/valkey_protocol.zig b/src/valkey/valkey_protocol.zig index 8d82f8a2f7..9e5fee62cd 100644 --- a/src/valkey/valkey_protocol.zig +++ b/src/valkey/valkey_protocol.zig @@ -316,7 +316,7 @@ pub const RESPValue = union(RESPType) { var js_obj = JSC.JSValue.createEmptyObjectWithNullPrototype(globalObject); // Add the push type - const kind_str = bun.String.createUTF8ForJS(globalObject, push.kind); + const kind_str = try bun.String.createUTF8ForJS(globalObject, push.kind); js_obj.put(globalObject, "type", kind_str); // Add the data as an array diff --git a/test/internal/ban-words.test.ts b/test/internal/ban-words.test.ts index 5a06632661..37bf95e59f 100644 --- a/test/internal/ban-words.test.ts +++ b/test/internal/ban-words.test.ts @@ -45,7 +45,7 @@ const words: Record "// autofix": { reason: "Evaluate if this variable should be deleted entirely or explicitly discarded.", limit: 173 }, "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: 47 }, + "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 }, }; const words_keys = [...Object.keys(words)]; diff --git a/test/no-validate-exceptions.txt b/test/no-validate-exceptions.txt index 6275da6dc6..6fcbf8b3e8 100644 --- a/test/no-validate-exceptions.txt +++ b/test/no-validate-exceptions.txt @@ -350,1362 +350,6 @@ 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/parallel/test-abortsignal-any.mjs -test/js/node/test/parallel/test-assert-async.js -test/js/node/test/parallel/test-assert-builtins-not-read-from-filesystem.js -test/js/node/test/parallel/test-assert-calltracker-calls.js -test/js/node/test/parallel/test-assert-calltracker-getCalls.js -test/js/node/test/parallel/test-assert-calltracker-report.js -test/js/node/test/parallel/test-assert-calltracker-verify.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-esm-cjs-message-verify.js -test/js/node/test/parallel/test-assert-fail-deprecation.js -test/js/node/test/parallel/test-assert-if-error.js -test/js/node/test/parallel/test-assert-strict-exists.js -test/js/node/test/parallel/test-assert.js -test/js/node/test/parallel/test-async-hooks-asyncresource-constructor.js -test/js/node/test/parallel/test-async-hooks-constructor.js -test/js/node/test/parallel/test-async-hooks-recursive-stack-runInAsyncScope.js -test/js/node/test/parallel/test-async-hooks-run-in-async-scope-caught-exception.js -test/js/node/test/parallel/test-async-hooks-run-in-async-scope-this-arg.js -test/js/node/test/parallel/test-async-hooks-vm-gc.js -test/js/node/test/parallel/test-async-hooks-worker-asyncfn-terminate-1.js -test/js/node/test/parallel/test-async-hooks-worker-asyncfn-terminate-2.js -test/js/node/test/parallel/test-async-hooks-worker-asyncfn-terminate-3.js -test/js/node/test/parallel/test-async-hooks-worker-asyncfn-terminate-4.js -test/js/node/test/parallel/test-async-local-storage-bind.js -test/js/node/test/parallel/test-async-local-storage-contexts.js -test/js/node/test/parallel/test-async-local-storage-deep-stack.js -test/js/node/test/parallel/test-async-local-storage-enter-with.js -test/js/node/test/parallel/test-async-local-storage-exit-does-not-leak.js -test/js/node/test/parallel/test-async-local-storage-http-multiclients.js -test/js/node/test/parallel/test-async-local-storage-snapshot.js -test/js/node/test/parallel/test-async-wrap-constructor.js -test/js/node/test/parallel/test-atomics-wake.js -test/js/node/test/parallel/test-bad-unicode.js -test/js/node/test/parallel/test-beforeexit-event-exit.js -test/js/node/test/parallel/test-binding-constants.js -test/js/node/test/parallel/test-blob-createobjecturl.js -test/js/node/test/parallel/test-blocklist-clone.js -test/js/node/test/parallel/test-blocklist.js -test/js/node/test/parallel/test-broadcastchannel-custom-inspect.js -test/js/node/test/parallel/test-btoa-atob.js -test/js/node/test/parallel/test-c-ares.js -test/js/node/test/parallel/test-child-process-advanced-serialization-largebuffer.js -test/js/node/test/parallel/test-child-process-advanced-serialization.js -test/js/node/test/parallel/test-child-process-can-write-to-stdout.js -test/js/node/test/parallel/test-child-process-constructor.js -test/js/node/test/parallel/test-child-process-cwd.js -test/js/node/test/parallel/test-child-process-default-options.js -test/js/node/test/parallel/test-child-process-destroy.js -test/js/node/test/parallel/test-child-process-detached.js -test/js/node/test/parallel/test-child-process-dgram-reuseport.js -test/js/node/test/parallel/test-child-process-disconnect.js -test/js/node/test/parallel/test-child-process-double-pipe.js -test/js/node/test/parallel/test-child-process-emfile.js -test/js/node/test/parallel/test-child-process-env.js -test/js/node/test/parallel/test-child-process-exec-abortcontroller-promisified.js -test/js/node/test/parallel/test-child-process-exec-any-shells-windows.js -test/js/node/test/parallel/test-child-process-exec-cwd.js -test/js/node/test/parallel/test-child-process-exec-encoding.js -test/js/node/test/parallel/test-child-process-exec-env.js -test/js/node/test/parallel/test-child-process-exec-error.js -test/js/node/test/parallel/test-child-process-exec-maxbuf.js -test/js/node/test/parallel/test-child-process-exec-std-encoding.js -test/js/node/test/parallel/test-child-process-exec-stdout-stderr-data-string.js -test/js/node/test/parallel/test-child-process-exec-timeout-expire.js -test/js/node/test/parallel/test-child-process-exec-timeout-kill.js -test/js/node/test/parallel/test-child-process-exec-timeout-not-expired.js -test/js/node/test/parallel/test-child-process-execFile-promisified-abortController.js -test/js/node/test/parallel/test-child-process-execfile-maxbuf.js -test/js/node/test/parallel/test-child-process-execfile.js -test/js/node/test/parallel/test-child-process-execfilesync-maxbuf.js -test/js/node/test/parallel/test-child-process-execsync-maxbuf.js -test/js/node/test/parallel/test-child-process-exit-code.js -test/js/node/test/parallel/test-child-process-flush-stdio.js -test/js/node/test/parallel/test-child-process-fork-abort-signal.js -test/js/node/test/parallel/test-child-process-fork-and-spawn.js -test/js/node/test/parallel/test-child-process-fork-args.js -test/js/node/test/parallel/test-child-process-fork-close.js -test/js/node/test/parallel/test-child-process-fork-closed-channel-segfault.js -test/js/node/test/parallel/test-child-process-fork-detached.js -test/js/node/test/parallel/test-child-process-fork-exec-argv.js -test/js/node/test/parallel/test-child-process-fork-exec-path.js -test/js/node/test/parallel/test-child-process-fork-no-shell.js -test/js/node/test/parallel/test-child-process-fork-ref.js -test/js/node/test/parallel/test-child-process-fork-ref2.js -test/js/node/test/parallel/test-child-process-fork-stdio-string-variant.js -test/js/node/test/parallel/test-child-process-fork-timeout-kill-signal.js -test/js/node/test/parallel/test-child-process-fork-url.mjs -test/js/node/test/parallel/test-child-process-fork.js -test/js/node/test/parallel/test-child-process-fork3.js -test/js/node/test/parallel/test-child-process-ipc-next-tick.js -test/js/node/test/parallel/test-child-process-ipc.js -test/js/node/test/parallel/test-child-process-kill.js -test/js/node/test/parallel/test-child-process-net-reuseport.js -test/js/node/test/parallel/test-child-process-no-deprecation.js -test/js/node/test/parallel/test-child-process-promisified.js -test/js/node/test/parallel/test-child-process-prototype-tampering.mjs -test/js/node/test/parallel/test-child-process-reject-null-bytes.js -test/js/node/test/parallel/test-child-process-send-after-close.js -test/js/node/test/parallel/test-child-process-send-cb.js -test/js/node/test/parallel/test-child-process-send-type-error.js -test/js/node/test/parallel/test-child-process-send-utf8.js -test/js/node/test/parallel/test-child-process-set-blocking.js -test/js/node/test/parallel/test-child-process-silent.js -test/js/node/test/parallel/test-child-process-spawn-args.js -test/js/node/test/parallel/test-child-process-spawn-argv0.js -test/js/node/test/parallel/test-child-process-spawn-controller.js -test/js/node/test/parallel/test-child-process-spawn-error.js -test/js/node/test/parallel/test-child-process-spawn-event.js -test/js/node/test/parallel/test-child-process-spawn-shell.js -test/js/node/test/parallel/test-child-process-spawn-timeout-kill-signal.js -test/js/node/test/parallel/test-child-process-spawn-typeerror.js -test/js/node/test/parallel/test-child-process-spawnsync-args.js -test/js/node/test/parallel/test-child-process-spawnsync-env.js -test/js/node/test/parallel/test-child-process-spawnsync-input.js -test/js/node/test/parallel/test-child-process-spawnsync-kill-signal.js -test/js/node/test/parallel/test-child-process-spawnsync-maxbuf.js -test/js/node/test/parallel/test-child-process-spawnsync-shell.js -test/js/node/test/parallel/test-child-process-spawnsync-timeout.js -test/js/node/test/parallel/test-child-process-spawnsync-validation-errors.js -test/js/node/test/parallel/test-child-process-spawnsync.js -test/js/node/test/parallel/test-child-process-stdin-ipc.js -test/js/node/test/parallel/test-child-process-stdin.js -test/js/node/test/parallel/test-child-process-stdio-big-write-end.js -test/js/node/test/parallel/test-child-process-stdio-inherit.js -test/js/node/test/parallel/test-child-process-stdio-overlapped.js -test/js/node/test/parallel/test-child-process-stdio.js -test/js/node/test/parallel/test-child-process-stdout-flush-exit.js -test/js/node/test/parallel/test-child-process-stdout-flush.js -test/js/node/test/parallel/test-child-process-stdout-ipc.js -test/js/node/test/parallel/test-cli-eval-event.js -test/js/node/test/parallel/test-cli-options-precedence.js -test/js/node/test/parallel/test-client-request-destroy.js -test/js/node/test/parallel/test-common-countdown.js -test/js/node/test/parallel/test-common-expect-warning.js -test/js/node/test/parallel/test-common-must-not-call.js -test/js/node/test/parallel/test-config-json-schema.js -test/js/node/test/parallel/test-console-assign-undefined.js -test/js/node/test/parallel/test-console-async-write-error.js -test/js/node/test/parallel/test-console-group.js -test/js/node/test/parallel/test-console-instance.js -test/js/node/test/parallel/test-console-issue-43095.js -test/js/node/test/parallel/test-console-log-stdio-broken-dest.js -test/js/node/test/parallel/test-console-log-throw-primitive.js -test/js/node/test/parallel/test-console-methods.js -test/js/node/test/parallel/test-console-no-swallow-stack-overflow.js -test/js/node/test/parallel/test-console-not-call-toString.js -test/js/node/test/parallel/test-console-self-assign.js -test/js/node/test/parallel/test-console-sync-write-error.js -test/js/node/test/parallel/test-console-tty-colors.js -test/js/node/test/parallel/test-console-with-frozen-intrinsics.js -test/js/node/test/parallel/test-coverage-with-inspector-disabled.js -test/js/node/test/parallel/test-crypto-async-sign-verify.js -test/js/node/test/parallel/test-crypto-certificate.js -test/js/node/test/parallel/test-crypto-cipheriv-decipheriv.js -test/js/node/test/parallel/test-crypto-classes.js -test/js/node/test/parallel/test-crypto-dh-constructor.js -test/js/node/test/parallel/test-crypto-dh-curves.js -test/js/node/test/parallel/test-crypto-dh-errors.js -test/js/node/test/parallel/test-crypto-dh-generate-keys.js -test/js/node/test/parallel/test-crypto-dh-leak.js -test/js/node/test/parallel/test-crypto-dh-odd-key.js -test/js/node/test/parallel/test-crypto-dh-padding.js -test/js/node/test/parallel/test-crypto-dh-shared.js -test/js/node/test/parallel/test-crypto-dh.js -test/js/node/test/parallel/test-crypto-domain.js -test/js/node/test/parallel/test-crypto-ecdh-convert-key.js -test/js/node/test/parallel/test-crypto-encoding-validation-error.js -test/js/node/test/parallel/test-crypto-from-binary.js -test/js/node/test/parallel/test-crypto-gcm-explicit-short-tag.js -test/js/node/test/parallel/test-crypto-gcm-implicit-short-tag.js -test/js/node/test/parallel/test-crypto-getcipherinfo.js -test/js/node/test/parallel/test-crypto-hash-stream-pipe.js -test/js/node/test/parallel/test-crypto-hash.js -test/js/node/test/parallel/test-crypto-hkdf.js -test/js/node/test/parallel/test-crypto-hmac.js -test/js/node/test/parallel/test-crypto-key-objects.js -test/js/node/test/parallel/test-crypto-keygen-async-dsa-key-object.js -test/js/node/test/parallel/test-crypto-keygen-async-dsa.js -test/js/node/test/parallel/test-crypto-keygen-async-elliptic-curve-jwk-ec.js -test/js/node/test/parallel/test-crypto-keygen-async-elliptic-curve-jwk-rsa.js -test/js/node/test/parallel/test-crypto-keygen-async-elliptic-curve-jwk.js -test/js/node/test/parallel/test-crypto-keygen-async-encrypted-private-key-der.js -test/js/node/test/parallel/test-crypto-keygen-async-encrypted-private-key.js -test/js/node/test/parallel/test-crypto-keygen-async-explicit-elliptic-curve-encrypted-p256.js -test/js/node/test/parallel/test-crypto-keygen-async-explicit-elliptic-curve-encrypted.js.js -test/js/node/test/parallel/test-crypto-keygen-async-explicit-elliptic-curve.js -test/js/node/test/parallel/test-crypto-keygen-async-named-elliptic-curve-encrypted-p256.js -test/js/node/test/parallel/test-crypto-keygen-async-named-elliptic-curve-encrypted.js -test/js/node/test/parallel/test-crypto-keygen-async-named-elliptic-curve.js -test/js/node/test/parallel/test-crypto-keygen-async-rsa.js -test/js/node/test/parallel/test-crypto-keygen-bit-length.js -test/js/node/test/parallel/test-crypto-keygen-duplicate-deprecated-option.js -test/js/node/test/parallel/test-crypto-keygen-eddsa.js -test/js/node/test/parallel/test-crypto-keygen-empty-passphrase-no-error.js -test/js/node/test/parallel/test-crypto-keygen-empty-passphrase-no-prompt.js -test/js/node/test/parallel/test-crypto-keygen-invalid-parameter-encoding-dsa.js -test/js/node/test/parallel/test-crypto-keygen-invalid-parameter-encoding-ec.js -test/js/node/test/parallel/test-crypto-keygen-key-object-without-encoding.js -test/js/node/test/parallel/test-crypto-keygen-key-objects.js -test/js/node/test/parallel/test-crypto-keygen-missing-oid.js -test/js/node/test/parallel/test-crypto-keygen-non-standard-public-exponent.js -test/js/node/test/parallel/test-crypto-keygen-promisify.js -test/js/node/test/parallel/test-crypto-keygen-rfc8017-9-1.js -test/js/node/test/parallel/test-crypto-keygen-rfc8017-a-2-3.js -test/js/node/test/parallel/test-crypto-keygen-rsa-pss.js -test/js/node/test/parallel/test-crypto-keygen-sync.js -test/js/node/test/parallel/test-crypto-lazy-transform-writable.js -test/js/node/test/parallel/test-crypto-no-algorithm.js -test/js/node/test/parallel/test-crypto-oaep-zero-length.js -test/js/node/test/parallel/test-crypto-oneshot-hash.js -test/js/node/test/parallel/test-crypto-op-during-process-exit.js -test/js/node/test/parallel/test-crypto-padding.js -test/js/node/test/parallel/test-crypto-padding-aes256.js -test/js/node/test/parallel/test-crypto-pbkdf2.js -test/js/node/test/parallel/test-crypto-prime.js -test/js/node/test/parallel/test-crypto-private-decrypt-gh32240.js -test/js/node/test/parallel/test-crypto-psychic-signatures.js -test/js/node/test/parallel/test-crypto-publicDecrypt-fails-first-time.js -test/js/node/test/parallel/test-crypto-random.js -test/js/node/test/parallel/test-crypto-randomfillsync-regression.js -test/js/node/test/parallel/test-crypto-randomuuid.js -test/js/node/test/parallel/test-crypto-scrypt.js -test/js/node/test/parallel/test-crypto-secret-keygen.js -test/js/node/test/parallel/test-crypto-sign-verify.js -test/js/node/test/parallel/test-crypto-stream.js -test/js/node/test/parallel/test-crypto-subtle-zero-length.js -test/js/node/test/parallel/test-crypto-update-encoding.js -test/js/node/test/parallel/test-crypto-verify-failure.js -test/js/node/test/parallel/test-crypto-webcrypto-aes-decrypt-tag-too-small.js -test/js/node/test/parallel/test-crypto-worker-thread.js -test/js/node/test/parallel/test-crypto-x509.js -test/js/node/test/parallel/test-datetime-change-notify.js -test/js/node/test/parallel/test-debug-process.js -test/js/node/test/parallel/test-debugger-backtrace.js -test/js/node/test/parallel/test-debugger-exec.js -test/js/node/test/parallel/test-debugger-invalid-json.mjs -test/js/node/test/parallel/test-debugger-low-level.js -test/js/node/test/parallel/test-debugger-preserve-breaks.js -test/js/node/test/parallel/test-debugger-repeat-last.js -test/js/node/test/parallel/test-debugger-restart-message.js -test/js/node/test/parallel/test-delayed-require.js -test/js/node/test/parallel/test-destroy-socket-in-lookup.js -test/js/node/test/parallel/test-dgram-abort-closed.js -test/js/node/test/parallel/test-dgram-address.js -test/js/node/test/parallel/test-dgram-async-dispose.mjs -test/js/node/test/parallel/test-dgram-bind-default-address.js -test/js/node/test/parallel/test-dgram-bind-error-repeat.js -test/js/node/test/parallel/test-dgram-bind-socket-close-before-lookup.js -test/js/node/test/parallel/test-dgram-bind.js -test/js/node/test/parallel/test-dgram-bytes-length.js -test/js/node/test/parallel/test-dgram-close-during-bind.js -test/js/node/test/parallel/test-dgram-close-in-listening.js -test/js/node/test/parallel/test-dgram-close-is-not-callback.js -test/js/node/test/parallel/test-dgram-close-signal.js -test/js/node/test/parallel/test-dgram-close.js -test/js/node/test/parallel/test-dgram-cluster-close-during-bind.js -test/js/node/test/parallel/test-dgram-cluster-close-in-listening.js -test/js/node/test/parallel/test-dgram-connect-send-callback-buffer-length.js -test/js/node/test/parallel/test-dgram-connect-send-callback-buffer.js -test/js/node/test/parallel/test-dgram-connect-send-callback-multi-buffer.js -test/js/node/test/parallel/test-dgram-connect-send-default-host.js -test/js/node/test/parallel/test-dgram-connect-send-empty-array.js -test/js/node/test/parallel/test-dgram-connect-send-empty-buffer.js -test/js/node/test/parallel/test-dgram-connect-send-empty-packet.js -test/js/node/test/parallel/test-dgram-connect-send-multi-buffer-copy.js -test/js/node/test/parallel/test-dgram-connect-send-multi-string-array.js -test/js/node/test/parallel/test-dgram-connect.js -test/js/node/test/parallel/test-dgram-custom-lookup.js -test/js/node/test/parallel/test-dgram-deprecation-error.js -test/js/node/test/parallel/test-dgram-error-message-address.js -test/js/node/test/parallel/test-dgram-implicit-bind.js -test/js/node/test/parallel/test-dgram-ipv6only.js -test/js/node/test/parallel/test-dgram-listen-after-bind.js -test/js/node/test/parallel/test-dgram-membership.js -test/js/node/test/parallel/test-dgram-msgsize.js -test/js/node/test/parallel/test-dgram-multicast-loopback.js -test/js/node/test/parallel/test-dgram-multicast-set-interface.js -test/js/node/test/parallel/test-dgram-multicast-setTTL.js -test/js/node/test/parallel/test-dgram-oob-buffer.js -test/js/node/test/parallel/test-dgram-recv-error.js -test/js/node/test/parallel/test-dgram-ref.js -test/js/node/test/parallel/test-dgram-reuseport.js -test/js/node/test/parallel/test-dgram-send-address-types.js -test/js/node/test/parallel/test-dgram-send-bad-arguments.js -test/js/node/test/parallel/test-dgram-send-callback-buffer-empty-address.js -test/js/node/test/parallel/test-dgram-send-callback-buffer-length-empty-address.js -test/js/node/test/parallel/test-dgram-send-callback-buffer-length.js -test/js/node/test/parallel/test-dgram-send-callback-buffer.js -test/js/node/test/parallel/test-dgram-send-callback-multi-buffer-empty-address.js -test/js/node/test/parallel/test-dgram-send-callback-multi-buffer.js -test/js/node/test/parallel/test-dgram-send-callback-recursive.js -test/js/node/test/parallel/test-dgram-send-cb-quelches-error.js -test/js/node/test/parallel/test-dgram-send-default-host.js -test/js/node/test/parallel/test-dgram-send-empty-array.js -test/js/node/test/parallel/test-dgram-send-empty-buffer.js -test/js/node/test/parallel/test-dgram-send-empty-packet.js -test/js/node/test/parallel/test-dgram-send-error.js -test/js/node/test/parallel/test-dgram-send-invalid-msg-type.js -test/js/node/test/parallel/test-dgram-send-multi-buffer-copy.js -test/js/node/test/parallel/test-dgram-send-multi-string-array.js -test/js/node/test/parallel/test-dgram-sendto.js -test/js/node/test/parallel/test-dgram-setBroadcast.js -test/js/node/test/parallel/test-dgram-setTTL.js -test/js/node/test/parallel/test-dgram-udp4.js -test/js/node/test/parallel/test-dgram-udp6-link-local-address.js -test/js/node/test/parallel/test-dgram-udp6-send-default-host.js -test/js/node/test/parallel/test-dgram-unref-in-cluster.js -test/js/node/test/parallel/test-dgram-unref.js -test/js/node/test/parallel/test-diagnostics-channel-bind-store.js -test/js/node/test/parallel/test-diagnostics-channel-has-subscribers.js -test/js/node/test/parallel/test-diagnostics-channel-object-channel-pub-sub.js -test/js/node/test/parallel/test-diagnostics-channel-pub-sub.js -test/js/node/test/parallel/test-diagnostics-channel-safe-subscriber-errors.js -test/js/node/test/parallel/test-diagnostics-channel-symbol-named.js -test/js/node/test/parallel/test-diagnostics-channel-sync-unsubscribe.js -test/js/node/test/parallel/test-diagnostics-channel-tracing-channel-callback-error.js -test/js/node/test/parallel/test-diagnostics-channel-tracing-channel-callback-run-stores.js -test/js/node/test/parallel/test-diagnostics-channel-tracing-channel-callback.js -test/js/node/test/parallel/test-diagnostics-channel-tracing-channel-promise-error.js -test/js/node/test/parallel/test-diagnostics-channel-tracing-channel-promise-run-stores.js -test/js/node/test/parallel/test-diagnostics-channel-tracing-channel-promise.js -test/js/node/test/parallel/test-diagnostics-channel-tracing-channel-sync-error.js -test/js/node/test/parallel/test-diagnostics-channel-tracing-channel-sync-run-stores.js -test/js/node/test/parallel/test-diagnostics-channel-tracing-channel-sync.js -test/js/node/test/parallel/test-diagnostics-channel-udp.js -test/js/node/test/parallel/test-domain-crypto.js -test/js/node/test/parallel/test-domain-ee-error-listener.js -test/js/node/test/parallel/test-domain-nested-throw.js -test/js/node/test/parallel/test-domain-vm-promise-isolation.js -test/js/node/test/parallel/test-domexception-cause.js -test/js/node/test/parallel/test-dsa-fips-invalid-key.js -test/js/node/test/parallel/test-emit-after-uncaught-exception.js -test/js/node/test/parallel/test-error-prepare-stack-trace.js -test/js/node/test/parallel/test-eslint-alphabetize-errors.js -test/js/node/test/parallel/test-eslint-alphabetize-primordials.js -test/js/node/test/parallel/test-eslint-async-iife-no-unused-result.js -test/js/node/test/parallel/test-eslint-avoid-prototype-pollution.js -test/js/node/test/parallel/test-eslint-crypto-check.js -test/js/node/test/parallel/test-eslint-documented-deprecation-codes.js -test/js/node/test/parallel/test-eslint-documented-errors.js -test/js/node/test/parallel/test-eslint-duplicate-requires.js -test/js/node/test/parallel/test-eslint-eslint-check.js -test/js/node/test/parallel/test-eslint-inspector-check.js -test/js/node/test/parallel/test-eslint-lowercase-name-for-primitive.js -test/js/node/test/parallel/test-eslint-no-array-destructuring.js -test/js/node/test/parallel/test-eslint-no-unescaped-regexp-dot.js -test/js/node/test/parallel/test-eslint-non-ascii-character.js -test/js/node/test/parallel/test-eslint-prefer-assert-iferror.js -test/js/node/test/parallel/test-eslint-prefer-assert-methods.js -test/js/node/test/parallel/test-eslint-prefer-common-mustnotcall.js -test/js/node/test/parallel/test-eslint-prefer-common-mustsucceed.js -test/js/node/test/parallel/test-eslint-prefer-optional-chaining.js -test/js/node/test/parallel/test-eslint-prefer-primordials.js -test/js/node/test/parallel/test-eslint-prefer-proto.js -test/js/node/test/parallel/test-eslint-prefer-util-format-errors.js -test/js/node/test/parallel/test-eslint-require-common-first.js -test/js/node/test/parallel/test-eslint-required-modules.js -test/js/node/test/parallel/test-eval-strict-referenceerror.js -test/js/node/test/parallel/test-eval.js -test/js/node/test/parallel/test-event-capture-rejections.js -test/js/node/test/parallel/test-event-emitter-add-listeners.js -test/js/node/test/parallel/test-event-emitter-check-listener-leaks.js -test/js/node/test/parallel/test-event-emitter-emit-context.js -test/js/node/test/parallel/test-event-emitter-error-monitor.js -test/js/node/test/parallel/test-event-emitter-errors.js -test/js/node/test/parallel/test-event-emitter-get-max-listeners.js -test/js/node/test/parallel/test-event-emitter-invalid-listener.js -test/js/node/test/parallel/test-event-emitter-listener-count.js -test/js/node/test/parallel/test-event-emitter-listeners-side-effects.js -test/js/node/test/parallel/test-event-emitter-listeners.js -test/js/node/test/parallel/test-event-emitter-max-listeners-warning-for-null.js -test/js/node/test/parallel/test-event-emitter-max-listeners-warning-for-symbol.js -test/js/node/test/parallel/test-event-emitter-max-listeners-warning.js -test/js/node/test/parallel/test-event-emitter-max-listeners.js -test/js/node/test/parallel/test-event-emitter-method-names.js -test/js/node/test/parallel/test-event-emitter-modify-in-emit.js -test/js/node/test/parallel/test-event-emitter-no-error-provided-to-error-event.js -test/js/node/test/parallel/test-event-emitter-num-args.js -test/js/node/test/parallel/test-event-emitter-once.js -test/js/node/test/parallel/test-event-emitter-prepend.js -test/js/node/test/parallel/test-event-emitter-remove-all-listeners.js -test/js/node/test/parallel/test-event-emitter-remove-listeners.js -test/js/node/test/parallel/test-event-emitter-set-max-listeners-side-effects.js -test/js/node/test/parallel/test-event-emitter-special-event-names.js -test/js/node/test/parallel/test-event-emitter-subclass.js -test/js/node/test/parallel/test-event-emitter-symbols.js -test/js/node/test/parallel/test-event-target.js -test/js/node/test/parallel/test-events-add-abort-listener.mjs -test/js/node/test/parallel/test-events-customevent.js -test/js/node/test/parallel/test-events-getmaxlisteners.js -test/js/node/test/parallel/test-events-list.js -test/js/node/test/parallel/test-events-listener-count-with-listener.js -test/js/node/test/parallel/test-events-on-async-iterator.js -test/js/node/test/parallel/test-events-once.js -test/js/node/test/parallel/test-events-static-geteventlisteners.js -test/js/node/test/parallel/test-events-uncaught-exception-stack.js -test/js/node/test/parallel/test-eventsource-disabled.js -test/js/node/test/parallel/test-eventtarget-once-twice.js -test/js/node/test/parallel/test-eventtarget.js -test/js/node/test/parallel/test-exception-handler.js -test/js/node/test/parallel/test-exception-handler2.js -test/js/node/test/parallel/test-fetch.mjs -test/js/node/test/parallel/test-global-domexception.js -test/js/node/test/parallel/test-global-encoder.js -test/js/node/test/parallel/test-global-webcrypto.js -test/js/node/test/parallel/test-handle-wrap-close-abort.js -test/js/node/test/parallel/test-http-1.0-keep-alive.js -test/js/node/test/parallel/test-http-abort-before-end.js -test/js/node/test/parallel/test-http-abort-stream-end.js -test/js/node/test/parallel/test-http-aborted.js -test/js/node/test/parallel/test-http-agent-false.js -test/js/node/test/parallel/test-http-agent-getname.js -test/js/node/test/parallel/test-http-agent-keepalive-delay.js -test/js/node/test/parallel/test-http-agent-no-protocol.js -test/js/node/test/parallel/test-http-agent-null.js -test/js/node/test/parallel/test-http-agent-remove.js -test/js/node/test/parallel/test-http-agent-uninitialized-with-handle.js -test/js/node/test/parallel/test-http-agent-uninitialized.js -test/js/node/test/parallel/test-http-allow-content-length-304.js -test/js/node/test/parallel/test-http-allow-req-after-204-res.js -test/js/node/test/parallel/test-http-autoselectfamily.js -test/js/node/test/parallel/test-http-bind-twice.js -test/js/node/test/parallel/test-http-blank-header.js -test/js/node/test/parallel/test-http-buffer-sanity.js -test/js/node/test/parallel/test-http-byteswritten.js -test/js/node/test/parallel/test-http-catch-uncaughtexception.js -test/js/node/test/parallel/test-http-chunk-problem.js -test/js/node/test/parallel/test-http-chunked-smuggling.js -test/js/node/test/parallel/test-http-chunked.js -test/js/node/test/parallel/test-http-client-abort-event.js -test/js/node/test/parallel/test-http-client-abort-response-event.js -test/js/node/test/parallel/test-http-client-abort.js -test/js/node/test/parallel/test-http-client-abort2.js -test/js/node/test/parallel/test-http-client-agent-abort-close-event.js -test/js/node/test/parallel/test-http-client-check-http-token.js -test/js/node/test/parallel/test-http-client-close-with-default-agent.js -test/js/node/test/parallel/test-http-client-defaults.js -test/js/node/test/parallel/test-http-client-encoding.js -test/js/node/test/parallel/test-http-client-get-url.js -test/js/node/test/parallel/test-http-client-headers-host-array.js -test/js/node/test/parallel/test-http-client-input-function.js -test/js/node/test/parallel/test-http-client-insecure-http-parser-error.js -test/js/node/test/parallel/test-http-client-invalid-path.js -test/js/node/test/parallel/test-http-client-keep-alive-hint.js -test/js/node/test/parallel/test-http-client-keep-alive-release-before-finish.js -test/js/node/test/parallel/test-http-client-pipe-end.js -test/js/node/test/parallel/test-http-client-race-2.js -test/js/node/test/parallel/test-http-client-race.js -test/js/node/test/parallel/test-http-client-read-in-error.js -test/js/node/test/parallel/test-http-client-reject-unexpected-agent.js -test/js/node/test/parallel/test-http-client-req-error-dont-double-fire.js -test/js/node/test/parallel/test-http-client-request-options.js -test/js/node/test/parallel/test-http-client-res-destroyed.js -test/js/node/test/parallel/test-http-client-timeout-agent.js -test/js/node/test/parallel/test-http-client-timeout-connect-listener.js -test/js/node/test/parallel/test-http-client-timeout-event.js -test/js/node/test/parallel/test-http-client-timeout-option.js -test/js/node/test/parallel/test-http-client-timeout.js -test/js/node/test/parallel/test-http-client-unescaped-path.js -test/js/node/test/parallel/test-http-client-upload-buf.js -test/js/node/test/parallel/test-http-client-upload.js -test/js/node/test/parallel/test-http-client-with-create-connection.js -test/js/node/test/parallel/test-http-common.js -test/js/node/test/parallel/test-http-conn-reset.js -test/js/node/test/parallel/test-http-content-length-mismatch.js -test/js/node/test/parallel/test-http-contentLength0.js -test/js/node/test/parallel/test-http-date-header.js -test/js/node/test/parallel/test-http-decoded-auth.js -test/js/node/test/parallel/test-http-default-encoding.js -test/js/node/test/parallel/test-http-dns-error.js -test/js/node/test/parallel/test-http-double-content-length.js -test/js/node/test/parallel/test-http-dummy-characters-smuggling.js -test/js/node/test/parallel/test-http-early-hints-invalid-argument.js -test/js/node/test/parallel/test-http-end-throw-socket-handling.js -test/js/node/test/parallel/test-http-eof-on-connect.js -test/js/node/test/parallel/test-http-exceptions.js -test/js/node/test/parallel/test-http-expect-continue.js -test/js/node/test/parallel/test-http-expect-handling.js -test/js/node/test/parallel/test-http-extra-response.js -test/js/node/test/parallel/test-http-flush-headers.js -test/js/node/test/parallel/test-http-flush-response-headers.js -test/js/node/test/parallel/test-http-full-response.js -test/js/node/test/parallel/test-http-get-pipeline-problem.js -test/js/node/test/parallel/test-http-head-request.js -test/js/node/test/parallel/test-http-head-response-has-no-body-end-implicit-headers.js -test/js/node/test/parallel/test-http-head-response-has-no-body-end.js -test/js/node/test/parallel/test-http-head-response-has-no-body.js -test/js/node/test/parallel/test-http-head-throw-on-response-body-write.js -test/js/node/test/parallel/test-http-header-obstext.js -test/js/node/test/parallel/test-http-header-overflow.js -test/js/node/test/parallel/test-http-header-owstext.js -test/js/node/test/parallel/test-http-header-read.js -test/js/node/test/parallel/test-http-header-validators.js -test/js/node/test/parallel/test-http-hex-write.js -test/js/node/test/parallel/test-http-highwatermark.js -test/js/node/test/parallel/test-http-host-headers.js -test/js/node/test/parallel/test-http-hostname-typechecking.js -test/js/node/test/parallel/test-http-import-websocket.js -test/js/node/test/parallel/test-http-incoming-message-destroy.js -test/js/node/test/parallel/test-http-invalid-path-chars.js -test/js/node/test/parallel/test-http-invalid-te.js -test/js/node/test/parallel/test-http-invalid-urls.js -test/js/node/test/parallel/test-http-invalidheaderfield.js -test/js/node/test/parallel/test-http-invalidheaderfield2.js -test/js/node/test/parallel/test-http-keep-alive-drop-requests.js -test/js/node/test/parallel/test-http-keep-alive-pipeline-max-requests.js -test/js/node/test/parallel/test-http-keep-alive-timeout-custom.js -test/js/node/test/parallel/test-http-keep-alive-timeout-race-condition.js -test/js/node/test/parallel/test-http-listening.js -test/js/node/test/parallel/test-http-malformed-request.js -test/js/node/test/parallel/test-http-many-ended-pipelines.js -test/js/node/test/parallel/test-http-max-header-size.js -test/js/node/test/parallel/test-http-methods.js -test/js/node/test/parallel/test-http-missing-header-separator-cr.js -test/js/node/test/parallel/test-http-missing-header-separator-lf.js -test/js/node/test/parallel/test-http-no-content-length.js -test/js/node/test/parallel/test-http-outgoing-buffer.js -test/js/node/test/parallel/test-http-outgoing-destroy.js -test/js/node/test/parallel/test-http-outgoing-end-multiple.js -test/js/node/test/parallel/test-http-outgoing-end-types.js -test/js/node/test/parallel/test-http-outgoing-finish-writable.js -test/js/node/test/parallel/test-http-outgoing-finish.js -test/js/node/test/parallel/test-http-outgoing-finished.js -test/js/node/test/parallel/test-http-outgoing-first-chunk-singlebyte-encoding.js -test/js/node/test/parallel/test-http-outgoing-internal-headernames-getter.js -test/js/node/test/parallel/test-http-outgoing-internal-headernames-setter.js -test/js/node/test/parallel/test-http-outgoing-internal-headers.js -test/js/node/test/parallel/test-http-outgoing-message-write-callback.js -test/js/node/test/parallel/test-http-outgoing-proto.js -test/js/node/test/parallel/test-http-outgoing-settimeout.js -test/js/node/test/parallel/test-http-outgoing-writableFinished.js -test/js/node/test/parallel/test-http-outgoing-write-types.js -test/js/node/test/parallel/test-http-parser-bad-ref.js -test/js/node/test/parallel/test-http-parser-lazy-loaded.js -test/js/node/test/parallel/test-http-parser.js -test/js/node/test/parallel/test-http-pause-no-dump.js -test/js/node/test/parallel/test-http-pause-resume-one-end.js -test/js/node/test/parallel/test-http-pause.js -test/js/node/test/parallel/test-http-pipe-fs.js -test/js/node/test/parallel/test-http-pipeline-requests-connection-leak.js -test/js/node/test/parallel/test-http-pipeline-socket-parser-typeerror.js -test/js/node/test/parallel/test-http-proxy.js -test/js/node/test/parallel/test-http-readable-data-event.js -test/js/node/test/parallel/test-http-request-agent.js -test/js/node/test/parallel/test-http-request-arguments.js -test/js/node/test/parallel/test-http-request-end-twice.js -test/js/node/test/parallel/test-http-request-end.js -test/js/node/test/parallel/test-http-request-invalid-method-error.js -test/js/node/test/parallel/test-http-request-large-payload.js -test/js/node/test/parallel/test-http-request-method-delete-payload.js -test/js/node/test/parallel/test-http-request-methods.js -test/js/node/test/parallel/test-http-request-smuggling-content-length.js -test/js/node/test/parallel/test-http-res-write-after-end.js -test/js/node/test/parallel/test-http-res-write-end-dont-take-array.js -test/js/node/test/parallel/test-http-response-add-header-after-sent.js -test/js/node/test/parallel/test-http-response-close.js -test/js/node/test/parallel/test-http-response-cork.js -test/js/node/test/parallel/test-http-response-multi-content-length.js -test/js/node/test/parallel/test-http-response-readable.js -test/js/node/test/parallel/test-http-response-remove-header-after-sent.js -test/js/node/test/parallel/test-http-response-setheaders.js -test/js/node/test/parallel/test-http-response-splitting.js -test/js/node/test/parallel/test-http-response-status-message.js -test/js/node/test/parallel/test-http-response-statuscode.js -test/js/node/test/parallel/test-http-response-writehead-returns-this.js -test/js/node/test/parallel/test-http-server-async-dispose.js -test/js/node/test/parallel/test-http-server-capture-rejections.js -test/js/node/test/parallel/test-http-server-close-all.js -test/js/node/test/parallel/test-http-server-close-destroy-timeout.js -test/js/node/test/parallel/test-http-server-close-idle-wait-response.js -test/js/node/test/parallel/test-http-server-de-chunked-trailer.js -test/js/node/test/parallel/test-http-server-delete-parser.js -test/js/node/test/parallel/test-http-server-destroy-socket-on-client-error.js -test/js/node/test/parallel/test-http-server-keep-alive-defaults.js -test/js/node/test/parallel/test-http-server-keep-alive-max-requests-null.js -test/js/node/test/parallel/test-http-server-method.query.js -test/js/node/test/parallel/test-http-server-multiheaders.js -test/js/node/test/parallel/test-http-server-non-utf8-header.js -test/js/node/test/parallel/test-http-server-options-incoming-message.js -test/js/node/test/parallel/test-http-server-options-server-response.js -test/js/node/test/parallel/test-http-server-reject-chunked-with-content-length.js -test/js/node/test/parallel/test-http-server-stale-close.js -test/js/node/test/parallel/test-http-server-timeouts-validation.js -test/js/node/test/parallel/test-http-server-write-after-end.js -test/js/node/test/parallel/test-http-server-write-end-after-end.js -test/js/node/test/parallel/test-http-set-cookies.js -test/js/node/test/parallel/test-http-set-header-chain.js -test/js/node/test/parallel/test-http-set-max-idle-http-parser.js -test/js/node/test/parallel/test-http-socket-error-listeners.js -test/js/node/test/parallel/test-http-status-code.js -test/js/node/test/parallel/test-http-status-message.js -test/js/node/test/parallel/test-http-status-reason-invalid-chars.js -test/js/node/test/parallel/test-http-timeout-client-warning.js -test/js/node/test/parallel/test-http-timeout-overflow.js -test/js/node/test/parallel/test-http-timeout.js -test/js/node/test/parallel/test-http-uncaught-from-request-callback.js -test/js/node/test/parallel/test-http-upgrade-reconsume-stream.js -test/js/node/test/parallel/test-http-url.parse-auth-with-header-in-request.js -test/js/node/test/parallel/test-http-url.parse-auth.js -test/js/node/test/parallel/test-http-url.parse-basic.js -test/js/node/test/parallel/test-http-url.parse-only-support-http-https-protocol.js -test/js/node/test/parallel/test-http-url.parse-path.js -test/js/node/test/parallel/test-http-url.parse-post.js -test/js/node/test/parallel/test-http-url.parse-search.js -test/js/node/test/parallel/test-http-wget.js -test/js/node/test/parallel/test-http-write-callbacks.js -test/js/node/test/parallel/test-http-write-empty-string.js -test/js/node/test/parallel/test-http-write-head-2.js -test/js/node/test/parallel/test-http-write-head.js -test/js/node/test/parallel/test-http-zero-length-write.js -test/js/node/test/parallel/test-http-zerolengthbuffer.js -test/js/node/test/parallel/test-http2-altsvc.js -test/js/node/test/parallel/test-http2-cancel-while-client-reading.js -test/js/node/test/parallel/test-http2-clean-output.js -test/js/node/test/parallel/test-http2-client-port-80.js -test/js/node/test/parallel/test-http2-client-priority-before-connect.js -test/js/node/test/parallel/test-http2-client-request-listeners-warning.js -test/js/node/test/parallel/test-http2-client-request-options-errors.js -test/js/node/test/parallel/test-http2-client-rststream-before-connect.js -test/js/node/test/parallel/test-http2-client-setLocalWindowSize.js -test/js/node/test/parallel/test-http2-client-setNextStreamID-errors.js -test/js/node/test/parallel/test-http2-client-shutdown-before-connect.js -test/js/node/test/parallel/test-http2-client-stream-destroy-before-connect.js -test/js/node/test/parallel/test-http2-client-upload-reject.js -test/js/node/test/parallel/test-http2-client-upload.js -test/js/node/test/parallel/test-http2-client-write-before-connect.js -test/js/node/test/parallel/test-http2-client-write-empty-string.js -test/js/node/test/parallel/test-http2-close-while-writing.js -test/js/node/test/parallel/test-http2-compat-aborted.js -test/js/node/test/parallel/test-http2-compat-client-upload-reject.js -test/js/node/test/parallel/test-http2-compat-errors.js -test/js/node/test/parallel/test-http2-compat-expect-continue-check.js -test/js/node/test/parallel/test-http2-compat-expect-continue.js -test/js/node/test/parallel/test-http2-compat-expect-handling.js -test/js/node/test/parallel/test-http2-compat-method-connect.js -test/js/node/test/parallel/test-http2-compat-serverrequest-end.js -test/js/node/test/parallel/test-http2-compat-serverrequest-headers.js -test/js/node/test/parallel/test-http2-compat-serverrequest-host.js -test/js/node/test/parallel/test-http2-compat-serverrequest-pause.js -test/js/node/test/parallel/test-http2-compat-serverrequest-pipe.js -test/js/node/test/parallel/test-http2-compat-serverrequest-settimeout.js -test/js/node/test/parallel/test-http2-compat-serverrequest-trailers.js -test/js/node/test/parallel/test-http2-compat-serverrequest.js -test/js/node/test/parallel/test-http2-compat-serverresponse-close.js -test/js/node/test/parallel/test-http2-compat-serverresponse-destroy.js -test/js/node/test/parallel/test-http2-compat-serverresponse-end-after-statuses-without-body.js -test/js/node/test/parallel/test-http2-compat-serverresponse-finished.js -test/js/node/test/parallel/test-http2-compat-serverresponse-flushheaders.js -test/js/node/test/parallel/test-http2-compat-serverresponse-headers-send-date.js -test/js/node/test/parallel/test-http2-compat-serverresponse-settimeout.js -test/js/node/test/parallel/test-http2-compat-serverresponse-statuscode.js -test/js/node/test/parallel/test-http2-compat-serverresponse-statusmessage-property-set.js -test/js/node/test/parallel/test-http2-compat-serverresponse-statusmessage-property.js -test/js/node/test/parallel/test-http2-compat-serverresponse-write.js -test/js/node/test/parallel/test-http2-compat-serverresponse.js -test/js/node/test/parallel/test-http2-compat-socket-destroy-delayed.js -test/js/node/test/parallel/test-http2-compat-write-early-hints-invalid-argument-type.js -test/js/node/test/parallel/test-http2-compat-write-early-hints-invalid-argument-value.js -test/js/node/test/parallel/test-http2-compat-write-early-hints.js -test/js/node/test/parallel/test-http2-compat-write-head-after-close.js -test/js/node/test/parallel/test-http2-compat-write-head-destroyed.js -test/js/node/test/parallel/test-http2-connect-tls-with-delay.js -test/js/node/test/parallel/test-http2-connect.js -test/js/node/test/parallel/test-http2-cookies.js -test/js/node/test/parallel/test-http2-create-client-connect.js -test/js/node/test/parallel/test-http2-create-client-session.js -test/js/node/test/parallel/test-http2-createsecureserver-options.js -test/js/node/test/parallel/test-http2-createserver-options.js -test/js/node/test/parallel/test-http2-createwritereq.js -test/js/node/test/parallel/test-http2-date-header.js -test/js/node/test/parallel/test-http2-destroy-after-write.js -test/js/node/test/parallel/test-http2-dont-override.js -test/js/node/test/parallel/test-http2-endafterheaders.js -test/js/node/test/parallel/test-http2-error-order.js -test/js/node/test/parallel/test-http2-forget-closed-streams.js -test/js/node/test/parallel/test-http2-goaway-opaquedata.js -test/js/node/test/parallel/test-http2-graceful-close.js -test/js/node/test/parallel/test-http2-head-request.js -test/js/node/test/parallel/test-http2-info-headers.js -test/js/node/test/parallel/test-http2-invalidargtypes-errors.js -test/js/node/test/parallel/test-http2-large-write-close.js -test/js/node/test/parallel/test-http2-large-write-destroy.js -test/js/node/test/parallel/test-http2-large-write-multiple-requests.js -test/js/node/test/parallel/test-http2-large-writes-session-memory-leak.js -test/js/node/test/parallel/test-http2-malformed-altsvc.js -test/js/node/test/parallel/test-http2-many-writes-and-destroy.js -test/js/node/test/parallel/test-http2-max-session-memory-leak.js -test/js/node/test/parallel/test-http2-methods.js -test/js/node/test/parallel/test-http2-misbehaving-flow-control-paused.js -test/js/node/test/parallel/test-http2-misbehaving-flow-control.js -test/js/node/test/parallel/test-http2-misused-pseudoheaders.js -test/js/node/test/parallel/test-http2-multiheaders-raw.js -test/js/node/test/parallel/test-http2-multiheaders.js -test/js/node/test/parallel/test-http2-multiplex.js -test/js/node/test/parallel/test-http2-multistream-destroy-on-read-tls.js -test/js/node/test/parallel/test-http2-no-more-streams.js -test/js/node/test/parallel/test-http2-no-wanttrailers-listener.js -test/js/node/test/parallel/test-http2-options-max-headers-block-length.js -test/js/node/test/parallel/test-http2-origin.js -test/js/node/test/parallel/test-http2-pipe-named-pipe.js -test/js/node/test/parallel/test-http2-pipe.js -test/js/node/test/parallel/test-http2-premature-close.js -test/js/node/test/parallel/test-http2-priority-cycle-.js -test/js/node/test/parallel/test-http2-request-remove-connect-listener.js -test/js/node/test/parallel/test-http2-request-response-proto.js -test/js/node/test/parallel/test-http2-res-corked.js -test/js/node/test/parallel/test-http2-respond-errors.js -test/js/node/test/parallel/test-http2-respond-file-204.js -test/js/node/test/parallel/test-http2-respond-file-304.js -test/js/node/test/parallel/test-http2-respond-file-404.js -test/js/node/test/parallel/test-http2-respond-file-compat.js -test/js/node/test/parallel/test-http2-respond-file-error-dir.js -test/js/node/test/parallel/test-http2-respond-file-error-pipe-offset.js -test/js/node/test/parallel/test-http2-respond-file-errors.js -test/js/node/test/parallel/test-http2-respond-file-fd-errors.js -test/js/node/test/parallel/test-http2-respond-file-fd-invalid.js -test/js/node/test/parallel/test-http2-respond-file-fd-range.js -test/js/node/test/parallel/test-http2-respond-file-fd.js -test/js/node/test/parallel/test-http2-respond-file-filehandle.js -test/js/node/test/parallel/test-http2-respond-file-range.js -test/js/node/test/parallel/test-http2-respond-file.js -test/js/node/test/parallel/test-http2-respond-no-data.js -test/js/node/test/parallel/test-http2-respond-with-file-connection-abort.js -test/js/node/test/parallel/test-http2-sent-headers.js -test/js/node/test/parallel/test-http2-serve-file.js -test/js/node/test/parallel/test-http2-server-async-dispose.js -test/js/node/test/parallel/test-http2-server-close-callback.js -test/js/node/test/parallel/test-http2-server-close-idle-connection.js -test/js/node/test/parallel/test-http2-server-errors.js -test/js/node/test/parallel/test-http2-server-rst-before-respond.js -test/js/node/test/parallel/test-http2-server-session-destroy.js -test/js/node/test/parallel/test-http2-server-setLocalWindowSize.js -test/js/node/test/parallel/test-http2-server-shutdown-options-errors.js -test/js/node/test/parallel/test-http2-session-gc-while-write-scheduled.js -test/js/node/test/parallel/test-http2-session-stream-state.js -test/js/node/test/parallel/test-http2-session-timeout.js -test/js/node/test/parallel/test-http2-single-headers.js -test/js/node/test/parallel/test-http2-socket-proxy-handler-for-has.js -test/js/node/test/parallel/test-http2-status-code.js -test/js/node/test/parallel/test-http2-stream-destroy-event-order.js -test/js/node/test/parallel/test-http2-timeouts.js -test/js/node/test/parallel/test-http2-tls-disconnect.js -test/js/node/test/parallel/test-http2-too-many-headers.js -test/js/node/test/parallel/test-http2-trailers-after-session-close.js -test/js/node/test/parallel/test-http2-trailers.js -test/js/node/test/parallel/test-http2-unbound-socket-proxy.js -test/js/node/test/parallel/test-http2-write-callbacks.js -test/js/node/test/parallel/test-http2-zero-length-header.js -test/js/node/test/parallel/test-http2-zero-length-write.js -test/js/node/test/parallel/test-https-agent-constructor.js -test/js/node/test/parallel/test-https-agent-session-eviction.js -test/js/node/test/parallel/test-https-agent.js -test/js/node/test/parallel/test-https-byteswritten.js -test/js/node/test/parallel/test-https-client-get-url.js -test/js/node/test/parallel/test-https-client-renegotiation-limit.js -test/js/node/test/parallel/test-https-close.js -test/js/node/test/parallel/test-https-connecting-to-http.js -test/js/node/test/parallel/test-https-eof-for-eom.js -test/js/node/test/parallel/test-https-foafssl.js -test/js/node/test/parallel/test-https-localaddress-bind-error.js -test/js/node/test/parallel/test-https-options-boolean-check.js -test/js/node/test/parallel/test-https-selfsigned-no-keycertsign-no-crash.js -test/js/node/test/parallel/test-https-server-async-dispose.js -test/js/node/test/parallel/test-https-server-close-destroy-timeout.js -test/js/node/test/parallel/test-https-server-headers-timeout.js -test/js/node/test/parallel/test-https-server-request-timeout.js -test/js/node/test/parallel/test-https-simple.js -test/js/node/test/parallel/test-https-socket-options.js -test/js/node/test/parallel/test-https-truncate.js -test/js/node/test/parallel/test-https-unix-socket-self-signed.js -test/js/node/test/parallel/test-icu-env.js -test/js/node/test/parallel/test-icu-punycode.js -test/js/node/test/parallel/test-icu-transcode.js -test/js/node/test/parallel/test-inspect-support-for-node_options.js -test/js/node/test/parallel/test-inspector-enabled.js -test/js/node/test/parallel/test-inspector-has-inspector-false.js -test/js/node/test/parallel/test-inspector-stops-no-file.js -test/js/node/test/parallel/test-inspector-workers-flat-list.js -test/js/node/test/parallel/test-instanceof.js -test/js/node/test/parallel/test-internal-module-require.js -test/js/node/test/parallel/test-internal-process-binding.js -test/js/node/test/parallel/test-intl-v8BreakIterator.js -test/js/node/test/parallel/test-kill-segfault-freebsd.js -test/js/node/test/parallel/test-listen-fd-detached-inherit.js -test/js/node/test/parallel/test-listen-fd-detached.js -test/js/node/test/parallel/test-math-random.js -test/js/node/test/parallel/test-memory-usage-emfile.js -test/js/node/test/parallel/test-memory-usage.js -test/js/node/test/parallel/test-messagechannel.js -test/js/node/test/parallel/test-messageevent-brandcheck.js -test/js/node/test/parallel/test-microtask-queue-integration.js -test/js/node/test/parallel/test-microtask-queue-run-immediate.js -test/js/node/test/parallel/test-microtask-queue-run.js -test/js/node/test/parallel/test-mime-api.js -test/js/node/test/parallel/test-mime-whatwg.js -test/js/node/test/parallel/test-module-builtin.js -test/js/node/test/parallel/test-module-cache.js -test/js/node/test/parallel/test-module-children.js -test/js/node/test/parallel/test-module-circular-dependency-warning.js -test/js/node/test/parallel/test-module-circular-symlinks.js -test/js/node/test/parallel/test-module-create-require.js -test/js/node/test/parallel/test-module-globalpaths-nodepath.js -test/js/node/test/parallel/test-module-loading-deprecated.js -test/js/node/test/parallel/test-module-loading-error.js -test/js/node/test/parallel/test-module-main-extension-lookup.js -test/js/node/test/parallel/test-module-main-fail.js -test/js/node/test/parallel/test-module-main-preserve-symlinks-fail.js -test/js/node/test/parallel/test-module-multi-extensions.js -test/js/node/test/parallel/test-module-nodemodulepaths.js -test/js/node/test/parallel/test-module-parent-deprecation.js -test/js/node/test/parallel/test-module-parent-setter-deprecation.js -test/js/node/test/parallel/test-module-prototype-mutation.js -test/js/node/test/parallel/test-module-readonly.js -test/js/node/test/parallel/test-module-relative-lookup.js -test/js/node/test/parallel/test-module-run-main-monkey-patch.js -test/js/node/test/parallel/test-module-stat.js -test/js/node/test/parallel/test-module-symlinked-peer-modules.js -test/js/node/test/parallel/test-module-version.js -test/js/node/test/parallel/test-module-wrap.js -test/js/node/test/parallel/test-module-wrapper.js -test/js/node/test/parallel/test-next-tick-doesnt-hang.js -test/js/node/test/parallel/test-next-tick-domain.js -test/js/node/test/parallel/test-next-tick-errors.js -test/js/node/test/parallel/test-next-tick-fixed-queue-regression.js -test/js/node/test/parallel/test-next-tick-intentional-starvation.js -test/js/node/test/parallel/test-next-tick-ordering.js -test/js/node/test/parallel/test-next-tick-ordering2.js -test/js/node/test/parallel/test-next-tick-when-exiting.js -test/js/node/test/parallel/test-next-tick.js -test/js/node/test/parallel/test-no-addons-resolution-condition.js -test/js/node/test/parallel/test-no-node-snapshot.js -test/js/node/test/parallel/test-os-eol.js -test/js/node/test/parallel/test-os-homedir-no-envvar.js -test/js/node/test/parallel/test-os-process-priority.js -test/js/node/test/parallel/test-os-userinfo-handles-getter-errors.js -test/js/node/test/parallel/test-os.js -test/js/node/test/parallel/test-outgoing-message-destroy.js -test/js/node/test/parallel/test-outgoing-message-pipe.js -test/js/node/test/parallel/test-parse-args.mjs -test/js/node/test/parallel/test-path-basename.js -test/js/node/test/parallel/test-path-dirname.js -test/js/node/test/parallel/test-path-extname.js -test/js/node/test/parallel/test-path-glob.js -test/js/node/test/parallel/test-path-isabsolute.js -test/js/node/test/parallel/test-path-join.js -test/js/node/test/parallel/test-path-makelong.js -test/js/node/test/parallel/test-path-normalize.js -test/js/node/test/parallel/test-path-parse-format.js -test/js/node/test/parallel/test-path-posix-exists.js -test/js/node/test/parallel/test-path-posix-relative-on-windows.js -test/js/node/test/parallel/test-path-relative.js -test/js/node/test/parallel/test-path-resolve.js -test/js/node/test/parallel/test-path-win32-exists.js -test/js/node/test/parallel/test-path-zero-length-strings.js -test/js/node/test/parallel/test-path.js -test/js/node/test/parallel/test-perf-gc-crash.js -test/js/node/test/parallel/test-performance-measure.js -test/js/node/test/parallel/test-performanceobserver-gc.js -test/js/node/test/parallel/test-permission-fs-supported.js -test/js/node/test/parallel/test-pipe-abstract-socket-http.js -test/js/node/test/parallel/test-pipe-address.js -test/js/node/test/parallel/test-pipe-file-to-http.js -test/js/node/test/parallel/test-pipe-head.js -test/js/node/test/parallel/test-pipe-outgoing-message-data-emitted-after-ended.js -test/js/node/test/parallel/test-pipe-return-val.js -test/js/node/test/parallel/test-pipe-writev.js -test/js/node/test/parallel/test-preload-print-process-argv.js -test/js/node/test/parallel/test-preload-self-referential.js -test/js/node/test/parallel/test-process-abort.js -test/js/node/test/parallel/test-process-argv-0.js -test/js/node/test/parallel/test-process-assert.js -test/js/node/test/parallel/test-process-available-memory.js -test/js/node/test/parallel/test-process-beforeexit-throw-exit.js -test/js/node/test/parallel/test-process-beforeexit.js -test/js/node/test/parallel/test-process-binding-util.js -test/js/node/test/parallel/test-process-chdir-errormessage.js -test/js/node/test/parallel/test-process-chdir.js -test/js/node/test/parallel/test-process-config.js -test/js/node/test/parallel/test-process-constants-noatime.js -test/js/node/test/parallel/test-process-constrained-memory.js -test/js/node/test/parallel/test-process-cpuUsage.js -test/js/node/test/parallel/test-process-default.js -test/js/node/test/parallel/test-process-dlopen-error-message-crash.js -test/js/node/test/parallel/test-process-dlopen-undefined-exports.js -test/js/node/test/parallel/test-process-domain-segfault.js -test/js/node/test/parallel/test-process-emit.js -test/js/node/test/parallel/test-process-emitwarning.js -test/js/node/test/parallel/test-process-env-windows-error-reset.js -test/js/node/test/parallel/test-process-euid-egid.js -test/js/node/test/parallel/test-process-exception-capture-errors.js -test/js/node/test/parallel/test-process-exception-capture-should-abort-on-uncaught.js -test/js/node/test/parallel/test-process-exception-capture.js -test/js/node/test/parallel/test-process-execpath.js -test/js/node/test/parallel/test-process-exit-code-validation.js -test/js/node/test/parallel/test-process-exit-from-before-exit.js -test/js/node/test/parallel/test-process-exit-handler.js -test/js/node/test/parallel/test-process-exit-recursive.js -test/js/node/test/parallel/test-process-exit.js -test/js/node/test/parallel/test-process-external-stdio-close-spawn.js -test/js/node/test/parallel/test-process-external-stdio-close.js -test/js/node/test/parallel/test-process-features.js -test/js/node/test/parallel/test-process-getgroups.js -test/js/node/test/parallel/test-process-hrtime-bigint.js -test/js/node/test/parallel/test-process-hrtime.js -test/js/node/test/parallel/test-process-kill-null.js -test/js/node/test/parallel/test-process-kill-pid.js -test/js/node/test/parallel/test-process-next-tick.js -test/js/node/test/parallel/test-process-no-deprecation.js -test/js/node/test/parallel/test-process-ppid.js -test/js/node/test/parallel/test-process-really-exit.js -test/js/node/test/parallel/test-process-release.js -test/js/node/test/parallel/test-process-remove-all-signal-listeners.js -test/js/node/test/parallel/test-process-setgroups.js -test/js/node/test/parallel/test-process-setsourcemapsenabled.js -test/js/node/test/parallel/test-process-title-cli.js -test/js/node/test/parallel/test-process-uid-gid.js -test/js/node/test/parallel/test-process-umask-mask.js -test/js/node/test/parallel/test-process-umask.js -test/js/node/test/parallel/test-process-uptime.js -test/js/node/test/parallel/test-process-warning.js -test/js/node/test/parallel/test-promise-handled-rejection-no-warning.js -test/js/node/test/parallel/test-promise-unhandled-default.js -test/js/node/test/parallel/test-promise-unhandled-error.js -test/js/node/test/parallel/test-promise-unhandled-flag.js -test/js/node/test/parallel/test-promise-unhandled-issue-43655.js -test/js/node/test/parallel/test-promise-unhandled-silent-no-hook.js -test/js/node/test/parallel/test-promise-unhandled-silent.js -test/js/node/test/parallel/test-promise-unhandled-throw-handler.js -test/js/node/test/parallel/test-promise-unhandled-throw.js -test/js/node/test/parallel/test-promise-unhandled-warn-no-hook.js -test/js/node/test/parallel/test-promises-unhandled-proxy-rejections.js -test/js/node/test/parallel/test-promises-unhandled-rejections.js -test/js/node/test/parallel/test-promises-unhandled-symbol-rejections.js -test/js/node/test/parallel/test-promises-warning-on-unhandled-rejection.js -test/js/node/test/parallel/test-punycode.js -test/js/node/test/parallel/test-querystring-escape.js -test/js/node/test/parallel/test-querystring-maxKeys-non-finite.js -test/js/node/test/parallel/test-querystring-multichar-separator.js -test/js/node/test/parallel/test-querystring.js -test/js/node/test/parallel/test-queue-microtask.js -test/js/node/test/parallel/test-quic-internal-endpoint-listen-defaults.js -test/js/node/test/parallel/test-quic-internal-endpoint-options.js -test/js/node/test/parallel/test-quic-internal-endpoint-stats-state.js -test/js/node/test/parallel/test-quic-internal-setcallbacks.js -test/js/node/test/parallel/test-readable-from-iterator-closing.js -test/js/node/test/parallel/test-readable-from-web-enqueue-then-close.js -test/js/node/test/parallel/test-readable-from.js -test/js/node/test/parallel/test-readable-large-hwm.js -test/js/node/test/parallel/test-readable-single-end.js -test/js/node/test/parallel/test-readline-async-iterators-backpressure.js -test/js/node/test/parallel/test-readline-async-iterators-destroy.js -test/js/node/test/parallel/test-readline-async-iterators.js -test/js/node/test/parallel/test-readline-carriage-return-between-chunks.js -test/js/node/test/parallel/test-readline-csi.js -test/js/node/test/parallel/test-readline-emit-keypress-events.js -test/js/node/test/parallel/test-readline-input-onerror.js -test/js/node/test/parallel/test-readline-interface-escapecodetimeout.js -test/js/node/test/parallel/test-readline-interface-no-trailing-newline.js -test/js/node/test/parallel/test-readline-interface-recursive-writes.js -test/js/node/test/parallel/test-readline-keys.js -test/js/node/test/parallel/test-readline-position.js -test/js/node/test/parallel/test-readline-promises-csi.mjs -test/js/node/test/parallel/test-readline-promises-tab-complete.js -test/js/node/test/parallel/test-readline-reopen.js -test/js/node/test/parallel/test-readline-set-raw-mode.js -test/js/node/test/parallel/test-readline-tab-complete.js -test/js/node/test/parallel/test-readline-undefined-columns.js -test/js/node/test/parallel/test-readline.js -test/js/node/test/parallel/test-ref-unref-return.js -test/js/node/test/parallel/test-repl-clear-immediate-crash.js -test/js/node/test/parallel/test-repl-close.js -test/js/node/test/parallel/test-repl-dynamic-import.js -test/js/node/test/parallel/test-repl-preview-without-inspector.js -test/js/node/test/parallel/test-repl-syntax-error-handling.js -test/js/node/test/parallel/test-require-cache.js -test/js/node/test/parallel/test-require-delete-array-iterator.js -test/js/node/test/parallel/test-require-dot.js -test/js/node/test/parallel/test-require-empty-main.js -test/js/node/test/parallel/test-require-enoent-dir.js -test/js/node/test/parallel/test-require-exceptions.js -test/js/node/test/parallel/test-require-extension-over-directory.js -test/js/node/test/parallel/test-require-extensions-main.js -test/js/node/test/parallel/test-require-extensions-same-filename-as-dir-trailing-slash.js -test/js/node/test/parallel/test-require-invalid-main-no-exports.js -test/js/node/test/parallel/test-require-invalid-package.js -test/js/node/test/parallel/test-require-json.js -test/js/node/test/parallel/test-require-long-path.js -test/js/node/test/parallel/test-require-node-prefix.js -test/js/node/test/parallel/test-require-nul.js -test/js/node/test/parallel/test-require-process.js -test/js/node/test/parallel/test-require-resolve.js -test/js/node/test/parallel/test-require-symlink.js -test/js/node/test/parallel/test-require-unicode.js -test/js/node/test/parallel/test-resource-usage.js -test/js/node/test/parallel/test-runner-filter-warning.js -test/js/node/test/parallel/test-runner-subtest-after-hook.js -test/js/node/test/parallel/test-set-process-debug-port.js -test/js/node/test/parallel/test-shadow-realm-gc-module.js -test/js/node/test/parallel/test-shadow-realm-module.js -test/js/node/test/parallel/test-shadow-realm-preload-module.js -test/js/node/test/parallel/test-shadow-realm-prepare-stack-trace.js -test/js/node/test/parallel/test-shadow-realm.js -test/js/node/test/parallel/test-sigint-infinite-loop.js -test/js/node/test/parallel/test-signal-args.js -test/js/node/test/parallel/test-signal-handler-remove-on-exit.js -test/js/node/test/parallel/test-signal-handler.js -test/js/node/test/parallel/test-signal-unregister.js -test/js/node/test/parallel/test-socket-address.js -test/js/node/test/parallel/test-socket-options-invalid.js -test/js/node/test/parallel/test-socket-write-after-fin-error.js -test/js/node/test/parallel/test-spawn-cmd-named-pipe.js -test/js/node/test/parallel/test-stdin-child-proc.js -test/js/node/test/parallel/test-stdin-from-file-spawn.js -test/js/node/test/parallel/test-stdin-from-file.js -test/js/node/test/parallel/test-stdin-hang.js -test/js/node/test/parallel/test-stdin-pause-resume-sync.js -test/js/node/test/parallel/test-stdin-pause-resume.js -test/js/node/test/parallel/test-stdin-pipe-large.js -test/js/node/test/parallel/test-stdin-pipe-resume.js -test/js/node/test/parallel/test-stdin-resume-pause.js -test/js/node/test/parallel/test-stdin-script-child-option.js -test/js/node/test/parallel/test-stdin-script-child.js -test/js/node/test/parallel/test-stdio-closed.js -test/js/node/test/parallel/test-stdio-pipe-access.js -test/js/node/test/parallel/test-stdio-pipe-stderr.js -test/js/node/test/parallel/test-stdio-undestroy.js -test/js/node/test/parallel/test-stdout-cannot-be-closed-child-process-pipe.js -test/js/node/test/parallel/test-stdout-pipeline-destroy.js -test/js/node/test/parallel/test-stdout-stderr-reading.js -test/js/node/test/parallel/test-stdout-stderr-write.js -test/js/node/test/parallel/test-stdout-to-file.js -test/js/node/test/parallel/test-string-decoder-end.js -test/js/node/test/parallel/test-string-decoder.js -test/js/node/test/parallel/test-stringbytes-external.js -test/js/node/test/parallel/test-sync-fileread.js -test/js/node/test/parallel/test-sys.js -test/js/node/test/parallel/test-timers-api-refs.js -test/js/node/test/parallel/test-timers-args.js -test/js/node/test/parallel/test-timers-clear-null-does-not-throw-error.js -test/js/node/test/parallel/test-timers-clear-object-does-not-throw-error.js -test/js/node/test/parallel/test-timers-clear-timeout-interval-equivalent.js -test/js/node/test/parallel/test-timers-clearImmediate-als.js -test/js/node/test/parallel/test-timers-clearImmediate.js -test/js/node/test/parallel/test-timers-destroyed.js -test/js/node/test/parallel/test-timers-dispose.js -test/js/node/test/parallel/test-timers-immediate-promisified.js -test/js/node/test/parallel/test-timers-immediate-queue-throw.js -test/js/node/test/parallel/test-timers-immediate-queue.js -test/js/node/test/parallel/test-timers-immediate-unref-nested-once.js -test/js/node/test/parallel/test-timers-immediate-unref-simple.js -test/js/node/test/parallel/test-timers-immediate-unref.js -test/js/node/test/parallel/test-timers-immediate.js -test/js/node/test/parallel/test-timers-interval-promisified.js -test/js/node/test/parallel/test-timers-interval-throw.js -test/js/node/test/parallel/test-timers-invalid-clear.js -test/js/node/test/parallel/test-timers-linked-list.js -test/js/node/test/parallel/test-timers-max-duration-warning.js -test/js/node/test/parallel/test-timers-nan-duration-emit-once-per-process.js -test/js/node/test/parallel/test-timers-nan-duration-warning-promises.js -test/js/node/test/parallel/test-timers-nan-duration-warning.js -test/js/node/test/parallel/test-timers-negative-duration-warning-emit-once-per-process.js -test/js/node/test/parallel/test-timers-negative-duration-warning.js -test/js/node/test/parallel/test-timers-nested.js -test/js/node/test/parallel/test-timers-next-tick.js -test/js/node/test/parallel/test-timers-non-integer-delay.js -test/js/node/test/parallel/test-timers-not-emit-duration-zero.js -test/js/node/test/parallel/test-timers-now.js -test/js/node/test/parallel/test-timers-ordering.js -test/js/node/test/parallel/test-timers-process-tampering.js -test/js/node/test/parallel/test-timers-promises-scheduler.js -test/js/node/test/parallel/test-timers-promises.js -test/js/node/test/parallel/test-timers-refresh-in-callback.js -test/js/node/test/parallel/test-timers-refresh.js -test/js/node/test/parallel/test-timers-same-timeout-wrong-list-deleted.js -test/js/node/test/parallel/test-timers-setimmediate-infinite-loop.js -test/js/node/test/parallel/test-timers-socket-timeout-removes-other-socket-unref-timer.js -test/js/node/test/parallel/test-timers-this.js -test/js/node/test/parallel/test-timers-throw-when-cb-not-function.js -test/js/node/test/parallel/test-timers-timeout-promisified.js -test/js/node/test/parallel/test-timers-timeout-to-interval.js -test/js/node/test/parallel/test-timers-timeout-with-non-integer.js -test/js/node/test/parallel/test-timers-to-primitive.js -test/js/node/test/parallel/test-timers-uncaught-exception.js -test/js/node/test/parallel/test-timers-unenroll-unref-interval.js -test/js/node/test/parallel/test-timers-unref-throw-then-ref.js -test/js/node/test/parallel/test-timers-unref.js -test/js/node/test/parallel/test-timers-unrefd-interval-still-fires.js -test/js/node/test/parallel/test-timers-unrefed-in-beforeexit.js -test/js/node/test/parallel/test-timers-unrefed-in-callback.js -test/js/node/test/parallel/test-timers-user-call.js -test/js/node/test/parallel/test-timers-zero-timeout.js -test/js/node/test/parallel/test-timers.js -test/js/node/test/parallel/test-tty-backwards-api.js -test/js/node/test/parallel/test-tty-stdin-end.js -test/js/node/test/parallel/test-tty-stdin-pipe.js -test/js/node/test/parallel/test-tz-version.js -test/js/node/test/parallel/test-unhandled-exception-with-worker-inuse.js -test/js/node/test/parallel/test-url-canParse-whatwg.js -test/js/node/test/parallel/test-url-domain-ascii-unicode.js -test/js/node/test/parallel/test-url-format-invalid-input.js -test/js/node/test/parallel/test-url-format-whatwg.js -test/js/node/test/parallel/test-url-format.js -test/js/node/test/parallel/test-url-parse-format.js -test/js/node/test/parallel/test-url-parse-invalid-input.js -test/js/node/test/parallel/test-url-parse-query.js -test/js/node/test/parallel/test-url-relative.js -test/js/node/test/parallel/test-url-revokeobjecturl.js -test/js/node/test/parallel/test-url-urltooptions.js -test/js/node/test/parallel/test-utf8-scripts.js -test/js/node/test/parallel/test-util-callbackify.js -test/js/node/test/parallel/test-util-deprecate-invalid-code.js -test/js/node/test/parallel/test-util-deprecate.js -test/js/node/test/parallel/test-util-inherits.js -test/js/node/test/parallel/test-util-inspect-getters-accessing-this.js -test/js/node/test/parallel/test-util-inspect-long-running.js -test/js/node/test/parallel/test-util-inspect-proxy.js -test/js/node/test/parallel/test-util-internal.js -test/js/node/test/parallel/test-util-parse-env.js -test/js/node/test/parallel/test-util-primordial-monkeypatching.js -test/js/node/test/parallel/test-util-promisify-custom-names.mjs -test/js/node/test/parallel/test-util-promisify.js -test/js/node/test/parallel/test-util-sigint-watchdog.js -test/js/node/test/parallel/test-util-sleep.js -test/js/node/test/parallel/test-util-stripvtcontrolcharacters.js -test/js/node/test/parallel/test-util-styletext.js -test/js/node/test/parallel/test-util-text-decoder.js -test/js/node/test/parallel/test-util-types-exists.js -test/js/node/test/parallel/test-util-types.js -test/js/node/test/parallel/test-util.js -test/js/node/test/parallel/test-v8-deserialize-buffer.js -test/js/node/test/parallel/test-v8-flag-pool-size-0.js -test/js/node/test/parallel/test-v8-getheapsnapshot-twice.js -test/js/node/test/parallel/test-v8-global-setter.js -test/js/node/test/parallel/test-v8-serialize-leak.js -test/js/node/test/parallel/test-vm-access-process-env.js -test/js/node/test/parallel/test-vm-api-handles-getter-errors.js -test/js/node/test/parallel/test-vm-attributes-property-not-on-sandbox.js -test/js/node/test/parallel/test-vm-basic.js -test/js/node/test/parallel/test-vm-cached-data.js -test/js/node/test/parallel/test-vm-context-async-script.js -test/js/node/test/parallel/test-vm-context-property-forwarding.js -test/js/node/test/parallel/test-vm-context.js -test/js/node/test/parallel/test-vm-create-and-run-in-context.js -test/js/node/test/parallel/test-vm-create-context-accessors.js -test/js/node/test/parallel/test-vm-create-context-arg.js -test/js/node/test/parallel/test-vm-create-context-circular-reference.js -test/js/node/test/parallel/test-vm-createcacheddata.js -test/js/node/test/parallel/test-vm-cross-context.js -test/js/node/test/parallel/test-vm-data-property-writable.js -test/js/node/test/parallel/test-vm-deleting-property.js -test/js/node/test/parallel/test-vm-function-declaration.js -test/js/node/test/parallel/test-vm-function-redefinition.js -test/js/node/test/parallel/test-vm-getters.js -test/js/node/test/parallel/test-vm-global-assignment.js -test/js/node/test/parallel/test-vm-global-configurable-properties.js -test/js/node/test/parallel/test-vm-global-define-property.js -test/js/node/test/parallel/test-vm-global-get-own.js -test/js/node/test/parallel/test-vm-global-non-writable-properties.js -test/js/node/test/parallel/test-vm-global-property-enumerator.js -test/js/node/test/parallel/test-vm-global-property-interceptors.js -test/js/node/test/parallel/test-vm-global-property-prototype.js -test/js/node/test/parallel/test-vm-global-setter.js -test/js/node/test/parallel/test-vm-harmony-symbols.js -test/js/node/test/parallel/test-vm-indexed-properties.js -test/js/node/test/parallel/test-vm-inherited_properties.js -test/js/node/test/parallel/test-vm-is-context.js -test/js/node/test/parallel/test-vm-low-stack-space.js -test/js/node/test/parallel/test-vm-module-basic.js -test/js/node/test/parallel/test-vm-module-cached-data.js -test/js/node/test/parallel/test-vm-module-errors.js -test/js/node/test/parallel/test-vm-module-import-meta.js -test/js/node/test/parallel/test-vm-module-link.js -test/js/node/test/parallel/test-vm-module-reevaluate.js -test/js/node/test/parallel/test-vm-module-referrer-realm.mjs -test/js/node/test/parallel/test-vm-module-synthetic.js -test/js/node/test/parallel/test-vm-new-script-context.js -test/js/node/test/parallel/test-vm-new-script-new-context.js -test/js/node/test/parallel/test-vm-new-script-this-context.js -test/js/node/test/parallel/test-vm-not-strict.js -test/js/node/test/parallel/test-vm-options-validation.js -test/js/node/test/parallel/test-vm-ownkeys.js -test/js/node/test/parallel/test-vm-ownpropertynames.js -test/js/node/test/parallel/test-vm-ownpropertysymbols.js -test/js/node/test/parallel/test-vm-parse-abort-on-uncaught-exception.js -test/js/node/test/parallel/test-vm-preserves-property.js -test/js/node/test/parallel/test-vm-proxies.js -test/js/node/test/parallel/test-vm-proxy-failure-CP.js -test/js/node/test/parallel/test-vm-run-in-new-context.js -test/js/node/test/parallel/test-vm-script-throw-in-tostring.js -test/js/node/test/parallel/test-vm-set-property-proxy.js -test/js/node/test/parallel/test-vm-set-proto-null-on-globalthis.js -test/js/node/test/parallel/test-vm-sigint-existing-handler.js -test/js/node/test/parallel/test-vm-sigint.js -test/js/node/test/parallel/test-vm-static-this.js -test/js/node/test/parallel/test-vm-strict-assign.js -test/js/node/test/parallel/test-vm-strict-mode.js -test/js/node/test/parallel/test-vm-symbols.js -test/js/node/test/parallel/test-vm-syntax-error-message.js -test/js/node/test/parallel/test-vm-syntax-error-stderr.js -test/js/node/test/parallel/test-vm-timeout-escape-promise-module.js -test/js/node/test/parallel/test-vm-timeout-escape-promise.js -test/js/node/test/parallel/test-vm-timeout.js -test/js/node/test/parallel/test-vm-util-lazy-properties.js -test/js/node/test/parallel/test-warn-stream-wrap.js -test/js/node/test/parallel/test-weakref.js -test/js/node/test/parallel/test-webcrypto-cryptokey-workers.js -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/node/test/parallel/test-webcrypto-encrypt-decrypt.js -test/js/node/test/parallel/test-webcrypto-getRandomValues.js -test/js/node/test/parallel/test-webcrypto-random.js -test/js/node/test/parallel/test-webcrypto-sign-verify.js -test/js/node/test/parallel/test-websocket.js -test/js/node/test/parallel/test-webstream-string-tag.js -test/js/node/test/parallel/test-whatwg-encoding-custom-api-basics.js -test/js/node/test/parallel/test-whatwg-encoding-custom-fatal-streaming.js -test/js/node/test/parallel/test-whatwg-encoding-custom-textdecoder-api-invalid-label.js -test/js/node/test/parallel/test-whatwg-encoding-custom-textdecoder-fatal.js -test/js/node/test/parallel/test-whatwg-encoding-custom-textdecoder-ignorebom.js -test/js/node/test/parallel/test-whatwg-encoding-custom-textdecoder-invalid-arg.js -test/js/node/test/parallel/test-whatwg-encoding-custom-textdecoder-streaming.js -test/js/node/test/parallel/test-whatwg-encoding-custom-textdecoder-utf16-surrogates.js -test/js/node/test/parallel/test-whatwg-events-add-event-listener-options-passive.js -test/js/node/test/parallel/test-whatwg-events-add-event-listener-options-signal.js -test/js/node/test/parallel/test-whatwg-events-customevent.js -test/js/node/test/parallel/test-whatwg-events-event-constructors.js -test/js/node/test/parallel/test-whatwg-events-eventtarget-this-of-listener.js -test/js/node/test/parallel/test-whatwg-readablebytestream.js -test/js/node/test/parallel/test-whatwg-readablebytestreambyob.js -test/js/node/test/parallel/test-whatwg-readablestream.mjs -test/js/node/test/parallel/test-whatwg-url-canparse.js -test/js/node/test/parallel/test-whatwg-url-custom-deepequal.js -test/js/node/test/parallel/test-whatwg-url-custom-domainto.js -test/js/node/test/parallel/test-whatwg-url-custom-global.js -test/js/node/test/parallel/test-whatwg-url-custom-href-side-effect.js -test/js/node/test/parallel/test-whatwg-url-custom-inspect.js -test/js/node/test/parallel/test-whatwg-url-custom-parsing.js -test/js/node/test/parallel/test-whatwg-url-custom-properties.js -test/js/node/test/parallel/test-whatwg-url-custom-searchparams-append.js -test/js/node/test/parallel/test-whatwg-url-custom-searchparams-delete.js -test/js/node/test/parallel/test-whatwg-url-custom-searchparams-entries.js -test/js/node/test/parallel/test-whatwg-url-custom-searchparams-foreach.js -test/js/node/test/parallel/test-whatwg-url-custom-searchparams-get.js -test/js/node/test/parallel/test-whatwg-url-custom-searchparams-getall.js -test/js/node/test/parallel/test-whatwg-url-custom-searchparams-has.js -test/js/node/test/parallel/test-whatwg-url-custom-searchparams-keys.js -test/js/node/test/parallel/test-whatwg-url-custom-searchparams-set.js -test/js/node/test/parallel/test-whatwg-url-custom-searchparams-sort.js -test/js/node/test/parallel/test-whatwg-url-custom-searchparams-stringifier.js -test/js/node/test/parallel/test-whatwg-url-custom-searchparams-values.js -test/js/node/test/parallel/test-whatwg-url-custom-searchparams.js -test/js/node/test/parallel/test-whatwg-url-custom-setters.js -test/js/node/test/parallel/test-whatwg-url-custom-tostringtag.js -test/js/node/test/parallel/test-whatwg-url-invalidthis.js -test/js/node/test/parallel/test-whatwg-url-override-hostname.js -test/js/node/test/parallel/test-whatwg-url-toascii.js -test/js/node/test/parallel/test-windows-abort-exitcode.js -test/js/node/test/parallel/test-windows-failed-heap-allocation.js -test/js/node/test/parallel/test-worker-abort-on-uncaught-exception.js -test/js/node/test/parallel/test-worker-arraybuffer-zerofill.js -test/js/node/test/parallel/test-worker-cjs-workerdata.js -test/js/node/test/parallel/test-worker-cleanexit-with-js.js -test/js/node/test/parallel/test-worker-cleanexit-with-moduleload.js -test/js/node/test/parallel/test-worker-console-listeners.js -test/js/node/test/parallel/test-worker-dns-terminate-during-query.js -test/js/node/test/parallel/test-worker-environmentdata.js -test/js/node/test/parallel/test-worker-esm-exit.js -test/js/node/test/parallel/test-worker-esm-missing-main.js -test/js/node/test/parallel/test-worker-esmodule.js -test/js/node/test/parallel/test-worker-event.js -test/js/node/test/parallel/test-worker-exit-event-error.js -test/js/node/test/parallel/test-worker-exit-from-uncaught-exception.js -test/js/node/test/parallel/test-worker-exit-heapsnapshot.js -test/js/node/test/parallel/test-worker-fs-stat-watcher.js -test/js/node/test/parallel/test-worker-heap-snapshot.js -test/js/node/test/parallel/test-worker-http2-generic-streams-terminate.js -test/js/node/test/parallel/test-worker-invalid-workerdata.js -test/js/node/test/parallel/test-worker-load-file-with-extension-other-than-js.js -test/js/node/test/parallel/test-worker-memory.js -test/js/node/test/parallel/test-worker-message-channel-sharedarraybuffer.js -test/js/node/test/parallel/test-worker-message-event.js -test/js/node/test/parallel/test-worker-message-port-constructor.js -test/js/node/test/parallel/test-worker-message-port-infinite-message-loop.js -test/js/node/test/parallel/test-worker-message-port-receive-message.js -test/js/node/test/parallel/test-worker-message-port-terminate-transfer-list.js -test/js/node/test/parallel/test-worker-message-port-transfer-duplicate.js -test/js/node/test/parallel/test-worker-message-port-transfer-terminate.js -test/js/node/test/parallel/test-worker-message-port-wasm-module.js -test/js/node/test/parallel/test-worker-message-port-wasm-threads.js -test/js/node/test/parallel/test-worker-mjs-workerdata.js -test/js/node/test/parallel/test-worker-nested-on-process-exit.js -test/js/node/test/parallel/test-worker-nested-uncaught.js -test/js/node/test/parallel/test-worker-no-sab.js -test/js/node/test/parallel/test-worker-non-fatal-uncaught-exception.js -test/js/node/test/parallel/test-worker-on-process-exit.js -test/js/node/test/parallel/test-worker-onmessage-not-a-function.js -test/js/node/test/parallel/test-worker-onmessage.js -test/js/node/test/parallel/test-worker-parent-port-ref.js -test/js/node/test/parallel/test-worker-process-argv.js -test/js/node/test/parallel/test-worker-ref-onexit.js -test/js/node/test/parallel/test-worker-ref.js -test/js/node/test/parallel/test-worker-relative-path-double-dot.js -test/js/node/test/parallel/test-worker-relative-path.js -test/js/node/test/parallel/test-worker-safe-getters.js -test/js/node/test/parallel/test-worker-sharedarraybuffer-from-worker-thread.js -test/js/node/test/parallel/test-worker-terminate-http2-respond-with-file.js -test/js/node/test/parallel/test-worker-terminate-nested.js -test/js/node/test/parallel/test-worker-terminate-null-handler.js -test/js/node/test/parallel/test-worker-terminate-timers.js -test/js/node/test/parallel/test-worker-type-check.js -test/js/node/test/parallel/test-worker-workerdata-sharedarraybuffer.js -test/js/node/test/parallel/test-worker.js -test/js/node/test/parallel/test-worker.mjs -test/js/node/test/sequential/test-buffer-creation-regression.js -test/js/node/test/sequential/test-child-process-emfile.js -test/js/node/test/sequential/test-child-process-execsync.js -test/js/node/test/sequential/test-child-process-exit.js -test/js/node/test/sequential/test-crypto-timing-safe-equal.js -test/js/node/test/sequential/test-debug-prompt.js -test/js/node/test/sequential/test-dgram-implicit-bind-failure.js -test/js/node/test/sequential/test-dgram-pingpong.js -test/js/node/test/sequential/test-fs-opendir-recursive.js -test/js/node/test/sequential/test-fs-readdir-recursive.js -test/js/node/test/sequential/test-fs-stat-sync-overflow.js -test/js/node/test/sequential/test-http-econnrefused.js -test/js/node/test/sequential/test-http-keep-alive-large-write.js -test/js/node/test/sequential/test-http-server-keep-alive-timeout-slow-server.js -test/js/node/test/sequential/test-http2-large-file.js -test/js/node/test/sequential/test-init.js -test/js/node/test/sequential/test-net-GH-5504.js -test/js/node/test/sequential/test-net-better-error-messages-port.js -test/js/node/test/sequential/test-net-connect-econnrefused.js -test/js/node/test/sequential/test-net-connect-handle-econnrefused.js -test/js/node/test/sequential/test-net-reconnect-error.js -test/js/node/test/sequential/test-net-response-size.js -test/js/node/test/sequential/test-net-server-address.js -test/js/node/test/sequential/test-net-server-bind.js -test/js/node/test/sequential/test-require-cache-without-stat.js -test/js/node/test/sequential/test-single-executable-application-assets-raw.js -test/js/node/test/sequential/test-single-executable-application-assets.js -test/js/node/test/sequential/test-single-executable-application-disable-experimental-sea-warning.js -test/js/node/test/sequential/test-single-executable-application-empty.js -test/js/node/test/sequential/test-single-executable-application-snapshot-and-code-cache.js -test/js/node/test/sequential/test-single-executable-application-snapshot-worker.js -test/js/node/test/sequential/test-single-executable-application-snapshot.js -test/js/node/test/sequential/test-single-executable-application-use-code-cache.js -test/js/node/test/sequential/test-single-executable-application.js -test/js/node/test/sequential/test-stream2-fs.js -test/js/node/test/sequential/test-timers-block-eventloop.js -test/js/node/test/sequential/test-timers-set-interval-excludes-callback-duration.js -test/js/node/test/sequential/test-tls-connect.js -test/js/node/test/sequential/test-tls-lookup.js -test/js/node/test/sequential/test-tls-psk-client.js -test/js/node/test/sequential/test-tls-securepair-client.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 @@ -2059,6 +703,21 @@ test/js/node/test/parallel/test-fs-read-promises-position-validation.mjs test/js/node/test/parallel/test-fs-read-position-validation.mjs test/js/node/test/parallel/test-net-server-async-dispose.mjs test/js/node/test/parallel/test-net-connect-custom-lookup-non-string-address.mjs +test/js/node/test/parallel/test-abortsignal-any.mjs +test/js/node/test/parallel/test-child-process-fork-url.mjs +test/js/node/test/parallel/test-debugger-invalid-json.mjs +test/js/node/test/parallel/test-dgram-async-dispose.mjs +test/js/node/test/parallel/test-events-add-abort-listener.mjs +test/js/node/test/parallel/test-fetch.mjs +test/js/node/test/parallel/test-module-globalpaths-nodepath.js +test/js/node/test/parallel/test-parse-args.mjs +test/js/node/test/parallel/test-process-default.js +test/js/node/test/parallel/test-readline-promises-csi.mjs +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/test/parallel/test-vm-module-referrer-realm.mjs # uses node:test test/js/node/test/parallel/test-fs-write-stream-flush.js @@ -2066,16 +725,48 @@ 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 # 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 -# uses jsobjectref -test/js/node/test/parallel/test-fs-readdir-buffer.js -test/js/node/test/parallel/test-stream-finished.js -test/js/node/test/parallel/test-cluster-primary-error.js - # 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/test/parallel/test-util-callbackify.js +# ProgramExecutable::initializeGlobalProperties +# missing RELEASE_AND_RETURN +test/js/node/test/parallel/test-repl-syntax-error-handling.js +# JSModuleRecord::instantiateDeclarations +# missing RETURN_IF_EXCEPTION +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 + +# llhttp +test/js/node/test/parallel/test-http-parser-bad-ref.js +test/js/node/test/parallel/test-http-parser.js + +# 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 + +# 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/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 +test/js/node/test/parallel/test-crypto-oaep-zero-length.js +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