diff --git a/cmake/targets/BuildBun.cmake b/cmake/targets/BuildBun.cmake index 11759e2f7a9418..35949d5239e97f 100644 --- a/cmake/targets/BuildBun.cmake +++ b/cmake/targets/BuildBun.cmake @@ -860,7 +860,7 @@ endif() if(WIN32) target_link_options(${bun} PUBLIC - /STACK:0x1200000,0x100000 + /STACK:0x1200000,0x200000 /errorlimit:0 ) if(RELEASE) diff --git a/src/bit_set.zig b/src/bit_set.zig index 245dbd09e6ed34..2ecd5b3591f12d 100644 --- a/src/bit_set.zig +++ b/src/bit_set.zig @@ -1,3 +1,8 @@ +//! This is a fork of Zig standard library bit_set.zig +//! - https://github.com/ziglang/zig/pull/14129 +//! - AutoBitset which optimally chooses between a dynamic or static bitset. +//! Prefer our fork over std.bit_set.zig. +//! //! This file defines several variants of bit sets. A bit set //! is a densely stored set of integers with a known maximum, //! in which each integer gets a single bit. Bit sets have very @@ -402,7 +407,7 @@ pub fn ArrayBitSet(comptime MaskIntType: type, comptime size: usize) type { /// Returns true if the bit at the specified index /// is present in the set, false otherwise. - pub inline fn isSet(self: *const Self, index: usize) bool { + pub fn isSet(self: *const Self, index: usize) bool { if (comptime Environment.allow_assert) bun.assert(index < bit_length); if (num_masks == 0) return false; // doesn't compile in this case return (self.masks[maskIndex(index)] & maskBit(index)) != 0; diff --git a/src/bun.js/ConsoleObject.zig b/src/bun.js/ConsoleObject.zig index 12a2506a4132e0..b6f05770b60443 100644 --- a/src/bun.js/ConsoleObject.zig +++ b/src/bun.js/ConsoleObject.zig @@ -299,6 +299,8 @@ pub const TablePrinter = struct { .quote_strings = false, .single_line = true, .max_depth = 5, + .can_throw_stack_overflow = true, + .stack_check = bun.StackCheck.init(), }, }; } @@ -481,8 +483,12 @@ pub const TablePrinter = struct { defer { if (value_formatter.map_node) |node| { - node.data = value_formatter.map; - node.data.clearRetainingCapacity(); + this.value_formatter.map_node = null; + if (node.data.capacity() > 512) { + node.data.clearAndFree(); + } else { + node.data.clearRetainingCapacity(); + } node.release(); } } @@ -767,17 +773,9 @@ pub fn format2( writer: Writer, options: FormatOptions, ) void { - var fmt: ConsoleObject.Formatter = undefined; - defer { - if (fmt.map_node) |node| { - node.data = fmt.map; - node.data.clearRetainingCapacity(); - node.release(); - } - } - if (len == 1) { - fmt = ConsoleObject.Formatter{ + // initialized later in this function. + var fmt = ConsoleObject.Formatter{ .remaining_values = &[_]JSValue{}, .globalThis = global, .ordered_properties = options.ordered_properties, @@ -785,7 +783,10 @@ pub fn format2( .max_depth = options.max_depth, .single_line = options.single_line, .indent = options.default_indent, + .stack_check = bun.StackCheck.init(), + .can_throw_stack_overflow = true, }; + defer fmt.deinit(); const tag = ConsoleObject.Formatter.Tag.get(vals[0], global); fmt.writeIndent(Writer, writer) catch return; @@ -858,14 +859,17 @@ pub fn format2( } var this_value: JSValue = vals[0]; - fmt = ConsoleObject.Formatter{ + var fmt = ConsoleObject.Formatter{ .remaining_values = vals[0..len][1..], .globalThis = global, .ordered_properties = options.ordered_properties, .quote_strings = options.quote_strings, .single_line = options.single_line, .indent = options.default_indent, + .stack_check = bun.StackCheck.init(), + .can_throw_stack_overflow = true, }; + defer fmt.deinit(); var tag: ConsoleObject.Formatter.Tag.Result = undefined; fmt.writeIndent(Writer, writer) catch return; @@ -942,6 +946,21 @@ pub const Formatter = struct { single_line: bool = false, ordered_properties: bool = false, custom_formatted_object: CustomFormattedObject = .{}, + disable_inspect_custom: bool = false, + stack_check: bun.StackCheck = .{ .cached_stack_end = std.math.maxInt(usize) }, + can_throw_stack_overflow: bool = false, + + pub fn deinit(this: *Formatter) void { + if (bun.take(&this.map_node)) |node| { + node.data = this.map; + if (node.data.capacity() > 512) { + node.data.clearAndFree(); + } else { + node.data.clearRetainingCapacity(); + } + node.release(); + } + } pub fn goodTimeForANewLine(this: *@This()) bool { if (this.estimated_line_length > 80) { @@ -1052,8 +1071,11 @@ pub const Formatter = struct { }; } - pub inline fn canHaveCircularReferences(tag: Tag) bool { - return tag == .Array or tag == .Object or tag == .Map or tag == .Set; + pub fn canHaveCircularReferences(tag: Tag) bool { + return switch (tag) { + .Function, .Array, .Object, .Map, .Set, .Error, .Class, .Event => true, + else => false, + }; } const Result = struct { @@ -1106,8 +1128,10 @@ pub const Formatter = struct { return getAdvanced(value, globalThis, .{ .hide_global = false }); } - pub const Options = struct { + // It sounds silly to make this packed, but Tag.getAdvanced is extremely recursive. + pub const Options = packed struct { hide_global: bool = false, + disable_inspect_custom: bool = false, }; pub fn getAdvanced(value: JSValue, globalThis: *JSGlobalObject, opts: Options) Result { @@ -1154,7 +1178,7 @@ pub const Formatter = struct { }; } - if (js_type.canGet() and js_type != .ProxyObject) { + if (js_type.canGet() and js_type != .ProxyObject and !opts.disable_inspect_custom) { // Attempt to get custom formatter if (value.fastGet(globalThis, .inspectCustom)) |callback_value| { if (callback_value.isCallable(globalThis.vm())) { @@ -1181,7 +1205,7 @@ pub const Formatter = struct { // If we check an Object has a method table and it does not // it will crash - if (js_type != .Object and value.isCallable(globalThis.vm())) { + if (js_type != .Object and js_type != .ProxyObject and value.isCallable(globalThis.vm())) { if (value.isClass(globalThis)) { return .{ .tag = .{ .Class = {} }, @@ -1544,11 +1568,17 @@ pub const Formatter = struct { } pub fn WrappedWriter(comptime Writer: type) type { + if (@hasDecl(Writer, "is_wrapped_writer")) { + @compileError("Do not nest WrappedWriter"); + } + return struct { ctx: Writer, failed: bool = false, estimated_line_length: *usize, + pub const is_wrapped_writer = true; + pub fn print(self: *@This(), comptime fmt: string, args: anytype) void { self.ctx.print(fmt, args) catch { self.failed = true; @@ -1642,16 +1672,16 @@ pub const Formatter = struct { }; } + const indentation_buf = [_]u8{' '} ** 64; pub fn writeIndent( this: *ConsoleObject.Formatter, comptime Writer: type, writer: Writer, ) !void { - var buf = [_]u8{' '} ** 64; var total_remain: u32 = this.indent; while (total_remain > 0) { const written: u8 = @min(32, total_remain); - try writer.writeAll(buf[0 .. written * 2]); + try writer.writeAll(indentation_buf[0 .. written * 2]); total_remain -|= written; } } @@ -1668,6 +1698,7 @@ pub const Formatter = struct { count: usize = 0, pub fn forEach(_: [*c]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; if (single_line and this.count > 0) { this.formatter.printComma(Writer, this.writer, enable_ansi_colors) catch unreachable; this.writer.writeAll(" ") catch unreachable; @@ -1679,7 +1710,10 @@ pub const Formatter = struct { if (!single_line) { this.formatter.writeIndent(Writer, this.writer) catch unreachable; } - const key_tag = Tag.getAdvanced(key, globalObject, .{ .hide_global = true }); + const key_tag = Tag.getAdvanced(key, globalObject, .{ + .hide_global = true, + .disable_inspect_custom = this.formatter.disable_inspect_custom, + }); this.formatter.format( key_tag, @@ -1690,7 +1724,10 @@ pub const Formatter = struct { enable_ansi_colors, ); this.writer.writeAll(": ") catch unreachable; - const value_tag = Tag.getAdvanced(value, globalObject, .{ .hide_global = true }); + const value_tag = Tag.getAdvanced(value, globalObject, .{ + .hide_global = true, + .disable_inspect_custom = this.formatter.disable_inspect_custom, + }); this.formatter.format( value_tag, Writer, @@ -1704,7 +1741,10 @@ pub const Formatter = struct { this.writer.writeAll("\n") catch unreachable; this.formatter.writeIndent(Writer, this.writer) catch unreachable; } - const tag = Tag.getAdvanced(nextValue, globalObject, .{ .hide_global = true }); + const tag = Tag.getAdvanced(nextValue, globalObject, .{ + .hide_global = true, + .disable_inspect_custom = this.formatter.disable_inspect_custom, + }); this.formatter.format( tag, Writer, @@ -1732,6 +1772,7 @@ pub const Formatter = struct { is_first: bool = true, pub fn forEach(_: [*c]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; if (single_line) { if (!this.is_first) { this.formatter.printComma(Writer, this.writer, enable_ansi_colors) catch unreachable; @@ -1741,7 +1782,10 @@ pub const Formatter = struct { } else { this.formatter.writeIndent(Writer, this.writer) catch {}; } - const key_tag = Tag.getAdvanced(nextValue, globalObject, .{ .hide_global = true }); + const key_tag = Tag.getAdvanced(nextValue, globalObject, .{ + .hide_global = true, + .disable_inspect_custom = this.formatter.disable_inspect_custom, + }); this.formatter.format( key_tag, Writer, @@ -1807,6 +1851,7 @@ pub const Formatter = struct { var ctx: *@This() = bun.cast(*@This(), ctx_ptr orelse return); var this = ctx.formatter; + if (this.failed) return; const writer_ = ctx.writer; var writer = WrappedWriter(Writer){ .ctx = writer_, @@ -1814,7 +1859,10 @@ pub const Formatter = struct { .estimated_line_length = &this.estimated_line_length, }; - const tag = Tag.getAdvanced(value, globalThis, .{ .hide_global = true }); + const tag = Tag.getAdvanced(value, globalThis, .{ + .hide_global = true, + .disable_inspect_custom = this.disable_inspect_custom, + }); if (tag.cell.isHidden()) return; if (ctx.i == 0) { @@ -1949,6 +1997,11 @@ pub const Formatter = struct { ) void { if (this.failed) return; + if (this.globalThis.hasException()) { + this.failed = true; + return; + } + var writer = WrappedWriter(Writer){ .ctx = writer_, .estimated_line_length = &this.estimated_line_length }; defer { if (writer.failed) { @@ -1956,6 +2009,14 @@ pub const Formatter = struct { } } if (comptime Format.canHaveCircularReferences()) { + if (!this.stack_check.isSafeToRecurse()) { + this.failed = true; + if (this.can_throw_stack_overflow) { + this.globalThis.throwStackOverflow(); + } + return; + } + if (this.map_node == null) { this.map_node = Visited.Pool.get(default_allocator); this.map_node.?.data.clearRetainingCapacity(); @@ -2156,6 +2217,7 @@ pub const Formatter = struct { value, null, null, + this, Writer, writer_, enable_ansi_colors, @@ -2270,7 +2332,10 @@ pub const Formatter = struct { first: { const element = value.getDirectIndex(this.globalThis, 0); - const tag = Tag.getAdvanced(element, this.globalThis, .{ .hide_global = true }); + const tag = Tag.getAdvanced(element, this.globalThis, .{ + .hide_global = true, + .disable_inspect_custom = this.disable_inspect_custom, + }); was_good_time = was_good_time or !tag.tag.isPrimitive() or this.goodTimeForANewLine(); @@ -2291,6 +2356,10 @@ pub const Formatter = struct { } this.format(tag, Writer, writer_, element, this.globalThis, enable_ansi_colors); + if (this.globalThis.hasException()) { + this.failed = true; + } + if (this.failed) return; if (tag.cell.isStringLike()) { if (comptime enable_ansi_colors) { @@ -2350,9 +2419,13 @@ pub const Formatter = struct { writer.space(); } - const tag = Tag.getAdvanced(element, this.globalThis, .{ .hide_global = true }); + const tag = Tag.getAdvanced(element, this.globalThis, .{ + .hide_global = true, + .disable_inspect_custom = this.disable_inspect_custom, + }); this.format(tag, Writer, writer_, element, this.globalThis, enable_ansi_colors); + if (this.failed) return; if (tag.cell.isStringLike()) { if (comptime enable_ansi_colors) { @@ -2395,6 +2468,10 @@ pub const Formatter = struct { .i = i, }; value.forEachPropertyNonIndexed(this.globalThis, &iter, Iterator.forEach); + if (this.globalThis.hasException()) { + this.failed = true; + } + if (this.failed) return; } } @@ -2581,6 +2658,7 @@ pub const Formatter = struct { .writer = writer_, }; value.forEach(this.globalThis, &iter, @TypeOf(iter).forEach); + if (this.failed) return; if (single_line and iter.count > 0) { writer.writeAll(" "); } @@ -2610,6 +2688,7 @@ pub const Formatter = struct { .writer = writer_, }; value.forEach(this.globalThis, &iter, @TypeOf(iter).forEach); + if (this.failed) return; if (iter.count > 0) { if (single_line) { writer.writeAll(" "); @@ -2643,6 +2722,7 @@ pub const Formatter = struct { .writer = writer_, }; value.forEach(this.globalThis, &iter, @TypeOf(iter).forEach); + if (this.failed) return; if (iter.count > 0 and !single_line) { writer.writeAll("\n"); } @@ -2689,6 +2769,7 @@ pub const Formatter = struct { .writer = writer_, }; value.forEach(this.globalThis, &iter, @TypeOf(iter).forEach); + if (this.failed) return; if (single_line and !iter.is_first) { writer.writeAll(" "); } @@ -2794,8 +2875,12 @@ pub const Formatter = struct { .{}, ); - const tag = Tag.getAdvanced(message_value, this.globalThis, .{ .hide_global = true }); + const tag = Tag.getAdvanced(message_value, this.globalThis, .{ + .hide_global = true, + .disable_inspect_custom = this.disable_inspect_custom, + }); this.format(tag, Writer, writer_, message_value, this.globalThis, enable_ansi_colors); + if (this.failed) return; this.printComma(Writer, writer_, enable_ansi_colors) catch unreachable; if (!this.single_line) { writer.writeAll("\n"); @@ -2814,8 +2899,12 @@ pub const Formatter = struct { .{}, ); const data = value.fastGet(this.globalThis, .data) orelse JSValue.undefined; - const tag = Tag.getAdvanced(data, this.globalThis, .{ .hide_global = true }); + const tag = Tag.getAdvanced(data, this.globalThis, .{ + .hide_global = true, + .disable_inspect_custom = this.disable_inspect_custom, + }); this.format(tag, Writer, writer_, data, this.globalThis, enable_ansi_colors); + if (this.failed) return; this.printComma(Writer, writer_, enable_ansi_colors) catch unreachable; if (!this.single_line) { writer.writeAll("\n"); @@ -2832,8 +2921,12 @@ pub const Formatter = struct { .{}, ); - const tag = Tag.getAdvanced(error_value, this.globalThis, .{ .hide_global = true }); + const tag = Tag.getAdvanced(error_value, this.globalThis, .{ + .hide_global = true, + .disable_inspect_custom = this.disable_inspect_custom, + }); this.format(tag, Writer, writer_, error_value, this.globalThis, enable_ansi_colors); + if (this.failed) return; this.printComma(Writer, writer_, enable_ansi_colors) catch unreachable; if (!this.single_line) { writer.writeAll("\n"); @@ -2863,7 +2956,10 @@ 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, .{ .hide_global = true }); + const _tag = Tag.getAdvanced(type_value, this.globalThis, .{ + .hide_global = true, + .disable_inspect_custom = this.disable_inspect_custom, + }); if (_tag.cell == .Symbol) {} else if (_tag.cell.isStringLike()) { type_value.toZigString(&tag_name_str, this.globalThis); @@ -2903,7 +2999,10 @@ pub const Formatter = struct { this.quote_strings = true; defer this.quote_strings = old_quote_strings; - this.format(Tag.getAdvanced(key_value, this.globalThis, .{ .hide_global = true }), Writer, writer_, key_value, this.globalThis, enable_ansi_colors); + this.format(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); needs_space = true; } @@ -2933,7 +3032,10 @@ pub const Formatter = struct { continue; const property_value = props_iter.value; - const tag = Tag.getAdvanced(property_value, this.globalThis, .{ .hide_global = true }); + const tag = Tag.getAdvanced(property_value, this.globalThis, .{ + .hide_global = true, + .disable_inspect_custom = this.disable_inspect_custom, + }); if (tag.cell.isHidden()) continue; @@ -3037,7 +3139,10 @@ pub const Formatter = struct { var j: usize = 0; while (j < length) : (j += 1) { const child = children.getIndex(this.globalThis, @as(u32, @intCast(j))); - this.format(Tag.getAdvanced(child, this.globalThis, .{ .hide_global = true }), Writer, writer_, child, this.globalThis, enable_ansi_colors); + this.format(Tag.getAdvanced(child, this.globalThis, .{ + .hide_global = true, + .disable_inspect_custom = this.disable_inspect_custom, + }), Writer, writer_, child, this.globalThis, enable_ansi_colors); if (j + 1 < length) { writer.writeAll("\n"); this.writeIndent(Writer, writer_) catch unreachable; @@ -3129,6 +3234,11 @@ pub const Formatter = struct { value.forEachProperty(this.globalThis, &iter, Iterator.forEach); } + if (this.globalThis.hasException()) { + this.failed = true; + } + if (this.failed) return; + if (iter.i == 0) { if (value.isClass(this.globalThis)) this.printAs(.Class, Writer, writer_, value, jsType, enable_ansi_colors) @@ -3446,6 +3556,8 @@ pub fn timeLog( .globalThis = global, .ordered_properties = false, .quote_strings = false, + .stack_check = bun.StackCheck.init(), + .can_throw_stack_overflow = true, }; var console = global.bunVM().console; var writer = console.error_writer.writer(); diff --git a/src/bun.js/api/BunObject.zig b/src/bun.js/api/BunObject.zig index 13d6f66d791805..259e741f33b6a0 100644 --- a/src/bun.js/api/BunObject.zig +++ b/src/bun.js/api/BunObject.zig @@ -344,7 +344,8 @@ pub fn braces(global: *JSC.JSGlobalObject, brace_str: bun.String, opts: gen.Brac pub fn which(globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) bun.JSError!JSC.JSValue { const arguments_ = callframe.arguments_old(2); - var path_buf: bun.PathBuffer = undefined; + const path_buf = bun.PathBufferPool.get(); + defer bun.PathBufferPool.put(path_buf); var arguments = JSC.Node.ArgumentsSlice.init(globalThis.bunVM(), arguments_.slice()); defer arguments.deinit(); const path_arg = arguments.nextEat() orelse { @@ -397,7 +398,7 @@ pub fn which(globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) bun.JSE } if (Which.which( - &path_buf, + path_buf, path_str.slice(), cwd_str.slice(), bin_str.slice(), @@ -506,6 +507,7 @@ pub fn inspect(globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) bun.J // very stable memory address var array = MutableString.init(getAllocator(globalThis), 0) catch unreachable; + defer array.deinit(); var buffered_writer_ = MutableString.BufferedWriter{ .context = &array }; var buffered_writer = &buffered_writer_; @@ -523,15 +525,19 @@ pub fn inspect(globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) bun.J writer, formatOptions, ); + if (globalThis.hasException()) { + return .zero; + } + buffered_writer.flush() catch { - return .undefined; + return globalThis.throwOutOfMemory(); }; // we are going to always clone to keep things simple for now // the common case here will be stack-allocated, so it should be fine var out = ZigString.init(array.slice()).withEncoding(); const ret = out.toJS(globalThis); - array.deinit(); + return ret; } diff --git a/src/bun.js/api/bun/subprocess.zig b/src/bun.js/api/bun/subprocess.zig index 143b87fb2544de..7c8774d54839d9 100644 --- a/src/bun.js/api/bun/subprocess.zig +++ b/src/bun.js/api/bun/subprocess.zig @@ -1703,15 +1703,58 @@ pub const Subprocess = struct { return spawnMaybeSync(globalThis, args, secondaryArgsValue, true); } + // This is split into a separate function to conserve stack space. + // On Windows, a single path buffer can take 64 KB. + fn getArgv0(globalThis: *JSC.JSGlobalObject, PATH: []const u8, cwd: []const u8, argv0: ?[*:0]const u8, first_cmd: JSValue, allocator: std.mem.Allocator) bun.JSError!struct { + argv0: [:0]const u8, + arg0: [:0]u8, + } { + var arg0 = try first_cmd.toSliceOrNullWithAllocator(globalThis, allocator); + defer arg0.deinit(); + // Heap allocate it to ensure we don't run out of stack space. + const path_buf: *bun.PathBuffer = try bun.default_allocator.create(bun.PathBuffer); + defer bun.default_allocator.destroy(path_buf); + + var actual_argv0: [:0]const u8 = ""; + + if (argv0 == null) { + const resolved = Which.which(path_buf, PATH, cwd, arg0.slice()) orelse { + return throwCommandNotFound(globalThis, arg0.slice()); + }; + actual_argv0 = try allocator.dupeZ(u8, resolved); + } else { + const resolved = Which.which(path_buf, PATH, cwd, bun.sliceTo(argv0.?, 0)) orelse { + return throwCommandNotFound(globalThis, arg0.slice()); + }; + actual_argv0 = try allocator.dupeZ(u8, resolved); + } + + return .{ + .argv0 = actual_argv0, + .arg0 = try allocator.dupeZ(u8, arg0.slice()), + }; + } + pub fn spawnMaybeSync( globalThis: *JSC.JSGlobalObject, args_: JSValue, secondaryArgsValue: ?JSValue, comptime is_sync: bool, ) bun.JSError!JSValue { + if (comptime is_sync) { + // We skip this on Windows due to test failures. + if (comptime !Environment.isWindows) { + // Since the event loop is recursively called, we need to check if it's safe to recurse. + if (!bun.StackCheck.init().isSafeToRecurse()) { + globalThis.throwStackOverflow(); + return error.JSError; + } + } + } + var arena = bun.ArenaAllocator.init(bun.default_allocator); defer arena.deinit(); - var allocator = arena.allocator(); + const allocator = arena.allocator(); var override_env = false; var env_array = std.ArrayListUnmanaged(?[*:0]const u8){}; @@ -1801,33 +1844,16 @@ pub const Subprocess = struct { return globalThis.throwInvalidArguments("cmd must not be empty", .{}); } - { - var first_cmd = cmds_array.next().?; - var arg0 = try first_cmd.toSliceOrNullWithAllocator(globalThis, allocator); - defer arg0.deinit(); - - if (argv0 == null) { - var path_buf: bun.PathBuffer = undefined; - const resolved = Which.which(&path_buf, PATH, cwd, arg0.slice()) orelse { - return throwCommandNotFound(globalThis, arg0.slice()); - }; - argv0 = try allocator.dupeZ(u8, resolved); - } else { - var path_buf: bun.PathBuffer = undefined; - const resolved = Which.which(&path_buf, PATH, cwd, bun.sliceTo(argv0.?, 0)) orelse { - return throwCommandNotFound(globalThis, arg0.slice()); - }; - argv0 = try allocator.dupeZ(u8, resolved); - } - - argv.appendAssumeCapacity(try allocator.dupeZ(u8, arg0.slice())); - } + const argv0_result = try getArgv0(globalThis, PATH, cwd, argv0, cmds_array.next().?, allocator); + argv0 = argv0_result.argv0.ptr; + argv.appendAssumeCapacity(argv0_result.arg0.ptr); while (cmds_array.next()) |value| { - const arg = value.getZigString(globalThis); + const arg = try value.toBunString2(globalThis); + defer arg.deref(); // if the string is empty, ignore it, don't add it to the argv - if (arg.len == 0) { + if (arg.isEmpty()) { continue; } argv.appendAssumeCapacity(try arg.toOwnedSliceZ(allocator)); diff --git a/src/bun.js/bindings/BunString.cpp b/src/bun.js/bindings/BunString.cpp index 17200b35c30552..319041594197f8 100644 --- a/src/bun.js/bindings/BunString.cpp +++ b/src/bun.js/bindings/BunString.cpp @@ -13,6 +13,7 @@ #include "ZigGlobalObject.h" #include "IDLTypes.h" +#include #include #include #include @@ -34,6 +35,7 @@ #include "GCDefferalContext.h" #include "wtf/text/StringImpl.h" +#include "wtf/text/StringToIntegerConversion.h" extern "C" void mi_free(void* ptr); @@ -90,6 +92,22 @@ extern "C" BunString BunString__tryCreateAtom(const char* bytes, size_t length) return { BunStringTag::Dead, {} }; } +// int64_t max to say "not a number" +extern "C" int64_t BunString__toInt32(BunString* bunString) +{ + if (bunString->tag == BunStringTag::Empty || bunString->tag == BunStringTag::Dead) { + return std::numeric_limits::max(); + } + + String str = bunString->toWTFString(); + auto val = WTF::parseIntegerAllowingTrailingJunk(str); + if (val) { + return val.value(); + } + + return std::numeric_limits::max(); +} + namespace Bun { JSC::JSValue toJS(JSC::JSGlobalObject* globalObject, BunString bunString) { diff --git a/src/bun.js/bindings/ErrorCode.ts b/src/bun.js/bindings/ErrorCode.ts index d04c096ae62c28..a4b54170546a4d 100644 --- a/src/bun.js/bindings/ErrorCode.ts +++ b/src/bun.js/bindings/ErrorCode.ts @@ -95,4 +95,7 @@ export default [ ["ERR_ASYNC_TYPE", TypeError], ["ERR_INVALID_ASYNC_ID", RangeError], ["ERR_ASYNC_CALLBACK", TypeError], + + // Postgres + ["ERR_POSTGRES_ERROR_RESPONSE", Error, "PostgresError"], ] as ErrorCodeMapping; diff --git a/src/bun.js/bindings/JSPropertyIterator.cpp b/src/bun.js/bindings/JSPropertyIterator.cpp index e386c6cc5a2c84..8d4657f469a9c8 100644 --- a/src/bun.js/bindings/JSPropertyIterator.cpp +++ b/src/bun.js/bindings/JSPropertyIterator.cpp @@ -1,7 +1,8 @@ - - #include "root.h" +#include "BunClientData.h" +#include "ZigGlobalObject.h" +#include "JavaScriptCore/JSType.h" #include "JavaScriptCore/EnumerationMode.h" #include "JavaScriptCore/ExceptionScope.h" #include "JavaScriptCore/ThrowScope.h" @@ -11,6 +12,7 @@ #include "wtf/Assertions.h" #include "wtf/FastMalloc.h" #include "headers-handwritten.h" +#include "ObjectBindings.h" namespace Bun { using namespace JSC; @@ -25,6 +27,7 @@ class JSPropertyIterator { RefPtr properties; Ref vm; + bool isSpecialProxy = false; static JSPropertyIterator* create(JSC::VM& vm, RefPtr data) { return new JSPropertyIterator(vm, data); @@ -33,7 +36,7 @@ class JSPropertyIterator { WTF_MAKE_FAST_ALLOCATED; }; -extern "C" JSPropertyIterator* Bun__JSPropertyIterator__create(JSC::JSGlobalObject* globalObject, JSC::EncodedJSValue encodedValue, size_t* count) +extern "C" JSPropertyIterator* Bun__JSPropertyIterator__create(JSC::JSGlobalObject* globalObject, JSC::EncodedJSValue encodedValue, size_t* count, bool own_properties_only, bool only_non_index_properties) { JSC::VM& vm = globalObject->vm(); JSC::JSValue value = JSValue::decode(encodedValue); @@ -41,7 +44,42 @@ extern "C" JSPropertyIterator* Bun__JSPropertyIterator__create(JSC::JSGlobalObje auto scope = DECLARE_THROW_SCOPE(vm); JSC::PropertyNameArray array(vm, PropertyNameMode::StringsAndSymbols, PrivateSymbolMode::Exclude); - object->getPropertyNames(globalObject, array, DontEnumPropertiesMode::Exclude); + +#if OS(WINDOWS) + if (UNLIKELY(object->type() == JSC::ProxyObjectType)) { + // Check if we're actually iterating through the JSEnvironmentVariableMap's proxy. + auto* zigGlobal = defaultGlobalObject(globalObject); + if (zigGlobal->m_processEnvObject.isInitialized()) { + if (object == zigGlobal->m_processEnvObject.get(zigGlobal)) { + object->methodTable()->getOwnPropertyNames( + object, + globalObject, + array, + DontEnumPropertiesMode::Exclude); + RETURN_IF_EXCEPTION(scope, nullptr); + + *count = array.size(); + if (array.size() == 0) { + return nullptr; + } + + auto* iter = JSPropertyIterator::create(vm, array.releaseData()); + iter->isSpecialProxy = true; + return iter; + } + } + } +#endif + + if (own_properties_only) { + if (only_non_index_properties) { + object->getOwnNonIndexPropertyNames(globalObject, array, DontEnumPropertiesMode::Exclude); + } else { + object->getOwnPropertyNames(object, globalObject, array, DontEnumPropertiesMode::Exclude); + } + } else { + object->getPropertyNames(globalObject, array, DontEnumPropertiesMode::Exclude); + } RETURN_IF_EXCEPTION(scope, nullptr); *count = array.size(); @@ -52,13 +90,79 @@ extern "C" JSPropertyIterator* Bun__JSPropertyIterator__create(JSC::JSGlobalObje return JSPropertyIterator::create(vm, array.releaseData()); } +extern "C" size_t Bun__JSPropertyIterator__getLongestPropertyName(JSPropertyIterator* iter, JSC::JSGlobalObject* globalObject, JSC::JSObject* object) +{ + size_t longest = 0; + for (const auto& prop : iter->properties->propertyNameVector()) { + if (prop.length() > longest) { + longest = prop.length(); + } + } + + return longest; +} + +static EncodedJSValue getOwnProxyObject(JSPropertyIterator* iter, JSObject* object, const JSC::Identifier& prop, BunString* propertyName) +{ + auto& vm = iter->vm; + auto scope = DECLARE_THROW_SCOPE(vm); + + PropertySlot slot(object, PropertySlot::InternalMethodType::GetOwnProperty, nullptr); + auto* globalObject = object->globalObject(); + if (!object->methodTable()->getOwnPropertySlot(object, globalObject, prop, slot)) { + return {}; + } + RETURN_IF_EXCEPTION(scope, {}); + + JSValue result = slot.getValue(globalObject, prop); + RETURN_IF_EXCEPTION(scope, {}); + + *propertyName = Bun::toString(prop.impl()); + return JSValue::encode(result); +} + extern "C" EncodedJSValue Bun__JSPropertyIterator__getNameAndValue(JSPropertyIterator* iter, JSC::JSGlobalObject* globalObject, JSC::JSObject* object, BunString* propertyName, size_t i) { const auto& prop = iter->properties->propertyNameVector()[i]; + if (UNLIKELY(iter->isSpecialProxy)) { + return getOwnProxyObject(iter, object, prop, propertyName); + } + + auto& vm = iter->vm; + auto scope = DECLARE_THROW_SCOPE(vm); + PropertySlot slot(object, PropertySlot::InternalMethodType::GetOwnProperty); + if (!object->getOwnPropertySlot(object, globalObject, prop, slot)) { + return {}; + } + RETURN_IF_EXCEPTION(scope, {}); - auto scope = DECLARE_THROW_SCOPE(iter->vm); - JSValue result = object->get(globalObject, prop); + JSValue result = slot.getValue(globalObject, prop); + RETURN_IF_EXCEPTION(scope, {}); + + *propertyName = Bun::toString(prop.impl()); + return JSValue::encode(result); +} + +extern "C" EncodedJSValue Bun__JSPropertyIterator__getNameAndValueNonObservable(JSPropertyIterator* iter, JSC::JSGlobalObject* globalObject, JSC::JSObject* object, BunString* propertyName, size_t i) +{ + const auto& prop = iter->properties->propertyNameVector()[i]; + if (UNLIKELY(iter->isSpecialProxy)) { + return getOwnProxyObject(iter, object, prop, propertyName); + } + auto& vm = iter->vm; + auto scope = DECLARE_THROW_SCOPE(vm); + + PropertySlot slot(object, PropertySlot::InternalMethodType::VMInquiry, vm.ptr()); + if (!object->getNonIndexPropertySlot(globalObject, prop, slot)) { + return {}; + } + RETURN_IF_EXCEPTION(scope, {}); + + if (slot.isAccessor() || slot.isCustom()) { + return {}; + } + JSValue result = slot.getPureResult(); RETURN_IF_EXCEPTION(scope, {}); *propertyName = Bun::toString(prop.impl()); diff --git a/src/bun.js/bindings/JSPropertyIterator.zig b/src/bun.js/bindings/JSPropertyIterator.zig index f5361cc3ae0fe7..ff4a4e77f6c776 100644 --- a/src/bun.js/bindings/JSPropertyIterator.zig +++ b/src/bun.js/bindings/JSPropertyIterator.zig @@ -2,14 +2,19 @@ const bun = @import("root").bun; const JSC = bun.JSC; //extern "C" EncodedJSValue Bun__JSPropertyIterator__getNameAndValue(JSPropertyIterator* iter, JSC::JSGlobalObject* globalObject, JSC::JSObject* object, BunString* propertyName, size_t i) -extern "C" fn Bun__JSPropertyIterator__create(globalObject: *JSC.JSGlobalObject, encodedValue: JSC.JSValue, *usize) ?*anyopaque; +extern "C" fn Bun__JSPropertyIterator__create(globalObject: *JSC.JSGlobalObject, encodedValue: JSC.JSValue, *usize, own_properties_only: bool, only_non_index_properties: bool) ?*anyopaque; extern "C" fn Bun__JSPropertyIterator__getNameAndValue(iter: ?*anyopaque, globalObject: *JSC.JSGlobalObject, object: *anyopaque, propertyName: *bun.String, i: usize) JSC.JSValue; +extern "C" fn Bun__JSPropertyIterator__getNameAndValueNonObservable(iter: ?*anyopaque, globalObject: *JSC.JSGlobalObject, object: *anyopaque, propertyName: *bun.String, i: usize) JSC.JSValue; extern "C" fn Bun__JSPropertyIterator__getName(iter: ?*anyopaque, propertyName: *bun.String, i: usize) void; extern "C" fn Bun__JSPropertyIterator__deinit(iter: ?*anyopaque) void; +extern "C" fn Bun__JSPropertyIterator__getLongestPropertyName(iter: ?*anyopaque, globalObject: *JSC.JSGlobalObject, object: *anyopaque) usize; pub const JSPropertyIteratorOptions = struct { skip_empty_name: bool, include_value: bool, + own_properties_only: bool = true, + observable: bool = true, + only_non_index_properties: bool = false, }; pub fn JSPropertyIterator(comptime options: JSPropertyIteratorOptions) type { @@ -23,6 +28,11 @@ pub fn JSPropertyIterator(comptime options: JSPropertyIteratorOptions) type { object: *JSC.JSCell = undefined, value: JSC.JSValue = .zero, + pub fn getLongestPropertyName(this: *@This()) usize { + if (this.impl == null) return 0; + return Bun__JSPropertyIterator__getLongestPropertyName(this.impl, this.globalObject, this.object); + } + pub fn deinit(this: *@This()) void { if (this.impl) |impl| { Bun__JSPropertyIterator__deinit(impl); @@ -36,7 +46,7 @@ pub fn JSPropertyIterator(comptime options: JSPropertyIteratorOptions) type { .globalObject = globalObject, }; - iter.impl = Bun__JSPropertyIterator__create(globalObject, object, &iter.len); + iter.impl = Bun__JSPropertyIterator__create(globalObject, object, &iter.len, options.own_properties_only, options.only_non_index_properties); return iter; } @@ -57,7 +67,8 @@ pub fn JSPropertyIterator(comptime options: JSPropertyIteratorOptions) type { this.iter_i += 1; var name = bun.String.dead; if (comptime options.include_value) { - const current = Bun__JSPropertyIterator__getNameAndValue(this.impl, this.globalObject, this.object, &name, i); + const FnToUse = if (options.observable) Bun__JSPropertyIterator__getNameAndValue else Bun__JSPropertyIterator__getNameAndValueNonObservable; + const current = FnToUse(this.impl, this.globalObject, this.object, &name, i); if (current == .zero) { return this.next(); } diff --git a/src/bun.js/bindings/bindings.cpp b/src/bun.js/bindings/bindings.cpp index cb1a0446df1359..45fb786707bbeb 100644 --- a/src/bun.js/bindings/bindings.cpp +++ b/src/bun.js/bindings/bindings.cpp @@ -1,5 +1,7 @@ + #include "root.h" +#include "JavaScriptCore/CatchScope.h" #include "JavaScriptCore/Exception.h" #include "ErrorCode+List.h" #include "ErrorCode.h" @@ -64,6 +66,7 @@ #include "wtf/Assertions.h" #include "wtf/Compiler.h" +#include "wtf/StackCheck.h" #include "wtf/text/ExternalStringImpl.h" #include "wtf/text/OrdinalNumber.h" #include "wtf/text/StringCommon.h" @@ -126,6 +129,8 @@ #include "ErrorStackTrace.h" #include "ObjectBindings.h" +#include + #if OS(DARWIN) #if BUN_DEBUG #include @@ -5362,6 +5367,12 @@ bool JSC__JSValue__toBoolean(JSC__JSValue JSValue0) return JSValue::decode(JSValue0).pureToBoolean() != TriState::False; } +extern "C" void JSGlobalObject__throwStackOverflow(JSC__JSGlobalObject* globalObject) +{ + auto scope = DECLARE_THROW_SCOPE(globalObject->vm()); + throwStackOverflowError(globalObject, scope); +} + template static void JSC__JSValue__forEachPropertyImpl(JSC__JSValue JSValue0, JSC__JSGlobalObject* globalObject, void* arg2, void (*iter)(JSC__JSGlobalObject* arg0, void* ctx, ZigString* arg2, JSC__JSValue JSValue3, bool isSymbol, bool isPrivateSymbol)) { @@ -5372,9 +5383,15 @@ static void JSC__JSValue__forEachPropertyImpl(JSC__JSValue JSValue0, JSC__JSGlob return; JSC::VM& vm = globalObject->vm(); - auto scope = DECLARE_CATCH_SCOPE(vm); + auto throwScope = DECLARE_THROW_SCOPE(vm); + + if (UNLIKELY(!vm.isSafeToRecurse())) { + throwStackOverflowError(globalObject, throwScope); + return; + } size_t prototypeCount = 0; + auto scope = DECLARE_CATCH_SCOPE(vm); JSC::Structure* structure = object->structure(); bool fast = !nonIndexedOnly && canPerformFastPropertyEnumerationForIterationBun(structure); @@ -5383,6 +5400,7 @@ static void JSC__JSValue__forEachPropertyImpl(JSC__JSValue JSValue0, JSC__JSGlob if (fast) { if (structure->outOfLineSize() == 0 && structure->inlineSize() == 0) { fast = false; + if (JSValue proto = object->getPrototype(vm, globalObject)) { if ((structure = proto.structureOrNull())) { prototypeObject = proto; @@ -5434,6 +5452,7 @@ static void JSC__JSValue__forEachPropertyImpl(JSC__JSValue JSValue0, JSC__JSGlob propertyValue = objectToUse->getIfPropertyExists(globalObject, prop); } + // Ignore exceptions due to getters. if (scope.exception()) scope.clearException(); @@ -5449,14 +5468,21 @@ static void JSC__JSValue__forEachPropertyImpl(JSC__JSValue JSValue0, JSC__JSGlob return true; iter(globalObject, arg2, &key, JSC::JSValue::encode(propertyValue), prop->isSymbol(), isPrivate); + // Propagate exceptions from callbacks. + if (UNLIKELY(scope.exception())) { + return false; + } return true; }); + + // Propagate exceptions from callbacks. if (scope.exception()) { - scope.clearException(); + return; } if (anyHits) { if (prototypeCount++ < 5) { + if (JSValue proto = prototypeObject.getPrototype(globalObject)) { if (!(proto == globalObject->objectPrototype() || proto == globalObject->functionPrototype() || (proto.inherits() && jsCast(proto)->target() != globalObject))) { if ((structure = proto.structureOrNull())) { @@ -5466,6 +5492,10 @@ static void JSC__JSValue__forEachPropertyImpl(JSC__JSValue JSValue0, JSC__JSGlob } } } + // Ignore exceptions from Proxy "getPrototype" trap. + if (UNLIKELY(scope.exception())) { + scope.clearException(); + } } return; } @@ -5484,7 +5514,7 @@ static void JSC__JSValue__forEachPropertyImpl(JSC__JSValue JSValue0, JSC__JSGlob iterating->methodTable()->getOwnPropertyNames(iterating, globalObject, properties, DontEnumPropertiesMode::Include); } - RETURN_IF_EXCEPTION(scope, ); + RETURN_IF_EXCEPTION(scope, void()); for (auto& property : properties) { if (UNLIKELY(property.isEmpty() || property.isNull())) continue; @@ -5502,6 +5532,10 @@ static void JSC__JSValue__forEachPropertyImpl(JSC__JSValue JSValue0, JSC__JSGlob JSC::PropertySlot slot(object, PropertySlot::InternalMethodType::Get); if (!object->getPropertySlot(globalObject, property, slot)) continue; + // Ignore exceptions from "Get" proxy traps. + if (scope.exception()) { + scope.clearException(); + } if ((slot.attributes() & PropertyAttribute::DontEnum) != 0) { if (property == propertyNames->underscoreProto @@ -5548,6 +5582,7 @@ static void JSC__JSValue__forEachPropertyImpl(JSC__JSValue JSValue0, JSC__JSGlob propertyValue = slot.getValue(globalObject, property); } + // Ignore exceptions from getters. if (scope.exception()) { scope.clearException(); propertyValue = jsUndefined(); @@ -5561,6 +5596,9 @@ static void JSC__JSValue__forEachPropertyImpl(JSC__JSValue JSValue0, JSC__JSGlob continue; iter(globalObject, arg2, &key, JSC::JSValue::encode(propertyValue), property.isSymbol(), isPrivate); + + // Propagate exceptions from callbacks. + RETURN_IF_EXCEPTION(scope, void()); } if constexpr (nonIndexedOnly) { break; diff --git a/src/bun.js/bindings/bindings.zig b/src/bun.js/bindings/bindings.zig index e79bf9799f4265..94a0698a29842f 100644 --- a/src/bun.js/bindings/bindings.zig +++ b/src/bun.js/bindings/bindings.zig @@ -3039,7 +3039,10 @@ pub const JSGlobalObject = opaque { pub fn allocator(this: *JSGlobalObject) std.mem.Allocator { return this.bunVM().allocator; } - + extern fn JSGlobalObject__throwStackOverflow(this: *JSGlobalObject) void; + pub fn throwStackOverflow(this: *JSGlobalObject) void { + JSGlobalObject__throwStackOverflow(this); + } extern fn JSGlobalObject__throwOutOfMemoryError(this: *JSGlobalObject) void; pub fn throwOutOfMemory(this: *JSGlobalObject) bun.JSError { JSGlobalObject__throwOutOfMemoryError(this); @@ -5798,10 +5801,10 @@ pub const JSValue = enum(i64) { formatter: *Exports.ConsoleObject.Formatter, ) Exports.ConsoleObject.Formatter.ZigFormatter { formatter.remaining_values = &[_]JSValue{}; - if (formatter.map_node) |node| { - node.release(); - formatter.map_node = null; + if (formatter.map_node != null) { + formatter.deinit(); } + formatter.stack_check.update(); return Exports.ConsoleObject.Formatter.ZigFormatter{ .formatter = formatter, @@ -6809,6 +6812,21 @@ pub fn toJSHostFunction(comptime Function: JSHostZigFunction) JSC.JSHostFunction error.JSError => .zero, error.OutOfMemory => globalThis.throwOutOfMemoryValue(), }; + if (comptime bun.Environment.isDebug) { + if (value != .zero) { + if (globalThis.hasException()) { + bun.Output.prettyErrorln( + \\Assertion failed: Native function returned a non-zero JSValue while an exception is pending + \\ + \\Did you forget to check if an exception is pending? + \\ + \\ if (globalThis.hasException()) return .zero; + \\ + , .{}); + Output.flush(); + } + } + } bun.assert((value == .zero) == globalThis.hasException()); return value; } diff --git a/src/bun.js/bindings/exports.zig b/src/bun.js/bindings/exports.zig index 586f3251782923..b7374f27051857 100644 --- a/src/bun.js/bindings/exports.zig +++ b/src/bun.js/bindings/exports.zig @@ -48,6 +48,10 @@ pub const ZigGlobalObject = extern struct { worker_ptr: ?*anyopaque, ) *JSGlobalObject { const global = shim.cppFn("create", .{ console, context_id, mini_mode, eval_mode, worker_ptr }); + + // JSC might mess with the stack size. + bun.StackCheck.configureThread(); + return global; } diff --git a/src/bun.js/bindings/wtf-bindings.cpp b/src/bun.js/bindings/wtf-bindings.cpp index 52de7d5a7c0b0c..d33725bbaebeeb 100644 --- a/src/bun.js/bindings/wtf-bindings.cpp +++ b/src/bun.js/bindings/wtf-bindings.cpp @@ -1,6 +1,7 @@ #include "root.h" #include "wtf-bindings.h" - +#include +#include #include #include #include @@ -237,4 +238,16 @@ size_t toISOString(JSC::VM& vm, double date, char in[64]) return charactersWritten; } +static thread_local WTF::StackBounds stackBoundsForCurrentThread = WTF::StackBounds::emptyBounds(); + +extern "C" void Bun__StackCheck__initialize() +{ + stackBoundsForCurrentThread = WTF::StackBounds::currentThreadStackBounds(); +} + +extern "C" void* Bun__StackCheck__getMaxStack() +{ + return stackBoundsForCurrentThread.end(); +} + } diff --git a/src/bun.js/javascript.zig b/src/bun.js/javascript.zig index 5db69ffbf25901..b5a2aa70482e46 100644 --- a/src/bun.js/javascript.zig +++ b/src/bun.js/javascript.zig @@ -2916,10 +2916,17 @@ pub const VirtualMachine = struct { writer: Writer, comptime allow_side_effects: bool, ) void { + var formatter = ConsoleObject.Formatter{ + .globalThis = this.global, + .quote_strings = false, + .single_line = false, + .stack_check = bun.StackCheck.init(), + }; + defer formatter.deinit(); if (Output.enable_ansi_colors) { - this.printErrorlikeObject(exception.value(), exception, exception_list, Writer, writer, true, allow_side_effects); + this.printErrorlikeObject(exception.value(), exception, exception_list, &formatter, Writer, writer, true, allow_side_effects); } else { - this.printErrorlikeObject(exception.value(), exception, exception_list, Writer, writer, false, allow_side_effects); + this.printErrorlikeObject(exception.value(), exception, exception_list, &formatter, Writer, writer, false, allow_side_effects); } } @@ -2949,7 +2956,6 @@ pub const VirtualMachine = struct { if (result.isException(this.global.vm())) { const exception = @as(*Exception, @ptrCast(result.asVoid())); - this.printException( exception, exception_list, @@ -2957,10 +2963,17 @@ pub const VirtualMachine = struct { writer, true, ); - } else if (Output.enable_ansi_colors) { - this.printErrorlikeObject(result, null, exception_list, @TypeOf(writer), writer, true, true); } else { - this.printErrorlikeObject(result, null, exception_list, @TypeOf(writer), writer, false, true); + var formatter = ConsoleObject.Formatter{ + .globalThis = this.global, + .quote_strings = false, + .single_line = false, + .stack_check = bun.StackCheck.init(), + }; + defer formatter.deinit(); + switch (Output.enable_ansi_colors) { + inline else => |enable_colors| this.printErrorlikeObject(result, null, exception_list, &formatter, @TypeOf(writer), writer, enable_colors, true), + } } } @@ -3265,14 +3278,8 @@ pub const VirtualMachine = struct { return promise; } - pub fn printErrorLikeObjectSimple(this: *VirtualMachine, value: JSValue, writer: anytype, comptime escape_codes: bool) void { - this.printErrorlikeObject(value, null, null, @TypeOf(writer), writer, escape_codes, false); - } - pub fn printErrorLikeObjectToConsole(this: *VirtualMachine, value: JSValue) void { - switch (Output.enable_ansi_colors_stderr) { - inline else => |colors| this.printErrorLikeObjectSimple(value, Output.errorWriter(), colors), - } + this.runErrorHandler(value, null); } // When the Error-like object is one of our own, it's best to rely on the object directly instead of serializing it to a ZigException. @@ -3287,6 +3294,7 @@ pub const VirtualMachine = struct { value: JSValue, exception: ?*Exception, exception_list: ?*ExceptionList, + formatter: *ConsoleObject.Formatter, comptime Writer: type, writer: Writer, comptime allow_ansi_color: bool, @@ -3324,6 +3332,7 @@ pub const VirtualMachine = struct { const AggregateErrorIterator = struct { writer: Writer, current_exception_list: ?*ExceptionList = null, + formatter: *ConsoleObject.Formatter, pub fn iteratorWithColor(_vm: [*c]VM, globalObject: *JSGlobalObject, ctx: ?*anyopaque, nextValue: JSValue) callconv(.C) void { iterator(_vm, globalObject, nextValue, ctx.?, true); @@ -3333,10 +3342,10 @@ pub const VirtualMachine = struct { } inline fn iterator(_: [*c]VM, _: *JSGlobalObject, nextValue: JSValue, ctx: ?*anyopaque, comptime color: bool) void { const this_ = @as(*@This(), @ptrFromInt(@intFromPtr(ctx))); - VirtualMachine.get().printErrorlikeObject(nextValue, null, this_.current_exception_list, Writer, this_.writer, color, allow_side_effects); + VirtualMachine.get().printErrorlikeObject(nextValue, null, this_.current_exception_list, this_.formatter, Writer, this_.writer, color, allow_side_effects); } }; - var iter = AggregateErrorIterator{ .writer = writer, .current_exception_list = exception_list }; + var iter = AggregateErrorIterator{ .writer = writer, .current_exception_list = exception_list, .formatter = formatter }; if (comptime allow_ansi_color) { value.getErrorsProperty(this.global).forEach(this.global, &iter, AggregateErrorIterator.iteratorWithColor); } else { @@ -3348,6 +3357,7 @@ pub const VirtualMachine = struct { was_internal = this.printErrorFromMaybePrivateData( value, exception_list, + formatter, Writer, writer, allow_ansi_color, @@ -3355,10 +3365,11 @@ pub const VirtualMachine = struct { ); } - pub fn printErrorFromMaybePrivateData( + fn printErrorFromMaybePrivateData( this: *VirtualMachine, value: JSC.JSValue, exception_list: ?*ExceptionList, + formatter: *ConsoleObject.Formatter, comptime Writer: type, writer: Writer, comptime allow_ansi_color: bool, @@ -3407,6 +3418,7 @@ pub const VirtualMachine = struct { this.printErrorInstance( value, exception_list, + formatter, Writer, writer, allow_ansi_color, @@ -3748,7 +3760,7 @@ pub const VirtualMachine = struct { } } - pub fn printErrorInstance(this: *VirtualMachine, error_instance: JSValue, exception_list: ?*ExceptionList, comptime Writer: type, writer: Writer, comptime allow_ansi_color: bool, comptime allow_side_effects: bool) anyerror!void { + fn printErrorInstance(this: *VirtualMachine, error_instance: JSValue, exception_list: ?*ExceptionList, formatter: *ConsoleObject.Formatter, comptime Writer: type, writer: Writer, comptime allow_ansi_color: bool, comptime allow_side_effects: bool) anyerror!void { var exception_holder = ZigException.Holder.init(); var exception = exception_holder.zigException(); defer exception_holder.deinit(this); @@ -3920,32 +3932,6 @@ pub const VirtualMachine = struct { try this.printErrorNameAndMessage(name, message, Writer, writer, allow_ansi_color); } - var add_extra_line = false; - - const Show = struct { - system_code: bool = false, - syscall: bool = false, - errno: bool = false, - path: bool = false, - fd: bool = false, - }; - - const show = Show{ - .system_code = !exception.system_code.eql(name) and !exception.system_code.isEmpty(), - .syscall = !exception.syscall.isEmpty(), - .errno = exception.errno != 0, - .path = !exception.path.isEmpty(), - .fd = exception.fd != -1, - }; - - const extra_fields = .{ - "url", - "info", - "pkg", - "errors", - "cause", - }; - // This is usually unsafe to do, but we are protecting them each time first var errors_to_append = std.ArrayList(JSC.JSValue).init(this.allocator); defer { @@ -3955,82 +3941,146 @@ pub const VirtualMachine = struct { errors_to_append.deinit(); } - if (error_instance != .zero and error_instance.isCell() and error_instance.jsType().canGet()) { - inline for (extra_fields) |field| { - if (try error_instance.getTruthyComptime(this.global, field)) |value| { - const kind = value.jsType(); - if (kind.isStringLike()) { - if (value.toStringOrNull(this.global)) |str| { - var zig_str = str.toSlice(this.global, bun.default_allocator); - defer zig_str.deinit(); - try writer.print(comptime Output.prettyFmt(" {s}: \"{s}\"\n", allow_ansi_color), .{ field, zig_str.slice() }); - add_extra_line = true; + var saw_cause = false; + if (error_instance != .zero) { + const error_instance_type = error_instance.jsType(); + if (error_instance_type == .ErrorInstance) { + const Iterator = JSC.JSPropertyIterator(.{ + .include_value = true, + .skip_empty_name = true, + .own_properties_only = true, + .observable = false, + .only_non_index_properties = true, + }); + var iterator = Iterator.init(this.global, error_instance); + defer iterator.deinit(); + const longest_name = @min(iterator.getLongestPropertyName(), 10); + var is_first_property = true; + while (iterator.next()) |field| { + const value = iterator.value; + if (field.eqlComptime("message") or field.eqlComptime("name") or field.eqlComptime("stack")) { + continue; + } + + // We special-case the code property. Let's avoid printing it twice. + if (field.eqlComptime("code")) { + if (value.isString()) { + const str = value.toBunString(this.global); + if (!str.isEmpty()) { + if (str.eql(name)) { + continue; + } + } } - } else if (kind == .ErrorInstance and + } + + const kind = value.jsType(); + if (kind == .ErrorInstance and // avoid infinite recursion !prev_had_errors) { + if (field.eqlComptime("cause")) { + saw_cause = true; + } value.protect(); try errors_to_append.append(value); - } else if (kind.isObject() or kind.isArray()) { + } else if (kind.isObject() or kind.isArray() or value.isPrimitive() or kind.isStringLike()) { var bun_str = bun.String.empty; defer bun_str.deref(); - value.jsonStringify(this.global, 2, &bun_str); //2 - try writer.print(comptime Output.prettyFmt(" {s}: {}\n", allow_ansi_color), .{ field, bun_str }); - add_extra_line = true; - } - } - } - } + const prev_disable_inspect_custom = formatter.disable_inspect_custom; + const prev_quote_strings = formatter.quote_strings; + const prev_max_depth = formatter.max_depth; + formatter.depth += 1; + defer { + formatter.depth -= 1; + formatter.max_depth = prev_max_depth; + formatter.quote_strings = prev_quote_strings; + formatter.disable_inspect_custom = prev_disable_inspect_custom; + } + formatter.max_depth = 1; + formatter.quote_strings = true; + formatter.disable_inspect_custom = true; - if (show.errno) { - if (show.syscall) { - try writer.writeAll(" "); - } - try writer.print(comptime Output.prettyFmt(" errno: {d}\n", allow_ansi_color), .{exception.errno}); - add_extra_line = true; - } + const pad_left = longest_name -| field.length(); + is_first_property = false; + try writer.writeByteNTimes(' ', pad_left); - if (show.system_code) { - if (show.syscall) { - try writer.writeAll(" "); - } else if (show.errno) { - try writer.writeAll(" "); - } - try writer.print(comptime Output.prettyFmt(" code: \"{}\"\n", allow_ansi_color), .{exception.system_code}); - add_extra_line = true; - } + try writer.print(comptime Output.prettyFmt(" {}: ", allow_ansi_color), .{field}); - if (show.syscall) { - try writer.print(comptime Output.prettyFmt(" syscall: \"{}\"\n", allow_ansi_color), .{exception.syscall}); - add_extra_line = true; - } + // When we're printing errors for a top-level uncaught eception / rejection, suppress further errors here. + if (allow_side_effects) { + if (this.global.hasException()) { + this.global.clearException(); + } + } + + formatter.format( + JSC.Formatter.Tag.getAdvanced( + value, + this.global, + .{ .disable_inspect_custom = true, .hide_global = true }, + ), + Writer, + writer, + value, + this.global, + allow_ansi_color, + ); + + if (allow_side_effects) { + // When we're printing errors for a top-level uncaught eception / rejection, suppress further errors here. + if (this.global.hasException()) { + this.global.clearException(); + } + } else if (this.global.hasException() or formatter.failed) { + return; + } - if (show.path) { - if (show.syscall) { - try writer.writeAll(" "); - } else if (show.errno) { - try writer.writeAll(" "); + try writer.writeAll(comptime Output.prettyFmt(",\n", allow_ansi_color)); + } + } + + if (!is_first_property) { + try writer.writeAll("\n"); + } + } else { + // If you do reportError([1,2,3]] we should still show something at least. + const tag = JSC.Formatter.Tag.getAdvanced( + error_instance, + this.global, + .{ .disable_inspect_custom = true, .hide_global = true }, + ); + if (tag.tag != .NativeCode) { + formatter.format( + tag, + Writer, + writer, + error_instance, + this.global, + allow_ansi_color, + ); + + // Always include a newline in this case + try writer.writeAll("\n"); + } } - try writer.print(comptime Output.prettyFmt(" path: \"{}\"\n", allow_ansi_color), .{exception.path}); - } - if (show.fd) { - if (show.syscall) { - try writer.writeAll(" "); - } else if (show.errno) { - try writer.writeAll(" "); + // "cause" is not enumerable, so the above loop won't see it. + if (!saw_cause and error_instance_type == .ErrorInstance) { + if (error_instance.getOwn(this.global, "cause")) |cause| { + if (cause.jsType() == .ErrorInstance) { + cause.protect(); + try errors_to_append.append(cause); + } + } } - try writer.print(comptime Output.prettyFmt(" fd: {d}\n", allow_ansi_color), .{exception.fd}); } - if (add_extra_line) try writer.writeAll("\n"); - try printStackTrace(@TypeOf(writer), writer, exception.stack, allow_ansi_color); for (errors_to_append.items) |err| { try writer.writeAll("\n"); - try this.printErrorInstance(err, exception_list, Writer, writer, allow_ansi_color, allow_side_effects); + try this.printErrorInstance(err, exception_list, formatter, Writer, writer, allow_ansi_color, allow_side_effects); } } diff --git a/src/bun.js/node/node_fs.zig b/src/bun.js/node/node_fs.zig index dab9d40b98b3d8..80860842090836 100644 --- a/src/bun.js/node/node_fs.zig +++ b/src/bun.js/node/node_fs.zig @@ -3557,10 +3557,12 @@ pub const NodeFS = struct { return Maybe(Return.CopyFile).todo(); } - var src_buf: bun.WPathBuffer = undefined; - var dest_buf: bun.WPathBuffer = undefined; - const src = strings.toWPathNormalizeAutoExtend(&src_buf, args.src.sliceZ(&this.sync_error_buf)); - const dest = strings.toWPathNormalizeAutoExtend(&dest_buf, args.dest.sliceZ(&this.sync_error_buf)); + const src_buf = bun.OSPathBufferPool.get(); + defer bun.OSPathBufferPool.put(src_buf); + const dest_buf = bun.OSPathBufferPool.get(); + defer bun.OSPathBufferPool.put(dest_buf); + const src = strings.toWPathNormalizeAutoExtend(src_buf, args.src.sliceZ(&this.sync_error_buf)); + const dest = strings.toWPathNormalizeAutoExtend(dest_buf, args.dest.sliceZ(&this.sync_error_buf)); if (windows.CopyFileW(src.ptr, dest.ptr, if (args.mode.shouldntOverwrite()) 1 else 0) == windows.FALSE) { if (ret.errnoSysP(0, .copyfile, args.src.slice())) |rest| { return shouldIgnoreEbusy(args.src, args.dest, rest); @@ -3766,11 +3768,12 @@ pub const NodeFS = struct { // TODO: verify this works correctly with unicode codepoints pub fn mkdirRecursiveImpl(this: *NodeFS, args: Arguments.Mkdir, comptime flavor: Flavor, comptime Ctx: type, ctx: Ctx) Maybe(Return.Mkdir) { _ = flavor; - var buf: bun.OSPathBuffer = undefined; + const buf = bun.OSPathBufferPool.get(); + defer bun.OSPathBufferPool.put(buf); const path: bun.OSPathSliceZ = if (Environment.isWindows) - strings.toNTPath(&buf, args.path.slice()) + strings.toNTPath(buf, args.path.slice()) else - args.path.osPath(&buf); + args.path.osPath(buf); // TODO: remove and make it always a comptime argument return switch (args.always_return_none) { @@ -5673,7 +5676,8 @@ pub const NodeFS = struct { pub fn osPathIntoSyncErrorBufOverlap(this: *NodeFS, slice: anytype) []const u8 { if (Environment.isWindows) { - var tmp: bun.WPathBuffer = undefined; + const tmp = bun.OSPathBufferPool.get(); + defer bun.OSPathBufferPool.put(tmp); @memcpy(tmp[0..slice.len], slice); return bun.strings.fromWPath(&this.sync_error_buf, tmp[0..slice.len]); } else {} @@ -6184,8 +6188,9 @@ pub const NodeFS = struct { .err => |err| return .{ .err = err }, .result => |src_fd| src_fd, }; - var wbuf: bun.WPathBuffer = undefined; - const len = bun.windows.GetFinalPathNameByHandleW(handle.cast(), &wbuf, wbuf.len, 0); + const wbuf = bun.OSPathBufferPool.get(); + defer bun.OSPathBufferPool.put(wbuf); + const len = bun.windows.GetFinalPathNameByHandleW(handle.cast(), wbuf, wbuf.len, 0); if (len == 0) { return ret.errnoSysP(0, .copyfile, this.osPathIntoSyncErrorBuf(dest)) orelse dst_enoent_maybe; } diff --git a/src/bun.js/node/types.zig b/src/bun.js/node/types.zig index fda45fe94b7aad..72232be19642b0 100644 --- a/src/bun.js/node/types.zig +++ b/src/bun.js/node/types.zig @@ -1123,7 +1123,7 @@ pub const ArgumentsSlice = struct { arena: bun.ArenaAllocator = bun.ArenaAllocator.init(bun.default_allocator), all: []const JSC.JSValue, threw: bool = false, - protected: std.bit_set.IntegerBitSet(32) = std.bit_set.IntegerBitSet(32).initEmpty(), + protected: bun.bit_set.IntegerBitSet(32) = bun.bit_set.IntegerBitSet(32).initEmpty(), will_be_async: bool = false, pub fn unprotect(this: *ArgumentsSlice) void { @@ -1132,7 +1132,7 @@ pub const ArgumentsSlice = struct { while (iter.next()) |i| { JSC.C.JSValueUnprotect(ctx, this.all[i].asObjectRef()); } - this.protected = std.bit_set.IntegerBitSet(32).initEmpty(); + this.protected = bun.bit_set.IntegerBitSet(32).initEmpty(); } pub fn deinit(this: *ArgumentsSlice) void { @@ -2137,10 +2137,14 @@ pub const Process = struct { pub fn Bun__Process__editWindowsEnvVar(k: bun.String, v: bun.String) callconv(.C) void { if (k.tag == .Empty) return; const wtf1 = k.value.WTFStringImpl; - var buf1: [32768]u16 = undefined; - var buf2: [32768]u16 = undefined; + var fixed_stack_allocator = std.heap.stackFallback(1025, bun.default_allocator); + const allocator = fixed_stack_allocator.get(); + var buf1 = allocator.alloc(u16, k.utf16ByteLength() + 1) catch bun.outOfMemory(); + defer allocator.free(buf1); + var buf2 = allocator.alloc(u16, v.utf16ByteLength() + 1) catch bun.outOfMemory(); + defer allocator.free(buf2); const len1: usize = switch (wtf1.is8Bit()) { - true => bun.strings.copyLatin1IntoUTF16([]u16, &buf1, []const u8, wtf1.latin1Slice()).written, + true => bun.strings.copyLatin1IntoUTF16([]u16, buf1, []const u8, wtf1.latin1Slice()).written, false => b: { @memcpy(buf1[0..wtf1.length()], wtf1.utf16Slice()); break :b wtf1.length(); @@ -2151,7 +2155,7 @@ pub const Process = struct { if (v.tag == .Empty) break :str (&[_]u16{0})[0..0 :0]; const wtf2 = v.value.WTFStringImpl; const len2: usize = switch (wtf2.is8Bit()) { - true => bun.strings.copyLatin1IntoUTF16([]u16, &buf2, []const u8, wtf2.latin1Slice()).written, + true => bun.strings.copyLatin1IntoUTF16([]u16, buf2, []const u8, wtf2.latin1Slice()).written, false => b: { @memcpy(buf2[0..wtf2.length()], wtf2.utf16Slice()); break :b wtf2.length(); diff --git a/src/bun.js/web_worker.zig b/src/bun.js/web_worker.zig index 6fcb6eed62ec30..506d818dc3a929 100644 --- a/src/bun.js/web_worker.zig +++ b/src/bun.js/web_worker.zig @@ -513,15 +513,18 @@ pub const WebWorker = struct { if (loop) |loop_| { loop_.internal_loop_data.jsc_vm = null; } + bun.uws.onThreadExit(); this.deinit(); if (vm_to_deinit) |vm| { vm.deinit(); // NOTE: deinit here isn't implemented, so freeing workers will leak the vm. } + bun.deleteAllPoolsForThreadExit(); if (arena) |*arena_| { arena_.deinit(); } + bun.exitThread(); } diff --git a/src/bun.js/webcore/streams.zig b/src/bun.js/webcore/streams.zig index 165190e6be0e61..d4f61a5c146aa5 100644 --- a/src/bun.js/webcore/streams.zig +++ b/src/bun.js/webcore/streams.zig @@ -1996,7 +1996,7 @@ pub fn NewJSSink(comptime SinkType: type, comptime name_: []const u8) type { // TODO: make this JSGlobalObject local // for better security -const ByteListPool = ObjectPool( +pub const ByteListPool = ObjectPool( bun.ByteList, null, true, @@ -2588,7 +2588,12 @@ pub fn HTTPServerWritable(comptime ssl: bool) type { if (this.pooled_buffer) |pooled| { this.buffer.len = 0; + if (this.buffer.cap > 64 * 1024) { + this.buffer.deinitWithAllocator(bun.default_allocator); + this.buffer = bun.ByteList.init(""); + } pooled.data = this.buffer; + this.buffer = bun.ByteList.init(""); this.pooled_buffer = null; pooled.release(); diff --git a/src/bun.zig b/src/bun.zig index 9c37bf88545be3..b96006c618a5b4 100644 --- a/src/bun.zig +++ b/src/bun.zig @@ -3229,6 +3229,19 @@ pub fn exitThread() noreturn { } } +pub fn deleteAllPoolsForThreadExit() void { + const pools_to_delete = .{ + JSC.WebCore.ByteListPool, + bun.WPathBufferPool, + bun.PathBufferPool, + bun.JSC.ConsoleObject.Formatter.Visited.Pool, + bun.js_parser.StringVoidMap.Pool, + }; + inline for (pools_to_delete) |pool| { + pool.deleteAll(); + } +} + pub const Tmpfile = @import("./tmp.zig").Tmpfile; pub const io = @import("./io/io.zig"); @@ -4122,3 +4135,81 @@ pub inline fn isComptimeKnown(x: anytype) bool { pub inline fn itemOrNull(comptime T: type, slice: []const T, index: usize) ?T { return if (index < slice.len) slice[index] else null; } + +/// To handle stack overflows: +/// 1. StackCheck.init() +/// 2. .isSafeToRecurse() +pub const StackCheck = struct { + cached_stack_end: usize = 0, + + extern fn Bun__StackCheck__initialize() void; + pub fn configureThread() void { + Bun__StackCheck__initialize(); + } + + extern "C" fn Bun__StackCheck__getMaxStack() usize; + fn getStackEnd() usize { + return Bun__StackCheck__getMaxStack(); + } + + pub fn init() StackCheck { + return StackCheck{ .cached_stack_end = getStackEnd() }; + } + + pub fn update(this: *StackCheck) void { + this.cached_stack_end = getStackEnd(); + } + + /// Is there at least 128 KB of stack space available? + pub fn isSafeToRecurse(this: StackCheck) bool { + const stack_ptr: usize = @frameAddress(); + const remaining_stack = stack_ptr -| this.cached_stack_end; + return remaining_stack > 1024 * if (Environment.isWindows) 256 else 128; + } +}; + +// Workaround for lack of branch hints. +pub noinline fn throwStackOverflow() StackOverflow!void { + @setCold(true); + return error.StackOverflow; +} +const StackOverflow = error{StackOverflow}; + +// This pool exists because on Windows, each path buffer costs 64 KB. +// This makes the stack memory usage very unpredictable, which means we can't really know how much stack space we have left. +// This pool is a workaround to make the stack memory usage more predictable. +// We keep up to 4 path buffers alive per thread at a time. +pub fn PathBufferPoolT(comptime T: type) type { + return struct { + const Pool = ObjectPool(PathBuf, null, true, 4); + pub const PathBuf = struct { + bytes: T, + + pub fn deinit(this: *PathBuf) void { + var node: *Pool.Node = @alignCast(@fieldParentPtr("data", this)); + node.release(); + } + }; + + pub fn get() *T { + // use a threadlocal allocator so mimalloc deletes it on thread deinit. + return &Pool.get(bun.threadlocalAllocator()).data.bytes; + } + + pub fn put(buffer: *T) void { + var path_buf: *PathBuf = @alignCast(@fieldParentPtr("bytes", buffer)); + path_buf.deinit(); + } + + pub fn deleteAll() void { + Pool.deleteAll(); + } + }; +} + +pub const PathBufferPool = PathBufferPoolT(bun.PathBuffer); +pub const WPathBufferPool = if (Environment.isWindows) PathBufferPoolT(bun.WPathBuffer) else struct { + // So it can be used in code that deletes all the pools. + pub fn deleteAll() void {} +}; +pub const OSPathBufferPool = if (Environment.isWindows) WPathBufferPool else PathBufferPool; diff --git a/src/hive_array.zig b/src/hive_array.zig index c3479da816bdb4..fd9085b03551ca 100644 --- a/src/hive_array.zig +++ b/src/hive_array.zig @@ -11,7 +11,7 @@ pub fn HiveArray(comptime T: type, comptime capacity: u16) type { return struct { const Self = @This(); buffer: [capacity]T = undefined, - available: std.bit_set.IntegerBitSet(capacity) = std.bit_set.IntegerBitSet(capacity).initFull(), + available: bun.bit_set.IntegerBitSet(capacity) = bun.bit_set.IntegerBitSet(capacity).initFull(), pub const size = capacity; pub fn init() Self { diff --git a/src/http/websocket_http_client.zig b/src/http/websocket_http_client.zig index 36fbf8d44558f1..d93e2aff466b5a 100644 --- a/src/http/websocket_http_client.zig +++ b/src/http/websocket_http_client.zig @@ -204,12 +204,6 @@ const CppWebSocket = opaque { } }; -const body_buf_len = 16384 - 16; -const BodyBufBytes = [body_buf_len]u8; - -const BodyBufPool = ObjectPool(BodyBufBytes, null, true, 4); -const BodyBuf = BodyBufPool.Node; - pub fn NewHTTPUpgradeClient(comptime ssl: bool) type { return struct { pub const Socket = uws.NewSocketHandler(ssl); diff --git a/src/install/semver.zig b/src/install/semver.zig index e371344c66fad9..d03e65ae780b48 100644 --- a/src/install/semver.zig +++ b/src/install/semver.zig @@ -2241,7 +2241,7 @@ pub const Query = struct { }; } - pub const FlagsBitSet = std.bit_set.IntegerBitSet(3); + pub const FlagsBitSet = bun.bit_set.IntegerBitSet(3); pub fn isExact(this: *const Group) bool { return this.head.next == null and this.head.head.next == null and !this.head.head.range.hasRight() and this.head.head.range.left.op == .eql; diff --git a/src/js/builtins/shell.ts b/src/js/builtins/shell.ts index 28774036acdb7c..2c3a1db28e0fe7 100644 --- a/src/js/builtins/shell.ts +++ b/src/js/builtins/shell.ts @@ -25,18 +25,25 @@ export function createBunShellTemplateFunction(createShellInterpreter, createPar this.#output = output; this.name = "ShellError"; - // Maybe we should just print all the properties on the Error instance - // instead of speical ones - this.info = { - exitCode: code, - stderr: output.stderr, - stdout: output.stdout, - }; + // We previously added this so that errors would display the "info" property + // We fixed that, but now it displays both. + Object.defineProperty(this, "info", { + value: { + exitCode: code, + stderr: output.stderr, + stdout: output.stdout, + }, + writable: true, + enumerable: false, + configurable: true, + }); this.info.stdout.toJSON = lazyBufferToHumanReadableString; this.info.stderr.toJSON = lazyBufferToHumanReadableString; - Object.assign(this, this.info); + this.stdout = output.stdout; + this.stderr = output.stderr; + this.exitCode = code; } text(encoding) { diff --git a/src/js_lexer.zig b/src/js_lexer.zig index de7cfc228396f9..a052e9ef0544fe 100644 --- a/src/js_lexer.zig +++ b/src/js_lexer.zig @@ -2143,7 +2143,7 @@ fn NewLexer_( const flag_characters = "dgimsuvy"; const min_flag = comptime std.mem.min(u8, flag_characters); const max_flag = comptime std.mem.max(u8, flag_characters); - const RegexpFlags = std.bit_set.IntegerBitSet((max_flag - min_flag) + 1); + const RegexpFlags = bun.bit_set.IntegerBitSet((max_flag - min_flag) + 1); var flags = RegexpFlags.initEmpty(); while (isIdentifierContinue(lexer.code_point)) { switch (lexer.code_point) { diff --git a/src/js_lexer/identifier_data.zig b/src/js_lexer/identifier_data.zig index d82751e6201dbb..1c98ac25032d85 100644 --- a/src/js_lexer/identifier_data.zig +++ b/src/js_lexer/identifier_data.zig @@ -57,8 +57,9 @@ const id_end_range: [2]i32 = brk: { const id_end_count = id_end_range[1] - id_end_range[0] + 1; -pub const IDStartType = std.bit_set.StaticBitSet(id_start_count + 1); -pub const IDContinueType = std.bit_set.StaticBitSet(id_end_count + 1); +// Do not use std.bit_set. +pub const IDStartType = @import("../bit_set.zig").StaticBitSet(id_start_count + 1); +pub const IDContinueType = @import("../bit_set.zig").StaticBitSet(id_end_count + 1); pub const id_start: IDStartType = brk: { var bits: IDStartType = IDStartType.initEmpty(); diff --git a/src/js_parser.zig b/src/js_parser.zig index d225194424de89..cc8fec29c62f67 100644 --- a/src/js_parser.zig +++ b/src/js_parser.zig @@ -197,17 +197,6 @@ const MacroRefData = struct { const MacroRefs = std.AutoArrayHashMap(Ref, MacroRefData); -pub const AllocatedNamesPool = ObjectPool( - std.ArrayList(string), - struct { - pub fn init(allocator: std.mem.Allocator) anyerror!std.ArrayList(string) { - return std.ArrayList(string).init(allocator); - } - }.init, - true, - 4, -); - const Substitution = union(enum) { success: Expr, failure: Expr, @@ -2611,7 +2600,7 @@ const StmtList = ListManaged(Stmt); // This hash table is used every time we parse function args // Rather than allocating a new hash table each time, we can just reuse the previous allocation -const StringVoidMap = struct { +pub const StringVoidMap = struct { allocator: Allocator, map: bun.StringHashMapUnmanaged(void) = bun.StringHashMapUnmanaged(void){}, @@ -2980,7 +2969,14 @@ pub const Parser = struct { // Which makes sense. // June 4: "Parsing took: 18028000" // June 4: "Rest of this took: 8003000" - _ = try p.parseStmtsUpTo(js_lexer.T.t_end_of_file, &opts); + _ = p.parseStmtsUpTo(js_lexer.T.t_end_of_file, &opts) catch |err| { + if (err == error.StackOverflow) { + // The lexer location won't be totally accurate, but it's kind of helpful. + try p.log.addError(p.source, p.lexer.loc(), "Maximum call stack size exceeded"); + return; + } + return err; + }; // if (comptime ParserType.parser_features.typescript) { @@ -3255,7 +3251,18 @@ pub const Parser = struct { // Which makes sense. // June 4: "Parsing took: 18028000" // June 4: "Rest of this took: 8003000" - const stmts = try p.parseStmtsUpTo(js_lexer.T.t_end_of_file, &opts); + const stmts = p.parseStmtsUpTo(js_lexer.T.t_end_of_file, &opts) catch |err| { + parse_tracer.end(); + if (err == error.StackOverflow) { + // The lexer location won't be totally accurate, but it's kind of helpful. + try p.log.addError(p.source, p.lexer.loc(), "Maximum call stack size exceeded"); + + // Return a SyntaxError so that we reuse existing code for handling erorrs. + return error.SyntaxError; + } + + return err; + }; parse_tracer.end(); @@ -4812,6 +4819,8 @@ fn NewParser_( /// Used by commonjs_at_runtime has_commonjs_export_names: bool = false, + stack_check: bun.StackCheck, + /// When this flag is enabled, we attempt to fold all expressions that /// TypeScript would consider to be "constant expressions". This flag is /// enabled inside each enum body block since TypeScript requires numeric @@ -9495,6 +9504,10 @@ fn NewParser_( } fn parseStmt(p: *P, opts: *ParseStatementOptions) anyerror!Stmt { + if (!p.stack_check.isSafeToRecurse()) { + try bun.throwStackOverflow(); + } + const loc = p.lexer.loc(); switch (p.lexer.token) { @@ -13035,7 +13048,11 @@ fn NewParser_( return try p.parseExprCommon(level, null, flags); } - pub fn parseExprCommon(p: *P, level: Level, errors: ?*DeferredErrors, flags: Expr.EFlags) anyerror!Expr { + fn parseExprCommon(p: *P, level: Level, errors: ?*DeferredErrors, flags: Expr.EFlags) anyerror!Expr { + if (!p.stack_check.isSafeToRecurse()) { + try bun.throwStackOverflow(); + } + const had_pure_comment_before = p.lexer.has_pure_comment_before and !p.options.ignore_dce_annotations; var expr = try p.parsePrefix(level, errors, flags); @@ -23717,6 +23734,7 @@ fn NewParser_( .named_imports = undefined, .named_exports = .{}, .log = log, + .stack_check = bun.StackCheck.init(), .allocator = allocator, .options = opts, .then_catch_chain = ThenCatchChain{ .next_target = nullExprData }, diff --git a/src/main.zig b/src/main.zig index 9c4df6072f75e2..d3b73b7ee552c5 100644 --- a/src/main.zig +++ b/src/main.zig @@ -44,7 +44,7 @@ pub fn main() void { if (Environment.isX64 and Environment.enableSIMD and Environment.isPosix) { bun_warn_avx_missing(@import("./cli/upgrade_command.zig").Version.Bun__githubBaselineURL.ptr); } - + bun.StackCheck.configureThread(); bun.CLI.Cli.start(bun.default_allocator); bun.Global.exit(0); } diff --git a/src/output.zig b/src/output.zig index ec0b60ac2101b4..29fb3019d2b925 100644 --- a/src/output.zig +++ b/src/output.zig @@ -88,6 +88,7 @@ pub const Source = struct { if (source_set) return; bun.debugAssert(stdout_stream_set); source = Source.init(stdout_stream, stderr_stream); + bun.StackCheck.configureThread(); } pub fn configureNamedThread(name: StringTypes.stringZ) void { diff --git a/src/patch.zig b/src/patch.zig index 55b5780a3bbc02..363184f47e282d 100644 --- a/src/patch.zig +++ b/src/patch.zig @@ -915,7 +915,7 @@ const PatchLinesParser = struct { fn parseHunkHeaderLineImpl(text_: []const u8) ParseErr!struct { line_nr: u32, line_count: u32, rest: []const u8 } { var text = text_; const DIGITS = brk: { - var set = std.bit_set.IntegerBitSet(256).initEmpty(); + var set = bun.bit_set.IntegerBitSet(256).initEmpty(); for ('0'..'9' + 1) |c| set.set(c); break :brk set; }; @@ -1026,8 +1026,8 @@ const PatchLinesParser = struct { const delimiter_start = std.mem.indexOf(u8, line, "..") orelse return null; - const VALID_CHARS: std.bit_set.IntegerBitSet(256) = comptime brk: { - var bitset = std.bit_set.IntegerBitSet(256).initEmpty(); + const VALID_CHARS: bun.bit_set.IntegerBitSet(256) = comptime brk: { + var bitset = bun.bit_set.IntegerBitSet(256).initEmpty(); // TODO: the regex uses \w which is [a-zA-Z0-9_] for ('0'..'9' + 1) |c| bitset.set(c); for ('a'..'z' + 1) |c| bitset.set(c); diff --git a/src/pool.zig b/src/pool.zig index 7d994c752f1c69..30e5d3e31facab 100644 --- a/src/pool.zig +++ b/src/pool.zig @@ -233,5 +233,21 @@ pub fn ObjectPool( data().list = LinkedList{ .first = node }; data().loaded = true; } + + pub fn deleteAll() void { + var dat = data(); + if (!dat.loaded) { + return; + } + dat.loaded = false; + dat.count = 0; + var next = dat.list.first; + dat.list.first = null; + while (next) |node| { + next = node.next; + if (std.meta.hasFn(Type, "deinit")) node.data.deinit(); + node.allocator.destroy(node); + } + } }; } diff --git a/src/shell/interpreter.zig b/src/shell/interpreter.zig index 76b94c04d08db4..58a3a915f786d8 100644 --- a/src/shell/interpreter.zig +++ b/src/shell/interpreter.zig @@ -1323,8 +1323,10 @@ pub const Interpreter = struct { break :brk export_env; }; - var pathbuf: bun.PathBuffer = undefined; - const cwd: [:0]const u8 = switch (Syscall.getcwdZ(&pathbuf)) { + // Avoid the large stack allocation on Windows. + const pathbuf = bun.default_allocator.create(bun.PathBuffer) catch bun.outOfMemory(); + defer bun.default_allocator.destroy(pathbuf); + const cwd: [:0]const u8 = switch (Syscall.getcwdZ(pathbuf)) { .result => |cwd| cwd, .err => |err| { return .{ .err = .{ .sys = err.toSystemError() } }; @@ -4883,8 +4885,9 @@ pub const Interpreter = struct { return; } - var path_buf: bun.PathBuffer = undefined; - const resolved = which(&path_buf, spawn_args.PATH, spawn_args.cwd, first_arg_real) orelse blk: { + const path_buf = bun.PathBufferPool.get(); + defer bun.PathBufferPool.put(path_buf); + const resolved = which(path_buf, spawn_args.PATH, spawn_args.cwd, first_arg_real) orelse blk: { if (bun.strings.eqlComptime(first_arg_real, "bun") or bun.strings.eqlComptime(first_arg_real, "bun-debug")) blk2: { break :blk bun.selfExePath() catch break :blk2; } @@ -7158,12 +7161,13 @@ pub const Interpreter = struct { } if (this.bltn.stdout.needsIO() == null) { - var path_buf: bun.PathBuffer = undefined; + const path_buf = bun.PathBufferPool.get(); + defer bun.PathBufferPool.put(path_buf); const PATH = this.bltn.parentCmd().base.shell.export_env.get(EnvStr.initSlice("PATH")) orelse EnvStr.initSlice(""); var had_not_found = false; for (args) |arg_raw| { const arg = arg_raw[0..std.mem.len(arg_raw)]; - const resolved = which(&path_buf, PATH.slice(), this.bltn.parentCmd().base.shell.cwdZ(), arg) orelse { + const resolved = which(path_buf, PATH.slice(), this.bltn.parentCmd().base.shell.cwdZ(), arg) orelse { had_not_found = true; const buf = this.bltn.fmtErrorArena(.which, "{s} not found\n", .{arg}); _ = this.bltn.writeNoIO(.stdout, buf); @@ -7198,10 +7202,11 @@ pub const Interpreter = struct { const arg_raw = multiargs.args_slice[multiargs.arg_idx]; const arg = arg_raw[0..std.mem.len(arg_raw)]; - var path_buf: bun.PathBuffer = undefined; + const path_buf = bun.PathBufferPool.get(); + defer bun.PathBufferPool.put(path_buf); const PATH = this.bltn.parentCmd().base.shell.export_env.get(EnvStr.initSlice("PATH")) orelse EnvStr.initSlice(""); - const resolved = which(&path_buf, PATH.slice(), this.bltn.parentCmd().base.shell.cwdZ(), arg) orelse { + const resolved = which(path_buf, PATH.slice(), this.bltn.parentCmd().base.shell.cwdZ(), arg) orelse { multiargs.had_not_found = true; if (this.bltn.stdout.needsIO()) |safeguard| { multiargs.state = .waiting_write; diff --git a/src/shell/shell.zig b/src/shell/shell.zig index cd63bf42015a91..ae35c27140dda4 100644 --- a/src/shell/shell.zig +++ b/src/shell/shell.zig @@ -3987,8 +3987,8 @@ pub const ShellSrcBuilder = struct { /// Characters that need to escaped const SPECIAL_CHARS = [_]u8{ '~', '[', ']', '#', ';', '\n', '*', '{', ',', '}', '`', '$', '=', '(', ')', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '|', '>', '<', '&', '\'', '"', ' ', '\\' }; -const SPECIAL_CHARS_TABLE: std.bit_set.IntegerBitSet(256) = brk: { - var table = std.bit_set.IntegerBitSet(256).initEmpty(); +const SPECIAL_CHARS_TABLE: bun.bit_set.IntegerBitSet(256) = brk: { + var table = bun.bit_set.IntegerBitSet(256).initEmpty(); for (SPECIAL_CHARS) |c| { table.set(c); } diff --git a/src/string.zig b/src/string.zig index e4497381d1583e..30bc054a53465a 100644 --- a/src/string.zig +++ b/src/string.zig @@ -197,6 +197,14 @@ pub const WTFStringImplStruct = extern struct { return this.is8Bit() and bun.strings.isAllASCII(this.latin1Slice()); } + pub fn utf16ByteLength(this: WTFStringImpl) usize { + if (this.is8Bit()) { + return this.length() * 2; + } else { + return this.length(); + } + } + pub fn utf8ByteLength(this: WTFStringImpl) usize { if (this.is8Bit()) { const input = this.latin1Slice(); @@ -207,11 +215,6 @@ pub const WTFStringImplStruct = extern struct { } } - pub fn utf16ByteLength(this: WTFStringImpl) usize { - // All latin1 characters fit in a single UTF-16 code unit. - return this.length() * 2; - } - pub fn latin1ByteLength(this: WTFStringImpl) usize { // Not all UTF-16 characters fit are representable in latin1. // Those get truncated? diff --git a/src/string_immutable.zig b/src/string_immutable.zig index 2517480e98057f..ab1d7964908809 100644 --- a/src/string_immutable.zig +++ b/src/string_immutable.zig @@ -1949,9 +1949,10 @@ pub fn toWPathNormalizeAutoExtend(wbuf: []u16, utf8: []const u8) [:0]const u16 { } pub fn toWPathNormalized(wbuf: []u16, utf8: []const u8) [:0]const u16 { - var renormalized: bun.PathBuffer = undefined; + const renormalized = bun.PathBufferPool.get(); + defer bun.PathBufferPool.put(renormalized); - var path_to_use = normalizeSlashesOnly(&renormalized, utf8, '\\'); + var path_to_use = normalizeSlashesOnly(renormalized, utf8, '\\'); // is there a trailing slash? Let's remove it before converting to UTF-16 if (path_to_use.len > 3 and bun.path.isSepAny(path_to_use[path_to_use.len - 1])) { @@ -1961,9 +1962,10 @@ pub fn toWPathNormalized(wbuf: []u16, utf8: []const u8) [:0]const u16 { return toWPath(wbuf, path_to_use); } pub fn toPathNormalized(buf: []u8, utf8: []const u8) [:0]const u8 { - var renormalized: bun.PathBuffer = undefined; + const renormalized = bun.PathBufferPool.get(); + defer bun.PathBufferPool.put(renormalized); - var path_to_use = normalizeSlashesOnly(&renormalized, utf8, '\\'); + var path_to_use = normalizeSlashesOnly(renormalized, utf8, '\\'); // is there a trailing slash? Let's remove it before converting to UTF-16 if (path_to_use.len > 3 and bun.path.isSepAny(path_to_use[path_to_use.len - 1])) { @@ -1991,17 +1993,20 @@ pub fn normalizeSlashesOnly(buf: []u8, utf8: []const u8, comptime desired_slash: } pub fn toWDirNormalized(wbuf: []u16, utf8: []const u8) [:0]const u16 { - var renormalized: bun.PathBuffer = undefined; + var renormalized: ?*bun.PathBuffer = null; + defer if (renormalized) |r| bun.PathBufferPool.put(r); + var path_to_use = utf8; if (bun.strings.containsChar(utf8, '/')) { - @memcpy(renormalized[0..utf8.len], utf8); - for (renormalized[0..utf8.len]) |*c| { + renormalized = bun.PathBufferPool.get(); + @memcpy(renormalized.?[0..utf8.len], utf8); + for (renormalized.?[0..utf8.len]) |*c| { if (c.* == '/') { c.* = '\\'; } } - path_to_use = renormalized[0..utf8.len]; + path_to_use = renormalized.?[0..utf8.len]; } return toWDirPath(wbuf, path_to_use); diff --git a/src/sys.zig b/src/sys.zig index 179ed41fecf670..33e98c14de5fa3 100644 --- a/src/sys.zig +++ b/src/sys.zig @@ -466,8 +466,9 @@ pub fn getcwdZ(buf: *bun.PathBuffer) Maybe([:0]const u8) { buf[0] = 0; if (comptime Environment.isWindows) { - var wbuf: bun.WPathBuffer = undefined; - const len: windows.DWORD = kernel32.GetCurrentDirectoryW(wbuf.len, &wbuf); + var wbuf = bun.WPathBufferPool.get(); + defer bun.WPathBufferPool.put(wbuf); + const len: windows.DWORD = kernel32.GetCurrentDirectoryW(wbuf.len, wbuf); if (Result.errnoSys(len, .getcwd)) |err| return err; return Result{ .result = bun.strings.fromWPath(buf, wbuf[0..len]) }; } @@ -555,8 +556,9 @@ pub fn chdir(destination: anytype) Maybe(void) { return chdirOSPath(@as(bun.OSPathSliceZ, destination)); } - var wbuf: bun.WPathBuffer = undefined; - return chdirOSPath(bun.strings.toWDirPath(&wbuf, destination)); + const wbuf = bun.WPathBufferPool.get(); + defer bun.WPathBufferPool.put(wbuf); + return chdirOSPath(bun.strings.toWDirPath(wbuf, destination)); } return Maybe(void).todo(); @@ -626,8 +628,9 @@ pub fn fstat(fd: bun.FileDescriptor) Maybe(bun.Stat) { } pub fn mkdiratA(dir_fd: bun.FileDescriptor, file_path: []const u8) Maybe(void) { - var buf: bun.WPathBuffer = undefined; - return mkdiratW(dir_fd, bun.strings.toWPathNormalized(&buf, file_path)); + const buf = bun.WPathBufferPool.get(); + defer bun.WPathBufferPool.put(buf); + return mkdiratW(dir_fd, bun.strings.toWPathNormalized(buf, file_path)); } pub fn mkdiratZ(dir_fd: bun.FileDescriptor, file_path: [*:0]const u8, mode: mode_t) Maybe(void) { @@ -688,9 +691,10 @@ pub fn mkdir(file_path: [:0]const u8, flags: bun.Mode) Maybe(void) { .linux => Maybe(void).errnoSysP(syscall.mkdir(file_path, flags), .mkdir, file_path) orelse Maybe(void).success, .windows => { - var wbuf: bun.WPathBuffer = undefined; + const wbuf = bun.WPathBufferPool.get(); + defer bun.WPathBufferPool.put(wbuf); return Maybe(void).errnoSysP( - kernel32.CreateDirectoryW(bun.strings.toWPath(&wbuf, file_path).ptr, null), + kernel32.CreateDirectoryW(bun.strings.toWPath(wbuf, file_path).ptr, null), .mkdir, file_path, ) orelse Maybe(void).success; @@ -720,8 +724,9 @@ pub fn mkdirA(file_path: []const u8, flags: bun.Mode) Maybe(void) { } if (comptime Environment.isWindows) { - var wbuf: bun.WPathBuffer = undefined; - const wpath = bun.strings.toWPath(&wbuf, file_path); + const wbuf = bun.WPathBufferPool.get(); + defer bun.WPathBufferPool.put(wbuf); + const wpath = bun.strings.toWPath(wbuf, file_path); assertIsValidWindowsPath(u16, wpath); return Maybe(void).errnoSysP( kernel32.CreateDirectoryW(wpath.ptr, null), @@ -792,8 +797,9 @@ pub fn normalizePathWindows( if (comptime T != u8 and T != u16) { @compileError("normalizePathWindows only supports u8 and u16 character types"); } - var wbuf: if (T == u16) void else bun.WPathBuffer = undefined; - var path = if (T == u16) path_ else bun.strings.convertUTF8toUTF16InBuffer(&wbuf, path_); + const wbuf = if (T != u16) bun.WPathBufferPool.get() else {}; + defer if (T != u16) bun.WPathBufferPool.put(wbuf); + var path = if (T == u16) path_ else bun.strings.convertUTF8toUTF16InBuffer(wbuf, path_); if (std.fs.path.isAbsoluteWindowsWTF16(path)) { // handle the special "nul" device @@ -845,7 +851,8 @@ pub fn normalizePathWindows( path = path[2..]; } - var buf1: bun.WPathBuffer = undefined; + const buf1 = bun.WPathBufferPool.get(); + defer bun.WPathBufferPool.put(buf1); @memcpy(buf1[0..base_path.len], base_path); buf1[base_path.len] = '\\'; @memcpy(buf1[base_path.len + 1 .. base_path.len + 1 + path.len], path); @@ -964,9 +971,10 @@ fn openDirAtWindowsT( path: []const T, options: WindowsOpenDirOptions, ) Maybe(bun.FileDescriptor) { - var wbuf: bun.WPathBuffer = undefined; + const wbuf = bun.WPathBufferPool.get(); + defer bun.WPathBufferPool.put(wbuf); - const norm = switch (normalizePathWindows(T, dirFd, path, &wbuf)) { + const norm = switch (normalizePathWindows(T, dirFd, path, wbuf)) { .err => |err| return .{ .err = err }, .result => |norm| norm, }; @@ -1157,9 +1165,10 @@ pub fn openFileAtWindowsT( disposition: w.ULONG, options: w.ULONG, ) Maybe(bun.FileDescriptor) { - var wbuf: bun.WPathBuffer = undefined; + const wbuf = bun.WPathBufferPool.get(); + defer bun.WPathBufferPool.put(wbuf); - const norm = switch (normalizePathWindows(T, dirFd, path, &wbuf)) { + const norm = switch (normalizePathWindows(T, dirFd, path, wbuf)) { .err => |err| return .{ .err = err }, .result => |norm| norm, }; @@ -1974,14 +1983,18 @@ pub fn renameat2(from_dir: bun.FileDescriptor, from: [:0]const u8, to_dir: bun.F pub fn renameat(from_dir: bun.FileDescriptor, from: [:0]const u8, to_dir: bun.FileDescriptor, to: [:0]const u8) Maybe(void) { if (Environment.isWindows) { - var w_buf_from: bun.WPathBuffer = undefined; - var w_buf_to: bun.WPathBuffer = undefined; + const w_buf_from = bun.WPathBufferPool.get(); + const w_buf_to = bun.WPathBufferPool.get(); + defer { + bun.WPathBufferPool.put(w_buf_from); + bun.WPathBufferPool.put(w_buf_to); + } const rc = bun.C.renameAtW( from_dir, - bun.strings.toNTPath(&w_buf_from, from), + bun.strings.toNTPath(w_buf_from, from), to_dir, - bun.strings.toNTPath(&w_buf_to, to), + bun.strings.toNTPath(w_buf_to, to), true, ); @@ -2053,10 +2066,14 @@ pub fn symlinkOrJunction(dest: [:0]const u8, target: [:0]const u8) Maybe(void) { if (comptime !Environment.isWindows) @compileError("symlinkOrJunction is windows only"); if (!WindowsSymlinkOptions.has_failed_to_create_symlink) { - var sym16: bun.WPathBuffer = undefined; - var target16: bun.WPathBuffer = undefined; - const sym_path = bun.strings.toWPathNormalizeAutoExtend(&sym16, dest); - const target_path = bun.strings.toWPathNormalizeAutoExtend(&target16, target); + const sym16 = bun.WPathBufferPool.get(); + const target16 = bun.WPathBufferPool.get(); + defer { + bun.WPathBufferPool.put(sym16); + bun.WPathBufferPool.put(target16); + } + const sym_path = bun.strings.toWPathNormalizeAutoExtend(sym16, dest); + const target_path = bun.strings.toWPathNormalizeAutoExtend(target16, target); switch (symlinkW(sym_path, target_path, .{ .directory = true })) { .result => { return Maybe(void).success; @@ -2163,8 +2180,9 @@ pub fn unlinkW(from: [:0]const u16) Maybe(void) { pub fn unlink(from: [:0]const u8) Maybe(void) { if (comptime Environment.isWindows) { - var w_buf: bun.WPathBuffer = undefined; - return unlinkW(bun.strings.toNTPath(&w_buf, from)); + const w_buf = bun.WPathBufferPool.get(); + defer bun.WPathBufferPool.put(w_buf); + return unlinkW(bun.strings.toNTPath(w_buf, from)); } while (true) { @@ -2185,8 +2203,9 @@ pub fn rmdirat(dirfd: bun.FileDescriptor, to: anytype) Maybe(void) { pub fn unlinkatWithFlags(dirfd: bun.FileDescriptor, to: anytype, flags: c_uint) Maybe(void) { if (Environment.isWindows) { if (comptime std.meta.Elem(@TypeOf(to)) == u8) { - var w_buf: bun.WPathBuffer = undefined; - return unlinkatWithFlags(dirfd, bun.strings.toNTPath(&w_buf, bun.span(to)), flags); + const w_buf = bun.WPathBufferPool.get(); + defer bun.WPathBufferPool.put(w_buf); + return unlinkatWithFlags(dirfd, bun.strings.toNTPath(w_buf, bun.span(to)), flags); } return bun.windows.DeleteFileBun(to, .{ @@ -2599,8 +2618,9 @@ pub fn getFileAttributes(path: anytype) ?WindowsFileAttributes { const attributes: WindowsFileAttributes = @bitCast(dword); return attributes; } else { - var wbuf: bun.WPathBuffer = undefined; - const path_to_use = bun.strings.toWPath(&wbuf, path); + const wbuf = bun.WPathBufferPool.get(); + defer bun.WPathBufferPool.put(wbuf); + const path_to_use = bun.strings.toWPath(wbuf, path); return getFileAttributes(path_to_use); } } @@ -2678,8 +2698,9 @@ pub fn faccessat(dir_: anytype, subpath: anytype) JSC.Maybe(bool) { pub fn directoryExistsAt(dir_: anytype, subpath: anytype) JSC.Maybe(bool) { const dir_fd = bun.toFD(dir_); if (comptime Environment.isWindows) { - var wbuf: bun.WPathBuffer = undefined; - const path = bun.strings.toNTPath(&wbuf, subpath); + const wbuf = bun.WPathBufferPool.get(); + defer bun.WPathBufferPool.put(wbuf); + const path = bun.strings.toNTPath(wbuf, subpath); const path_len_bytes: u16 = @truncate(path.len * 2); var nt_name = w.UNICODE_STRING{ .Length = path_len_bytes, @@ -2745,8 +2766,9 @@ pub fn existsAt(fd: bun.FileDescriptor, subpath: [:0]const u8) bool { } if (comptime Environment.isWindows) { - var wbuf: bun.WPathBuffer = undefined; - const path = bun.strings.toNTPath(&wbuf, subpath); + const wbuf = bun.WPathBufferPool.get(); + defer bun.WPathBufferPool.put(wbuf); + const path = bun.strings.toNTPath(wbuf, subpath); const path_len_bytes: u16 = @truncate(path.len * 2); var nt_name = w.UNICODE_STRING{ .Length = path_len_bytes, diff --git a/src/url.zig b/src/url.zig index 3e7260aa8ac811..5dafcac0c7a50f 100644 --- a/src/url.zig +++ b/src/url.zig @@ -488,7 +488,7 @@ pub const QueryStringMap = struct { pub const Iterator = struct { // Assume no query string param map will exceed 2048 keys // Browsers typically limit URL lengths to around 64k - const VisitedMap = std.bit_set.ArrayBitSet(usize, 2048); + const VisitedMap = bun.bit_set.ArrayBitSet(usize, 2048); i: usize = 0, map: *const QueryStringMap, diff --git a/src/which.zig b/src/which.zig index 093b141c4f6ced..0470af9d61ea71 100644 --- a/src/which.zig +++ b/src/which.zig @@ -20,8 +20,9 @@ pub fn which(buf: *bun.PathBuffer, path: []const u8, cwd: []const u8, bin: []con bun.Output.scoped(.which, true)("path={s} cwd={s} bin={s}", .{ path, cwd, bin }); if (bun.Environment.os == .windows) { - var convert_buf: bun.WPathBuffer = undefined; - const result = whichWin(&convert_buf, path, cwd, bin) orelse return null; + const convert_buf = bun.WPathBufferPool.get(); + defer bun.WPathBufferPool.put(convert_buf); + const result = whichWin(convert_buf, path, cwd, bin) orelse return null; const result_converted = bun.strings.convertUTF16toUTF8InBuffer(buf, result) catch unreachable; buf[result_converted.len] = 0; bun.assert(result_converted.ptr == buf.ptr); @@ -132,13 +133,14 @@ fn searchBinInPath(buf: *bun.WPathBuffer, path_buf: *bun.PathBuffer, path: []con /// It is similar to Get-Command in powershell. pub fn whichWin(buf: *bun.WPathBuffer, path: []const u8, cwd: []const u8, bin: []const u8) ?[:0]const u16 { if (bin.len == 0) return null; - var path_buf: bun.PathBuffer = undefined; + const path_buf = bun.PathBufferPool.get(); + defer bun.PathBufferPool.put(path_buf); const check_windows_extensions = !endsWithExtension(bin); // handle absolute paths if (std.fs.path.isAbsolute(bin)) { - const normalized_bin = PosixToWinNormalizer.resolveCWDWithExternalBuf(&path_buf, bin) catch return null; + const normalized_bin = PosixToWinNormalizer.resolveCWDWithExternalBuf(path_buf, bin) catch return null; const bin_utf16 = bun.strings.convertUTF8toUTF16InBuffer(buf, normalized_bin); buf[bin_utf16.len] = 0; return searchBin(buf, bin_utf16.len, check_windows_extensions); @@ -148,7 +150,7 @@ pub fn whichWin(buf: *bun.WPathBuffer, path: []const u8, cwd: []const u8, bin: [ if (bun.strings.containsChar(bin, '/') or bun.strings.containsChar(bin, '\\')) { if (searchBinInPath( buf, - &path_buf, + path_buf, cwd, bun.strings.withoutPrefixComptime(bin, "./"), check_windows_extensions, @@ -163,7 +165,7 @@ pub fn whichWin(buf: *bun.WPathBuffer, path: []const u8, cwd: []const u8, bin: [ // iterate over system path delimiter var path_iter = std.mem.tokenizeScalar(u8, path, ';'); while (path_iter.next()) |segment_part| { - if (searchBinInPath(buf, &path_buf, segment_part, bin, check_windows_extensions)) |bin_path| { + if (searchBinInPath(buf, path_buf, segment_part, bin, check_windows_extensions)) |bin_path| { return bin_path; } } diff --git a/test/bundler/transpiler/fixtures/lots-of-for-loop.js b/test/bundler/transpiler/fixtures/lots-of-for-loop.js new file mode 100644 index 00000000000000..096ff28911de89 --- /dev/null +++ b/test/bundler/transpiler/fixtures/lots-of-for-loop.js @@ -0,0 +1,713 @@ +let counter = 0; +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) + +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) + +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) + +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) + +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) + +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) + +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) + +for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) counter++; +console.log(counter); \ No newline at end of file diff --git a/test/bundler/transpiler/transpiler.test.js b/test/bundler/transpiler/transpiler.test.js index 8757b968ae5e8a..0b0103848fe0f1 100644 --- a/test/bundler/transpiler/transpiler.test.js +++ b/test/bundler/transpiler/transpiler.test.js @@ -3441,3 +3441,19 @@ it("does not crash with 9 comments and typescript type skipping", () => { expect(stdout.toString()).toContain("success!"); expect(exitCode).toBe(0); }); + +it("runtime transpiler stack overflows", async () => { + expect(async () => await import("./fixtures/lots-of-for-loop.js")).toThrow(`Maximum call stack size exceeded`); +}); + +it("Bun.Transpiler.transformSync stack overflows", async () => { + const code = await Bun.file(join(import.meta.dir, "fixtures", "lots-of-for-loop.js")).text(); + const transpiler = new Bun.Transpiler(); + expect(() => transpiler.transformSync(code)).toThrow(`Maximum call stack size exceeded`); +}); + +it("Bun.Transpiler.transform stack overflows", async () => { + const code = await Bun.file(join(import.meta.dir, "fixtures", "lots-of-for-loop.js")).text(); + const transpiler = new Bun.Transpiler(); + expect(async () => await transpiler.transform(code)).toThrow(`Maximum call stack size exceeded`); +}); diff --git a/test/js/bun/test/stack.test.ts b/test/js/bun/test/stack.test.ts index ac3fde49c0ca79..dd32267d49091b 100644 --- a/test/js/bun/test/stack.test.ts +++ b/test/js/bun/test/stack.test.ts @@ -93,11 +93,16 @@ test("throwing inside an error suppresses the error and prints the stack", async const { stderr, exitCode } = result; - expect(stderr.toString().trim()).toStartWith( - `error: My custom error message - at http://example.com/test.js:42 - `.trim(), - ); + expect(stderr.toString().trim().split("\n").slice(0, -1).join("\n").trim()).toMatchInlineSnapshot(` +"error: My custom error message +{ + message: "My custom error message", + name: [Getter], + line: 42, + sourceURL: "http://example.com/test.js", +} + at http://example.com/test.js:42" +`); expect(exitCode).toBe(1); }); @@ -108,8 +113,10 @@ test("throwing inside an error suppresses the error and continues printing prope const { stderr, exitCode } = result; - expect(stderr.toString().trim()).toStartWith( - 'ENOENT: No such file or directory\n errno: -2\n syscall: "open"\n path: "this-file-path-is-bad"'.trim(), - ); + expect(stderr.toString().trim()).toStartWith(`ENOENT: No such file or directory + path: "this-file-path-is-bad", + syscall: "open", + errno: -2, +`); expect(exitCode).toBe(1); }); diff --git a/test/js/bun/util/error-gc-test.test.js b/test/js/bun/util/error-gc-test.test.js index da1cfecb02cf82..19bb1210b9227e 100644 --- a/test/js/bun/util/error-gc-test.test.js +++ b/test/js/bun/util/error-gc-test.test.js @@ -50,9 +50,12 @@ test("error gc test #3", () => { // - The test failure message gets a non-sensical error test("error gc test #4", () => { const tmp = tmpdirSync(); - for (let i = 0; i < 1000; i++) { + const base = Buffer.from(join(tmp, "does", "not", "exist").repeat(10)); + + function iterate() { // Use a long-enough string for it to be obvious if we leak memory - let path = join(tmp, join("does", "not", "exist").repeat(10)); + // Use .toString() on the Buffer to ensure we clone the string every time. + let path = base.toString(); try { readFileSync(path); throw new Error("unreachable"); @@ -61,8 +64,14 @@ test("error gc test #4", () => { throw e; } - const inspected = Bun.inspect(e); + path = path.replaceAll("\\", "/"); + if (e.path) { + e.path = e.path.replaceAll("\\", "/"); + } + + let inspected = Bun.inspect(e); Bun.gc(true); + inspected = inspected.replaceAll("\\", "/"); // Deliberately avoid using .toContain() directly to avoid // BunString shenanigins. @@ -80,4 +89,8 @@ test("error gc test #4", () => { Bun.gc(true); } } + + for (let i = 0; i < 1000; i++) { + iterate(); + } }); diff --git a/test/js/bun/util/reportError.test.ts b/test/js/bun/util/reportError.test.ts index 14f0466af3c660..f1e6008991406a 100644 --- a/test/js/bun/util/reportError.test.ts +++ b/test/js/bun/util/reportError.test.ts @@ -18,5 +18,49 @@ test("reportError", () => { // remove bun version from output output = output.split("\n").slice(0, -2).join("\n"); - expect(output).toMatchSnapshot(); + expect(output.replaceAll("\\", "/").replaceAll("/reportError.ts", "[file]")).toMatchInlineSnapshot( + ` +"1 | reportError(new Error("reportError Test!")); + ^ +error: reportError Test! + at [file]:1:13 +error: true +true +error: false +false +error: null +null +error: 123 +123 +error: Infinity +Infinity +error: NaN +NaN +error: NaN +NaN +error + +error +Uint8Array(1) [ 0 ] +error +Uint8Array(0) [ ] +error +ArrayBuffer(0) [ ] +error +ArrayBuffer(1) [ 0 ] +error: string +string +error +[] +error +[ 123, null ] +error +{} +error +[ + {} +] +" +`, + ); }); diff --git a/test/js/node/util/bun-inspect.test.ts b/test/js/node/util/bun-inspect.test.ts index 57151a7b5b5b1c..115ad1c500a885 100644 --- a/test/js/node/util/bun-inspect.test.ts +++ b/test/js/node/util/bun-inspect.test.ts @@ -47,18 +47,46 @@ describe("Bun.inspect", () => { expect(() => Bun.inspect({}, { depth: -1 })).toThrow(); expect(() => Bun.inspect({}, { depth: -13210 })).toThrow(); }); - it("depth = Infinity works", () => { - function createRecursiveObject(n: number): any { - if (n === 0) return { hi: true }; - return { a: createRecursiveObject(n - 1) }; + for (let base of [new Error("hi"), { a: "hi" }]) { + it(`depth = Infinity works for ${base.constructor.name}`, () => { + function createRecursiveObject(n: number): any { + if (n === 0) { + return { a: base }; + } + return { a: createRecursiveObject(n - 1) }; + } + + const obj = createRecursiveObject(512); + expect(Bun.inspect(obj, { depth: Infinity })).toContain("hi"); + // this gets converted to u16, which if just truncating, will turn into 0 + expect(Bun.inspect(obj, { depth: 0x0fff0000 })).toContain("hi"); + }); + } + + it("stack overflow is thrown when it should be for objects", () => { + var object = { a: { b: { c: { d: 1 } } } }; + for (let i = 0; i < 16 * 1024; i++) { + object = { a: object }; } - const obj = createRecursiveObject(1000); + expect(() => Bun.inspect(object, { depth: Infinity })).toThrowErrorMatchingInlineSnapshot( + `"Maximum call stack size exceeded."`, + ); + }); + + it("stack overflow is thrown when it should be for Error", () => { + var object = { a: { b: { c: { d: 1 } } } }; + for (let i = 0; i < 16 * 1024; i++) { + const err = new Error("hello"); + err.object = object; + object = err; + } - expect(Bun.inspect(obj, { depth: Infinity })).toContain("hi"); - // this gets converted to u16, which if just truncating, will turn into 0 - expect(Bun.inspect(obj, { depth: 0x0fff0000 })).toContain("hi"); + expect(() => Bun.inspect(object, { depth: Infinity })).toThrowErrorMatchingInlineSnapshot( + `"Maximum call stack size exceeded."`, + ); }); + it("depth = 0", () => { expect(Bun.inspect({ a: { b: { c: { d: 1 } } } }, { depth: 0 })).toEqual("{\n a: [Object ...],\n}"); });