diff --git a/cmake/sources/CxxSources.txt b/cmake/sources/CxxSources.txt index c5e07b9814..3f04817879 100644 --- a/cmake/sources/CxxSources.txt +++ b/cmake/sources/CxxSources.txt @@ -28,6 +28,7 @@ src/bun.js/bindings/BunWorkerGlobalScope.cpp src/bun.js/bindings/c-bindings.cpp src/bun.js/bindings/CallSite.cpp src/bun.js/bindings/CallSitePrototype.cpp +src/bun.js/bindings/CatchScopeBinding.cpp src/bun.js/bindings/CodeCoverage.cpp src/bun.js/bindings/ConsoleObject.cpp src/bun.js/bindings/Cookie.cpp diff --git a/cmake/sources/ZigSources.txt b/cmake/sources/ZigSources.txt index 7ffe24fafb..f8e597503c 100644 --- a/cmake/sources/ZigSources.txt +++ b/cmake/sources/ZigSources.txt @@ -85,6 +85,7 @@ src/bun.js/bindings/AnyPromise.zig src/bun.js/bindings/bun-simdutf.zig src/bun.js/bindings/CachedBytecode.zig src/bun.js/bindings/CallFrame.zig +src/bun.js/bindings/CatchScope.zig src/bun.js/bindings/codegen.zig src/bun.js/bindings/CommonAbortReason.zig src/bun.js/bindings/CommonStrings.zig diff --git a/package.json b/package.json index 764e813718..06acf99b10 100644 --- a/package.json +++ b/package.json @@ -24,7 +24,7 @@ }, "scripts": { "build": "bun run build:debug", - "watch": "bun run zig build check --watch -fincremental --prominent-compile-errors --global-cache-dir build/debug/zig-check-cache --zig-lib-dir vendor/zig/lib -Doverride-no-export-cpp-apis=true", + "watch": "bun run zig build check --watch -fincremental --prominent-compile-errors --global-cache-dir build/debug/zig-check-cache --zig-lib-dir vendor/zig/lib", "watch-windows": "bun run zig build check-windows --watch -fincremental --prominent-compile-errors --global-cache-dir build/debug/zig-check-cache --zig-lib-dir vendor/zig/lib", "bd:v": "(bun run --silent build:debug &> /tmp/bun.debug.build.log || (cat /tmp/bun.debug.build.log && rm -rf /tmp/bun.debug.build.log && exit 1)) && rm -f /tmp/bun.debug.build.log && ./build/debug/bun-debug", "bd": "BUN_DEBUG_QUIET_LOGS=1 bun bd:v", diff --git a/scripts/runner.node.mjs b/scripts/runner.node.mjs index 70c7cd5def..2aaaa179d6 100755 --- a/scripts/runner.node.mjs +++ b/scripts/runner.node.mjs @@ -230,6 +230,27 @@ function getTestExpectations() { return expectations; } +/** + * 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("#")); + } + return !(skipArray.includes(test) || skipArray.includes("test/" + test)); + }; +})(); + /** * @param {string} testPath * @returns {string[]} @@ -416,16 +437,20 @@ async function runTests() { const runWithBunTest = title.includes("needs-test") || testContent.includes("bun:test") || testContent.includes("node:test"); const subcommand = runWithBunTest ? "test" : "run"; + const env = { + FORCE_COLOR: "0", + NO_COLOR: "1", + BUN_DEBUG_QUIET_LOGS: "1", + }; + if (basename(execPath).includes("asan") && shouldValidateExceptions(testPath)) { + env.BUN_JSC_validateExceptionChecks = "1"; + } await runTest(title, async () => { const { ok, error, stdout } = await spawnBun(execPath, { cwd: cwd, args: [subcommand, "--config=" + join(import.meta.dirname, "../bunfig.node-test.toml"), absoluteTestPath], timeout: getNodeParallelTestTimeout(title), - env: { - FORCE_COLOR: "0", - NO_COLOR: "1", - BUN_DEBUG_QUIET_LOGS: "1", - }, + env, stdout: chunk => pipeTestStdout(process.stdout, chunk), stderr: chunk => pipeTestStdout(process.stderr, chunk), }); @@ -953,13 +978,18 @@ async function spawnBunTest(execPath, testPath, options = { cwd }) { testArgs.push(absPath); + const env = { + GITHUB_ACTIONS: "true", // always true so annotations are parsed + }; + if (basename(execPath).includes("asan") && shouldValidateExceptions(relative(cwd, absPath))) { + env.BUN_JSC_validateExceptionChecks = "1"; + } + const { ok, error, stdout } = await spawnBun(execPath, { args: isReallyTest ? testArgs : [...args, absPath], cwd: options["cwd"], timeout: isReallyTest ? timeout : 30_000, - env: { - GITHUB_ACTIONS: "true", // always true so annotations are parsed - }, + env, stdout: chunk => pipeTestStdout(process.stdout, chunk), stderr: chunk => pipeTestStdout(process.stderr, chunk), }); diff --git a/src/bake/bake.zig b/src/bake/bake.zig index 39a665251b..a03eca25f0 100644 --- a/src/bake/bake.zig +++ b/src/bake/bake.zig @@ -104,13 +104,13 @@ pub const SplitBundlerOptions = struct { .ssr = .{}, }; - pub fn parsePluginArray(opts: *SplitBundlerOptions, plugin_array: JSValue, global: *JSC.JSGlobalObject) !void { + pub fn parsePluginArray(opts: *SplitBundlerOptions, plugin_array: JSValue, global: *JSC.JSGlobalObject) bun.JSError!void { const plugin = opts.plugin orelse Plugin.create(global, .bun); opts.plugin = plugin; const empty_object = JSValue.createEmptyObject(global, 0); - var iter = plugin_array.arrayIterator(global); - while (iter.next()) |plugin_config| { + var iter = try plugin_array.arrayIterator(global); + while (try iter.next()) |plugin_config| { if (!plugin_config.isObject()) { return global.throwInvalidArguments("Expected plugin to be an object", .{}); } @@ -359,7 +359,7 @@ pub const Framework = struct { refs: *StringRefList, bundler_options: *SplitBundlerOptions, arena: Allocator, - ) !Framework { + ) bun.JSError!Framework { if (opts.isString()) { const str = try opts.toBunString(global); defer str.deref(); @@ -446,13 +446,13 @@ pub const Framework = struct { const array = try opts.getArray(global, "builtInModules") orelse break :built_in_modules .{}; - const len = array.getLength(global); + const len = try array.getLength(global); var files: bun.StringArrayHashMapUnmanaged(BuiltInModule) = .{}; try files.ensureTotalCapacity(arena, len); - var it = array.arrayIterator(global); + var it = try array.arrayIterator(global); var i: usize = 0; - while (it.next()) |file| : (i += 1) { + while (try it.next()) |file| : (i += 1) { if (!file.isObject()) { return global.throwInvalidArguments("'builtInModules[{d}]' is not an object", .{i}); } @@ -477,16 +477,16 @@ pub const Framework = struct { const array: JSValue = try opts.getArray(global, "fileSystemRouterTypes") orelse { return global.throwInvalidArguments("Missing 'framework.fileSystemRouterTypes'", .{}); }; - const len = array.getLength(global); + const len = try array.getLength(global); if (len > 256) { return global.throwInvalidArguments("Framework can only define up to 256 file-system router types", .{}); } const file_system_router_types = try arena.alloc(FileSystemRouterType, len); - var it = array.arrayIterator(global); + var it = try array.arrayIterator(global); var i: usize = 0; errdefer for (file_system_router_types[0..i]) |*fsr| fsr.style.deinit(); - while (it.next()) |fsr_opts| : (i += 1) { + while (try it.next()) |fsr_opts| : (i += 1) { const root = try getOptionalString(fsr_opts, global, "root", refs, arena) orelse { return global.throwInvalidArguments("'fileSystemRouterTypes[{d}]' is missing 'root'", .{i}); }; @@ -511,10 +511,10 @@ pub const Framework = struct { break :exts &.{}; } } else if (exts_js.isArray()) { - var it_2 = exts_js.arrayIterator(global); + var it_2 = try exts_js.arrayIterator(global); var i_2: usize = 0; - const extensions = try arena.alloc([]const u8, exts_js.getLength(global)); - while (it_2.next()) |array_item| : (i_2 += 1) { + const extensions = try arena.alloc([]const u8, try exts_js.getLength(global)); + while (try it_2.next()) |array_item| : (i_2 += 1) { const slice = refs.track(try array_item.toSlice(global, arena)); if (bun.strings.eqlComptime(slice, "*")) return global.throwInvalidArguments("'extensions' cannot include \"*\" as an extension. Pass \"*\" instead of the array.", .{}); @@ -536,10 +536,10 @@ pub const Framework = struct { const ignore_dirs: []const []const u8 = if (try fsr_opts.get(global, "ignoreDirs")) |exts_js| exts: { if (exts_js.isArray()) { - var it_2 = array.arrayIterator(global); + var it_2 = try array.arrayIterator(global); var i_2: usize = 0; const dirs = try arena.alloc([]const u8, len); - while (it_2.next()) |array_item| : (i_2 += 1) { + while (try it_2.next()) |array_item| : (i_2 += 1) { dirs[i_2] = refs.track(try array_item.toSlice(global, arena)); } break :exts dirs; diff --git a/src/bun.js/ConsoleObject.zig b/src/bun.js/ConsoleObject.zig index 70fa6654e7..90891e020b 100644 --- a/src/bun.js/ConsoleObject.zig +++ b/src/bun.js/ConsoleObject.zig @@ -185,7 +185,7 @@ fn messageWithTypeAndLevel_( var tabular_data = vals[0]; if (tabular_data.isObject()) { const properties: JSValue = if (len >= 2 and vals[1].jsType().isArray()) vals[1] else .js_undefined; - var table_printer = TablePrinter.init( + var table_printer = try TablePrinter.init( global, level, tabular_data, @@ -277,13 +277,13 @@ pub const TablePrinter = struct { level: MessageLevel, tabular_data: JSValue, properties: JSValue, - ) TablePrinter { + ) bun.JSError!TablePrinter { return TablePrinter{ .level = level, .globalObject = globalObject, .tabular_data = tabular_data, .properties = properties, - .is_iterable = tabular_data.isIterable(globalObject), + .is_iterable = try tabular_data.isIterable(globalObject), .jstype = tabular_data.jsType(), .value_formatter = ConsoleObject.Formatter{ .remaining_values = &[_]JSValue{}, @@ -320,11 +320,11 @@ pub const TablePrinter = struct { }; /// Compute how much horizontal space will take a JSValue when printed - fn getWidthForValue(this: *TablePrinter, value: JSValue) u32 { + fn getWidthForValue(this: *TablePrinter, value: JSValue) bun.JSError!u32 { var width: usize = 0; var value_formatter = this.value_formatter; - const tag = ConsoleObject.Formatter.Tag.get(value, this.globalObject); + const tag = try ConsoleObject.Formatter.Tag.get(value, this.globalObject); value_formatter.quote_strings = !(tag.tag == .String or tag.tag == .StringPossiblyFormatted); value_formatter.format( tag, @@ -343,7 +343,7 @@ pub const TablePrinter = struct { } /// Update the sizes of the columns for the values of a given row, and create any additional columns as needed - fn updateColumnsForRow(this: *TablePrinter, columns: *std.ArrayList(Column), row_key: RowKey, row_value: JSValue) !void { + fn updateColumnsForRow(this: *TablePrinter, columns: *std.ArrayList(Column), row_key: RowKey, row_value: JSValue) bun.JSError!void { // update size of "(index)" column const row_key_len: u32 = switch (row_key) { .str => |value| @intCast(value.visibleWidthExcludeANSIColors(false)), @@ -353,10 +353,10 @@ pub const TablePrinter = struct { // special handling for Map: column with idx=1 is "Keys" if (this.jstype.isMap()) { - const entry_key = row_value.getIndex(this.globalObject, 0); - const entry_value = row_value.getIndex(this.globalObject, 1); - columns.items[1].width = @max(columns.items[1].width, this.getWidthForValue(entry_key)); - this.values_col_width = @max(this.values_col_width orelse 0, this.getWidthForValue(entry_value)); + const entry_key = try row_value.getIndex(this.globalObject, 0); + const entry_value = try row_value.getIndex(this.globalObject, 1); + columns.items[1].width = @max(columns.items[1].width, try this.getWidthForValue(entry_key)); + this.values_col_width = @max(this.values_col_width orelse 0, try this.getWidthForValue(entry_value)); return; } @@ -366,8 +366,8 @@ pub const TablePrinter = struct { // - otherwise: iterate the object properties, and create the columns on-demand if (!this.properties.isUndefined()) { for (columns.items[1..]) |*column| { - if (row_value.getOwn(this.globalObject, column.name)) |value| { - column.width = @max(column.width, this.getWidthForValue(value)); + if (try row_value.getOwn(this.globalObject, column.name)) |value| { + column.width = @max(column.width, try this.getWidthForValue(value)); } } } else { @@ -399,12 +399,12 @@ pub const TablePrinter = struct { break :brk &columns.items[columns.items.len - 1]; }; - column.width = @max(column.width, this.getWidthForValue(value)); + column.width = @max(column.width, try this.getWidthForValue(value)); } } } else if (this.properties.isUndefined()) { // not object -> the value will go to the special "Values" column - this.values_col_width = @max(this.values_col_width orelse 1, this.getWidthForValue(row_value)); + this.values_col_width = @max(this.values_col_width orelse 1, try this.getWidthForValue(row_value)); } } @@ -452,24 +452,24 @@ pub const TablePrinter = struct { var value = JSValue.zero; if (col_idx == 1 and this.jstype.isMap()) { // is the "Keys" column, when iterating a Map? - value = row_value.getIndex(this.globalObject, 0); + value = try row_value.getIndex(this.globalObject, 0); } else if (col_idx == this.values_col_idx) { // is the "Values" column? if (this.jstype.isMap()) { - value = row_value.getIndex(this.globalObject, 1); + value = try row_value.getIndex(this.globalObject, 1); } else if (!row_value.isObject()) { value = row_value; } } else if (row_value.isObject()) { - value = row_value.getOwn(this.globalObject, col.name) orelse JSValue.zero; + value = try row_value.getOwn(this.globalObject, col.name) orelse JSValue.zero; } if (value == .zero) { try writer.writeByteNTimes(' ', col.width + (PADDING * 2)); } else { - const len: u32 = this.getWidthForValue(value); + const len: u32 = try this.getWidthForValue(value); const needed = col.width -| len; try writer.writeByteNTimes(' ', PADDING); - const tag = ConsoleObject.Formatter.Tag.get(value, this.globalObject); + const tag = try ConsoleObject.Formatter.Tag.get(value, this.globalObject); var value_formatter = this.value_formatter; value_formatter.quote_strings = !(tag.tag == .String or tag.tag == .StringPossiblyFormatted); @@ -532,8 +532,8 @@ pub const TablePrinter = struct { // if the "properties" arg was provided, pre-populate the columns if (!this.properties.isUndefined()) { - var properties_iter = JSC.JSArrayIterator.init(this.properties, globalObject); - while (properties_iter.next()) |value| { + var properties_iter = try JSC.JSArrayIterator.init(this.properties, globalObject); + while (try properties_iter.next()) |value| { try columns.append(.{ .name = try value.toBunString(globalObject), }); @@ -838,7 +838,7 @@ pub fn format2( .error_display_level = options.error_display_level, }; defer fmt.deinit(); - const tag = ConsoleObject.Formatter.Tag.get(vals[0], global); + const tag = try ConsoleObject.Formatter.Tag.get(vals[0], global); fmt.writeIndent(Writer, writer) catch return; if (tag.tag == .String) { @@ -937,7 +937,7 @@ pub fn format2( } any = true; - tag = ConsoleObject.Formatter.Tag.get(this_value, global); + tag = try ConsoleObject.Formatter.Tag.get(this_value, global); if (tag.tag == .String and fmt.remaining_values.len > 0) { tag.tag = .{ .StringPossiblyFormatted = {} }; } @@ -959,7 +959,7 @@ pub fn format2( _ = writer.write(" ") catch 0; } any = true; - tag = ConsoleObject.Formatter.Tag.get(this_value, global); + tag = try ConsoleObject.Formatter.Tag.get(this_value, global); if (tag.tag == .String and fmt.remaining_values.len > 0) { tag.tag = .{ .StringPossiblyFormatted = {} }; } @@ -1046,7 +1046,7 @@ pub const Formatter = struct { self.formatter.remaining_values = &[_]JSValue{}; } try self.formatter.format( - Tag.get(self.value, self.formatter.globalThis), + try Tag.get(self.value, self.formatter.globalThis), @TypeOf(writer), writer, self.value, @@ -1181,7 +1181,7 @@ pub const Formatter = struct { cell: JSValue.JSType = JSValue.JSType.Cell, }; - pub fn get(value: JSValue, globalThis: *JSGlobalObject) Result { + pub fn get(value: JSValue, globalThis: *JSGlobalObject) bun.JSError!Result { return getAdvanced(value, globalThis, .{ .hide_global = false }); } @@ -1191,12 +1191,12 @@ pub const Formatter = struct { disable_inspect_custom: bool = false, }; - pub fn getAdvanced(value: JSValue, globalThis: *JSGlobalObject, opts: Options) Result { - switch (@intFromEnum(value)) { - 0, 0xa => return Result{ + pub fn getAdvanced(value: JSValue, globalThis: *JSGlobalObject, opts: Options) bun.JSError!Result { + switch (value) { + .zero, .js_undefined => return Result{ .tag = .{ .Undefined = {} }, }, - 0x2 => return Result{ + .null => return Result{ .tag = .{ .Null = {} }, }, else => {}, @@ -1294,16 +1294,16 @@ pub const Formatter = struct { // Is this a react element? if (js_type.isObject() and js_type != .ProxyObject) { - if (value.getOwnTruthy(globalThis, "$$typeof")) |typeof_symbol| { + if (try value.getOwnTruthy(globalThis, "$$typeof")) |typeof_symbol| { // React 18 and below var react_element_legacy = ZigString.init("react.element"); // For React 19 - https://github.com/oven-sh/bun/issues/17223 var react_element_transitional = ZigString.init("react.transitional.element"); var react_fragment = ZigString.init("react.fragment"); - if (JSValue.isSameValue(typeof_symbol, JSValue.symbolFor(globalThis, &react_element_legacy), globalThis) or - JSValue.isSameValue(typeof_symbol, JSValue.symbolFor(globalThis, &react_element_transitional), globalThis) or - JSValue.isSameValue(typeof_symbol, JSValue.symbolFor(globalThis, &react_fragment), globalThis)) + if (try typeof_symbol.isSameValue(.symbolFor(globalThis, &react_element_legacy), globalThis) or + try typeof_symbol.isSameValue(.symbolFor(globalThis, &react_element_transitional), globalThis) or + try typeof_symbol.isSameValue(.symbolFor(globalThis, &react_fragment), globalThis)) { return .{ .tag = .{ .JSX = {} }, .cell = js_type }; } @@ -1613,7 +1613,7 @@ pub const Formatter = struct { // > implementation-specific, potentially-interactive representation // > of an object judged to be maximally useful and informative. } - try this.format(Tag.get(next_value, global), Writer, writer_, next_value, global, enable_ansi_colors); + try this.format(try Tag.get(next_value, global), Writer, writer_, next_value, global, enable_ansi_colors); }, .c => { @@ -1766,8 +1766,8 @@ pub const Formatter = struct { this.writer.writeAll(" ") catch unreachable; } if (!is_iterator) { - const key = nextValue.getIndex(globalObject, 0); - const value = nextValue.getIndex(globalObject, 1); + const key = nextValue.getIndex(globalObject, 0) catch return; + const value = nextValue.getIndex(globalObject, 1) catch return; if (!single_line) { this.formatter.writeIndent(Writer, this.writer) catch unreachable; @@ -1775,7 +1775,7 @@ pub const Formatter = struct { const key_tag = Tag.getAdvanced(key, globalObject, .{ .hide_global = true, .disable_inspect_custom = this.formatter.disable_inspect_custom, - }); + }) catch return; this.formatter.format( key_tag, @@ -1789,7 +1789,7 @@ pub const Formatter = struct { const value_tag = Tag.getAdvanced(value, globalObject, .{ .hide_global = true, .disable_inspect_custom = this.formatter.disable_inspect_custom, - }); + }) catch return; this.formatter.format( value_tag, Writer, @@ -1806,7 +1806,7 @@ pub const Formatter = struct { const tag = Tag.getAdvanced(nextValue, globalObject, .{ .hide_global = true, .disable_inspect_custom = this.formatter.disable_inspect_custom, - }); + }) catch return; this.formatter.format( tag, Writer, @@ -1847,7 +1847,7 @@ pub const Formatter = struct { const key_tag = Tag.getAdvanced(nextValue, globalObject, .{ .hide_global = true, .disable_inspect_custom = this.formatter.disable_inspect_custom, - }); + }) catch return; this.formatter.format( key_tag, Writer, @@ -1924,7 +1924,7 @@ pub const Formatter = struct { const tag = Tag.getAdvanced(value, globalThis, .{ .hide_global = true, .disable_inspect_custom = this.disable_inspect_custom, - }); + }) catch return; if (tag.cell.isHidden()) return; if (ctx.i == 0) { @@ -2270,7 +2270,7 @@ pub const Formatter = struct { if (result.isString()) { writer.print("{}", .{result.fmtString(this.globalThis)}); } else { - try this.format(ConsoleObject.Formatter.Tag.get(result, this.globalThis), Writer, writer_, result, this.globalThis, enable_ansi_colors); + try this.format(try ConsoleObject.Formatter.Tag.get(result, this.globalThis), Writer, writer_, result, this.globalThis, enable_ansi_colors); } }, .Symbol => { @@ -2369,7 +2369,7 @@ pub const Formatter = struct { } }, .Array => { - const len = value.getLength(this.globalThis); + const len = try value.getLength(this.globalThis); // TODO: DerivedArray does not get passed along in JSType, and it's not clear why. // if (jsType == .DerivedArray) { @@ -2404,7 +2404,7 @@ pub const Formatter = struct { first: { const element = value.getDirectIndex(this.globalThis, 0); - const tag = Tag.getAdvanced(element, this.globalThis, .{ + const tag = try Tag.getAdvanced(element, this.globalThis, .{ .hide_global = true, .disable_inspect_custom = this.disable_inspect_custom, }); @@ -2487,7 +2487,7 @@ pub const Formatter = struct { writer.space(); } - const tag = Tag.getAdvanced(element, this.globalThis, .{ + const tag = try Tag.getAdvanced(element, this.globalThis, .{ .hide_global = true, .disable_inspect_custom = this.disable_inspect_custom, }); @@ -2534,10 +2534,7 @@ pub const Formatter = struct { .parent = value, .i = i, }; - value.forEachPropertyNonIndexed(this.globalThis, &iter, Iterator.forEach); - if (this.globalThis.hasException()) { - return error.JSError; - } + try value.forEachPropertyNonIndexed(this.globalThis, &iter, Iterator.forEach); if (this.failed) return; } } @@ -2571,7 +2568,7 @@ pub const Formatter = struct { s3client.writeFormat(ConsoleObject.Formatter, this, writer_, enable_ansi_colors) catch {}; return; } else if (value.as(bun.webcore.FetchHeaders) != null) { - if (value.get_unsafe(this.globalThis, "toJSON")) |toJSONFunction| { + if (try value.get(this.globalThis, "toJSON")) |toJSONFunction| { this.addForNewLine("Headers ".len); writer.writeAll(comptime Output.prettyFmt("Headers ", enable_ansi_colors)); const prev_quote_keys = this.quote_keys; @@ -2589,7 +2586,7 @@ pub const Formatter = struct { ); } } else if (value.as(JSC.DOMFormData) != null) { - if (value.get_unsafe(this.globalThis, "toJSON")) |toJSONFunction| { + if (try value.get(this.globalThis, "toJSON")) |toJSONFunction| { const prev_quote_keys = this.quote_keys; this.quote_keys = true; defer this.quote_keys = prev_quote_keys; @@ -2705,7 +2702,7 @@ pub const Formatter = struct { writer.writeAll(comptime Output.prettyFmt("" ++ fmt ++ "", enable_ansi_colors)); }, .Map => { - const length_value = value.get_unsafe(this.globalThis, "size") orelse JSC.JSValue.jsNumberFromInt32(0); + const length_value = try value.get(this.globalThis, "size") orelse JSC.JSValue.jsNumberFromInt32(0); const length = length_value.toInt32(); const prev_quote_strings = this.quote_strings; @@ -2812,7 +2809,7 @@ pub const Formatter = struct { writer.writeAll("}"); }, .Set => { - const length_value = value.get_unsafe(this.globalThis, "size") orelse JSC.JSValue.jsNumberFromInt32(0); + const length_value = try value.get(this.globalThis, "size") orelse JSC.JSValue.jsNumberFromInt32(0); const length = length_value.toInt32(); const prev_quote_strings = this.quote_strings; @@ -2855,7 +2852,7 @@ pub const Formatter = struct { writer.writeAll("}"); }, .toJSON => { - if (value.get_unsafe(this.globalThis, "toJSON")) |func| brk: { + if (try value.get(this.globalThis, "toJSON")) |func| brk: { const result = func.call(this.globalThis, value, &.{}) catch { this.globalThis.clearException(); break :brk; @@ -2863,7 +2860,7 @@ pub const Formatter = struct { const prev_quote_keys = this.quote_keys; this.quote_keys = true; defer this.quote_keys = prev_quote_keys; - const tag = ConsoleObject.Formatter.Tag.get(result, this.globalThis); + const tag = try ConsoleObject.Formatter.Tag.get(result, this.globalThis); try this.format(tag, Writer, writer_, result, this.globalThis, enable_ansi_colors); return; } @@ -2896,7 +2893,7 @@ pub const Formatter = struct { }, .Event => { const event_type_value: JSValue = brk: { - const value_ = value.get_unsafe(this.globalThis, "type") orelse break :brk .js_undefined; + const value_ = try value.get(this.globalThis, "type") orelse break :brk .js_undefined; if (value_.isString()) { break :brk value_; } @@ -2949,7 +2946,7 @@ pub const Formatter = struct { .{}, ); - const tag = Tag.getAdvanced(message_value, this.globalThis, .{ + const tag = try Tag.getAdvanced(message_value, this.globalThis, .{ .hide_global = true, .disable_inspect_custom = this.disable_inspect_custom, }); @@ -2973,7 +2970,7 @@ pub const Formatter = struct { .{}, ); const data: JSValue = (try value.fastGet(this.globalThis, .data)) orelse .js_undefined; - const tag = Tag.getAdvanced(data, this.globalThis, .{ + const tag = try Tag.getAdvanced(data, this.globalThis, .{ .hide_global = true, .disable_inspect_custom = this.disable_inspect_custom, }); @@ -2995,7 +2992,7 @@ pub const Formatter = struct { .{}, ); - const tag = Tag.getAdvanced(error_value, this.globalThis, .{ + const tag = try Tag.getAdvanced(error_value, this.globalThis, .{ .hide_global = true, .disable_inspect_custom = this.disable_inspect_custom, }); @@ -3029,8 +3026,8 @@ pub const Formatter = struct { defer if (tag_name_slice.isAllocated()) tag_name_slice.deinit(); - if (value.get_unsafe(this.globalThis, "type")) |type_value| { - const _tag = Tag.getAdvanced(type_value, this.globalThis, .{ + if (try value.get(this.globalThis, "type")) |type_value| { + const _tag = try Tag.getAdvanced(type_value, this.globalThis, .{ .hide_global = true, .disable_inspect_custom = this.disable_inspect_custom, }); @@ -3062,7 +3059,7 @@ pub const Formatter = struct { writer.writeAll(tag_name_slice.slice()); if (enable_ansi_colors) writer.writeAll(comptime Output.prettyFmt("", enable_ansi_colors)); - if (value.get_unsafe(this.globalThis, "key")) |key_value| { + if (try value.get(this.globalThis, "key")) |key_value| { if (!key_value.isUndefinedOrNull()) { if (needs_space) writer.writeAll(" key=") @@ -3073,7 +3070,7 @@ pub const Formatter = struct { this.quote_strings = true; defer this.quote_strings = old_quote_strings; - try this.format(Tag.getAdvanced(key_value, this.globalThis, .{ + try this.format(try Tag.getAdvanced(key_value, this.globalThis, .{ .hide_global = true, .disable_inspect_custom = this.disable_inspect_custom, }), Writer, writer_, key_value, this.globalThis, enable_ansi_colors); @@ -3082,7 +3079,7 @@ pub const Formatter = struct { } } - if (value.get_unsafe(this.globalThis, "props")) |props| { + if (try value.get(this.globalThis, "props")) |props| { const prev_quote_strings = this.quote_strings; defer this.quote_strings = prev_quote_strings; this.quote_strings = true; @@ -3095,7 +3092,7 @@ pub const Formatter = struct { }).init(this.globalThis, props_obj); defer props_iter.deinit(); - const children_prop = props.get_unsafe(this.globalThis, "children"); + const children_prop = try props.get(this.globalThis, "children"); if (props_iter.len > 0) { { this.indent += 1; @@ -3107,7 +3104,7 @@ pub const Formatter = struct { continue; const property_value = props_iter.value; - const tag = Tag.getAdvanced(property_value, this.globalThis, .{ + const tag = try Tag.getAdvanced(property_value, this.globalThis, .{ .hide_global = true, .disable_inspect_custom = this.disable_inspect_custom, }); @@ -3156,7 +3153,7 @@ pub const Formatter = struct { } if (children_prop) |children| { - const tag = Tag.get(children, this.globalThis); + const tag = try Tag.get(children, this.globalThis); const print_children = switch (tag.tag) { .String, .JSX, .Array => true, @@ -3191,14 +3188,14 @@ pub const Formatter = struct { this.indent += 1; this.writeIndent(Writer, writer_) catch unreachable; defer this.indent -|= 1; - try this.format(Tag.get(children, this.globalThis), Writer, writer_, children, this.globalThis, enable_ansi_colors); + try this.format(try Tag.get(children, this.globalThis), Writer, writer_, children, this.globalThis, enable_ansi_colors); } writer.writeAll("\n"); this.writeIndent(Writer, writer_) catch unreachable; }, .Array => { - const length = children.getLength(this.globalThis); + const length = try children.getLength(this.globalThis); if (length == 0) break :print_children; writer.writeAll(">\n"); @@ -3213,8 +3210,8 @@ pub const Formatter = struct { var j: usize = 0; while (j < length) : (j += 1) { - const child = children.getIndex(this.globalThis, @as(u32, @intCast(j))); - try this.format(Tag.getAdvanced(child, this.globalThis, .{ + const child = try children.getIndex(this.globalThis, @as(u32, @intCast(j))); + try this.format(try Tag.getAdvanced(child, this.globalThis, .{ .hide_global = true, .disable_inspect_custom = this.disable_inspect_custom, }), Writer, writer_, child, this.globalThis, enable_ansi_colors); @@ -3304,14 +3301,11 @@ pub const Formatter = struct { }); return; } else if (this.ordered_properties) { - value.forEachPropertyOrdered(this.globalThis, &iter, Iterator.forEach); + try value.forEachPropertyOrdered(this.globalThis, &iter, Iterator.forEach); } else { - value.forEachProperty(this.globalThis, &iter, Iterator.forEach); + try value.forEachProperty(this.globalThis, &iter, Iterator.forEach); } - if (this.globalThis.hasException()) { - return error.JSError; - } if (this.failed) return; if (iter.i == 0) { @@ -3464,7 +3458,7 @@ pub const Formatter = struct { } // TODO: if (options.showProxy), print like `Proxy { target: ..., handlers: ... }` // this is default off so it is not used. - try this.format(ConsoleObject.Formatter.Tag.get(target, this.globalThis), Writer, writer_, target, this.globalThis, enable_ansi_colors); + try this.format(try ConsoleObject.Formatter.Tag.get(target, this.globalThis), Writer, writer_, target, this.globalThis, enable_ansi_colors); }, } } @@ -3654,7 +3648,7 @@ pub fn timeLog( var writer = console.error_writer.writer(); const Writer = @TypeOf(writer); for (args[0..args_len]) |arg| { - const tag = ConsoleObject.Formatter.Tag.get(arg, global); + const tag = ConsoleObject.Formatter.Tag.get(arg, global) catch return; _ = writer.write(" ") catch 0; if (Output.enable_ansi_colors_stderr) { fmt.format(tag, Writer, writer, arg, global, true) catch {}; // TODO: diff --git a/src/bun.js/ModuleLoader.zig b/src/bun.js/ModuleLoader.zig index d190e053ea..5154d9c3e5 100644 --- a/src/bun.js/ModuleLoader.zig +++ b/src/bun.js/ModuleLoader.zig @@ -429,7 +429,7 @@ pub const AsyncModule = struct { errorable = JSC.ErrorableResolvedSource.ok(this.resumeLoadingModule(&log) catch |err| { switch (err) { error.JSError => { - errorable = .err(error.JSError, this.globalThis.takeError(error.JSError).asVoid()); + errorable = .err(error.JSError, this.globalThis.takeError(error.JSError)); break :outer; }, else => { @@ -468,13 +468,16 @@ pub const AsyncModule = struct { specifier_: bun.String, referrer_: bun.String, log: *logger.Log, - ) void { + ) bun.JSExecutionTerminated!void { JSC.markBinding(@src()); var specifier = specifier_; var referrer = referrer_; + var scope: JSC.CatchScope = undefined; + scope.init(globalThis, @src(), .enabled); defer { specifier.deref(); referrer.deref(); + scope.deinit(); } var errorable: JSC.ErrorableResolvedSource = undefined; @@ -487,7 +490,7 @@ pub const AsyncModule = struct { } if (e == error.JSError) { - errorable = JSC.ErrorableResolvedSource.err(error.JSError, globalThis.takeError(error.JSError).asVoid()); + errorable = JSC.ErrorableResolvedSource.err(error.JSError, globalThis.takeError(error.JSError)); } else { VirtualMachine.processFetchLog( globalThis, @@ -512,6 +515,7 @@ pub const AsyncModule = struct { &specifier, &referrer, ); + try scope.assertNoExceptionExceptTermination(); } pub fn resolveError(this: *AsyncModule, vm: *VirtualMachine, import_record_id: u32, result: PackageResolveError) !void { @@ -1616,7 +1620,7 @@ pub export fn Bun__transpileFile( var virtual_source_to_use: ?logger.Source = null; var blob_to_deinit: ?JSC.WebCore.Blob = null; var lr = options.getLoaderAndVirtualSource(_specifier.slice(), jsc_vm, &virtual_source_to_use, &blob_to_deinit, type_attribute_str) catch { - ret.* = JSC.ErrorableResolvedSource.err(error.JSErrorObject, globalObject.ERR(.MODULE_NOT_FOUND, "Blob not found", .{}).toJS().asVoid()); + ret.* = JSC.ErrorableResolvedSource.err(error.JSErrorObject, globalObject.ERR(.MODULE_NOT_FOUND, "Blob not found", .{}).toJS()); return null; }; defer if (blob_to_deinit) |*blob| blob.deinit(); @@ -1815,7 +1819,7 @@ pub export fn Bun__transpileFile( }, error.PluginError => return null, error.JSError => { - ret.* = JSC.ErrorableResolvedSource.err(error.JSError, globalObject.takeError(error.JSError).asVoid()); + ret.* = JSC.ErrorableResolvedSource.err(error.JSError, globalObject.takeError(error.JSError)); return null; }, else => { @@ -1991,7 +1995,7 @@ export fn Bun__transpileVirtualModule( switch (err) { error.PluginError => return true, error.JSError => { - ret.* = JSC.ErrorableResolvedSource.err(error.JSError, globalObject.takeError(error.JSError).asVoid()); + ret.* = JSC.ErrorableResolvedSource.err(error.JSError, globalObject.takeError(error.JSError)); return true; }, else => { @@ -2140,12 +2144,12 @@ pub const RuntimeTranspilerStore = struct { } // This is run at the top of the event loop on the JS thread. - pub fn drain(this: *RuntimeTranspilerStore) void { + pub fn drain(this: *RuntimeTranspilerStore) bun.JSExecutionTerminated!void { var batch = this.queue.popBatch(); var iter = batch.iterator(); if (iter.next()) |job| { // we run just one job first to see if there are more - job.runFromJSThread(); + try job.runFromJSThread(); } else { return; } @@ -2155,8 +2159,8 @@ pub const RuntimeTranspilerStore = struct { const jsc_vm = vm.jsc; while (iter.next()) |job| { // if there are more, we need to drain the microtasks from the previous run - event_loop.drainMicrotasksWithGlobal(global, jsc_vm); - job.runFromJSThread(); + try event_loop.drainMicrotasksWithGlobal(global, jsc_vm); + try job.runFromJSThread(); } // immediately after this is called, the microtasks will be drained again. @@ -2263,7 +2267,7 @@ pub const RuntimeTranspilerStore = struct { this.vm.eventLoop().enqueueTaskConcurrent(JSC.ConcurrentTask.createFrom(&this.vm.transpiler_store)); } - pub fn runFromJSThread(this: *TranspilerJob) void { + pub fn runFromJSThread(this: *TranspilerJob) bun.JSExecutionTerminated!void { var vm = this.vm; const promise = this.promise.swap(); const globalThis = this.globalThis; @@ -2296,7 +2300,7 @@ pub const RuntimeTranspilerStore = struct { _ = vm.transpiler_store.store.put(this); - ModuleLoader.AsyncModule.fulfill(globalThis, promise, &resolved_source, parse_error, specifier, referrer, &log); + try ModuleLoader.AsyncModule.fulfill(globalThis, promise, &resolved_source, parse_error, specifier, referrer, &log); } pub fn schedule(this: *TranspilerJob) void { diff --git a/src/bun.js/VirtualMachine.zig b/src/bun.js/VirtualMachine.zig index 10e2a063de..ac4a53f840 100644 --- a/src/bun.js/VirtualMachine.zig +++ b/src/bun.js/VirtualMachine.zig @@ -535,60 +535,80 @@ fn wrapUnhandledRejectionErrorForUncaughtException(globalObject: *JSGlobalObject return globalObject.ERR(.UNHANDLED_REJECTION, msg, .{"undefined"}).toJS(); } -pub fn unhandledRejection(this: *JSC.VirtualMachine, globalObject: *JSGlobalObject, reason: JSValue, promise: JSValue) bool { +pub fn unhandledRejection(this: *JSC.VirtualMachine, globalObject: *JSGlobalObject, reason: JSValue, promise: JSValue) void { if (this.isShuttingDown()) { Output.debugWarn("unhandledRejection during shutdown.", .{}); - return true; + return; } if (isBunTest) { this.unhandled_error_counter += 1; this.onUnhandledRejection(this, globalObject, reason); - return true; + return; } switch (this.unhandledRejectionsMode()) { .bun => { - if (Bun__handleUnhandledRejection(globalObject, reason, promise) > 0) return true; + if (Bun__handleUnhandledRejection(globalObject, reason, promise) > 0) return; // continue to default handler }, .none => { - defer this.eventLoop().drainMicrotasks(); - if (Bun__handleUnhandledRejection(globalObject, reason, promise) > 0) return true; - return true; // ignore the unhandled rejection + defer this.eventLoop().drainMicrotasks() catch |e| switch (e) { + error.JSExecutionTerminated => {}, // we are returning anyway + }; + if (Bun__handleUnhandledRejection(globalObject, reason, promise) > 0) return; + return; // ignore the unhandled rejection }, .warn => { - defer this.eventLoop().drainMicrotasks(); + defer this.eventLoop().drainMicrotasks() catch |e| switch (e) { + error.JSExecutionTerminated => {}, // we are returning anyway + }; _ = Bun__handleUnhandledRejection(globalObject, reason, promise); Bun__promises__emitUnhandledRejectionWarning(globalObject, reason, promise); - return true; + return; }, .warn_with_error_code => { - defer this.eventLoop().drainMicrotasks(); - if (Bun__handleUnhandledRejection(globalObject, reason, promise) > 0) return true; + defer this.eventLoop().drainMicrotasks() catch |e| switch (e) { + error.JSExecutionTerminated => {}, // we are returning anyway + }; + if (Bun__handleUnhandledRejection(globalObject, reason, promise) > 0) return; Bun__promises__emitUnhandledRejectionWarning(globalObject, reason, promise); this.exit_handler.exit_code = 1; - return true; + return; }, .strict => { - defer this.eventLoop().drainMicrotasks(); + defer this.eventLoop().drainMicrotasks() catch |e| switch (e) { + error.JSExecutionTerminated => {}, // we are returning anyway + }; const wrapped_reason = wrapUnhandledRejectionErrorForUncaughtException(globalObject, reason); _ = this.uncaughtException(globalObject, wrapped_reason, true); - if (Bun__handleUnhandledRejection(globalObject, reason, promise) > 0) return true; + if (Bun__handleUnhandledRejection(globalObject, reason, promise) > 0) return; Bun__promises__emitUnhandledRejectionWarning(globalObject, reason, promise); - return true; + return; }, .throw => { - defer this.eventLoop().drainMicrotasks(); - if (Bun__handleUnhandledRejection(globalObject, reason, promise) > 0) return true; + if (Bun__handleUnhandledRejection(globalObject, reason, promise) > 0) { + this.eventLoop().drainMicrotasks() catch |e| switch (e) { + error.JSExecutionTerminated => {}, // we are returning anyway + }; + return; + } const wrapped_reason = wrapUnhandledRejectionErrorForUncaughtException(globalObject, reason); - if (this.uncaughtException(globalObject, wrapped_reason, true)) return true; + if (this.uncaughtException(globalObject, wrapped_reason, true)) { + this.eventLoop().drainMicrotasks() catch |e| switch (e) { + error.JSExecutionTerminated => {}, // we are returning anyway + }; + return; + } // continue to default handler + this.eventLoop().drainMicrotasks() catch |e| switch (e) { + error.JSExecutionTerminated => return, + }; }, } this.unhandled_error_counter += 1; this.onUnhandledRejection(this, globalObject, reason); - return false; + return; } pub fn handledPromise(this: *JSC.VirtualMachine, globalObject: *JSGlobalObject, promise: JSValue) bool { @@ -636,7 +656,7 @@ pub fn uncaughtException(this: *JSC.VirtualMachine, globalObject: *JSGlobalObjec pub fn handlePendingInternalPromiseRejection(this: *JSC.VirtualMachine) void { var promise = this.pending_internal_promise.?; if (promise.status(this.global.vm()) == .rejected and !promise.isHandled(this.global.vm())) { - _ = this.unhandledRejection(this.global, promise.result(this.global.vm()), promise.asValue()); + this.unhandledRejection(this.global, promise.result(this.global.vm()), promise.asValue()); promise.setHandled(this.global.vm()); } } @@ -1660,7 +1680,7 @@ pub fn resolveMaybeNeedsTrailingSlash( printed, ), }; - res.* = ErrorableString.err(error.NameTooLong, (try bun.api.ResolveMessage.create(global, VirtualMachine.get().allocator, msg, source_utf8.slice())).asVoid()); + res.* = ErrorableString.err(error.NameTooLong, (try bun.api.ResolveMessage.create(global, VirtualMachine.get().allocator, msg, source_utf8.slice()))); return; } @@ -1750,7 +1770,7 @@ pub fn resolveMaybeNeedsTrailingSlash( }; { - res.* = ErrorableString.err(err, (try bun.api.ResolveMessage.create(global, VirtualMachine.get().allocator, msg, source_utf8.slice())).asVoid()); + res.* = ErrorableString.err(err, (try bun.api.ResolveMessage.create(global, VirtualMachine.get().allocator, msg, source_utf8.slice()))); } return; @@ -1772,7 +1792,8 @@ pub export fn Bun__drainMicrotasksFromJS(globalObject: *JSGlobalObject, callfram } pub fn drainMicrotasks(this: *VirtualMachine) void { - this.eventLoop().drainMicrotasks(); + // TODO: properly propagate exception upwards + this.eventLoop().drainMicrotasks() catch {}; } pub fn processFetchLog(globalThis: *JSGlobalObject, specifier: bun.String, referrer: bun.String, log: *logger.Log, ret: *ErrorableResolvedSource, err: anyerror) void { @@ -1794,7 +1815,7 @@ pub fn processFetchLog(globalThis: *JSGlobalObject, specifier: bun.String, refer }; }; { - ret.* = ErrorableResolvedSource.err(err, (bun.api.BuildMessage.create(globalThis, globalThis.allocator(), msg) catch |e| globalThis.takeException(e)).asVoid()); + ret.* = ErrorableResolvedSource.err(err, (bun.api.BuildMessage.create(globalThis, globalThis.allocator(), msg) catch |e| globalThis.takeException(e))); } return; }, @@ -1802,13 +1823,13 @@ pub fn processFetchLog(globalThis: *JSGlobalObject, specifier: bun.String, refer 1 => { const msg = log.msgs.items[0]; ret.* = ErrorableResolvedSource.err(err, switch (msg.metadata) { - .build => (bun.api.BuildMessage.create(globalThis, globalThis.allocator(), msg) catch |e| globalThis.takeException(e)).asVoid(), + .build => (bun.api.BuildMessage.create(globalThis, globalThis.allocator(), msg) catch |e| globalThis.takeException(e)), .resolve => (bun.api.ResolveMessage.create( globalThis, globalThis.allocator(), msg, referrer.toUTF8(bun.default_allocator).slice(), - ) catch |e| globalThis.takeException(e)).asVoid(), + ) catch |e| globalThis.takeException(e)), }); return; }, @@ -1841,7 +1862,7 @@ pub fn processFetchLog(globalThis: *JSGlobalObject, specifier: bun.String, refer specifier, }) catch unreachable, ), - ).asVoid(), + ), ); }, } @@ -1910,8 +1931,7 @@ pub noinline fn runErrorHandler(this: *VirtualMachine, result: JSValue, exceptio const writer = buffered_writer.writer(); - if (result.isException(this.global.vm())) { - const exception = @as(*Exception, @ptrCast(result.asVoid())); + if (result.asException(this.jsc)) |exception| { this.printException( exception, exception_list, @@ -1987,7 +2007,7 @@ fn loadPreloads(this: *VirtualMachine) !?*JSInternalPromise { return error.ModuleNotFound; }, }; - var promise = JSModuleLoader.import(this.global, &String.fromBytes(result.path().?.text)); + var promise = try JSModuleLoader.import(this.global, &String.fromBytes(result.path().?.text)); this.pending_internal_promise = promise; JSValue.fromCell(promise).protect(); @@ -3091,7 +3111,7 @@ fn printErrorInstance( } formatter.format( - JSC.Formatter.Tag.getAdvanced( + try JSC.Formatter.Tag.getAdvanced( value, this.global, .{ .disable_inspect_custom = true, .hide_global = true }, @@ -3132,7 +3152,7 @@ fn printErrorInstance( // "cause" is not enumerable, so the above loop won't see it. if (!saw_cause) { - if (error_instance.getOwn(this.global, "cause")) |cause| { + if (try error_instance.getOwn(this.global, "cause")) |cause| { if (cause.jsType() == .ErrorInstance) { cause.protect(); try errors_to_append.append(cause); @@ -3141,7 +3161,7 @@ fn printErrorInstance( } } else if (mode == .js and error_instance != .zero) { // If you do reportError([1,2,3]] we should still show something at least. - const tag = JSC.Formatter.Tag.getAdvanced( + const tag = try JSC.Formatter.Tag.getAdvanced( error_instance, this.global, .{ .disable_inspect_custom = true, .hide_global = true }, diff --git a/src/bun.js/api/BunObject.zig b/src/bun.js/api/BunObject.zig index 22901fde80..a84db98bc3 100644 --- a/src/bun.js/api/BunObject.zig +++ b/src/bun.js/api/BunObject.zig @@ -95,7 +95,7 @@ pub const BunObject = struct { fn toJSGetter(comptime getter: anytype) LazyPropertyCallback { return struct { pub fn callback(this: *JSC.JSGlobalObject, object: *JSC.JSObject) callconv(JSC.conv) JSValue { - return bun.jsc.toJSHostValue(this, getter(this, object)); + return bun.jsc.toJSHostCall(this, @src(), getter, .{ this, object }); } }.callback; } @@ -381,7 +381,7 @@ pub fn inspectTable(globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) const writer = buffered_writer.writer(); const Writer = @TypeOf(writer); const properties: JSValue = if (arguments[1].jsType().isArray()) arguments[1] else .js_undefined; - var table_printer = ConsoleObject.TablePrinter.init( + var table_printer = try ConsoleObject.TablePrinter.init( globalThis, .Log, value, @@ -847,7 +847,7 @@ fn doResolveWithArgs(ctx: *JSC.JSGlobalObject, specifier: bun.String, from: bun. ); if (!errorable.success) { - return ctx.throwValue(bun.cast(JSC.C.JSValueRef, errorable.result.err.ptr.?).?.value()); + return ctx.throwValue(errorable.result.err.value); } if (query_string.len > 0) { @@ -905,7 +905,7 @@ export fn Bun__resolveSync(global: *JSGlobalObject, specifier: JSValue, source: const source_str = source.toBunString(global) catch return .zero; defer source_str.deref(); - return JSC.toJSHostValue(global, doResolveWithArgs(global, specifier_str, source_str, is_esm, true, is_user_require_resolve)); + return JSC.toJSHostCall(global, @src(), doResolveWithArgs, .{ global, specifier_str, source_str, is_esm, true, is_user_require_resolve }); } export fn Bun__resolveSyncWithPaths( @@ -934,12 +934,12 @@ export fn Bun__resolveSyncWithPaths( bun_vm.transpiler.resolver.custom_dir_paths = paths; defer bun_vm.transpiler.resolver.custom_dir_paths = null; - return JSC.toJSHostValue(global, doResolveWithArgs(global, specifier_str, source_str, is_esm, true, is_user_require_resolve)); + return JSC.toJSHostCall(global, @src(), doResolveWithArgs, .{ global, specifier_str, source_str, is_esm, true, is_user_require_resolve }); } export fn Bun__resolveSyncWithStrings(global: *JSGlobalObject, specifier: *bun.String, source: *bun.String, is_esm: bool) JSC.JSValue { Output.scoped(.importMetaResolve, false)("source: {s}, specifier: {s}", .{ source.*, specifier.* }); - return JSC.toJSHostValue(global, doResolveWithArgs(global, specifier.*, source.*, is_esm, true, false)); + return JSC.toJSHostCall(global, @src(), doResolveWithArgs, .{ global, specifier.*, source.*, is_esm, true, false }); } export fn Bun__resolveSyncWithSource(global: *JSGlobalObject, specifier: JSValue, source: *bun.String, is_esm: bool, is_user_require_resolve: bool) JSC.JSValue { @@ -948,7 +948,7 @@ export fn Bun__resolveSyncWithSource(global: *JSGlobalObject, specifier: JSValue if (specifier_str.length() == 0) { return global.ERR(.INVALID_ARG_VALUE, "The argument 'id' must be a non-empty string. Received ''", .{}).throw() catch .zero; } - return JSC.toJSHostValue(global, doResolveWithArgs(global, specifier_str, source.*, is_esm, true, is_user_require_resolve)); + return JSC.toJSHostCall(global, @src(), doResolveWithArgs, .{ global, specifier_str, source.*, is_esm, true, is_user_require_resolve }); } pub fn indexOfLine(globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) bun.JSError!JSC.JSValue { diff --git a/src/bun.js/api/JSBundler.zig b/src/bun.js/api/JSBundler.zig index 66da89ea28..7ffa49672d 100644 --- a/src/bun.js/api/JSBundler.zig +++ b/src/bun.js/api/JSBundler.zig @@ -86,11 +86,11 @@ pub const JSBundler = struct { // Plugins must be resolved first as they are allowed to mutate the config JSValue if (try config.getArray(globalThis, "plugins")) |array| { - const length = array.getLength(globalThis); - var iter = array.arrayIterator(globalThis); + const length = try array.getLength(globalThis); + var iter = try array.arrayIterator(globalThis); var onstart_promise_array: JSValue = .js_undefined; var i: usize = 0; - while (iter.next()) |plugin| : (i += 1) { + while (try iter.next()) |plugin| : (i += 1) { if (!plugin.isObject()) { return globalThis.throwInvalidArguments("Expected plugin to be an object", .{}); } @@ -267,8 +267,8 @@ pub const JSBundler = struct { } if (try config.getArray(globalThis, "entrypoints") orelse try config.getArray(globalThis, "entryPoints")) |entry_points| { - var iter = entry_points.arrayIterator(globalThis); - while (iter.next()) |entry_point| { + var iter = try entry_points.arrayIterator(globalThis); + while (try iter.next()) |entry_point| { var slice = try entry_point.toSliceOrNull(globalThis); defer slice.deinit(); try this.entry_points.insert(slice.slice()); @@ -291,8 +291,8 @@ pub const JSBundler = struct { defer slice.deinit(); try this.conditions.insert(slice.slice()); } else if (conditions_value.jsType().isArray()) { - var iter = conditions_value.arrayIterator(globalThis); - while (iter.next()) |entry_point| { + var iter = try conditions_value.arrayIterator(globalThis); + while (try iter.next()) |entry_point| { var slice = try entry_point.toSliceOrNull(globalThis); defer slice.deinit(); try this.conditions.insert(slice.slice()); @@ -332,8 +332,8 @@ pub const JSBundler = struct { } if (try config.getOwnArray(globalThis, "external")) |externals| { - var iter = externals.arrayIterator(globalThis); - while (iter.next()) |entry_point| { + var iter = try externals.arrayIterator(globalThis); + while (try iter.next()) |entry_point| { var slice = try entry_point.toSliceOrNull(globalThis); defer slice.deinit(); try this.external.insert(slice.slice()); @@ -341,8 +341,8 @@ pub const JSBundler = struct { } if (try config.getOwnArray(globalThis, "drop")) |drops| { - var iter = drops.arrayIterator(globalThis); - while (iter.next()) |entry| { + var iter = try drops.arrayIterator(globalThis); + while (try iter.next()) |entry| { var slice = try entry.toSliceOrNull(globalThis); defer slice.deinit(); try this.drop.insert(slice.slice()); @@ -782,7 +782,7 @@ pub const JSBundler = struct { } export fn JSBundlerPlugin__onDefer(load: *Load, global: *JSC.JSGlobalObject) JSValue { - return JSC.toJSHostValue(global, load.onDefer(global)); + return JSC.toJSHostCall(global, @src(), Load.onDefer, .{ load, global }); } fn onDefer(this: *Load, globalObject: *JSC.JSGlobalObject) bun.JSError!JSValue { if (this.called_defer) { diff --git a/src/bun.js/api/JSTranspiler.zig b/src/bun.js/api/JSTranspiler.zig index b9ec44b4d4..b9a7dbdcd0 100644 --- a/src/bun.js/api/JSTranspiler.zig +++ b/src/bun.js/api/JSTranspiler.zig @@ -6,7 +6,6 @@ const JSC = bun.JSC; const Transpiler = bun.transpiler; const options = @import("../../options.zig"); const ZigString = JSC.ZigString; -const JSObject = JSC.JSObject; const JSValue = bun.JSC.JSValue; const JSGlobalObject = JSC.JSGlobalObject; const strings = bun.strings; @@ -354,13 +353,13 @@ fn transformOptionsFromJSC(globalObject: *JSC.JSGlobalObject, temp_allocator: st single_external[0] = std.fmt.allocPrint(allocator, "{}", .{external}) catch unreachable; transpiler.transform.external = single_external; } else if (toplevel_type.isArray()) { - const count = external.getLength(globalThis); + const count = try external.getLength(globalThis); if (count == 0) break :external; var externals = allocator.alloc(string, count) catch unreachable; - var iter = external.arrayIterator(globalThis); + var iter = try external.arrayIterator(globalThis); var i: usize = 0; - while (iter.next()) |entry| { + while (try iter.next()) |entry| { if (!entry.jsType().isStringLike()) { return globalObject.throwInvalidArguments("external must be a string or string[]", .{}); } @@ -550,13 +549,13 @@ fn transformOptionsFromJSC(globalObject: *JSC.JSGlobalObject, temp_allocator: st var total_name_buf_len: u32 = 0; var string_count: u32 = 0; - const iter = JSC.JSArrayIterator.init(eliminate, globalThis); + const iter = try JSC.JSArrayIterator.init(eliminate, globalThis); { var length_iter = iter; - while (length_iter.next()) |value| { + while (try length_iter.next()) |value| { if (value.isString()) { - const length = @as(u32, @truncate(value.getLength(globalThis))); - string_count += @as(u32, @intFromBool(length > 0)); + const length: u32 = @truncate(try value.getLength(globalThis)); + string_count += @intFromBool(length > 0); total_name_buf_len += length; } } @@ -567,7 +566,7 @@ fn transformOptionsFromJSC(globalObject: *JSC.JSGlobalObject, temp_allocator: st try replacements.ensureUnusedCapacity(bun.default_allocator, string_count); { var length_iter = iter; - while (length_iter.next()) |value| { + while (try length_iter.next()) |value| { if (!value.isString()) continue; const str = try value.getZigString(globalThis); if (str.len == 0) continue; @@ -624,10 +623,10 @@ fn transformOptionsFromJSC(globalObject: *JSC.JSGlobalObject, temp_allocator: st continue; } - if (value.isObject() and value.getLength(globalObject) == 2) { - const replacementValue = JSC.JSObject.getIndex(value, globalThis, 1); + if (value.isObject() and try value.getLength(globalObject) == 2) { + const replacementValue = try value.getIndex(globalThis, 1); if (try exportReplacementValue(replacementValue, globalThis)) |to_replace| { - const replacementKey = JSC.JSObject.getIndex(value, globalThis, 0); + const replacementKey = try value.getIndex(globalThis, 0); var slice = (try (try replacementKey.toSlice(globalThis, bun.default_allocator)).cloneIfNeeded(bun.default_allocator)); const replacement_name = slice.slice(); diff --git a/src/bun.js/api/Timer/TimerObjectInternals.zig b/src/bun.js/api/Timer/TimerObjectInternals.zig index cc3db48996..60e3c88cba 100644 --- a/src/bun.js/api/Timer/TimerObjectInternals.zig +++ b/src/bun.js/api/Timer/TimerObjectInternals.zig @@ -96,7 +96,7 @@ pub fn runImmediateTask(this: *TimerObjectInternals, vm: *VirtualMachine) bool { this.deref(); } - vm.eventLoop().exitMaybeDrainMicrotasks(!exception_thrown); + vm.eventLoop().exitMaybeDrainMicrotasks(!exception_thrown) catch return true; return exception_thrown; } diff --git a/src/bun.js/api/bun/dns_resolver.zig b/src/bun.js/api/bun/dns_resolver.zig index f7bfc86f29..4fe7437c67 100644 --- a/src/bun.js/api/bun/dns_resolver.zig +++ b/src/bun.js/api/bun/dns_resolver.zig @@ -3303,7 +3303,7 @@ pub const DNSResolver = struct { return globalThis.throwInvalidArgumentType("setServers", "servers", "array"); } - var triplesIterator = argument.arrayIterator(globalThis); + var triplesIterator = try argument.arrayIterator(globalThis); if (triplesIterator.len == 0) { const r = c_ares.ares_set_servers_ports(channel, null); @@ -3321,19 +3321,19 @@ pub const DNSResolver = struct { var i: u32 = 0; - while (triplesIterator.next()) |triple| : (i += 1) { + while (try triplesIterator.next()) |triple| : (i += 1) { if (!triple.isArray()) { return globalThis.throwInvalidArgumentType("setServers", "triple", "array"); } - const family = JSValue.getIndex(triple, globalThis, 0).toInt32(); - const port = JSValue.getIndex(triple, globalThis, 2).toInt32(); + const family = (try triple.getIndex(globalThis, 0)).toInt32(); + const port = (try triple.getIndex(globalThis, 2)).toInt32(); if (family != 4 and family != 6) { return globalThis.throwInvalidArguments("Invalid address family", .{}); } - const addressString = try JSValue.getIndex(triple, globalThis, 1).toBunString(globalThis); + const addressString = try (try triple.getIndex(globalThis, 1)).toBunString(globalThis); defer addressString.deref(); const addressSlice = try addressString.toOwnedSlice(allocator); diff --git a/src/bun.js/api/bun/h2_frame_parser.zig b/src/bun.js/api/bun/h2_frame_parser.zig index 5e6e4305d7..9009855bae 100644 --- a/src/bun.js/api/bun/h2_frame_parser.zig +++ b/src/bun.js/api/bun/h2_frame_parser.zig @@ -2878,9 +2878,9 @@ pub const H2FrameParser = struct { var stream = std.io.fixedBufferStream(&buffer); const writer = stream.writer(); stream.seekTo(FrameHeader.byteSize) catch {}; - var value_iter = origin_arg.arrayIterator(globalObject); + var value_iter = try origin_arg.arrayIterator(globalObject); - while (value_iter.next()) |item| { + while (try value_iter.next()) |item| { if (!item.isString()) { return globalObject.throwInvalidArguments("Expected origin to be a string or an array of strings", .{}); } @@ -3446,7 +3446,7 @@ pub const H2FrameParser = struct { if (js_value.jsType().isArray()) { // https://github.com/oven-sh/bun/issues/8940 - var value_iter = js_value.arrayIterator(globalObject); + var value_iter = try js_value.arrayIterator(globalObject); if (SingleValueHeaders.indexOf(validated_name)) |idx| { if (value_iter.len > 1 or single_value_headers[idx]) { @@ -3456,7 +3456,7 @@ pub const H2FrameParser = struct { single_value_headers[idx] = true; } - while (value_iter.next()) |item| { + while (try value_iter.next()) |item| { if (item.isEmptyOrUndefinedOrNull()) { const exception = globalObject.toTypeError(.HTTP2_INVALID_HEADER_VALUE, "Invalid value for header \"{s}\"", .{validated_name}); return globalObject.throwValue(exception); @@ -3889,7 +3889,7 @@ pub const H2FrameParser = struct { if (js_value.jsType().isArray()) { log("array header {s}", .{name}); // https://github.com/oven-sh/bun/issues/8940 - var value_iter = js_value.arrayIterator(globalObject); + var value_iter = try js_value.arrayIterator(globalObject); if (SingleValueHeaders.indexOf(validated_name)) |idx| { if (value_iter.len > 1 or single_value_headers[idx]) { @@ -3902,7 +3902,7 @@ pub const H2FrameParser = struct { single_value_headers[idx] = true; } - while (value_iter.next()) |item| { + while (try value_iter.next()) |item| { if (item.isEmptyOrUndefinedOrNull()) { if (!globalObject.hasException()) { return globalObject.ERR(.HTTP2_INVALID_HEADER_VALUE, "Invalid value for header \"{s}\"", .{validated_name}).throw(); diff --git a/src/bun.js/api/bun/subprocess.zig b/src/bun.js/api/bun/subprocess.zig index fcb4307457..0e25964198 100644 --- a/src/bun.js/api/bun/subprocess.zig +++ b/src/bun.js/api/bun/subprocess.zig @@ -1827,7 +1827,7 @@ fn getArgv0(globalThis: *JSC.JSGlobalObject, PATH: []const u8, cwd: []const u8, } fn getArgv(globalThis: *JSC.JSGlobalObject, args: JSValue, PATH: []const u8, cwd: []const u8, argv0: *?[*:0]const u8, allocator: std.mem.Allocator, argv: *std.ArrayList(?[*:0]const u8)) bun.JSError!void { - var cmds_array = args.arrayIterator(globalThis); + var cmds_array = try args.arrayIterator(globalThis); // + 1 for argv0 // + 1 for null terminator argv.* = try @TypeOf(argv.*).initCapacity(allocator, cmds_array.len + 2); @@ -1840,12 +1840,12 @@ fn getArgv(globalThis: *JSC.JSGlobalObject, args: JSValue, PATH: []const u8, cwd return globalThis.throwInvalidArguments("cmd must not be empty", .{}); } - const argv0_result = try getArgv0(globalThis, PATH, cwd, argv0.*, cmds_array.next().?, allocator); + const argv0_result = try getArgv0(globalThis, PATH, cwd, argv0.*, (try cmds_array.next()).?, allocator); argv0.* = argv0_result.argv0.ptr; argv.appendAssumeCapacity(argv0_result.arg0.ptr); - while (cmds_array.next()) |value| { + while (try cmds_array.next()) |value| { const arg = try value.toBunString(globalThis); defer arg.deref(); @@ -2031,16 +2031,16 @@ pub fn spawnMaybeSync( if (try args.get(globalThis, "stdio")) |stdio_val| { if (!stdio_val.isEmptyOrUndefinedOrNull()) { if (stdio_val.jsType().isArray()) { - var stdio_iter = stdio_val.arrayIterator(globalThis); + var stdio_iter = try stdio_val.arrayIterator(globalThis); var i: u31 = 0; - while (stdio_iter.next()) |value| : (i += 1) { + while (try stdio_iter.next()) |value| : (i += 1) { try stdio[i].extract(globalThis, i, value); if (i == 2) break; } i += 1; - while (stdio_iter.next()) |value| : (i += 1) { + while (try stdio_iter.next()) |value| : (i += 1) { var new_item: Stdio = undefined; try new_item.extract(globalThis, i, value); diff --git a/src/bun.js/api/bun/udp_socket.zig b/src/bun.js/api/bun/udp_socket.zig index ca7f196f4f..d6ae1e3765 100644 --- a/src/bun.js/api/bun/udp_socket.zig +++ b/src/bun.js/api/bun/udp_socket.zig @@ -608,7 +608,7 @@ pub const UDPSocket = struct { return globalThis.throwInvalidArgumentType("sendMany", "first argument", "array"); } - const array_len = arg.getLength(globalThis); + const array_len = try arg.getLength(globalThis); if (this.connect_info == null and array_len % 3 != 0) { return globalThis.throwInvalidArguments("Expected 3 arguments for each packet", .{}); } @@ -624,11 +624,11 @@ pub const UDPSocket = struct { var addr_ptrs = alloc.alloc(?*const anyopaque, len) catch bun.outOfMemory(); var addrs = alloc.alloc(std.posix.sockaddr.storage, len) catch bun.outOfMemory(); - var iter = arg.arrayIterator(globalThis); + var iter = try arg.arrayIterator(globalThis); var i: u16 = 0; var port: JSValue = .zero; - while (iter.next()) |val| : (i += 1) { + while (try iter.next()) |val| : (i += 1) { if (i >= array_len) { return globalThis.throwInvalidArguments("Mismatch between array length property and number of items", .{}); } diff --git a/src/bun.js/api/ffi.zig b/src/bun.js/api/ffi.zig index ff6e0075ad..1297c2cdfe 100644 --- a/src/bun.js/api/ffi.zig +++ b/src/bun.js/api/ffi.zig @@ -538,10 +538,10 @@ pub const FFI = struct { } pub fn fromJSArray(globalThis: *JSC.JSGlobalObject, value: JSC.JSValue, comptime property: []const u8) bun.JSError!StringArray { - var iter = value.arrayIterator(globalThis); + var iter = try value.arrayIterator(globalThis); var items = std.ArrayList([:0]const u8).init(bun.default_allocator); - while (iter.next()) |val| { + while (try iter.next()) |val| { if (!val.isString()) { for (items.items) |item| { bun.default_allocator.free(@constCast(item)); @@ -595,7 +595,7 @@ pub const FFI = struct { } } - const symbols_object: JSValue = object.getOwn(globalThis, "symbols") orelse .js_undefined; + const symbols_object: JSValue = try object.getOwn(globalThis, "symbols") orelse .js_undefined; if (!globalThis.hasException() and (symbols_object == .zero or !symbols_object.isObject())) { return globalThis.throwInvalidArgumentTypeValue("symbols", "object", symbols_object); } @@ -615,7 +615,7 @@ pub const FFI = struct { return globalThis.throw("Expected at least one exported symbol", .{}); } - if (object.getOwn(globalThis, "library")) |library_value| { + if (try object.getOwn(globalThis, "library")) |library_value| { compile_c.libraries = try StringArray.fromJS(globalThis, library_value, "library"); } @@ -625,13 +625,13 @@ pub const FFI = struct { if (try object.getTruthy(globalThis, "flags")) |flags_value| { if (flags_value.isArray()) { - var iter = flags_value.arrayIterator(globalThis); + var iter = try flags_value.arrayIterator(globalThis); var flags = std.ArrayList(u8).init(allocator); defer flags.deinit(); flags.appendSlice(CompileC.default_tcc_options) catch bun.outOfMemory(); - while (iter.next()) |value| { + while (try iter.next()) |value| { if (!value.isString()) { return globalThis.throwInvalidArgumentTypeValue("flags", "array of strings", value); } @@ -698,11 +698,11 @@ pub const FFI = struct { return error.JSError; } - if (object.getOwn(globalThis, "source")) |source_value| { + if (try object.getOwn(globalThis, "source")) |source_value| { if (source_value.isArray()) { compile_c.source = .{ .files = .{} }; - var iter = source_value.arrayIterator(globalThis); - while (iter.next()) |value| { + var iter = try source_value.arrayIterator(globalThis); + while (try iter.next()) |value| { if (!value.isString()) { return globalThis.throwInvalidArgumentTypeValue("source", "array of strings", value); } @@ -1249,15 +1249,15 @@ pub const FFI = struct { var abi_types = std.ArrayListUnmanaged(ABIType){}; - if (value.getOwn(global, "args")) |args| { + if (try value.getOwn(global, "args")) |args| { if (args.isEmptyOrUndefinedOrNull() or !args.jsType().isArray()) { return ZigString.static("Expected an object with \"args\" as an array").toErrorInstance(global); } - var array = args.arrayIterator(global); + var array = try args.arrayIterator(global); try abi_types.ensureTotalCapacityPrecise(allocator, array.len); - while (array.next()) |val| { + while (try array.next()) |val| { if (val.isEmptyOrUndefinedOrNull()) { abi_types.clearAndFree(allocator); return ZigString.static("param must be a string (type name) or number").toErrorInstance(global); diff --git a/src/bun.js/api/filesystem_router.zig b/src/bun.js/api/filesystem_router.zig index a0e4894a62..05521e5283 100644 --- a/src/bun.js/api/filesystem_router.zig +++ b/src/bun.js/api/filesystem_router.zig @@ -99,16 +99,16 @@ pub const FileSystemRouter = struct { return globalThis.throwInvalidArguments("Expected fileExtensions to be an Array", .{}); } - var iter = file_extensions.arrayIterator(globalThis); + var iter = try file_extensions.arrayIterator(globalThis); extensions.ensureTotalCapacityPrecise(iter.len) catch unreachable; - while (iter.next()) |val| { + while (try iter.next()) |val| { if (!val.isString()) { origin_str.deinit(); arena.deinit(); globalThis.allocator().destroy(arena); return globalThis.throwInvalidArguments("Expected fileExtensions to be an Array of strings", .{}); } - if (val.getLength(globalThis) == 0) continue; + if (try val.getLength(globalThis) == 0) continue; extensions.appendAssumeCapacity(((try val.toSlice(globalThis, allocator)).clone(allocator) catch unreachable).slice()[1..]); } } diff --git a/src/bun.js/api/html_rewriter.zig b/src/bun.js/api/html_rewriter.zig index c5ef322882..67fd3d3b8c 100644 --- a/src/bun.js/api/html_rewriter.zig +++ b/src/bun.js/api/html_rewriter.zig @@ -923,7 +923,7 @@ fn HandlerCallback( this.global.bunVM().waitForPromise(promise); const fail = promise.status(this.global.vm()) == .rejected; if (fail) { - _ = this.global.bunVM().unhandledRejection(this.global, promise.result(this.global.vm()), promise.asValue()); + this.global.bunVM().unhandledRejection(this.global, promise.result(this.global.vm()), promise.asValue()); } return fail; } diff --git a/src/bun.js/api/server/SSLConfig.zig b/src/bun.js/api/server/SSLConfig.zig index 5ed7eecbdf..bbe7cd5b29 100644 --- a/src/bun.js/api/server/SSLConfig.zig +++ b/src/bun.js/api/server/SSLConfig.zig @@ -252,13 +252,13 @@ pub fn fromJS(vm: *JSC.VirtualMachine, global: *JSC.JSGlobalObject, obj: JSC.JSV if (try obj.getTruthy(global, "key")) |js_obj| { if (js_obj.jsType().isArray()) { - const count = js_obj.getLength(global); + const count = try js_obj.getLength(global); if (count > 0) { const native_array = try bun.default_allocator.alloc([*c]const u8, count); var valid_count: u32 = 0; for (0..count) |i| { - const item = js_obj.getIndex(global, @intCast(i)); + const item = try js_obj.getIndex(global, @intCast(i)); if (try JSC.Node.StringOrBuffer.fromJS(global, arena.allocator(), item)) |sb| { defer sb.deinit(); const sliced = sb.slice(); @@ -360,13 +360,13 @@ pub fn fromJS(vm: *JSC.VirtualMachine, global: *JSC.JSGlobalObject, obj: JSC.JSV if (try obj.getTruthy(global, "cert")) |js_obj| { if (js_obj.jsType().isArray()) { - const count = js_obj.getLength(global); + const count = try js_obj.getLength(global); if (count > 0) { const native_array = try bun.default_allocator.alloc([*c]const u8, count); var valid_count: u32 = 0; for (0..count) |i| { - const item = js_obj.getIndex(global, @intCast(i)); + const item = try js_obj.getIndex(global, @intCast(i)); if (try JSC.Node.StringOrBuffer.fromJS(global, arena.allocator(), item)) |sb| { defer sb.deinit(); const sliced = sb.slice(); @@ -469,13 +469,13 @@ pub fn fromJS(vm: *JSC.VirtualMachine, global: *JSC.JSGlobalObject, obj: JSC.JSV if (try obj.getTruthy(global, "ca")) |js_obj| { if (js_obj.jsType().isArray()) { - const count = js_obj.getLength(global); + const count = try js_obj.getLength(global); if (count > 0) { const native_array = try bun.default_allocator.alloc([*c]const u8, count); var valid_count: u32 = 0; for (0..count) |i| { - const item = js_obj.getIndex(global, @intCast(i)); + const item = try js_obj.getIndex(global, @intCast(i)); if (try JSC.Node.StringOrBuffer.fromJS(global, arena.allocator(), item)) |sb| { defer sb.deinit(); const sliced = sb.slice(); diff --git a/src/bun.js/api/server/ServerConfig.zig b/src/bun.js/api/server/ServerConfig.zig index 88a3effc7b..964b08b3c9 100644 --- a/src/bun.js/api/server/ServerConfig.zig +++ b/src/bun.js/api/server/ServerConfig.zig @@ -579,7 +579,7 @@ pub fn fromJS( }; var found = false; inline for (methods) |method| { - if (value.getOwn(global, @tagName(method))) |function| { + if (try value.getOwn(global, @tagName(method))) |function| { if (!found) { try validateRouteName(global, path); } @@ -911,11 +911,11 @@ pub fn fromJS( if (tls.isFalsey()) { args.ssl_config = null; } else if (tls.jsType().isArray()) { - var value_iter = tls.arrayIterator(global); + var value_iter = try tls.arrayIterator(global); if (value_iter.len == 1) { return global.throwInvalidArguments("tls option expects at least 1 tls object", .{}); } - while (value_iter.next()) |item| { + while (try value_iter.next()) |item| { var ssl_config = try SSLConfig.fromJS(vm, global, item) orelse { if (global.hasException()) { return error.JSError; diff --git a/src/bun.js/bindings/AnyPromise.zig b/src/bun.js/bindings/AnyPromise.zig index 4dcce82733..9d12999dee 100644 --- a/src/bun.js/bindings/AnyPromise.zig +++ b/src/bun.js/bindings/AnyPromise.zig @@ -76,11 +76,15 @@ pub const AnyPromise = union(enum) { args: Args, pub fn call(wrap_: *@This(), global: *JSC.JSGlobalObject) callconv(.c) JSC.JSValue { - return JSC.toJSHostValue(global, @call(.auto, Fn, wrap_.args)); + return JSC.toJSHostCall(global, @src(), Fn, wrap_.args); } }; + var scope: JSC.CatchScope = undefined; + scope.init(globalObject, @src(), .enabled); + defer scope.deinit(); var ctx = Wrapper{ .args = args }; JSC__AnyPromise__wrap(globalObject, this.asValue(), &ctx, @ptrCast(&Wrapper.call)); + bun.debugAssert(!scope.hasException()); // TODO: properly propagate exception upwards } }; diff --git a/src/bun.js/bindings/BunObject.cpp b/src/bun.js/bindings/BunObject.cpp index 8f24d751b3..82a4e54728 100644 --- a/src/bun.js/bindings/BunObject.cpp +++ b/src/bun.js/bindings/BunObject.cpp @@ -359,6 +359,7 @@ static JSValue constructBunShell(VM& vm, JSObject* bunObject) auto* bunShell = shell.getObject(); auto ShellError = bunShell->get(globalObject, JSC::Identifier::fromString(vm, "ShellError"_s)); + RETURN_IF_EXCEPTION(scope, {}); if (!ShellError.isObject()) [[unlikely]] { throwTypeError(globalObject, scope, "Internal error: BunShell.ShellError is not an object"_s); return {}; diff --git a/src/bun.js/bindings/BunProcess.cpp b/src/bun.js/bindings/BunProcess.cpp index 01e538bb30..5e313628ff 100644 --- a/src/bun.js/bindings/BunProcess.cpp +++ b/src/bun.js/bindings/BunProcess.cpp @@ -2062,7 +2062,6 @@ static JSValue constructReportObjectComplete(VM& vm, Zig::GlobalObject* globalOb JSC_DEFINE_HOST_FUNCTION(Process_functionGetReport, (JSGlobalObject * globalObject, JSC::CallFrame* callFrame)) { auto& vm = JSC::getVM(globalObject); - auto scope = DECLARE_THROW_SCOPE(vm); // TODO: node:vm return JSValue::encode(constructReportObjectComplete(vm, jsCast(globalObject), String())); } diff --git a/src/bun.js/bindings/CatchScope.zig b/src/bun.js/bindings/CatchScope.zig new file mode 100644 index 0000000000..bcd98f5480 --- /dev/null +++ b/src/bun.js/bindings/CatchScope.zig @@ -0,0 +1,173 @@ +//! Binding for JSC::CatchScope. This should be used rarely, only at translation boundaries between +//! JSC's exception checking and Zig's. Make sure not to move it after creation. For instance: +//! +//! ```zig +//! // Declare a CatchScope surrounding the call that may throw an exception +//! var scope: CatchScope = undefined; +//! scope.init(global, @src(), .assertions_only); +//! defer scope.deinit(); +//! +//! const value = external_call(vm, foo, bar, baz); +//! // Calling hasException() suffices to prove that we checked for an exception. +//! // This function's caller does not need to use a CatchScope or ThrowScope +//! // because it can use Zig error unions. +//! if (Environment.allow_assert) assert((value == .zero) == scope.hasException()); +//! return if (value == .zero) error.JSError else value; +//! ``` + +const CatchScope = @This(); + +/// TODO determine size and alignment automatically +const size = 56; +const alignment = 8; + +bytes: [size]u8 align(alignment), +global: *jsc.JSGlobalObject, +/// Pointer to `bytes`, set by `init()`, used to assert that the location did not change +location: if (Environment.allow_assert) *u8 else void, +enabled: bool, + +pub const Enable = enum { + /// You are using the CatchScope to check for exceptions. + enabled, + /// You have another way to detect exceptions and are only using the CatchScope to prove that + /// exceptions are checked. + /// + /// This CatchScope will only do anything when assertions are enabled. Otherwise, init and + /// deinit do nothing and it always reports there is no exception. + assertions_only, +}; + +pub fn init( + self: *CatchScope, + global: *jsc.JSGlobalObject, + src: std.builtin.SourceLocation, + /// If not enabled, the scope does nothing (it never has an exception). + /// If you need to do something different when there is an exception, leave enabled. + /// If you are only using the scope to prove you handle exceptions correctly, you can pass + /// `Environment.allow_assert` as `enabled`. + enable_condition: Enable, +) void { + const enabled = switch (enable_condition) { + .enabled => true, + .assertions_only => Environment.allow_assert, + }; + if (enabled) { + CatchScope__construct( + &self.bytes, + global, + src.fn_name, + src.file, + src.line, + @sizeOf(@TypeOf(self.bytes)), + @typeInfo(CatchScope).@"struct".fields[0].alignment, + ); + } + self.* = .{ + .bytes = self.bytes, + .global = global, + .location = if (Environment.allow_assert) &self.bytes[0], + .enabled = enabled, + }; +} + +/// Generate a useful message including where the exception was thrown. +/// Only intended to be called when there is a pending exception. +fn assertionFailure(self: *CatchScope, proof: *jsc.Exception) noreturn { + _ = proof; + if (Environment.allow_assert) bun.assert(self.location == &self.bytes[0]); + CatchScope__assertNoException(&self.bytes); + @panic("assertionFailure called without a pending exception"); +} + +pub fn hasException(self: *CatchScope) bool { + return self.exception() != null; +} + +/// Get the thrown exception if it exists (like scope.exception() in C++) +pub fn exception(self: *CatchScope) ?*jsc.Exception { + if (Environment.allow_assert) bun.assert(self.location == &self.bytes[0]); + if (!self.enabled) return null; + return CatchScope__pureException(&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 (Environment.allow_assert) bun.assert(self.location == &self.bytes[0]); + if (!self.enabled) return null; + return CatchScope__exceptionIncludingTraps(&self.bytes); +} + +/// Intended for use with `try`. Returns if there is already a pending exception or if traps cause +/// an exception to be thrown (this is the same as how RETURN_IF_EXCEPTION behaves in C++) +pub fn returnIfException(self: *CatchScope) bun.JSError!void { + if (self.exceptionIncludingTraps() != null) return error.JSError; +} + +/// Asserts there has not been any exception thrown. +pub fn assertNoException(self: *CatchScope) void { + if (Environment.allow_assert) { + if (self.exception()) |e| self.assertionFailure(e); + } +} + +/// Asserts that there is or is not an exception according to the value of `should_have_exception`. +/// Prefer over `assert(scope.hasException() == ...)` because if there is an unexpected exception, +/// this function prints a trace of where it was thrown. +pub fn assertExceptionPresenceMatches(self: *CatchScope, should_have_exception: bool) void { + if (Environment.allow_assert) { + // paranoid; will only fail if you manually changed enabled to false + bun.assert(self.enabled); + if (should_have_exception) { + bun.assertf(self.hasException(), "Expected an exception to be thrown", .{}); + } else { + self.assertNoException(); + } + } +} + +/// If no exception, returns. +/// If termination exception, returns JSExecutionTerminated (so you can `try`) +/// If non-termination exception, assertion failure. +pub fn assertNoExceptionExceptTermination(self: *CatchScope) bun.JSExecutionTerminated!void { + bun.assert(self.enabled); + return if (self.exception()) |e| + if (jsc.JSValue.fromCell(e).isTerminationException(self.global.vm())) + error.JSExecutionTerminated + else if (Environment.allow_assert) + self.assertionFailure(e) + else + // we got an exception other than the termination one, but we can't assert. + // treat this like the termination exception so we still bail out + error.JSExecutionTerminated + else {}; +} + +pub fn deinit(self: *CatchScope) void { + if (Environment.allow_assert) bun.assert(self.location == &self.bytes[0]); + if (!self.enabled) return; + CatchScope__destruct(&self.bytes); + self.bytes = undefined; +} + +extern fn CatchScope__construct( + ptr: *align(alignment) [size]u8, + global: *jsc.JSGlobalObject, + function: [*:0]const u8, + file: [*:0]const u8, + line: c_uint, + size: usize, + alignment: usize, +) void; +/// only returns exceptions that have already been thrown. does not check traps +extern fn CatchScope__pureException(ptr: *align(alignment) [size]u8) ?*jsc.Exception; +/// 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; +extern fn CatchScope__assertNoException(ptr: *align(alignment) [size]u8) void; +extern fn CatchScope__destruct(ptr: *align(alignment) [size]u8) void; + +const std = @import("std"); +const bun = @import("bun"); +const jsc = bun.jsc; +const Environment = bun.Environment; diff --git a/src/bun.js/bindings/CatchScopeBinding.cpp b/src/bun.js/bindings/CatchScopeBinding.cpp new file mode 100644 index 0000000000..3efe668735 --- /dev/null +++ b/src/bun.js/bindings/CatchScopeBinding.cpp @@ -0,0 +1,57 @@ +#include + +using JSC::CatchScope; + +extern "C" void CatchScope__construct( + void* ptr, + JSC::JSGlobalObject* globalObject, + const char* function, + const char* file, + unsigned line, + size_t size, + size_t alignment) +{ + // validate that Zig is correct about what the size and alignment should be + ASSERT(size >= sizeof(CatchScope)); + ASSERT(alignment >= alignof(CatchScope)); + ASSERT((uintptr_t)ptr % alignment == 0); + +#if ENABLE(EXCEPTION_SCOPE_VERIFICATION) + new (ptr) JSC::CatchScope(JSC::getVM(globalObject), + JSC::ExceptionEventLocation { currentStackPointer(), function, file, line }); +#else + (void)function; + (void)file; + (void)line; + new (ptr) JSC::CatchScope(JSC::getVM(globalObject)); +#endif +} + +extern "C" JSC::Exception* CatchScope__pureException(void* ptr) +{ + ASSERT((uintptr_t)ptr % alignof(CatchScope) == 0); + return static_cast(ptr)->exception(); +} + +extern "C" JSC::Exception* CatchScope__exceptionIncludingTraps(void* ptr) +{ + ASSERT((uintptr_t)ptr % alignof(CatchScope) == 0); + auto* scope = static_cast(ptr); + // this is different than `return scope->exception()` because `RETURN_IF_EXCEPTION` also checks + // if there are traps that should throw an exception (like a termination request from another + // thread) + RETURN_IF_EXCEPTION(*scope, scope->exception()); + return nullptr; +} + +extern "C" void CatchScope__destruct(void* ptr) +{ + ASSERT((uintptr_t)ptr % alignof(CatchScope) == 0); + static_cast(ptr)->~CatchScope(); +} + +extern "C" void CatchScope__assertNoException(void* ptr) +{ + ASSERT((uintptr_t)ptr % alignof(CatchScope) == 0); + static_cast(ptr)->assertNoException(); +} diff --git a/src/bun.js/bindings/ErrorCode.cpp b/src/bun.js/bindings/ErrorCode.cpp index 168a98f3e1..78d62a50bf 100644 --- a/src/bun.js/bindings/ErrorCode.cpp +++ b/src/bun.js/bindings/ErrorCode.cpp @@ -189,6 +189,7 @@ static Structure* createErrorStructure(JSC::VM& vm, JSGlobalObject* globalObject JSObject* ErrorCodeCache::createError(VM& vm, Zig::GlobalObject* globalObject, ErrorCode code, JSValue message, JSValue options) { + auto scope = DECLARE_CATCH_SCOPE(vm); auto* cache = errorCache(globalObject); const auto& data = errors[static_cast(code)]; if (!cache->internalField(static_cast(code))) { @@ -197,7 +198,15 @@ JSObject* ErrorCodeCache::createError(VM& vm, Zig::GlobalObject* globalObject, E } auto* structure = jsCast(cache->internalField(static_cast(code)).get()); - return JSC::ErrorInstance::create(globalObject, structure, message, options, nullptr, JSC::RuntimeType::TypeNothing, data.type, true); + auto* created_error = JSC::ErrorInstance::create(globalObject, structure, message, options, nullptr, JSC::RuntimeType::TypeNothing, data.type, true); + if (auto* thrown_exception = scope.exception()) [[unlikely]] { + scope.clearException(); + // TODO investigate what can throw here and whether it will throw non-objects + // (this is better than before where we would have returned nullptr from createError if any + // exception were thrown by ErrorInstance::create) + return jsCast(thrown_exception->value()); + } + return created_error; } JSObject* createError(VM& vm, Zig::GlobalObject* globalObject, ErrorCode code, const String& message) diff --git a/src/bun.js/bindings/Errorable.zig b/src/bun.js/bindings/Errorable.zig index 2e27290c40..6bcbe25d48 100644 --- a/src/bun.js/bindings/Errorable.zig +++ b/src/bun.js/bindings/Errorable.zig @@ -1,3 +1,4 @@ +const bun = @import("bun"); const ZigErrorType = @import("ZigErrorType.zig").ZigErrorType; const ErrorCode = @import("ErrorCode.zig").ErrorCode; @@ -27,12 +28,12 @@ pub fn Errorable(comptime Type: type) type { return @This(){ .result = .{ .value = val }, .success = true }; } - pub fn err(code: anyerror, ptr: *anyopaque) @This() { + pub fn err(code: anyerror, err_value: bun.jsc.JSValue) @This() { return @This(){ .result = .{ .err = .{ .code = ErrorCode.from(code), - .ptr = ptr, + .value = err_value, }, }, .success = false, diff --git a/src/bun.js/bindings/ImportMetaObject.cpp b/src/bun.js/bindings/ImportMetaObject.cpp index 814126bd1e..f670fc76f1 100644 --- a/src/bun.js/bindings/ImportMetaObject.cpp +++ b/src/bun.js/bindings/ImportMetaObject.cpp @@ -541,7 +541,8 @@ JSC_DEFINE_CUSTOM_GETTER(jsImportMetaObjectGetter_require, (JSGlobalObject * glo if (!thisObject) [[unlikely]] return JSValue::encode(jsUndefined()); - return JSValue::encode(thisObject->requireProperty.getInitializedOnMainThread(thisObject)); + auto* nullable = thisObject->requireProperty.getInitializedOnMainThread(thisObject); + return JSValue::encode(nullable ? nullable : jsUndefined()); } // https://github.com/oven-sh/bun/issues/11754#issuecomment-2452626172 @@ -651,6 +652,7 @@ void ImportMetaObject::finishCreation(VM& vm) ASSERT(inherits(info())); this->requireProperty.initLater([](const JSC::LazyProperty::Initializer& init) { + auto scope = DECLARE_THROW_SCOPE(init.vm); ImportMetaObject* meta = jsCast(init.owner); WTF::URL url = isAbsolutePath(meta->url) ? WTF::URL::fileURLWithFileSystemPath(meta->url) : WTF::URL(meta->url); @@ -666,8 +668,10 @@ void ImportMetaObject::finishCreation(VM& vm) path = meta->url; } - JSFunction* value = jsCast(Bun::JSCommonJSModule::createBoundRequireFunction(init.vm, meta->globalObject(), path)); - init.set(value); + auto* object = Bun::JSCommonJSModule::createBoundRequireFunction(init.vm, meta->globalObject(), path); + RETURN_IF_EXCEPTION(scope, ); + ASSERT(object); + init.set(jsCast(object)); }); this->urlProperty.initLater([](const JSC::LazyProperty::Initializer& init) { ImportMetaObject* meta = jsCast(init.owner); diff --git a/src/bun.js/bindings/JSArray.zig b/src/bun.js/bindings/JSArray.zig index 1f5d23c385..62662ae309 100644 --- a/src/bun.js/bindings/JSArray.zig +++ b/src/bun.js/bindings/JSArray.zig @@ -9,16 +9,16 @@ pub const JSArray = opaque { extern fn JSArray__constructArray(*JSGlobalObject, [*]const JSValue, usize) JSValue; pub fn create(global: *JSGlobalObject, items: []const JSValue) bun.JSError!JSValue { - return bun.jsc.fromJSHostValue(JSArray__constructArray(global, items.ptr, items.len)); + return bun.jsc.fromJSHostCall(global, @src(), JSArray__constructArray, .{ global, items.ptr, items.len }); } extern fn JSArray__constructEmptyArray(*JSGlobalObject, usize) JSValue; pub fn createEmpty(global: *JSGlobalObject, len: usize) bun.JSError!JSValue { - return bun.jsc.fromJSHostValue(JSArray__constructEmptyArray(global, len)); + return bun.jsc.fromJSHostCall(global, @src(), JSArray__constructEmptyArray, .{ global, len }); } - pub fn iterator(array: *JSArray, global: *JSGlobalObject) JSArrayIterator { + pub fn iterator(array: *JSArray, global: *JSGlobalObject) bun.JSError!JSArrayIterator { return JSValue.fromCell(array).arrayIterator(global); } }; diff --git a/src/bun.js/bindings/JSArrayIterator.zig b/src/bun.js/bindings/JSArrayIterator.zig index 315171fe63..6ff2beb691 100644 --- a/src/bun.js/bindings/JSArrayIterator.zig +++ b/src/bun.js/bindings/JSArrayIterator.zig @@ -10,21 +10,20 @@ pub const JSArrayIterator = struct { array: JSValue, global: *JSGlobalObject, - pub fn init(value: JSValue, global: *JSGlobalObject) JSArrayIterator { + pub fn init(value: JSValue, global: *JSGlobalObject) bun.JSError!JSArrayIterator { return .{ .array = value, .global = global, - .len = @as(u32, @truncate(value.getLength(global))), + .len = @truncate(try value.getLength(global)), }; } - // TODO: this can throw - pub fn next(this: *JSArrayIterator) ?JSValue { + pub fn next(this: *JSArrayIterator) bun.JSError!?JSValue { if (!(this.i < this.len)) { return null; } const i = this.i; this.i += 1; - return JSObject.getIndex(this.array, this.global, i); + return try JSObject.getIndex(this.array, this.global, i); } }; diff --git a/src/bun.js/bindings/JSBuffer.cpp b/src/bun.js/bindings/JSBuffer.cpp index e32794b288..5971a32a20 100644 --- a/src/bun.js/bindings/JSBuffer.cpp +++ b/src/bun.js/bindings/JSBuffer.cpp @@ -219,21 +219,15 @@ std::optional byteLength(JSC::JSString* str, JSC::JSGlobalObject* lexica static JSUint8Array* allocBuffer(JSC::JSGlobalObject* lexicalGlobalObject, size_t byteLength) { -#if ASSERT_ENABLED auto& vm = JSC::getVM(lexicalGlobalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); -#endif auto* globalObject = defaultGlobalObject(lexicalGlobalObject); auto* subclassStructure = globalObject->JSBufferSubclassStructure(); auto* uint8Array = JSC::JSUint8Array::create(lexicalGlobalObject, subclassStructure, byteLength); -#if ASSERT_ENABLED - if (!uint8Array) [[unlikely]] { - // it should have thrown an exception already - ASSERT(throwScope.exception()); - } -#endif + // it should have thrown an exception already + ASSERT(!!throwScope.exception() == !uint8Array); return uint8Array; } @@ -241,19 +235,13 @@ static JSUint8Array* allocBuffer(JSC::JSGlobalObject* lexicalGlobalObject, size_ static JSUint8Array* allocBufferUnsafe(JSC::JSGlobalObject* lexicalGlobalObject, size_t byteLength) { -#if ASSERT_ENABLED auto& vm = JSC::getVM(lexicalGlobalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); -#endif auto* result = createUninitializedBuffer(lexicalGlobalObject, byteLength); -#if ASSERT_ENABLED - if (!result) [[unlikely]] { - // it should have thrown an exception already - ASSERT(throwScope.exception()); - } -#endif + // it should have thrown an exception already + ASSERT(!!throwScope.exception() == !result); return result; } @@ -566,6 +554,7 @@ JSC::EncodedJSValue constructFromEncoding(JSGlobalObject* lexicalGlobalObject, W } } } + RETURN_IF_EXCEPTION(scope, {}); JSC::JSValue decoded = JSC::JSValue::decode(result); if (!result) [[unlikely]] { @@ -606,7 +595,7 @@ static JSC::EncodedJSValue constructBufferFromStringAndEncoding(JSC::JSGlobalObj } if (str->length() == 0) - return constructBufferEmpty(lexicalGlobalObject); + RELEASE_AND_RETURN(scope, constructBufferEmpty(lexicalGlobalObject)); JSC::EncodedJSValue result = constructFromEncoding(lexicalGlobalObject, view, encoding); @@ -626,7 +615,7 @@ static JSC::EncodedJSValue jsBufferConstructorFunction_allocBody(JSC::JSGlobalOb RETURN_IF_EXCEPTION(scope, {}); if (length == 0) { - return JSValue::encode(createEmptyBuffer(lexicalGlobalObject)); + RELEASE_AND_RETURN(scope, JSValue::encode(createEmptyBuffer(lexicalGlobalObject))); } // fill argument if (callFrame->argumentCount() > 1) [[unlikely]] { diff --git a/src/bun.js/bindings/JSCommonJSModule.cpp b/src/bun.js/bindings/JSCommonJSModule.cpp index 4739efe53c..4c4a0468ae 100644 --- a/src/bun.js/bindings/JSCommonJSModule.cpp +++ b/src/bun.js/bindings/JSCommonJSModule.cpp @@ -148,7 +148,9 @@ static bool evaluateCommonJSModuleOnce(JSC::VM& vm, Zig::GlobalObject* globalObj // Using same approach as node, `arguments` in the entry point isn't defined // https://github.com/nodejs/node/blob/592c6907bfe1922f36240e9df076be1864c3d1bd/lib/internal/process/execution.js#L92 - globalObject->putDirect(vm, builtinNames(vm).exportsPublicName(), moduleObject->exportsObject(), 0); + auto exports = moduleObject->exportsObject(); + RETURN_IF_EXCEPTION(scope, {}); + globalObject->putDirect(vm, builtinNames(vm).exportsPublicName(), exports, 0); globalObject->putDirect(vm, builtinNames(vm).requirePublicName(), requireFunction, 0); globalObject->putDirect(vm, Identifier::fromString(vm, "module"_s), moduleObject, 0); globalObject->putDirect(vm, Identifier::fromString(vm, "__filename"_s), filename, 0); @@ -183,7 +185,9 @@ static bool evaluateCommonJSModuleOnce(JSC::VM& vm, Zig::GlobalObject* globalObj RETURN_IF_EXCEPTION(scope, false); MarkedArgumentBuffer args; - args.append(moduleObject->exportsObject()); // exports + auto exports = moduleObject->exportsObject(); + RETURN_IF_EXCEPTION(scope, false); + args.append(exports); // exports args.append(requireFunction); // require args.append(moduleObject); // module args.append(filename); // filename @@ -1126,7 +1130,9 @@ void JSCommonJSModule::toSyntheticSource(JSC::JSGlobalObject* globalObject, Vector& exportNames, JSC::MarkedArgumentBuffer& exportValues) { + auto scope = DECLARE_THROW_SCOPE(JSC::getVM(globalObject)); auto result = this->exportsObject(); + RETURN_IF_EXCEPTION(scope, ); populateESMExports(globalObject, result, exportNames, exportValues, this->ignoreESModuleAnnotation); } @@ -1305,7 +1311,9 @@ JSC_DEFINE_HOST_FUNCTION(jsFunctionRequireNativeModule, (JSGlobalObject * lexica res.success = false; memset(&res.result, 0, sizeof res.result); BunString specifierStr = Bun::toString(specifier); - if (auto result = fetchBuiltinModuleWithoutResolution(globalObject, &specifierStr, &res)) { + auto result = fetchBuiltinModuleWithoutResolution(globalObject, &specifierStr, &res); + RETURN_IF_EXCEPTION(throwScope, {}); + if (result) { if (res.success) return JSC::JSValue::encode(result); } @@ -1411,10 +1419,13 @@ std::optional createCommonJSModule( ResolvedSource& source, bool isBuiltIn) { + auto& vm = JSC::getVM(globalObject); + auto scope = DECLARE_THROW_SCOPE(vm); JSCommonJSModule* moduleObject = nullptr; WTF::String sourceURL = source.source_url.toWTFString(); JSValue entry = globalObject->requireMap()->get(globalObject, requireMapKey); + RETURN_IF_EXCEPTION(scope, {}); bool ignoreESModuleAnnotation = source.tag == ResolvedSourceTagPackageJSONTypeModule; SourceOrigin sourceOrigin; @@ -1423,12 +1434,12 @@ std::optional createCommonJSModule( } if (!moduleObject) { - VM& vm = JSC::getVM(globalObject); size_t index = sourceURL.reverseFind(PLATFORM_SEP, sourceURL.length()); JSString* dirname; JSString* filename = requireMapKey; if (index != WTF::notFound) { dirname = JSC::jsSubstring(globalObject, requireMapKey, 0, index); + RETURN_IF_EXCEPTION(scope, {}); } else { dirname = jsEmptyString(vm); } @@ -1458,6 +1469,7 @@ std::optional createCommonJSModule( JSC::constructEmptyObject(globalObject, globalObject->objectPrototype()), 0); requireMap->set(globalObject, filename, moduleObject); + RETURN_IF_EXCEPTION(scope, {}); } else { sourceOrigin = Zig::toSourceOrigin(sourceURL, isBuiltIn); } @@ -1472,14 +1484,15 @@ std::optional createCommonJSModule( JSC::MarkedArgumentBuffer& exportValues) -> void { auto* globalObject = jsCast(lexicalGlobalObject); auto& vm = JSC::getVM(globalObject); + auto scope = DECLARE_THROW_SCOPE(vm); JSValue keyValue = identifierToJSValue(vm, moduleKey); JSValue entry = globalObject->requireMap()->get(globalObject, keyValue); + RETURN_IF_EXCEPTION(scope, {}); if (entry) { if (auto* moduleObject = jsDynamicCast(entry)) { if (!moduleObject->hasEvaluated) { - auto scope = DECLARE_THROW_SCOPE(vm); evaluateCommonJSModuleOnce( vm, globalObject, @@ -1492,6 +1505,7 @@ std::optional createCommonJSModule( // On error, remove the module from the require map // so that it can be re-evaluated on the next require. globalObject->requireMap()->remove(globalObject, moduleObject->filename()); + RETURN_IF_EXCEPTION(scope, {}); scope.throwException(globalObject, exception); return; @@ -1499,6 +1513,7 @@ std::optional createCommonJSModule( } moduleObject->toSyntheticSource(globalObject, moduleKey, exportNames, exportValues); + RETURN_IF_EXCEPTION(scope, {}); } } else { // require map was cleared of the entry @@ -1513,12 +1528,14 @@ JSObject* JSCommonJSModule::createBoundRequireFunction(VM& vm, JSGlobalObject* l ASSERT(!pathString.startsWith("file://"_s)); auto* globalObject = jsCast(lexicalGlobalObject); + auto scope = DECLARE_THROW_SCOPE(vm); JSString* filename = JSC::jsStringWithCache(vm, pathString); auto index = pathString.reverseFind(PLATFORM_SEP, pathString.length()); JSString* dirname; if (index != WTF::notFound) { dirname = JSC::jsSubstring(globalObject, filename, 0, index); + RETURN_IF_EXCEPTION(scope, nullptr); } else { dirname = jsEmptyString(vm); } @@ -1533,12 +1550,14 @@ JSObject* JSCommonJSModule::createBoundRequireFunction(VM& vm, JSGlobalObject* l globalObject->requireFunctionUnbound(), moduleObject, ArgList(), 1, globalObject->commonStrings().requireString(globalObject)); + RETURN_IF_EXCEPTION(scope, nullptr); JSFunction* resolveFunction = JSC::JSBoundFunction::create(vm, globalObject, globalObject->requireResolveFunctionUnbound(), moduleObject->filename(), ArgList(), 1, globalObject->commonStrings().resolveString(globalObject)); + RETURN_IF_EXCEPTION(scope, nullptr); requireFunction->putDirect(vm, vm.propertyNames->resolve, resolveFunction, 0); diff --git a/src/bun.js/bindings/JSDOMExceptionHandling.cpp b/src/bun.js/bindings/JSDOMExceptionHandling.cpp index f2c83e14e7..de78fc5d29 100644 --- a/src/bun.js/bindings/JSDOMExceptionHandling.cpp +++ b/src/bun.js/bindings/JSDOMExceptionHandling.cpp @@ -212,7 +212,9 @@ JSValue createDOMException(JSGlobalObject& lexicalGlobalObject, Exception&& exce void propagateExceptionSlowPath(JSC::JSGlobalObject& lexicalGlobalObject, JSC::ThrowScope& throwScope, Exception&& exception) { throwScope.assertNoExceptionExceptTermination(); - throwException(&lexicalGlobalObject, throwScope, createDOMException(lexicalGlobalObject, WTFMove(exception))); + auto jsException = createDOMException(lexicalGlobalObject, WTFMove(exception)); + RETURN_IF_EXCEPTION(throwScope, ); + throwException(&lexicalGlobalObject, throwScope, jsException); } static EncodedJSValue throwTypeError(JSC::JSGlobalObject& lexicalGlobalObject, JSC::ThrowScope& scope, const String& errorMessage) diff --git a/src/bun.js/bindings/JSEnvironmentVariableMap.cpp b/src/bun.js/bindings/JSEnvironmentVariableMap.cpp index 6f08fa2a2a..d3f1baafb9 100644 --- a/src/bun.js/bindings/JSEnvironmentVariableMap.cpp +++ b/src/bun.js/bindings/JSEnvironmentVariableMap.cpp @@ -78,7 +78,9 @@ JSC_DEFINE_CUSTOM_GETTER(jsTimeZoneEnvironmentVariableGetter, (JSGlobalObject * ZigString name = toZigString(propertyName.publicName()); ZigString value = { nullptr, 0 }; - if (auto hasExistingValue = thisObject->getIfPropertyExists(globalObject, clientData->builtinNames().dataPrivateName())) { + auto hasExistingValue = thisObject->getIfPropertyExists(globalObject, clientData->builtinNames().dataPrivateName()); + RETURN_IF_EXCEPTION(scope, {}); + if (hasExistingValue) { return JSValue::encode(hasExistingValue); } diff --git a/src/bun.js/bindings/JSGlobalObject.zig b/src/bun.js/bindings/JSGlobalObject.zig index 723b633af8..85637512e9 100644 --- a/src/bun.js/bindings/JSGlobalObject.zig +++ b/src/bun.js/bindings/JSGlobalObject.zig @@ -490,6 +490,7 @@ pub const JSGlobalObject = opaque { return JSC__JSGlobalObject__generateHeapSnapshot(this); } + // DEPRECATED - use CatchScope to check for exceptions and signal exceptions by returning JSError pub fn hasException(this: *JSGlobalObject) bool { return JSGlobalObject__hasException(this); } diff --git a/src/bun.js/bindings/JSModuleLoader.zig b/src/bun.js/bindings/JSModuleLoader.zig index bebeaacd9a..8692a6b449 100644 --- a/src/bun.js/bindings/JSModuleLoader.zig +++ b/src/bun.js/bindings/JSModuleLoader.zig @@ -46,8 +46,8 @@ pub const JSModuleLoader = opaque { return JSC__JSModuleLoader__loadAndEvaluateModule(globalObject, module_name); } - extern fn JSModuleLoader__import(*JSGlobalObject, *const bun.String) *JSInternalPromise; - pub fn import(globalObject: *JSGlobalObject, module_name: *const bun.String) *JSInternalPromise { - return JSModuleLoader__import(globalObject, module_name); + extern fn JSModuleLoader__import(*JSGlobalObject, *const bun.String) ?*JSInternalPromise; + pub fn import(globalObject: *JSGlobalObject, module_name: *const bun.String) bun.JSError!*JSInternalPromise { + return JSModuleLoader__import(globalObject, module_name) orelse error.JSError; } }; diff --git a/src/bun.js/bindings/JSObject.zig b/src/bun.js/bindings/JSObject.zig index 748b5322e4..188ae137ee 100644 --- a/src/bun.js/bindings/JSObject.zig +++ b/src/bun.js/bindings/JSObject.zig @@ -144,8 +144,18 @@ pub const JSObject = opaque { return JSC__JSObject__create(global, length, creator, Type.call); } - pub fn getIndex(this: JSValue, globalThis: *JSGlobalObject, i: u32) JSValue { - return JSC__JSObject__getIndex(this, globalThis, i); + pub fn getIndex(this: JSValue, globalThis: *JSGlobalObject, i: u32) JSError!JSValue { + // we don't use fromJSHostCall, because it will assert that if there is an exception + // then the JSValue is zero. the function this ends up calling can return undefined + // with an exception: + // https://github.com/oven-sh/WebKit/blob/397dafc9721b8f8046f9448abb6dbc14efe096d3/Source/JavaScriptCore/runtime/JSObjectInlines.h#L112 + var scope: JSC.CatchScope = undefined; + scope.init(globalThis, @src(), .enabled); + defer scope.deinit(); + const value = JSC__JSObject__getIndex(this, globalThis, i); + try scope.returnIfException(); + bun.assert(value != .zero); + return value; } pub fn putRecord(this: *JSObject, global: *JSGlobalObject, key: *ZigString, values: []ZigString) void { diff --git a/src/bun.js/bindings/JSPromise.zig b/src/bun.js/bindings/JSPromise.zig index 5cb0765641..631e29e6bc 100644 --- a/src/bun.js/bindings/JSPromise.zig +++ b/src/bun.js/bindings/JSPromise.zig @@ -189,12 +189,17 @@ pub const JSPromise = opaque { args: Args, pub fn call(this: *@This(), g: *JSC.JSGlobalObject) callconv(.c) JSC.JSValue { - return JSC.toJSHostValue(g, @call(.auto, Fn, this.args)); + return JSC.toJSHostCall(g, @src(), Fn, this.args); } }; + var scope: JSC.CatchScope = undefined; + scope.init(globalObject, @src(), .enabled); + defer scope.deinit(); var ctx = Wrapper{ .args = args }; - return JSC__JSPromise__wrap(globalObject, &ctx, @ptrCast(&Wrapper.call)); + const promise = JSC__JSPromise__wrap(globalObject, &ctx, @ptrCast(&Wrapper.call)); + bun.debugAssert(!scope.hasException()); // TODO: properly propagate exception upwards + return promise; } pub fn wrapValue(globalObject: *JSGlobalObject, value: JSValue) JSValue { @@ -257,6 +262,9 @@ pub const JSPromise = opaque { /// The value can be another Promise /// If you want to create a new Promise that is already resolved, see JSPromise.resolvedPromiseValue pub fn resolve(this: *JSPromise, globalThis: *JSGlobalObject, value: JSValue) void { + var scope: JSC.CatchScope = undefined; + scope.init(globalThis, @src(), .enabled); + defer scope.deinit(); if (comptime bun.Environment.isDebug) { const loop = JSC.VirtualMachine.get().eventLoop(); loop.debug.js_call_count_outside_tick_queue += @as(usize, @intFromBool(!loop.debug.is_inside_tick_queue)); @@ -266,6 +274,7 @@ pub const JSPromise = opaque { } JSC__JSPromise__resolve(this, globalThis, value); + bun.debugAssert(!scope.hasException()); // TODO: properly propagate exception upwards } pub fn reject(this: *JSPromise, globalThis: *JSGlobalObject, value: JSError!JSValue) void { diff --git a/src/bun.js/bindings/JSPropertyIterator.zig b/src/bun.js/bindings/JSPropertyIterator.zig index 226585e337..401d47d0df 100644 --- a/src/bun.js/bindings/JSPropertyIterator.zig +++ b/src/bun.js/bindings/JSPropertyIterator.zig @@ -121,10 +121,11 @@ const JSPropertyIteratorImpl = opaque { own_properties_only: bool, only_non_index_properties: bool, ) bun.JSError!?*JSPropertyIteratorImpl { + var scope: JSC.CatchScope = undefined; + scope.init(globalObject, @src(), .enabled); + defer scope.deinit(); const iter = Bun__JSPropertyIterator__create(globalObject, object.toJS(), count, own_properties_only, only_non_index_properties); - if (globalObject.hasException()) { - return error.JSError; - } + try scope.returnIfException(); return iter; } @@ -134,6 +135,7 @@ const JSPropertyIteratorImpl = opaque { pub const getName = Bun__JSPropertyIterator__getName; pub const getLongestPropertyName = Bun__JSPropertyIterator__getLongestPropertyName; + /// may return null without an exception extern "c" fn Bun__JSPropertyIterator__create(globalObject: *JSC.JSGlobalObject, encodedValue: JSC.JSValue, count: *usize, own_properties_only: bool, only_non_index_properties: bool) ?*JSPropertyIteratorImpl; extern "c" fn Bun__JSPropertyIterator__getNameAndValue(iter: *JSPropertyIteratorImpl, globalObject: *JSC.JSGlobalObject, object: *JSC.JSObject, propertyName: *bun.String, i: usize) JSC.JSValue; extern "c" fn Bun__JSPropertyIterator__getNameAndValueNonObservable(iter: *JSPropertyIteratorImpl, globalObject: *JSC.JSGlobalObject, object: *JSC.JSObject, propertyName: *bun.String, i: usize) JSC.JSValue; diff --git a/src/bun.js/bindings/JSValue.zig b/src/bun.js/bindings/JSValue.zig index 218f07800c..3a89ee7770 100644 --- a/src/bun.js/bindings/JSValue.zig +++ b/src/bun.js/bindings/JSValue.zig @@ -58,7 +58,7 @@ pub const JSValue = enum(i64) { return JSC__JSValue__coerceToInt64(this, globalThis); } - pub fn getIndex(this: JSValue, globalThis: *JSGlobalObject, i: u32) JSValue { + pub fn getIndex(this: JSValue, globalThis: *JSGlobalObject, i: u32) JSError!JSValue { return JSC.JSObject.getIndex(this, globalThis, i); } @@ -91,8 +91,12 @@ pub const JSValue = enum(i64) { globalThis: *JSC.JSGlobalObject, ctx: ?*anyopaque, callback: PropertyIteratorFn, - ) void { + ) JSError!void { + var scope: CatchScope = undefined; + scope.init(globalThis, @src(), .enabled); + defer scope.deinit(); JSC__JSValue__forEachPropertyNonIndexed(this, globalThis, ctx, callback); + try scope.returnIfException(); } pub fn forEachProperty( @@ -100,17 +104,25 @@ pub const JSValue = enum(i64) { globalThis: *JSC.JSGlobalObject, ctx: ?*anyopaque, callback: PropertyIteratorFn, - ) void { + ) JSError!void { + var scope: CatchScope = undefined; + scope.init(globalThis, @src(), .enabled); + defer scope.deinit(); JSC__JSValue__forEachProperty(this, globalThis, ctx, callback); + try scope.returnIfException(); } pub fn forEachPropertyOrdered( this: JSValue, - globalObject: *JSC.JSGlobalObject, + globalThis: *JSC.JSGlobalObject, ctx: ?*anyopaque, callback: PropertyIteratorFn, - ) void { - JSC__JSValue__forEachPropertyOrdered(this, globalObject, ctx, callback); + ) JSError!void { + var scope: CatchScope = undefined; + scope.init(globalThis, @src(), .enabled); + defer scope.deinit(); + JSC__JSValue__forEachPropertyOrdered(this, globalThis, ctx, callback); + try scope.returnIfException(); } extern fn JSC__JSValue__coerceToDouble(this: JSValue, globalObject: *JSC.JSGlobalObject) f64; @@ -255,13 +267,13 @@ pub const JSValue = enum(i64) { return this.call(globalThis, globalThis.toJSValue(), args); } - pub extern "c" fn Bun__JSValue__call( + extern "c" fn Bun__JSValue__call( ctx: *JSGlobalObject, object: JSValue, thisObject: JSValue, argumentCount: usize, arguments: [*]const JSValue, - ) JSValue.MaybeException; + ) JSValue; pub fn call(function: JSValue, global: *JSGlobalObject, thisValue: JSC.JSValue, args: []const JSC.JSValue) bun.JSError!JSC.JSValue { JSC.markBinding(@src()); @@ -277,13 +289,13 @@ pub const JSValue = enum(i64) { // this can be an async context so it's fine if it's not callable. } - return Bun__JSValue__call( + return fromJSHostCall(global, @src(), Bun__JSValue__call, .{ global, function, thisValue, args.len, args.ptr, - ).unwrap(); + }); } extern fn Bun__Process__queueNextTick1(*JSGlobalObject, func: JSValue, JSValue) void; @@ -337,7 +349,7 @@ pub const JSValue = enum(i64) { extern fn JSC__JSValue__createEmptyArray(global: *JSGlobalObject, len: usize) JSValue; pub fn createEmptyArray(global: *JSGlobalObject, len: usize) bun.JSError!JSValue { - return bun.jsc.fromJSHostValue(JSC__JSValue__createEmptyArray(global, len)); + return fromJSHostCall(global, @src(), JSC__JSValue__createEmptyArray, .{ global, len }); } extern fn JSC__JSValue__putRecord(value: JSValue, global: *JSGlobalObject, key: *ZigString, values_array: [*]ZigString, values_len: usize) void; @@ -758,24 +770,24 @@ pub const JSValue = enum(i64) { } extern fn JSC__JSValue__keys(globalThis: *JSGlobalObject, value: JSValue) JSValue; - pub fn keys(value: JSValue, globalThis: *JSGlobalObject) JSValue { - return JSC__JSValue__keys( + pub fn keys(value: JSValue, globalThis: *JSGlobalObject) JSError!JSValue { + return fromJSHostCall(globalThis, @src(), JSC__JSValue__keys, .{ globalThis, value, - ); + }); } extern fn JSC__JSValue__values(globalThis: *JSGlobalObject, value: JSValue) JSValue; /// This is `Object.values`. /// `value` is assumed to be not empty, undefined, or null. - pub fn values(value: JSValue, globalThis: *JSGlobalObject) JSValue { + pub fn values(value: JSValue, globalThis: *JSGlobalObject) JSError!JSValue { if (comptime bun.Environment.allow_assert) { bun.assert(!value.isEmptyOrUndefinedOrNull()); } - return JSC__JSValue__values( + return fromJSHostCall(globalThis, @src(), JSC__JSValue__values, .{ globalThis, value, - ); + }); } extern "c" fn JSC__JSValue__hasOwnPropertyValue(JSValue, *JSGlobalObject, JSValue) bool; @@ -783,9 +795,16 @@ pub const JSValue = enum(i64) { /// Returns true if the object has the property, false otherwise /// /// If the object is not an object, it will crash. **You must check if the object is an object before calling this function.** - pub const hasOwnPropertyValue = JSC__JSValue__hasOwnPropertyValue; + pub fn hasOwnPropertyValue(this: JSValue, global: *JSGlobalObject, key: JSValue) JSError!bool { + var scope: CatchScope = undefined; + scope.init(global, @src(), .enabled); + defer scope.deinit(); + const result = JSC__JSValue__hasOwnPropertyValue(this, global, key); + try scope.returnIfException(); + return result; + } - pub inline fn arrayIterator(this: JSValue, global: *JSGlobalObject) JSArrayIterator { + pub inline fn arrayIterator(this: JSValue, global: *JSGlobalObject) JSError!JSArrayIterator { return JSArrayIterator.init(this, global); } @@ -1044,7 +1063,7 @@ pub const JSValue = enum(i64) { pub inline fn isFunction(this: JSValue) bool { return this.isCell() and this.jsType().isFunction(); } - pub fn isObjectEmpty(this: JSValue, globalObject: *JSGlobalObject) bool { + pub fn isObjectEmpty(this: JSValue, globalObject: *JSGlobalObject) JSError!bool { const type_of_value = this.jsType(); // https://github.com/jestjs/jest/blob/main/packages/jest-get-type/src/index.ts#L26 // Map and Set are not considered as object in jest-extended @@ -1052,7 +1071,7 @@ pub const JSValue = enum(i64) { return false; } - return this.jsType().isObject() and keys(this, globalObject).getLength(globalObject) == 0; + return this.jsType().isObject() and try (try this.keys(globalObject)).getLength(globalObject) == 0; } extern fn JSC__JSValue__isClass(this: JSValue, global: *JSGlobalObject) bool; @@ -1118,6 +1137,14 @@ pub const JSValue = enum(i64) { return JSC__JSValue__isException(this, vm); } + /// Cast to an Exception pointer, or null if not an Exception + pub fn asException(this: JSValue, vm: *VM) ?*JSC.Exception { + return if (this.isException(vm)) + this.uncheckedPtrCast(JSC.Exception) + else + null; + } + extern fn JSC__JSValue__isTerminationException(this: JSValue, vm: *VM) bool; pub fn isTerminationException(this: JSValue, vm: *VM) bool { return JSC__JSValue__isTerminationException(this, vm); @@ -1129,9 +1156,12 @@ pub const JSValue = enum(i64) { } extern fn JSC__JSValue__toZigString(this: JSValue, out: *ZigString, global: *JSGlobalObject) void; - pub fn toZigString(this: JSValue, out: *ZigString, global: *JSGlobalObject) error{JSError}!void { + pub fn toZigString(this: JSValue, out: *ZigString, global: *JSGlobalObject) JSError!void { + var scope: CatchScope = undefined; + scope.init(global, @src(), .enabled); + defer scope.deinit(); JSC__JSValue__toZigString(this, out, global); - if (global.hasException()) return error.JSError; + try scope.returnIfException(); } /// Increments the reference count, you must call `.deref()` or it will leak memory. @@ -1232,7 +1262,12 @@ pub const JSValue = enum(i64) { extern fn JSC__JSValue__toStringOrNull(this: JSValue, globalThis: *JSGlobalObject) ?*JSString; // Calls JSValue::toStringOrNull. Returns error on exception. pub fn toJSString(this: JSValue, globalThis: *JSGlobalObject) bun.JSError!*JSString { - return JSC__JSValue__toStringOrNull(this, globalThis) orelse return error.JSError; + var scope: CatchScope = undefined; + scope.init(globalThis, @src(), .assertions_only); + defer scope.deinit(); + const maybe_string = JSC__JSValue__toStringOrNull(this, globalThis); + scope.assertExceptionPresenceMatches(maybe_string == null); + return maybe_string orelse error.JSError; } /// Call `toString()` on the JSValue and clone the result. @@ -1363,8 +1398,13 @@ pub const JSValue = enum(i64) { if (bun.Environment.isDebug) bun.assert(this.isObject()); - return switch (JSC__JSValue__fastGet(this, global, @intFromEnum(builtin_name))) { - .zero => error.JSError, + return switch (try fromJSHostCall( + global, + @src(), + JSC__JSValue__fastGet, + .{ this, global, @intFromEnum(builtin_name) }, + )) { + .zero => unreachable, // handled by fromJSHostCall .js_undefined, .property_does_not_exist_on_object => null, else => |val| val, }; @@ -1398,8 +1438,13 @@ pub const JSValue = enum(i64) { extern fn JSC__JSValue__getIfPropertyExistsImpl(target: JSValue, global: *JSGlobalObject, ptr: [*]const u8, len: u32) JSValue; extern fn JSC__JSValue__getPropertyValue(target: JSValue, global: *JSGlobalObject, ptr: [*]const u8, len: u32) JSValue; extern fn JSC__JSValue__getIfPropertyExistsFromPath(this: JSValue, global: *JSGlobalObject, path: JSValue) JSValue; - pub fn getIfPropertyExistsFromPath(this: JSValue, global: *JSGlobalObject, path: JSValue) JSValue { - return JSC__JSValue__getIfPropertyExistsFromPath(this, global, path); + pub fn getIfPropertyExistsFromPath(this: JSValue, global: *JSGlobalObject, path: JSValue) JSError!JSValue { + var scope: CatchScope = undefined; + scope.init(global, @src(), .enabled); + defer scope.deinit(); + const result = JSC__JSValue__getIfPropertyExistsFromPath(this, global, path); + try scope.returnIfException(); + return result; } extern fn JSC__JSValue__getSymbolDescription(this: JSValue, global: *JSGlobalObject, str: *ZigString) void; @@ -1418,16 +1463,24 @@ pub const JSValue = enum(i64) { } extern fn JSC__JSValue___then(this: JSValue, global: *JSGlobalObject, ctx: JSValue, resolve: *const JSC.JSHostFn, reject: *const JSC.JSHostFn) void; - pub fn _then(this: JSValue, global: *JSGlobalObject, ctx: JSValue, resolve: JSC.JSHostFnZig, reject: JSC.JSHostFnZig) void { + fn _then(this: JSValue, global: *JSGlobalObject, ctx: JSValue, resolve: JSC.JSHostFnZig, reject: JSC.JSHostFnZig) void { return JSC__JSValue___then(this, global, ctx, toJSHostFunction(resolve), toJSHostFunction(reject)); } pub fn _then2(this: JSValue, global: *JSGlobalObject, ctx: JSValue, resolve: *const JSC.JSHostFn, reject: *const JSC.JSHostFn) void { - return JSC__JSValue___then(this, global, ctx, resolve, reject); + var scope: CatchScope = undefined; + scope.init(global, @src(), .enabled); + defer scope.deinit(); + JSC__JSValue___then(this, global, ctx, resolve, reject); + bun.debugAssert(!scope.hasException()); // TODO: properly propagate exception upwards } pub fn then(this: JSValue, global: *JSGlobalObject, ctx: ?*anyopaque, resolve: JSC.JSHostFnZig, reject: JSC.JSHostFnZig) void { - return this._then(global, JSValue.fromPtrAddress(@intFromPtr(ctx)), resolve, reject); + var scope: CatchScope = undefined; + scope.init(global, @src(), .enabled); + defer scope.deinit(); + this._then(global, JSValue.fromPtrAddress(@intFromPtr(ctx)), resolve, reject); + bun.debugAssert(!scope.hasException()); // TODO: properly propagate exception upwards } pub fn getDescription(this: JSValue, global: *JSGlobalObject) ZigString { @@ -1436,23 +1489,6 @@ pub const JSValue = enum(i64) { return zig_str; } - /// Equivalent to `obj.property` in JavaScript. - /// Reminder: `undefined` is a value! - /// - /// Prefer `get` in new code, as this function is incapable of returning an exception - pub fn get_unsafe(this: JSValue, global: *JSGlobalObject, property: []const u8) ?JSValue { - if (comptime bun.Environment.isDebug) { - if (BuiltinName.has(property)) { - Output.debugWarn("get(\"{s}\") called. Please use fastGet(.{s}) instead!", .{ property, property }); - } - } - - return switch (JSC__JSValue__getIfPropertyExistsImpl(this, global, property.ptr, @intCast(property.len))) { - .js_undefined, .zero, .property_does_not_exist_on_object => null, - else => |val| val, - }; - } - /// Equivalent to `target[property]`. Calls userland getters/proxies. Can /// throw. Null indicates the property does not exist. JavaScript undefined /// and JavaScript null can exist as a property and is different than zig @@ -1466,7 +1502,7 @@ pub const JSValue = enum(i64) { /// Cannot handle property names that are numeric indexes. (For this use `getPropertyValue` instead.) /// pub inline fn get(target: JSValue, global: *JSGlobalObject, property: anytype) JSError!?JSValue { - if (bun.Environment.isDebug) bun.assert(target.isObject()); + bun.debugAssert(target.isObject()); const property_slice: []const u8 = property; // must be a slice! // This call requires `get` to be `inline` @@ -1476,8 +1512,13 @@ pub const JSValue = enum(i64) { } } - return switch (JSC__JSValue__getIfPropertyExistsImpl(target, global, property_slice.ptr, @intCast(property_slice.len))) { - .zero => error.JSError, + return switch (try fromJSHostCall(global, @src(), JSC__JSValue__getIfPropertyExistsImpl, .{ + target, + global, + property_slice.ptr, + @intCast(property_slice.len), + })) { + .zero => unreachable, // handled by fromJSHostCall .property_does_not_exist_on_object => null, // TODO: see bug described in ObjectBindings.cpp @@ -1512,10 +1553,17 @@ pub const JSValue = enum(i64) { extern fn JSC__JSValue__getOwn(value: JSValue, globalObject: *JSGlobalObject, propertyName: *const bun.String) JSValue; /// Get *own* property value (i.e. does not resolve property in the prototype chain) - pub fn getOwn(this: JSValue, global: *JSGlobalObject, property_name: anytype) ?JSValue { + pub fn getOwn(this: JSValue, global: *JSGlobalObject, property_name: anytype) bun.JSError!?JSValue { var property_name_str = bun.String.init(property_name); + var scope: CatchScope = undefined; + scope.init(global, @src(), .enabled); + defer scope.deinit(); const value = JSC__JSValue__getOwn(this, global, &property_name_str); - return if (@intFromEnum(value) != 0) value else return null; + try scope.returnIfException(); + return if (value == .zero) + null + else + value; } extern fn JSC__JSValue__getOwnByValue(value: JSValue, globalObject: *JSGlobalObject, propertyValue: JSValue) JSValue; @@ -1525,8 +1573,8 @@ pub const JSValue = enum(i64) { return if (@intFromEnum(value) != 0) value else return null; } - pub fn getOwnTruthy(this: JSValue, global: *JSGlobalObject, property_name: anytype) ?JSValue { - if (getOwn(this, global, property_name)) |prop| { + pub fn getOwnTruthy(this: JSValue, global: *JSGlobalObject, property_name: anytype) bun.JSError!?JSValue { + if (try getOwn(this, global, property_name)) |prop| { if (prop.isUndefined()) return null; return prop; } @@ -1610,6 +1658,9 @@ pub const JSValue = enum(i64) { /// - .js_undefined /// - an empty string pub fn getStringish(this: JSValue, global: *JSGlobalObject, property: []const u8) bun.JSError!?bun.String { + var scope: CatchScope = undefined; + scope.init(global, @src(), .enabled); + defer scope.deinit(); const prop = try get(this, global, property) orelse return null; if (prop.isNull() or prop == .false) { return null; @@ -1619,14 +1670,12 @@ pub const JSValue = enum(i64) { } const str = try prop.toBunString(global); - if (global.hasException()) { - str.deref(); - return error.JSError; - } - if (str.isEmpty()) { - return null; - } - return str; + errdefer str.deref(); + try scope.returnIfException(); + return if (str.isEmpty()) + null + else + str; } pub fn toEnumFromMap( @@ -1715,7 +1764,7 @@ pub const JSValue = enum(i64) { return globalThis.throwInvalidArguments(property_name ++ " must be an array", .{}); } - if (prop.getLength(globalThis) == 0) { + if (try prop.getLength(globalThis) == 0) { return null; } @@ -1731,7 +1780,7 @@ pub const JSValue = enum(i64) { } pub fn getOwnArray(this: JSValue, globalThis: *JSGlobalObject, comptime property_name: []const u8) JSError!?JSValue { - if (getOwnTruthy(this, globalThis, property_name)) |prop| { + if (try getOwnTruthy(this, globalThis, property_name)) |prop| { return coerceToArray(prop, globalThis, property_name); } @@ -1739,7 +1788,7 @@ pub const JSValue = enum(i64) { } pub fn getOwnObject(this: JSValue, globalThis: *JSGlobalObject, comptime property_name: []const u8) JSError!?*JSC.JSObject { - if (getOwnTruthy(this, globalThis, property_name)) |prop| { + if (try getOwnTruthy(this, globalThis, property_name)) |prop| { const obj = prop.getObject() orelse { return globalThis.throwInvalidArguments(property_name ++ " must be an object", .{}); }; @@ -1867,46 +1916,66 @@ pub const JSValue = enum(i64) { /// /// This algorithm differs from the IsStrictlyEqual Algorithm by treating all NaN values as equivalent and by differentiating +0𝔽 from -0𝔽. /// https://tc39.es/ecma262/#sec-samevalue - pub fn isSameValue(this: JSValue, other: JSValue, global: *JSGlobalObject) bool { - return @intFromEnum(this) == @intFromEnum(other) or JSC__JSValue__isSameValue(this, other, global); + /// + /// This can throw because it resolves rope strings + pub fn isSameValue(this: JSValue, other: JSValue, global: *JSGlobalObject) JSError!bool { + if (@intFromEnum(this) == @intFromEnum(other)) return true; + var scope: CatchScope = undefined; + scope.init(global, @src(), .enabled); + defer scope.deinit(); + const same = JSC__JSValue__isSameValue(this, other, global); + try scope.returnIfException(); + return same; } extern fn JSC__JSValue__deepEquals(this: JSValue, other: JSValue, global: *JSGlobalObject) bool; pub fn deepEquals(this: JSValue, other: JSValue, global: *JSGlobalObject) JSError!bool { + var scope: CatchScope = undefined; + scope.init(global, @src(), .enabled); + defer scope.deinit(); const result = JSC__JSValue__deepEquals(this, other, global); - if (global.hasException()) return error.JSError; + try scope.returnIfException(); return result; } extern fn JSC__JSValue__jestDeepEquals(this: JSValue, other: JSValue, global: *JSGlobalObject) bool; /// same as `JSValue.deepEquals`, but with jest asymmetric matchers enabled pub fn jestDeepEquals(this: JSValue, other: JSValue, global: *JSGlobalObject) JSError!bool { + var scope: CatchScope = undefined; + scope.init(global, @src(), .enabled); + defer scope.deinit(); const result = JSC__JSValue__jestDeepEquals(this, other, global); - if (global.hasException()) return error.JSError; + try scope.returnIfException(); return result; } extern fn JSC__JSValue__strictDeepEquals(this: JSValue, other: JSValue, global: *JSGlobalObject) bool; pub fn strictDeepEquals(this: JSValue, other: JSValue, global: *JSGlobalObject) JSError!bool { + var scope: CatchScope = undefined; + scope.init(global, @src(), .enabled); + defer scope.deinit(); const result = JSC__JSValue__strictDeepEquals(this, other, global); - if (global.hasException()) return error.JSError; + try scope.returnIfException(); return result; } extern fn JSC__JSValue__jestStrictDeepEquals(this: JSValue, other: JSValue, global: *JSGlobalObject) bool; /// same as `JSValue.strictDeepEquals`, but with jest asymmetric matchers enabled pub fn jestStrictDeepEquals(this: JSValue, other: JSValue, global: *JSGlobalObject) JSError!bool { + var scope: CatchScope = undefined; + scope.init(global, @src(), .enabled); + defer scope.deinit(); const result = JSC__JSValue__jestStrictDeepEquals(this, other, global); - if (global.hasException()) return error.JSError; + try scope.returnIfException(); return result; } - extern fn JSC__JSValue__deepMatch(this: JSValue, subset: JSValue, global: *JSGlobalObject, replace_props_with_asymmetric_matchers: bool) bool; - /// NOTE: can throw. Check for exceptions. - pub fn deepMatch(this: JSValue, subset: JSValue, global: *JSGlobalObject, replace_props_with_asymmetric_matchers: bool) bool { - return JSC__JSValue__deepMatch(this, subset, global, replace_props_with_asymmetric_matchers); - } extern fn JSC__JSValue__jestDeepMatch(this: JSValue, subset: JSValue, global: *JSGlobalObject, replace_props_with_asymmetric_matchers: bool) bool; /// same as `JSValue.deepMatch`, but with jest asymmetric matchers enabled - pub fn jestDeepMatch(this: JSValue, subset: JSValue, global: *JSGlobalObject, replace_props_with_asymmetric_matchers: bool) bool { - return JSC__JSValue__jestDeepMatch(this, subset, global, replace_props_with_asymmetric_matchers); + pub fn jestDeepMatch(this: JSValue, subset: JSValue, global: *JSGlobalObject, replace_props_with_asymmetric_matchers: bool) JSError!bool { + var scope: CatchScope = undefined; + scope.init(global, @src(), .enabled); + defer scope.deinit(); + const result = JSC__JSValue__jestDeepMatch(this, subset, global, replace_props_with_asymmetric_matchers); + try scope.returnIfException(); + return result; } pub const DiffMethod = enum(u8) { @@ -2107,42 +2176,27 @@ pub const JSValue = enum(i64) { /// - anything with a .length property returning a number /// /// If the "length" property does not exist, this function will return 0. - pub fn getLength(this: JSValue, globalThis: *JSGlobalObject) u64 { - const len = this.getLengthIfPropertyExistsInternal(globalThis); + pub fn getLength(this: JSValue, globalThis: *JSGlobalObject) JSError!u64 { + const len = try this.getLengthIfPropertyExistsInternal(globalThis); if (len == std.math.floatMax(f64)) { return 0; } - return @as(u64, @intFromFloat(@max(@min(len, std.math.maxInt(i52)), 0))); - } - - /// This function supports: - /// - Array, DerivedArray & friends - /// - String, DerivedString & friends - /// - TypedArray - /// - Map (size) - /// - WeakMap (size) - /// - Set (size) - /// - WeakSet (size) - /// - ArrayBuffer (byteLength) - /// - anything with a .length property returning a number - /// - /// If the "length" property does not exist, this function will return null. - pub fn tryGetLength(this: JSValue, globalThis: *JSGlobalObject) ?f64 { - const len = this.getLengthIfPropertyExistsInternal(globalThis); - if (len == std.math.floatMax(f64)) { - return null; - } - - return @as(u64, @intFromFloat(@max(@min(len, std.math.maxInt(i52)), 0))); + return @intFromFloat(std.math.clamp(len, 0, std.math.maxInt(i52))); } extern fn JSC__JSValue__getLengthIfPropertyExistsInternal(this: JSValue, globalThis: *JSGlobalObject) f64; /// Do not use this directly! /// /// If the property does not exist, this function will return max(f64) instead of 0. - pub fn getLengthIfPropertyExistsInternal(this: JSValue, globalThis: *JSGlobalObject) f64 { - return JSC__JSValue__getLengthIfPropertyExistsInternal(this, globalThis); + /// TODO this should probably just return an optional + pub fn getLengthIfPropertyExistsInternal(this: JSValue, globalThis: *JSGlobalObject) JSError!f64 { + var scope: CatchScope = undefined; + scope.init(globalThis, @src(), .enabled); + defer scope.deinit(); + const length = JSC__JSValue__getLengthIfPropertyExistsInternal(this, globalThis); + try scope.returnIfException(); + return length; } extern fn JSC__JSValue__isAggregateError(this: JSValue, globalObject: *JSGlobalObject) bool; @@ -2172,8 +2226,13 @@ pub const JSValue = enum(i64) { } extern fn JSC__JSValue__isIterable(this: JSValue, globalObject: *JSGlobalObject) bool; - pub fn isIterable(this: JSValue, globalObject: *JSGlobalObject) bool { - return JSC__JSValue__isIterable(this, globalObject); + pub fn isIterable(this: JSValue, globalObject: *JSGlobalObject) JSError!bool { + var scope: CatchScope = undefined; + scope.init(globalObject, @src(), .enabled); + defer scope.deinit(); + const is_iterable = JSC__JSValue__isIterable(this, globalObject); + try scope.returnIfException(); + return is_iterable; } extern fn JSC__JSValue__stringIncludes(this: JSValue, globalObject: *JSGlobalObject, other: JSValue) bool; @@ -2198,7 +2257,7 @@ pub const JSValue = enum(i64) { // TODO: remove this (no replacement) pub inline fn asObjectRef(this: JSValue) C_API.JSObjectRef { - return @as(C_API.JSObjectRef, @ptrCast(this.asVoid())); + return @ptrFromInt(@as(usize, @bitCast(@intFromEnum(this)))); } /// When the GC sees a JSValue referenced in the stack, it knows not to free it @@ -2208,19 +2267,6 @@ pub const JSValue = enum(i64) { std.mem.doNotOptimizeAway(this.asEncoded().asPtr); } - pub inline fn asNullableVoid(this: JSValue) ?*anyopaque { - return @as(?*anyopaque, @ptrFromInt(@as(usize, @bitCast(@intFromEnum(this))))); - } - - pub inline fn asVoid(this: JSValue) *anyopaque { - if (comptime bun.Environment.allow_assert) { - if (@intFromEnum(this) == 0) { - @panic("JSValue is null"); - } - } - return this.asNullableVoid().?; - } - pub fn uncheckedPtrCast(value: JSValue, comptime T: type) *T { return @alignCast(@ptrCast(value.asEncoded().asPtr)); } @@ -2450,6 +2496,8 @@ const JSString = JSC.JSString; const JSObject = JSC.JSObject; const JSArrayIterator = JSC.JSArrayIterator; const JSCell = JSC.JSCell; +const fromJSHostCall = JSC.fromJSHostCall; +const CatchScope = JSC.CatchScope; const AnyPromise = JSC.AnyPromise; const DOMURL = JSC.DOMURL; diff --git a/src/bun.js/bindings/ModuleLoader.cpp b/src/bun.js/bindings/ModuleLoader.cpp index adb8f33bb2..b3a71c7a6a 100644 --- a/src/bun.js/bindings/ModuleLoader.cpp +++ b/src/bun.js/bindings/ModuleLoader.cpp @@ -358,7 +358,7 @@ static JSValue handleVirtualModuleResult( case OnLoadResultTypeCode: { Bun__transpileVirtualModule(globalObject, specifier, referrer, &onLoadResult.value.sourceText.string, onLoadResult.value.sourceText.loader, res); if (!res->success) { - return reject(JSValue::decode(reinterpret_cast(res->result.err.ptr))); + return reject(JSValue::decode(res->result.err.value)); } auto provider = Zig::SourceProvider::create(globalObject, res->result.value); @@ -434,20 +434,23 @@ extern "C" void Bun__onFulfillAsyncModule( JSC::JSInternalPromise* promise = jsCast(JSC::JSValue::decode(encodedPromiseValue)); if (!res->success) { - throwException(scope, res->result.err, globalObject); - auto* exception = scope.exception(); - scope.clearException(); - return promise->reject(globalObject, exception); + return promise->reject(globalObject, JSValue::decode(res->result.err.value)); } auto specifierValue = Bun::toJS(globalObject, *specifier); - if (auto entry = globalObject->esmRegistryMap()->get(globalObject, specifierValue)) { + auto* map = globalObject->esmRegistryMap(); + RETURN_IF_EXCEPTION(scope, ); + auto entry = map->get(globalObject, specifierValue); + RETURN_IF_EXCEPTION(scope, ); + if (entry) { if (entry.isObject()) { auto* object = entry.getObject(); - if (auto state = object->getIfPropertyExists(globalObject, Bun::builtinNames(vm).statePublicName())) { - if (state.toInt32(globalObject) > JSC::JSModuleLoader::Status::Fetch) { + auto state = object->getIfPropertyExists(globalObject, Bun::builtinNames(vm).statePublicName()); + RETURN_IF_EXCEPTION(scope, ); + if (state && state.isInt32()) { + if (state.asInt32() > JSC::JSModuleLoader::Status::Fetch) { // it's a race! we lost. // https://github.com/oven-sh/bun/issues/6946 // https://github.com/oven-sh/bun/issues/12910 @@ -463,12 +466,15 @@ extern "C" void Bun__onFulfillAsyncModule( promise->resolve(globalObject, code); } else { auto* exception = scope.exception(); - scope.clearException(); - promise->reject(globalObject, exception); + if (!vm.isTerminationException(exception)) { + scope.clearException(); + promise->reject(globalObject, exception); + } } } else { auto&& provider = Zig::SourceProvider::create(jsDynamicCast(globalObject), res->result.value); promise->resolve(globalObject, JSC::JSSourceCode::create(vm, JSC::SourceCode(provider))); + scope.assertNoExceptionExceptTermination(); } } else { // the module has since been deleted from the registry. @@ -659,7 +665,9 @@ JSValue fetchCommonJSModule( } } - if (auto builtin = fetchBuiltinModuleWithoutResolution(globalObject, &specifier, res)) { + auto builtin = fetchBuiltinModuleWithoutResolution(globalObject, &specifier, res); + RETURN_IF_EXCEPTION(scope, {}); + if (builtin) { if (!res->success) { RELEASE_AND_RETURN(scope, builtin); } @@ -708,18 +716,22 @@ JSValue fetchCommonJSModule( JSMap* registry = globalObject->esmRegistryMap(); - const auto hasAlreadyLoadedESMVersionSoWeShouldntTranspileItTwice = [&]() -> bool { + bool hasAlreadyLoadedESMVersionSoWeShouldntTranspileItTwice = [&]() -> bool { JSValue entry = registry->get(globalObject, specifierValue); if (!entry || !entry.isObject()) { return false; } + // return value doesn't matter since we check for exceptions after calling this lambda and + // before checking the returned bool + RETURN_IF_EXCEPTION(scope, false); int status = entry.getObject()->getDirect(vm, WebCore::clientData(vm)->builtinNames().statePublicName()).asInt32(); return status > JSModuleLoader::Status::Fetch; - }; + }(); + RETURN_IF_EXCEPTION(scope, {}); - if (hasAlreadyLoadedESMVersionSoWeShouldntTranspileItTwice()) { + if (hasAlreadyLoadedESMVersionSoWeShouldntTranspileItTwice) { RELEASE_AND_RETURN(scope, jsNumber(-1)); } return fetchCommonJSModuleNonBuiltin(bunVM, vm, globalObject, &specifier, specifierValue, referrer, typeAttribute, res, target, specifierWtfString, BunLoaderTypeNone, scope); diff --git a/src/bun.js/bindings/NodeHTTP.cpp b/src/bun.js/bindings/NodeHTTP.cpp index 39b4bad591..7e0108f168 100644 --- a/src/bun.js/bindings/NodeHTTP.cpp +++ b/src/bun.js/bindings/NodeHTTP.cpp @@ -677,6 +677,7 @@ static void assignHeadersFromUWebSocketsForCall(uWS::HttpRequest* request, JSVal } else { headersObject->putDirectMayBeIndex(globalObject, nameIdentifier, jsValue); + RETURN_IF_EXCEPTION(scope, void()); arrayValues.append(nameString); arrayValues.append(jsValue); RETURN_IF_EXCEPTION(scope, void()); diff --git a/src/bun.js/bindings/NodeModuleModule.zig b/src/bun.js/bindings/NodeModuleModule.zig index 2b903d806d..133cfd643f 100644 --- a/src/bun.js/bindings/NodeModuleModule.zig +++ b/src/bun.js/bindings/NodeModuleModule.zig @@ -5,12 +5,14 @@ const JSGlobalObject = JSC.JSGlobalObject; const JSValue = JSC.JSValue; const ErrorableString = JSC.ErrorableString; +export const NodeModuleModule__findPath = JSC.host_fn.wrap3(findPath); + // https://github.com/nodejs/node/blob/40ef9d541ed79470977f90eb445c291b95ab75a0/lib/internal/modules/cjs/loader.js#L666 -pub export fn NodeModuleModule__findPath( +fn findPath( global: *JSGlobalObject, request_bun_str: bun.String, paths_maybe: ?*JSC.JSArray, -) JSValue { +) bun.JSError!JSValue { var stack_buf = std.heap.stackFallback(8192, bun.default_allocator); const alloc = stack_buf.get(); @@ -25,12 +27,9 @@ pub export fn NodeModuleModule__findPath( // for each path const found = if (paths_maybe) |paths| found: { - var iter = paths.iterator(global); - while (iter.next()) |path| { - const cur_path = bun.String.fromJS(path, global) catch |err| switch (err) { - error.JSError => return .zero, - error.OutOfMemory => return global.throwOutOfMemoryValue(), - }; + var iter = try paths.iterator(global); + while (try iter.next()) |path| { + const cur_path = try bun.String.fromJS(path, global); defer cur_path.deref(); if (findPathInner(request_bun_str, cur_path, global)) |found| { @@ -65,7 +64,7 @@ fn findPathInner( true, ) catch |err| switch (err) { error.JSError => { - global.clearException(); + global.clearException(); // TODO sus return null; }, else => return null, diff --git a/src/bun.js/bindings/NodeTimerObject.cpp b/src/bun.js/bindings/NodeTimerObject.cpp index d3523c983d..2936bddeb4 100644 --- a/src/bun.js/bindings/NodeTimerObject.cpp +++ b/src/bun.js/bindings/NodeTimerObject.cpp @@ -19,7 +19,7 @@ using namespace JSC; static bool call(JSGlobalObject* globalObject, JSValue timerObject, JSValue callbackValue, JSValue argumentsValue) { auto& vm = JSC::getVM(globalObject); - auto scope = DECLARE_THROW_SCOPE(vm); + auto scope = DECLARE_CATCH_SCOPE(vm); JSValue restoreAsyncContext {}; JSC::InternalFieldTuple* asyncContextData = nullptr; diff --git a/src/bun.js/bindings/ObjectBindings.cpp b/src/bun.js/bindings/ObjectBindings.cpp index 7ccd219cf3..fcdc4336b2 100644 --- a/src/bun.js/bindings/ObjectBindings.cpp +++ b/src/bun.js/bindings/ObjectBindings.cpp @@ -68,10 +68,12 @@ JSC::JSValue getIfPropertyExistsPrototypePollutionMitigationUnsafe(JSC::VM& vm, auto isDefined = getNonIndexPropertySlotPrototypePollutionMitigation(vm, object, globalObject, name, propertySlot); if (!isDefined) { + RETURN_IF_EXCEPTION(scope, {}); return JSValue::decode(JSC::JSValue::ValueDeleted); } - scope.assertNoException(); + scope.assertNoExceptionExceptTermination(); + RETURN_IF_EXCEPTION(scope, {}); JSValue value = propertySlot.getValue(globalObject, name); RETURN_IF_EXCEPTION(scope, {}); return value; diff --git a/src/bun.js/bindings/ProcessBindingTTYWrap.cpp b/src/bun.js/bindings/ProcessBindingTTYWrap.cpp index 9e5866e78b..2b13975d21 100644 --- a/src/bun.js/bindings/ProcessBindingTTYWrap.cpp +++ b/src/bun.js/bindings/ProcessBindingTTYWrap.cpp @@ -323,7 +323,9 @@ JSC_DEFINE_HOST_FUNCTION(Process_functionInternalGetWindowSize, } array->putDirectIndex(globalObject, 0, jsNumber(width)); + RETURN_IF_EXCEPTION(throwScope, {}); array->putDirectIndex(globalObject, 1, jsNumber(height)); + RETURN_IF_EXCEPTION(throwScope, {}); return JSC::JSValue::encode(jsBoolean(true)); } diff --git a/src/bun.js/bindings/ZigErrorType.zig b/src/bun.js/bindings/ZigErrorType.zig index 8559dda282..ce38dbda88 100644 --- a/src/bun.js/bindings/ZigErrorType.zig +++ b/src/bun.js/bindings/ZigErrorType.zig @@ -1,6 +1,7 @@ pub const ZigErrorType = extern struct { code: ErrorCode, - ptr: ?*anyopaque, + value: bun.jsc.JSValue, }; +const bun = @import("bun"); const ErrorCode = @import("ErrorCode.zig").ErrorCode; diff --git a/src/bun.js/bindings/ZigGlobalObject.cpp b/src/bun.js/bindings/ZigGlobalObject.cpp index 6b3615dc3c..ef26ff8471 100644 --- a/src/bun.js/bindings/ZigGlobalObject.cpp +++ b/src/bun.js/bindings/ZigGlobalObject.cpp @@ -662,7 +662,7 @@ static String computeErrorInfoWithoutPrepareStackTrace( String& sourceURL, JSObject* errorInstance) { - + auto scope = DECLARE_THROW_SCOPE(vm); WTF::String name = "Error"_s; WTF::String message; @@ -673,7 +673,9 @@ static String computeErrorInfoWithoutPrepareStackTrace( lexicalGlobalObject = errorInstance->globalObject(); } name = instance->sanitizedNameString(lexicalGlobalObject); + RETURN_IF_EXCEPTION(scope, {}); message = instance->sanitizedMessageString(lexicalGlobalObject); + RETURN_IF_EXCEPTION(scope, {}); } } @@ -752,7 +754,7 @@ static JSValue computeErrorInfoWithPrepareStackTrace(JSC::VM& vm, Zig::GlobalObj JSArray* callSitesArray = JSC::constructArray(globalObject, globalObject->arrayStructureForIndexingTypeDuringAllocation(JSC::ArrayWithContiguous), callSites); RETURN_IF_EXCEPTION(scope, {}); - return formatStackTraceToJSValue(vm, globalObject, lexicalGlobalObject, errorObject, callSitesArray, prepareStackTrace); + RELEASE_AND_RETURN(scope, formatStackTraceToJSValue(vm, globalObject, lexicalGlobalObject, errorObject, callSitesArray, prepareStackTrace)); } static String computeErrorInfoToString(JSC::VM& vm, Vector& stackTrace, OrdinalNumber& line, OrdinalNumber& column, String& sourceURL) @@ -2189,7 +2191,9 @@ extern "C" JSC::EncodedJSValue ZigGlobalObject__createNativeReadableStream(Zig:: arguments.append(JSValue::decode(nativePtr)); auto callData = JSC::getCallData(function); - return JSC::JSValue::encode(call(globalObject, function, callData, JSC::jsUndefined(), arguments)); + auto result = call(globalObject, function, callData, JSC::jsUndefined(), arguments); + EXCEPTION_ASSERT(!!scope.exception() == !result); + return JSValue::encode(result); } extern "C" JSC::EncodedJSValue Bun__Jest__createTestModuleObject(JSC::JSGlobalObject*); @@ -2931,16 +2935,20 @@ void GlobalObject::finishCreation(VM& vm) m_JSBufferSubclassStructure.initLater( [](const Initializer& init) { + auto scope = DECLARE_CATCH_SCOPE(init.vm); auto* globalObject = static_cast(init.owner); auto* baseStructure = globalObject->typedArrayStructureWithTypedArrayType(); JSC::Structure* subclassStructure = JSC::InternalFunction::createSubclassStructure(globalObject, globalObject->JSBufferConstructor(), baseStructure); + scope.assertNoExceptionExceptTermination(); init.set(subclassStructure); }); m_JSResizableOrGrowableSharedBufferSubclassStructure.initLater( [](const Initializer& init) { + auto scope = DECLARE_CATCH_SCOPE(init.vm); auto* globalObject = static_cast(init.owner); auto* baseStructure = globalObject->resizableOrGrowableSharedTypedArrayStructureWithTypedArrayType(); JSC::Structure* subclassStructure = JSC::InternalFunction::createSubclassStructure(globalObject, globalObject->JSBufferConstructor(), baseStructure); + scope.assertNoExceptionExceptTermination(); init.set(subclassStructure); }); m_performMicrotaskFunction.initLater( @@ -3184,9 +3192,24 @@ void GlobalObject::finishCreation(VM& vm) [](const JSC::LazyProperty::Initializer& init) { auto* global = init.owner; auto& vm = init.vm; + auto scope = DECLARE_THROW_SCOPE(vm); + + // if we get the termination exception, we'd still like to set a non-null Map so that + // we don't segfault + auto setEmpty = [&]() { + ASSERT(scope.exception()); + init.set(JSC::JSMap::create(init.vm, init.owner->mapStructure())); + }; + JSMap* registry = nullptr; - if (auto loaderValue = global->getIfPropertyExists(global, JSC::Identifier::fromString(vm, "Loader"_s))) { - if (auto registryValue = loaderValue.getObject()->getIfPropertyExists(global, JSC::Identifier::fromString(vm, "registry"_s))) { + auto loaderValue = global->getIfPropertyExists(global, JSC::Identifier::fromString(vm, "Loader"_s)); + scope.assertNoExceptionExceptTermination(); + RETURN_IF_EXCEPTION(scope, setEmpty()); + if (loaderValue) { + auto registryValue = loaderValue.getObject()->getIfPropertyExists(global, JSC::Identifier::fromString(vm, "registry"_s)); + scope.assertNoExceptionExceptTermination(); + RETURN_IF_EXCEPTION(scope, setEmpty()); + if (registryValue) { registry = jsCast(registryValue); } } @@ -3613,6 +3636,7 @@ JSValue GlobalObject_getGlobalThis(VM& vm, JSObject* globalObject) void GlobalObject::addBuiltinGlobals(JSC::VM& vm) { + auto scope = DECLARE_CATCH_SCOPE(vm); m_builtinInternalFunctions.initialize(*this); auto clientData = WebCore::clientData(vm); @@ -3726,6 +3750,8 @@ void GlobalObject::addBuiltinGlobals(JSC::VM& vm) errorConstructor->putDirectCustomAccessor(vm, JSC::Identifier::fromString(vm, "prepareStackTrace"_s), JSC::CustomGetterSetter::create(vm, errorConstructorPrepareStackTraceGetter, errorConstructorPrepareStackTraceSetter), PropertyAttribute::DontEnum | PropertyAttribute::CustomValue); JSC::JSObject* consoleObject = this->get(this, JSC::Identifier::fromString(vm, "console"_s)).getObject(); + scope.assertNoExceptionExceptTermination(); + RETURN_IF_EXCEPTION(scope, ); consoleObject->putDirectBuiltinFunction(vm, this, vm.propertyNames->asyncIteratorSymbol, consoleObjectAsyncIteratorCodeGenerator(vm), PropertyAttribute::Builtin | 0); consoleObject->putDirectBuiltinFunction(vm, this, clientData->builtinNames().writePublicName(), consoleObjectWriteCodeGenerator(vm), PropertyAttribute::Builtin | 0); consoleObject->putDirectCustomAccessor(vm, Identifier::fromString(vm, "Console"_s), CustomGetterSetter::create(vm, getConsoleConstructor, nullptr), PropertyAttribute::CustomValue | 0); @@ -4242,6 +4268,8 @@ JSC::JSInternalPromise* GlobalObject::moduleLoaderFetch(JSGlobalObject* globalOb &source, typeAttributeString.isEmpty() ? nullptr : &typeAttribute); + RETURN_IF_EXCEPTION(scope, rejectedInternalPromise(globalObject, scope.exception()->value())); + ASSERT(result); if (auto* internalPromise = JSC::jsDynamicCast(result)) { return internalPromise; } else if (auto* promise = JSC::jsDynamicCast(result)) { diff --git a/src/bun.js/bindings/bindings.cpp b/src/bun.js/bindings/bindings.cpp index a0a6b00a93..34db22da41 100644 --- a/src/bun.js/bindings/bindings.cpp +++ b/src/bun.js/bindings/bindings.cpp @@ -191,11 +191,34 @@ enum class AsymmetricMatcherConstructorType : int8_t { }; #if ASSERT_ENABLED -#define ASSERT_NO_PENDING_EXCEPTION(globalObject) DECLARE_THROW_SCOPE(globalObject->vm()).assertNoExceptionExceptTermination() +#define ASSERT_NO_PENDING_EXCEPTION(globalObject) DECLARE_CATCH_SCOPE(globalObject->vm()).assertNoExceptionExceptTermination() #else #define ASSERT_NO_PENDING_EXCEPTION(globalObject) void() #endif +// Ensure we instantiate the true and false variants of this function +template bool Bun__deepMatch( + JSValue objValue, + std::set* seenObjProperties, + JSValue subsetValue, + std::set* seenSubsetProperties, + JSGlobalObject* globalObject, + ThrowScope* throwScope, + MarkedArgumentBuffer* gcBuffer, + bool replacePropsWithAsymmetricMatchers, + bool isMatchingObjectContaining); + +template bool Bun__deepMatch( + JSValue objValue, + std::set* seenObjProperties, + JSValue subsetValue, + std::set* seenSubsetProperties, + JSGlobalObject* globalObject, + ThrowScope* throwScope, + MarkedArgumentBuffer* gcBuffer, + bool replacePropsWithAsymmetricMatchers, + bool isMatchingObjectContaining); + extern "C" bool Expect_readFlagsAndProcessPromise(JSC::EncodedJSValue instanceValue, JSC::JSGlobalObject* globalObject, ExpectFlags* flags, JSC::EncodedJSValue* value, AsymmetricMatcherConstructorType* constructorType); extern "C" int8_t AsymmetricMatcherConstructorType__fromJS(JSC::JSGlobalObject* globalObject, JSC::EncodedJSValue encodedValue) @@ -375,7 +398,9 @@ AsymmetricMatcherResult matchAsymmetricMatcherAndGetFlags(JSGlobalObject* global } } - if (constructorObject->hasInstance(globalObject, otherProp)) { + bool hasInstance = constructorObject->hasInstance(globalObject, otherProp); + RETURN_IF_EXCEPTION(*throwScope, AsymmetricMatcherResult::FAIL); + if (hasInstance) { return AsymmetricMatcherResult::PASS; } @@ -453,10 +478,11 @@ AsymmetricMatcherResult matchAsymmetricMatcherAndGetFlags(JSGlobalObject* global for (unsigned n = 0; n < otherLength; n++) { JSValue otherValue = otherArray->getIndex(globalObject, n); - ThrowScope scope = DECLARE_THROW_SCOPE(globalObject->vm()); Vector, 16> stack; MarkedArgumentBuffer gcBuffer; - if (Bun__deepEquals(globalObject, expectedValue, otherValue, gcBuffer, stack, &scope, true)) { + bool foundNow = Bun__deepEquals(globalObject, expectedValue, otherValue, gcBuffer, stack, throwScope, true); + RETURN_IF_EXCEPTION(*throwScope, AsymmetricMatcherResult::FAIL); + if (foundNow) { found = true; break; } @@ -479,11 +505,12 @@ AsymmetricMatcherResult matchAsymmetricMatcherAndGetFlags(JSGlobalObject* global JSValue patternObject = expectObjectContaining->m_objectValue.get(); if (patternObject.isObject()) { if (otherProp.isObject()) { - ThrowScope scope = DECLARE_THROW_SCOPE(globalObject->vm()); // SAFETY: visited property sets are not required when // `enableAsymmetricMatchers` and `isMatchingObjectContaining` // are both true - if (Bun__deepMatch(otherProp, nullptr, patternObject, nullptr, globalObject, &scope, nullptr, false, true)) { + bool match = Bun__deepMatch(otherProp, nullptr, patternObject, nullptr, globalObject, throwScope, nullptr, false, true); + RETURN_IF_EXCEPTION(*throwScope, AsymmetricMatcherResult::FAIL); + if (match) { return AsymmetricMatcherResult::PASS; } } @@ -686,6 +713,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); if (isSpecialEqual.has_value()) return std::move(*isSpecialEqual); isSpecialEqual = specialObjectsDequal(globalObject, gcBuffer, stack, scope, c2, c1); if (isSpecialEqual.has_value()) return std::move(*isSpecialEqual); @@ -755,7 +783,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); JSObject::getOwnPropertyNames(o2, globalObject, a2, DontEnumPropertiesMode::Exclude); + RETURN_IF_EXCEPTION(*scope, false); size_t propertyLength = a1.size(); if constexpr (isStrict) { @@ -1000,23 +1030,28 @@ std::optional specialObjectsDequal(JSC::JSGlobalObject* globalObject, Mark } auto iter1 = JSSetIterator::create(globalObject, globalObject->setIteratorStructure(), set1, IterationKind::Keys); + RETURN_IF_EXCEPTION(*scope, {}); JSValue key1; while (iter1->next(globalObject, key1)) { - if (set2->has(globalObject, key1)) { + bool has = set2->has(globalObject, key1); + RETURN_IF_EXCEPTION(*scope, {}); + if (has) { continue; } // 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, {}); JSValue key2; bool foundMatchingKey = false; while (iter2->next(globalObject, key2)) { - if (Bun__deepEquals(globalObject, key1, key2, gcBuffer, stack, scope, false)) { + bool equal = Bun__deepEquals(globalObject, key1, key2, gcBuffer, stack, scope, false); + RETURN_IF_EXCEPTION(*scope, {}); + if (equal) { foundMatchingKey = true; break; } - RETURN_IF_EXCEPTION(*scope, false); } if (!foundMatchingKey) { @@ -1040,22 +1075,26 @@ std::optional specialObjectsDequal(JSC::JSGlobalObject* globalObject, Mark } auto iter1 = JSMapIterator::create(globalObject, globalObject->mapIteratorStructure(), map1, IterationKind::Entries); + RETURN_IF_EXCEPTION(*scope, {}); JSValue key1, value1; while (iter1->nextKeyValue(globalObject, key1, value1)) { JSValue value2 = map2->get(globalObject, key1); + 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, {}); JSValue key2; bool foundMatchingKey = false; while (iter2->nextKeyValue(globalObject, key2, value2)) { - if (Bun__deepEquals(globalObject, key1, key2, gcBuffer, stack, scope, false)) { + bool keysEqual = Bun__deepEquals(globalObject, key1, key2, gcBuffer, stack, scope, false); + RETURN_IF_EXCEPTION(*scope, {}); + if (keysEqual) { foundMatchingKey = true; break; } - RETURN_IF_EXCEPTION(*scope, false); } if (!foundMatchingKey) { @@ -1065,7 +1104,9 @@ std::optional specialObjectsDequal(JSC::JSGlobalObject* globalObject, Mark // Compare both values below. } - if (!Bun__deepEquals(globalObject, value1, value2, gcBuffer, stack, scope, false)) { + bool valuesEqual = Bun__deepEquals(globalObject, value1, value2, gcBuffer, stack, scope, false); + RETURN_IF_EXCEPTION(*scope, {}); + if (!valuesEqual) { return false; } } @@ -1147,11 +1188,26 @@ std::optional specialObjectsDequal(JSC::JSGlobalObject* globalObject, Mark return false; } - if ( - left->errorType() != right->errorType() || // quick check on ctors (does not handle subclasses) - left->sanitizedNameString(globalObject) != right->sanitizedNameString(globalObject) || // manual `.name` changes (usually in subclasses) - left->sanitizedMessageString(globalObject) != right->sanitizedMessageString(globalObject) // `.message` - ) { + if (left->errorType() != right->errorType()) { + // quick check on ctors (does not handle subclasses) + return false; + } + + auto leftName = left->sanitizedNameString(globalObject); + RETURN_IF_EXCEPTION(*scope, {}); + auto rightName = right->sanitizedNameString(globalObject); + RETURN_IF_EXCEPTION(*scope, {}); + if (leftName != rightName) { + // manual `.name` changes (usually in subclasses) + return false; + } + + auto leftMessage = left->sanitizedMessageString(globalObject); + RETURN_IF_EXCEPTION(*scope, {}); + auto rightMessage = right->sanitizedMessageString(globalObject); + RETURN_IF_EXCEPTION(*scope, {}); + if (leftMessage != rightMessage) { + // `.message` return false; } @@ -1161,25 +1217,30 @@ std::optional specialObjectsDequal(JSC::JSGlobalObject* globalObject, Mark } } - VM& vm = globalObject->vm(); + VM& vm = JSC::getVM(globalObject); // `.cause` is non-enumerable, so it must be checked explicitly. // note that an undefined cause is different than a missing cause in // strict mode. const PropertyName cause(vm.propertyNames->cause); if constexpr (isStrict) { - if (left->hasProperty(globalObject, cause) != right->hasProperty(globalObject, cause)) { + bool leftHasCause = left->hasProperty(globalObject, cause); + RETURN_IF_EXCEPTION(*scope, {}); + bool rightHasCause = right->hasProperty(globalObject, cause); + RETURN_IF_EXCEPTION(*scope, {}); + if (leftHasCause != rightHasCause) { return false; } } auto leftCause = left->get(globalObject, cause); - RETURN_IF_EXCEPTION(*scope, false); + RETURN_IF_EXCEPTION(*scope, {}); auto rightCause = right->get(globalObject, cause); - RETURN_IF_EXCEPTION(*scope, false); - if (!Bun__deepEquals(globalObject, leftCause, rightCause, gcBuffer, stack, scope, true)) { + RETURN_IF_EXCEPTION(*scope, {}); + bool causesEqual = Bun__deepEquals(globalObject, leftCause, rightCause, gcBuffer, stack, scope, true); + RETURN_IF_EXCEPTION(*scope, {}); + if (!causesEqual) { return false; } - RETURN_IF_EXCEPTION(*scope, false); // check arbitrary enumerable properties. `.stack` is not checked. left->materializeErrorInfoIfNeeded(vm); @@ -1187,9 +1248,9 @@ std::optional specialObjectsDequal(JSC::JSGlobalObject* globalObject, Mark 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, false); + RETURN_IF_EXCEPTION(*scope, {}); right->getPropertyNames(globalObject, a2, DontEnumPropertiesMode::Exclude); - RETURN_IF_EXCEPTION(*scope, false); + RETURN_IF_EXCEPTION(*scope, {}); const size_t propertyArrayLength1 = a1.size(); const size_t propertyArrayLength2 = a2.size(); @@ -1207,14 +1268,11 @@ std::optional specialObjectsDequal(JSC::JSGlobalObject* globalObject, Mark PropertyName propertyName1 = PropertyName(i1); JSValue prop1 = left->get(globalObject, propertyName1); - RETURN_IF_EXCEPTION(*scope, false); - - if (!prop1) [[unlikely]] { - return false; - } + RETURN_IF_EXCEPTION(*scope, {}); + ASSERT(prop1); JSValue prop2 = right->getIfPropertyExists(globalObject, propertyName1); - RETURN_IF_EXCEPTION(*scope, false); + RETURN_IF_EXCEPTION(*scope, {}); if constexpr (!isStrict) { if (prop1.isUndefined() && prop2.isEmpty()) { @@ -1226,11 +1284,11 @@ std::optional specialObjectsDequal(JSC::JSGlobalObject* globalObject, Mark return false; } - if (!Bun__deepEquals(globalObject, prop1, prop2, gcBuffer, stack, scope, true)) { + bool propertiesEqual = Bun__deepEquals(globalObject, prop1, prop2, gcBuffer, stack, scope, true); + RETURN_IF_EXCEPTION(*scope, {}); + if (!propertiesEqual) { return false; } - - RETURN_IF_EXCEPTION(*scope, false); } // for the remaining properties in the other object, make sure they are undefined @@ -1240,7 +1298,7 @@ std::optional specialObjectsDequal(JSC::JSGlobalObject* globalObject, Mark PropertyName propertyName2 = PropertyName(i2); JSValue prop2 = right->getIfPropertyExists(globalObject, propertyName2); - RETURN_IF_EXCEPTION(*scope, false); + RETURN_IF_EXCEPTION(*scope, {}); if (!prop2.isUndefined()) { return false; @@ -1347,9 +1405,13 @@ std::optional specialObjectsDequal(JSC::JSGlobalObject* globalObject, Mark } JSString* s1 = c1->toStringInline(globalObject); + RETURN_IF_EXCEPTION(*scope, {}); JSString* s2 = c2->toStringInline(globalObject); + RETURN_IF_EXCEPTION(*scope, {}); - return s1->equal(globalObject, s2); + bool stringsEqual = s1->equal(globalObject, s2); + RETURN_IF_EXCEPTION(*scope, {}); + return stringsEqual; } case JSFunctionType: { return false; @@ -1542,6 +1604,7 @@ bool Bun__deepMatch( PropertyNameArray subsetProps(vm, PropertyNameMode::StringsAndSymbols, PrivateSymbolMode::Include); subsetObj->getPropertyNames(globalObject, subsetProps, DontEnumPropertiesMode::Exclude); + RETURN_IF_EXCEPTION(*throwScope, false); // TODO: add fast paths for: // - two "simple" objects (using ->forEachProperty in both) @@ -1555,6 +1618,7 @@ bool Bun__deepMatch( } PropertyNameArray objProps(vm, PropertyNameMode::StringsAndSymbols, PrivateSymbolMode::Include); obj->getPropertyNames(globalObject, objProps, DontEnumPropertiesMode::Exclude); + RETURN_IF_EXCEPTION(*throwScope, false); if (objProps.size() != subsetProps.size()) { return false; } @@ -1582,6 +1646,7 @@ bool Bun__deepMatch( case AsymmetricMatcherResult::PASS: if (replacePropsWithAsymmetricMatchers) { obj->putDirectMayBeIndex(globalObject, property, subsetProp); + RETURN_IF_EXCEPTION(*throwScope, false); } // continue to next subset prop continue; @@ -1595,6 +1660,7 @@ bool Bun__deepMatch( case AsymmetricMatcherResult::PASS: if (replacePropsWithAsymmetricMatchers) { subsetObj->putDirectMayBeIndex(globalObject, property, prop); + RETURN_IF_EXCEPTION(*throwScope, false); } // continue to next subset prop continue; @@ -1647,7 +1713,8 @@ inline bool deepEqualsWrapperImpl(JSC::EncodedJSValue a, JSC::EncodedJSValue b, auto scope = DECLARE_THROW_SCOPE(vm); Vector, 16> stack; MarkedArgumentBuffer args; - return 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); } } @@ -2284,9 +2351,9 @@ double JSC__JSValue__getLengthIfPropertyExistsInternal(JSC::EncodedJSValue value if (auto* object = jsDynamicCast(cell)) { auto scope = DECLARE_THROW_SCOPE(globalObject->vm()); + scope.release(); // zig binding handles exceptions if (JSValue lengthValue = object->getIfPropertyExists(globalObject, globalObject->vm().propertyNames->length)) { - RETURN_IF_EXCEPTION(scope, {}); - RELEASE_AND_RETURN(scope, lengthValue.toNumber(globalObject)); + return lengthValue.toNumber(globalObject); } } } @@ -2557,19 +2624,6 @@ bool JSC__JSValue__jestStrictDeepEquals(JSC::EncodedJSValue JSValue0, JSC::Encod #undef IMPL_DEEP_EQUALS_WRAPPER -bool JSC__JSValue__deepMatch(JSC::EncodedJSValue JSValue0, JSC::EncodedJSValue JSValue1, JSC::JSGlobalObject* globalObject, bool replacePropsWithAsymmetricMatchers) -{ - JSValue obj = JSValue::decode(JSValue0); - JSValue subset = JSValue::decode(JSValue1); - - ThrowScope scope = DECLARE_THROW_SCOPE(globalObject->vm()); - - std::set objVisited; - std::set subsetVisited; - MarkedArgumentBuffer gcBuffer; - return Bun__deepMatch(obj, &objVisited, subset, &subsetVisited, globalObject, &scope, &gcBuffer, replacePropsWithAsymmetricMatchers, false); -} - bool JSC__JSValue__jestDeepMatch(JSC::EncodedJSValue JSValue0, JSC::EncodedJSValue JSValue1, JSC::JSGlobalObject* globalObject, bool replacePropsWithAsymmetricMatchers) { JSValue obj = JSValue::decode(JSValue0); @@ -2580,7 +2634,7 @@ bool JSC__JSValue__jestDeepMatch(JSC::EncodedJSValue JSValue0, JSC::EncodedJSVal std::set objVisited; std::set subsetVisited; MarkedArgumentBuffer gcBuffer; - return 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) @@ -2684,11 +2738,16 @@ JSC::EncodedJSValue JSObjectCallAsFunctionReturnValueHoldingAPILock(JSContextRef // CPP_DECL void JSC__PropertyNameArray__release(JSC__PropertyNameArray* arg0); size_t JSC__JSObject__getArrayLength(JSC::JSObject* arg0) { return arg0->getArrayLength(); } -JSC::EncodedJSValue JSC__JSObject__getIndex(JSC::EncodedJSValue jsValue, JSC::JSGlobalObject* arg1, - uint32_t arg3) +JSC::EncodedJSValue JSC__JSObject__getIndex(JSC::EncodedJSValue jsValue, JSC::JSGlobalObject* globalObject, + uint32_t index) { - ASSERT_NO_PENDING_EXCEPTION(arg1); - return JSC::JSValue::encode(JSC::JSValue::decode(jsValue).toObject(arg1)->getIndex(arg1, arg3)); + ASSERT_NO_PENDING_EXCEPTION(globalObject); + auto scope = DECLARE_THROW_SCOPE(getVM(globalObject)); + auto* object = JSC::JSValue::decode(jsValue).toObject(globalObject); + RETURN_IF_EXCEPTION(scope, {}); + auto value = object->getIndex(globalObject, index); + RETURN_IF_EXCEPTION(scope, {}); + return JSC::JSValue::encode(value); } JSC::EncodedJSValue JSC__JSValue__getDirectIndex(JSC::EncodedJSValue jsValue, JSC::JSGlobalObject* arg1, @@ -2756,10 +2815,10 @@ JSC::JSObject* JSC__JSString__toObject(JSC::JSString* arg0, JSC::JSGlobalObject* extern "C" JSC::JSInternalPromise* JSModuleLoader__import(JSC::JSGlobalObject* globalObject, const BunString* moduleNameStr) { auto& vm = JSC::getVM(globalObject); - auto scope = DECLARE_THROW_SCOPE(vm); + auto scope = DECLARE_CATCH_SCOPE(vm); auto* promise = JSC::importModule(globalObject, JSC::Identifier::fromString(vm, moduleNameStr->toWTFString()), jsUndefined(), jsUndefined(), jsUndefined()); - RETURN_IF_EXCEPTION(scope, {}); + EXCEPTION_ASSERT(!!scope.exception() == !promise); return promise; } @@ -3201,7 +3260,7 @@ JSC__JSModuleLoader__loadAndEvaluateModule(JSC::JSGlobalObject* globalObject, const BunString* arg1) { auto& vm = JSC::getVM(globalObject); - auto scope = DECLARE_THROW_SCOPE(vm); + auto scope = DECLARE_CATCH_SCOPE(vm); auto name = makeAtomString(arg1->toWTFString()); auto* promise = JSC::loadAndEvaluateModule(globalObject, name, JSC::jsUndefined(), JSC::jsUndefined()); @@ -3212,7 +3271,9 @@ JSC__JSModuleLoader__loadAndEvaluateModule(JSC::JSGlobalObject* globalObject, JSC::JSNativeStdFunction* resolverFunction = JSC::JSNativeStdFunction::create( vm, globalObject, 1, String(), resolverFunctionCallback); - return promise->then(globalObject, resolverFunction, nullptr); + auto* newPromise = promise->then(globalObject, resolverFunction, nullptr); + EXCEPTION_ASSERT(!!scope.exception() == !newPromise); + return newPromise; } #pragma mark - JSC::JSPromise @@ -3231,11 +3292,13 @@ void JSC__AnyPromise__wrap(JSC::JSGlobalObject* globalObject, EncodedJSValue enc if (auto* promise = jsDynamicCast(promiseValue)) { promise->reject(globalObject, exception->value()); + RETURN_IF_EXCEPTION(scope, ); return; } if (auto* promise = jsDynamicCast(promiseValue)) { promise->reject(globalObject, exception->value()); + RETURN_IF_EXCEPTION(scope, ); return; } @@ -3245,11 +3308,13 @@ void JSC__AnyPromise__wrap(JSC::JSGlobalObject* globalObject, EncodedJSValue enc if (auto* errorInstance = jsDynamicCast(result)) { if (auto* promise = jsDynamicCast(promiseValue)) { promise->reject(globalObject, errorInstance); + RETURN_IF_EXCEPTION(scope, ); return; } if (auto* promise = jsDynamicCast(promiseValue)) { promise->reject(globalObject, errorInstance); + RETURN_IF_EXCEPTION(scope, ); return; } @@ -3258,10 +3323,12 @@ void JSC__AnyPromise__wrap(JSC::JSGlobalObject* globalObject, EncodedJSValue enc if (auto* promise = jsDynamicCast(promiseValue)) { promise->resolve(globalObject, result); + RETURN_IF_EXCEPTION(scope, ); return; } if (auto* promise = jsDynamicCast(promiseValue)) { promise->resolve(globalObject, result); + RETURN_IF_EXCEPTION(scope, ); return; } @@ -3271,24 +3338,24 @@ void JSC__AnyPromise__wrap(JSC::JSGlobalObject* globalObject, EncodedJSValue enc JSC::EncodedJSValue JSC__JSPromise__wrap(JSC::JSGlobalObject* globalObject, void* ctx, JSC::EncodedJSValue (*func)(void*, JSC::JSGlobalObject*)) { auto& vm = JSC::getVM(globalObject); - auto scope = DECLARE_CATCH_SCOPE(vm); + auto scope = DECLARE_THROW_SCOPE(vm); JSValue result = JSC::JSValue::decode(func(ctx, globalObject)); if (scope.exception()) { auto* exception = scope.exception(); scope.clearException(); - return JSValue::encode(JSC::JSPromise::rejectedPromise(globalObject, exception->value())); + RELEASE_AND_RETURN(scope, JSValue::encode(JSC::JSPromise::rejectedPromise(globalObject, exception->value()))); } if (auto* promise = jsDynamicCast(result)) { - return JSValue::encode(promise); + RELEASE_AND_RETURN(scope, JSValue::encode(promise)); } if (JSC::ErrorInstance* err = jsDynamicCast(result)) { - return JSValue::encode(JSC::JSPromise::rejectedPromise(globalObject, err)); + RELEASE_AND_RETURN(scope, JSValue::encode(JSC::JSPromise::rejectedPromise(globalObject, err))); } - return JSValue::encode(JSC::JSPromise::resolvedPromise(globalObject, result)); + RELEASE_AND_RETURN(scope, JSValue::encode(JSC::JSPromise::resolvedPromise(globalObject, result))); } void JSC__JSPromise__reject(JSC::JSPromise* arg0, JSC::JSGlobalObject* globalObject, @@ -3974,15 +4041,16 @@ extern "C" JSC::EncodedJSValue JSC__JSValue__getOwn(JSC::EncodedJSValue JSValue0 ASSERT_NO_PENDING_EXCEPTION(globalObject); VM& vm = globalObject->vm(); + auto scope = DECLARE_THROW_SCOPE(vm); JSValue value = JSC::JSValue::decode(JSValue0); WTF::String propertyNameString = propertyName->tag == BunStringTag::Empty ? WTF::emptyString() : propertyName->toWTFString(BunString::ZeroCopy); auto identifier = JSC::Identifier::fromString(vm, propertyNameString); auto property = JSC::PropertyName(identifier); PropertySlot slot(value, PropertySlot::InternalMethodType::GetOwnProperty); if (value.getOwnPropertySlot(globalObject, property, slot)) { - return JSValue::encode(slot.getValue(globalObject, property)); + RELEASE_AND_RETURN(scope, JSValue::encode(slot.getValue(globalObject, property))); } - return JSValue::encode({}); + RELEASE_AND_RETURN(scope, JSValue::encode({})); } JSC::EncodedJSValue JSC__JSValue__getIfPropertyExistsFromPath(JSC::EncodedJSValue JSValue0, JSC::JSGlobalObject* globalObject, JSC::EncodedJSValue arg1) @@ -3995,10 +4063,13 @@ JSC::EncodedJSValue JSC__JSValue__getIfPropertyExistsFromPath(JSC::EncodedJSValu if (path.isString()) { String pathString = path.toWTFString(globalObject); + RETURN_IF_EXCEPTION(scope, {}); uint32_t length = pathString.length(); if (length == 0) { - JSValue prop = value.toObject(globalObject)->getIfPropertyExists(globalObject, PropertyName(Identifier::EmptyIdentifier)); + auto* valueObject = value.toObject(globalObject); + RETURN_IF_EXCEPTION(scope, {}); + JSValue prop = valueObject->getIfPropertyExists(globalObject, PropertyName(Identifier::EmptyIdentifier)); RETURN_IF_EXCEPTION(scope, {}); return JSValue::encode(prop); } @@ -4013,7 +4084,9 @@ JSC::EncodedJSValue JSC__JSValue__getIfPropertyExistsFromPath(JSC::EncodedJSValu // if "." is the only character, it will search for an empty string twice. if (pathString.characterAt(0) == '.') { - currProp = currProp.toObject(globalObject)->getIfPropertyExists(globalObject, PropertyName(Identifier::EmptyIdentifier)); + auto* currPropObject = currProp.toObject(globalObject); + RETURN_IF_EXCEPTION(scope, {}); + currProp = currPropObject->getIfPropertyExists(globalObject, PropertyName(Identifier::EmptyIdentifier)); RETURN_IF_EXCEPTION(scope, {}); if (currProp.isEmpty()) { return JSValue::encode(currProp); @@ -4027,7 +4100,9 @@ JSC::EncodedJSValue JSC__JSValue__getIfPropertyExistsFromPath(JSC::EncodedJSValu if (i == length) { if (ic == '.') { - currProp = currProp.toObject(globalObject)->getIfPropertyExists(globalObject, PropertyName(Identifier::EmptyIdentifier)); + auto* currPropObject = currProp.toObject(globalObject); + RETURN_IF_EXCEPTION(scope, {}); + currProp = currPropObject->getIfPropertyExists(globalObject, PropertyName(Identifier::EmptyIdentifier)); RETURN_IF_EXCEPTION(scope, {}); return JSValue::encode(currProp); } @@ -4043,7 +4118,9 @@ JSC::EncodedJSValue JSC__JSValue__getIfPropertyExistsFromPath(JSC::EncodedJSValu UChar previous = ic; ic = pathString.characterAt(i); if (previous == '.' && ic == '.') { - currProp = currProp.toObject(globalObject)->getIfPropertyExists(globalObject, PropertyName(Identifier::EmptyIdentifier)); + auto* currPropObject = currProp.toObject(globalObject); + RETURN_IF_EXCEPTION(scope, {}); + currProp = currPropObject->getIfPropertyExists(globalObject, PropertyName(Identifier::EmptyIdentifier)); RETURN_IF_EXCEPTION(scope, {}); if (currProp.isEmpty()) { return JSValue::encode(currProp); @@ -4066,7 +4143,9 @@ JSC::EncodedJSValue JSC__JSValue__getIfPropertyExistsFromPath(JSC::EncodedJSValu String propNameStr = pathString.substring(i, j - i); PropertyName propName = PropertyName(Identifier::fromString(vm, propNameStr)); - currProp = currProp.toObject(globalObject)->getIfPropertyExists(globalObject, propName); + auto* currPropObject = currProp.toObject(globalObject); + RETURN_IF_EXCEPTION(scope, {}); + currProp = currPropObject->getIfPropertyExists(globalObject, propName); RETURN_IF_EXCEPTION(scope, {}); if (currProp.isEmpty()) { return JSValue::encode(currProp); @@ -4081,7 +4160,9 @@ JSC::EncodedJSValue JSC__JSValue__getIfPropertyExistsFromPath(JSC::EncodedJSValu if (isArray(globalObject, path)) { // each item in array is property name, ignore dot/bracket notation JSValue currProp = value; - forEachInArrayLike(globalObject, path.toObject(globalObject), [&](JSValue item) -> bool { + auto* pathObject = path.toObject(globalObject); + RETURN_IF_EXCEPTION(scope, {}); + forEachInArrayLike(globalObject, pathObject, [&](JSValue item) -> bool { if (!(item.isString() || item.isNumber())) { currProp = {}; return false; @@ -4092,7 +4173,9 @@ JSC::EncodedJSValue JSC__JSValue__getIfPropertyExistsFromPath(JSC::EncodedJSValu PropertyName propName = PropertyName(propNameString->toIdentifier(globalObject)); RETURN_IF_EXCEPTION(scope, {}); - currProp = currProp.toObject(globalObject)->getIfPropertyExists(globalObject, propName); + auto* currPropObject = currProp.toObject(globalObject); + RETURN_IF_EXCEPTION(scope, {}); + currProp = currPropObject->getIfPropertyExists(globalObject, propName); RETURN_IF_EXCEPTION(scope, {}); if (currProp.isEmpty()) { return false; @@ -4100,7 +4183,7 @@ JSC::EncodedJSValue JSC__JSValue__getIfPropertyExistsFromPath(JSC::EncodedJSValu return true; }); - + RETURN_IF_EXCEPTION(scope, {}); return JSValue::encode(currProp); } @@ -4648,13 +4731,13 @@ static void fromErrorInstance(ZigException* except, JSC::JSGlobalObject* global, bool getFromSourceURL = false; if (stackTrace != nullptr && stackTrace->size() > 0) { populateStackTrace(vm, *stackTrace, &except->stack, global, flags); - if (scope.exception()) [[unlikely]] { - scope.clearExceptionExceptTermination(); + if (!scope.clearExceptionExceptTermination()) [[unlikely]] { + return; } } else if (err->stackTrace() != nullptr && err->stackTrace()->size() > 0) { populateStackTrace(vm, *err->stackTrace(), &except->stack, global, flags); - if (scope.exception()) [[unlikely]] { - scope.clearExceptionExceptTermination(); + if (!scope.clearExceptionExceptTermination()) [[unlikely]] { + return; } } else { getFromSourceURL = true; @@ -4668,17 +4751,26 @@ static void fromErrorInstance(ZigException* except, JSC::JSGlobalObject* global, } if (except->type == SYNTAX_ERROR_CODE) { except->message = Bun::toStringRef(err->sanitizedMessageString(global)); + if (!scope.clearExceptionExceptTermination()) [[unlikely]] { + return; + } } else if (JSC::JSValue message = obj->getIfPropertyExists(global, vm.propertyNames->message)) { except->message = Bun::toStringRef(global, message); } else { except->message = Bun::toStringRef(err->sanitizedMessageString(global)); + if (!scope.clearExceptionExceptTermination()) [[unlikely]] { + return; + } } - if (scope.exception()) [[unlikely]] { - scope.clearExceptionExceptTermination(); + if (!scope.clearExceptionExceptTermination()) [[unlikely]] { + return; } except->name = Bun::toStringRef(err->sanitizedNameString(global)); + if (!scope.clearExceptionExceptTermination()) [[unlikely]] { + return; + } except->runtime_type = err->runtimeTypeForCause(); @@ -4691,8 +4783,8 @@ static void fromErrorInstance(ZigException* except, JSC::JSGlobalObject* global, } } - if (scope.exception()) [[unlikely]] { - scope.clearExceptionExceptTermination(); + if (!scope.clearExceptionExceptTermination()) [[unlikely]] { + return; } if (JSC::JSValue code = getNonObservable(vm, global, obj, names.codePublicName())) { @@ -4701,8 +4793,8 @@ static void fromErrorInstance(ZigException* except, JSC::JSGlobalObject* global, } } - if (scope.exception()) [[unlikely]] { - scope.clearExceptionExceptTermination(); + if (!scope.clearExceptionExceptTermination()) [[unlikely]] { + return; } if (JSC::JSValue path = getNonObservable(vm, global, obj, names.pathPublicName())) { @@ -4711,8 +4803,8 @@ static void fromErrorInstance(ZigException* except, JSC::JSGlobalObject* global, } } - if (scope.exception()) [[unlikely]] { - scope.clearExceptionExceptTermination(); + if (!scope.clearExceptionExceptTermination()) [[unlikely]] { + return; } if (JSC::JSValue fd = getNonObservable(vm, global, obj, names.fdPublicName())) { @@ -4721,8 +4813,8 @@ static void fromErrorInstance(ZigException* except, JSC::JSGlobalObject* global, } } - if (scope.exception()) [[unlikely]] { - scope.clearExceptionExceptTermination(); + if (!scope.clearExceptionExceptTermination()) [[unlikely]] { + return; } if (JSC::JSValue errno_ = getNonObservable(vm, global, obj, names.errnoPublicName())) { @@ -4731,8 +4823,8 @@ static void fromErrorInstance(ZigException* except, JSC::JSGlobalObject* global, } } - if (scope.exception()) [[unlikely]] { - scope.clearExceptionExceptTermination(); + if (!scope.clearExceptionExceptTermination()) [[unlikely]] { + return; } } @@ -4742,14 +4834,12 @@ static void fromErrorInstance(ZigException* except, JSC::JSGlobalObject* global, // we don't want to serialize JSC::StackFrame longer than we need to // so in this case, we parse the stack trace as a string - auto catchScope = DECLARE_CATCH_SCOPE(vm); - // This one intentionally calls getters. if (JSC::JSValue stackValue = obj->getIfPropertyExists(global, vm.propertyNames->stack)) { if (stackValue.isString()) { WTF::String stack = stackValue.toWTFString(global); - if (catchScope.exception()) [[unlikely]] { - catchScope.clearExceptionExceptTermination(); + if (!scope.clearExceptionExceptTermination()) [[unlikely]] { + return; } if (!stack.isEmpty()) { @@ -4793,8 +4883,8 @@ static void fromErrorInstance(ZigException* except, JSC::JSGlobalObject* global, } } - if (catchScope.exception()) [[unlikely]] { - catchScope.clearExceptionExceptTermination(); + if (!scope.clearExceptionExceptTermination()) [[unlikely]] { + return; } } @@ -5519,10 +5609,10 @@ static void JSC__JSValue__forEachPropertyImpl(JSC::EncodedJSValue JSValue0, JSC: return; auto& vm = JSC::getVM(globalObject); - auto throwScope = DECLARE_THROW_SCOPE(vm); + auto throwScopeForStackOverflowException = DECLARE_THROW_SCOPE(vm); if (!vm.isSafeToRecurse()) [[unlikely]] { - throwStackOverflowError(globalObject, throwScope); + throwStackOverflowError(globalObject, throwScopeForStackOverflowException); return; } @@ -5776,11 +5866,11 @@ void JSC__JSValue__forEachPropertyOrdered(JSC::EncodedJSValue JSValue0, JSC::JSG return; auto& vm = JSC::getVM(globalObject); + auto scope = DECLARE_CATCH_SCOPE(vm); JSC::PropertyNameArray properties(vm, PropertyNameMode::StringsAndSymbols, PrivateSymbolMode::Exclude); { - auto scope = DECLARE_CATCH_SCOPE(vm); JSC::JSObject::getOwnPropertyNames(object, globalObject, properties, DontEnumPropertiesMode::Include); if (scope.exception()) { scope.clearException(); @@ -5805,8 +5895,11 @@ void JSC__JSValue__forEachPropertyOrdered(JSC::EncodedJSValue JSValue0, JSC::JSG continue; JSC::PropertySlot slot(object, PropertySlot::InternalMethodType::Get); - if (!object->getPropertySlot(globalObject, property, slot)) + bool hasProperty = object->getPropertySlot(globalObject, property, slot); + scope.clearException(); + if (!hasProperty) { continue; + } if ((slot.attributes() & PropertyAttribute::DontEnum) != 0) { if (property == vm.propertyNames->underscoreProto @@ -5815,7 +5908,6 @@ void JSC__JSValue__forEachPropertyOrdered(JSC::EncodedJSValue JSValue0, JSC::JSG } JSC::JSValue propertyValue = jsUndefined(); - auto scope = DECLARE_CATCH_SCOPE(vm); if ((slot.attributes() & PropertyAttribute::DontEnum) != 0) { if ((slot.attributes() & PropertyAttribute::Accessor) != 0) { propertyValue = slot.getPureResult(); @@ -5843,6 +5935,7 @@ void JSC__JSValue__forEachPropertyOrdered(JSC::EncodedJSValue JSValue0, JSC::JSG ZigString key = toZigString(name); JSC::EnsureStillAliveScope ensureStillAliveScope(propertyValue); + // TODO: properly propagate exception upwards iter(globalObject, arg2, &key, JSC::JSValue::encode(propertyValue), property.isSymbol(), property.isPrivateName()); } properties.releaseData(); @@ -6425,7 +6518,7 @@ extern "C" EncodedJSValue Bun__JSObject__getCodePropertyVMInquiry(JSC::JSGlobalO } auto& vm = global->vm(); - auto scope = DECLARE_THROW_SCOPE(vm); + auto scope = DECLARE_CATCH_SCOPE(vm); if (object->type() == JSC::ProxyObjectType) [[unlikely]] { return {}; } @@ -6433,9 +6526,9 @@ extern "C" EncodedJSValue Bun__JSObject__getCodePropertyVMInquiry(JSC::JSGlobalO auto& builtinNames = WebCore::builtinNames(vm); PropertySlot slot(object, PropertySlot::InternalMethodType::VMInquiry, &vm); - ASSERT(!scope.exception()); + scope.assertNoExceptionExceptTermination(); if (!object->getNonIndexPropertySlot(global, builtinNames.codePublicName(), slot)) { - ASSERT(!scope.exception()); + scope.assertNoExceptionExceptTermination(); return {}; } diff --git a/src/bun.js/bindings/headers-handwritten.h b/src/bun.js/bindings/headers-handwritten.h index d4b56c87fc..c2b7184183 100644 --- a/src/bun.js/bindings/headers-handwritten.h +++ b/src/bun.js/bindings/headers-handwritten.h @@ -85,7 +85,7 @@ typedef struct BunString { typedef struct ZigErrorType { ZigErrorCode code; - void* ptr; + JSC::EncodedJSValue value; } ZigErrorType; typedef union ErrorableZigStringResult { ZigString value; diff --git a/src/bun.js/bindings/headers.h b/src/bun.js/bindings/headers.h index 9abc67f3b4..cfbb1c7f81 100644 --- a/src/bun.js/bindings/headers.h +++ b/src/bun.js/bindings/headers.h @@ -212,7 +212,6 @@ CPP_DECL JSC::EncodedJSValue JSC__JSValue__createStringArray(JSC::JSGlobalObject CPP_DECL JSC::EncodedJSValue JSC__JSValue__createTypeError(const ZigString* arg0, const ZigString* arg1, JSC::JSGlobalObject* arg2); CPP_DECL JSC::EncodedJSValue JSC__JSValue__createUninitializedUint8Array(JSC::JSGlobalObject* arg0, size_t arg1); CPP_DECL bool JSC__JSValue__deepEquals(JSC::EncodedJSValue JSValue0, JSC::EncodedJSValue JSValue1, JSC::JSGlobalObject* arg2); -CPP_DECL bool JSC__JSValue__deepMatch(JSC::EncodedJSValue JSValue0, JSC::EncodedJSValue JSValue1, JSC::JSGlobalObject* arg2, bool arg3); CPP_DECL bool JSC__JSValue__eqlCell(JSC::EncodedJSValue JSValue0, JSC::JSCell* arg1); CPP_DECL bool JSC__JSValue__eqlValue(JSC::EncodedJSValue JSValue0, JSC::EncodedJSValue JSValue1); CPP_DECL JSC::EncodedJSValue JSC__JSValue__fastGet(JSC::EncodedJSValue JSValue0, JSC::JSGlobalObject* arg1, unsigned char arg2); @@ -325,16 +324,6 @@ CPP_DECL void JSC__VM__throwError(JSC::VM* arg0, JSC::JSGlobalObject* arg1, JSC: CPP_DECL void JSC__VM__throwError(JSC::VM* arg0, JSC::JSGlobalObject* arg1, JSC::EncodedJSValue JSValue2); CPP_DECL void JSC__VM__whenIdle(JSC::VM* arg0, void(* ArgFn1)()); -#pragma mark - JSC::ThrowScope - -CPP_DECL void JSC__ThrowScope__clearException(JSC::ThrowScope* arg0); -CPP_DECL JSC::Exception* JSC__ThrowScope__exception(JSC::ThrowScope* arg0); -CPP_DECL void JSC__ThrowScope__release(JSC::ThrowScope* arg0); - -#pragma mark - JSC::CatchScope - -CPP_DECL void JSC__CatchScope__clearException(JSC::CatchScope* arg0); -CPP_DECL JSC::Exception* JSC__CatchScope__exception(JSC::CatchScope* arg0); CPP_DECL void FFI__ptr__put(JSC::JSGlobalObject* arg0, JSC::EncodedJSValue JSValue1); #ifdef __cplusplus diff --git a/src/bun.js/bindings/helpers.h b/src/bun.js/bindings/helpers.h index 1c70272776..8314fa81b2 100644 --- a/src/bun.js/bindings/helpers.h +++ b/src/bun.js/bindings/helpers.h @@ -273,7 +273,7 @@ static WTF::StringView toStringView(ZigString str) static void throwException(JSC::ThrowScope& scope, ZigErrorType err, JSC::JSGlobalObject* global) { scope.throwException(global, - JSC::Exception::create(global->vm(), JSC::JSValue((JSC::JSCell*)err.ptr))); + JSC::Exception::create(global->vm(), JSC::JSValue::decode(err.value))); } static ZigString toZigString(JSC::JSValue val, JSC::JSGlobalObject* global) diff --git a/src/bun.js/bindings/node/http/JSConnectionsList.cpp b/src/bun.js/bindings/node/http/JSConnectionsList.cpp index 20ee467ea9..bdc549c83c 100644 --- a/src/bun.js/bindings/node/http/JSConnectionsList.cpp +++ b/src/bun.js/bindings/node/http/JSConnectionsList.cpp @@ -60,6 +60,7 @@ JSArray* JSConnectionsList::all(JSGlobalObject* globalObject) RETURN_IF_EXCEPTION(scope, {}); auto iter = JSSetIterator::create(globalObject, globalObject->setIteratorStructure(), all, IterationKind::Keys); + RETURN_IF_EXCEPTION(scope, nullptr); JSValue item; size_t i = 0; @@ -85,6 +86,7 @@ JSArray* JSConnectionsList::idle(JSGlobalObject* globalObject) RETURN_IF_EXCEPTION(scope, {}); auto iter = JSSetIterator::create(globalObject, globalObject->setIteratorStructure(), all, IterationKind::Keys); + RETURN_IF_EXCEPTION(scope, nullptr); JSValue item; size_t i = 0; @@ -112,6 +114,7 @@ JSArray* JSConnectionsList::active(JSGlobalObject* globalObject) RETURN_IF_EXCEPTION(scope, {}); auto iter = JSSetIterator::create(globalObject, globalObject->setIteratorStructure(), active, IterationKind::Keys); + RETURN_IF_EXCEPTION(scope, nullptr); JSValue item; size_t i = 0; @@ -137,6 +140,7 @@ JSArray* JSConnectionsList::expired(JSGlobalObject* globalObject, uint64_t heade RETURN_IF_EXCEPTION(scope, {}); auto iter = JSSetIterator::create(globalObject, globalObject->setIteratorStructure(), active, IterationKind::Keys); + RETURN_IF_EXCEPTION(scope, nullptr); JSValue item = iter->next(vm); size_t i = 0; diff --git a/src/bun.js/event_loop.zig b/src/bun.js/event_loop.zig index 100aa7a6cc..a583403ba0 100644 --- a/src/bun.js/event_loop.zig +++ b/src/bun.js/event_loop.zig @@ -70,20 +70,20 @@ pub fn exit(this: *EventLoop) void { defer this.debug.exit(); if (count == 1 and !this.virtual_machine.is_inside_deferred_task_queue) { - this.drainMicrotasksWithGlobal(this.global, this.virtual_machine.jsc); + this.drainMicrotasksWithGlobal(this.global, this.virtual_machine.jsc) catch {}; } this.entered_event_loop_count -= 1; } -pub fn exitMaybeDrainMicrotasks(this: *EventLoop, allow_drain_microtask: bool) void { +pub fn exitMaybeDrainMicrotasks(this: *EventLoop, allow_drain_microtask: bool) bun.JSExecutionTerminated!void { const count = this.entered_event_loop_count; log("exit() = {d}", .{count - 1}); defer this.debug.exit(); if (allow_drain_microtask and count == 1 and !this.virtual_machine.is_inside_deferred_task_queue) { - this.drainMicrotasksWithGlobal(this.global, this.virtual_machine.jsc); + try this.drainMicrotasksWithGlobal(this.global, this.virtual_machine.jsc); } this.entered_event_loop_count -= 1; @@ -107,11 +107,15 @@ pub fn tickWhilePaused(this: *EventLoop, done: *bool) void { } extern fn JSC__JSGlobalObject__drainMicrotasks(*JSC.JSGlobalObject) void; -pub fn drainMicrotasksWithGlobal(this: *EventLoop, globalObject: *JSC.JSGlobalObject, jsc_vm: *JSC.VM) void { +pub fn drainMicrotasksWithGlobal(this: *EventLoop, globalObject: *JSC.JSGlobalObject, jsc_vm: *JSC.VM) bun.JSExecutionTerminated!void { JSC.markBinding(@src()); + var scope: JSC.CatchScope = undefined; + scope.init(globalObject, @src(), .enabled); + defer scope.deinit(); jsc_vm.releaseWeakRefs(); JSC__JSGlobalObject__drainMicrotasks(globalObject); + try scope.assertNoExceptionExceptTermination(); this.virtual_machine.is_inside_deferred_task_queue = true; this.deferred_tasks.run(); @@ -122,14 +126,14 @@ pub fn drainMicrotasksWithGlobal(this: *EventLoop, globalObject: *JSC.JSGlobalOb } } -pub fn drainMicrotasks(this: *EventLoop) void { - this.drainMicrotasksWithGlobal(this.global, this.virtual_machine.jsc); +pub fn drainMicrotasks(this: *EventLoop) bun.JSExecutionTerminated!void { + try this.drainMicrotasksWithGlobal(this.global, this.virtual_machine.jsc); } // should be called after exit() pub fn maybeDrainMicrotasks(this: *EventLoop) void { if (this.entered_event_loop_count == 0 and !this.virtual_machine.is_inside_deferred_task_queue) { - this.drainMicrotasksWithGlobal(this.global, this.virtual_machine.jsc); + this.drainMicrotasksWithGlobal(this.global, this.virtual_machine.jsc) catch {}; } } @@ -444,6 +448,9 @@ pub fn processGCTimer(this: *EventLoop) void { pub fn tick(this: *EventLoop) void { JSC.markBinding(@src()); + var scope: JSC.CatchScope = undefined; + scope.init(this.global, @src(), .enabled); + defer scope.deinit(); this.entered_event_loop_count += 1; this.debug.enter(); defer { @@ -462,7 +469,8 @@ pub fn tick(this: *EventLoop) void { while (this.tickWithCount(ctx) > 0) : (this.global.handleRejectedPromises()) { this.tickConcurrent(); } else { - this.drainMicrotasksWithGlobal(global, global_vm); + this.drainMicrotasksWithGlobal(global, global_vm) catch return; + if (scope.hasException()) return; this.tickConcurrent(); if (this.tasks.count > 0) continue; } diff --git a/src/bun.js/event_loop/Task.zig b/src/bun.js/event_loop/Task.zig index c29a78de2a..b35e534d62 100644 --- a/src/bun.js/event_loop/Task.zig +++ b/src/bun.js/event_loop/Task.zig @@ -95,7 +95,7 @@ pub const Task = TaggedPointerUnion(.{ pub fn tickQueueWithCount(this: *EventLoop, virtual_machine: *VirtualMachine) u32 { var global = this.global; const global_vm = global.vm(); - var counter: usize = 0; + var counter: u32 = 0; if (comptime Environment.isDebug) { if (this.debug.js_call_count_outside_tick_queue > this.debug.drain_microtasks_count_outside_tick_queue) { @@ -460,7 +460,7 @@ pub fn tickQueueWithCount(this: *EventLoop, virtual_machine: *VirtualMachine) u3 }, @field(Task.Tag, @typeName(RuntimeTranspilerStore)) => { var any: *RuntimeTranspilerStore = task.get(RuntimeTranspilerStore).?; - any.drain(); + any.drain() catch {}; }, @field(Task.Tag, @typeName(ServerAllConnectionsClosedTask)) => { var any: *ServerAllConnectionsClosedTask = task.get(ServerAllConnectionsClosedTask).?; @@ -485,16 +485,20 @@ pub fn tickQueueWithCount(this: *EventLoop, virtual_machine: *VirtualMachine) u3 any.runFromJSThread(); }, - else => { + .@"shell.builtin.yes.YesTask", .@"bun.js.api.Timer.ImmediateObject", .@"bun.js.api.Timer.TimeoutObject" => { bun.Output.panic("Unexpected tag: {s}", .{@tagName(task.tag())}); }, + _ => { + // handle unnamed variants + bun.Output.panic("Unknown tag: {d}", .{@intFromEnum(task.tag())}); + }, } - this.drainMicrotasksWithGlobal(global, global_vm); + this.drainMicrotasksWithGlobal(global, global_vm) catch return counter; } this.tasks.head = if (this.tasks.count == 0) 0 else this.tasks.head; - return @as(u32, @truncate(counter)); + return counter; } const TaggedPointerUnion = bun.TaggedPointerUnion; diff --git a/src/bun.js/ipc.zig b/src/bun.js/ipc.zig index 3e43f8151f..f3ae7a053d 100644 --- a/src/bun.js/ipc.zig +++ b/src/bun.js/ipc.zig @@ -356,7 +356,7 @@ pub const CallbackList = union(enum) { }, } } - fn callNextTick(self: *@This(), global: *JSC.JSGlobalObject) void { + fn callNextTick(self: *@This(), global: *JSC.JSGlobalObject) bun.JSError!void { switch (self.*) { .ack_nack => {}, .none => {}, @@ -366,8 +366,8 @@ pub const CallbackList = union(enum) { self.* = .none; }, .callback_array => { - var iter = self.callback_array.arrayIterator(global); - while (iter.next()) |item| { + var iter = try self.callback_array.arrayIterator(global); + while (try iter.next()) |item| { item.callNextTick(global, .{.null}); } self.callback_array.unprotect(); @@ -399,8 +399,8 @@ pub const SendHandle = struct { /// Call the callback and deinit pub fn complete(self: *SendHandle, global: *JSC.JSGlobalObject) void { - self.callbacks.callNextTick(global); - self.deinit(); + defer self.deinit(); + self.callbacks.callNextTick(global) catch {}; // TODO: properly propagate exception upwards } pub fn deinit(self: *SendHandle) void { self.data.deinit(); @@ -981,8 +981,8 @@ pub fn doSend(ipc: ?*SendQueue, globalObject: *JSC.JSGlobalObject, callFrame: *J if (serialized_array.isUndefinedOrNull()) { handle = .js_undefined; } else { - const serialized_handle = serialized_array.getIndex(globalObject, 0); - const serialized_message = serialized_array.getIndex(globalObject, 1); + const serialized_handle = try serialized_array.getIndex(globalObject, 0); + const serialized_message = try serialized_array.getIndex(globalObject, 1); handle = serialized_handle; message = serialized_message; } diff --git a/src/bun.js/jsc.zig b/src/bun.js/jsc.zig index 36b43620f8..db9e03fc76 100644 --- a/src/bun.js/jsc.zig +++ b/src/bun.js/jsc.zig @@ -33,8 +33,8 @@ pub const JSHostFnZigWithContext = host_fn.JSHostFnZigWithContext; pub const JSHostFunctionTypeWithContext = host_fn.JSHostFunctionTypeWithContext; pub const toJSHostFn = host_fn.toJSHostFn; pub const toJSHostFnWithContext = host_fn.toJSHostFnWithContext; -pub const toJSHostValue = host_fn.toJSHostValue; -pub const fromJSHostValue = host_fn.fromJSHostValue; +pub const toJSHostCall = host_fn.toJSHostCall; +pub const fromJSHostCall = host_fn.fromJSHostCall; pub const createCallback = host_fn.createCallback; // JSC Classes Bindings @@ -79,6 +79,7 @@ pub const Weak = @import("Weak.zig").Weak; pub const WeakRefType = @import("Weak.zig").WeakRefType; pub const Exception = @import("bindings/Exception.zig").Exception; pub const SourceProvider = @import("bindings/SourceProvider.zig").SourceProvider; +pub const CatchScope = @import("bindings/CatchScope.zig"); // JavaScript-related pub const Errorable = @import("bindings/Errorable.zig").Errorable; diff --git a/src/bun.js/jsc/host_fn.zig b/src/bun.js/jsc/host_fn.zig index a563783e63..9bba8d08f5 100644 --- a/src/bun.js/jsc/host_fn.zig +++ b/src/bun.js/jsc/host_fn.zig @@ -81,20 +81,44 @@ pub fn toJSHostSetterValue(globalThis: *JSGlobalObject, value: error{ OutOfMemor return true; } -pub fn toJSHostValue(globalThis: *JSGlobalObject, value: error{ OutOfMemory, JSError }!JSValue) JSValue { - const normal = value catch |err| switch (err) { +/// Convert the return value of a function returning an error union into a maybe-empty JSValue +pub fn toJSHostCall( + globalThis: *JSGlobalObject, + src: std.builtin.SourceLocation, + comptime function: anytype, + // This can't use std.meta.ArgsTuple because that will turn comptime function parameters into + // runtime tuple values + args: anytype, +) JSValue { + var scope: jsc.CatchScope = undefined; + scope.init(globalThis, src, .assertions_only); + defer scope.deinit(); + + const returned: error{ OutOfMemory, JSError }!JSValue = @call(.auto, function, args); + const normal = returned catch |err| switch (err) { error.JSError => .zero, error.OutOfMemory => globalThis.throwOutOfMemoryValue(), }; - if (Environment.allow_assert and Environment.is_canary) { - debugExceptionAssertion(globalThis, normal, toJSHostValue); - } + scope.assertExceptionPresenceMatches(normal == .zero); return normal; } -pub fn fromJSHostValue(value: JSValue) bun.JSError!JSValue { - if (value == .zero) return error.JSError; - return value; +/// Convert the return value of a function returning a maybe-empty JSValue into an error union. +/// The wrapped function must return an empty JSValue if and only if it has thrown an exception. +pub fn fromJSHostCall( + globalThis: *JSGlobalObject, + /// For attributing thrown exceptions + src: std.builtin.SourceLocation, + comptime function: anytype, + args: std.meta.ArgsTuple(@TypeOf(function)), +) bun.JSError!JSValue { + var scope: jsc.CatchScope = undefined; + scope.init(globalThis, src, .assertions_only); + defer scope.deinit(); + + const value = @call(.auto, function, args); + scope.assertExceptionPresenceMatches(value == .zero); + return if (value == .zero) error.JSError else value; } const ParsedHostFunctionErrorSet = struct { @@ -122,14 +146,7 @@ pub fn wrap1(comptime func: anytype) @"return": { const p = @typeInfo(@TypeOf(func)).@"fn".params; return struct { pub fn wrapped(arg0: p[0].type.?) callconv(.c) JSValue { - const value = func(arg0) catch |err| switch (err) { - error.JSError => .zero, - error.OutOfMemory => arg0.throwOutOfMemoryValue(), - }; - if (Environment.allow_assert and Environment.is_canary) { - debugExceptionAssertion(arg0, value, func); - } - return value; + return toJSHostCall(arg0, @src(), func, .{arg0}); } }.wrapped; } @@ -141,14 +158,7 @@ pub fn wrap2(comptime func: anytype) @"return": { const p = @typeInfo(@TypeOf(func)).@"fn".params; return struct { pub fn wrapped(arg0: p[0].type.?, arg1: p[1].type.?) callconv(.c) JSValue { - const value = func(arg0, arg1) catch |err| switch (err) { - error.JSError => .zero, - error.OutOfMemory => arg0.throwOutOfMemoryValue(), - }; - if (Environment.allow_assert and Environment.is_canary) { - debugExceptionAssertion(arg0, value, func); - } - return value; + return toJSHostCall(arg0, @src(), func, .{ arg0, arg1 }); } }.wrapped; } @@ -160,14 +170,7 @@ pub fn wrap3(comptime func: anytype) @"return": { const p = @typeInfo(@TypeOf(func)).@"fn".params; return struct { pub fn wrapped(arg0: p[0].type.?, arg1: p[1].type.?, arg2: p[2].type.?) callconv(.c) JSValue { - const value = func(arg0, arg1, arg2) catch |err| switch (err) { - error.JSError => .zero, - error.OutOfMemory => arg0.throwOutOfMemoryValue(), - }; - if (Environment.allow_assert and Environment.is_canary) { - debugExceptionAssertion(arg0, value, func); - } - return value; + return toJSHostCall(arg0, @src(), func, .{ arg0, arg1, arg2 }); } }.wrapped; } @@ -179,14 +182,7 @@ pub fn wrap4(comptime func: anytype) @"return": { 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(.c) JSValue { - const value = func(arg0, arg1, arg2, arg3) catch |err| switch (err) { - error.JSError => .zero, - error.OutOfMemory => arg0.throwOutOfMemoryValue(), - }; - if (Environment.allow_assert and Environment.is_canary) { - debugExceptionAssertion(arg0, value, func); - } - return value; + return toJSHostCall(arg0, @src(), func, .{ arg0, arg1, arg2, arg3 }); } }.wrapped; } @@ -198,14 +194,7 @@ pub fn wrap5(comptime func: anytype) @"return": { 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.?, arg4: p[4].type.?) callconv(.c) JSValue { - const value = func(arg0, arg1, arg2, arg3, arg4) catch |err| switch (err) { - error.JSError => .zero, - error.OutOfMemory => arg0.throwOutOfMemoryValue(), - }; - if (Environment.allow_assert and Environment.is_canary) { - debugExceptionAssertion(arg0, value, func); - } - return value; + return toJSHostCall(arg0, @src(), func, .{ arg0, arg1, arg2, arg3, arg4 }); } }.wrapped; } @@ -469,7 +458,7 @@ pub fn DOMCall( arguments_ptr: [*]const jsc.JSValue, arguments_len: usize, ) callconv(jsc.conv) jsc.JSValue { - return jsc.toJSHostValue(globalObject, @field(Container, functionName)(globalObject, thisValue, arguments_ptr[0..arguments_len])); + return jsc.toJSHostCall(globalObject, @src(), @field(Container, functionName), .{ globalObject, thisValue, arguments_ptr[0..arguments_len] }); } pub const fastpath = @field(Container, functionName ++ "WithoutTypeChecks"); diff --git a/src/bun.js/modules/BunJSCModule.h b/src/bun.js/modules/BunJSCModule.h index 509cd96180..de0e5750b9 100644 --- a/src/bun.js/modules/BunJSCModule.h +++ b/src/bun.js/modules/BunJSCModule.h @@ -584,8 +584,11 @@ JSC_DEFINE_HOST_FUNCTION(functionDrainMicrotasks, (JSGlobalObject * globalObject, CallFrame*)) { VM& vm = globalObject->vm(); + auto scope = DECLARE_THROW_SCOPE(vm); vm.drainMicrotasks(); + RETURN_IF_EXCEPTION(scope, {}); Bun__drainMicrotasks(); + RETURN_IF_EXCEPTION(scope, {}); return JSValue::encode(jsUndefined()); } diff --git a/src/bun.js/modules/NodeBufferModule.h b/src/bun.js/modules/NodeBufferModule.h index eba221af55..8542ac4dcf 100644 --- a/src/bun.js/modules/NodeBufferModule.h +++ b/src/bun.js/modules/NodeBufferModule.h @@ -158,6 +158,7 @@ JSC_DEFINE_CUSTOM_SETTER(jsSetter_INSPECT_MAX_BYTES, (JSGlobalObject * lexicalGl DEFINE_NATIVE_MODULE(NodeBuffer) { INIT_NATIVE_MODULE(12); + auto scope = DECLARE_THROW_SCOPE(vm); put(JSC::Identifier::fromString(vm, "Buffer"_s), globalObject->JSBufferConstructor()); @@ -192,9 +193,11 @@ DEFINE_NATIVE_MODULE(NodeBuffer) JSC::Identifier atobI = JSC::Identifier::fromString(vm, "atob"_s); JSC::JSValue atobV = lexicalGlobalObject->get(globalObject, PropertyName(atobI)); + RETURN_IF_EXCEPTION(scope, ); JSC::Identifier btoaI = JSC::Identifier::fromString(vm, "btoa"_s); JSC::JSValue btoaV = lexicalGlobalObject->get(globalObject, PropertyName(btoaI)); + RETURN_IF_EXCEPTION(scope, ); put(atobI, atobV); put(btoaI, btoaV); diff --git a/src/bun.js/node/node_os.zig b/src/bun.js/node/node_os.zig index 2dedf0cc5d..6a4b9aa8f5 100644 --- a/src/bun.js/node/node_os.zig +++ b/src/bun.js/node/node_os.zig @@ -129,7 +129,7 @@ fn cpusImplLinux(globalThis: *JSC.JSGlobalObject) !JSC.JSValue { while (line_iter.next()) |line| { if (strings.hasPrefixComptime(line, key_processor)) { if (!has_model_name) { - const cpu = JSC.JSObject.getIndex(values, globalThis, cpu_index); + const cpu = try values.getIndex(globalThis, cpu_index); cpu.put(globalThis, JSC.ZigString.static("model"), JSC.ZigString.static("unknown").withEncoding().toJS(globalThis)); } // If this line starts a new processor, parse the index from the line @@ -140,26 +140,26 @@ fn cpusImplLinux(globalThis: *JSC.JSGlobalObject) !JSC.JSValue { } else if (strings.hasPrefixComptime(line, key_model_name)) { // If this is the model name, extract it and store on the current cpu const model_name = line[key_model_name.len..]; - const cpu = JSC.JSObject.getIndex(values, globalThis, cpu_index); + const cpu = try values.getIndex(globalThis, cpu_index); cpu.put(globalThis, JSC.ZigString.static("model"), JSC.ZigString.init(model_name).withEncoding().toJS(globalThis)); has_model_name = true; } } if (!has_model_name) { - const cpu = JSC.JSObject.getIndex(values, globalThis, cpu_index); + const cpu = try values.getIndex(globalThis, cpu_index); cpu.put(globalThis, JSC.ZigString.static("model"), JSC.ZigString.static("unknown").withEncoding().toJS(globalThis)); } } else |_| { // Initialize model name to "unknown" - var it = values.arrayIterator(globalThis); - while (it.next()) |cpu| { + var it = try values.arrayIterator(globalThis); + while (try it.next()) |cpu| { cpu.put(globalThis, JSC.ZigString.static("model"), JSC.ZigString.static("unknown").withEncoding().toJS(globalThis)); } } // Read /sys/devices/system/cpu/cpu{}/cpufreq/scaling_cur_freq to get current frequency (optional) for (0..num_cpus) |cpu_index| { - const cpu = JSC.JSObject.getIndex(values, globalThis, @truncate(cpu_index)); + const cpu = try values.getIndex(globalThis, @truncate(cpu_index)); var path_buf: [128]u8 = undefined; const path = try std.fmt.bufPrint(&path_buf, "/sys/devices/system/cpu/cpu{}/cpufreq/scaling_cur_freq", .{cpu_index}); @@ -632,9 +632,9 @@ fn networkInterfacesPosix(globalThis: *JSC.JSGlobalObject) bun.JSError!JSC.JSVal } // Does this entry already exist? - if (ret.get_unsafe(globalThis, interface_name)) |array| { + if (try ret.get(globalThis, interface_name)) |array| { // Add this interface entry to the existing array - const next_index = @as(u32, @intCast(array.getLength(globalThis))); + const next_index: u32 = @intCast(try array.getLength(globalThis)); array.putIndex(globalThis, next_index, interface); } else { // Add it as an array with this interface as an element @@ -746,9 +746,9 @@ fn networkInterfacesWindows(globalThis: *JSC.JSGlobalObject) bun.JSError!JSC.JSV // Does this entry already exist? const interface_name = bun.span(iface.name); - if (ret.get_unsafe(globalThis, interface_name)) |array| { + if (try ret.get(globalThis, interface_name)) |array| { // Add this interface entry to the existing array - const next_index = @as(u32, @intCast(array.getLength(globalThis))); + const next_index: u32 = @intCast(try array.getLength(globalThis)); array.putIndex(globalThis, next_index, interface); } else { // Add it as an array with this interface as an element diff --git a/src/bun.js/node/node_process.zig b/src/bun.js/node/node_process.zig index bb6c23d898..7647189c26 100644 --- a/src/bun.js/node/node_process.zig +++ b/src/bun.js/node/node_process.zig @@ -193,9 +193,7 @@ pub fn getExecArgv(global: *JSGlobalObject) callconv(.c) JSValue { return Bun__Process__getExecArgv(global); } -pub fn getCwd(globalObject: *JSC.JSGlobalObject) callconv(.C) JSC.JSValue { - return JSC.toJSHostValue(globalObject, getCwd_(globalObject)); -} +pub const getCwd = JSC.host_fn.wrap1(getCwd_); fn getCwd_(globalObject: *JSC.JSGlobalObject) bun.JSError!JSC.JSValue { var buf: bun.PathBuffer = undefined; switch (bun.api.node.path.getCwd(&buf)) { @@ -206,9 +204,7 @@ fn getCwd_(globalObject: *JSC.JSGlobalObject) bun.JSError!JSC.JSValue { } } -pub fn setCwd(globalObject: *JSC.JSGlobalObject, to: *JSC.ZigString) callconv(.C) JSC.JSValue { - return JSC.toJSHostValue(globalObject, setCwd_(globalObject, to)); -} +pub const setCwd = JSC.host_fn.wrap2(setCwd_); fn setCwd_(globalObject: *JSC.JSGlobalObject, to: *JSC.ZigString) bun.JSError!JSC.JSValue { if (to.len == 0) { return globalObject.throwInvalidArguments("Expected path to be a non-empty string", .{}); diff --git a/src/bun.js/node/types.zig b/src/bun.js/node/types.zig index 7df8e8d663..64ae53630c 100644 --- a/src/bun.js/node/types.zig +++ b/src/bun.js/node/types.zig @@ -800,11 +800,11 @@ pub const VectorArrayBuffer = struct { var bufferlist = std.ArrayList(bun.PlatformIOVec).init(allocator); var i: usize = 0; - const len = val.getLength(globalObject); + const len = try val.getLength(globalObject); bufferlist.ensureTotalCapacityPrecise(len) catch bun.outOfMemory(); while (i < len) { - const element = val.getIndex(globalObject, @as(u32, @truncate(i))); + const element = try val.getIndex(globalObject, @as(u32, @truncate(i))); if (!element.isCell()) { return globalObject.throwInvalidArguments("Expected ArrayBufferView[]", .{}); diff --git a/src/bun.js/node/util/parse_args.zig b/src/bun.js/node/util/parse_args.zig index be9f380498..83932a4518 100644 --- a/src/bun.js/node/util/parse_args.zig +++ b/src/bun.js/node/util/parse_args.zig @@ -24,7 +24,7 @@ const ArgsSlice = struct { start: u32, end: u32, - pub inline fn get(this: ArgsSlice, globalThis: *JSGlobalObject, i: u32) JSValue { + pub inline fn get(this: ArgsSlice, globalThis: *JSGlobalObject, i: u32) bun.JSError!JSValue { return this.array.getIndex(globalThis, this.start + i); } }; @@ -157,8 +157,8 @@ fn getDefaultArgs(globalThis: *JSGlobalObject) !ArgsSlice { const exec_argv = bun.api.node.process.getExecArgv(globalThis); const argv = bun.api.node.process.getArgv(globalThis); if (argv.isArray() and exec_argv.isArray()) { - var iter = exec_argv.arrayIterator(globalThis); - while (iter.next()) |item| { + var iter = try exec_argv.arrayIterator(globalThis); + while (try iter.next()) |item| { if (item.isString()) { const str = try item.toBunString(globalThis); defer str.deref(); @@ -166,12 +166,12 @@ fn getDefaultArgs(globalThis: *JSGlobalObject) !ArgsSlice { return .{ .array = argv, .start = 1, - .end = @intCast(argv.getLength(globalThis)), + .end = @intCast(try argv.getLength(globalThis)), }; } } } - return .{ .array = argv, .start = 2, .end = @intCast(argv.getLength(globalThis)) }; + return .{ .array = argv, .start = 2, .end = @intCast(try argv.getLength(globalThis)) }; } return .{ @@ -285,7 +285,7 @@ fn storeOption(globalThis: *JSGlobalObject, option_name: ValueRef, option_value: // values[long_option] starts out not present, // first value is added as new array [new_value], // subsequent values are pushed to existing array. - if (values.getOwn(globalThis, key)) |value_list| { + if (try values.getOwn(globalThis, key)) |value_list| { value_list.push(globalThis, new_value); } else { var value_list = try JSValue.createEmptyArray(globalThis, 1); @@ -316,10 +316,10 @@ fn parseOptionDefinitions(globalThis: *JSGlobalObject, options_obj: JSValue, opt try validators.validateObject(globalThis, obj, "options.{s}", .{option.long_name}, .{}); // type field is required - const option_type: JSValue = obj.getOwn(globalThis, "type") orelse .js_undefined; + const option_type: JSValue = try obj.getOwn(globalThis, "type") orelse .js_undefined; option.type = try validators.validateStringEnum(OptionValueType, globalThis, option_type, "options.{s}.type", .{option.long_name}); - if (obj.getOwn(globalThis, "short")) |short_option| { + if (try obj.getOwn(globalThis, "short")) |short_option| { try validators.validateString(globalThis, short_option, "options.{s}.short", .{option.long_name}); var short_option_str = try short_option.toBunString(globalThis); if (short_option_str.length() != 1) { @@ -329,13 +329,13 @@ fn parseOptionDefinitions(globalThis: *JSGlobalObject, options_obj: JSValue, opt option.short_name = short_option_str; } - if (obj.getOwn(globalThis, "multiple")) |multiple_value| { + if (try obj.getOwn(globalThis, "multiple")) |multiple_value| { if (!multiple_value.isUndefined()) { option.multiple = try validators.validateBoolean(globalThis, multiple_value, "options.{s}.multiple", .{option.long_name}); } } - if (obj.getOwn(globalThis, "default")) |default_value| { + if (try obj.getOwn(globalThis, "default")) |default_value| { if (!default_value.isUndefined()) { switch (option.type) { .string => { @@ -382,7 +382,7 @@ fn tokenizeArgs( const num_args: u32 = args.end - args.start; var index: u32 = 0; while (index < num_args) : (index += 1) { - const arg_ref: ValueRef = ValueRef{ .jsvalue = args.get(globalThis, index) }; + const arg_ref: ValueRef = ValueRef{ .jsvalue = try args.get(globalThis, index) }; const arg = arg_ref.asBunString(globalThis); const token_rawtype = classifyToken(arg, options); @@ -401,7 +401,7 @@ fn tokenizeArgs( while (index < num_args) : (index += 1) { try ctx.handleToken(.{ .positional = .{ .index = index, - .value = ValueRef{ .jsvalue = args.get(globalThis, index) }, + .value = ValueRef{ .jsvalue = try args.get(globalThis, index) }, } }); } break; // Finished processing args, leave while loop. @@ -417,7 +417,7 @@ fn tokenizeArgs( var has_inline_value = true; if (option_type == .string and index + 1 < num_args) { // e.g. '-f', "bar" - value = ValueRef{ .jsvalue = args.get(globalThis, index + 1) }; + value = ValueRef{ .jsvalue = try args.get(globalThis, index + 1) }; has_inline_value = false; log(" (lone_short_option consuming next token as value)", .{}); } @@ -451,7 +451,7 @@ fn tokenizeArgs( var has_inline_value = true; if (option_type == .string and index + 1 < num_args) { // e.g. '-f', "bar" - value = ValueRef{ .jsvalue = args.get(globalThis, index + 1) }; + value = ValueRef{ .jsvalue = try args.get(globalThis, index + 1) }; has_inline_value = false; log(" (short_option_group short option consuming next token as value)", .{}); } @@ -520,7 +520,7 @@ fn tokenizeArgs( var value: ?JSValue = null; if (option_type == .string and index + 1 < num_args and !negative) { // e.g. '--foo', "bar" - value = args.get(globalThis, index + 1); + value = try args.get(globalThis, index + 1); log(" (consuming next as value)", .{}); } @@ -665,23 +665,23 @@ pub fn parseArgs(globalThis: *JSGlobalObject, callframe: *JSC.CallFrame) bun.JSE const config = if (config_value.isUndefined()) null else config_value; // Phase 0.A: Get and validate type of input args - const config_args: JSValue = if (config) |c| c.getOwn(globalThis, "args") orelse .js_undefined else .js_undefined; + const config_args: JSValue = if (config) |c| try c.getOwn(globalThis, "args") orelse .js_undefined else .js_undefined; const args: ArgsSlice = if (!config_args.isUndefinedOrNull()) args: { try validators.validateArray(globalThis, config_args, "args", .{}, null); break :args .{ .array = config_args, .start = 0, - .end = @intCast(config_args.getLength(globalThis)), + .end = @intCast(try config_args.getLength(globalThis)), }; } else try getDefaultArgs(globalThis); // Phase 0.B: Parse and validate config - const config_strict: JSValue = (if (config) |c| c.getOwn(globalThis, "strict") else null) orelse JSValue.jsBoolean(true); - var config_allow_positionals: JSValue = if (config) |c| c.getOwn(globalThis, "allowPositionals") orelse JSC.jsBoolean(!config_strict.toBoolean()) else JSC.jsBoolean(!config_strict.toBoolean()); - const config_return_tokens: JSValue = (if (config) |c| c.getOwn(globalThis, "tokens") else null) orelse JSValue.jsBoolean(false); - const config_allow_negative: JSValue = if (config) |c| c.getOwn(globalThis, "allowNegative") orelse .false else .false; - const config_options: JSValue = if (config) |c| c.getOwn(globalThis, "options") orelse .js_undefined else .js_undefined; + const config_strict: JSValue = (if (config) |c| try c.getOwn(globalThis, "strict") else null) orelse JSValue.jsBoolean(true); + var config_allow_positionals: JSValue = if (config) |c| try c.getOwn(globalThis, "allowPositionals") orelse JSC.jsBoolean(!config_strict.toBoolean()) else JSC.jsBoolean(!config_strict.toBoolean()); + const config_return_tokens: JSValue = (if (config) |c| try c.getOwn(globalThis, "tokens") else null) orelse JSValue.jsBoolean(false); + const config_allow_negative: JSValue = if (config) |c| try c.getOwn(globalThis, "allowNegative") orelse .false else .false; + const config_options: JSValue = if (config) |c| try c.getOwn(globalThis, "options") orelse .js_undefined else .js_undefined; const strict = try validators.validateBoolean(globalThis, config_strict, "strict", .{}); @@ -739,7 +739,7 @@ pub fn parseArgs(globalThis: *JSGlobalObject, callframe: *JSC.CallFrame) bun.JSE for (option_defs.items) |option| { if (option.default_value) |default_value| { if (!option.long_name.eqlComptime("__proto__")) { - if (state.values.getOwn(globalThis, option.long_name) == null) { + if (try state.values.getOwn(globalThis, option.long_name) == null) { log(" Setting \"{}\" to default value", .{option.long_name}); state.values.putMayBeIndex(globalThis, &option.long_name, default_value); } diff --git a/src/bun.js/node/util/validators.zig b/src/bun.js/node/util/validators.zig index 1f3f412f45..9fed7e7f68 100644 --- a/src/bun.js/node/util/validators.zig +++ b/src/bun.js/node/util/validators.zig @@ -244,8 +244,8 @@ pub fn validateArray(globalThis: *JSGlobalObject, value: JSValue, comptime name_ pub fn validateStringArray(globalThis: *JSGlobalObject, value: JSValue, comptime name_fmt: string, name_args: anytype) bun.JSError!usize { try validateArray(globalThis, value, name_fmt, name_args, null); var i: usize = 0; - var iter = value.arrayIterator(globalThis); - while (iter.next()) |item| { + var iter = try value.arrayIterator(globalThis); + while (try iter.next()) |item| { if (!item.isString()) { return throwErrInvalidArgType(globalThis, name_fmt ++ "[{d}]", name_args ++ .{i}, "string", value); } @@ -257,8 +257,8 @@ pub fn validateStringArray(globalThis: *JSGlobalObject, value: JSValue, comptime pub fn validateBooleanArray(globalThis: *JSGlobalObject, value: JSValue, comptime name_fmt: string, name_args: anytype) bun.JSError!usize { try validateArray(globalThis, value, name_fmt, name_args, null); var i: usize = 0; - var iter = value.arrayIterator(globalThis); - while (iter.next()) |item| { + var iter = try value.arrayIterator(globalThis); + while (try iter.next()) |item| { if (!item.isBoolean()) { return throwErrInvalidArgType(globalThis, name_fmt ++ "[{d}]", name_args ++ .{i}, "boolean", value); } diff --git a/src/bun.js/test/expect.zig b/src/bun.js/test/expect.zig index a04e1fd0cd..64a44c91e8 100644 --- a/src/bun.js/test/expect.zig +++ b/src/bun.js/test/expect.zig @@ -513,7 +513,7 @@ pub const Expect = struct { const left = try this.getValue(globalThis, thisValue, "toBe", "expected"); const not = this.flags.not; - var pass = right.isSameValue(left, globalThis); + var pass = try right.isSameValue(left, globalThis); if (not) pass = !pass; if (pass) return .js_undefined; @@ -594,7 +594,7 @@ pub const Expect = struct { const not = this.flags.not; var pass = false; - const actual_length = value.getLengthIfPropertyExistsInternal(globalThis); + const actual_length = try value.getLengthIfPropertyExistsInternal(globalThis); if (actual_length == std.math.inf(f64)) { var fmt = JSC.ConsoleObject.Formatter{ .globalThis = globalThis, .quote_strings = true }; @@ -652,15 +652,15 @@ pub const Expect = struct { }; if (list_value.jsTypeLoose().isArrayLike()) { - var itr = list_value.arrayIterator(globalThis); - while (itr.next()) |item| { + var itr = try list_value.arrayIterator(globalThis); + while (try itr.next()) |item| { // Confusingly, jest-extended uses `deepEqual`, instead of `toBe` if (try item.jestDeepEquals(expected, globalThis)) { pass = true; break; } } - } else if (list_value.isIterable(globalThis)) { + } else if (try list_value.isIterable(globalThis)) { var expected_entry = ExpectedEntry{ .globalThis = globalThis, .expected = expected, @@ -736,9 +736,9 @@ pub const Expect = struct { }; if (value.jsTypeLoose().isArrayLike()) { - var itr = value.arrayIterator(globalThis); - while (itr.next()) |item| { - if (item.isSameValue(expected, globalThis)) { + var itr = try value.arrayIterator(globalThis); + while (try itr.next()) |item| { + if (try item.isSameValue(expected, globalThis)) { pass = true; break; } @@ -756,7 +756,7 @@ pub const Expect = struct { } else if (value_string.len == 0 and expected_string.len == 0) { // edge case two empty strings are true pass = true; } - } else if (value.isIterable(globalThis)) { + } else if (try value.isIterable(globalThis)) { var expected_entry = ExpectedEntry{ .globalThis = globalThis, .expected = expected, @@ -770,7 +770,7 @@ pub const Expect = struct { item: JSValue, ) callconv(.C) void { const entry = bun.cast(*ExpectedEntry, entry_.?); - if (item.isSameValue(entry.expected, entry.globalThis)) { + if (item.isSameValue(entry.expected, entry.globalThis) catch return) { entry.pass.* = true; // TODO(perf): break out of the `forEach` when a match is found } @@ -828,11 +828,7 @@ pub const Expect = struct { return globalThis.throwInvalidArguments("Expected value must be an object\nReceived: {}", .{value.toFmt(&formatter)}); } - var pass = value.hasOwnPropertyValue(globalThis, expected); - - if (globalThis.hasException()) { - return .zero; - } + var pass = try value.hasOwnPropertyValue(globalThis, expected); if (not) pass = !pass; if (pass) return thisValue; @@ -880,7 +876,7 @@ pub const Expect = struct { const not = this.flags.not; var pass = brk: { - const count = expected.getLength(globalThis); + const count = try expected.getLength(globalThis); // jest-extended checks for truthiness before calling hasOwnProperty // https://github.com/jest-community/jest-extended/blob/711fdcc54d68c2b2c1992c7cfbdf0d0bd6be0f4d/src/matchers/toContainKeys.js#L1-L6 @@ -889,9 +885,9 @@ pub const Expect = struct { var i: u32 = 0; while (i < count) : (i += 1) { - const key = expected.getIndex(globalThis, i); + const key = try expected.getIndex(globalThis, i); - if (!value.hasOwnPropertyValue(globalThis, key)) { + if (!try value.hasOwnPropertyValue(globalThis, key)) { break :brk false; } } @@ -899,10 +895,6 @@ pub const Expect = struct { break :brk true; }; - if (globalThis.hasException()) { - return .zero; - } - if (not) pass = !pass; if (pass) return thisValue; @@ -951,16 +943,16 @@ pub const Expect = struct { const not = this.flags.not; var pass = false; - const count = expected.getLength(globalObject); + const count = try expected.getLength(globalObject); - var keys = value.keys(globalObject); - if (keys.getLength(globalObject) == count) { - var itr = keys.arrayIterator(globalObject); + var keys = try value.keys(globalObject); + if (try keys.getLength(globalObject) == count) { + var itr = try keys.arrayIterator(globalObject); outer: { - while (itr.next()) |item| { + while (try itr.next()) |item| { var i: u32 = 0; while (i < count) : (i += 1) { - const key = expected.getIndex(globalObject, i); + const key = try expected.getIndex(globalObject, i); if (try item.jestDeepEquals(key, globalObject)) break; } else break :outer; } @@ -1016,23 +1008,19 @@ pub const Expect = struct { const not = this.flags.not; var pass = false; - const count = expected.getLength(globalThis); + const count = try expected.getLength(globalThis); var i: u32 = 0; while (i < count) : (i += 1) { - const key = expected.getIndex(globalThis, i); + const key = try expected.getIndex(globalThis, i); - if (value.hasOwnPropertyValue(globalThis, key)) { + if (try value.hasOwnPropertyValue(globalThis, key)) { pass = true; break; } } - if (globalThis.hasException()) { - return .zero; - } - if (not) pass = !pass; if (pass) return thisValue; @@ -1078,9 +1066,9 @@ pub const Expect = struct { var pass = false; if (!value.isUndefinedOrNull()) { - const values = value.values(globalObject); - var itr = values.arrayIterator(globalObject); - while (itr.next()) |item| { + const values = try value.values(globalObject); + var itr = try values.arrayIterator(globalObject); + while (try itr.next()) |item| { if (try item.jestDeepEquals(expected, globalObject)) { pass = true; break; @@ -1136,14 +1124,14 @@ pub const Expect = struct { var pass = true; if (!value.isUndefinedOrNull()) { - const values = value.values(globalObject); - var itr = expected.arrayIterator(globalObject); - const count = values.getLength(globalObject); + const values = try value.values(globalObject); + var itr = try expected.arrayIterator(globalObject); + const count = try values.getLength(globalObject); - while (itr.next()) |item| { + while (try itr.next()) |item| { var i: u32 = 0; while (i < count) : (i += 1) { - const key = values.getIndex(globalObject, i); + const key = try values.getIndex(globalObject, i); if (try key.jestDeepEquals(item, globalObject)) break; } else { pass = false; @@ -1200,16 +1188,16 @@ pub const Expect = struct { var pass = false; if (!value.isUndefinedOrNull()) { - var values = value.values(globalObject); - var itr = expected.arrayIterator(globalObject); - const count = values.getLength(globalObject); - const expectedLength = expected.getLength(globalObject); + var values = try value.values(globalObject); + var itr = try expected.arrayIterator(globalObject); + const count = try values.getLength(globalObject); + const expectedLength = try expected.getLength(globalObject); if (count == expectedLength) { - while (itr.next()) |item| { + while (try itr.next()) |item| { var i: u32 = 0; while (i < count) : (i += 1) { - const key = values.getIndex(globalObject, i); + const key = try values.getIndex(globalObject, i); if (try key.jestDeepEquals(item, globalObject)) { pass = true; break; @@ -1270,14 +1258,14 @@ pub const Expect = struct { var pass = false; if (!value.isUndefinedOrNull()) { - var values = value.values(globalObject); - var itr = expected.arrayIterator(globalObject); - const count = values.getLength(globalObject); + var values = try value.values(globalObject); + var itr = try expected.arrayIterator(globalObject); + const count = try values.getLength(globalObject); - outer: while (itr.next()) |item| { + outer: while (try itr.next()) |item| { var i: u32 = 0; while (i < count) : (i += 1) { - const key = values.getIndex(globalObject, i); + const key = try values.getIndex(globalObject, i); if (try key.jestDeepEquals(item, globalObject)) { pass = true; break :outer; @@ -1340,8 +1328,8 @@ pub const Expect = struct { const expected_type = expected.jsType(); if (value_type.isArrayLike()) { - var itr = value.arrayIterator(globalThis); - while (itr.next()) |item| { + var itr = try value.arrayIterator(globalThis); + while (try itr.next()) |item| { if (try item.jestDeepEquals(expected, globalThis)) { pass = true; break; @@ -1366,7 +1354,7 @@ pub const Expect = struct { else strings.indexOf(value_string.slice(), expected_string.slice()) != null; } - } else if (value.isIterable(globalThis)) { + } else if (try value.isIterable(globalThis)) { var expected_entry = ExpectedEntry{ .globalThis = globalThis, .expected = expected, @@ -1685,7 +1673,7 @@ pub const Expect = struct { const value: JSValue = try this.getValue(globalThis, thisValue, "toHaveProperty", "path, value"); - if (!expected_property_path.isString() and !expected_property_path.isIterable(globalThis)) { + if (!expected_property_path.isString() and !try expected_property_path.isIterable(globalThis)) { return globalThis.throw("Expected path must be a string or an array", .{}); } @@ -1697,7 +1685,7 @@ pub const Expect = struct { var received_property: JSValue = .zero; if (pass) { - received_property = value.getIfPropertyExistsFromPath(globalThis, expected_property_path); + received_property = try value.getIfPropertyExistsFromPath(globalThis, expected_property_path); pass = received_property != .zero; } @@ -2290,7 +2278,7 @@ pub const Expect = struct { if (globalThis.hasException()) return .zero; // no partial match for this case - if (!expected_message.isSameValue(received_message, globalThis)) return .js_undefined; + if (!try expected_message.isSameValue(received_message, globalThis)) return .js_undefined; return this.throw(globalThis, signature, "\n\nExpected message: not {any}\n", .{expected_message.toFmt(&formatter)}); } @@ -2397,7 +2385,7 @@ pub const Expect = struct { const signature = comptime getSignature("toThrow", "expected", false); if (_received_message) |received_message| { - if (received_message.isSameValue(expected_message, globalThis)) return .js_undefined; + if (try received_message.isSameValue(expected_message, globalThis)) return .js_undefined; } // error: message from received error does not match expected error message. @@ -2916,7 +2904,7 @@ pub const Expect = struct { const prop_matchers = _prop_matchers; - if (!value.jestDeepMatch(prop_matchers, globalThis, true)) { + if (!try value.jestDeepMatch(prop_matchers, globalThis, true)) { // TODO: print diff with properties from propertyMatchers const signature = comptime getSignature(fn_name, "propertyMatchers", false); const fmt = signature ++ "\n\nExpected propertyMatchers to match properties from received object" ++ @@ -2986,11 +2974,11 @@ pub const Expect = struct { var formatter = JSC.ConsoleObject.Formatter{ .globalThis = globalThis, .quote_strings = true }; defer formatter.deinit(); - const actual_length = value.getLengthIfPropertyExistsInternal(globalThis); + const actual_length = try value.getLengthIfPropertyExistsInternal(globalThis); if (actual_length == std.math.inf(f64)) { if (value.jsTypeLoose().isObject()) { - if (value.isIterable(globalThis)) { + if (try value.isIterable(globalThis)) { var any_properties_in_iterator = false; value.forEach(globalThis, &any_properties_in_iterator, struct { pub fn anythingInIterator( @@ -3060,7 +3048,7 @@ pub const Expect = struct { incrementExpectCallCounter(); const not = this.flags.not; - var pass = value.isObjectEmpty(globalThis); + var pass = try value.isObjectEmpty(globalThis); if (not) pass = !pass; if (pass) return thisValue; @@ -3153,7 +3141,7 @@ pub const Expect = struct { incrementExpectCallCounter(); const not = this.flags.not; - var pass = value.jsType().isArray() and @as(i32, @intCast(value.getLength(globalThis))) == size.toInt32(); + var pass = value.jsType().isArray() and @as(i32, @intCast(try value.getLength(globalThis))) == size.toInt32(); if (not) pass = !pass; if (pass) return .js_undefined; @@ -4198,7 +4186,8 @@ pub const Expect = struct { return globalThis.throw("Expected value must be a mock function: {}", .{value}); } - var pass = calls.getLength(globalThis) > 0; + const calls_length = try calls.getLength(globalThis); + var pass = calls_length > 0; const not = this.flags.not; if (not) pass = !pass; @@ -4207,11 +4196,11 @@ pub const Expect = struct { // handle failure if (not) { const signature = comptime getSignature("toHaveBeenCalled", "", true); - return this.throw(globalThis, signature, "\n\n" ++ "Expected number of calls: 0\n" ++ "Received number of calls: {any}\n", .{calls.getLength(globalThis)}); + return this.throw(globalThis, signature, "\n\n" ++ "Expected number of calls: 0\n" ++ "Received number of calls: {any}\n", .{calls_length}); } const signature = comptime getSignature("toHaveBeenCalled", "", false); - return this.throw(globalThis, signature, "\n\n" ++ "Expected number of calls: \\>= 1\n" ++ "Received number of calls: {any}\n", .{calls.getLength(globalThis)}); + return this.throw(globalThis, signature, "\n\n" ++ "Expected number of calls: \\>= 1\n" ++ "Received number of calls: {any}\n", .{calls_length}); } pub fn toHaveBeenCalledOnce(this: *Expect, globalThis: *JSGlobalObject, callframe: *CallFrame) bun.JSError!JSValue { @@ -4229,7 +4218,8 @@ pub const Expect = struct { return globalThis.throw("Expected value must be a mock function: {}", .{value}); } - var pass = @as(i32, @intCast(calls.getLength(globalThis))) == 1; + const calls_length = try calls.getLength(globalThis); + var pass = calls_length == 1; const not = this.flags.not; if (not) pass = !pass; @@ -4238,11 +4228,11 @@ pub const Expect = struct { // handle failure if (not) { const signature = comptime getSignature("toHaveBeenCalledOnce", "expected", true); - return this.throw(globalThis, signature, "\n\n" ++ "Expected number of calls: not 1\n" ++ "Received number of calls: {d}\n", .{calls.getLength(globalThis)}); + return this.throw(globalThis, signature, "\n\n" ++ "Expected number of calls: not 1\n" ++ "Received number of calls: {d}\n", .{calls_length}); } const signature = comptime getSignature("toHaveBeenCalledOnce", "expected", false); - return this.throw(globalThis, signature, "\n\n" ++ "Expected number of calls: 1\n" ++ "Received number of calls: {d}\n", .{calls.getLength(globalThis)}); + return this.throw(globalThis, signature, "\n\n" ++ "Expected number of calls: 1\n" ++ "Received number of calls: {d}\n", .{calls_length}); } pub fn toHaveBeenCalledTimes(this: *Expect, globalThis: *JSGlobalObject, callframe: *CallFrame) bun.JSError!JSValue { @@ -4268,7 +4258,7 @@ pub const Expect = struct { const times = arguments[0].coerce(i32, globalThis); - var pass = @as(i32, @intCast(calls.getLength(globalThis))) == times; + var pass = @as(i32, @intCast(try calls.getLength(globalThis))) == times; const not = this.flags.not; if (not) pass = !pass; @@ -4320,7 +4310,7 @@ pub const Expect = struct { const property_matchers = args[0]; - var pass = received_object.jestDeepMatch(property_matchers, globalThis, true); + var pass = try received_object.jestDeepMatch(property_matchers, globalThis, true); if (not) pass = !pass; if (pass) return .js_undefined; @@ -4360,20 +4350,20 @@ pub const Expect = struct { var pass = false; - if (calls.getLength(globalThis) > 0) { - var itr = calls.arrayIterator(globalThis); - while (itr.next()) |callItem| { + if (try calls.getLength(globalThis) > 0) { + var itr = try calls.arrayIterator(globalThis); + while (try itr.next()) |callItem| { if (callItem == .zero or !callItem.jsType().isArray()) { return globalThis.throw("Expected value must be a mock function with calls: {}", .{value}); } - if (callItem.getLength(globalThis) != arguments.len) { + if (try callItem.getLength(globalThis) != arguments.len) { continue; } - var callItr = callItem.arrayIterator(globalThis); + var callItr = try callItem.arrayIterator(globalThis); var match = true; - while (callItr.next()) |callArg| { + while (try callItr.next()) |callArg| { if (!try callArg.jestDeepEquals(arguments[callItr.i - 1], globalThis)) { match = false; break; @@ -4417,23 +4407,23 @@ pub const Expect = struct { return globalThis.throw("Expected value must be a mock function: {}", .{value}); } - const totalCalls = @as(u32, @intCast(calls.getLength(globalThis))); + const totalCalls: u32 = @truncate(try calls.getLength(globalThis)); var lastCallValue: JSValue = .zero; var pass = totalCalls > 0; if (pass) { - lastCallValue = calls.getIndex(globalThis, totalCalls - 1); + lastCallValue = try calls.getIndex(globalThis, totalCalls - 1); - if (lastCallValue == .zero or !lastCallValue.jsType().isArray()) { + if (!lastCallValue.jsType().isArray()) { return globalThis.throw("Expected value must be a mock function with calls: {}", .{value}); } - if (lastCallValue.getLength(globalThis) != arguments.len) { + if (try lastCallValue.getLength(globalThis) != arguments.len) { pass = false; } else { - var itr = lastCallValue.arrayIterator(globalThis); - while (itr.next()) |callArg| { + var itr = try lastCallValue.arrayIterator(globalThis); + while (try itr.next()) |callArg| { if (!try callArg.jestDeepEquals(arguments[itr.i - 1], globalThis)) { pass = false; break; @@ -4481,23 +4471,23 @@ pub const Expect = struct { return globalThis.throwInvalidArguments("toHaveBeenNthCalledWith() requires a positive integer argument", .{}); } - const totalCalls = calls.getLength(globalThis); + const totalCalls = try calls.getLength(globalThis); var nthCallValue: JSValue = .zero; var pass = totalCalls >= nthCallNum; if (pass) { - nthCallValue = calls.getIndex(globalThis, @as(u32, @intCast(nthCallNum)) - 1); + nthCallValue = try calls.getIndex(globalThis, @as(u32, @intCast(nthCallNum)) - 1); - if (nthCallValue == .zero or !nthCallValue.jsType().isArray()) { + if (!nthCallValue.jsType().isArray()) { return globalThis.throw("Expected value must be a mock function with calls: {}", .{value}); } - if (nthCallValue.getLength(globalThis) != (arguments.len - 1)) { + if (try nthCallValue.getLength(globalThis) != (arguments.len - 1)) { pass = false; } else { - var itr = nthCallValue.arrayIterator(globalThis); - while (itr.next()) |callArg| { + var itr = try nthCallValue.arrayIterator(globalThis); + while (try itr.next()) |callArg| { if (!try callArg.jestDeepEquals(arguments[itr.i], globalThis)) { pass = false; break; @@ -4567,7 +4557,7 @@ pub const Expect = struct { index, ); - const total_count = returns.getLength(globalThis); + const total_count = try returns.getLength(globalThis); const return_status: ReturnStatus = brk: { // Returns is an array of: @@ -5445,7 +5435,7 @@ pub const ExpectCustomAsymmetricMatcher = struct { captured_args.ensureStillAlive(); // prepare the args array as `[received, ...captured_args]` - const args_count = captured_args.getLength(globalThis); + const args_count = captured_args.getLength(globalThis) catch return false; var allocator = std.heap.stackFallback(8 * @sizeOf(JSValue), globalThis.allocator()); var matcher_args = std.ArrayList(JSValue).initCapacity(allocator.get(), args_count + 1) catch { globalThis.throwOutOfMemory() catch {}; @@ -5453,7 +5443,7 @@ pub const ExpectCustomAsymmetricMatcher = struct { }; matcher_args.appendAssumeCapacity(received); for (0..args_count) |i| { - matcher_args.appendAssumeCapacity(captured_args.getIndex(globalThis, @truncate(i))); + matcher_args.appendAssumeCapacity(captured_args.getIndex(globalThis, @truncate(i)) catch return false); } return Expect.executeCustomMatcher(globalThis, matcher_name, matcher_fn, matcher_args.items, this.flags, true) catch false; @@ -5466,34 +5456,30 @@ pub const ExpectCustomAsymmetricMatcher = struct { return JSValue.jsBoolean(matched); } + fn maybeClear(comptime dontThrow: bool, globalThis: *JSGlobalObject, err: bun.JSError) bun.JSError!bool { + if (dontThrow) { + globalThis.clearException(); + return false; + } + return err; + } + /// Calls a custom implementation (if provided) to stringify this asymmetric matcher, and returns true if it was provided and it succeed pub fn customPrint(_: *ExpectCustomAsymmetricMatcher, thisValue: JSValue, globalThis: *JSGlobalObject, writer: anytype, comptime dontThrow: bool) !bool { const matcher_fn: JSValue = js.matcherFnGetCached(thisValue) orelse return false; - if (matcher_fn.get_unsafe(globalThis, "toAsymmetricMatcher")) |fn_value| { + if (matcher_fn.get(globalThis, "toAsymmetricMatcher") catch |e| return maybeClear(dontThrow, globalThis, e)) |fn_value| { if (fn_value.jsType().isFunction()) { const captured_args: JSValue = js.capturedArgsGetCached(thisValue) orelse return false; var stack_fallback = std.heap.stackFallback(256, globalThis.allocator()); - const args_len = captured_args.getLength(globalThis); + const args_len = captured_args.getLength(globalThis) catch |e| return maybeClear(dontThrow, globalThis, e); var args = try std.ArrayList(JSValue).initCapacity(stack_fallback.get(), args_len); - var iter = captured_args.arrayIterator(globalThis); - while (iter.next()) |arg| { + var iter = captured_args.arrayIterator(globalThis) catch |e| return maybeClear(dontThrow, globalThis, e); + while (iter.next() catch |e| return maybeClear(dontThrow, globalThis, e)) |arg| { args.appendAssumeCapacity(arg); } - const result = matcher_fn.call(globalThis, thisValue, args.items) catch |err| { - if (dontThrow) { - globalThis.clearException(); - return false; - } - return err; - }; - try writer.print("{}", .{result.toBunString(globalThis) catch { - if (dontThrow) { - globalThis.clearException(); - return false; - } - return error.JSError; - }}); + const result = matcher_fn.call(globalThis, thisValue, args.items) catch |e| return maybeClear(dontThrow, globalThis, e); + try writer.print("{}", .{result.toBunString(globalThis) catch |e| return maybeClear(dontThrow, globalThis, e)}); } } return false; diff --git a/src/bun.js/test/jest.zig b/src/bun.js/test/jest.zig index 95c5e6d358..b541296ca2 100644 --- a/src/bun.js/test/jest.zig +++ b/src/bun.js/test/jest.zig @@ -279,7 +279,7 @@ pub const Jest = struct { return globalThis.throwInvalidArgumentType(name, "callback", "function"); } - if (function.getLength(globalThis) > 0) { + if (try function.getLength(globalThis) > 0) { return globalThis.throw("done() callback is not implemented in global hooks yet. Please make your function take no arguments", .{}); } @@ -735,7 +735,7 @@ pub const TestScope = struct { switch (promise.status(vm.global.vm())) { .rejected => { if (!promise.isHandled(vm.global.vm()) and this.tag != .fail) { - _ = vm.unhandledRejection(vm.global, promise.result(vm.global.vm()), promise.asValue()); + vm.unhandledRejection(vm.global, promise.result(vm.global.vm()), promise.asValue()); } return switch (this.tag) { @@ -913,6 +913,7 @@ pub const DescribeScope = struct { pub const beforeAll = createCallback(.beforeAll); pub const beforeEach = createCallback(.beforeEach); + // TODO this should return JSError pub fn execCallback(this: *DescribeScope, globalObject: *JSGlobalObject, comptime hook: LifecycleHook) ?JSValue { var hooks = &@field(this, @tagName(hook) ++ "s"); defer { @@ -933,7 +934,7 @@ pub const DescribeScope = struct { } const vm = VirtualMachine.get(); - var result: JSValue = switch (cb.getLength(globalObject)) { + var result: JSValue = switch (cb.getLength(globalObject) catch |e| return globalObject.takeException(e)) { // TODO is this right? 0 => callJSFunctionForTestRunner(vm, globalObject, cb, &.{}), else => brk: { this.done = false; @@ -1095,7 +1096,7 @@ pub const DescribeScope = struct { switch (prom.status(globalObject.vm())) { .fulfilled => {}, else => { - _ = globalObject.bunVM().unhandledRejection(globalObject, prom.result(globalObject.vm()), prom.asValue()); + globalObject.bunVM().unhandledRejection(globalObject, prom.result(globalObject.vm()), prom.asValue()); return .js_undefined; }, } @@ -1834,7 +1835,7 @@ inline fn createScope( function.protect(); } - const func_params_length = function.getLength(globalThis); + const func_params_length = try function.getLength(globalThis); var arg_size: usize = 0; var has_callback = false; if (func_params_length > 0) { @@ -2062,16 +2063,16 @@ fn eachBind(globalThis: *JSGlobalObject, callframe: *CallFrame) bun.JSError!JSVa return .js_undefined; } - var iter = array.arrayIterator(globalThis); + var iter = try array.arrayIterator(globalThis); var test_idx: usize = 0; - while (iter.next()) |item| { - const func_params_length = function.getLength(globalThis); + while (try iter.next()) |item| { + const func_params_length = try function.getLength(globalThis); const item_is_array = !item.isEmptyOrUndefinedOrNull() and item.jsType().isArray(); var arg_size: usize = 1; if (item_is_array) { - arg_size = item.getLength(globalThis); + arg_size = try item.getLength(globalThis); } // add room for callback function @@ -2085,8 +2086,8 @@ fn eachBind(globalThis: *JSGlobalObject, callframe: *CallFrame) bun.JSError!JSVa if (item_is_array) { // Spread array as args - var item_iter = item.arrayIterator(globalThis); - while (item_iter.next()) |array_item| { + var item_iter = try item.arrayIterator(globalThis); + while (try item_iter.next()) |array_item| { if (array_item == .zero) { allocator.free(function_args); break; @@ -2206,7 +2207,7 @@ fn callJSFunctionForTestRunner(vm: *JSC.VirtualMachine, globalObject: *JSGlobalO vm.eventLoop().enter(); defer vm.eventLoop().exit(); - globalObject.clearTerminationException(); + globalObject.clearTerminationException(); // TODO this is sus return function.call(globalObject, .js_undefined, args) catch |err| globalObject.takeException(err); } diff --git a/src/bun.js/test/pretty_format.zig b/src/bun.js/test/pretty_format.zig index daa4c316f1..e58ee6ab40 100644 --- a/src/bun.js/test/pretty_format.zig +++ b/src/bun.js/test/pretty_format.zig @@ -107,7 +107,7 @@ pub const JestPrettyFormat = struct { .globalThis = global, .quote_strings = options.quote_strings, }; - const tag = JestPrettyFormat.Formatter.Tag.get(vals[0], global); + const tag = try JestPrettyFormat.Formatter.Tag.get(vals[0], global); var unbuffered_writer = if (comptime Writer != RawWriter) writer.context.unbuffered_writer.context.writer() @@ -197,7 +197,7 @@ pub const JestPrettyFormat = struct { } any = true; - tag = JestPrettyFormat.Formatter.Tag.get(this_value, global); + tag = try JestPrettyFormat.Formatter.Tag.get(this_value, global); if (tag.tag == .String and fmt.remaining_values.len > 0) { tag.tag = .StringPossiblyFormatted; } @@ -219,7 +219,7 @@ pub const JestPrettyFormat = struct { _ = writer.write(" ") catch 0; } any = true; - tag = JestPrettyFormat.Formatter.Tag.get(this_value, global); + tag = try JestPrettyFormat.Formatter.Tag.get(this_value, global); if (tag.tag == .String and fmt.remaining_values.len > 0) { tag.tag = .StringPossiblyFormatted; } @@ -358,12 +358,12 @@ pub const JestPrettyFormat = struct { cell: JSValue.JSType = .Cell, }; - pub fn get(value: JSValue, globalThis: *JSGlobalObject) Result { - switch (@intFromEnum(value)) { - 0, 0xa => return Result{ + pub fn get(value: JSValue, globalThis: *JSGlobalObject) bun.JSError!Result { + switch (value) { + .zero, .js_undefined => return Result{ .tag = .Undefined, }, - 0x2 => return Result{ + .null => return Result{ .tag = .Null, }, else => {}, @@ -439,11 +439,11 @@ pub const JestPrettyFormat = struct { // Is this a react element? if (js_type.isObject() and js_type != .ProxyObject) { - if (value.getOwnTruthy(globalThis, "$$typeof")) |typeof_symbol| { + if (try value.getOwnTruthy(globalThis, "$$typeof")) |typeof_symbol| { var reactElement = ZigString.init("react.element"); var react_fragment = ZigString.init("react.fragment"); - if (JSValue.isSameValue(typeof_symbol, JSValue.symbolFor(globalThis, &reactElement), globalThis) or JSValue.isSameValue(typeof_symbol, JSValue.symbolFor(globalThis, &react_fragment), globalThis)) { + if (try typeof_symbol.isSameValue(.symbolFor(globalThis, &reactElement), globalThis) or try typeof_symbol.isSameValue(.symbolFor(globalThis, &react_fragment), globalThis)) { return .{ .tag = .JSX, .cell = js_type }; } } @@ -576,7 +576,7 @@ pub const JestPrettyFormat = struct { Tag.Integer => this.printAs(Tag.Integer, Writer, writer_, next_value, next_value.jsType(), enable_ansi_colors) catch return, // undefined is overloaded to mean the '%o" field - Tag.Undefined => this.format(Tag.get(next_value, globalThis), Writer, writer_, next_value, globalThis, enable_ansi_colors) catch return, + Tag.Undefined => this.format(Tag.get(next_value, globalThis) catch return, Writer, writer_, next_value, globalThis, enable_ansi_colors) catch return, else => unreachable, } @@ -677,10 +677,10 @@ pub const JestPrettyFormat = struct { pub fn forEach(_: *JSC.VM, globalObject: *JSGlobalObject, ctx: ?*anyopaque, nextValue: JSValue) callconv(.C) void { var this: *@This() = bun.cast(*@This(), ctx orelse return); if (this.formatter.failed) return; - const key = JSC.JSObject.getIndex(nextValue, globalObject, 0); - const value = JSC.JSObject.getIndex(nextValue, globalObject, 1); + const key = JSC.JSObject.getIndex(nextValue, globalObject, 0) catch return; + const value = JSC.JSObject.getIndex(nextValue, globalObject, 1) catch return; this.formatter.writeIndent(Writer, this.writer) catch return; - const key_tag = Tag.get(key, globalObject); + const key_tag = Tag.get(key, globalObject) catch return; this.formatter.format( key_tag, @@ -691,7 +691,7 @@ pub const JestPrettyFormat = struct { enable_ansi_colors, ) catch return; this.writer.writeAll(" => ") catch return; - const value_tag = Tag.get(value, globalObject); + const value_tag = Tag.get(value, globalObject) catch return; this.formatter.format( value_tag, Writer, @@ -714,7 +714,7 @@ pub const JestPrettyFormat = struct { var this: *@This() = bun.cast(*@This(), ctx orelse return); if (this.formatter.failed) return; this.formatter.writeIndent(Writer, this.writer) catch return; - const key_tag = Tag.get(nextValue, globalObject); + const key_tag = Tag.get(nextValue, globalObject) catch return; this.formatter.format( key_tag, Writer, @@ -794,7 +794,7 @@ pub const JestPrettyFormat = struct { .failed = false, }; - const tag = Tag.get(value, globalThis); + const tag = Tag.get(value, globalThis) catch return; if (tag.cell.isHidden()) return; if (ctx.i == 0) { @@ -1137,7 +1137,7 @@ pub const JestPrettyFormat = struct { } }, .Array => { - const len = @as(u32, @truncate(value.getLength(this.globalThis))); + const len: u32 = @truncate(try value.getLength(this.globalThis)); if (len == 0) { writer.writeAll("[]"); this.addForNewLine(2); @@ -1163,7 +1163,7 @@ pub const JestPrettyFormat = struct { { const element = JSValue.fromRef(CAPI.JSObjectGetPropertyAtIndex(this.globalThis, ref, 0, null)); - const tag = Tag.get(element, this.globalThis); + const tag = try Tag.get(element, this.globalThis); was_good_time = was_good_time or !tag.tag.isPrimitive() or this.goodTimeForANewLine(); @@ -1194,7 +1194,7 @@ pub const JestPrettyFormat = struct { this.writeIndent(Writer, writer_) catch unreachable; const element = JSValue.fromRef(CAPI.JSObjectGetPropertyAtIndex(this.globalThis, ref, i, null)); - const tag = Tag.get(element, this.globalThis); + const tag = try Tag.get(element, this.globalThis); try this.format(tag, Writer, writer_, element, this.globalThis, enable_ansi_colors); @@ -1260,7 +1260,7 @@ pub const JestPrettyFormat = struct { }; return; } else if (value.as(JSC.DOMFormData) != null) { - const toJSONFunction = value.get_unsafe(this.globalThis, "toJSON").?; + const toJSONFunction = (try value.get(this.globalThis, "toJSON")).?; this.addForNewLine("FormData (entries) ".len); writer.writeAll(comptime Output.prettyFmt("FormData (entries) ", enable_ansi_colors)); @@ -1341,7 +1341,7 @@ pub const JestPrettyFormat = struct { writer.writeAll(comptime Output.prettyFmt("" ++ fmt ++ "", enable_ansi_colors)); }, .Map => { - const length_value = value.get_unsafe(this.globalThis, "size") orelse JSC.JSValue.jsNumberFromInt32(0); + const length_value = try value.get(this.globalThis, "size") orelse JSC.JSValue.jsNumberFromInt32(0); const length = length_value.toInt32(); const prev_quote_strings = this.quote_strings; @@ -1369,7 +1369,7 @@ pub const JestPrettyFormat = struct { writer.writeAll("\n"); }, .Set => { - const length_value = value.get_unsafe(this.globalThis, "size") orelse JSC.JSValue.jsNumberFromInt32(0); + const length_value = try value.get(this.globalThis, "size") orelse JSC.JSValue.jsNumberFromInt32(0); const length = length_value.toInt32(); const prev_quote_strings = this.quote_strings; @@ -1421,7 +1421,7 @@ pub const JestPrettyFormat = struct { }, .Event => { const event_type_value: JSValue = brk: { - const value_: JSValue = value.get_unsafe(this.globalThis, "type") orelse break :brk .js_undefined; + const value_: JSValue = try value.get(this.globalThis, "type") orelse break :brk .js_undefined; if (value_.isString()) { break :brk value_; } @@ -1465,7 +1465,7 @@ pub const JestPrettyFormat = struct { .{}, ); - const tag = Tag.get(message_value, this.globalThis); + const tag = try Tag.get(message_value, this.globalThis); try this.format(tag, Writer, writer_, message_value, this.globalThis, enable_ansi_colors); writer.writeAll(", \n"); } @@ -1479,7 +1479,7 @@ pub const JestPrettyFormat = struct { .{}, ); const data: JSValue = (try value.fastGet(this.globalThis, .data)) orelse .js_undefined; - const tag = Tag.get(data, this.globalThis); + const tag = try Tag.get(data, this.globalThis); if (tag.cell.isStringLike()) { try this.format(tag, Writer, writer_, data, this.globalThis, enable_ansi_colors); @@ -1496,7 +1496,7 @@ pub const JestPrettyFormat = struct { .{}, ); - const tag = Tag.get(data, this.globalThis); + const tag = try Tag.get(data, this.globalThis); try this.format(tag, Writer, writer_, data, this.globalThis, enable_ansi_colors); writer.writeAll("\n"); } @@ -1521,8 +1521,8 @@ pub const JestPrettyFormat = struct { defer if (tag_name_slice.isAllocated()) tag_name_slice.deinit(); - if (value.get_unsafe(this.globalThis, "type")) |type_value| { - const _tag = Tag.get(type_value, this.globalThis); + if (try value.get(this.globalThis, "type")) |type_value| { + const _tag = try Tag.get(type_value, this.globalThis); if (_tag.cell == .Symbol) {} else if (_tag.cell.isStringLike()) { try type_value.toZigString(&tag_name_str, this.globalThis); @@ -1551,7 +1551,7 @@ pub const JestPrettyFormat = struct { writer.writeAll(tag_name_slice.slice()); if (enable_ansi_colors) writer.writeAll(comptime Output.prettyFmt("", enable_ansi_colors)); - if (value.get_unsafe(this.globalThis, "key")) |key_value| { + if (try value.get(this.globalThis, "key")) |key_value| { if (!key_value.isUndefinedOrNull()) { if (needs_space) writer.writeAll(" key=") @@ -1562,13 +1562,13 @@ pub const JestPrettyFormat = struct { this.quote_strings = true; defer this.quote_strings = old_quote_strings; - try this.format(Tag.get(key_value, this.globalThis), Writer, writer_, key_value, this.globalThis, enable_ansi_colors); + try this.format(try Tag.get(key_value, this.globalThis), Writer, writer_, key_value, this.globalThis, enable_ansi_colors); needs_space = true; } } - if (value.get_unsafe(this.globalThis, "props")) |props| { + if (try value.get(this.globalThis, "props")) |props| { const prev_quote_strings = this.quote_strings; defer this.quote_strings = prev_quote_strings; this.quote_strings = true; @@ -1581,7 +1581,7 @@ pub const JestPrettyFormat = struct { }).init(this.globalThis, props_obj); defer props_iter.deinit(); - const children_prop = props.get_unsafe(this.globalThis, "children"); + const children_prop = try props.get(this.globalThis, "children"); if (props_iter.len > 0) { { this.indent += 1; @@ -1593,7 +1593,7 @@ pub const JestPrettyFormat = struct { continue; const property_value = props_iter.value; - const tag = Tag.get(property_value, this.globalThis); + const tag = try Tag.get(property_value, this.globalThis); if (tag.cell.isHidden()) continue; @@ -1639,7 +1639,7 @@ pub const JestPrettyFormat = struct { } if (children_prop) |children| { - const tag = Tag.get(children, this.globalThis); + const tag = try Tag.get(children, this.globalThis); const print_children = switch (tag.tag) { .String, .JSX, .Array => true, @@ -1674,14 +1674,14 @@ pub const JestPrettyFormat = struct { this.indent += 1; this.writeIndent(Writer, writer_) catch unreachable; defer this.indent -|= 1; - try this.format(Tag.get(children, this.globalThis), Writer, writer_, children, this.globalThis, enable_ansi_colors); + try this.format(try Tag.get(children, this.globalThis), Writer, writer_, children, this.globalThis, enable_ansi_colors); } writer.writeAll("\n"); this.writeIndent(Writer, writer_) catch unreachable; }, .Array => { - const length = children.getLength(this.globalThis); + const length = try children.getLength(this.globalThis); if (length == 0) break :print_children; writer.writeAll(">\n"); @@ -1696,8 +1696,8 @@ pub const JestPrettyFormat = struct { var j: usize = 0; while (j < length) : (j += 1) { - const child = JSC.JSObject.getIndex(children, this.globalThis, @as(u32, @intCast(j))); - try this.format(Tag.get(child, this.globalThis), Writer, writer_, child, this.globalThis, enable_ansi_colors); + const child = try JSC.JSObject.getIndex(children, this.globalThis, @as(u32, @intCast(j))); + try this.format(try Tag.get(child, this.globalThis), Writer, writer_, child, this.globalThis, enable_ansi_colors); if (j + 1 < length) { writer.writeAll("\n"); this.writeIndent(Writer, writer_) catch unreachable; @@ -1764,7 +1764,7 @@ pub const JestPrettyFormat = struct { .parent = value, }; - value.forEachPropertyOrdered(this.globalThis, &iter, Iterator.forEach); + try value.forEachPropertyOrdered(this.globalThis, &iter, Iterator.forEach); if (iter.i == 0) { var object_name = ZigString.Empty; diff --git a/src/bun.js/virtual_machine_exports.zig b/src/bun.js/virtual_machine_exports.zig index 6122e926cc..b86d08c4e7 100644 --- a/src/bun.js/virtual_machine_exports.zig +++ b/src/bun.js/virtual_machine_exports.zig @@ -12,6 +12,7 @@ pub export fn Bun__getVM() *JSC.VirtualMachine { return JSC.VirtualMachine.get(); } +/// Caller must check for termination exception pub export fn Bun__drainMicrotasks() void { JSC.VirtualMachine.get().eventLoop().tick(); } @@ -115,7 +116,7 @@ pub export fn Bun__handleRejectedPromise(global: *JSGlobalObject, promise: *JSC. if (result == .zero) return; - _ = jsc_vm.unhandledRejection(global, result, promise.toJS()); + jsc_vm.unhandledRejection(global, result, promise.toJS()); jsc_vm.autoGarbageCollect(); } diff --git a/src/bun.js/webcore/Blob.zig b/src/bun.js/webcore/Blob.zig index 9f9beceac5..22995f2f3e 100644 --- a/src/bun.js/webcore/Blob.zig +++ b/src/bun.js/webcore/Blob.zig @@ -105,7 +105,7 @@ pub fn doReadFromS3(this: *Blob, comptime Function: anytype, global: *JSGlobalOb const WrappedFn = struct { pub fn wrapped(b: *Blob, g: *JSGlobalObject, by: []u8) JSC.JSValue { - return JSC.toJSHostValue(g, Function(b, g, by, .clone)); + return JSC.toJSHostCall(g, @src(), Function, .{ b, g, by, .clone }); } }; return S3BlobDownloadTask.init(global, this, WrappedFn.wrapped); @@ -1231,7 +1231,7 @@ pub fn writeFileInternal(globalThis: *JSC.JSGlobalObject, path_or_blob_: *PathOr bun.isRegularFile(path_or_blob.blob.store.?.data.file.mode)))) { if (data.isString()) { - const len = data.getLength(globalThis); + const len = try data.getLength(globalThis); if (len < 256 * 1024) { const str = try data.toBunString(globalThis); @@ -2012,7 +2012,7 @@ pub fn toStreamWithOffset( fn lifetimeWrap(comptime Fn: anytype, comptime lifetime: JSC.WebCore.Lifetime) fn (*Blob, *JSC.JSGlobalObject) JSC.JSValue { return struct { fn wrap(this: *Blob, globalObject: *JSC.JSGlobalObject) JSC.JSValue { - return JSC.toJSHostValue(globalObject, Fn(this, globalObject, lifetime)); + return JSC.toJSHostCall(globalObject, @src(), Fn, .{ this, globalObject, lifetime }); } }.wrap; } @@ -3762,13 +3762,13 @@ fn fromJSWithoutDeferGC( var fail_if_top_value_is_not_typed_array_like = false; switch (current.jsTypeLoose()) { .Array, .DerivedArray => { - var top_iter = JSC.JSArrayIterator.init(current, global); + var top_iter = try JSC.JSArrayIterator.init(current, global); might_only_be_one_thing = top_iter.len == 1; if (top_iter.len == 0) { return Blob{ .globalThis = global }; } if (might_only_be_one_thing) { - top_value = top_iter.next().?; + top_value = (try top_iter.next()).?; } }, else => { @@ -3875,10 +3875,10 @@ fn fromJSWithoutDeferGC( }, .Array, .DerivedArray => { - var iter = JSC.JSArrayIterator.init(current, global); + var iter = try JSC.JSArrayIterator.init(current, global); try stack.ensureUnusedCapacity(iter.len); var any_arrays = false; - while (iter.next()) |item| { + while (try iter.next()) |item| { if (item.isUndefinedOrNull()) continue; // When it's a string or ArrayBuffer inside an array, we can avoid the extra push/pop diff --git a/src/bun.js/webcore/Body.zig b/src/bun.js/webcore/Body.zig index 4684c06575..2a8b087f7c 100644 --- a/src/bun.js/webcore/Body.zig +++ b/src/bun.js/webcore/Body.zig @@ -1153,7 +1153,7 @@ pub fn Mixin(comptime Type: type) type { fn lifetimeWrap(comptime Fn: anytype, comptime lifetime: JSC.WebCore.Lifetime) fn (*AnyBlob, *JSC.JSGlobalObject) JSC.JSValue { return struct { fn wrap(this: *AnyBlob, globalObject: *JSC.JSGlobalObject) JSC.JSValue { - return JSC.toJSHostValue(globalObject, Fn(this, globalObject, lifetime)); + return JSC.toJSHostCall(globalObject, @src(), Fn, .{ this, globalObject, lifetime }); } }.wrap; } diff --git a/src/bun.js/webcore/blob/read_file.zig b/src/bun.js/webcore/blob/read_file.zig index 13cc393747..4ce7514532 100644 --- a/src/bun.js/webcore/blob/read_file.zig +++ b/src/bun.js/webcore/blob/read_file.zig @@ -36,7 +36,7 @@ pub fn NewReadFileHandler(comptime Function: anytype) type { blob.size = @min(@as(SizeType, @truncate(bytes.len)), blob.size); const WrappedFn = struct { pub fn wrapped(b: *Blob, g: *JSGlobalObject, by: []u8) JSC.JSValue { - return JSC.toJSHostValue(g, Function(b, g, by, .temporary)); + return JSC.toJSHostCall(g, @src(), Function, .{ b, g, by, .temporary }); } }; diff --git a/src/bun.js/webcore/fetch.zig b/src/bun.js/webcore/fetch.zig index 3c5177bd79..2a3da09bbe 100644 --- a/src/bun.js/webcore/fetch.zig +++ b/src/bun.js/webcore/fetch.zig @@ -1853,7 +1853,7 @@ pub fn Bun__fetch_( inline for (0..2) |i| { if (objects_to_try[i] != .zero) { if (try objects_to_try[i].get(globalThis, "unix")) |socket_path| { - if (socket_path.isString() and socket_path.getLength(ctx) > 0) { + if (socket_path.isString() and try socket_path.getLength(ctx) > 0) { if (socket_path.toSliceCloneWithAllocator(globalThis, allocator)) |slice| { break :extract_unix_socket_path slice; } @@ -2001,7 +2001,7 @@ pub fn Bun__fetch_( inline for (0..2) |i| { if (objects_to_try[i] != .zero) { if (try objects_to_try[i].get(globalThis, "proxy")) |proxy_arg| { - if (proxy_arg.isString() and proxy_arg.getLength(ctx) > 0) { + if (proxy_arg.isString() and try proxy_arg.getLength(ctx) > 0) { var href = try JSC.URL.hrefFromJS(proxy_arg, globalThis); if (href.tag == .Dead) { const err = ctx.toTypeError(.INVALID_ARG_VALUE, "fetch() proxy URL is invalid", .{}); diff --git a/src/bun.js/webcore/streams.zig b/src/bun.js/webcore/streams.zig index 43f8e8f508..22294ae0e4 100644 --- a/src/bun.js/webcore/streams.zig +++ b/src/bun.js/webcore/streams.zig @@ -81,7 +81,7 @@ pub const Start = union(Tag) { var chunk_size: Blob.SizeType = 0; var empty = true; - if (value.getOwn(globalThis, "asUint8Array")) |val| { + if (try value.getOwn(globalThis, "asUint8Array")) |val| { if (val.isBoolean()) { as_uint8array = val.toBoolean(); empty = false; diff --git a/src/bun.zig b/src/bun.zig index 72e9fcf79b..7410e259c1 100644 --- a/src/bun.zig +++ b/src/bun.zig @@ -123,6 +123,15 @@ pub const JSError = error{ OutOfMemory, }; +pub const JSExecutionTerminated = error{ + /// JavaScript execution has been terminated. + /// This condition is indicated by throwing an exception, so most code should still handle it + /// with JSError. If you expect that you will not throw any errors other than the termination + /// exception, you can catch JSError, assert that the exception is the termination exception, + /// and return error.JSExecutionTerminated. + JSExecutionTerminated, +}; + pub const JSOOM = OOM || JSError; pub const detectCI = @import("ci_info.zig").detectCI; diff --git a/src/cli/test_command.zig b/src/cli/test_command.zig index 9896d18894..cacdd6735e 100644 --- a/src/cli/test_command.zig +++ b/src/cli/test_command.zig @@ -1527,7 +1527,7 @@ pub const TestCommand = struct { switch (promise.status(vm.global.vm())) { .rejected => { - _ = vm.unhandledRejection(vm.global, promise.result(vm.global.vm()), promise.asValue()); + vm.unhandledRejection(vm.global, promise.result(vm.global.vm()), promise.asValue()); reporter.summary.fail += 1; if (reporter.jest.bail == reporter.summary.fail) { diff --git a/src/codegen/bindgen.ts b/src/codegen/bindgen.ts index 271be57437..193c949eeb 100644 --- a/src/codegen/bindgen.ts +++ b/src/codegen/bindgen.ts @@ -1363,7 +1363,7 @@ for (const [filename, { functions, typedefs }] of files) { switch (returnStrategy.type) { case "jsvalue": - zigInternal.add(`return JSC.toJSHostValue(${globalObjectArg}, `); + zigInternal.add(`return JSC.toJSHostCall(${globalObjectArg}, @src(), `); break; case "basic-out-param": zigInternal.add(`out.* = @as(bun.JSError!${returnStrategy.abiType}, `); @@ -1373,7 +1373,12 @@ for (const [filename, { functions, typedefs }] of files) { break; } - zigInternal.line(`${zid("import_" + namespaceVar)}.${fn.zigPrefix}${fn.name + vari.suffix}(`); + zigInternal.add(`${zid("import_" + namespaceVar)}.${fn.zigPrefix}${fn.name + vari.suffix}`); + if (returnStrategy.type === "jsvalue") { + zigInternal.line(", .{"); + } else { + zigInternal.line("("); + } zigInternal.indent(); for (const arg of vari.args) { const argName = arg.zigMappedName!; @@ -1421,7 +1426,7 @@ for (const [filename, { functions, typedefs }] of files) { zigInternal.dedent(); switch (returnStrategy.type) { case "jsvalue": - zigInternal.line(`));`); + zigInternal.line(`});`); break; case "basic-out-param": case "void": diff --git a/src/codegen/generate-classes.ts b/src/codegen/generate-classes.ts index 4ae300fa0b..19fb13650a 100644 --- a/src/codegen/generate-classes.ts +++ b/src/codegen/generate-classes.ts @@ -1958,7 +1958,7 @@ const JavaScriptCoreBindings = struct { if (comptime Environment.enable_logs) log_zig_getter("${typeName}", "${name}"); return switch (@typeInfo(@typeInfo(@TypeOf(${typeName}.${getter})).@"fn".return_type.?)) { .error_union => { - return @call(.always_inline, jsc.toJSHostValue, .{globalObject, @call(.always_inline, ${typeName}.${getter}, .{this, ${thisValue ? "thisValue," : ""} globalObject})}); + return @call(.always_inline, jsc.toJSHostCall, .{globalObject, @src(), ${typeName}.${getter}, .{this, ${thisValue ? "thisValue," : ""} globalObject}}); }, else => @call(.always_inline, ${typeName}.${getter}, .{this, ${thisValue ? "thisValue," : ""} globalObject}), }; @@ -2002,7 +2002,7 @@ const JavaScriptCoreBindings = struct { output += ` pub fn ${names.fn}(thisValue: *${typeName}, globalObject: *jsc.JSGlobalObject, callFrame: *jsc.CallFrame${proto[name].passThis ? ", js_this_value: jsc.JSValue" : ""}) callconv(jsc.conv) jsc.JSValue { if (comptime Environment.enable_logs) log_zig_method("${typeName}", "${name}", callFrame); - return @call(.always_inline, jsc.toJSHostValue, .{globalObject, @call(.always_inline, ${typeName}.${fn}, .{thisValue, globalObject, callFrame${proto[name].passThis ? ", js_this_value" : ""}})}); + return @call(.always_inline, jsc.toJSHostCall, .{globalObject, @src(), ${typeName}.${fn}, .{thisValue, globalObject, callFrame${proto[name].passThis ? ", js_this_value" : ""}}}); } `; } @@ -2020,7 +2020,7 @@ const JavaScriptCoreBindings = struct { if (comptime Environment.enable_logs) log_zig_class_getter("${typeName}", "${name}"); return switch (@typeInfo(@typeInfo(@TypeOf(${typeName}.${getter})).@"fn".return_type.?)) { .error_union => { - return @call(.always_inline, jsc.toJSHostValue, .{globalObject, @call(.always_inline, ${typeName}.${getter}, .{globalObject, ${thisValue ? "thisValue," : ""} propertyName})}); + return @call(.always_inline, jsc.toJSHostCall, .{globalObject, @src(), ${typeName}.${getter}, .{globalObject, ${thisValue ? "thisValue," : ""} propertyName}}); }, else => { return @call(.always_inline, ${typeName}.${getter}, .{globalObject, ${thisValue ? "thisValue," : ""} propertyName}); @@ -2087,7 +2087,7 @@ const JavaScriptCoreBindings = struct { output += ` pub fn ${symbolName(typeName, "onStructuredCloneDeserialize")}(globalObject: *jsc.JSGlobalObject, ptr: [*]u8, end: [*]u8) callconv(jsc.conv) jsc.JSValue { if (comptime Environment.enable_logs) log_zig_structured_clone_deserialize("${typeName}"); - return @call(.always_inline, jsc.toJSHostValue, .{ globalObject, @call(.always_inline, ${typeName}.onStructuredCloneDeserialize, .{globalObject, ptr, end}) }); + return @call(.always_inline, jsc.toJSHostCall, .{ globalObject, @src(), ${typeName}.onStructuredCloneDeserialize, .{globalObject, ptr, end} }); } `; } else { diff --git a/src/codegen/generate-js2native.ts b/src/codegen/generate-js2native.ts index 5116e1f390..84c0aa7065 100644 --- a/src/codegen/generate-js2native.ts +++ b/src/codegen/generate-js2native.ts @@ -215,7 +215,7 @@ export function getJS2NativeZig(gs2NativeZigPath: string) { .filter(x => x.type === "zig") .flatMap(call => [ `export fn ${symbol(call)}_workaround(global: *JSC.JSGlobalObject) callconv(JSC.conv) JSC.JSValue {`, - ` return JSC.toJSHostValue(global, @import(${JSON.stringify(path.relative(path.dirname(gs2NativeZigPath), call.filename))}).${call.symbol}(global));`, + ` return JSC.toJSHostCall(global, @src(), @import(${JSON.stringify(path.relative(path.dirname(gs2NativeZigPath), call.filename))}).${call.symbol}, .{global});`, "}", ]), ...wrapperCalls diff --git a/src/codegen/generate-node-errors.ts b/src/codegen/generate-node-errors.ts index aafbe8c4e1..bb41dc1389 100644 --- a/src/codegen/generate-node-errors.ts +++ b/src/codegen/generate-node-errors.ts @@ -124,6 +124,7 @@ zig += ` extern fn Bun__createErrorWithCode(globalThis: *JSC.JSGlobalObject, code: Error, message: *bun.String) JSC.JSValue; /// Creates an Error object with the given error code. + /// If an error is thrown while creating the Error object, returns that error instead. /// Derefs the message string. pub fn toJS(this: Error, globalThis: *JSC.JSGlobalObject, message: *bun.String) JSC.JSValue { defer message.deref(); diff --git a/src/csrf.zig b/src/csrf.zig index cfdef4b424..7a9c3abd76 100644 --- a/src/csrf.zig +++ b/src/csrf.zig @@ -230,7 +230,7 @@ pub fn csrf__generate_impl(globalObject: *JSC.JSGlobalObject, callframe: *JSC.Ca if (jsSecret.isEmptyOrUndefinedOrNull()) { return globalObject.throwInvalidArguments("Secret is required", .{}); } - if (!jsSecret.isString() or jsSecret.getLength(globalObject) == 0) { + if (!jsSecret.isString() or try jsSecret.getLength(globalObject) == 0) { return globalObject.throwInvalidArguments("Secret must be a non-empty string", .{}); } secret = try jsSecret.toSlice(globalObject, bun.default_allocator); @@ -316,7 +316,7 @@ pub fn csrf__verify_impl(globalObject: *JSC.JSGlobalObject, call_frame: *JSC.Cal if (jsToken.isUndefinedOrNull()) { return globalObject.throwInvalidArguments("Token is required", .{}); } - if (!jsToken.isString() or jsToken.getLength(globalObject) == 0) { + if (!jsToken.isString() or try jsToken.getLength(globalObject) == 0) { return globalObject.throwInvalidArguments("Token must be a non-empty string", .{}); } const token = try jsToken.toSlice(globalObject, bun.default_allocator); diff --git a/src/css/css_internals.zig b/src/css/css_internals.zig index 47bd0e5833..76d35336f6 100644 --- a/src/css/css_internals.zig +++ b/src/css/css_internals.zig @@ -158,8 +158,8 @@ fn parserOptionsFromJS(globalThis: *JSC.JSGlobalObject, allocator: Allocator, op _ = allocator; // autofix if (try jsobj.getTruthy(globalThis, "flags")) |val| { if (val.isArray()) { - var iter = val.arrayIterator(globalThis); - while (iter.next()) |item| { + var iter = try val.arrayIterator(globalThis); + while (try iter.next()) |item| { const bunstr = try item.toBunString(globalThis); defer bunstr.deref(); const str = bunstr.toUTF8(bun.default_allocator); diff --git a/src/css/values/color_js.zig b/src/css/values/color_js.zig index 4ac9e2c647..5d4b84b0dc 100644 --- a/src/css/values/color_js.zig +++ b/src/css/values/color_js.zig @@ -183,18 +183,18 @@ pub fn jsFunctionColor(globalThis: *JSC.JSGlobalObject, callFrame: *JSC.CallFram break :brk .{ .result = css.CssColor{ .rgba = .{ .alpha = rgba.alpha, .red = rgba.red, .green = rgba.green, .blue = rgba.blue } } }; } else if (args[0].jsType().isArrayLike()) { - switch (args[0].getLength(globalThis)) { + switch (try args[0].getLength(globalThis)) { 3 => { - const r = try colorIntFromJS(globalThis, args[0].getIndex(globalThis, 0), "[0]"); - const g = try colorIntFromJS(globalThis, args[0].getIndex(globalThis, 1), "[1]"); - const b = try colorIntFromJS(globalThis, args[0].getIndex(globalThis, 2), "[2]"); + const r = try colorIntFromJS(globalThis, try args[0].getIndex(globalThis, 0), "[0]"); + const g = try colorIntFromJS(globalThis, try args[0].getIndex(globalThis, 1), "[1]"); + const b = try colorIntFromJS(globalThis, try args[0].getIndex(globalThis, 2), "[2]"); break :brk .{ .result = css.CssColor{ .rgba = .{ .alpha = 255, .red = @intCast(r), .green = @intCast(g), .blue = @intCast(b) } } }; }, 4 => { - const r = try colorIntFromJS(globalThis, args[0].getIndex(globalThis, 0), "[0]"); - const g = try colorIntFromJS(globalThis, args[0].getIndex(globalThis, 1), "[1]"); - const b = try colorIntFromJS(globalThis, args[0].getIndex(globalThis, 2), "[2]"); - const a = try colorIntFromJS(globalThis, args[0].getIndex(globalThis, 3), "[3]"); + const r = try colorIntFromJS(globalThis, try args[0].getIndex(globalThis, 0), "[0]"); + const g = try colorIntFromJS(globalThis, try args[0].getIndex(globalThis, 1), "[1]"); + const b = try colorIntFromJS(globalThis, try args[0].getIndex(globalThis, 2), "[2]"); + const a = try colorIntFromJS(globalThis, try args[0].getIndex(globalThis, 3), "[3]"); break :brk .{ .result = css.CssColor{ .rgba = .{ .alpha = @intCast(a), .red = @intCast(r), .green = @intCast(g), .blue = @intCast(b) } } }; }, else => { diff --git a/src/deps/c_ares.zig b/src/deps/c_ares.zig index 9dccf83abf..44dbc53791 100644 --- a/src/deps/c_ares.zig +++ b/src/deps/c_ares.zig @@ -1418,8 +1418,8 @@ pub const struct_any_reply = struct { reply.toJSResponse(allocator, globalThis, lookup_name); if (response.isArray()) { - var iterator = response.arrayIterator(globalThis); - while (iterator.next()) |item| { + var iterator = try response.arrayIterator(globalThis); + while (try iterator.next()) |item| { try append(globalThis, array, i, item, lookup_name); } } else { diff --git a/src/install/install.zig b/src/install/install.zig index 3766862d54..555513b573 100644 --- a/src/install/install.zig +++ b/src/install/install.zig @@ -6736,8 +6736,8 @@ pub const PackageManager = struct { if (input_str.len > 0) try all_positionals.append(input_str.slice()); } else if (input.isArray()) { - var iter = input.arrayIterator(globalThis); - while (iter.next()) |item| { + var iter = try input.arrayIterator(globalThis); + while (try iter.next()) |item| { const slice = item.toSliceCloneWithAllocator(globalThis, allocator) orelse return .zero; if (globalThis.hasException()) return .zero; if (slice.len == 0) continue; diff --git a/src/install/npm.zig b/src/install/npm.zig index d333ea5c20..4f0c652c91 100644 --- a/src/install/npm.zig +++ b/src/install/npm.zig @@ -724,8 +724,8 @@ pub const OperatingSystem = enum(u16) { pub fn jsFunctionOperatingSystemIsMatch(globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) bun.JSError!JSC.JSValue { const args = callframe.arguments_old(1); var operating_system = negatable(.none); - var iter = args.ptr[0].arrayIterator(globalObject); - while (iter.next()) |item| { + var iter = try args.ptr[0].arrayIterator(globalObject); + while (try iter.next()) |item| { const slice = try item.toSlice(globalObject, bun.default_allocator); defer slice.deinit(); operating_system.apply(slice.slice()); @@ -841,8 +841,8 @@ pub const Architecture = enum(u16) { pub fn jsFunctionArchitectureIsMatch(globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) bun.JSError!JSC.JSValue { const args = callframe.arguments_old(1); var architecture = negatable(.none); - var iter = args.ptr[0].arrayIterator(globalObject); - while (iter.next()) |item| { + var iter = try args.ptr[0].arrayIterator(globalObject); + while (try iter.next()) |item| { const slice = try item.toSlice(globalObject, bun.default_allocator); defer slice.deinit(); architecture.apply(slice.slice()); diff --git a/src/js_ast.zig b/src/js_ast.zig index b2f5021920..edeb32c2a1 100644 --- a/src/js_ast.zig +++ b/src/js_ast.zig @@ -8228,7 +8228,7 @@ pub const Macro = struct { switch (loaded_result.unwrap(vm.jsc, .leave_unhandled)) { .rejected => |result| { - _ = vm.unhandledRejection(vm.global, result, loaded_result.asValue()); + vm.unhandledRejection(vm.global, result, loaded_result.asValue()); vm.disableMacroMode(); return error.MacroLoadError; }, @@ -8303,7 +8303,7 @@ pub const Macro = struct { this: *Run, value: JSC.JSValue, ) MacroError!Expr { - return switch (JSC.ConsoleObject.Formatter.Tag.get(value, this.global).tag) { + return switch ((try JSC.ConsoleObject.Formatter.Tag.get(value, this.global)).tag) { .Error => this.coerce(value, .Error), .Undefined => this.coerce(value, .Undefined), .Null => this.coerce(value, .Null), @@ -8409,7 +8409,7 @@ pub const Macro = struct { return _entry.value_ptr.*; } - var iter = JSC.JSArrayIterator.init(value, this.global); + var iter = try JSC.JSArrayIterator.init(value, this.global); if (iter.len == 0) { const result = Expr.init( E.Array, @@ -8435,7 +8435,7 @@ pub const Macro = struct { errdefer this.allocator.free(array); var i: usize = 0; - while (iter.next()) |item| { + while (try iter.next()) |item| { array[i] = try this.run(item); if (array[i].isMissing()) continue; @@ -8539,7 +8539,7 @@ pub const Macro = struct { } if (rejected or promise_result.isError() or promise_result.isAggregateError(this.global) or promise_result.isException(this.global.vm())) { - _ = this.macro.vm.unhandledRejection(this.global, promise_result, promise.asValue()); + this.macro.vm.unhandledRejection(this.global, promise_result, promise.asValue()); return error.MacroFailed; } this.is_top_level = false; diff --git a/src/napi/napi.zig b/src/napi/napi.zig index 334b96c173..c54cd8d883 100644 --- a/src/napi/napi.zig +++ b/src/napi/napi.zig @@ -570,7 +570,7 @@ pub export fn napi_get_array_length(env_: napi_env, value_: napi_value, result_: return env.setLastError(.array_expected); } - result.* = @as(u32, @truncate(value.getLength(env.toJS()))); + result.* = @truncate(value.getLength(env.toJS()) catch return env.setLastError(.pending_exception)); return env.ok(); } pub export fn napi_strict_equals(env_: napi_env, lhs_: napi_value, rhs_: napi_value, result_: ?*bool) napi_status { @@ -582,8 +582,8 @@ pub export fn napi_strict_equals(env_: napi_env, lhs_: napi_value, rhs_: napi_va return env.invalidArg(); }; const lhs, const rhs = .{ lhs_.get(), rhs_.get() }; - // there is some nuance with NaN here i'm not sure about - result.* = lhs.isSameValue(rhs, env.toJS()); + // TODO: this needs to be strictEquals not isSameValue (NaN !== NaN and -0 === 0) + result.* = lhs.isSameValue(rhs, env.toJS()) catch return env.setLastError(.pending_exception); return env.ok(); } pub extern fn napi_call_function(env: napi_env, recv: napi_value, func: napi_value, argc: usize, argv: [*c]const napi_value, result: *napi_value) napi_status; @@ -1592,7 +1592,7 @@ pub const ThreadSafeFunction = struct { break :brk .{ !this.isClosing(), t }; }; - this.call(task, !is_first); + this.call(task, !is_first) catch return false; if (queue_finalizer_after_call) { this.maybeQueueFinalizer(); @@ -1604,10 +1604,10 @@ pub const ThreadSafeFunction = struct { /// This function can be called multiple times in one tick of the event loop. /// See: https://github.com/nodejs/node/pull/38506 /// In that case, we need to drain microtasks. - fn call(this: *ThreadSafeFunction, task: ?*anyopaque, is_first: bool) void { + fn call(this: *ThreadSafeFunction, task: ?*anyopaque, is_first: bool) bun.JSExecutionTerminated!void { const env = this.env; if (!is_first) { - this.event_loop.drainMicrotasks(); + try this.event_loop.drainMicrotasks(); } const globalObject = env.toJS(); diff --git a/src/shell/ParsedShellScript.zig b/src/shell/ParsedShellScript.zig index f48092dc6c..1dfce3de9d 100644 --- a/src/shell/ParsedShellScript.zig +++ b/src/shell/ParsedShellScript.zig @@ -110,7 +110,7 @@ pub fn createParsedShellScript(globalThis: *JSC.JSGlobalObject, callframe: *JSC. } const string_args = arguments[0]; const template_args_js = arguments[1]; - var template_args = template_args_js.arrayIterator(globalThis); + var template_args = try template_args_js.arrayIterator(globalThis); var stack_alloc = std.heap.stackFallback(@sizeOf(bun.String) * 4, shargs.arena_allocator()); var jsstrings = try std.ArrayList(bun.String).initCapacity(stack_alloc.get(), 4); diff --git a/src/shell/shell.zig b/src/shell/shell.zig index fcc8cfece0..e4c3160a64 100644 --- a/src/shell/shell.zig +++ b/src/shell/shell.zig @@ -3715,10 +3715,10 @@ pub fn shellCmdFromJS( var builder = ShellSrcBuilder.init(globalThis, out_script, jsstrings); var jsobjref_buf: [128]u8 = [_]u8{0} ** 128; - var string_iter = string_args.arrayIterator(globalThis); + var string_iter = try string_args.arrayIterator(globalThis); var i: u32 = 0; const last = string_iter.len -| 1; - while (string_iter.next()) |js_value| { + while (try string_iter.next()) |js_value| { defer i += 1; if (!try builder.appendJSValueStr(js_value, false)) { return globalThis.throw("Shell script string contains invalid UTF-16", .{}); @@ -3726,7 +3726,7 @@ pub fn shellCmdFromJS( // const str = js_value.getZigString(globalThis); // try script.appendSlice(str.full()); if (i < last) { - const template_value = template_args.next() orelse { + const template_value = try template_args.next() orelse { return globalThis.throw("Shell script is missing JSValue arg", .{}); }; try handleTemplateValue(globalThis, template_value, out_jsobjs, out_script, jsstrings, jsobjref_buf[0..]); @@ -3806,10 +3806,10 @@ pub fn handleTemplateValue( } if (template_value.jsType().isArray()) { - var array = template_value.arrayIterator(globalThis); + var array = try template_value.arrayIterator(globalThis); const last = array.len -| 1; var i: u32 = 0; - while (array.next()) |arr| : (i += 1) { + while (try array.next()) |arr| : (i += 1) { try handleTemplateValue(globalThis, arr, out_jsobjs, out_script, jsstrings, jsobjref_buf); if (i < last) { const str = bun.String.static(" "); @@ -3822,7 +3822,7 @@ pub fn handleTemplateValue( } if (template_value.isObject()) { - if (template_value.getOwnTruthy(globalThis, "raw")) |maybe_str| { + if (try template_value.getOwnTruthy(globalThis, "raw")) |maybe_str| { const bunstr = try maybe_str.toBunString(globalThis); defer bunstr.deref(); if (!try builder.appendBunStr(bunstr, false)) { @@ -4308,7 +4308,7 @@ pub const TestingAPIs = struct { const template_args_js = arguments.nextEat() orelse { return globalThis.throw("shell: expected 2 arguments, got 0", .{}); }; - var template_args = template_args_js.arrayIterator(globalThis); + var template_args = try template_args_js.arrayIterator(globalThis); var stack_alloc = std.heap.stackFallback(@sizeOf(bun.String) * 4, arena.allocator()); var jsstrings = try std.ArrayList(bun.String).initCapacity(stack_alloc.get(), 4); defer { @@ -4376,7 +4376,7 @@ pub const TestingAPIs = struct { const template_args_js = arguments.nextEat() orelse { return globalThis.throw("shell: expected 2 arguments, got 0", .{}); }; - var template_args = template_args_js.arrayIterator(globalThis); + var template_args = try template_args_js.arrayIterator(globalThis); var stack_alloc = std.heap.stackFallback(@sizeOf(bun.String) * 4, arena.allocator()); var jsstrings = try std.ArrayList(bun.String).initCapacity(stack_alloc.get(), 4); defer { diff --git a/src/sql/postgres.zig b/src/sql/postgres.zig index df0664368a..5608ee9bcf 100644 --- a/src/sql/postgres.zig +++ b/src/sql/postgres.zig @@ -586,10 +586,10 @@ pub const PostgresSQLQuery = struct { const bigint = js_bigint.isBoolean() and js_bigint.asBoolean(); const simple = js_simple.isBoolean() and js_simple.asBoolean(); if (simple) { - if (values.getLength(globalThis) > 0) { + if (try values.getLength(globalThis) > 0) { return globalThis.throwInvalidArguments("simple query cannot have parameters", .{}); } - if (query.getLength(globalThis) >= std.math.maxInt(i32)) { + if (try query.getLength(globalThis) >= std.math.maxInt(i32)) { return globalThis.throwInvalidArguments("query is too long", .{}); } } @@ -866,7 +866,7 @@ pub const PostgresRequest = struct { // of parameters. try writer.short(len); - var iter = QueryBindingIterator.init(values_array, columns_value, globalObject); + var iter = try QueryBindingIterator.init(values_array, columns_value, globalObject); for (0..len) |i| { const parameter_field = parameter_fields[i]; const is_custom_type = std.math.maxInt(short) < parameter_field; @@ -874,7 +874,7 @@ pub const PostgresRequest = struct { const force_text = is_custom_type or (tag.isBinaryFormatSupported() and brk: { iter.to(@truncate(i)); - if (iter.next()) |value| { + if (try iter.next()) |value| { break :brk value.isString(); } if (iter.anyFailed()) { @@ -905,7 +905,7 @@ pub const PostgresRequest = struct { debug("Bind: {} ({d} args)", .{ bun.fmt.quote(name), len }); iter.to(0); var i: usize = 0; - while (iter.next()) |value| : (i += 1) { + while (try iter.next()) |value| : (i += 1) { const tag: types.Tag = brk: { if (i >= len) { // parameter in array but not in parameter_fields @@ -3050,9 +3050,9 @@ const QueryBindingIterator = union(enum) { array: JSC.JSArrayIterator, objects: ObjectIterator, - pub fn init(array: JSValue, columns: JSValue, globalObject: *JSC.JSGlobalObject) QueryBindingIterator { + pub fn init(array: JSValue, columns: JSValue, globalObject: *JSC.JSGlobalObject) bun.JSError!QueryBindingIterator { if (columns.isEmptyOrUndefinedOrNull()) { - return .{ .array = JSC.JSArrayIterator.init(array, globalObject) }; + return .{ .array = try JSC.JSArrayIterator.init(array, globalObject) }; } return .{ @@ -3060,8 +3060,8 @@ const QueryBindingIterator = union(enum) { .array = array, .columns = columns, .globalObject = globalObject, - .columns_count = columns.getLength(globalObject), - .array_length = array.getLength(globalObject), + .columns_count = try columns.getLength(globalObject), + .array_length = try array.getLength(globalObject), }, }; } @@ -3089,12 +3089,12 @@ const QueryBindingIterator = union(enum) { const globalObject = this.globalObject; if (this.current_row == .zero) { - this.current_row = JSC.JSObject.getIndex(this.array, globalObject, @intCast(row_i)); - if (this.current_row.isEmptyOrUndefinedOrNull()) { - if (!globalObject.hasException()) - return globalObject.throw("Expected a row to be returned at index {d}", .{row_i}) catch null; + this.current_row = JSC.JSObject.getIndex(this.array, globalObject, @intCast(row_i)) catch { this.any_failed = true; return null; + }; + if (this.current_row.isEmptyOrUndefinedOrNull()) { + return globalObject.throw("Expected a row to be returned at index {d}", .{row_i}) catch null; } } @@ -3106,12 +3106,12 @@ const QueryBindingIterator = union(enum) { } } - const property = JSC.JSObject.getIndex(this.columns, globalObject, @intCast(cell_i)); - if (property == .zero or property.isUndefined()) { - if (!globalObject.hasException()) - return globalObject.throw("Expected a column at index {d} in row {d}", .{ cell_i, row_i }) catch null; + const property = JSC.JSObject.getIndex(this.columns, globalObject, @intCast(cell_i)) catch { this.any_failed = true; return null; + }; + if (property.isUndefined()) { + return globalObject.throw("Expected a column at index {d} in row {d}", .{ cell_i, row_i }) catch null; } const value = this.current_row.getOwnByValue(globalObject, property); @@ -3125,7 +3125,7 @@ const QueryBindingIterator = union(enum) { } }; - pub fn next(this: *QueryBindingIterator) ?JSC.JSValue { + pub fn next(this: *QueryBindingIterator) bun.JSError!?JSC.JSValue { return switch (this.*) { .array => |*iter| iter.next(), .objects => |*iter| iter.next(), @@ -3213,9 +3213,9 @@ const Signature = struct { name.deinit(); } - var iter = QueryBindingIterator.init(array_value, columns, globalObject); + var iter = try QueryBindingIterator.init(array_value, columns, globalObject); - while (iter.next()) |value| { + while (try iter.next()) |value| { if (value.isEmptyOrUndefinedOrNull()) { // Allow postgres to decide the type try fields.append(0); diff --git a/src/sql/postgres/postgres_types.zig b/src/sql/postgres/postgres_types.zig index 7ab4dae90c..4119ad23da 100644 --- a/src/sql/postgres/postgres_types.zig +++ b/src/sql/postgres/postgres_types.zig @@ -353,10 +353,9 @@ pub const Tag = enum(short) { return .int8; } - if (tag.isArrayLike() and value.getLength(globalObject) > 0) { - return Tag.fromJS(globalObject, value.getIndex(globalObject, 0)); + if (tag.isArrayLike() and try value.getLength(globalObject) > 0) { + return Tag.fromJS(globalObject, try value.getIndex(globalObject, 0)); } - if (globalObject.hasException()) return error.JSError; // Ban these types: if (tag == .NumberObject) { diff --git a/src/string.zig b/src/string.zig index 2025afe79a..24380fad21 100644 --- a/src/string.zig +++ b/src/string.zig @@ -514,18 +514,22 @@ pub const String = extern struct { } pub fn fromJS(value: bun.JSC.JSValue, globalObject: *JSC.JSGlobalObject) bun.JSError!String { + var scope: JSC.CatchScope = undefined; + scope.init(globalObject, @src(), .assertions_only); + defer scope.deinit(); var out: String = String.dead; - if (BunString__fromJS(globalObject, value, &out)) { - if (comptime bun.Environment.isDebug) { - bun.assert(out.tag != .Dead); - } - return out; + const ok = BunString__fromJS(globalObject, value, &out); + + // If there is a pending exception, but stringifying succeeds, we don't return JSError. + // We do need to always call hasException() to satisfy the need for an exception check. + const has_exception = scope.hasException(); + if (ok) { + bun.debugAssert(out.tag != .Dead); + } else { + bun.debugAssert(has_exception); } - if (comptime bun.Environment.isDebug) { - bun.assert(globalObject.hasException()); - } - return error.JSError; + return if (ok) out else error.JSError; } pub fn toJS(this: *const String, globalObject: *bun.JSC.JSGlobalObject) JSC.JSValue { @@ -549,7 +553,7 @@ pub const String = extern struct { /// calls toJS on all elements of `array`. pub fn toJSArray(globalObject: *bun.JSC.JSGlobalObject, array: []const bun.String) bun.JSError!JSC.JSValue { JSC.markBinding(@src()); - return bun.jsc.fromJSHostValue(BunString__createArray(globalObject, array.ptr, array.len)); + return bun.jsc.fromJSHostCall(globalObject, @src(), BunString__createArray, .{ globalObject, array.ptr, array.len }); } pub fn toZigString(this: String) ZigString { diff --git a/src/transpiler.zig b/src/transpiler.zig index 848e389289..fdede87e22 100644 --- a/src/transpiler.zig +++ b/src/transpiler.zig @@ -241,7 +241,7 @@ pub const PluginRunner = struct { if (!path_value.isString()) { return JSC.ErrorableString.err( error.JSErrorObject, - bun.String.static("Expected \"path\" to be a string in onResolve plugin").toErrorInstance(this.global_object).asVoid(), + bun.String.static("Expected \"path\" to be a string in onResolve plugin").toErrorInstance(this.global_object), ); } @@ -250,7 +250,7 @@ pub const PluginRunner = struct { if (file_path.length() == 0) { return JSC.ErrorableString.err( error.JSErrorObject, - bun.String.static("Expected \"path\" to be a non-empty string in onResolve plugin").toErrorInstance(this.global_object).asVoid(), + bun.String.static("Expected \"path\" to be a non-empty string in onResolve plugin").toErrorInstance(this.global_object), ); } else if // TODO: validate this better @@ -261,7 +261,7 @@ pub const PluginRunner = struct { { return JSC.ErrorableString.err( error.JSErrorObject, - bun.String.static("\"path\" is invalid in onResolve plugin").toErrorInstance(this.global_object).asVoid(), + bun.String.static("\"path\" is invalid in onResolve plugin").toErrorInstance(this.global_object), ); } var static_namespace = true; @@ -270,7 +270,7 @@ pub const PluginRunner = struct { if (!namespace_value.isString()) { return JSC.ErrorableString.err( error.JSErrorObject, - bun.String.static("Expected \"namespace\" to be a string").toErrorInstance(this.global_object).asVoid(), + bun.String.static("Expected \"namespace\" to be a string").toErrorInstance(this.global_object), ); } diff --git a/src/valkey/js_valkey_functions.zig b/src/valkey/js_valkey_functions.zig index 4abe8b7b1f..e3cac8e08c 100644 --- a/src/valkey/js_valkey_functions.zig +++ b/src/valkey/js_valkey_functions.zig @@ -6,7 +6,7 @@ pub fn jsSend(this: *JSValkeyClient, globalObject: *JSC.JSGlobalObject, callfram if (!args_array.isObject() or !args_array.isArray()) { return globalObject.throw("Arguments must be an array", .{}); } - var iter = args_array.arrayIterator(globalObject); + var iter = try args_array.arrayIterator(globalObject); var args = try std.ArrayList(JSArgument).initCapacity(bun.default_allocator, iter.len); defer { for (args.items) |*item| { @@ -15,7 +15,7 @@ pub fn jsSend(this: *JSValkeyClient, globalObject: *JSC.JSGlobalObject, callfram args.deinit(); } - while (iter.next()) |arg_js| { + while (try iter.next()) |arg_js| { args.appendAssumeCapacity(try fromJS(globalObject, arg_js) orelse { return globalObject.throwInvalidArgumentType("sendCommand", "argument", "string or buffer"); }); @@ -390,7 +390,7 @@ pub fn hmget(this: *JSValkeyClient, globalObject: *JSC.JSGlobalObject, callframe return globalObject.throw("Fields must be an array", .{}); } - var iter = fields_array.arrayIterator(globalObject); + var iter = try fields_array.arrayIterator(globalObject); var args = try std.ArrayList(JSC.ZigString.Slice).initCapacity(bun.default_allocator, iter.len + 1); defer { for (args.items) |item| { @@ -402,7 +402,7 @@ pub fn hmget(this: *JSValkeyClient, globalObject: *JSC.JSGlobalObject, callframe args.appendAssumeCapacity(JSC.ZigString.Slice.fromUTF8NeverFree(key.slice())); // Add field names as arguments - while (iter.next()) |field_js| { + while (try iter.next()) |field_js| { const field_str = try field_js.toBunString(globalObject); defer field_str.deref(); @@ -495,7 +495,7 @@ pub fn hmset(this: *JSValkeyClient, globalObject: *JSC.JSGlobalObject, callframe return globalObject.throw("Arguments must be an array of alternating field names and values", .{}); } - var iter = array_arg.arrayIterator(globalObject); + var iter = try array_arg.arrayIterator(globalObject); if (iter.len % 2 != 0) { return globalObject.throw("Arguments must be an array of alternating field names and values", .{}); } @@ -514,7 +514,7 @@ pub fn hmset(this: *JSValkeyClient, globalObject: *JSC.JSGlobalObject, callframe args.appendAssumeCapacity(key_slice); // Add field-value pairs - while (iter.next()) |field_js| { + while (try iter.next()) |field_js| { // Add field name const field_str = try field_js.toBunString(globalObject); defer field_str.deref(); @@ -522,7 +522,7 @@ pub fn hmset(this: *JSValkeyClient, globalObject: *JSC.JSGlobalObject, callframe args.appendAssumeCapacity(field_slice); // Add value - if (iter.next()) |value_js| { + if (try iter.next()) |value_js| { const value_str = try value_js.toBunString(globalObject); defer value_str.deref(); const value_slice = value_str.toUTF8WithoutRef(bun.default_allocator); diff --git a/test/internal/ban-words.test.ts b/test/internal/ban-words.test.ts index f23b5535ab..f840f0987b 100644 --- a/test/internal/ban-words.test.ts +++ b/test/internal/ban-words.test.ts @@ -43,6 +43,10 @@ const words: Record ".stdDir()": { reason: "Prefer bun.sys + bun.FD instead of std.fs.File. Zig hides 'errno' when Bun wants to match libuv", limit: 49 }, ".arguments_old(": { reason: "Please migrate to .argumentsAsArray() or another argument API", limit: 284 }, "// autofix": { reason: "Evaluate if this variable should be deleted entirely or explicitly discarded.", limit: 175 }, + + "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: 49 }, + "globalThis.hasException": { reason: "Incompatible with strict exception checks. Use a CatchScope instead.", limit: 139 }, }; const words_keys = [...Object.keys(words)]; diff --git a/test/no-validate-exceptions.txt b/test/no-validate-exceptions.txt new file mode 100644 index 0000000000..0714b5bca3 --- /dev/null +++ b/test/no-validate-exceptions.txt @@ -0,0 +1,2807 @@ +# List of tests for which we do NOT set validateExceptionChecks=1 when running in ASan CI +test/bake/dev-and-prod.test.ts +test/bake/dev/plugins.test.ts +test/bake/framework-router.test.ts +test/bundler/bun-build-api.test.ts +test/bundler/bundler_banner.test.ts +test/bundler/bundler_browser.test.ts +test/bundler/bundler_bun.test.ts +test/bundler/bundler_cjs2esm.test.ts +test/bundler/bundler_comments.test.ts +test/bundler/bundler_compile.test.ts +test/bundler/bundler_decorator_metadata.test.ts +test/bundler/bundler_defer.test.ts +test/bundler/bundler_drop.test.ts +test/bundler/bundler_env.test.ts +test/bundler/bundler_footer.test.ts +test/bundler/bundler_html.test.ts +test/bundler/bundler_jsx.test.ts +test/bundler/bundler_minify.test.ts +test/bundler/bundler_naming.test.ts +test/bundler/bundler_plugin.test.ts +test/bundler/bundler_regressions.test.ts +test/bundler/bundler_string.test.ts +test/bundler/css/css-modules.test.ts +test/bundler/css/wpt/background-computed.test.ts +test/bundler/css/wpt/color-computed-rgb.test.ts +test/bundler/css/wpt/color-computed.test.ts +test/bundler/css/wpt/relative_color_out_of_gamut.test.ts +test/bundler/esbuild/css.test.ts +test/bundler/esbuild/dce.test.ts +test/bundler/esbuild/extra.test.ts +test/bundler/esbuild/importstar_ts.test.ts +test/bundler/esbuild/importstar.test.ts +test/bundler/esbuild/loader.test.ts +test/bundler/esbuild/lower.test.ts +test/bundler/esbuild/packagejson.test.ts +test/bundler/esbuild/splitting.test.ts +test/bundler/esbuild/ts.test.ts +test/bundler/esbuild/tsconfig.test.ts +test/bundler/html-import-manifest.test.ts +test/bundler/transpiler/bun-pragma.test.ts +test/bundler/transpiler/jsx-production.test.ts +test/bundler/transpiler/macro-test.test.ts +test/bundler/transpiler/runtime-transpiler.test.ts +test/bundler/transpiler/transpiler.test.js +test/cli/init/init.test.ts +test/cli/install/bun-add.test.ts +test/cli/install/bun-audit.test.ts +test/cli/install/bun-create.test.ts +test/cli/install/bun-info.test.ts +test/cli/install/bun-install-dep.test.ts +test/cli/install/bun-install-lifecycle-scripts.test.ts +test/cli/install/bun-install-patch.test.ts +test/cli/install/bun-install-registry.test.ts +test/cli/install/bun-install-retry.test.ts +test/cli/install/bun-link.test.ts +test/cli/install/bun-lock.test.ts +test/cli/install/bun-lockb.test.ts +test/cli/install/bun-pack.test.ts +test/cli/install/bun-patch.test.ts +test/cli/install/bun-pm.test.ts +test/cli/install/bun-publish.test.ts +test/cli/install/bun-remove.test.ts +test/cli/install/bun-update.test.ts +test/cli/install/bun-upgrade.test.ts +test/cli/install/bun-workspaces.test.ts +test/cli/install/bunx.test.ts +test/cli/install/catalogs.test.ts +test/cli/install/npmrc.test.ts +test/cli/install/overrides.test.ts +test/cli/run/env.test.ts +test/cli/run/esm-defineProperty.test.ts +test/cli/run/jsx-namespaced-attributes.test.ts +test/cli/run/log-test.test.ts +test/cli/run/require-and-import-trailing.test.ts +test/cli/run/run-autoinstall.test.ts +test/cli/run/run-eval.test.ts +test/cli/run/self-reference.test.ts +test/cli/run/shell-keepalive.test.ts +test/cli/test/bun-test.test.ts +test/cli/watch/watch.test.ts +test/config/bunfig/preload.test.ts +test/integration/bun-types/bun-types.test.ts +test/integration/bun-types/fixture/serve-types.test.ts +test/integration/esbuild/esbuild.test.ts +test/integration/jsdom/jsdom.test.ts +test/integration/mysql2/mysql2.test.ts +test/integration/nest/nest_metadata.test.ts +test/integration/sass/sass.test.ts +test/integration/sharp/sharp.test.ts +test/integration/svelte/client-side.test.ts +test/integration/typegraphql/src/typegraphql.test.ts +test/internal/bindgen.test.ts +test/js/bun/bun-object/deep-match.spec.ts +test/js/bun/bun-object/write.spec.ts +test/js/bun/console/bun-inspect-table.test.ts +test/js/bun/console/console-iterator.test.ts +test/js/bun/console/console-table.test.ts +test/js/bun/cookie/cookie-expires-validation.test.ts +test/js/bun/cookie/cookie-map.test.ts +test/js/bun/cookie/cookie.test.ts +test/js/bun/crypto/cipheriv-decipheriv.test.ts +test/js/bun/crypto/wpt-webcrypto.generateKey.test.ts +test/js/bun/dns/resolve-dns.test.ts +test/js/bun/glob/scan.test.ts +test/js/bun/globals.test.js +test/js/bun/http/async-iterator-stream.test.ts +test/js/bun/http/bun-connect-x509.test.ts +test/js/bun/http/bun-serve-args.test.ts +test/js/bun/http/bun-serve-cookies.test.ts +test/js/bun/http/bun-serve-file.test.ts +test/js/bun/http/bun-serve-headers.test.ts +test/js/bun/http/bun-serve-html-entry.test.ts +test/js/bun/http/bun-serve-html.test.ts +test/js/bun/http/bun-serve-routes.test.ts +test/js/bun/http/bun-serve-static.test.ts +test/js/bun/http/bun-server.test.ts +test/js/bun/http/decodeURIComponentSIMD.test.ts +test/js/bun/http/fetch-file-upload.test.ts +test/js/bun/http/hspec.test.ts +test/js/bun/http/http-server-chunking.test.ts +test/js/bun/http/http-spec.ts +test/js/bun/http/leaks-test.test.ts +test/js/bun/http/proxy.test.ts +test/js/bun/http/serve-body-leak.test.ts +test/js/bun/http/serve-listen.test.ts +test/js/bun/http/serve.test.ts +test/js/bun/import-attributes/import-attributes.test.ts +test/js/bun/ini/ini.test.ts +test/js/bun/io/bun-write.test.js +test/js/bun/jsc/bun-jsc.test.ts +test/js/bun/jsc/domjit.test.ts +test/js/bun/net/socket.test.ts +test/js/bun/net/tcp-server.test.ts +test/js/bun/net/tcp.spec.ts +test/js/bun/net/tcp.test.ts +test/js/bun/patch/patch.test.ts +test/js/bun/perf_hooks/histogram.test.ts +test/js/bun/plugin/plugins.test.ts +test/js/bun/resolve/build-error.test.ts +test/js/bun/resolve/bun-lock.test.ts +test/js/bun/resolve/esModule-annotation.test.js +test/js/bun/resolve/import-custom-condition.test.ts +test/js/bun/resolve/import-empty.test.js +test/js/bun/resolve/import-meta-resolve.test.mjs +test/js/bun/resolve/import-meta.test.js +test/js/bun/resolve/jsonc.test.ts +test/js/bun/resolve/require.test.ts +test/js/bun/resolve/toml/toml.test.js +test/js/bun/s3/s3-insecure.test.ts +test/js/bun/s3/s3-list-objects.test.ts +test/js/bun/s3/s3-storage-class.test.ts +test/js/bun/s3/s3.test.ts +test/js/bun/shell/bunshell-default.test.ts +test/js/bun/shell/bunshell-file.test.ts +test/js/bun/shell/bunshell-instance.test.ts +test/js/bun/shell/commands/basename.test.ts +test/js/bun/shell/commands/dirname.test.ts +test/js/bun/shell/commands/exit.test.ts +test/js/bun/shell/commands/false.test.ts +test/js/bun/shell/commands/mv.test.ts +test/js/bun/shell/commands/rm.test.ts +test/js/bun/shell/commands/seq.test.ts +test/js/bun/shell/commands/true.test.ts +test/js/bun/shell/commands/which.test.ts +test/js/bun/shell/commands/yes.test.ts +test/js/bun/shell/env.positionals.test.ts +test/js/bun/shell/exec.test.ts +test/js/bun/shell/lazy.test.ts +test/js/bun/shell/leak.test.ts +test/js/bun/shell/lex.test.ts +test/js/bun/shell/shell-hang.test.ts +test/js/bun/shell/shell-load.test.ts +test/js/bun/shell/shelloutput.test.ts +test/js/bun/shell/throw.test.ts +test/js/bun/spawn/bun-ipc-inherit.test.ts +test/js/bun/spawn/job-object-bug.test.ts +test/js/bun/spawn/spawn_waiter_thread.test.ts +test/js/bun/spawn/spawn-empty-arrayBufferOrBlob.test.ts +test/js/bun/spawn/spawn-path.test.ts +test/js/bun/spawn/spawn-stdin-destroy.test.ts +test/js/bun/spawn/spawn-stream-serve.test.ts +test/js/bun/spawn/spawn-streaming-stdout.test.ts +test/js/bun/spawn/spawn-stress.test.ts +test/js/bun/spawn/spawn.ipc.bun-node.test.ts +test/js/bun/spawn/spawn.ipc.node-bun.test.ts +test/js/bun/spawn/spawn.ipc.test.ts +test/js/bun/sqlite/sql-timezone.test.js +test/js/bun/stream/direct-readable-stream.test.tsx +test/js/bun/symbols.test.ts +test/js/bun/test/done-async.test.ts +test/js/bun/test/expect-assertions.test.ts +test/js/bun/test/jest-extended.test.js +test/js/bun/test/mock-fn.test.js +test/js/bun/test/mock/6874/A.test.ts +test/js/bun/test/mock/6874/B.test.ts +test/js/bun/test/mock/6879/6879.test.ts +test/js/bun/test/mock/mock-module.test.ts +test/js/bun/test/snapshot-tests/bun-snapshots.test.ts +test/js/bun/test/snapshot-tests/existing-snapshots.test.ts +test/js/bun/test/snapshot-tests/new-snapshot.test.ts +test/js/bun/test/snapshot-tests/snapshots/more.test.ts +test/js/bun/test/snapshot-tests/snapshots/moremore.test.ts +test/js/bun/test/snapshot-tests/snapshots/snapshot.test.ts +test/js/bun/test/stack.test.ts +test/js/bun/test/test-failing.test.ts +test/js/bun/test/test-only.test.ts +test/js/bun/test/test-test.test.ts +test/js/bun/udp/dgram.test.ts +test/js/bun/udp/udp_socket.test.ts +test/js/bun/util/arraybuffersink.test.ts +test/js/bun/util/bun-cryptohasher.test.ts +test/js/bun/util/bun-file-exists.test.js +test/js/bun/util/bun-file.test.ts +test/js/bun/util/bun-isMainThread.test.js +test/js/bun/util/BunObject.test.ts +test/js/bun/util/concat.test.js +test/js/bun/util/cookie.test.js +test/js/bun/util/error-gc-test.test.js +test/js/bun/util/escapeHTML.test.js +test/js/bun/util/filesink.test.ts +test/js/bun/util/filesystem_router.test.ts +test/js/bun/util/fileUrl.test.js +test/js/bun/util/fuzzy-wuzzy.test.ts +test/js/bun/util/hash.test.js +test/js/bun/util/heap-snapshot.test.ts +test/js/bun/util/index-of-line.test.ts +test/js/bun/util/inspect-error.test.js +test/js/bun/util/inspect.test.js +test/js/bun/util/mmap.test.js +test/js/bun/util/password.test.ts +test/js/bun/util/readablestreamtoarraybuffer.test.ts +test/js/bun/util/stringWidth.test.ts +test/js/bun/util/text-loader.test.ts +test/js/bun/util/unsafe.test.js +test/js/bun/util/v8-heap-snapshot.test.ts +test/js/bun/util/which.test.ts +test/js/bun/util/zstd.test.ts +test/js/bun/websocket/websocket-server.test.ts +test/js/deno/abort/abort-controller.test.ts +test/js/deno/crypto/random.test.ts +test/js/deno/crypto/webcrypto.test.ts +test/js/deno/encoding/encoding.test.ts +test/js/deno/event/custom-event.test.ts +test/js/deno/event/event-target.test.ts +test/js/deno/event/event.test.ts +test/js/deno/fetch/blob.test.ts +test/js/deno/fetch/body.test.ts +test/js/deno/fetch/headers.test.ts +test/js/deno/fetch/request.test.ts +test/js/deno/fetch/response.test.ts +test/js/deno/performance/performance.test.ts +test/js/deno/url/url.test.ts +test/js/deno/url/urlsearchparams.test.ts +test/js/deno/v8/error.test.ts +test/js/first_party/undici/undici.test.ts +test/js/junit-reporter/junit.test.js +test/js/node/assert/assert-promise.test.ts +test/js/node/assert/assert.spec.ts +test/js/node/async_hooks/AsyncLocalStorage.test.ts +test/js/node/buffer-concat.test.ts +test/js/node/buffer.test.js +test/js/node/child_process/child_process_ipc_large_disconnect.test.js +test/js/node/child_process/child_process_ipc.test.js +test/js/node/child_process/child_process_send_cb.test.js +test/js/node/child_process/child_process-node.test.js +test/js/node/child_process/child-process-exec.test.ts +test/js/node/child_process/child-process-stdio.test.js +test/js/node/cluster.test.ts +test/js/node/cluster/test-docs-http-server.ts +test/js/node/cluster/test-worker-no-exit-http.ts +test/js/node/crypto/crypto-hmac-algorithm.test.ts +test/js/node/crypto/crypto-oneshot.test.ts +test/js/node/crypto/crypto-random.test.ts +test/js/node/crypto/crypto-rsa.test.js +test/js/node/crypto/crypto.hmac.test.ts +test/js/node/crypto/crypto.key-objects.test.ts +test/js/node/crypto/crypto.test.ts +test/js/node/crypto/ecdh.test.ts +test/js/node/crypto/node-crypto.test.js +test/js/node/crypto/pbkdf2.test.ts +test/js/node/diagnostics_channel/diagnostics_channel.test.ts +test/js/node/dns/dns-lookup-keepalive.test.ts +test/js/node/dns/node-dns.test.js +test/js/node/events/event-emitter.test.ts +test/js/node/fs/cp.test.ts +test/js/node/fs/dir.test.ts +test/js/node/fs/fs-leak.test.js +test/js/node/fs/fs-mkdir.test.ts +test/js/node/fs/fs-oom.test.ts +test/js/node/fs/fs-promises-writeFile-async-iterator.test.ts +test/js/node/fs/fs-stats-truncate.test.ts +test/js/node/fs/fs.test.ts +test/js/node/fs/glob.test.ts +test/js/node/fs/promises.test.js +test/js/node/http/client-timeout-error.test.ts +test/js/node/http/node-fetch.test.js +test/js/node/http/node-http-backpressure.test.ts +test/js/node/http/node-http-parser.test.ts +test/js/node/http/node-http-primoridals.test.ts +test/js/node/http/node-http-transfer-encoding.test.ts +test/js/node/http/node-http.test.ts +test/js/node/http/numeric-header.test.ts +test/js/node/module/node-module-module.test.js +test/js/node/module/require-extensions.test.ts +test/js/node/net/double-connect.test.ts +test/js/node/net/node-net-allowHalfOpen.test.js +test/js/node/net/node-net-server.test.ts +test/js/node/net/node-net.test.ts +test/js/node/net/server.spec.ts +test/js/node/no-addons.test.ts +test/js/node/os/os.test.js +test/js/node/path/browserify.test.js +test/js/node/path/matches-glob.test.ts +test/js/node/path/parse-format.test.js +test/js/node/path/to-namespaced-path.test.js +test/js/node/process/call-constructor.test.js +test/js/node/process/process-args.test.js +test/js/node/process/process-nexttick.test.js +test/js/node/process/process-stdin.test.ts +test/js/node/process/process-stdio.test.ts +test/js/node/process/process.test.js +test/js/node/promise/reject-tostring.test.ts +test/js/node/readline/pause_stdin_should_exit.test.ts +test/js/node/readline/readline_never_unrefs.test.ts +test/js/node/readline/readline_promises.node.test.ts +test/js/node/readline/readline.node.test.ts +test/js/node/readline/stdin_fell_asleep.test.ts +test/js/node/stream/node-stream-uint8array.test.ts +test/js/node/stream/node-stream.test.js +test/js/node/string_decoder/string-decoder.test.js +test/js/node/string-module.test.js +test/js/node/stubs.test.js +test/js/node/test_runner/node-test.test.ts +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-buffer-alloc.js +test/js/node/test/parallel/test-buffer-arraybuffer.js +test/js/node/test/parallel/test-buffer-ascii.js +test/js/node/test/parallel/test-buffer-backing-arraybuffer.js +test/js/node/test/parallel/test-buffer-badhex.js +test/js/node/test/parallel/test-buffer-bigint64.js +test/js/node/test/parallel/test-buffer-bytelength.js +test/js/node/test/parallel/test-buffer-compare-offset.js +test/js/node/test/parallel/test-buffer-compare.js +test/js/node/test/parallel/test-buffer-concat.js +test/js/node/test/parallel/test-buffer-constants.js +test/js/node/test/parallel/test-buffer-constructor-deprecation-error.js +test/js/node/test/parallel/test-buffer-constructor-node-modules-paths.js +test/js/node/test/parallel/test-buffer-constructor-node-modules.js +test/js/node/test/parallel/test-buffer-constructor-outside-node-modules.js +test/js/node/test/parallel/test-buffer-copy.js +test/js/node/test/parallel/test-buffer-equals.js +test/js/node/test/parallel/test-buffer-failed-alloc-typed-arrays.js +test/js/node/test/parallel/test-buffer-fakes.js +test/js/node/test/parallel/test-buffer-fill.js +test/js/node/test/parallel/test-buffer-from.js +test/js/node/test/parallel/test-buffer-includes.js +test/js/node/test/parallel/test-buffer-indexof.js +test/js/node/test/parallel/test-buffer-inheritance.js +test/js/node/test/parallel/test-buffer-inspect.js +test/js/node/test/parallel/test-buffer-isascii.js +test/js/node/test/parallel/test-buffer-isencoding.js +test/js/node/test/parallel/test-buffer-isutf8.js +test/js/node/test/parallel/test-buffer-iterator.js +test/js/node/test/parallel/test-buffer-new.js +test/js/node/test/parallel/test-buffer-no-negative-allocation.js +test/js/node/test/parallel/test-buffer-nopendingdep-map.js +test/js/node/test/parallel/test-buffer-of-no-deprecation.js +test/js/node/test/parallel/test-buffer-over-max-length.js +test/js/node/test/parallel/test-buffer-parent-property.js +test/js/node/test/parallel/test-buffer-pending-deprecation.js +test/js/node/test/parallel/test-buffer-pool-untransferable.js +test/js/node/test/parallel/test-buffer-prototype-inspect.js +test/js/node/test/parallel/test-buffer-read.js +test/js/node/test/parallel/test-buffer-readdouble.js +test/js/node/test/parallel/test-buffer-readfloat.js +test/js/node/test/parallel/test-buffer-readint.js +test/js/node/test/parallel/test-buffer-readuint.js +test/js/node/test/parallel/test-buffer-safe-unsafe.js +test/js/node/test/parallel/test-buffer-set-inspect-max-bytes.js +test/js/node/test/parallel/test-buffer-sharedarraybuffer.js +test/js/node/test/parallel/test-buffer-slice.js +test/js/node/test/parallel/test-buffer-slow.js +test/js/node/test/parallel/test-buffer-swap.js +test/js/node/test/parallel/test-buffer-tojson.js +test/js/node/test/parallel/test-buffer-tostring-range.js +test/js/node/test/parallel/test-buffer-tostring-rangeerror.js +test/js/node/test/parallel/test-buffer-tostring.js +test/js/node/test/parallel/test-buffer-write-fast.js +test/js/node/test/parallel/test-buffer-write.js +test/js/node/test/parallel/test-buffer-writedouble.js +test/js/node/test/parallel/test-buffer-writefloat.js +test/js/node/test/parallel/test-buffer-writeint.js +test/js/node/test/parallel/test-buffer-writeuint.js +test/js/node/test/parallel/test-buffer-zero-fill-cli.js +test/js/node/test/parallel/test-buffer-zero-fill-reset.js +test/js/node/test/parallel/test-buffer-zero-fill.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-maxbuf.js +test/js/node/test/parallel/test-child-process-execFile-promisified-abortController.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-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-cluster-advanced-serialization.js +test/js/node/test/parallel/test-cluster-bind-privileged-port.js +test/js/node/test/parallel/test-cluster-call-and-destroy.js +test/js/node/test/parallel/test-cluster-child-index-dgram.js +test/js/node/test/parallel/test-cluster-child-index-net.js +test/js/node/test/parallel/test-cluster-concurrent-disconnect.js +test/js/node/test/parallel/test-cluster-cwd.js +test/js/node/test/parallel/test-cluster-dgram-ipv6only.js +test/js/node/test/parallel/test-cluster-dgram-reuse.js +test/js/node/test/parallel/test-cluster-dgram-reuseport.js +test/js/node/test/parallel/test-cluster-disconnect-before-exit.js +test/js/node/test/parallel/test-cluster-disconnect-exitedAfterDisconnect-race.js +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-cluster-disconnect-with-no-workers.js +test/js/node/test/parallel/test-cluster-eaddrinuse.js +test/js/node/test/parallel/test-cluster-fork-env.js +test/js/node/test/parallel/test-cluster-fork-windowsHide.js +test/js/node/test/parallel/test-cluster-http-pipe.js +test/js/node/test/parallel/test-cluster-invalid-message.js +test/js/node/test/parallel/test-cluster-ipc-throw.js +test/js/node/test/parallel/test-cluster-kill-disconnect.js +test/js/node/test/parallel/test-cluster-kill-infinite-loop.js +test/js/node/test/parallel/test-cluster-listening-port.js +test/js/node/test/parallel/test-cluster-message.js +test/js/node/test/parallel/test-cluster-net-listen.js +test/js/node/test/parallel/test-cluster-primary-error.js +test/js/node/test/parallel/test-cluster-primary-kill.js +test/js/node/test/parallel/test-cluster-process-disconnect.js +test/js/node/test/parallel/test-cluster-rr-domain-listen.js +test/js/node/test/parallel/test-cluster-rr-handle-keep-loop-alive.js +test/js/node/test/parallel/test-cluster-rr-ref.js +test/js/node/test/parallel/test-cluster-send-deadlock.js +test/js/node/test/parallel/test-cluster-setup-primary-argv.js +test/js/node/test/parallel/test-cluster-setup-primary-cumulative.js +test/js/node/test/parallel/test-cluster-setup-primary-emit.js +test/js/node/test/parallel/test-cluster-setup-primary-multiple.js +test/js/node/test/parallel/test-cluster-setup-primary.js +test/js/node/test/parallel/test-cluster-shared-handle-bind-privileged-port.js +test/js/node/test/parallel/test-cluster-uncaught-exception.js +test/js/node/test/parallel/test-cluster-worker-constructor.js +test/js/node/test/parallel/test-cluster-worker-death.js +test/js/node/test/parallel/test-cluster-worker-destroy.js +test/js/node/test/parallel/test-cluster-worker-disconnect-on-error.js +test/js/node/test/parallel/test-cluster-worker-disconnect.js +test/js/node/test/parallel/test-cluster-worker-events.js +test/js/node/test/parallel/test-cluster-worker-exit.js +test/js/node/test/parallel/test-cluster-worker-forced-exit.js +test/js/node/test/parallel/test-cluster-worker-init.js +test/js/node/test/parallel/test-cluster-worker-isconnected.js +test/js/node/test/parallel/test-cluster-worker-isdead.js +test/js/node/test/parallel/test-cluster-worker-kill-signal.js +test/js/node/test/parallel/test-cluster-worker-kill.js +test/js/node/test/parallel/test-cluster-worker-no-exit.js +test/js/node/test/parallel/test-cluster-worker-wait-server-close.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-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-dns-cancel-reverse-lookup.js +test/js/node/test/parallel/test-dns-channel-cancel-promise.js +test/js/node/test/parallel/test-dns-channel-cancel.js +test/js/node/test/parallel/test-dns-channel-timeout.js +test/js/node/test/parallel/test-dns-default-order-ipv4.js +test/js/node/test/parallel/test-dns-default-order-ipv6.js +test/js/node/test/parallel/test-dns-default-order-verbatim.js +test/js/node/test/parallel/test-dns-get-server.js +test/js/node/test/parallel/test-dns-lookup-promises-options-deprecated.js +test/js/node/test/parallel/test-dns-lookup.js +test/js/node/test/parallel/test-dns-lookupService-promises.js +test/js/node/test/parallel/test-dns-lookupService.js +test/js/node/test/parallel/test-dns-multi-channel.js +test/js/node/test/parallel/test-dns-promises-exists.js +test/js/node/test/parallel/test-dns-resolve-promises.js +test/js/node/test/parallel/test-dns-resolveany-bad-ancount.js +test/js/node/test/parallel/test-dns-resolveany.js +test/js/node/test/parallel/test-dns-resolvens-typeerror.js +test/js/node/test/parallel/test-dns-set-default-order.js +test/js/node/test/parallel/test-dns-setlocaladdress.js +test/js/node/test/parallel/test-dns-setserver-when-querying.js +test/js/node/test/parallel/test-dns-setservers-type-check.js +test/js/node/test/parallel/test-dns.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-file-read-noexist.js +test/js/node/test/parallel/test-file-validate-mode-flag.js +test/js/node/test/parallel/test-file-write-stream.js +test/js/node/test/parallel/test-file-write-stream2.js +test/js/node/test/parallel/test-file-write-stream3.js +test/js/node/test/parallel/test-file-write-stream4.js +test/js/node/test/parallel/test-filehandle-close.js +test/js/node/test/parallel/test-finalization-registry-shutdown.js +test/js/node/test/parallel/test-fs-access.js +test/js/node/test/parallel/test-fs-append-file-flush.js +test/js/node/test/parallel/test-fs-append-file-sync.js +test/js/node/test/parallel/test-fs-append-file.js +test/js/node/test/parallel/test-fs-assert-encoding-error.js +test/js/node/test/parallel/test-fs-buffer.js +test/js/node/test/parallel/test-fs-buffertype-writesync.js +test/js/node/test/parallel/test-fs-chmod-mask.js +test/js/node/test/parallel/test-fs-chmod.js +test/js/node/test/parallel/test-fs-chown-type-check.js +test/js/node/test/parallel/test-fs-close-errors.js +test/js/node/test/parallel/test-fs-close.js +test/js/node/test/parallel/test-fs-constants.js +test/js/node/test/parallel/test-fs-copyfile-respect-permissions.js +test/js/node/test/parallel/test-fs-copyfile.js +test/js/node/test/parallel/test-fs-empty-readStream.js +test/js/node/test/parallel/test-fs-exists.js +test/js/node/test/parallel/test-fs-existssync-false.js +test/js/node/test/parallel/test-fs-fchmod.js +test/js/node/test/parallel/test-fs-fchown.js +test/js/node/test/parallel/test-fs-filehandle-use-after-close.js +test/js/node/test/parallel/test-fs-fsync.js +test/js/node/test/parallel/test-fs-lchmod.js +test/js/node/test/parallel/test-fs-lchown.js +test/js/node/test/parallel/test-fs-link.js +test/js/node/test/parallel/test-fs-long-path.js +test/js/node/test/parallel/test-fs-make-callback.js +test/js/node/test/parallel/test-fs-makeStatsCallback.js +test/js/node/test/parallel/test-fs-mkdir-mode-mask.js +test/js/node/test/parallel/test-fs-mkdir-recursive-eaccess.js +test/js/node/test/parallel/test-fs-mkdir-rmdir.js +test/js/node/test/parallel/test-fs-mkdir.js +test/js/node/test/parallel/test-fs-mkdtemp-prefix-check.js +test/js/node/test/parallel/test-fs-mkdtemp.js +test/js/node/test/parallel/test-fs-non-number-arguments-throw.js +test/js/node/test/parallel/test-fs-null-bytes.js +test/js/node/test/parallel/test-fs-open-mode-mask.js +test/js/node/test/parallel/test-fs-open-no-close.js +test/js/node/test/parallel/test-fs-open-numeric-flags.js +test/js/node/test/parallel/test-fs-open.js +test/js/node/test/parallel/test-fs-options-immutable.js +test/js/node/test/parallel/test-fs-promises-exists.js +test/js/node/test/parallel/test-fs-promises-file-handle-append-file.js +test/js/node/test/parallel/test-fs-promises-file-handle-chmod.js +test/js/node/test/parallel/test-fs-promises-file-handle-dispose.js +test/js/node/test/parallel/test-fs-promises-file-handle-read-worker.js +test/js/node/test/parallel/test-fs-promises-file-handle-read.js +test/js/node/test/parallel/test-fs-promises-file-handle-readFile.js +test/js/node/test/parallel/test-fs-promises-file-handle-stat.js +test/js/node/test/parallel/test-fs-promises-file-handle-stream.js +test/js/node/test/parallel/test-fs-promises-file-handle-sync.js +test/js/node/test/parallel/test-fs-promises-file-handle-truncate.js +test/js/node/test/parallel/test-fs-promises-file-handle-write.js +test/js/node/test/parallel/test-fs-promises-file-handle-writeFile.js +test/js/node/test/parallel/test-fs-promises-readfile-empty.js +test/js/node/test/parallel/test-fs-promises-readfile-with-fd.js +test/js/node/test/parallel/test-fs-promises-readfile.js +test/js/node/test/parallel/test-fs-promises-write-optional-params.js +test/js/node/test/parallel/test-fs-promises-writefile-typedarray.js +test/js/node/test/parallel/test-fs-promises-writefile-with-fd.js +test/js/node/test/parallel/test-fs-promises-writefile.js +test/js/node/test/parallel/test-fs-promisified.js +test/js/node/test/parallel/test-fs-read-empty-buffer.js +test/js/node/test/parallel/test-fs-read-file-assert-encoding.js +test/js/node/test/parallel/test-fs-read-file-sync-hostname.js +test/js/node/test/parallel/test-fs-read-file-sync.js +test/js/node/test/parallel/test-fs-read-offset-null.js +test/js/node/test/parallel/test-fs-read-optional-params.js +test/js/node/test/parallel/test-fs-read-position-validation.mjs +test/js/node/test/parallel/test-fs-read-promises-optional-params.js +test/js/node/test/parallel/test-fs-read-promises-position-validation.mjs +test/js/node/test/parallel/test-fs-read-stream-autoClose.js +test/js/node/test/parallel/test-fs-read-stream-concurrent-reads.js +test/js/node/test/parallel/test-fs-read-stream-double-close.js +test/js/node/test/parallel/test-fs-read-stream-encoding.js +test/js/node/test/parallel/test-fs-read-stream-err.js +test/js/node/test/parallel/test-fs-read-stream-fd-leak.js +test/js/node/test/parallel/test-fs-read-stream-fd.js +test/js/node/test/parallel/test-fs-read-stream-file-handle.js +test/js/node/test/parallel/test-fs-read-stream-inherit.js +test/js/node/test/parallel/test-fs-read-stream-patch-open.js +test/js/node/test/parallel/test-fs-read-stream-resume.js +test/js/node/test/parallel/test-fs-read-stream-throw-type-error.js +test/js/node/test/parallel/test-fs-read-type.js +test/js/node/test/parallel/test-fs-read-zero-length.js +test/js/node/test/parallel/test-fs-read.js +test/js/node/test/parallel/test-fs-readdir-buffer.js +test/js/node/test/parallel/test-fs-readdir-pipe.js +test/js/node/test/parallel/test-fs-readdir-recursive.js +test/js/node/test/parallel/test-fs-readdir-stack-overflow.js +test/js/node/test/parallel/test-fs-readdir-types-symlinks.js +test/js/node/test/parallel/test-fs-readdir-types.js +test/js/node/test/parallel/test-fs-readdir-ucs2.js +test/js/node/test/parallel/test-fs-readdir.js +test/js/node/test/parallel/test-fs-readfile-empty.js +test/js/node/test/parallel/test-fs-readfile-eof.js +test/js/node/test/parallel/test-fs-readfile-error.js +test/js/node/test/parallel/test-fs-readfile-fd.js +test/js/node/test/parallel/test-fs-readfile-flags.js +test/js/node/test/parallel/test-fs-readfile-pipe-large.js +test/js/node/test/parallel/test-fs-readfile-pipe.js +test/js/node/test/parallel/test-fs-readfile-unlink.js +test/js/node/test/parallel/test-fs-readfile-zero-byte-liar.js +test/js/node/test/parallel/test-fs-readfile.js +test/js/node/test/parallel/test-fs-readfilesync-enoent.js +test/js/node/test/parallel/test-fs-readfilesync-pipe-large.js +test/js/node/test/parallel/test-fs-readlink-type-check.js +test/js/node/test/parallel/test-fs-readSync-optional-params.js +test/js/node/test/parallel/test-fs-readSync-position-validation.mjs +test/js/node/test/parallel/test-fs-readv-promises.js +test/js/node/test/parallel/test-fs-readv-promisify.js +test/js/node/test/parallel/test-fs-readv-sync.js +test/js/node/test/parallel/test-fs-readv.js +test/js/node/test/parallel/test-fs-ready-event-stream.js +test/js/node/test/parallel/test-fs-realpath-buffer-encoding.js +test/js/node/test/parallel/test-fs-realpath-native.js +test/js/node/test/parallel/test-fs-realpath-on-substed-drive.js +test/js/node/test/parallel/test-fs-realpath-pipe.js +test/js/node/test/parallel/test-fs-realpath.js +test/js/node/test/parallel/test-fs-rename-type-check.js +test/js/node/test/parallel/test-fs-rmdir-recursive-sync-warns-not-found.js +test/js/node/test/parallel/test-fs-rmdir-recursive-sync-warns-on-file.js +test/js/node/test/parallel/test-fs-rmdir-recursive-throws-not-found.js +test/js/node/test/parallel/test-fs-rmdir-recursive-throws-on-file.js +test/js/node/test/parallel/test-fs-rmdir-recursive-warns-not-found.js +test/js/node/test/parallel/test-fs-rmdir-recursive-warns-on-file.js +test/js/node/test/parallel/test-fs-rmdir-recursive.js +test/js/node/test/parallel/test-fs-rmdir-type-check.js +test/js/node/test/parallel/test-fs-sir-writes-alot.js +test/js/node/test/parallel/test-fs-stat-bigint.js +test/js/node/test/parallel/test-fs-stat-date.mjs +test/js/node/test/parallel/test-fs-stat.js +test/js/node/test/parallel/test-fs-statfs.js +test/js/node/test/parallel/test-fs-stream-construct-compat-error-read.js +test/js/node/test/parallel/test-fs-stream-construct-compat-error-write.js +test/js/node/test/parallel/test-fs-stream-construct-compat-graceful-fs.js +test/js/node/test/parallel/test-fs-stream-construct-compat-old-node.js +test/js/node/test/parallel/test-fs-stream-destroy-emit-error.js +test/js/node/test/parallel/test-fs-stream-double-close.js +test/js/node/test/parallel/test-fs-stream-fs-options.js +test/js/node/test/parallel/test-fs-stream-options.js +test/js/node/test/parallel/test-fs-symlink-buffer-path.js +test/js/node/test/parallel/test-fs-symlink-dir-junction-relative.js +test/js/node/test/parallel/test-fs-symlink-dir-junction.js +test/js/node/test/parallel/test-fs-symlink-dir.js +test/js/node/test/parallel/test-fs-symlink-longpath.js +test/js/node/test/parallel/test-fs-symlink.js +test/js/node/test/parallel/test-fs-syncwritestream.js +test/js/node/test/parallel/test-fs-timestamp-parsing-error.js +test/js/node/test/parallel/test-fs-truncate-clear-file-zero.js +test/js/node/test/parallel/test-fs-truncate-fd.js +test/js/node/test/parallel/test-fs-truncate-sync.js +test/js/node/test/parallel/test-fs-truncate.js +test/js/node/test/parallel/test-fs-unlink-type-check.js +test/js/node/test/parallel/test-fs-utimes-y2K38.js +test/js/node/test/parallel/test-fs-watch-abort-signal.js +test/js/node/test/parallel/test-fs-watch-close-when-destroyed.js +test/js/node/test/parallel/test-fs-watch-encoding.js +test/js/node/test/parallel/test-fs-watch-file-enoent-after-deletion.js +test/js/node/test/parallel/test-fs-watch-recursive-add-file-to-existing-subfolder.js +test/js/node/test/parallel/test-fs-watch-recursive-add-file-with-url.js +test/js/node/test/parallel/test-fs-watch-recursive-add-file.js +test/js/node/test/parallel/test-fs-watch-recursive-add-folder.js +test/js/node/test/parallel/test-fs-watch-recursive-assert-leaks.js +test/js/node/test/parallel/test-fs-watch-recursive-delete.js +test/js/node/test/parallel/test-fs-watch-recursive-sync-write.js +test/js/node/test/parallel/test-fs-watch-recursive-validate.js +test/js/node/test/parallel/test-fs-watch-ref-unref.js +test/js/node/test/parallel/test-fs-watch-stop-sync.js +test/js/node/test/parallel/test-fs-watchfile-ref-unref.js +test/js/node/test/parallel/test-fs-whatwg-url.js +test/js/node/test/parallel/test-fs-write-buffer-large.js +test/js/node/test/parallel/test-fs-write-buffer.js +test/js/node/test/parallel/test-fs-write-file-buffer.js +test/js/node/test/parallel/test-fs-write-file-flush.js +test/js/node/test/parallel/test-fs-write-file-invalid-path.js +test/js/node/test/parallel/test-fs-write-file-sync.js +test/js/node/test/parallel/test-fs-write-file-typedarrays.js +test/js/node/test/parallel/test-fs-write-file.js +test/js/node/test/parallel/test-fs-write-negativeoffset.js +test/js/node/test/parallel/test-fs-write-no-fd.js +test/js/node/test/parallel/test-fs-write-optional-params.js +test/js/node/test/parallel/test-fs-write-reuse-callback.js +test/js/node/test/parallel/test-fs-write-sigxfsz.js +test/js/node/test/parallel/test-fs-write-stream-autoclose-option.js +test/js/node/test/parallel/test-fs-write-stream-change-open.js +test/js/node/test/parallel/test-fs-write-stream-close-without-callback.js +test/js/node/test/parallel/test-fs-write-stream-double-close.js +test/js/node/test/parallel/test-fs-write-stream-encoding.js +test/js/node/test/parallel/test-fs-write-stream-end.js +test/js/node/test/parallel/test-fs-write-stream-err.js +test/js/node/test/parallel/test-fs-write-stream-file-handle-2.js +test/js/node/test/parallel/test-fs-write-stream-file-handle.js +test/js/node/test/parallel/test-fs-write-stream-flush.js +test/js/node/test/parallel/test-fs-write-stream-fs.js +test/js/node/test/parallel/test-fs-write-stream-patch-open.js +test/js/node/test/parallel/test-fs-write-stream-throw-type-error.js +test/js/node/test/parallel/test-fs-write-stream.js +test/js/node/test/parallel/test-fs-write-sync.js +test/js/node/test/parallel/test-fs-writefile-with-fd.js +test/js/node/test/parallel/test-fs-writestream-open-write.js +test/js/node/test/parallel/test-fs-writev-promises.js +test/js/node/test/parallel/test-fs-writev-sync.js +test/js/node/test/parallel/test-fs-writev.js +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-net-access-byteswritten.js +test/js/node/test/parallel/test-net-after-close.js +test/js/node/test/parallel/test-net-autoselectfamily-attempt-timeout-default-value.js +test/js/node/test/parallel/test-net-autoselectfamily-default.js +test/js/node/test/parallel/test-net-autoselectfamily-ipv4first.js +test/js/node/test/parallel/test-net-better-error-messages-listen-path.js +test/js/node/test/parallel/test-net-better-error-messages-listen.js +test/js/node/test/parallel/test-net-better-error-messages-port-hostname.js +test/js/node/test/parallel/test-net-bind-twice.js +test/js/node/test/parallel/test-net-blocklist.js +test/js/node/test/parallel/test-net-buffersize.js +test/js/node/test/parallel/test-net-bytes-written-large.js +test/js/node/test/parallel/test-net-can-reset-timeout.js +test/js/node/test/parallel/test-net-child-process-connect-reset.js +test/js/node/test/parallel/test-net-connect-abort-controller.js +test/js/node/test/parallel/test-net-connect-after-destroy.js +test/js/node/test/parallel/test-net-connect-buffer.js +test/js/node/test/parallel/test-net-connect-buffer2.js +test/js/node/test/parallel/test-net-connect-call-socket-connect.js +test/js/node/test/parallel/test-net-connect-destroy.js +test/js/node/test/parallel/test-net-connect-immediate-destroy.js +test/js/node/test/parallel/test-net-connect-immediate-finish.js +test/js/node/test/parallel/test-net-connect-no-arg.js +test/js/node/test/parallel/test-net-connect-nodelay.js +test/js/node/test/parallel/test-net-connect-options-invalid.js +test/js/node/test/parallel/test-net-connect-options-ipv6.js +test/js/node/test/parallel/test-net-connect-options-path.js +test/js/node/test/parallel/test-net-connect-options-port.js +test/js/node/test/parallel/test-net-connect-reset-before-connected.js +test/js/node/test/parallel/test-net-connect-reset.js +test/js/node/test/parallel/test-net-deprecated-setsimultaneousaccepts.js +test/js/node/test/parallel/test-net-dns-custom-lookup.js +test/js/node/test/parallel/test-net-dns-error.js +test/js/node/test/parallel/test-net-dns-lookup-skip.js +test/js/node/test/parallel/test-net-dns-lookup.js +test/js/node/test/parallel/test-net-during-close.js +test/js/node/test/parallel/test-net-eaddrinuse.js +test/js/node/test/parallel/test-net-end-without-connect.js +test/js/node/test/parallel/test-net-isip.js +test/js/node/test/parallel/test-net-isipv4.js +test/js/node/test/parallel/test-net-isipv6.js +test/js/node/test/parallel/test-net-keepalive.js +test/js/node/test/parallel/test-net-listen-after-destroying-stdin.js +test/js/node/test/parallel/test-net-listen-close-server-callback-is-not-function.js +test/js/node/test/parallel/test-net-listen-close-server.js +test/js/node/test/parallel/test-net-listen-error.js +test/js/node/test/parallel/test-net-listen-exclusive-random-ports.js +test/js/node/test/parallel/test-net-listen-handle-in-cluster-1.js +test/js/node/test/parallel/test-net-listen-invalid-port.js +test/js/node/test/parallel/test-net-listen-ipv6only.js +test/js/node/test/parallel/test-net-listening.js +test/js/node/test/parallel/test-net-local-address-port.js +test/js/node/test/parallel/test-net-localerror.js +test/js/node/test/parallel/test-net-options-lookup.js +test/js/node/test/parallel/test-net-persistent-keepalive.js +test/js/node/test/parallel/test-net-reconnect.js +test/js/node/test/parallel/test-net-remote-address-port.js +test/js/node/test/parallel/test-net-remote-address.js +test/js/node/test/parallel/test-net-reuseport.js +test/js/node/test/parallel/test-net-server-async-dispose.mjs +test/js/node/test/parallel/test-net-server-blocklist.js +test/js/node/test/parallel/test-net-server-call-listen-multiple-times.js +test/js/node/test/parallel/test-net-server-close-before-calling-lookup-callback.js +test/js/node/test/parallel/test-net-server-close-before-ipc-response.js +test/js/node/test/parallel/test-net-server-close.js +test/js/node/test/parallel/test-net-server-drop-connections.js +test/js/node/test/parallel/test-net-server-listen-options-signal.js +test/js/node/test/parallel/test-net-server-listen-remove-callback.js +test/js/node/test/parallel/test-net-server-max-connections-close-makes-more-available.js +test/js/node/test/parallel/test-net-server-max-connections.js +test/js/node/test/parallel/test-net-server-options.js +test/js/node/test/parallel/test-net-server-pause-on-connect.js +test/js/node/test/parallel/test-net-server-simultaneous-accepts-produce-warning-once.js +test/js/node/test/parallel/test-net-server-try-ports.js +test/js/node/test/parallel/test-net-server-unref-persistent.js +test/js/node/test/parallel/test-net-server-unref.js +test/js/node/test/parallel/test-net-settimeout.js +test/js/node/test/parallel/test-net-socket-byteswritten.js +test/js/node/test/parallel/test-net-socket-close-after-end.js +test/js/node/test/parallel/test-net-socket-connect-invalid-autoselectfamily.js +test/js/node/test/parallel/test-net-socket-connect-invalid-autoselectfamilyattempttimeout.js +test/js/node/test/parallel/test-net-socket-connect-without-cb.js +test/js/node/test/parallel/test-net-socket-connecting.js +test/js/node/test/parallel/test-net-socket-constructor.js +test/js/node/test/parallel/test-net-socket-destroy-send.js +test/js/node/test/parallel/test-net-socket-destroy-twice.js +test/js/node/test/parallel/test-net-socket-end-before-connect.js +test/js/node/test/parallel/test-net-socket-end-callback.js +test/js/node/test/parallel/test-net-socket-local-address.js +test/js/node/test/parallel/test-net-socket-no-halfopen-enforcer.js +test/js/node/test/parallel/test-net-socket-ready-without-cb.js +test/js/node/test/parallel/test-net-socket-reset-twice.js +test/js/node/test/parallel/test-net-socket-timeout-unref.js +test/js/node/test/parallel/test-net-socket-timeout.js +test/js/node/test/parallel/test-net-socket-write-error.js +test/js/node/test/parallel/test-net-sync-cork.js +test/js/node/test/parallel/test-net-throttle.js +test/js/node/test/parallel/test-net-timeout-no-handle.js +test/js/node/test/parallel/test-net-writable.js +test/js/node/test/parallel/test-net-write-arguments.js +test/js/node/test/parallel/test-net-write-cb-on-destroy-before-connect.js +test/js/node/test/parallel/test-net-write-connect-write.js +test/js/node/test/parallel/test-net-write-fully-async-buffer.js +test/js/node/test/parallel/test-net-write-fully-async-hex-string.js +test/js/node/test/parallel/test-net-write-slow.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-stream-aliases-legacy.js +test/js/node/test/parallel/test-stream-auto-destroy.js +test/js/node/test/parallel/test-stream-await-drain-writers-in-synchronously-recursion-write.js +test/js/node/test/parallel/test-stream-backpressure.js +test/js/node/test/parallel/test-stream-base-prototype-accessors-enumerability.js +test/js/node/test/parallel/test-stream-big-packet.js +test/js/node/test/parallel/test-stream-big-push.js +test/js/node/test/parallel/test-stream-catch-rejections.js +test/js/node/test/parallel/test-stream-compose-operator.js +test/js/node/test/parallel/test-stream-compose.js +test/js/node/test/parallel/test-stream-construct.js +test/js/node/test/parallel/test-stream-consumers.js +test/js/node/test/parallel/test-stream-decoder-objectmode.js +test/js/node/test/parallel/test-stream-destroy-event-order.js +test/js/node/test/parallel/test-stream-drop-take.js +test/js/node/test/parallel/test-stream-duplex-destroy.js +test/js/node/test/parallel/test-stream-duplex-end.js +test/js/node/test/parallel/test-stream-duplex-from.js +test/js/node/test/parallel/test-stream-duplex-props.js +test/js/node/test/parallel/test-stream-duplex-readable-end.js +test/js/node/test/parallel/test-stream-duplex-readable-writable.js +test/js/node/test/parallel/test-stream-duplex-writable-finished.js +test/js/node/test/parallel/test-stream-duplex.js +test/js/node/test/parallel/test-stream-duplexpair.js +test/js/node/test/parallel/test-stream-end-of-streams.js +test/js/node/test/parallel/test-stream-end-paused.js +test/js/node/test/parallel/test-stream-err-multiple-callback-construction.js +test/js/node/test/parallel/test-stream-error-once.js +test/js/node/test/parallel/test-stream-event-names.js +test/js/node/test/parallel/test-stream-events-prepend.js +test/js/node/test/parallel/test-stream-filter.js +test/js/node/test/parallel/test-stream-finished.js +test/js/node/test/parallel/test-stream-flatMap.js +test/js/node/test/parallel/test-stream-forEach.js +test/js/node/test/parallel/test-stream-inheritance.js +test/js/node/test/parallel/test-stream-ispaused.js +test/js/node/test/parallel/test-stream-iterator-helpers-test262-tests.mjs +test/js/node/test/parallel/test-stream-map.js +test/js/node/test/parallel/test-stream-objectmode-undefined.js +test/js/node/test/parallel/test-stream-once-readable-pipe.js +test/js/node/test/parallel/test-stream-passthrough-drain.js +test/js/node/test/parallel/test-stream-pipe-after-end.js +test/js/node/test/parallel/test-stream-pipe-await-drain-manual-resume.js +test/js/node/test/parallel/test-stream-pipe-await-drain-push-while-write.js +test/js/node/test/parallel/test-stream-pipe-await-drain.js +test/js/node/test/parallel/test-stream-pipe-cleanup-pause.js +test/js/node/test/parallel/test-stream-pipe-cleanup.js +test/js/node/test/parallel/test-stream-pipe-deadlock.js +test/js/node/test/parallel/test-stream-pipe-error-handling.js +test/js/node/test/parallel/test-stream-pipe-error-unhandled.js +test/js/node/test/parallel/test-stream-pipe-event.js +test/js/node/test/parallel/test-stream-pipe-flow-after-unpipe.js +test/js/node/test/parallel/test-stream-pipe-flow.js +test/js/node/test/parallel/test-stream-pipe-manual-resume.js +test/js/node/test/parallel/test-stream-pipe-multiple-pipes.js +test/js/node/test/parallel/test-stream-pipe-needDrain.js +test/js/node/test/parallel/test-stream-pipe-same-destination-twice.js +test/js/node/test/parallel/test-stream-pipe-unpipe-streams.js +test/js/node/test/parallel/test-stream-pipe-without-listenerCount.js +test/js/node/test/parallel/test-stream-pipeline-async-iterator.js +test/js/node/test/parallel/test-stream-pipeline-duplex.js +test/js/node/test/parallel/test-stream-pipeline-listeners.js +test/js/node/test/parallel/test-stream-pipeline-process.js +test/js/node/test/parallel/test-stream-pipeline-queued-end-in-destroy.js +test/js/node/test/parallel/test-stream-pipeline-uncaught.js +test/js/node/test/parallel/test-stream-pipeline-with-empty-string.js +test/js/node/test/parallel/test-stream-preprocess.js +test/js/node/test/parallel/test-stream-promises.js +test/js/node/test/parallel/test-stream-push-order.js +test/js/node/test/parallel/test-stream-push-strings.js +test/js/node/test/parallel/test-stream-readable-aborted.js +test/js/node/test/parallel/test-stream-readable-add-chunk-during-data.js +test/js/node/test/parallel/test-stream-readable-constructor-set-methods.js +test/js/node/test/parallel/test-stream-readable-data.js +test/js/node/test/parallel/test-stream-readable-default-encoding.js +test/js/node/test/parallel/test-stream-readable-destroy.js +test/js/node/test/parallel/test-stream-readable-didRead.js +test/js/node/test/parallel/test-stream-readable-dispose.js +test/js/node/test/parallel/test-stream-readable-emit-readable-short-stream.js +test/js/node/test/parallel/test-stream-readable-emittedReadable.js +test/js/node/test/parallel/test-stream-readable-end-destroyed.js +test/js/node/test/parallel/test-stream-readable-ended.js +test/js/node/test/parallel/test-stream-readable-error-end.js +test/js/node/test/parallel/test-stream-readable-event.js +test/js/node/test/parallel/test-stream-readable-flow-recursion.js +test/js/node/test/parallel/test-stream-readable-from-web-termination.js +test/js/node/test/parallel/test-stream-readable-hwm-0-async.js +test/js/node/test/parallel/test-stream-readable-hwm-0-no-flow-data.js +test/js/node/test/parallel/test-stream-readable-hwm-0.js +test/js/node/test/parallel/test-stream-readable-infinite-read.js +test/js/node/test/parallel/test-stream-readable-invalid-chunk.js +test/js/node/test/parallel/test-stream-readable-needReadable.js +test/js/node/test/parallel/test-stream-readable-next-no-null.js +test/js/node/test/parallel/test-stream-readable-no-unneeded-readable.js +test/js/node/test/parallel/test-stream-readable-object-multi-push-async.js +test/js/node/test/parallel/test-stream-readable-pause-and-resume.js +test/js/node/test/parallel/test-stream-readable-readable-then-resume.js +test/js/node/test/parallel/test-stream-readable-readable.js +test/js/node/test/parallel/test-stream-readable-reading-readingMore.js +test/js/node/test/parallel/test-stream-readable-resume-hwm.js +test/js/node/test/parallel/test-stream-readable-resumeScheduled.js +test/js/node/test/parallel/test-stream-readable-setEncoding-existing-buffers.js +test/js/node/test/parallel/test-stream-readable-setEncoding-null.js +test/js/node/test/parallel/test-stream-readable-strategy-option.js +test/js/node/test/parallel/test-stream-readable-to-web-termination.js +test/js/node/test/parallel/test-stream-readable-to-web.js +test/js/node/test/parallel/test-stream-readable-unpipe-resume.js +test/js/node/test/parallel/test-stream-readable-unshift.js +test/js/node/test/parallel/test-stream-readable-with-unimplemented-_read.js +test/js/node/test/parallel/test-stream-readableListening-state.js +test/js/node/test/parallel/test-stream-reduce.js +test/js/node/test/parallel/test-stream-set-default-hwm.js +test/js/node/test/parallel/test-stream-some-find-every.mjs +test/js/node/test/parallel/test-stream-toArray.js +test/js/node/test/parallel/test-stream-toWeb-allows-server-response.js +test/js/node/test/parallel/test-stream-transform-callback-twice.js +test/js/node/test/parallel/test-stream-transform-constructor-set-methods.js +test/js/node/test/parallel/test-stream-transform-destroy.js +test/js/node/test/parallel/test-stream-transform-final-sync.js +test/js/node/test/parallel/test-stream-transform-final.js +test/js/node/test/parallel/test-stream-transform-flush-data.js +test/js/node/test/parallel/test-stream-transform-hwm0.js +test/js/node/test/parallel/test-stream-transform-objectmode-falsey-value.js +test/js/node/test/parallel/test-stream-transform-split-highwatermark.js +test/js/node/test/parallel/test-stream-transform-split-objectmode.js +test/js/node/test/parallel/test-stream-typedarray.js +test/js/node/test/parallel/test-stream-uint8array.js +test/js/node/test/parallel/test-stream-unpipe-event.js +test/js/node/test/parallel/test-stream-unshift-empty-chunk.js +test/js/node/test/parallel/test-stream-unshift-read-race.js +test/js/node/test/parallel/test-stream-writable-aborted.js +test/js/node/test/parallel/test-stream-writable-change-default-encoding.js +test/js/node/test/parallel/test-stream-writable-clear-buffer.js +test/js/node/test/parallel/test-stream-writable-constructor-set-methods.js +test/js/node/test/parallel/test-stream-writable-decoded-encoding.js +test/js/node/test/parallel/test-stream-writable-destroy.js +test/js/node/test/parallel/test-stream-writable-end-cb-error.js +test/js/node/test/parallel/test-stream-writable-end-cb-uncaught.js +test/js/node/test/parallel/test-stream-writable-end-multiple.js +test/js/node/test/parallel/test-stream-writable-ended-state.js +test/js/node/test/parallel/test-stream-writable-final-async.js +test/js/node/test/parallel/test-stream-writable-final-destroy.js +test/js/node/test/parallel/test-stream-writable-final-throw.js +test/js/node/test/parallel/test-stream-writable-finish-destroyed.js +test/js/node/test/parallel/test-stream-writable-finished-state.js +test/js/node/test/parallel/test-stream-writable-finished.js +test/js/node/test/parallel/test-stream-writable-invalid-chunk.js +test/js/node/test/parallel/test-stream-writable-needdrain-state.js +test/js/node/test/parallel/test-stream-writable-null.js +test/js/node/test/parallel/test-stream-writable-properties.js +test/js/node/test/parallel/test-stream-writable-writable.js +test/js/node/test/parallel/test-stream-writable-write-cb-error.js +test/js/node/test/parallel/test-stream-writable-write-cb-twice.js +test/js/node/test/parallel/test-stream-writable-write-error.js +test/js/node/test/parallel/test-stream-writable-write-writev-finish.js +test/js/node/test/parallel/test-stream-writableState-ending.js +test/js/node/test/parallel/test-stream-writableState-uncorked-bufferedRequestCount.js +test/js/node/test/parallel/test-stream-write-destroy.js +test/js/node/test/parallel/test-stream-write-drain.js +test/js/node/test/parallel/test-stream-write-final.js +test/js/node/test/parallel/test-stream-writev.js +test/js/node/test/parallel/test-stream2-base64-single-char-read-end.js +test/js/node/test/parallel/test-stream2-basic.js +test/js/node/test/parallel/test-stream2-compatibility.js +test/js/node/test/parallel/test-stream2-decode-partial.js +test/js/node/test/parallel/test-stream2-finish-pipe-error.js +test/js/node/test/parallel/test-stream2-finish-pipe.js +test/js/node/test/parallel/test-stream2-large-read-stall.js +test/js/node/test/parallel/test-stream2-objects.js +test/js/node/test/parallel/test-stream2-pipe-error-handling.js +test/js/node/test/parallel/test-stream2-pipe-error-once-listener.js +test/js/node/test/parallel/test-stream2-push.js +test/js/node/test/parallel/test-stream2-read-sync-stack.js +test/js/node/test/parallel/test-stream2-readable-empty-buffer-no-eof.js +test/js/node/test/parallel/test-stream2-readable-legacy-drain.js +test/js/node/test/parallel/test-stream2-readable-non-empty-end.js +test/js/node/test/parallel/test-stream2-readable-wrap-destroy.js +test/js/node/test/parallel/test-stream2-readable-wrap-empty.js +test/js/node/test/parallel/test-stream2-readable-wrap-error.js +test/js/node/test/parallel/test-stream2-readable-wrap.js +test/js/node/test/parallel/test-stream2-set-encoding.js +test/js/node/test/parallel/test-stream2-transform.js +test/js/node/test/parallel/test-stream2-unpipe-drain.js +test/js/node/test/parallel/test-stream2-unpipe-leak.js +test/js/node/test/parallel/test-stream2-writable.js +test/js/node/test/parallel/test-stream3-cork-end.js +test/js/node/test/parallel/test-stream3-cork-uncork.js +test/js/node/test/parallel/test-stream3-pause-then-read.js +test/js/node/test/parallel/test-stream3-pipeline-async-iterator.js +test/js/node/test/parallel/test-streams-highwatermark.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-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-tls-0-dns-altname.js +test/js/node/test/parallel/test-tls-add-context.js +test/js/node/test/parallel/test-tls-alert-handling.js +test/js/node/test/parallel/test-tls-alert.js +test/js/node/test/parallel/test-tls-ca-concat.js +test/js/node/test/parallel/test-tls-cert-ext-encoding.js +test/js/node/test/parallel/test-tls-cert-regression.js +test/js/node/test/parallel/test-tls-check-server-identity.js +test/js/node/test/parallel/test-tls-client-abort.js +test/js/node/test/parallel/test-tls-client-abort2.js +test/js/node/test/parallel/test-tls-client-destroy-soon.js +test/js/node/test/parallel/test-tls-client-renegotiation-limit.js +test/js/node/test/parallel/test-tls-client-verify.js +test/js/node/test/parallel/test-tls-close-error.js +test/js/node/test/parallel/test-tls-close-event-after-write.js +test/js/node/test/parallel/test-tls-connect-abort-controller.js +test/js/node/test/parallel/test-tls-connect-address-family.js +test/js/node/test/parallel/test-tls-connect-hints-option.js +test/js/node/test/parallel/test-tls-connect-hwm-option.js +test/js/node/test/parallel/test-tls-connect-no-host.js +test/js/node/test/parallel/test-tls-connect-pipe.js +test/js/node/test/parallel/test-tls-connect-secure-context.js +test/js/node/test/parallel/test-tls-connect-simple.js +test/js/node/test/parallel/test-tls-destroy-whilst-write.js +test/js/node/test/parallel/test-tls-dhe.js +test/js/node/test/parallel/test-tls-ecdh-auto.js +test/js/node/test/parallel/test-tls-ecdh-multiple.js +test/js/node/test/parallel/test-tls-ecdh.js +test/js/node/test/parallel/test-tls-econnreset.js +test/js/node/test/parallel/test-tls-env-extra-ca-no-crypto.js +test/js/node/test/parallel/test-tls-fast-writing.js +test/js/node/test/parallel/test-tls-friendly-error-message.js +test/js/node/test/parallel/test-tls-get-ca-certificates-bundled-subset.js +test/js/node/test/parallel/test-tls-get-ca-certificates-bundled.js +test/js/node/test/parallel/test-tls-get-ca-certificates-default.js +test/js/node/test/parallel/test-tls-get-ca-certificates-error.js +test/js/node/test/parallel/test-tls-get-ca-certificates-extra-empty.js +test/js/node/test/parallel/test-tls-get-ca-certificates-extra-subset.js +test/js/node/test/parallel/test-tls-get-ca-certificates-extra.js +test/js/node/test/parallel/test-tls-handshake-error.js +test/js/node/test/parallel/test-tls-inception.js +test/js/node/test/parallel/test-tls-interleave.js +test/js/node/test/parallel/test-tls-invoke-queued.js +test/js/node/test/parallel/test-tls-junk-closes-server.js +test/js/node/test/parallel/test-tls-keyengine-invalid-arg-type.js +test/js/node/test/parallel/test-tls-legacy-pfx.js +test/js/node/test/parallel/test-tls-multiple-cas-as-string.js +test/js/node/test/parallel/test-tls-net-connect-prefer-path.js +test/js/node/test/parallel/test-tls-no-rsa-key.js +test/js/node/test/parallel/test-tls-no-sslv3.js +test/js/node/test/parallel/test-tls-ocsp-callback.js +test/js/node/test/parallel/test-tls-on-empty-socket.js +test/js/node/test/parallel/test-tls-options-boolean-check.js +test/js/node/test/parallel/test-tls-peer-certificate-encoding.js +test/js/node/test/parallel/test-tls-peer-certificate-multi-keys.js +test/js/node/test/parallel/test-tls-psk-server.js +test/js/node/test/parallel/test-tls-request-timeout.js +test/js/node/test/parallel/test-tls-reuse-host-from-socket.js +test/js/node/test/parallel/test-tls-root-certificates.js +test/js/node/test/parallel/test-tls-secure-context-usage-order.js +test/js/node/test/parallel/test-tls-securepair-server.js +test/js/node/test/parallel/test-tls-server-connection-server.js +test/js/node/test/parallel/test-tls-server-verify.js +test/js/node/test/parallel/test-tls-session-cache.js +test/js/node/test/parallel/test-tls-set-ciphers-error.js +test/js/node/test/parallel/test-tls-set-ciphers.js +test/js/node/test/parallel/test-tls-set-encoding.js +test/js/node/test/parallel/test-tls-sni-server-client.js +test/js/node/test/parallel/test-tls-socket-allow-half-open-option.js +test/js/node/test/parallel/test-tls-startcom-wosign-whitelist.js +test/js/node/test/parallel/test-tls-timeout-server-2.js +test/js/node/test/parallel/test-tls-tlswrap-segfault-2.js +test/js/node/test/parallel/test-tls-tlswrap-segfault.js +test/js/node/test/parallel/test-tls-translate-peer-certificate.js +test/js/node/test/parallel/test-tls-transport-destroy-after-own-gc.js +test/js/node/test/parallel/test-tls-use-after-free-regression.js +test/js/node/test/parallel/test-tls-wrap-econnreset-localaddress.js +test/js/node/test/parallel/test-tls-wrap-econnreset-socket.js +test/js/node/test/parallel/test-tls-wrap-econnreset.js +test/js/node/test/parallel/test-tls-write-error.js +test/js/node/test/parallel/test-tls-zero-clear-in.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-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/parallel/test-zlib-brotli-16GB.js +test/js/node/test/parallel/test-zlib-brotli-flush.js +test/js/node/test/parallel/test-zlib-brotli-from-brotli.js +test/js/node/test/parallel/test-zlib-brotli-from-string.js +test/js/node/test/parallel/test-zlib-brotli-kmaxlength-rangeerror.js +test/js/node/test/parallel/test-zlib-brotli.js +test/js/node/test/parallel/test-zlib-close-after-error.js +test/js/node/test/parallel/test-zlib-close-after-write.js +test/js/node/test/parallel/test-zlib-close-in-ondata.js +test/js/node/test/parallel/test-zlib-const.js +test/js/node/test/parallel/test-zlib-convenience-methods.js +test/js/node/test/parallel/test-zlib-crc32.js +test/js/node/test/parallel/test-zlib-create-raw.js +test/js/node/test/parallel/test-zlib-deflate-constructors.js +test/js/node/test/parallel/test-zlib-deflate-raw-inherits.js +test/js/node/test/parallel/test-zlib-destroy-pipe.js +test/js/node/test/parallel/test-zlib-destroy.js +test/js/node/test/parallel/test-zlib-dictionary-fail.js +test/js/node/test/parallel/test-zlib-dictionary.js +test/js/node/test/parallel/test-zlib-empty-buffer.js +test/js/node/test/parallel/test-zlib-failed-init.js +test/js/node/test/parallel/test-zlib-flush-drain-longblock.js +test/js/node/test/parallel/test-zlib-flush-drain.js +test/js/node/test/parallel/test-zlib-flush-flags.js +test/js/node/test/parallel/test-zlib-flush-write-sync-interleaved.js +test/js/node/test/parallel/test-zlib-flush.js +test/js/node/test/parallel/test-zlib-from-concatenated-gzip.js +test/js/node/test/parallel/test-zlib-from-gzip-with-trailing-garbage.js +test/js/node/test/parallel/test-zlib-from-gzip.js +test/js/node/test/parallel/test-zlib-from-string.js +test/js/node/test/parallel/test-zlib-invalid-arg-value-brotli-compress.js +test/js/node/test/parallel/test-zlib-invalid-input.js +test/js/node/test/parallel/test-zlib-kmaxlength-rangeerror.js +test/js/node/test/parallel/test-zlib-maxOutputLength.js +test/js/node/test/parallel/test-zlib-not-string-or-buffer.js +test/js/node/test/parallel/test-zlib-object-write.js +test/js/node/test/parallel/test-zlib-params.js +test/js/node/test/parallel/test-zlib-premature-end.js +test/js/node/test/parallel/test-zlib-random-byte-pipes.js +test/js/node/test/parallel/test-zlib-reset-before-write.js +test/js/node/test/parallel/test-zlib-sync-no-event.js +test/js/node/test/parallel/test-zlib-truncated.js +test/js/node/test/parallel/test-zlib-unzip-one-byte-chunks.js +test/js/node/test/parallel/test-zlib-write-after-close.js +test/js/node/test/parallel/test-zlib-write-after-end.js +test/js/node/test/parallel/test-zlib-write-after-flush.js +test/js/node/test/parallel/test-zlib-zero-byte.js +test/js/node/test/parallel/test-zlib-zero-windowBits.js +test/js/node/test/parallel/test-zlib-zstd-flush.js +test/js/node/test/parallel/test-zlib-zstd-from-string.js +test/js/node/test/parallel/test-zlib-zstd-from-zstd.js +test/js/node/test/parallel/test-zlib-zstd-kmaxlength-rangeerror.js +test/js/node/test/parallel/test-zlib-zstd-pledged-src-size.js +test/js/node/test/parallel/test-zlib-zstd.js +test/js/node/test/parallel/test-zlib.js +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-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-GH-5504.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/timers.promises/timers.promises.test.ts +test/js/node/timers/node-timers.test.ts +test/js/node/tls/fetch-tls-cert.test.ts +test/js/node/tls/node-tls-cert.test.ts +test/js/node/tls/node-tls-connect.test.ts +test/js/node/tls/node-tls-context.test.ts +test/js/node/tls/node-tls-create-secure-context-args.test.ts +test/js/node/tls/node-tls-no-cipher-match-error.test.ts +test/js/node/tls/node-tls-server.test.ts +test/js/node/tls/node-tls-upgrade.test.ts +test/js/node/tls/renegotiation.test.ts +test/js/node/url/url-parse-format.test.js +test/js/node/url/url-parse-ipv6.test.ts +test/js/node/url/url-relative.test.js +test/js/node/url/url.test.ts +test/js/node/util/bun-inspect.test.ts +test/js/node/util/custom-inspect.test.js +test/js/node/util/mime-api.test.ts +test/js/node/util/node-inspect-tests/parallel/util-inspect.test.js +test/js/node/util/parse_args/default-args.test.mjs +test/js/node/util/test-util-types.test.js +test/js/node/util/util-callbackify.test.js +test/js/node/util/util-promisify.test.js +test/js/node/util/util.test.js +test/js/node/v8/capture-stack-trace.test.js +test/js/node/vm/happy-dom-vm-16277.test.ts +test/js/node/vm/sourcetextmodule-leak.test.ts +test/js/node/vm/vm-sourceUrl.test.ts +test/js/node/vm/vm.test.ts +test/js/node/watch/fs.watchFile.test.ts +test/js/node/worker_threads/15787.test.ts +test/js/node/zlib/zlib.kMaxLength.global.test.js +test/js/node/zlib/zlib.test.js +test/js/sql/local-sql.test.ts +test/js/sql/sql.test.ts +test/js/third_party/@azure/service-bus/azure-service-bus.test.ts +test/js/third_party/@duckdb/node-api/duckdb.test.ts +test/js/third_party/@fastify/websocket/fastity-test-websocket.test.js +test/js/third_party/@napi-rs/canvas/napi-rs-canvas.test.ts +test/js/third_party/body-parser/express-body-parser-test.test.ts +test/js/third_party/body-parser/express-bun-build-compile.test.ts +test/js/third_party/body-parser/express-memory-leak.test.ts +test/js/third_party/comlink/comlink.test.ts +test/js/third_party/duckdb/duckdb-basic-usage.test.ts +test/js/third_party/esbuild/esbuild-child_process.test.ts +test/js/third_party/express/app.router.test.ts +test/js/third_party/express/express.json.test.ts +test/js/third_party/express/express.test.ts +test/js/third_party/express/express.text.test.ts +test/js/third_party/express/res.json.test.ts +test/js/third_party/express/res.location.test.ts +test/js/third_party/express/res.redirect.test.ts +test/js/third_party/express/res.send.test.ts +test/js/third_party/express/res.sendFile.test.ts +test/js/third_party/grpc-js/test-call-credentials.test.ts +test/js/third_party/grpc-js/test-call-propagation.test.ts +test/js/third_party/grpc-js/test-certificate-provider.test.ts +test/js/third_party/grpc-js/test-channel-credentials.test.ts +test/js/third_party/grpc-js/test-channelz.test.ts +test/js/third_party/grpc-js/test-client.test.ts +test/js/third_party/grpc-js/test-confg-parsing.test.ts +test/js/third_party/grpc-js/test-deadline.test.ts +test/js/third_party/grpc-js/test-duration.test.ts +test/js/third_party/grpc-js/test-end-to-end.test.ts +test/js/third_party/grpc-js/test-global-subchannel-pool.test.ts +test/js/third_party/grpc-js/test-idle-timer.test.ts +test/js/third_party/grpc-js/test-local-subchannel-pool.test.ts +test/js/third_party/grpc-js/test-logging.test.ts +test/js/third_party/grpc-js/test-metadata.test.ts +test/js/third_party/grpc-js/test-outlier-detection.test.ts +test/js/third_party/grpc-js/test-pick-first.test.ts +test/js/third_party/grpc-js/test-prototype-pollution.test.ts +test/js/third_party/grpc-js/test-resolver.test.ts +test/js/third_party/grpc-js/test-retry-config.test.ts +test/js/third_party/grpc-js/test-retry.test.ts +test/js/third_party/grpc-js/test-server-credentials.test.ts +test/js/third_party/grpc-js/test-server-deadlines.test.ts +test/js/third_party/grpc-js/test-server-errors.test.ts +test/js/third_party/grpc-js/test-server-interceptors.test.ts +test/js/third_party/grpc-js/test-server.test.ts +test/js/third_party/grpc-js/test-status-builder.test.ts +test/js/third_party/grpc-js/test-uri-parser.test.ts +test/js/third_party/http2-wrapper/http2-wrapper.test.ts +test/js/third_party/jsonwebtoken/async_sign.test.js +test/js/third_party/jsonwebtoken/buffer.test.js +test/js/third_party/jsonwebtoken/claim-aud.test.js +test/js/third_party/jsonwebtoken/claim-exp.test.js +test/js/third_party/jsonwebtoken/claim-iat.test.js +test/js/third_party/jsonwebtoken/claim-iss.test.js +test/js/third_party/jsonwebtoken/claim-jti.test.js +test/js/third_party/jsonwebtoken/claim-nbf.test.js +test/js/third_party/jsonwebtoken/claim-private.test.js +test/js/third_party/jsonwebtoken/claim-sub.test.js +test/js/third_party/jsonwebtoken/decoding.test.js +test/js/third_party/jsonwebtoken/encoding.test.js +test/js/third_party/jsonwebtoken/expires_format.test.js +test/js/third_party/jsonwebtoken/header-kid.test.js +test/js/third_party/jsonwebtoken/invalid_exp.test.js +test/js/third_party/jsonwebtoken/issue_147.test.js +test/js/third_party/jsonwebtoken/issue_304.test.js +test/js/third_party/jsonwebtoken/issue_70.test.js +test/js/third_party/jsonwebtoken/jwt.asymmetric_signing.test.js +test/js/third_party/jsonwebtoken/jwt.hs.test.js +test/js/third_party/jsonwebtoken/jwt.malicious.test.js +test/js/third_party/jsonwebtoken/non_object_values.test.js +test/js/third_party/jsonwebtoken/noTimestamp.test.js +test/js/third_party/jsonwebtoken/option-complete.test.js +test/js/third_party/jsonwebtoken/option-maxAge.test.js +test/js/third_party/jsonwebtoken/option-nonce.test.js +test/js/third_party/jsonwebtoken/rsa-public-key.test.js +test/js/third_party/jsonwebtoken/schema.test.js +test/js/third_party/jsonwebtoken/set_headers.test.js +test/js/third_party/jsonwebtoken/undefined_secretOrPublickey.test.js +test/js/third_party/jsonwebtoken/validateAsymmetricKey.test.js +test/js/third_party/jsonwebtoken/verify.test.js +test/js/third_party/jsonwebtoken/wrong_alg.test.js +test/js/third_party/mongodb/mongodb.test.ts +test/js/third_party/msw/msw.test.ts +test/js/third_party/nodemailer/nodemailer.test.ts +test/js/third_party/pg-gateway/pglite.test.ts +test/js/third_party/pg/pg.test.ts +test/js/third_party/pino/pino.test.js +test/js/third_party/postgres/postgres.test.ts +test/js/third_party/prisma/prisma.test.ts +test/js/third_party/prompts/prompts.test.ts +test/js/third_party/remix/remix.test.ts +test/js/third_party/resvg/bbox.test.js +test/js/third_party/rollup-v4/rollup-v4.test.ts +test/js/third_party/socket.io/socket.io-close.test.ts +test/js/third_party/socket.io/socket.io-connection-state-recovery.test.ts +test/js/third_party/socket.io/socket.io-handshake.test.ts +test/js/third_party/socket.io/socket.io-messaging-many.test.ts +test/js/third_party/socket.io/socket.io-middleware.test.ts +test/js/third_party/socket.io/socket.io-namespaces.test.ts +test/js/third_party/socket.io/socket.io-server-attachment.test.ts +test/js/third_party/socket.io/socket.io-socket-middleware.test.ts +test/js/third_party/socket.io/socket.io-socket-timeout.test.ts +test/js/third_party/socket.io/socket.io-utility-methods.test.ts +test/js/third_party/socket.io/socket.io.test.ts +test/js/third_party/solc/solc.test.ts +test/js/third_party/st/st.test.ts +test/js/third_party/stripe/stripe.test.ts +test/js/third_party/svelte/svelte.test.ts +test/js/web/abort/abort.test.ts +test/js/web/broadcastchannel/broadcast-channel.test.ts +test/js/web/console/console-timeLog.test.ts +test/js/web/crypto/web-crypto.test.ts +test/js/web/encoding/encode-bad-chunks.test.ts +test/js/web/encoding/text-decoder-stream.test.ts +test/js/web/encoding/text-decoder.test.js +test/js/web/encoding/text-encoder-stream.test.ts +test/js/web/encoding/text-encoder.test.js +test/js/web/fetch/abort-signal-leak.test.ts +test/js/web/fetch/blob-oom.test.ts +test/js/web/fetch/blob.test.ts +test/js/web/fetch/body-clone.test.ts +test/js/web/fetch/body-stream-excess.test.ts +test/js/web/fetch/body-stream.test.ts +test/js/web/fetch/body.test.ts +test/js/web/fetch/chunked-trailing.test.js +test/js/web/fetch/client-fetch.test.ts +test/js/web/fetch/content-length.test.js +test/js/web/fetch/cookies.test.ts +test/js/web/fetch/fetch_headers.test.js +test/js/web/fetch/fetch-args.test.ts +test/js/web/fetch/fetch-gzip.test.ts +test/js/web/fetch/fetch-preconnect.test.ts +test/js/web/fetch/fetch-redirect.test.ts +test/js/web/fetch/fetch-tcp-stress.test.ts +test/js/web/fetch/fetch-url-after-redirect.test.ts +test/js/web/fetch/fetch.brotli.test.ts +test/js/web/fetch/fetch.stream.test.ts +test/js/web/fetch/fetch.test.ts +test/js/web/fetch/fetch.tls.test.ts +test/js/web/fetch/fetch.unix.test.ts +test/js/web/fetch/headers.test.ts +test/js/web/fetch/headers.undici.test.ts +test/js/web/fetch/stream-fast-path.test.ts +test/js/web/fetch/utf8-bom.test.ts +test/js/web/html/FormData.test.ts +test/js/web/request/request-clone-leak.test.ts +test/js/web/request/request-subclass.test.ts +test/js/web/request/request.test.ts +test/js/web/streams/streams.test.js +test/js/web/timers/microtask.test.js +test/js/web/timers/setInterval.test.js +test/js/web/timers/setTimeout.test.js +test/js/web/websocket/websocket-client-short-read.test.ts +test/js/web/websocket/websocket-client.test.ts +test/js/web/websocket/websocket.test.js +test/js/web/workers/message-channel.test.ts +test/js/web/workers/message-event.test.ts +test/js/web/workers/structured-clone.test.ts +test/js/web/workers/worker_blob.test.ts +test/js/web/workers/worker.test.ts +test/js/workerd/html-rewriter.test.js +test/napi/node-napi.test.ts +test/napi/uv_stub.test.ts +test/napi/uv.test.ts +test/regression/issue/012040.test.ts +test/regression/issue/014187.test.ts +test/regression/issue/01466.test.ts +test/regression/issue/014865.test.ts +test/regression/issue/02368.test.ts +test/regression/issue/02499/02499.test.ts +test/regression/issue/04298/04298.test.ts +test/regression/issue/04947.test.js +test/regression/issue/06946/06946.test.ts +test/regression/issue/07001.test.ts +test/regression/issue/07261.test.ts +test/regression/issue/07827.test.ts +test/regression/issue/07917/7917.test.ts +test/regression/issue/08093.test.ts +test/regression/issue/08794.test.ts +test/regression/issue/09041.test.ts +test/regression/issue/09340.test.ts +test/regression/issue/09469.test.ts +test/regression/issue/09555.test.ts +test/regression/issue/09559.test.ts +test/regression/issue/09778.test.ts +test/regression/issue/10132.test.ts +test/regression/issue/10139.test.ts +test/regression/issue/10170.test.ts +test/regression/issue/11297/11297.test.ts +test/regression/issue/11664.test.ts +test/regression/issue/12910/12910.test.ts +test/regression/issue/14477/14477.test.ts +test/regression/issue/14515.test.tsx +test/regression/issue/14976/14976.test.ts +test/regression/issue/14982/14982.test.ts +test/regression/issue/16312.test.ts +test/regression/issue/16474.test.ts +test/regression/issue/17605.test.ts +test/regression/issue/17766.test.ts +test/regression/issue/18159/18159.test.ts +test/regression/issue/18239/18239.test.ts +test/regression/issue/18547.test.ts +test/regression/issue/18595.test.ts +test/regression/issue/19661.test.ts +test/regression/issue/20144/20144.test.ts +test/regression/issue/crypto-names.test.ts +test/v8/v8.test.ts +vendor/elysia/test/a.test.ts +vendor/elysia/test/adapter/web-standard/cookie-to-header.test.ts +vendor/elysia/test/adapter/web-standard/map-compact-response.test.ts +vendor/elysia/test/adapter/web-standard/map-early-response.test.ts +vendor/elysia/test/adapter/web-standard/map-response.test.ts +vendor/elysia/test/adapter/web-standard/set-cookie.test.ts +vendor/elysia/test/aot/analysis.test.ts +vendor/elysia/test/aot/generation.test.ts +vendor/elysia/test/aot/has-transform.test.ts +vendor/elysia/test/aot/has-type.test.ts +vendor/elysia/test/aot/response.test.ts +vendor/elysia/test/bun/router.test.ts +vendor/elysia/test/cookie/explicit.test.ts +vendor/elysia/test/cookie/implicit.test.ts +vendor/elysia/test/cookie/response.test.ts +vendor/elysia/test/cookie/signature.test.ts +vendor/elysia/test/core/as.test.ts +vendor/elysia/test/core/config.test.ts +vendor/elysia/test/core/context.test.ts +vendor/elysia/test/core/dynamic.test.ts +vendor/elysia/test/core/elysia.test.ts +vendor/elysia/test/core/formdata.test.ts +vendor/elysia/test/core/handle-error.test.ts +vendor/elysia/test/core/modules.test.ts +vendor/elysia/test/core/mount.test.ts +vendor/elysia/test/core/native-static.test.ts +vendor/elysia/test/core/normalize.test.ts +vendor/elysia/test/core/path.test.ts +vendor/elysia/test/core/redirect.test.ts +vendor/elysia/test/core/sanitize.test.ts +vendor/elysia/test/core/stop.test.ts +vendor/elysia/test/extends/decorators.test.ts +vendor/elysia/test/extends/error.test.ts +vendor/elysia/test/extends/models.test.ts +vendor/elysia/test/extends/store.test.ts +vendor/elysia/test/hoc/index.test.ts +vendor/elysia/test/lifecycle/after-handle.test.ts +vendor/elysia/test/lifecycle/before-handle.test.ts +vendor/elysia/test/lifecycle/derive.test.ts +vendor/elysia/test/lifecycle/error.test.ts +vendor/elysia/test/lifecycle/hook-types.test.ts +vendor/elysia/test/lifecycle/map-derive.test.ts +vendor/elysia/test/lifecycle/map-resolve.test.ts +vendor/elysia/test/lifecycle/map-response.test.ts +vendor/elysia/test/lifecycle/parser.test.ts +vendor/elysia/test/lifecycle/request.test.ts +vendor/elysia/test/lifecycle/resolve.test.ts +vendor/elysia/test/lifecycle/response.test.ts +vendor/elysia/test/lifecycle/transform.test.ts +vendor/elysia/test/macro/macro.test.ts +vendor/elysia/test/path/group.test.ts +vendor/elysia/test/path/guard.test.ts +vendor/elysia/test/path/path.test.ts +vendor/elysia/test/plugins/affix.test.ts +vendor/elysia/test/plugins/checksum.test.ts +vendor/elysia/test/plugins/error-propagation.test.ts +vendor/elysia/test/plugins/plugin.test.ts +vendor/elysia/test/production/index.test.ts +vendor/elysia/test/response/custom-response.test.ts +vendor/elysia/test/response/headers.test.ts +vendor/elysia/test/response/redirect.test.ts +vendor/elysia/test/response/static.test.ts +vendor/elysia/test/response/stream.test.ts +vendor/elysia/test/sucrose/query.test.ts +vendor/elysia/test/sucrose/sucrose.test.ts +vendor/elysia/test/tracer/aot.test.ts +vendor/elysia/test/tracer/detail.test.ts +vendor/elysia/test/tracer/timing.test.ts +vendor/elysia/test/tracer/trace.test.ts +vendor/elysia/test/type-system/array-string.test.ts +vendor/elysia/test/type-system/boolean-string.test.ts +vendor/elysia/test/type-system/coercion-number.test.ts +vendor/elysia/test/type-system/date.test.ts +vendor/elysia/test/type-system/form.test.ts +vendor/elysia/test/type-system/object-string.test.ts +vendor/elysia/test/type-system/string-format.test.ts +vendor/elysia/test/type-system/union-enum.test.ts +vendor/elysia/test/units/deduplicate-checksum.test.ts +vendor/elysia/test/units/has-ref.test.ts +vendor/elysia/test/units/has-transform.test.ts +vendor/elysia/test/units/merge-deep.test.ts +vendor/elysia/test/units/merge-object-schemas.test.ts +vendor/elysia/test/units/replace-schema-type.test.ts +vendor/elysia/test/validator/body.test.ts +vendor/elysia/test/validator/encode.test.ts +vendor/elysia/test/validator/exact-mirror.test.ts +vendor/elysia/test/validator/header.test.ts +vendor/elysia/test/validator/params.test.ts +vendor/elysia/test/validator/query.test.ts +vendor/elysia/test/validator/response.test.ts +vendor/elysia/test/validator/standalone.test.ts +vendor/elysia/test/validator/validator.test.ts +vendor/elysia/test/ws/aot.test.ts +vendor/elysia/test/ws/connection.test.ts +vendor/elysia/test/ws/destructuring.test.ts +vendor/elysia/test/ws/message.test.ts