diff options
author | 2022-11-23 00:02:20 -0800 | |
---|---|---|
committer | 2022-11-23 00:02:20 -0800 | |
commit | ed72fa057bdcaf29843544c425a704c0586be1ec (patch) | |
tree | 7d499519092e215982e6d3503bdaa8386d03e35b | |
parent | b60095576e5c7855841ddc0343bfe09f070f661e (diff) | |
parent | ae3fcb5bd89a4ac908ba6d4cdb1be4e7c7f0ea81 (diff) | |
download | bun-ed72fa057bdcaf29843544c425a704c0586be1ec.tar.gz bun-ed72fa057bdcaf29843544c425a704c0586be1ec.tar.zst bun-ed72fa057bdcaf29843544c425a704c0586be1ec.zip |
Merge branch 'main' into jarred/wip-more-reliable
97 files changed, 7941 insertions, 4891 deletions
diff --git a/.vscode/launch.json b/.vscode/launch.json index bb6dc393d..b70542414 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -7,10 +7,10 @@ "name": "bun test", "program": "bun-debug", "args": ["wiptest", "${file}"], - "cwd": "${workspaceFolder}/test", + "cwd": "${workspaceFolder}/test/bun.js", "env": { - "FORCE_COLOR": "1" - // "BUN_DEBUG_ALL": "1" + "FORCE_COLOR": "1", + "BUN_GARBAGE_COLLECTOR_LEVEL": "2" }, "console": "internalConsole" }, @@ -22,8 +22,8 @@ "args": ["wiptest"], "cwd": "${workspaceFolder}/test", "env": { - "FORCE_COLOR": "1" - // "BUN_DEBUG_ALL": "1" + "FORCE_COLOR": "1", + "BUN_GARBAGE_COLLECTOR_LEVEL": "2" }, "console": "internalConsole" }, @@ -42,6 +42,18 @@ { "type": "lldb", "request": "launch", + "name": "bun run (hot)", + "program": "bun-debug", + "args": ["--hot", "${file}"], + "cwd": "${file}/../../", + "env": { + "FORCE_COLOR": "1" + }, + "console": "internalConsole" + }, + { + "type": "lldb", + "request": "launch", "name": "bun run", "program": "bun-debug", "args": ["check.tsx", "-c"], @@ -110,6 +122,15 @@ { "type": "lldb", "request": "launch", + "name": "Build zig unit test", + "program": "make", + "args": ["build-unit", "${file}"], + "cwd": "${workspaceFolder}", + "console": "internalConsole" + }, + { + "type": "lldb", + "request": "launch", "name": "Run zig unit test", "program": "${workspaceFolder}/zig-out/bin/test", "args": ["abc"], diff --git a/Dockerfile b/Dockerfile index 4cf3e48c3..bb2fbe62d 100644 --- a/Dockerfile +++ b/Dockerfile @@ -16,7 +16,7 @@ ARG WEBKIT_URL="https://github.com/oven-sh/WebKit/releases/download/$WEBKIT_TAG/ ARG ZIG_URL="https://github.com/oven-sh/zig/releases/download/$ZIG_TAG/zig-linux-$BUILDARCH.zip" ARG GIT_SHA="" -ARG BUN_BASE_VERSION=0.2 +ARG BUN_BASE_VERSION=0.3 FROM bitnami/minideb:bullseye as bun-base @@ -35,7 +35,7 @@ NATIVE_OR_OLD_MARCH = -march=westmere endif MIN_MACOS_VERSION ?= $(DEFAULT_MIN_MACOS_VERSION) -BUN_BASE_VERSION = 0.2 +BUN_BASE_VERSION = 0.3 AR= @@ -884,7 +884,7 @@ MIMALLOC_OVERRIDE_FLAG ?= bump: - expr 0.2.0 + 1 > build-id + expr 0.3.0 + 1 > build-id .PHONY: identifier-cache identifier-cache: @@ -1458,9 +1458,11 @@ wasm-return1: generate-classes: bun src/bun.js/scripts/generate-classes.ts $(ZIG) fmt src/bun.js/bindings/generated_classes.zig + clang-format -i src/bun.js/bindings/ZigGeneratedClasses.h src/bun.js/bindings/ZigGeneratedClasses.cpp generate-sink: bun src/bun.js/scripts/generate-jssink.js + clang-format -i src/bun.js/bindings/JSSink.cpp src/bun.js/bindings/JSSink.h $(WEBKIT_DIR)/Source/JavaScriptCore/create_hash_table src/bun.js/bindings/JSSink.cpp > src/bun.js/bindings/JSSinkLookupTable.h $(SED) -i -e 's/#include "Lookup.h"//' src/bun.js/bindings/JSSinkLookupTable.h $(SED) -i -e 's/namespace JSC {//' src/bun.js/bindings/JSSinkLookupTable.h @@ -1 +1 @@ -3
\ No newline at end of file +0
\ No newline at end of file diff --git a/packages/bun-types/bun.d.ts b/packages/bun-types/bun.d.ts index 252e50055..bab5f5810 100644 --- a/packages/bun-types/bun.d.ts +++ b/packages/bun-types/bun.d.ts @@ -1699,6 +1699,23 @@ declare module "bun" { /** Mock bun's segfault handler. You probably don't want to use this */ segfault(): void; + + /** + * Force the garbage collector to run extremely often, + * especially inside `bun:test`. + * + * - `0`: default, disable + * - `1`: asynchronously call the garbage collector more often + * - `2`: synchronously call the garbage collector more often. + * + * This is a global setting. It's useful for debugging seemingly random crashes. + * + * `BUN_GARBAGE_COLLECTOR_LEVEL` environment variable is also supported. + * + * @param level + * @returns The previous level + */ + gcAggressionLevel(level: 0 | 1 | 2): 0 | 1 | 2; } export const unsafe: unsafe; diff --git a/src/__global.zig b/src/__global.zig index eb2522139..280c74215 100644 --- a/src/__global.zig +++ b/src/__global.zig @@ -6,7 +6,7 @@ const use_mimalloc = @import("./global.zig").use_mimalloc; const StringTypes = @import("./string_types.zig"); const Mimalloc = @import("./global.zig").Mimalloc; -const BASE_VERSION = "0.2"; +const BASE_VERSION = "0.3"; pub const build_id = std.fmt.parseInt(u64, std.mem.trim(u8, @embedFile("../build-id"), "\n \r\t"), 10) catch unreachable; pub const package_json_version = if (Environment.isDebug) @@ -48,7 +48,7 @@ pub inline fn getStartTime() i128 { pub const version: @import("./install/semver.zig").Version = .{ .major = 0, - .minor = 2, + .minor = 3, .patch = build_id, }; @@ -167,3 +167,5 @@ pub export const Bun__userAgent: [*:0]const u8 = Global.user_agent; comptime { _ = Bun__userAgent; } + +const Mimalloc = @import("./global.zig").Mimalloc; diff --git a/src/allocators/mimalloc.zig b/src/allocators/mimalloc.zig index f671b4553..5d8d7f2e3 100644 --- a/src/allocators/mimalloc.zig +++ b/src/allocators/mimalloc.zig @@ -1,17 +1,3 @@ -const C = @import("std").zig.c_builtins; -const __attribute__ = C.__attribute__; -const _Nonnull = C._Nonnull; -const _Null_unspecified = C._Null_unspecified; -const _Nullable = C._Nullable; -const enum_mi_option_e = C.enum_mi_option_e; -const L = C.L; -const LL = C.LL; -const U = C.U; -const UL = C.UL; -const ULL = C.ULL; -pub const ptrdiff_t = c_long; -pub const wchar_t = c_int; -pub const max_align_t = c_longdouble; pub extern fn mi_malloc(size: usize) ?*anyopaque; pub extern fn mi_calloc(count: usize, size: usize) ?*anyopaque; pub extern fn mi_realloc(p: ?*anyopaque, newsize: usize) ?*anyopaque; @@ -30,7 +16,7 @@ pub extern fn mi_usable_size(p: ?*const anyopaque) usize; pub extern fn mi_good_size(size: usize) usize; pub const mi_deferred_free_fun = fn (bool, c_ulonglong, ?*anyopaque) callconv(.C) void; pub extern fn mi_register_deferred_free(deferred_free: ?mi_deferred_free_fun, arg: ?*anyopaque) void; -pub const mi_output_fun = fn ([*c]const u8, ?*anyopaque) callconv(.C) void; +pub const mi_output_fun = fn ([*:0]const u8, ?*anyopaque) callconv(.C) void; pub extern fn mi_register_output(out: ?mi_output_fun, arg: ?*anyopaque) void; pub const mi_error_fun = fn (c_int, ?*anyopaque) callconv(.C) void; pub extern fn mi_register_error(fun: ?mi_error_fun, arg: ?*anyopaque) void; @@ -44,61 +30,84 @@ pub extern fn mi_process_init() void; pub extern fn mi_thread_init() void; pub extern fn mi_thread_done() void; pub extern fn mi_thread_stats_print_out(out: ?mi_output_fun, arg: ?*anyopaque) void; -pub extern fn mi_process_info(elapsed_msecs: *usize, user_msecs: *usize, system_msecs: *usize, current_rss: *usize, peak_rss: *usize, current_commit: *usize, peak_commit: *usize, page_faults: *usize) void; +pub extern fn mi_process_info(elapsed_msecs: [*c]usize, user_msecs: [*c]usize, system_msecs: [*c]usize, current_rss: [*c]usize, peak_rss: [*c]usize, current_commit: [*c]usize, peak_commit: [*c]usize, page_faults: [*c]usize) void; pub extern fn mi_malloc_aligned(size: usize, alignment: usize) ?*anyopaque; -pub extern fn mi_malloc_aligned_at(size: usize, alignment: usize, offset: usize) ?[*]u8; +pub extern fn mi_malloc_aligned_at(size: usize, alignment: usize, offset: usize) ?*anyopaque; pub extern fn mi_zalloc_aligned(size: usize, alignment: usize) ?*anyopaque; pub extern fn mi_zalloc_aligned_at(size: usize, alignment: usize, offset: usize) ?*anyopaque; pub extern fn mi_calloc_aligned(count: usize, size: usize, alignment: usize) ?*anyopaque; pub extern fn mi_calloc_aligned_at(count: usize, size: usize, alignment: usize, offset: usize) ?*anyopaque; pub extern fn mi_realloc_aligned(p: ?*anyopaque, newsize: usize, alignment: usize) ?*anyopaque; pub extern fn mi_realloc_aligned_at(p: ?*anyopaque, newsize: usize, alignment: usize, offset: usize) ?*anyopaque; -pub const struct_mi_heap_s = opaque { - pub inline fn backing(_: anytype) *mi_heap_t { - return mi_heap_get_backing(); +pub const Heap = opaque { + pub fn new() ?*Heap { + return mi_heap_new(); + } + + pub fn delete(self: *Heap) void { + mi_heap_delete(self); + } + + pub fn malloc(self: *Heap, size: usize) ?*anyopaque { + return mi_heap_malloc(self, size); + } + + pub fn backing(_: *Heap) *Heap { + return mi_heap_get_default(); + } + + pub fn calloc(self: *Heap, count: usize, size: usize) ?*anyopaque { + return mi_heap_calloc(self, count, size); + } + + pub fn realloc(self: *Heap, p: ?*anyopaque, newsize: usize) ?*anyopaque { + return mi_heap_realloc(self, p, newsize); + } + + pub fn isOwned(self: *Heap, p: ?*anyopaque) bool { + return mi_heap_check_owned(self, p); } }; -pub const mi_heap_t = struct_mi_heap_s; -pub extern fn mi_heap_new() ?*mi_heap_t; -pub extern fn mi_heap_delete(heap: ?*mi_heap_t) void; -pub extern fn mi_heap_destroy(heap: ?*mi_heap_t) void; -pub extern fn mi_heap_set_default(heap: ?*mi_heap_t) ?*mi_heap_t; -pub extern fn mi_heap_get_default() *mi_heap_t; -pub extern fn mi_heap_get_backing() *mi_heap_t; -pub extern fn mi_heap_collect(heap: ?*mi_heap_t, force: bool) void; -pub extern fn mi_heap_malloc(heap: ?*mi_heap_t, size: usize) ?*anyopaque; -pub extern fn mi_heap_zalloc(heap: ?*mi_heap_t, size: usize) ?*anyopaque; -pub extern fn mi_heap_calloc(heap: ?*mi_heap_t, count: usize, size: usize) ?*anyopaque; -pub extern fn mi_heap_mallocn(heap: ?*mi_heap_t, count: usize, size: usize) ?*anyopaque; -pub extern fn mi_heap_malloc_small(heap: ?*mi_heap_t, size: usize) ?*anyopaque; -pub extern fn mi_heap_realloc(heap: ?*mi_heap_t, p: ?*anyopaque, newsize: usize) ?*anyopaque; -pub extern fn mi_heap_reallocn(heap: ?*mi_heap_t, p: ?*anyopaque, count: usize, size: usize) ?*anyopaque; -pub extern fn mi_heap_reallocf(heap: ?*mi_heap_t, p: ?*anyopaque, newsize: usize) ?*anyopaque; -pub extern fn mi_heap_strdup(heap: ?*mi_heap_t, s: [*c]const u8) [*c]u8; -pub extern fn mi_heap_strndup(heap: ?*mi_heap_t, s: [*c]const u8, n: usize) [*c]u8; -pub extern fn mi_heap_realpath(heap: ?*mi_heap_t, fname: [*c]const u8, resolved_name: [*c]u8) [*c]u8; -pub extern fn mi_heap_malloc_aligned(heap: ?*mi_heap_t, size: usize, alignment: usize) ?*anyopaque; -pub extern fn mi_heap_malloc_aligned_at(heap: ?*mi_heap_t, size: usize, alignment: usize, offset: usize) ?*anyopaque; -pub extern fn mi_heap_zalloc_aligned(heap: ?*mi_heap_t, size: usize, alignment: usize) ?*anyopaque; -pub extern fn mi_heap_zalloc_aligned_at(heap: ?*mi_heap_t, size: usize, alignment: usize, offset: usize) ?*anyopaque; -pub extern fn mi_heap_calloc_aligned(heap: ?*mi_heap_t, count: usize, size: usize, alignment: usize) ?*anyopaque; -pub extern fn mi_heap_calloc_aligned_at(heap: ?*mi_heap_t, count: usize, size: usize, alignment: usize, offset: usize) ?*anyopaque; -pub extern fn mi_heap_realloc_aligned(heap: ?*mi_heap_t, p: ?*anyopaque, newsize: usize, alignment: usize) ?*anyopaque; -pub extern fn mi_heap_realloc_aligned_at(heap: ?*mi_heap_t, p: ?*anyopaque, newsize: usize, alignment: usize, offset: usize) ?*anyopaque; +pub extern fn mi_heap_new() ?*Heap; +pub extern fn mi_heap_delete(heap: *Heap) void; +pub extern fn mi_heap_destroy(heap: *Heap) void; +pub extern fn mi_heap_set_default(heap: *Heap) *Heap; +pub extern fn mi_heap_get_default() *Heap; +pub extern fn mi_heap_get_backing() *Heap; +pub extern fn mi_heap_collect(heap: *Heap, force: bool) void; +pub extern fn mi_heap_malloc(heap: *Heap, size: usize) ?*anyopaque; +pub extern fn mi_heap_zalloc(heap: *Heap, size: usize) ?*anyopaque; +pub extern fn mi_heap_calloc(heap: *Heap, count: usize, size: usize) ?*anyopaque; +pub extern fn mi_heap_mallocn(heap: *Heap, count: usize, size: usize) ?*anyopaque; +pub extern fn mi_heap_malloc_small(heap: *Heap, size: usize) ?*anyopaque; +pub extern fn mi_heap_realloc(heap: *Heap, p: ?*anyopaque, newsize: usize) ?*anyopaque; +pub extern fn mi_heap_reallocn(heap: *Heap, p: ?*anyopaque, count: usize, size: usize) ?*anyopaque; +pub extern fn mi_heap_reallocf(heap: *Heap, p: ?*anyopaque, newsize: usize) ?*anyopaque; +pub extern fn mi_heap_strdup(heap: *Heap, s: [*c]const u8) [*c]u8; +pub extern fn mi_heap_strndup(heap: *Heap, s: [*c]const u8, n: usize) [*c]u8; +pub extern fn mi_heap_realpath(heap: *Heap, fname: [*c]const u8, resolved_name: [*c]u8) [*c]u8; +pub extern fn mi_heap_malloc_aligned(heap: *Heap, size: usize, alignment: usize) ?*anyopaque; +pub extern fn mi_heap_malloc_aligned_at(heap: *Heap, size: usize, alignment: usize, offset: usize) ?*anyopaque; +pub extern fn mi_heap_zalloc_aligned(heap: *Heap, size: usize, alignment: usize) ?*anyopaque; +pub extern fn mi_heap_zalloc_aligned_at(heap: *Heap, size: usize, alignment: usize, offset: usize) ?*anyopaque; +pub extern fn mi_heap_calloc_aligned(heap: *Heap, count: usize, size: usize, alignment: usize) ?*anyopaque; +pub extern fn mi_heap_calloc_aligned_at(heap: *Heap, count: usize, size: usize, alignment: usize, offset: usize) ?*anyopaque; +pub extern fn mi_heap_realloc_aligned(heap: *Heap, p: ?*anyopaque, newsize: usize, alignment: usize) ?*anyopaque; +pub extern fn mi_heap_realloc_aligned_at(heap: *Heap, p: ?*anyopaque, newsize: usize, alignment: usize, offset: usize) ?*anyopaque; pub extern fn mi_rezalloc(p: ?*anyopaque, newsize: usize) ?*anyopaque; pub extern fn mi_recalloc(p: ?*anyopaque, newcount: usize, size: usize) ?*anyopaque; pub extern fn mi_rezalloc_aligned(p: ?*anyopaque, newsize: usize, alignment: usize) ?*anyopaque; pub extern fn mi_rezalloc_aligned_at(p: ?*anyopaque, newsize: usize, alignment: usize, offset: usize) ?*anyopaque; pub extern fn mi_recalloc_aligned(p: ?*anyopaque, newcount: usize, size: usize, alignment: usize) ?*anyopaque; pub extern fn mi_recalloc_aligned_at(p: ?*anyopaque, newcount: usize, size: usize, alignment: usize, offset: usize) ?*anyopaque; -pub extern fn mi_heap_rezalloc(heap: ?*mi_heap_t, p: ?*anyopaque, newsize: usize) ?*anyopaque; -pub extern fn mi_heap_recalloc(heap: ?*mi_heap_t, p: ?*anyopaque, newcount: usize, size: usize) ?*anyopaque; -pub extern fn mi_heap_rezalloc_aligned(heap: ?*mi_heap_t, p: ?*anyopaque, newsize: usize, alignment: usize) ?*anyopaque; -pub extern fn mi_heap_rezalloc_aligned_at(heap: ?*mi_heap_t, p: ?*anyopaque, newsize: usize, alignment: usize, offset: usize) ?*anyopaque; -pub extern fn mi_heap_recalloc_aligned(heap: ?*mi_heap_t, p: ?*anyopaque, newcount: usize, size: usize, alignment: usize) ?*anyopaque; -pub extern fn mi_heap_recalloc_aligned_at(heap: ?*mi_heap_t, p: ?*anyopaque, newcount: usize, size: usize, alignment: usize, offset: usize) ?*anyopaque; -pub extern fn mi_heap_contains_block(heap: ?*mi_heap_t, p: ?*const anyopaque) bool; -pub extern fn mi_heap_check_owned(heap: ?*mi_heap_t, p: ?*const anyopaque) bool; +pub extern fn mi_heap_rezalloc(heap: *Heap, p: ?*anyopaque, newsize: usize) ?*anyopaque; +pub extern fn mi_heap_recalloc(heap: *Heap, p: ?*anyopaque, newcount: usize, size: usize) ?*anyopaque; +pub extern fn mi_heap_rezalloc_aligned(heap: *Heap, p: ?*anyopaque, newsize: usize, alignment: usize) ?*anyopaque; +pub extern fn mi_heap_rezalloc_aligned_at(heap: *Heap, p: ?*anyopaque, newsize: usize, alignment: usize, offset: usize) ?*anyopaque; +pub extern fn mi_heap_recalloc_aligned(heap: *Heap, p: ?*anyopaque, newcount: usize, size: usize, alignment: usize) ?*anyopaque; +pub extern fn mi_heap_recalloc_aligned_at(heap: *Heap, p: ?*anyopaque, newcount: usize, size: usize, alignment: usize, offset: usize) ?*anyopaque; +pub extern fn mi_heap_contains_block(heap: *Heap, p: *const anyopaque) bool; +pub extern fn mi_heap_check_owned(heap: *Heap, p: *const anyopaque) bool; pub extern fn mi_check_owned(p: ?*const anyopaque) bool; pub const struct_mi_heap_area_s = extern struct { blocks: ?*anyopaque, @@ -106,18 +115,26 @@ pub const struct_mi_heap_area_s = extern struct { committed: usize, used: usize, block_size: usize, + full_block_size: usize, }; pub const mi_heap_area_t = struct_mi_heap_area_s; -pub const mi_block_visit_fun = fn (?*const mi_heap_t, [*c]const mi_heap_area_t, ?*anyopaque, usize, ?*anyopaque) callconv(.C) bool; -pub extern fn mi_heap_visit_blocks(heap: ?*const mi_heap_t, visit_all_blocks: bool, visitor: ?mi_block_visit_fun, arg: ?*anyopaque) bool; +pub const mi_block_visit_fun = fn (?*const Heap, [*c]const mi_heap_area_t, ?*anyopaque, usize, ?*anyopaque) callconv(.C) bool; +pub extern fn mi_heap_visit_blocks(heap: ?*const Heap, visit_all_blocks: bool, visitor: ?mi_block_visit_fun, arg: ?*anyopaque) bool; pub extern fn mi_is_in_heap_region(p: ?*const anyopaque) bool; pub extern fn mi_is_redirected() bool; pub extern fn mi_reserve_huge_os_pages_interleave(pages: usize, numa_nodes: usize, timeout_msecs: usize) c_int; pub extern fn mi_reserve_huge_os_pages_at(pages: usize, numa_node: c_int, timeout_msecs: usize) c_int; pub extern fn mi_reserve_os_memory(size: usize, commit: bool, allow_large: bool) c_int; pub extern fn mi_manage_os_memory(start: ?*anyopaque, size: usize, is_committed: bool, is_large: bool, is_zero: bool, numa_node: c_int) bool; +pub extern fn mi_debug_show_arenas() void; +pub const ArenaID = c_int; +pub extern fn mi_arena_area(arena_id: ArenaID, size: [*c]usize) ?*anyopaque; +pub extern fn mi_reserve_huge_os_pages_at_ex(pages: usize, numa_node: c_int, timeout_msecs: usize, exclusive: bool, arena_id: *ArenaID) c_int; +pub extern fn mi_reserve_os_memory_ex(size: usize, commit: bool, allow_large: bool, exclusive: bool, arena_id: *ArenaID) c_int; +pub extern fn mi_manage_os_memory_ex(start: ?*anyopaque, size: usize, is_committed: bool, is_large: bool, is_zero: bool, numa_node: c_int, exclusive: bool, arena_id: *ArenaID) bool; +pub extern fn mi_heap_new_in_arena(arena_id: ArenaID) ?*Heap; pub extern fn mi_reserve_huge_os_pages(pages: usize, max_secs: f64, pages_reserved: [*c]usize) c_int; -pub const mi_option_t = enum(c_uint) { +pub const Option = enum(c_uint) { show_errors = 0, show_stats = 1, verbose = 2, @@ -128,7 +145,7 @@ pub const mi_option_t = enum(c_uint) { reserve_huge_os_pages = 7, reserve_huge_os_pages_at = 8, reserve_os_memory = 9, - segment_cache = 10, + deprecated_segment_cache = 10, page_reset = 11, abandoned_page_decommit = 12, deprecated_segment_reset = 13, @@ -139,24 +156,24 @@ pub const mi_option_t = enum(c_uint) { os_tag = 18, max_errors = 19, max_warnings = 20, - - // mimalloc v2 specific - allow_decommit = 21, - segment_decommit_delay = 22, - decommit_extend_delay = 23, + max_segment_reclaim = 21, + allow_decommit = 22, + segment_decommit_delay = 23, + decommit_extend_delay = 24, }; - -pub extern fn mi_option_is_enabled(option: mi_option_t) bool; -pub extern fn mi_option_enable(option: mi_option_t) void; -pub extern fn mi_option_disable(option: mi_option_t) void; -pub extern fn mi_option_set_enabled(option: mi_option_t, enable: bool) void; -pub extern fn mi_option_set_enabled_default(option: mi_option_t, enable: bool) void; -pub extern fn mi_option_get(option: mi_option_t) c_long; -pub extern fn mi_option_set(option: mi_option_t, value: c_long) void; -pub extern fn mi_option_set_default(option: mi_option_t, value: c_long) void; +pub extern fn mi_option_is_enabled(option: Option) bool; +pub extern fn mi_option_enable(option: Option) void; +pub extern fn mi_option_disable(option: Option) void; +pub extern fn mi_option_set_enabled(option: Option, enable: bool) void; +pub extern fn mi_option_set_enabled_default(option: Option, enable: bool) void; +pub extern fn mi_option_get(option: Option) c_long; +pub extern fn mi_option_get_clamp(option: Option, min: c_long, max: c_long) c_long; +pub extern fn mi_option_set(option: Option, value: c_long) void; +pub extern fn mi_option_set_default(option: Option, value: c_long) void; pub extern fn mi_cfree(p: ?*anyopaque) void; pub extern fn mi__expand(p: ?*anyopaque, newsize: usize) ?*anyopaque; pub extern fn mi_malloc_size(p: ?*const anyopaque) usize; +pub extern fn mi_malloc_good_size(size: usize) usize; pub extern fn mi_malloc_usable_size(p: ?*const anyopaque) usize; pub extern fn mi_posix_memalign(p: [*c]?*anyopaque, alignment: usize, size: usize) c_int; pub extern fn mi_memalign(alignment: usize, size: usize) ?*anyopaque; @@ -164,6 +181,7 @@ pub extern fn mi_valloc(size: usize) ?*anyopaque; pub extern fn mi_pvalloc(size: usize) ?*anyopaque; pub extern fn mi_aligned_alloc(alignment: usize, size: usize) ?*anyopaque; pub extern fn mi_reallocarray(p: ?*anyopaque, count: usize, size: usize) ?*anyopaque; +pub extern fn mi_reallocarr(p: ?*anyopaque, count: usize, size: usize) c_int; pub extern fn mi_aligned_recalloc(p: ?*anyopaque, newcount: usize, size: usize, alignment: usize) ?*anyopaque; pub extern fn mi_aligned_offset_recalloc(p: ?*anyopaque, newcount: usize, size: usize, alignment: usize, offset: usize) ?*anyopaque; pub extern fn mi_wcsdup(s: [*c]const c_ushort) [*c]c_ushort; @@ -180,30 +198,6 @@ pub extern fn mi_new_aligned_nothrow(size: usize, alignment: usize) ?*anyopaque; pub extern fn mi_new_n(count: usize, size: usize) ?*anyopaque; pub extern fn mi_new_realloc(p: ?*anyopaque, newsize: usize) ?*anyopaque; pub extern fn mi_new_reallocn(p: ?*anyopaque, newcount: usize, size: usize) ?*anyopaque; -pub const mi_attr_alloc_size = @compileError("unable to translate C expr: unexpected token .Eof"); // /Users/jarred/Downloads/mimalloc-1.7.2/include/mimalloc.h:66:13 -pub const mi_attr_alloc_size2 = @compileError("unable to translate C expr: unexpected token .Eof"); // /Users/jarred/Downloads/mimalloc-1.7.2/include/mimalloc.h:67:13 -pub const mi_attr_alloc_align = @compileError("unable to translate C expr: unexpected token .Eof"); // /Users/jarred/Downloads/mimalloc-1.7.2/include/mimalloc.h:68:13 -pub const offsetof = @compileError("TODO implement function '__builtin_offsetof' in std.zig.c_builtins"); // /Users/jarred/Build/zig/lib/include/stddef.h:104:9 -pub const mi_malloc_tp = @compileError("unable to translate C expr: unexpected token .RParen"); // /Users/jarred/Downloads/mimalloc-1.7.2/include/mimalloc.h:279:9 -pub const mi_zalloc_tp = @compileError("unable to translate C expr: unexpected token .RParen"); // /Users/jarred/Downloads/mimalloc-1.7.2/include/mimalloc.h:280:9 -pub const mi_calloc_tp = @compileError("unable to translate C expr: unexpected token .RParen"); // /Users/jarred/Downloads/mimalloc-1.7.2/include/mimalloc.h:281:9 -pub const mi_mallocn_tp = @compileError("unable to translate C expr: unexpected token .RParen"); // /Users/jarred/Downloads/mimalloc-1.7.2/include/mimalloc.h:282:9 -pub const mi_reallocn_tp = @compileError("unable to translate C expr: unexpected token .RParen"); // /Users/jarred/Downloads/mimalloc-1.7.2/include/mimalloc.h:283:9 -pub const mi_recalloc_tp = @compileError("unable to translate C expr: unexpected token .RParen"); // /Users/jarred/Downloads/mimalloc-1.7.2/include/mimalloc.h:284:9 -pub const mi_heap_malloc_tp = @compileError("unable to translate C expr: unexpected token .RParen"); // /Users/jarred/Downloads/mimalloc-1.7.2/include/mimalloc.h:286:9 -pub const mi_heap_zalloc_tp = @compileError("unable to translate C expr: unexpected token .RParen"); // /Users/jarred/Downloads/mimalloc-1.7.2/include/mimalloc.h:287:9 -pub const mi_heap_calloc_tp = @compileError("unable to translate C expr: unexpected token .RParen"); // /Users/jarred/Downloads/mimalloc-1.7.2/include/mimalloc.h:288:9 -pub const mi_heap_mallocn_tp = @compileError("unable to translate C expr: unexpected token .RParen"); // /Users/jarred/Downloads/mimalloc-1.7.2/include/mimalloc.h:289:9 -pub const mi_heap_reallocn_tp = @compileError("unable to translate C expr: unexpected token .RParen"); // /Users/jarred/Downloads/mimalloc-1.7.2/include/mimalloc.h:290:9 -pub const mi_heap_recalloc_tp = @compileError("unable to translate C expr: unexpected token .RParen"); // /Users/jarred/Downloads/mimalloc-1.7.2/include/mimalloc.h:291:9 -pub const MI_MALLOC_VERSION = @as(c_int, 171); -pub const NULL = @import("std").zig.c_translation.cast(?*anyopaque, @as(c_int, 0)); -pub const bool_1 = bool; -pub const true_2 = @as(c_int, 1); -pub const false_3 = @as(c_int, 0); -pub const __bool_true_false_are_defined = @as(c_int, 1); pub const MI_SMALL_WSIZE_MAX = @as(c_int, 128); pub const MI_SMALL_SIZE_MAX = MI_SMALL_WSIZE_MAX * @import("std").zig.c_translation.sizeof(?*anyopaque); -pub const mi_heap_s = struct_mi_heap_s; -pub const mi_heap_area_s = struct_mi_heap_area_s; -pub const mi_option_e = enum_mi_option_e; +pub const MI_ALIGNMENT_MAX = (@as(c_int, 16) * @as(c_int, 1024)) * @as(c_ulong, 1024); diff --git a/src/bun.js/api/bun.classes.ts b/src/bun.js/api/bun.classes.ts index f617c53c5..04dd94a38 100644 --- a/src/bun.js/api/bun.classes.ts +++ b/src/bun.js/api/bun.classes.ts @@ -4,6 +4,7 @@ export default [ define({ name: "Subprocess", construct: true, + noConstructor: true, finalize: true, hasPendingActivity: true, klass: {}, diff --git a/src/bun.js/api/bun.zig b/src/bun.js/api/bun.zig index 9046fd6e9..ee26b09f5 100644 --- a/src/bun.js/api/bun.zig +++ b/src/bun.js/api/bun.zig @@ -31,7 +31,7 @@ const ImportKind = ast.ImportKind; const Analytics = @import("../../analytics/analytics_thread.zig"); const ZigString = @import("../../jsc.zig").ZigString; const Runtime = @import("../../runtime.zig"); -const Router = @import("./router.zig"); +const Router = @import("./filesystem_router.zig"); const ImportRecord = ast.ImportRecord; const DotEnv = @import("../../env_loader.zig"); const ParseResult = @import("../../bundler.zig").ParseResult; @@ -820,7 +820,14 @@ pub fn readFileAsString( } pub fn getPublicPath(to: string, origin: URL, comptime Writer: type, writer: Writer) void { - const relative_path = VirtualMachine.vm.bundler.fs.relativeTo(to); + return getPublicPathWithAssetPrefix(to, VirtualMachine.vm.bundler.fs.top_level_dir, origin, VirtualMachine.vm.bundler.options.routes.asset_prefix_path, comptime Writer, writer); +} + +pub fn getPublicPathWithAssetPrefix(to: string, dir: string, origin: URL, asset_prefix: string, comptime Writer: type, writer: Writer) void { + const relative_path = if (strings.hasPrefix(to, dir)) + strings.withoutTrailingSlash(to[dir.len..]) + else + VirtualMachine.vm.bundler.fs.relative(dir, to); if (origin.isAbsolute()) { if (strings.hasPrefix(relative_path, "..") or strings.hasPrefix(relative_path, "./")) { writer.writeAll(origin.origin) catch return; @@ -834,7 +841,7 @@ pub fn getPublicPath(to: string, origin: URL, comptime Writer: type, writer: Wri origin.joinWrite( Writer, writer, - VirtualMachine.vm.bundler.options.routes.asset_prefix_path, + asset_prefix, "", relative_path, "", @@ -894,11 +901,7 @@ pub fn runGC( arguments: []const js.JSValueRef, _: js.ExceptionRef, ) js.JSValueRef { - // it should only force cleanup on thread exit - - Global.mimalloc_cleanup(false); - - return ctx.ptr().vm().runGC(arguments.len > 0 and JSValue.fromRef(arguments[0]).toBoolean()).asRef(); + return ctx.bunVM().garbageCollect(arguments.len > 0 and JSC.JSValue.c(arguments[0]).toBoolean()).asObjectRef(); } pub fn shrink( @@ -1087,7 +1090,7 @@ pub const Class = NewClass( }, .{ .match = .{ - .rfn = Router.match, + .rfn = Router.deprecatedBunGlobalMatch, }, .sleepSync = .{ .rfn = sleepSync, @@ -1284,6 +1287,9 @@ pub const Class = NewClass( .FFI = .{ .get = FFI.getter, }, + .FileSystemRouter = .{ + .get = getFileSystemRouter, + }, }, ); @@ -1295,7 +1301,7 @@ fn dump_mimalloc( _: []const JSC.C.JSValueRef, _: JSC.C.ExceptionRef, ) JSC.C.JSValueRef { - globalThis.bunVM().arena.dumpThreadStats(); + globalThis.bunVM().arena.dumpStats(); return JSC.JSValue.jsUndefined().asObjectRef(); } @@ -1800,6 +1806,16 @@ pub fn getTranspilerConstructor( return existing.asObjectRef(); } +pub fn getFileSystemRouter( + _: void, + ctx: js.JSContextRef, + _: js.JSValueRef, + _: js.JSStringRef, + _: js.ExceptionRef, +) js.JSValueRef { + return JSC.API.FileSystemRouter.getConstructor(ctx).asObjectRef(); +} + pub fn getHashObject( _: void, ctx: js.JSContextRef, @@ -1994,10 +2010,30 @@ pub const Unsafe = struct { .arrayBufferToString = .{ .rfn = arrayBufferToString, }, + .gcAggressionLevel = .{ + .rfn = JSC.wrapWithHasContainer(Unsafe, "gcAggressionLevel", false, false, false), + }, }, .{}, ); + pub fn gcAggressionLevel( + globalThis: *JSC.JSGlobalObject, + value_: ?JSValue, + ) JSValue { + const ret = JSValue.jsNumber(@as(i32, @enumToInt(globalThis.bunVM().aggressive_garbage_collection))); + + if (value_) |value| { + switch (value.coerce(i32, globalThis)) { + 1 => globalThis.bunVM().aggressive_garbage_collection = .mild, + 2 => globalThis.bunVM().aggressive_garbage_collection = .aggressive, + 0 => globalThis.bunVM().aggressive_garbage_collection = .none, + else => {}, + } + } + return ret; + } + // For testing the segfault handler pub fn __debug__doSegfault( _: void, @@ -3410,7 +3446,6 @@ pub const EnvironmentVariables = struct { // this can be a statically allocated string if (bun.isHeapMemory(entry.value_ptr.*)) allocator.free(bun.constStrToU8(entry.value_ptr.*)); - const cloned_value = value.?.value().toSlice(globalThis, allocator).cloneIfNeeded(allocator) catch return false; entry.value_ptr.* = cloned_value.slice(); } diff --git a/src/bun.js/api/bun/socket.zig b/src/bun.js/api/bun/socket.zig index 5bc1629c0..2405996cf 100644 --- a/src/bun.js/api/bun/socket.zig +++ b/src/bun.js/api/bun/socket.zig @@ -775,11 +775,21 @@ fn NewSocket(comptime ssl: bool) type { reffer: JSC.Ref = JSC.Ref.init(), last_4: [4]u8 = .{ 0, 0, 0, 0 }, + // TODO: switch to something that uses `visitAggregate` and have the + // `Listener` keep a list of all the sockets JSValue in there + // This is wasteful because it means we are keeping a JSC::Weak for every single open socket + has_pending_activity: std.atomic.Atomic(bool) = std.atomic.Atomic(bool).init(true), + const This = @This(); const log = Output.scoped(.Socket, false); pub usingnamespace JSSocketType(ssl); + pub fn hasPendingActivity(this: *This) callconv(.C) bool { + @fence(.Acquire); + return this.has_pending_activity.load(.Acquire); + } + pub fn doConnect(this: *This, connection: Listener.UnixOrHost, socket_ctx: *uws.SocketContext) !void { switch (connection) { .host => |c| { @@ -874,13 +884,13 @@ fn NewSocket(comptime ssl: bool) type { _ = handlers.rejectPromise(err.toErrorInstance(handlers.globalObject)); this.reffer.unref(handlers.vm); handlers.markInactive(ssl, socket.context()); - this.finalize(); } pub fn markActive(this: *This) void { if (!this.reffer.has) { this.handlers.markActive(); this.reffer.ref(this.handlers.vm); + this.has_pending_activity.store(true, .Release); } } @@ -897,10 +907,7 @@ fn NewSocket(comptime ssl: bool) type { this.handlers.markInactive(ssl, this.socket.context()); this.poll_ref.unref(vm); - } - - if (this.this_value != .zero) { - this.this_value.unprotect(); + this.has_pending_activity.store(false, .Release); } } @@ -954,8 +961,8 @@ fn NewSocket(comptime ssl: bool) type { pub fn getThisValue(this: *This, globalObject: *JSC.JSGlobalObject) JSValue { if (this.this_value == .zero) { const value = this.toJS(globalObject); + value.ensureStillAlive(); this.this_value = value; - value.protect(); return value; } @@ -1346,9 +1353,9 @@ fn NewSocket(comptime ssl: bool) type { if (!this.socket.isClosed()) this.socket.flush(); this.detached = true; - this.markInactive(); if (!this.socket.isClosed()) this.socket.close(0, null); + this.markInactive(); } return JSValue.jsUndefined(); @@ -1364,9 +1371,10 @@ fn NewSocket(comptime ssl: bool) type { if (result != .zero and result.toInt32() > 0) { this.socket.flush(); this.detached = true; - this.markInactive(); + if (!this.socket.isClosed()) this.socket.close(0, null); + this.markInactive(); } return result; diff --git a/src/bun.js/api/bun/subprocess.zig b/src/bun.js/api/bun/subprocess.zig index eebbcc597..95cad84c6 100644 --- a/src/bun.js/api/bun/subprocess.zig +++ b/src/bun.js/api/bun/subprocess.zig @@ -32,7 +32,6 @@ pub const Subprocess = struct { poll_ref: ?*JSC.FilePoll = null, exit_promise: JSC.Strong = .{}, - on_exit_callback: JSC.Strong = .{}, exit_code: ?u8 = null, @@ -63,6 +62,18 @@ pub const Subprocess = struct { this.has_pending_activity.store(this.waitpid_err == null and this.exit_code == null, .SeqCst); } + has_pending_activity: std.atomic.Atomic(bool) = std.atomic.Atomic(bool).init(true), + + pub fn hasPendingActivity(this: *Subprocess) callconv(.C) bool { + @fence(.Acquire); + return this.has_pending_activity.load(.Acquire); + } + + pub fn updateHasPendingActivity(this: *Subprocess) void { + @fence(.Release); + this.has_pending_activity.store(this.waitpid_err == null and this.exit_code == null, .Release); + } + pub fn ref(this: *Subprocess) void { var vm = this.globalThis.bunVM(); if (this.poll_ref) |poll| poll.enableKeepingProcessAlive(vm); @@ -307,30 +318,6 @@ pub const Subprocess = struct { } } - pub fn closePorts(this: *Subprocess, finalizing: bool) void { - this.closeProcess(); - - if (finalizing and !this.hasCalledGetter(.stdout) and !(this.stdout == .pipe and this.stdout.pipe == .buffer)) { - this.stdout.close(); - } else if (this.stdout == .pipe) { - this.stdout.pipe.done(); - } - - if (finalizing and !this.hasCalledGetter(.stderr) and !(this.stderr == .pipe and this.stderr.pipe == .buffer)) { - this.stderr.close(); - } else if (this.stderr == .pipe) { - this.stderr.pipe.done(); - } - - if (finalizing and !this.hasCalledGetter(.stdin) or (this.stdin == .buffered_input and this.stdin == .pipe_to_readable_stream)) { - this.stdin.close(); - } else if (this.stdin == .pipe) { - this.stdin.pipe.signal.clear(); - this.stdin.pipe.onHangup(); - this.stdin = .ignore; - } - } - pub fn doRef(this: *Subprocess, _: *JSC.JSGlobalObject, _: *JSC.CallFrame) callconv(.C) JSValue { this.ref(); return JSC.JSValue.jsUndefined(); @@ -788,12 +775,9 @@ pub const Subprocess = struct { bun.default_allocator.destroy(this); } - pub fn finalizeSync(this: *Subprocess) void { - if (this.poll_ref) |poll| { - this.poll_ref = null; - poll.deinit(); - } - this.closePorts(true); + this.finalized = true; + bun.default_allocator.destroy(this); + log("Finalize", .{}); } pub fn getExited( @@ -1286,8 +1270,9 @@ pub const Subprocess = struct { } } - fn onExit(this: *Subprocess, globalThis: *JSC.JSGlobalObject) void { - this.closePorts(false); + fn onExit(this: *Subprocess) void { + defer this.updateHasPendingActivity(); + this.closePorts(); this.has_waitpid_task = false; diff --git a/src/bun.js/api/ffi.zig b/src/bun.js/api/ffi.zig index 269557bcc..a1d0640b2 100644 --- a/src/bun.js/api/ffi.zig +++ b/src/bun.js/api/ffi.zig @@ -31,7 +31,6 @@ const ImportKind = ast.ImportKind; const Analytics = @import("../../analytics/analytics_thread.zig"); const ZigString = @import("../../jsc.zig").ZigString; const Runtime = @import("../../runtime.zig"); -const Router = @import("./router.zig"); const ImportRecord = ast.ImportRecord; const DotEnv = @import("../../env_loader.zig"); const ParseResult = @import("../../bundler.zig").ParseResult; diff --git a/src/bun.js/api/filesystem_router.classes.ts b/src/bun.js/api/filesystem_router.classes.ts new file mode 100644 index 000000000..9bcf56dd3 --- /dev/null +++ b/src/bun.js/api/filesystem_router.classes.ts @@ -0,0 +1,78 @@ +import { define } from "../scripts/class-definitions"; + +export default [ + define({ + name: "FileSystemRouter", + construct: true, + finalize: true, + JSType: "0b11101110", + + proto: { + match: { + fn: "match", + length: 1, + }, + routes: { + getter: "getRoutes", + cache: true, + }, + reload: { + fn: "reload", + length: 0, + }, + origin: { + getter: "getOrigin", + cache: true, + }, + style: { + getter: "getStyle", + cache: true, + }, + }, + klass: {}, + }), + + define({ + name: "MatchedRoute", + noConstructor: true, + JSType: "0b11101110", + construct: true, + finalize: true, + proto: { + params: { + getter: "getParams", + cache: true, + }, + pathname: { + getter: "getPathname", + cache: true, + }, + query: { + getter: "getQuery", + cache: true, + }, + name: { + getter: "getName", + cache: true, + }, + kind: { + getter: "getKind", + cache: true, + }, + filePath: { + getter: "getFilePath", + cache: true, + }, + // this is for compatibiltiy with bun-framework-next old versions + scriptSrc: { + getter: "getScriptSrc", + cache: true, + }, + src: { + getter: "getScriptSrc", + cache: "scriptSrc", + }, + }, + klass: {}, + }), +]; diff --git a/src/bun.js/api/filesystem_router.zig b/src/bun.js/api/filesystem_router.zig new file mode 100644 index 000000000..c80a4ed07 --- /dev/null +++ b/src/bun.js/api/filesystem_router.zig @@ -0,0 +1,739 @@ +const std = @import("std"); +const Api = @import("../../api/schema.zig").Api; +const http = @import("../../http.zig"); +const JavaScript = @import("../javascript.zig"); +const QueryStringMap = @import("../../url.zig").QueryStringMap; +const CombinedScanner = @import("../../url.zig").CombinedScanner; +const bun = @import("../../global.zig"); +const string = bun.string; +const JSC = @import("../../jsc.zig"); +const js = JSC.C; +const WebCore = @import("../webcore/response.zig"); +const Bundler = @import("../../bundler.zig"); +const VirtualMachine = JavaScript.VirtualMachine; +const ScriptSrcStream = std.io.FixedBufferStream([]u8); +const ZigString = JSC.ZigString; +const Fs = @import("../../fs.zig"); +const Base = @import("../base.zig"); +const getAllocator = Base.getAllocator; +const JSObject = JSC.JSObject; +const JSError = Base.JSError; +const JSValue = JSC.JSValue; +const JSGlobalObject = JSC.JSGlobalObject; +const strings = @import("strings"); +const NewClass = Base.NewClass; +const To = Base.To; +const Request = WebCore.Request; +const d = Base.d; +const FetchEvent = WebCore.FetchEvent; +const URLPath = @import("../../http/url_path.zig"); +const URL = @import("../../url.zig").URL; +const Log = @import("../../logger.zig"); +const Resolver = @import("../../resolver/resolver.zig").Resolver; +const Router = @import("../../router.zig"); + +const default_extensions = &[_][]const u8{ + "tsx", + "jsx", + "ts", + "mjs", + "cjs", + "js", +}; + +const DeprecatedGlobalRouter = struct { + pub fn deprecatedBunGlobalMatch( + _: void, + ctx: js.JSContextRef, + _: js.JSObjectRef, + _: js.JSObjectRef, + arguments: []const js.JSValueRef, + exception: js.ExceptionRef, + ) js.JSObjectRef { + if (arguments.len == 0) { + JSError(getAllocator(ctx), "Expected string, FetchEvent, or Request but there were no arguments", .{}, ctx, exception); + return null; + } + + const arg: JSC.JSValue = brk: { + if (FetchEvent.Class.isLoaded()) { + if (JSValue.as(JSValue.fromRef(arguments[0]), FetchEvent)) |fetch_event| { + if (fetch_event.request_context != null) { + return deprecatedMatchFetchEvent(ctx, fetch_event, exception); + } + + // When disconencted, we still have a copy of the request data in here + break :brk JSC.JSValue.fromRef(fetch_event.getRequest(ctx, null, undefined, null)); + } + } + break :brk JSC.JSValue.fromRef(arguments[0]); + }; + + var router = JavaScript.VirtualMachine.vm.bundler.router orelse { + JSError(getAllocator(ctx), "Bun.match needs a framework configured with routes", .{}, ctx, exception); + return null; + }; + + var path_: ?ZigString.Slice = null; + var pathname: string = ""; + defer { + if (path_) |path| { + path.deinit(); + } + } + + if (arg.isString()) { + var path_string = arg.getZigString(ctx); + path_ = path_string.toSlice(bun.default_allocator); + var url = URL.parse(path_.?.slice()); + pathname = url.pathname; + } else if (arg.as(Request)) |req| { + var url = URL.parse(req.url); + pathname = url.pathname; + } + + if (path_ == null) { + JSError(getAllocator(ctx), "Expected string, FetchEvent, or Request", .{}, ctx, exception); + return null; + } + + const url_path = URLPath.parse(path_.?.slice()) catch { + JSError(getAllocator(ctx), "Could not parse URL path", .{}, ctx, exception); + return null; + }; + + var match_params_fallback = std.heap.stackFallback(1024, bun.default_allocator); + var match_params_allocator = match_params_fallback.get(); + var match_params = Router.Param.List{}; + match_params.ensureTotalCapacity(match_params_allocator, 16) catch unreachable; + var prev_allocator = router.routes.allocator; + router.routes.allocator = match_params_allocator; + defer router.routes.allocator = prev_allocator; + if (router.routes.matchPage("", url_path, &match_params)) |matched| { + return createRouteObjectFromMatch(ctx, &matched); + } + // router.routes.matchPage + + return JSC.JSValue.jsNull().asObjectRef(); + } + + fn deprecatedMatchFetchEvent( + ctx: js.JSContextRef, + fetch_event: *const FetchEvent, + _: js.ExceptionRef, + ) js.JSObjectRef { + return createRouteObject(ctx, fetch_event.request_context.?); + } + + fn createRouteObject(ctx: js.JSContextRef, req: *const http.RequestContext) js.JSValueRef { + const route = &(req.matched_route orelse { + return js.JSValueMakeNull(ctx); + }); + + return createRouteObjectFromMatch(ctx, route); + } + + fn createRouteObjectFromMatch( + ctx: js.JSContextRef, + route: *const Router.Match, + ) js.JSValueRef { + var matched = MatchedRoute.init( + getAllocator(ctx), + route.*, + JSC.VirtualMachine.vm.refCountedString(JSC.VirtualMachine.vm.origin.href, null, false), + JSC.VirtualMachine.vm.refCountedString(JSC.VirtualMachine.vm.bundler.options.routes.asset_prefix_path, null, false), + JSC.VirtualMachine.vm.refCountedString(JSC.VirtualMachine.vm.bundler.fs.top_level_dir, null, false), + ) catch unreachable; + + return matched.toJS(ctx).asObjectRef(); + } +}; + +pub const FileSystemRouter = struct { + origin: ?*JSC.RefString = null, + base_dir: ?*JSC.RefString = null, + router: Router, + arena: *std.heap.ArenaAllocator = undefined, + allocator: std.mem.Allocator = undefined, + asset_prefix: ?*JSC.RefString = null, + + pub usingnamespace JSC.Codegen.JSFileSystemRouter; + + pub fn constructor(globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) ?*FileSystemRouter { + const argument_ = callframe.arguments(1); + if (argument_.len == 0) { + globalThis.throwInvalidArguments("Expected object", .{}); + return null; + } + + const argument = argument_.ptr[0]; + if (argument.isEmptyOrUndefinedOrNull() or !argument.isObject()) { + globalThis.throwInvalidArguments("Expected object", .{}); + return null; + } + var vm = globalThis.bunVM(); + + var root_dir_path: ZigString.Slice = ZigString.Slice.fromUTF8NeverFree(vm.bundler.fs.top_level_dir); + defer root_dir_path.deinit(); + var origin_str: ZigString.Slice = .{}; + var asset_prefix_slice: ZigString.Slice = .{}; + + if (argument.get(globalThis, "style")) |style_val| { + if (!style_val.getZigString(globalThis).eqlComptime("nextjs")) { + globalThis.throwInvalidArguments("Only 'nextjs' style is currently implemented", .{}); + return null; + } + } else { + globalThis.throwInvalidArguments("Expected 'style' option (ex: \"style\": \"nextjs\")", .{}); + return null; + } + + if (argument.get(globalThis, "dir")) |dir| { + const root_dir_path_ = dir.toSlice(globalThis, globalThis.allocator()); + if (!(root_dir_path_.len == 0 or strings.eqlComptime(root_dir_path_.slice(), "."))) { + root_dir_path = root_dir_path_; + } + } + var arena = globalThis.allocator().create(std.heap.ArenaAllocator) catch unreachable; + arena.* = std.heap.ArenaAllocator.init(globalThis.allocator()); + var allocator = arena.allocator(); + var extensions = std.ArrayList(string).init(allocator); + if (argument.get(globalThis, "fileExtensions")) |file_extensions| { + if (!file_extensions.jsType().isArray()) { + globalThis.throwInvalidArguments("Expected fileExtensions to be an Array", .{}); + origin_str.deinit(); + arena.deinit(); + globalThis.allocator().destroy(arena); + return null; + } + + var iter = file_extensions.arrayIterator(globalThis); + extensions.ensureTotalCapacityPrecise(iter.len) catch unreachable; + while (iter.next()) |val| { + if (!val.isString()) { + globalThis.throwInvalidArguments("Expected fileExtensions to be an Array of strings", .{}); + origin_str.deinit(); + arena.deinit(); + globalThis.allocator().destroy(arena); + return null; + } + if (val.getLengthOfArray(globalThis) == 0) continue; + extensions.appendAssumeCapacity((val.toSlice(globalThis, allocator).clone(allocator) catch unreachable).slice()[1..]); + } + } + + if (argument.getTruthy(globalThis, "assetPrefix")) |asset_prefix| { + if (!asset_prefix.isString()) { + globalThis.throwInvalidArguments("Expected assetPrefix to be a string", .{}); + origin_str.deinit(); + arena.deinit(); + globalThis.allocator().destroy(arena); + return null; + } + + asset_prefix_slice = asset_prefix.toSlice(globalThis, allocator).clone(allocator) catch unreachable; + } + + var orig_log = vm.bundler.resolver.log; + var log = Log.Log.init(allocator); + vm.bundler.resolver.log = &log; + defer vm.bundler.resolver.log = orig_log; + + var path_to_use = (root_dir_path.cloneWithTrailingSlash(allocator) catch unreachable).slice(); + var root_dir_info = vm.bundler.resolver.readDirInfo(path_to_use) catch { + globalThis.throwValue(log.toJS(globalThis, globalThis.allocator(), "reading root directory")); + origin_str.deinit(); + arena.deinit(); + globalThis.allocator().destroy(arena); + return null; + } orelse { + globalThis.throw("Unable to find directory: {s}", .{root_dir_path.slice()}); + origin_str.deinit(); + arena.deinit(); + globalThis.allocator().destroy(arena); + return null; + }; + var router = Router.init(vm.bundler.fs, allocator, .{ + .dir = path_to_use, + .extensions = if (extensions.items.len > 0) extensions.items else default_extensions, + .asset_prefix_path = asset_prefix_slice.slice(), + }) catch unreachable; + router.loadRoutes(&log, root_dir_info, Resolver, &vm.bundler.resolver) catch { + globalThis.throwValue(log.toJS(globalThis, globalThis.allocator(), "loading routes")); + origin_str.deinit(); + arena.deinit(); + globalThis.allocator().destroy(arena); + return null; + }; + + if (argument.get(globalThis, "origin")) |origin| { + origin_str = origin.toSlice(globalThis, globalThis.allocator()); + } + + if (log.errors + log.warnings > 0) { + globalThis.throwValue(log.toJS(globalThis, globalThis.allocator(), "loading routes")); + origin_str.deinit(); + arena.deinit(); + globalThis.allocator().destroy(arena); + return null; + } + + var fs_router = globalThis.allocator().create(FileSystemRouter) catch unreachable; + fs_router.* = .{ + .origin = if (origin_str.len > 0) vm.refCountedString(origin_str.slice(), null, true) else null, + .base_dir = vm.refCountedString(if (root_dir_info.abs_real_path.len > 0) + root_dir_info.abs_real_path + else + root_dir_info.abs_path, null, true), + .asset_prefix = if (asset_prefix_slice.len > 0) vm.refCountedString(asset_prefix_slice.slice(), null, true) else null, + .router = router, + .arena = arena, + .allocator = allocator, + }; + router.config.dir = fs_router.base_dir.?.slice(); + fs_router.base_dir.?.ref(); + return fs_router; + } + + pub fn reload(this: *FileSystemRouter, globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) JSValue { + var this_value = callframe.this(); + + var arena = globalThis.allocator().create(std.heap.ArenaAllocator) catch unreachable; + arena.* = std.heap.ArenaAllocator.init(globalThis.allocator()); + + var allocator = arena.allocator(); + var vm = globalThis.bunVM(); + + var orig_log = vm.bundler.resolver.log; + var log = Log.Log.init(allocator); + vm.bundler.resolver.log = &log; + defer vm.bundler.resolver.log = orig_log; + + var root_dir_info = vm.bundler.resolver.readDirInfo(this.router.config.dir) catch { + globalThis.throwValue(log.toJS(globalThis, globalThis.allocator(), "reading root directory")); + return .zero; + } orelse { + globalThis.throw("Unable to find directory: {s}", .{this.router.config.dir}); + arena.deinit(); + globalThis.allocator().destroy(arena); + return .zero; + }; + + var router = Router.init(vm.bundler.fs, allocator, .{ + .dir = allocator.dupe(u8, this.router.config.dir) catch unreachable, + .extensions = allocator.dupe(string, this.router.config.extensions) catch unreachable, + .asset_prefix_path = this.router.config.asset_prefix_path, + }) catch unreachable; + router.loadRoutes(&log, root_dir_info, Resolver, &vm.bundler.resolver) catch { + globalThis.throwValue(log.toJS(globalThis, globalThis.allocator(), "loading routes")); + + arena.deinit(); + globalThis.allocator().destroy(arena); + return .zero; + }; + + this.arena.deinit(); + globalThis.allocator().destroy(this.arena); + + this.arena = arena; + @This().routesSetCached(this_value, globalThis, JSC.JSValue.zero); + this.allocator = allocator; + this.router = router; + return this_value; + } + + pub fn match(this: *FileSystemRouter, globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) JSValue { + const argument_ = callframe.arguments(2); + if (argument_.len == 0) { + globalThis.throwInvalidArguments("Expected string, Request or Response", .{}); + return JSValue.zero; + } + + const argument = argument_.ptr[0]; + if (argument.isEmptyOrUndefinedOrNull() or !argument.isCell()) { + globalThis.throwInvalidArguments("Expected string, Request or Response", .{}); + return JSValue.zero; + } + + var path: ZigString.Slice = brk: { + if (argument.isString()) { + break :brk argument.toSlice(globalThis, globalThis.allocator()).clone(globalThis.allocator()) catch unreachable; + } + + if (argument.isCell()) { + if (argument.as(JSC.WebCore.Request)) |req| { + req.ensureURL() catch unreachable; + break :brk ZigString.Slice.fromUTF8NeverFree(req.url).clone(globalThis.allocator()) catch unreachable; + } + + if (argument.as(JSC.WebCore.Response)) |resp| { + break :brk ZigString.Slice.fromUTF8NeverFree(resp.url).clone(globalThis.allocator()) catch unreachable; + } + } + + globalThis.throwInvalidArguments("Expected string, Request or Response", .{}); + return JSValue.zero; + }; + + if (path.len == 0 or (path.len == 1 and path.ptr[0] == '/')) { + path = ZigString.Slice.fromUTF8NeverFree("/"); + } + + if (strings.hasPrefixComptime(path.slice(), "http://") or strings.hasPrefixComptime(path.slice(), "https://") or strings.hasPrefixComptime(path.slice(), "file://")) { + const prev_path = path; + path = ZigString.init(URL.parse(path.slice()).pathname).toSliceFast(globalThis.allocator()).clone(globalThis.allocator()) catch unreachable; + prev_path.deinit(); + } + + const url_path = URLPath.parse(path.slice()) catch |err| { + globalThis.throw("{s} parsing path: {s}", .{ @errorName(err), path.slice() }); + return JSValue.zero; + }; + var params = Router.Param.List{}; + defer params.deinit(globalThis.allocator()); + const route = this.router.routes.matchPageWithAllocator( + "", + url_path, + ¶ms, + globalThis.allocator(), + ) orelse { + return JSValue.jsNull(); + }; + + var result = MatchedRoute.init( + globalThis.allocator(), + route, + this.origin, + this.asset_prefix, + this.base_dir.?, + ) catch unreachable; + return result.toJS(globalThis); + } + + pub fn getOrigin(this: *FileSystemRouter, globalThis: *JSC.JSGlobalObject) callconv(.C) JSValue { + if (this.origin) |origin| { + return JSC.ZigString.init(origin.slice()).withEncoding().toValueGC(globalThis); + } + + return JSValue.jsNull(); + } + + pub fn getRoutes(this: *FileSystemRouter, globalThis: *JSC.JSGlobalObject) callconv(.C) JSValue { + const paths = this.router.getEntryPoints() catch unreachable; + const names = this.router.getNames() catch unreachable; + var name_strings = bun.default_allocator.alloc(ZigString, names.len * 2) catch unreachable; + defer bun.default_allocator.free(name_strings); + var paths_strings = name_strings[names.len..]; + for (names) |name, i| { + name_strings[i] = ZigString.init(name).withEncoding(); + paths_strings[i] = ZigString.init(paths[i]).withEncoding(); + } + return JSC.JSValue.fromEntries( + globalThis, + name_strings.ptr, + paths_strings.ptr, + names.len, + true, + ); + } + + pub fn getStyle(_: *FileSystemRouter, globalThis: *JSC.JSGlobalObject) callconv(.C) JSValue { + return ZigString.static("nextjs").toValue(globalThis); + } + + pub fn getAssetPrefix(this: *FileSystemRouter, globalThis: *JSC.JSGlobalObject) callconv(.C) JSValue { + if (this.asset_prefix) |asset_prefix| { + return JSC.ZigString.init(asset_prefix.slice()).withEncoding().toValueGC(globalThis); + } + + return JSValue.jsNull(); + } + + pub fn finalize( + this: *FileSystemRouter, + ) callconv(.C) void { + if (this.asset_prefix) |prefix| { + prefix.deref(); + } + + if (this.origin) |prefix| { + prefix.deref(); + } + + if (this.base_dir) |dir| { + dir.deref(); + } + + this.arena.deinit(); + } +}; + +pub const MatchedRoute = struct { + route: *const Router.Match, + route_holder: Router.Match = undefined, + query_string_map: ?QueryStringMap = null, + param_map: ?QueryStringMap = null, + params_list_holder: Router.Param.List = .{}, + origin: ?*JSC.RefString = null, + asset_prefix: ?*JSC.RefString = null, + needs_deinit: bool = true, + base_dir: ?*JSC.RefString = null, + + pub usingnamespace JSC.Codegen.JSMatchedRoute; + + pub fn getName(this: *MatchedRoute, globalThis: *JSC.JSGlobalObject) callconv(.C) JSValue { + return ZigString.init(this.route.name).withEncoding().toValueGC(globalThis); + } + + pub fn init( + allocator: std.mem.Allocator, + match: Router.Match, + origin: ?*JSC.RefString, + asset_prefix: ?*JSC.RefString, + base_dir: *JSC.RefString, + ) !*MatchedRoute { + var params_list = try match.params.clone(allocator); + + var route = try allocator.create(MatchedRoute); + + route.* = MatchedRoute{ + .route_holder = match, + .route = undefined, + .asset_prefix = asset_prefix, + .origin = origin, + .base_dir = base_dir, + }; + base_dir.ref(); + route.params_list_holder = params_list; + route.route = &route.route_holder; + route.route_holder.params = &route.params_list_holder; + if (origin) |o| { + o.ref(); + } + + if (asset_prefix) |prefix| { + prefix.ref(); + } + + return route; + } + + pub fn deinit(this: *MatchedRoute) void { + if (this.query_string_map) |*map| { + map.deinit(); + } + if (this.needs_deinit) { + if (this.route.pathname.len > 0 and bun.Mimalloc.mi_check_owned(this.route.pathname.ptr)) { + bun.Mimalloc.mi_free(bun.constStrToU8(this.route.pathname).ptr); + } + + this.params_list_holder.deinit(bun.default_allocator); + this.params_list_holder = .{}; + } + + if (this.origin) |o| { + o.deref(); + } + + if (this.asset_prefix) |prefix| { + prefix.deref(); + } + + if (this.base_dir) |base| + base.deref(); + + bun.default_allocator.destroy(this); + } + + pub fn getFilePath( + this: *MatchedRoute, + globalThis: *JSC.JSGlobalObject, + ) callconv(.C) JSValue { + return ZigString.init(this.route.file_path) + .withEncoding() + .toValueGC(globalThis); + } + + pub fn finalize( + this: *MatchedRoute, + ) callconv(.C) void { + this.deinit(); + } + + pub fn getPathname(this: *MatchedRoute, globalThis: *JSC.JSGlobalObject) callconv(.C) JSValue { + return ZigString.init(this.route.pathname) + .withEncoding() + .toValueGC(globalThis); + } + + pub fn getRoute(this: *MatchedRoute, globalThis: *JSC.JSGlobalObject) callconv(.C) JSValue { + return ZigString.init(this.route.name) + .withEncoding() + .toValueGC(globalThis); + } + + const KindEnum = struct { + pub const exact = "exact"; + pub const catch_all = "catch-all"; + pub const optional_catch_all = "optional-catch-all"; + pub const dynamic = "dynamic"; + + // this is kinda stupid it should maybe just store it + pub fn init(name: string) ZigString { + if (strings.contains(name, "[[...")) { + return ZigString.init(optional_catch_all); + } else if (strings.contains(name, "[...")) { + return ZigString.init(catch_all); + } else if (strings.contains(name, "[")) { + return ZigString.init(dynamic); + } else { + return ZigString.init(exact); + } + } + }; + + pub fn getKind(this: *MatchedRoute, globalThis: *JSC.JSGlobalObject) callconv(.C) JSValue { + return KindEnum.init(this.route.name).toValue(globalThis); + } + + threadlocal var query_string_values_buf: [256]string = undefined; + threadlocal var query_string_value_refs_buf: [256]ZigString = undefined; + pub fn createQueryObject(ctx: js.JSContextRef, map: *QueryStringMap) callconv(.C) JSValue { + const QueryObjectCreator = struct { + query: *QueryStringMap, + pub fn create(this: *@This(), obj: *JSObject, global: *JSGlobalObject) void { + var iter = this.query.iter(); + while (iter.next(&query_string_values_buf)) |entry| { + const entry_name = entry.name; + var str = ZigString.init(entry_name).withEncoding(); + + std.debug.assert(entry.values.len > 0); + if (entry.values.len > 1) { + var values = query_string_value_refs_buf[0..entry.values.len]; + for (entry.values) |value, i| { + values[i] = ZigString.init(value).withEncoding(); + } + obj.putRecord(global, &str, values.ptr, values.len); + } else { + query_string_value_refs_buf[0] = ZigString.init(entry.values[0]).withEncoding(); + + obj.putRecord(global, &str, &query_string_value_refs_buf, 1); + } + } + } + }; + + var creator = QueryObjectCreator{ .query = map }; + + var value = JSObject.createWithInitializer(QueryObjectCreator, &creator, ctx, map.getNameCount()); + + return value; + } + + pub fn getScriptSrcString( + origin: []const u8, + comptime Writer: type, + writer: Writer, + file_path: string, + client_framework_enabled: bool, + ) void { + var entry_point_tempbuf: [bun.MAX_PATH_BYTES]u8 = undefined; + // We don't store the framework config including the client parts in the server + // instead, we just store a boolean saying whether we should generate this whenever the script is requested + // this is kind of bad. we should consider instead a way to inline the contents of the script. + if (client_framework_enabled) { + JSC.API.Bun.getPublicPath( + Bundler.ClientEntryPoint.generateEntryPointPath( + &entry_point_tempbuf, + Fs.PathName.init(file_path), + ), + origin, + Writer, + writer, + ); + } else { + JSC.API.Bun.getPublicPath(file_path, origin, Writer, writer); + } + } + + pub fn getScriptSrc( + this: *MatchedRoute, + globalThis: *JSC.JSGlobalObject, + ) callconv(.C) JSC.JSValue { + var buf: [bun.MAX_PATH_BYTES]u8 = undefined; + var stream = std.io.fixedBufferStream(&buf); + var writer = stream.writer(); + JSC.API.Bun.getPublicPathWithAssetPrefix( + this.route.file_path, + if (this.base_dir) |base_dir| base_dir.slice() else VirtualMachine.vm.bundler.fs.top_level_dir, + if (this.origin) |origin| URL.parse(origin.slice()) else URL{}, + if (this.asset_prefix) |prefix| prefix.slice() else "", + @TypeOf(&writer), + &writer, + ); + return ZigString.init(buf[0..writer.context.pos]) + .withEncoding() + .toValueGC(globalThis); + } + + pub fn getParams( + this: *MatchedRoute, + globalThis: *JSC.JSGlobalObject, + ) callconv(.C) JSC.JSValue { + if (this.route.params.len == 0) + return JSValue.createEmptyObject(globalThis, 0); + + if (this.param_map == null) { + this.param_map = QueryStringMap.initWithScanner( + globalThis.allocator(), + CombinedScanner.init( + "", + this.route.pathnameWithoutLeadingSlash(), + this.route.name, + this.route.params, + ), + ) catch + unreachable; + } + + return createQueryObject(globalThis, &this.param_map.?); + } + + pub fn getQuery( + this: *MatchedRoute, + globalThis: *JSC.JSGlobalObject, + ) callconv(.C) JSC.JSValue { + if (this.route.query_string.len == 0 and this.route.params.len == 0) { + return JSValue.createEmptyObject(globalThis, 0); + } else if (this.route.query_string.len == 0) { + return this.getParams(globalThis); + } + + if (this.query_string_map == null) { + if (this.route.params.len > 0) { + if (QueryStringMap.initWithScanner(globalThis.allocator(), CombinedScanner.init( + this.route.query_string, + this.route.pathnameWithoutLeadingSlash(), + this.route.name, + + this.route.params, + ))) |map| { + this.query_string_map = map; + } else |_| {} + } else { + if (QueryStringMap.init(globalThis.allocator(), this.route.query_string)) |map| { + this.query_string_map = map; + } else |_| {} + } + } + + // If it's still null, the query string has no names. + if (this.query_string_map) |*map| { + return createQueryObject(globalThis, map); + } + + return JSValue.createEmptyObject(globalThis, 0); + } +}; + +pub const deprecatedBunGlobalMatch = DeprecatedGlobalRouter.deprecatedBunGlobalMatch; diff --git a/src/bun.js/api/html_rewriter.zig b/src/bun.js/api/html_rewriter.zig index 18fb35b17..1dcb44f4f 100644 --- a/src/bun.js/api/html_rewriter.zig +++ b/src/bun.js/api/html_rewriter.zig @@ -1,6 +1,5 @@ const std = @import("std"); const Api = @import("../../api/schema.zig").Api; -const FilesystemRouter = @import("../../router.zig"); const http = @import("../../http.zig"); const JavaScript = @import("../javascript.zig"); const QueryStringMap = @import("../../url.zig").QueryStringMap; diff --git a/src/bun.js/api/router.zig b/src/bun.js/api/router.zig deleted file mode 100644 index 21e8536c5..000000000 --- a/src/bun.js/api/router.zig +++ /dev/null @@ -1,507 +0,0 @@ -const std = @import("std"); -const Api = @import("../../api/schema.zig").Api; -const FilesystemRouter = @import("../../router.zig"); -const http = @import("../../http.zig"); -const JavaScript = @import("../javascript.zig"); -const QueryStringMap = @import("../../url.zig").QueryStringMap; -const CombinedScanner = @import("../../url.zig").CombinedScanner; -const bun = @import("../../global.zig"); -const string = bun.string; -const JSC = @import("../../jsc.zig"); -const js = JSC.C; -const WebCore = @import("../webcore/response.zig"); -const Router = @This(); -const Bundler = @import("../../bundler.zig"); -const VirtualMachine = JavaScript.VirtualMachine; -const ScriptSrcStream = std.io.FixedBufferStream([]u8); -const ZigString = JSC.ZigString; -const Fs = @import("../../fs.zig"); -const Base = @import("../base.zig"); -const getAllocator = Base.getAllocator; -const JSObject = JSC.JSObject; -const JSError = Base.JSError; -const JSValue = JSC.JSValue; -const JSGlobalObject = JSC.JSGlobalObject; -const strings = @import("strings"); -const NewClass = Base.NewClass; -const To = Base.To; -const Request = WebCore.Request; -const d = Base.d; -const FetchEvent = WebCore.FetchEvent; -const URLPath = @import("../../http/url_path.zig"); -const URL = @import("../../url.zig").URL; - -route: *const FilesystemRouter.Match, -route_holder: FilesystemRouter.Match = undefined, -needs_deinit: bool = false, -query_string_map: ?QueryStringMap = null, -param_map: ?QueryStringMap = null, -params_list_holder: FilesystemRouter.Param.List = .{}, - -pub fn importRoute( - this: *Router, - ctx: js.JSContextRef, - _: js.JSObjectRef, - _: js.JSObjectRef, - _: []const js.JSValueRef, - _: js.ExceptionRef, -) js.JSObjectRef { - const prom = JSC.JSModuleLoader.loadAndEvaluateModule(ctx.ptr(), &ZigString.init(this.route.file_path)); - - VirtualMachine.vm.tick(); - - return prom.result(ctx.ptr().vm()).asRef(); -} - -pub fn match( - _: void, - ctx: js.JSContextRef, - _: js.JSObjectRef, - _: js.JSObjectRef, - arguments: []const js.JSValueRef, - exception: js.ExceptionRef, -) js.JSObjectRef { - if (arguments.len == 0) { - JSError(getAllocator(ctx), "Expected string, FetchEvent, or Request but there were no arguments", .{}, ctx, exception); - return null; - } - - const arg: JSC.JSValue = brk: { - if (FetchEvent.Class.isLoaded()) { - if (JSValue.as(JSValue.fromRef(arguments[0]), FetchEvent)) |fetch_event| { - if (fetch_event.request_context != null) { - return matchFetchEvent(ctx, fetch_event, exception); - } - - // When disconencted, we still have a copy of the request data in here - break :brk JSC.JSValue.fromRef(fetch_event.getRequest(ctx, null, undefined, null)); - } - } - break :brk JSC.JSValue.fromRef(arguments[0]); - }; - - var router = JavaScript.VirtualMachine.vm.bundler.router orelse { - JSError(getAllocator(ctx), "Bun.match needs a framework configured with routes", .{}, ctx, exception); - return null; - }; - - var path_: ?ZigString.Slice = null; - var pathname: string = ""; - defer { - if (path_) |path| { - path.deinit(); - } - } - - if (arg.isString()) { - var path_string = arg.getZigString(ctx.ptr()); - path_ = path_string.toSlice(bun.default_allocator); - var url = URL.parse(path_.?.slice()); - pathname = url.pathname; - } else if (arg.as(Request)) |req| { - var url = URL.parse(req.url); - pathname = url.pathname; - } - - if (path_ == null) { - JSError(getAllocator(ctx), "Expected string, FetchEvent, or Request", .{}, ctx, exception); - return null; - } - - const url_path = URLPath.parse(path_.?.slice()) catch { - JSError(getAllocator(ctx), "Could not parse URL path", .{}, ctx, exception); - return null; - }; - - var match_params_fallback = std.heap.stackFallback(1024, bun.default_allocator); - var match_params_allocator = match_params_fallback.get(); - var match_params = FilesystemRouter.Param.List{}; - match_params.ensureTotalCapacity(match_params_allocator, 16) catch unreachable; - var prev_allocator = router.routes.allocator; - router.routes.allocator = match_params_allocator; - defer router.routes.allocator = prev_allocator; - if (router.routes.matchPage("", url_path, &match_params)) |matched| { - var match_ = matched; - var params_list = match_.params.clone(bun.default_allocator) catch unreachable; - var instance = getAllocator(ctx).create(Router) catch unreachable; - - instance.* = Router{ - .route_holder = match_, - .route = undefined, - }; - instance.params_list_holder = params_list; - instance.route = &instance.route_holder; - instance.route_holder.params = &instance.params_list_holder; - - return Instance.make(ctx, instance); - } - // router.routes.matchPage - - return JSC.JSValue.jsNull().asObjectRef(); -} - -fn matchRequest( - ctx: js.JSContextRef, - request: *const Request, - _: js.ExceptionRef, -) js.JSObjectRef { - return createRouteObject(ctx, request.request_context); -} - -fn matchFetchEvent( - ctx: js.JSContextRef, - fetch_event: *const FetchEvent, - _: js.ExceptionRef, -) js.JSObjectRef { - return createRouteObject(ctx, fetch_event.request_context.?); -} - -fn createRouteObject(ctx: js.JSContextRef, req: *const http.RequestContext) js.JSValueRef { - const route = &(req.matched_route orelse { - return js.JSValueMakeNull(ctx); - }); - - return createRouteObjectFromMatch(ctx, route); -} - -fn createRouteObjectFromMatch( - ctx: js.JSContextRef, - route: *const FilesystemRouter.Match, -) js.JSValueRef { - var router = getAllocator(ctx).create(Router) catch unreachable; - router.* = Router{ - .route = route, - }; - - return Instance.make(ctx, router); -} - -pub const Instance = NewClass( - Router, - .{ - .name = "Route", - .read_only = true, - .ts = .{ - .class = d.ts.class{ - .tsdoc = - \\Route matched from the filesystem. - , - }, - }, - }, - .{ - .finalize = finalize, - .import = .{ - .rfn = importRoute, - .ts = d.ts{ - .@"return" = "Object", - .tsdoc = - \\Synchronously load & evaluate the file corresponding to the route. Returns the exports of the route. This is similar to `await import(route.filepath)`, except it's synchronous. It is recommended to use this function instead of `import`. - , - }, - }, - }, - .{ - .pathname = .{ - .get = getPathname, - .ro = true, - .ts = d.ts{ - .@"return" = "string", - .@"tsdoc" = "URL path as appears in a web browser's address bar", - }, - }, - - .filePath = .{ - .get = getFilePath, - .ro = true, - .ts = d.ts{ - .@"return" = "string", - .tsdoc = - \\Project-relative filesystem path to the route file. - , - }, - }, - .scriptSrc = .{ - .get = getScriptSrc, - .ro = true, - .ts = d.ts{ - .@"return" = "string", - .tsdoc = - \\src attribute of the script tag that loads the route. - , - }, - }, - .kind = .{ - .get = getKind, - .ro = true, - .ts = d.ts{ - .@"return" = "\"exact\" | \"dynamic\" | \"catch-all\" | \"optional-catch-all\"", - }, - }, - .name = .{ - .get = getRoute, - .ro = true, - .ts = d.ts{ - .@"return" = "string", - .tsdoc = - \\Route name - \\@example - \\`"blog/posts/[id]"` - \\`"blog/posts/[id]/[[...slug]]"` - \\`"blog"` - , - }, - }, - .query = .{ - .get = getQuery, - .ro = true, - .ts = d.ts{ - .@"return" = "Record<string, string | string[]>", - .tsdoc = - \\Route parameters & parsed query string values as a key-value object - \\ - \\@example - \\```js - \\console.assert(router.query.id === "123"); - \\console.assert(router.pathname === "/blog/posts/123"); - \\console.assert(router.route === "blog/posts/[id]"); - \\``` - , - }, - }, - .params = .{ - .get = getParams, - .ro = true, - .ts = d.ts{ - .@"return" = "Record<string, string | string[]>", - .tsdoc = - \\Route parameters as a key-value object - \\ - \\@example - \\```js - \\console.assert(router.query.id === "123"); - \\console.assert(router.pathname === "/blog/posts/123"); - \\console.assert(router.route === "blog/posts/[id]"); - \\``` - , - }, - }, - }, -); - -pub fn getFilePath( - this: *Router, - ctx: js.JSContextRef, - _: js.JSObjectRef, - _: js.JSStringRef, - _: js.ExceptionRef, -) js.JSValueRef { - return ZigString.init(this.route.file_path) - .withEncoding() - .toValueGC(ctx.ptr()).asRef(); -} - -pub fn finalize( - this: *Router, -) void { - if (this.query_string_map) |*map| { - map.deinit(); - } - - if (this.needs_deinit) { - this.params_list_holder.deinit(bun.default_allocator); - this.params_list_holder = .{}; - this.needs_deinit = false; - } - - bun.default_allocator.destroy(this); -} - -pub fn getPathname( - this: *Router, - ctx: js.JSContextRef, - _: js.JSObjectRef, - _: js.JSStringRef, - _: js.ExceptionRef, -) js.JSValueRef { - return ZigString.init(this.route.pathname) - .withEncoding() - .toValueGC(ctx.ptr()).asRef(); -} - -pub fn getRoute( - this: *Router, - ctx: js.JSContextRef, - _: js.JSObjectRef, - _: js.JSStringRef, - _: js.ExceptionRef, -) js.JSValueRef { - return ZigString.init(this.route.name) - .withEncoding() - .toValueGC(ctx.ptr()).asRef(); -} - -const KindEnum = struct { - pub const exact = "exact"; - pub const catch_all = "catch-all"; - pub const optional_catch_all = "optional-catch-all"; - pub const dynamic = "dynamic"; - - // this is kinda stupid it should maybe just store it - pub fn init(name: string) ZigString { - if (strings.contains(name, "[[...")) { - return ZigString.init(optional_catch_all); - } else if (strings.contains(name, "[...")) { - return ZigString.init(catch_all); - } else if (strings.contains(name, "[")) { - return ZigString.init(dynamic); - } else { - return ZigString.init(exact); - } - } -}; - -pub fn getKind( - this: *Router, - ctx: js.JSContextRef, - _: js.JSObjectRef, - _: js.JSStringRef, - _: js.ExceptionRef, -) js.JSValueRef { - return KindEnum.init(this.route.name).toValue(ctx.ptr()).asRef(); -} - -threadlocal var query_string_values_buf: [256]string = undefined; -threadlocal var query_string_value_refs_buf: [256]ZigString = undefined; -pub fn createQueryObject(ctx: js.JSContextRef, map: *QueryStringMap, _: js.ExceptionRef) callconv(.C) js.JSValueRef { - const QueryObjectCreator = struct { - query: *QueryStringMap, - pub fn create(this: *@This(), obj: *JSObject, global: *JSGlobalObject) void { - var iter = this.query.iter(); - var str: ZigString = undefined; - while (iter.next(&query_string_values_buf)) |entry| { - str = ZigString.init(entry.name); - - std.debug.assert(entry.values.len > 0); - if (entry.values.len > 1) { - var values = query_string_value_refs_buf[0..entry.values.len]; - for (entry.values) |value, i| { - values[i] = ZigString.init(value); - } - obj.putRecord(global, &str, values.ptr, values.len); - } else { - query_string_value_refs_buf[0] = ZigString.init(entry.values[0]); - - obj.putRecord(global, &str, &query_string_value_refs_buf, 1); - } - } - } - }; - - var creator = QueryObjectCreator{ .query = map }; - - var value = JSObject.createWithInitializer(QueryObjectCreator, &creator, ctx.ptr(), map.getNameCount()); - - return value.asRef(); -} - -pub fn getScriptSrcString( - comptime Writer: type, - writer: Writer, - file_path: string, - client_framework_enabled: bool, -) void { - var entry_point_tempbuf: [bun.MAX_PATH_BYTES]u8 = undefined; - // We don't store the framework config including the client parts in the server - // instead, we just store a boolean saying whether we should generate this whenever the script is requested - // this is kind of bad. we should consider instead a way to inline the contents of the script. - if (client_framework_enabled) { - JSC.API.Bun.getPublicPath( - Bundler.ClientEntryPoint.generateEntryPointPath( - &entry_point_tempbuf, - Fs.PathName.init(file_path), - ), - VirtualMachine.vm.origin, - Writer, - writer, - ); - } else { - JSC.API.Bun.getPublicPath(file_path, VirtualMachine.vm.origin, Writer, writer); - } -} - -pub fn getScriptSrc( - this: *Router, - ctx: js.JSContextRef, - _: js.JSObjectRef, - _: js.JSStringRef, - _: js.ExceptionRef, -) js.JSValueRef { - var script_src_buffer = std.ArrayList(u8).init(bun.default_allocator); - - var writer = script_src_buffer.writer(); - getScriptSrcString(@TypeOf(&writer), &writer, this.route.file_path, this.route.client_framework_enabled); - - return ZigString.init(script_src_buffer.toOwnedSlice()).toExternalValue(ctx.ptr()).asObjectRef(); -} - -pub fn getParams( - this: *Router, - ctx: js.JSContextRef, - _: js.JSObjectRef, - _: js.JSStringRef, - exception: js.ExceptionRef, -) js.JSValueRef { - if (this.param_map == null) { - if (this.route.params.len > 0) { - if (QueryStringMap.initWithScanner(getAllocator(ctx), CombinedScanner.init( - "", - this.route.pathnameWithoutLeadingSlash(), - this.route.name, - this.route.params, - ))) |map| { - this.param_map = map; - } else |_| {} - } - } - - // If it's still null, there are no params - if (this.param_map) |*map| { - return createQueryObject(ctx, map, exception); - } else { - return JSValue.createEmptyObject(ctx.ptr(), 0).asRef(); - } -} - -pub fn getQuery( - this: *Router, - ctx: js.JSContextRef, - _: js.JSObjectRef, - _: js.JSStringRef, - exception: js.ExceptionRef, -) js.JSValueRef { - if (this.query_string_map == null) { - if (this.route.params.len > 0) { - if (QueryStringMap.initWithScanner(getAllocator(ctx), CombinedScanner.init( - this.route.query_string, - this.route.pathnameWithoutLeadingSlash(), - this.route.name, - - this.route.params, - ))) |map| { - this.query_string_map = map; - } else |_| {} - } else if (this.route.query_string.len > 0) { - if (QueryStringMap.init(getAllocator(ctx), this.route.query_string)) |map| { - this.query_string_map = map; - } else |_| {} - } - } - - // If it's still null, the query string has no names. - if (this.query_string_map) |*map| { - return createQueryObject(ctx, map, exception); - } else { - return JSValue.createEmptyObject(ctx.ptr(), 0).asRef(); - } -} diff --git a/src/bun.js/api/server.zig b/src/bun.js/api/server.zig index 246f83515..531d4830b 100644 --- a/src/bun.js/api/server.zig +++ b/src/bun.js/api/server.zig @@ -31,7 +31,6 @@ const ImportKind = ast.ImportKind; const Analytics = @import("../../analytics/analytics_thread.zig"); const ZigString = @import("javascript_core").ZigString; const Runtime = @import("../../runtime.zig"); -const Router = @import("./router.zig"); const ImportRecord = ast.ImportRecord; const DotEnv = @import("../../env_loader.zig"); const ParseResult = @import("../../bundler.zig").ParseResult; @@ -3949,7 +3948,7 @@ pub fn NewServer(comptime ssl_enabled_: bool, comptime debug_mode_: bool) type { _: js.ExceptionRef, ) js.JSObjectRef { var globalThis = ctx.ptr(); - + JSC.markBinding(@src()); if (arguments.len == 0) { const fetch_error = WebCore.Fetch.fetch_error_no_args; return JSPromise.rejectedPromiseValue(globalThis, ZigString.init(fetch_error).toErrorInstance(globalThis)).asRef(); @@ -4497,7 +4496,7 @@ pub fn NewServer(comptime ssl_enabled_: bool, comptime debug_mode_: bool) type { this.config.hostname; this.ref(); - + this.vm.autoGarbageCollect(); this.app.listenWithConfig(*ThisServer, this, onListen, .{ .port = this.config.port, .host = host, diff --git a/src/bun.js/api/sockets.classes.ts b/src/bun.js/api/sockets.classes.ts index 0c72d1d8d..87f96fd88 100644 --- a/src/bun.js/api/sockets.classes.ts +++ b/src/bun.js/api/sockets.classes.ts @@ -4,6 +4,8 @@ function generate(ssl) { return define({ name: ssl ? "TCPSocket" : "TLSSocket", JSType: "0b11101110", + hasPendingActivity: true, + noConstructor: true, proto: { write: { fn: "write", @@ -83,6 +85,7 @@ export default [ generate(false), define({ name: "Listener", + noConstructor: true, JSType: "0b11101110", proto: { stop: { diff --git a/src/bun.js/api/transpiler.zig b/src/bun.js/api/transpiler.zig index c48f1f093..cd47e1997 100644 --- a/src/bun.js/api/transpiler.zig +++ b/src/bun.js/api/transpiler.zig @@ -1,6 +1,5 @@ const std = @import("std"); const Api = @import("../../api/schema.zig").Api; -const FilesystemRouter = @import("../../router.zig"); const http = @import("../../http.zig"); const JavaScript = @import("../javascript.zig"); const QueryStringMap = @import("../../url.zig").QueryStringMap; @@ -224,7 +223,7 @@ pub const TransformTask = struct { } } - pub fn then(this: *TransformTask, promise: *JSC.JSInternalPromise) void { + pub fn then(this: *TransformTask, promise: *JSC.JSPromise) void { if (this.log.hasAny() or this.err != null) { const error_value: JSValue = brk: { if (this.err) |err| { @@ -254,7 +253,7 @@ pub const TransformTask = struct { this.deinit(); } - noinline fn finish(code: ZigString, global: *JSGlobalObject, promise: *JSC.JSInternalPromise) void { + noinline fn finish(code: ZigString, global: *JSGlobalObject, promise: *JSC.JSPromise) void { promise.resolve(global, code.toValueGC(global)); } @@ -606,7 +605,7 @@ fn transformOptionsFromJSC(ctx: JSC.C.JSContextRef, temp_allocator: std.mem.Allo var length_iter = iter; while (length_iter.next()) |value| { if (value.isString()) { - const length = value.getLengthOfArray(globalThis); + const length = @truncate(u32, value.getLengthOfArray(globalThis)); string_count += @as(u32, @boolToInt(length > 0)); total_name_buf_len += length; } @@ -986,7 +985,7 @@ pub fn transform( var task = TransformTask.create(this, if (code_holder == .string) arguments[0] else null, ctx.ptr(), ZigString.init(code), loader orelse this.transpiler_options.default_loader) catch return null; task.schedule(); - return task.promise.asObjectRef(); + return task.promise.value().asObjectRef(); } pub fn transformSync( diff --git a/src/bun.js/base.zig b/src/bun.js/base.zig index 46ffd4fd8..8fb1d544d 100644 --- a/src/bun.js/base.zig +++ b/src/bun.js/base.zig @@ -19,7 +19,7 @@ const Test = @import("./test/jest.zig"); const Fetch = WebCore.Fetch; const Response = WebCore.Response; const Request = WebCore.Request; -const Router = @import("./api/router.zig"); +const Router = @import("./api/filesystem_router.zig"); const FetchEvent = WebCore.FetchEvent; const IdentityContext = @import("../identity_context.zig").IdentityContext; const uws = @import("uws"); diff --git a/src/bun.js/bindings/JSSink.cpp b/src/bun.js/bindings/JSSink.cpp index a342793f0..ed3b6a5ac 100644 --- a/src/bun.js/bindings/JSSink.cpp +++ b/src/bun.js/bindings/JSSink.cpp @@ -1,6 +1,6 @@ // AUTO-GENERATED FILE. DO NOT EDIT. -// Generated by 'make generate-sink' at 2022-11-13T22:44:00.280Z +// Generated by 'make generate-sink' at 2022-11-20T12:51:04.404Z // To regenerate this file, run: // // make generate-sink @@ -54,18 +54,12 @@ #include "JavaScriptCore/Weak.h" #include "JavaScriptCore/WeakInlines.h" - - namespace WebCore { using namespace JSC; - - - - -JSC_DEFINE_HOST_FUNCTION(functionStartDirectStream, (JSC::JSGlobalObject * lexicalGlobalObject, JSC::CallFrame *callFrame)) +JSC_DEFINE_HOST_FUNCTION(functionStartDirectStream, (JSC::JSGlobalObject * lexicalGlobalObject, JSC::CallFrame* callFrame)) { - + auto& vm = lexicalGlobalObject->vm(); auto scope = DECLARE_THROW_SCOPE(vm); Zig::GlobalObject* globalObject = reinterpret_cast<Zig::GlobalObject*>(lexicalGlobalObject); @@ -86,12 +80,10 @@ JSC_DEFINE_HOST_FUNCTION(functionStartDirectStream, (JSC::JSGlobalObject * lexic onClose = JSC::jsUndefined(); } - JSC::JSFunction *onPullFunction = JSC::jsDynamicCast<JSC::JSFunction*>(onPull); - JSC::JSFunction *onCloseFunction = JSC::jsDynamicCast<JSC::JSFunction*>(onClose); - - + JSC::JSFunction* onPullFunction = JSC::jsDynamicCast<JSC::JSFunction*>(onPull); + JSC::JSFunction* onCloseFunction = JSC::jsDynamicCast<JSC::JSFunction*>(onClose); - if (WebCore::JSReadableArrayBufferSinkController* ArrayBufferSinkController = JSC::jsDynamicCast<WebCore::JSReadableArrayBufferSinkController*>(callFrame->thisValue())) { + if (WebCore::JSReadableArrayBufferSinkController* ArrayBufferSinkController = JSC::jsDynamicCast<WebCore::JSReadableArrayBufferSinkController*>(callFrame->thisValue())) { if (ArrayBufferSinkController->wrapped() == nullptr) { scope.throwException(globalObject, JSC::createTypeError(globalObject, "Cannot start stream with closed controller"_s)); return JSC::JSValue::encode(JSC::jsUndefined()); @@ -100,7 +92,6 @@ JSC_DEFINE_HOST_FUNCTION(functionStartDirectStream, (JSC::JSGlobalObject * lexic ArrayBufferSinkController->start(globalObject, readableStream, onPullFunction, onCloseFunction); } - else if (WebCore::JSReadableFileSinkController* FileSinkController = JSC::jsDynamicCast<WebCore::JSReadableFileSinkController*>(callFrame->thisValue())) { if (FileSinkController->wrapped() == nullptr) { scope.throwException(globalObject, JSC::createTypeError(globalObject, "Cannot start stream with closed controller"_s)); @@ -110,7 +101,6 @@ JSC_DEFINE_HOST_FUNCTION(functionStartDirectStream, (JSC::JSGlobalObject * lexic FileSinkController->start(globalObject, readableStream, onPullFunction, onCloseFunction); } - else if (WebCore::JSReadableHTTPResponseSinkController* HTTPResponseSinkController = JSC::jsDynamicCast<WebCore::JSReadableHTTPResponseSinkController*>(callFrame->thisValue())) { if (HTTPResponseSinkController->wrapped() == nullptr) { scope.throwException(globalObject, JSC::createTypeError(globalObject, "Cannot start stream with closed controller"_s)); @@ -120,7 +110,6 @@ JSC_DEFINE_HOST_FUNCTION(functionStartDirectStream, (JSC::JSGlobalObject * lexic HTTPResponseSinkController->start(globalObject, readableStream, onPullFunction, onCloseFunction); } - else if (WebCore::JSReadableHTTPSResponseSinkController* HTTPSResponseSinkController = JSC::jsDynamicCast<WebCore::JSReadableHTTPSResponseSinkController*>(callFrame->thisValue())) { if (HTTPSResponseSinkController->wrapped() == nullptr) { scope.throwException(globalObject, JSC::createTypeError(globalObject, "Cannot start stream with closed controller"_s)); @@ -146,11 +135,10 @@ JSC_DEFINE_CUSTOM_GETTER(functionArrayBufferSink__getter, (JSC::JSGlobalObject * return JSC::JSValue::encode(globalObject->ArrayBufferSink()); } - JSC_DECLARE_HOST_FUNCTION(JSReadableArrayBufferSinkController__close); -JSC_DEFINE_HOST_FUNCTION(JSReadableArrayBufferSinkController__close, (JSC::JSGlobalObject * lexicalGlobalObject, JSC::CallFrame *callFrame)) +JSC_DEFINE_HOST_FUNCTION(JSReadableArrayBufferSinkController__close, (JSC::JSGlobalObject * lexicalGlobalObject, JSC::CallFrame* callFrame)) { - + auto& vm = lexicalGlobalObject->vm(); auto scope = DECLARE_THROW_SCOPE(vm); Zig::GlobalObject* globalObject = reinterpret_cast<Zig::GlobalObject*>(lexicalGlobalObject); @@ -160,22 +148,20 @@ JSC_DEFINE_HOST_FUNCTION(JSReadableArrayBufferSinkController__close, (JSC::JSGlo return JSC::JSValue::encode(JSC::jsUndefined()); } - void *ptr = controller->wrapped(); + void* ptr = controller->wrapped(); if (ptr == nullptr) { return JSC::JSValue::encode(JSC::jsUndefined()); } controller->detach(); ArrayBufferSink__close(lexicalGlobalObject, ptr); - // Release the controller right before close. - controller->m_hasPendingActivity = false; return JSC::JSValue::encode(JSC::jsUndefined()); } JSC_DECLARE_HOST_FUNCTION(JSReadableArrayBufferSinkController__end); -JSC_DEFINE_HOST_FUNCTION(JSReadableArrayBufferSinkController__end, (JSC::JSGlobalObject * lexicalGlobalObject, JSC::CallFrame *callFrame)) +JSC_DEFINE_HOST_FUNCTION(JSReadableArrayBufferSinkController__end, (JSC::JSGlobalObject * lexicalGlobalObject, JSC::CallFrame* callFrame)) { - + auto& vm = lexicalGlobalObject->vm(); auto scope = DECLARE_THROW_SCOPE(vm); Zig::GlobalObject* globalObject = reinterpret_cast<Zig::GlobalObject*>(lexicalGlobalObject); @@ -185,7 +171,7 @@ JSC_DEFINE_HOST_FUNCTION(JSReadableArrayBufferSinkController__end, (JSC::JSGloba return JSC::JSValue::encode(JSC::jsUndefined()); } - void *ptr = controller->wrapped(); + void* ptr = controller->wrapped(); if (ptr == nullptr) { return JSC::JSValue::encode(JSC::jsUndefined()); } @@ -194,11 +180,10 @@ JSC_DEFINE_HOST_FUNCTION(JSReadableArrayBufferSinkController__end, (JSC::JSGloba return ArrayBufferSink__endWithSink(ptr, lexicalGlobalObject); } - JSC_DECLARE_HOST_FUNCTION(ArrayBufferSink__doClose); -JSC_DEFINE_HOST_FUNCTION(ArrayBufferSink__doClose, (JSC::JSGlobalObject * lexicalGlobalObject, JSC::CallFrame *callFrame)) +JSC_DEFINE_HOST_FUNCTION(ArrayBufferSink__doClose, (JSC::JSGlobalObject * lexicalGlobalObject, JSC::CallFrame* callFrame)) { - + auto& vm = lexicalGlobalObject->vm(); auto scope = DECLARE_THROW_SCOPE(vm); Zig::GlobalObject* globalObject = reinterpret_cast<Zig::GlobalObject*>(lexicalGlobalObject); @@ -208,7 +193,7 @@ JSC_DEFINE_HOST_FUNCTION(ArrayBufferSink__doClose, (JSC::JSGlobalObject * lexica return JSC::JSValue::encode(JSC::jsUndefined()); } - void *ptr = sink->wrapped(); + void* ptr = sink->wrapped(); if (ptr == nullptr) { return JSC::JSValue::encode(JSC::jsUndefined()); } @@ -218,8 +203,6 @@ JSC_DEFINE_HOST_FUNCTION(ArrayBufferSink__doClose, (JSC::JSGlobalObject * lexica return JSC::JSValue::encode(JSC::jsUndefined()); } - - JSC_DEFINE_CUSTOM_GETTER(functionFileSink__getter, (JSC::JSGlobalObject * lexicalGlobalObject, JSC::EncodedJSValue thisValue, JSC::PropertyName)) { auto& vm = lexicalGlobalObject->vm(); @@ -228,11 +211,10 @@ JSC_DEFINE_CUSTOM_GETTER(functionFileSink__getter, (JSC::JSGlobalObject * lexica return JSC::JSValue::encode(globalObject->FileSink()); } - JSC_DECLARE_HOST_FUNCTION(JSReadableFileSinkController__close); -JSC_DEFINE_HOST_FUNCTION(JSReadableFileSinkController__close, (JSC::JSGlobalObject * lexicalGlobalObject, JSC::CallFrame *callFrame)) +JSC_DEFINE_HOST_FUNCTION(JSReadableFileSinkController__close, (JSC::JSGlobalObject * lexicalGlobalObject, JSC::CallFrame* callFrame)) { - + auto& vm = lexicalGlobalObject->vm(); auto scope = DECLARE_THROW_SCOPE(vm); Zig::GlobalObject* globalObject = reinterpret_cast<Zig::GlobalObject*>(lexicalGlobalObject); @@ -242,22 +224,20 @@ JSC_DEFINE_HOST_FUNCTION(JSReadableFileSinkController__close, (JSC::JSGlobalObje return JSC::JSValue::encode(JSC::jsUndefined()); } - void *ptr = controller->wrapped(); + void* ptr = controller->wrapped(); if (ptr == nullptr) { return JSC::JSValue::encode(JSC::jsUndefined()); } controller->detach(); FileSink__close(lexicalGlobalObject, ptr); - // Release the controller right before close. - controller->m_hasPendingActivity = false; return JSC::JSValue::encode(JSC::jsUndefined()); } JSC_DECLARE_HOST_FUNCTION(JSReadableFileSinkController__end); -JSC_DEFINE_HOST_FUNCTION(JSReadableFileSinkController__end, (JSC::JSGlobalObject * lexicalGlobalObject, JSC::CallFrame *callFrame)) +JSC_DEFINE_HOST_FUNCTION(JSReadableFileSinkController__end, (JSC::JSGlobalObject * lexicalGlobalObject, JSC::CallFrame* callFrame)) { - + auto& vm = lexicalGlobalObject->vm(); auto scope = DECLARE_THROW_SCOPE(vm); Zig::GlobalObject* globalObject = reinterpret_cast<Zig::GlobalObject*>(lexicalGlobalObject); @@ -267,7 +247,7 @@ JSC_DEFINE_HOST_FUNCTION(JSReadableFileSinkController__end, (JSC::JSGlobalObject return JSC::JSValue::encode(JSC::jsUndefined()); } - void *ptr = controller->wrapped(); + void* ptr = controller->wrapped(); if (ptr == nullptr) { return JSC::JSValue::encode(JSC::jsUndefined()); } @@ -276,11 +256,10 @@ JSC_DEFINE_HOST_FUNCTION(JSReadableFileSinkController__end, (JSC::JSGlobalObject return FileSink__endWithSink(ptr, lexicalGlobalObject); } - JSC_DECLARE_HOST_FUNCTION(FileSink__doClose); -JSC_DEFINE_HOST_FUNCTION(FileSink__doClose, (JSC::JSGlobalObject * lexicalGlobalObject, JSC::CallFrame *callFrame)) +JSC_DEFINE_HOST_FUNCTION(FileSink__doClose, (JSC::JSGlobalObject * lexicalGlobalObject, JSC::CallFrame* callFrame)) { - + auto& vm = lexicalGlobalObject->vm(); auto scope = DECLARE_THROW_SCOPE(vm); Zig::GlobalObject* globalObject = reinterpret_cast<Zig::GlobalObject*>(lexicalGlobalObject); @@ -290,7 +269,7 @@ JSC_DEFINE_HOST_FUNCTION(FileSink__doClose, (JSC::JSGlobalObject * lexicalGlobal return JSC::JSValue::encode(JSC::jsUndefined()); } - void *ptr = sink->wrapped(); + void* ptr = sink->wrapped(); if (ptr == nullptr) { return JSC::JSValue::encode(JSC::jsUndefined()); } @@ -300,8 +279,6 @@ JSC_DEFINE_HOST_FUNCTION(FileSink__doClose, (JSC::JSGlobalObject * lexicalGlobal return JSC::JSValue::encode(JSC::jsUndefined()); } - - JSC_DEFINE_CUSTOM_GETTER(functionHTTPResponseSink__getter, (JSC::JSGlobalObject * lexicalGlobalObject, JSC::EncodedJSValue thisValue, JSC::PropertyName)) { auto& vm = lexicalGlobalObject->vm(); @@ -310,11 +287,10 @@ JSC_DEFINE_CUSTOM_GETTER(functionHTTPResponseSink__getter, (JSC::JSGlobalObject return JSC::JSValue::encode(globalObject->HTTPResponseSink()); } - JSC_DECLARE_HOST_FUNCTION(JSReadableHTTPResponseSinkController__close); -JSC_DEFINE_HOST_FUNCTION(JSReadableHTTPResponseSinkController__close, (JSC::JSGlobalObject * lexicalGlobalObject, JSC::CallFrame *callFrame)) +JSC_DEFINE_HOST_FUNCTION(JSReadableHTTPResponseSinkController__close, (JSC::JSGlobalObject * lexicalGlobalObject, JSC::CallFrame* callFrame)) { - + auto& vm = lexicalGlobalObject->vm(); auto scope = DECLARE_THROW_SCOPE(vm); Zig::GlobalObject* globalObject = reinterpret_cast<Zig::GlobalObject*>(lexicalGlobalObject); @@ -324,22 +300,20 @@ JSC_DEFINE_HOST_FUNCTION(JSReadableHTTPResponseSinkController__close, (JSC::JSGl return JSC::JSValue::encode(JSC::jsUndefined()); } - void *ptr = controller->wrapped(); + void* ptr = controller->wrapped(); if (ptr == nullptr) { return JSC::JSValue::encode(JSC::jsUndefined()); } controller->detach(); HTTPResponseSink__close(lexicalGlobalObject, ptr); - // Release the controller right before close. - controller->m_hasPendingActivity = false; return JSC::JSValue::encode(JSC::jsUndefined()); } JSC_DECLARE_HOST_FUNCTION(JSReadableHTTPResponseSinkController__end); -JSC_DEFINE_HOST_FUNCTION(JSReadableHTTPResponseSinkController__end, (JSC::JSGlobalObject * lexicalGlobalObject, JSC::CallFrame *callFrame)) +JSC_DEFINE_HOST_FUNCTION(JSReadableHTTPResponseSinkController__end, (JSC::JSGlobalObject * lexicalGlobalObject, JSC::CallFrame* callFrame)) { - + auto& vm = lexicalGlobalObject->vm(); auto scope = DECLARE_THROW_SCOPE(vm); Zig::GlobalObject* globalObject = reinterpret_cast<Zig::GlobalObject*>(lexicalGlobalObject); @@ -349,7 +323,7 @@ JSC_DEFINE_HOST_FUNCTION(JSReadableHTTPResponseSinkController__end, (JSC::JSGlob return JSC::JSValue::encode(JSC::jsUndefined()); } - void *ptr = controller->wrapped(); + void* ptr = controller->wrapped(); if (ptr == nullptr) { return JSC::JSValue::encode(JSC::jsUndefined()); } @@ -358,11 +332,10 @@ JSC_DEFINE_HOST_FUNCTION(JSReadableHTTPResponseSinkController__end, (JSC::JSGlob return HTTPResponseSink__endWithSink(ptr, lexicalGlobalObject); } - JSC_DECLARE_HOST_FUNCTION(HTTPResponseSink__doClose); -JSC_DEFINE_HOST_FUNCTION(HTTPResponseSink__doClose, (JSC::JSGlobalObject * lexicalGlobalObject, JSC::CallFrame *callFrame)) +JSC_DEFINE_HOST_FUNCTION(HTTPResponseSink__doClose, (JSC::JSGlobalObject * lexicalGlobalObject, JSC::CallFrame* callFrame)) { - + auto& vm = lexicalGlobalObject->vm(); auto scope = DECLARE_THROW_SCOPE(vm); Zig::GlobalObject* globalObject = reinterpret_cast<Zig::GlobalObject*>(lexicalGlobalObject); @@ -372,7 +345,7 @@ JSC_DEFINE_HOST_FUNCTION(HTTPResponseSink__doClose, (JSC::JSGlobalObject * lexic return JSC::JSValue::encode(JSC::jsUndefined()); } - void *ptr = sink->wrapped(); + void* ptr = sink->wrapped(); if (ptr == nullptr) { return JSC::JSValue::encode(JSC::jsUndefined()); } @@ -382,8 +355,6 @@ JSC_DEFINE_HOST_FUNCTION(HTTPResponseSink__doClose, (JSC::JSGlobalObject * lexic return JSC::JSValue::encode(JSC::jsUndefined()); } - - JSC_DEFINE_CUSTOM_GETTER(functionHTTPSResponseSink__getter, (JSC::JSGlobalObject * lexicalGlobalObject, JSC::EncodedJSValue thisValue, JSC::PropertyName)) { auto& vm = lexicalGlobalObject->vm(); @@ -392,11 +363,10 @@ JSC_DEFINE_CUSTOM_GETTER(functionHTTPSResponseSink__getter, (JSC::JSGlobalObject return JSC::JSValue::encode(globalObject->HTTPSResponseSink()); } - JSC_DECLARE_HOST_FUNCTION(JSReadableHTTPSResponseSinkController__close); -JSC_DEFINE_HOST_FUNCTION(JSReadableHTTPSResponseSinkController__close, (JSC::JSGlobalObject * lexicalGlobalObject, JSC::CallFrame *callFrame)) +JSC_DEFINE_HOST_FUNCTION(JSReadableHTTPSResponseSinkController__close, (JSC::JSGlobalObject * lexicalGlobalObject, JSC::CallFrame* callFrame)) { - + auto& vm = lexicalGlobalObject->vm(); auto scope = DECLARE_THROW_SCOPE(vm); Zig::GlobalObject* globalObject = reinterpret_cast<Zig::GlobalObject*>(lexicalGlobalObject); @@ -406,22 +376,20 @@ JSC_DEFINE_HOST_FUNCTION(JSReadableHTTPSResponseSinkController__close, (JSC::JSG return JSC::JSValue::encode(JSC::jsUndefined()); } - void *ptr = controller->wrapped(); + void* ptr = controller->wrapped(); if (ptr == nullptr) { return JSC::JSValue::encode(JSC::jsUndefined()); } controller->detach(); HTTPSResponseSink__close(lexicalGlobalObject, ptr); - // Release the controller right before close. - controller->m_hasPendingActivity = false; return JSC::JSValue::encode(JSC::jsUndefined()); } JSC_DECLARE_HOST_FUNCTION(JSReadableHTTPSResponseSinkController__end); -JSC_DEFINE_HOST_FUNCTION(JSReadableHTTPSResponseSinkController__end, (JSC::JSGlobalObject * lexicalGlobalObject, JSC::CallFrame *callFrame)) +JSC_DEFINE_HOST_FUNCTION(JSReadableHTTPSResponseSinkController__end, (JSC::JSGlobalObject * lexicalGlobalObject, JSC::CallFrame* callFrame)) { - + auto& vm = lexicalGlobalObject->vm(); auto scope = DECLARE_THROW_SCOPE(vm); Zig::GlobalObject* globalObject = reinterpret_cast<Zig::GlobalObject*>(lexicalGlobalObject); @@ -431,7 +399,7 @@ JSC_DEFINE_HOST_FUNCTION(JSReadableHTTPSResponseSinkController__end, (JSC::JSGlo return JSC::JSValue::encode(JSC::jsUndefined()); } - void *ptr = controller->wrapped(); + void* ptr = controller->wrapped(); if (ptr == nullptr) { return JSC::JSValue::encode(JSC::jsUndefined()); } @@ -440,11 +408,10 @@ JSC_DEFINE_HOST_FUNCTION(JSReadableHTTPSResponseSinkController__end, (JSC::JSGlo return HTTPSResponseSink__endWithSink(ptr, lexicalGlobalObject); } - JSC_DECLARE_HOST_FUNCTION(HTTPSResponseSink__doClose); -JSC_DEFINE_HOST_FUNCTION(HTTPSResponseSink__doClose, (JSC::JSGlobalObject * lexicalGlobalObject, JSC::CallFrame *callFrame)) +JSC_DEFINE_HOST_FUNCTION(HTTPSResponseSink__doClose, (JSC::JSGlobalObject * lexicalGlobalObject, JSC::CallFrame* callFrame)) { - + auto& vm = lexicalGlobalObject->vm(); auto scope = DECLARE_THROW_SCOPE(vm); Zig::GlobalObject* globalObject = reinterpret_cast<Zig::GlobalObject*>(lexicalGlobalObject); @@ -454,7 +421,7 @@ JSC_DEFINE_HOST_FUNCTION(HTTPSResponseSink__doClose, (JSC::JSGlobalObject * lexi return JSC::JSValue::encode(JSC::jsUndefined()); } - void *ptr = sink->wrapped(); + void* ptr = sink->wrapped(); if (ptr == nullptr) { return JSC::JSValue::encode(JSC::jsUndefined()); } @@ -464,10 +431,8 @@ JSC_DEFINE_HOST_FUNCTION(HTTPSResponseSink__doClose, (JSC::JSGlobalObject * lexi return JSC::JSValue::encode(JSC::jsUndefined()); } - - #include "JSSinkLookupTable.h" - + /* Source for JSArrayBufferSinkPrototypeTableValues.lut.h @begin JSArrayBufferSinkPrototypeTable close ArrayBufferSink__doClose ReadOnly|DontDelete|Function 0 @@ -478,7 +443,6 @@ JSC_DEFINE_HOST_FUNCTION(HTTPSResponseSink__doClose, (JSC::JSGlobalObject * lexi @end */ - /* Source for JSReadableArrayBufferSinkControllerPrototypeTableValues.lut.h @begin JSReadableArrayBufferSinkControllerPrototypeTable close JSReadableArrayBufferSinkController__close ReadOnly|DontDelete|Function 0 @@ -489,7 +453,6 @@ JSC_DEFINE_HOST_FUNCTION(HTTPSResponseSink__doClose, (JSC::JSGlobalObject * lexi @end */ - /* Source for JSFileSinkPrototypeTableValues.lut.h @begin JSFileSinkPrototypeTable close FileSink__doClose ReadOnly|DontDelete|Function 0 @@ -500,7 +463,6 @@ JSC_DEFINE_HOST_FUNCTION(HTTPSResponseSink__doClose, (JSC::JSGlobalObject * lexi @end */ - /* Source for JSReadableFileSinkControllerPrototypeTableValues.lut.h @begin JSReadableFileSinkControllerPrototypeTable close JSReadableFileSinkController__close ReadOnly|DontDelete|Function 0 @@ -511,7 +473,6 @@ JSC_DEFINE_HOST_FUNCTION(HTTPSResponseSink__doClose, (JSC::JSGlobalObject * lexi @end */ - /* Source for JSHTTPResponseSinkPrototypeTableValues.lut.h @begin JSHTTPResponseSinkPrototypeTable close HTTPResponseSink__doClose ReadOnly|DontDelete|Function 0 @@ -522,7 +483,6 @@ JSC_DEFINE_HOST_FUNCTION(HTTPSResponseSink__doClose, (JSC::JSGlobalObject * lexi @end */ - /* Source for JSReadableHTTPResponseSinkControllerPrototypeTableValues.lut.h @begin JSReadableHTTPResponseSinkControllerPrototypeTable close JSReadableHTTPResponseSinkController__close ReadOnly|DontDelete|Function 0 @@ -533,7 +493,6 @@ JSC_DEFINE_HOST_FUNCTION(HTTPSResponseSink__doClose, (JSC::JSGlobalObject * lexi @end */ - /* Source for JSHTTPSResponseSinkPrototypeTableValues.lut.h @begin JSHTTPSResponseSinkPrototypeTable close HTTPSResponseSink__doClose ReadOnly|DontDelete|Function 0 @@ -544,7 +503,6 @@ JSC_DEFINE_HOST_FUNCTION(HTTPSResponseSink__doClose, (JSC::JSGlobalObject * lexi @end */ - /* Source for JSReadableHTTPSResponseSinkControllerPrototypeTableValues.lut.h @begin JSReadableHTTPSResponseSinkControllerPrototypeTable close JSReadableHTTPSResponseSinkController__close ReadOnly|DontDelete|Function 0 @@ -555,7 +513,6 @@ JSC_DEFINE_HOST_FUNCTION(HTTPSResponseSink__doClose, (JSC::JSGlobalObject * lexi @end */ - #pragma mark - ArrayBufferSink class JSArrayBufferSinkPrototype final : public JSC::JSNonFinalObject { @@ -591,42 +548,41 @@ private: STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(JSArrayBufferSinkPrototype, JSArrayBufferSinkPrototype::Base); class JSReadableArrayBufferSinkControllerPrototype final : public JSC::JSNonFinalObject { - public: - using Base = JSC::JSNonFinalObject; - - static JSReadableArrayBufferSinkControllerPrototype* create(JSC::VM& vm, JSGlobalObject* globalObject, JSC::Structure* structure) - { - JSReadableArrayBufferSinkControllerPrototype* ptr = new (NotNull, JSC::allocateCell<JSReadableArrayBufferSinkControllerPrototype>(vm)) JSReadableArrayBufferSinkControllerPrototype(vm, globalObject, structure); - ptr->finishCreation(vm, globalObject); - return ptr; - } - - DECLARE_INFO; - template<typename CellType, JSC::SubspaceAccess> - static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) - { - return &vm.plainObjectSpace(); - } - static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) - { - return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), info()); - } - - private: - JSReadableArrayBufferSinkControllerPrototype(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure) - : Base(vm, structure) - { - } - - void finishCreation(JSC::VM&, JSC::JSGlobalObject*); - }; - STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(JSReadableArrayBufferSinkControllerPrototype, JSReadableArrayBufferSinkControllerPrototype::Base); +public: + using Base = JSC::JSNonFinalObject; + + static JSReadableArrayBufferSinkControllerPrototype* create(JSC::VM& vm, JSGlobalObject* globalObject, JSC::Structure* structure) + { + JSReadableArrayBufferSinkControllerPrototype* ptr = new (NotNull, JSC::allocateCell<JSReadableArrayBufferSinkControllerPrototype>(vm)) JSReadableArrayBufferSinkControllerPrototype(vm, globalObject, structure); + ptr->finishCreation(vm, globalObject); + return ptr; + } + + DECLARE_INFO; + template<typename CellType, JSC::SubspaceAccess> + static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) + { + return &vm.plainObjectSpace(); + } + static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) + { + return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), info()); + } + +private: + JSReadableArrayBufferSinkControllerPrototype(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure) + : Base(vm, structure) + { + } + + void finishCreation(JSC::VM&, JSC::JSGlobalObject*); +}; +STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(JSReadableArrayBufferSinkControllerPrototype, JSReadableArrayBufferSinkControllerPrototype::Base); const ClassInfo JSArrayBufferSinkPrototype::s_info = { "ArrayBufferSink"_s, &Base::s_info, &JSArrayBufferSinkPrototypeTable, nullptr, CREATE_METHOD_TABLE(JSArrayBufferSinkPrototype) }; const ClassInfo JSArrayBufferSink::s_info = { "ArrayBufferSink"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSArrayBufferSink) }; const ClassInfo JSArrayBufferSinkConstructor::s_info = { "ArrayBufferSink"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSArrayBufferSinkConstructor) }; - const ClassInfo JSReadableArrayBufferSinkControllerPrototype::s_info = { "ReadableArrayBufferSinkController"_s, &Base::s_info, &JSReadableArrayBufferSinkControllerPrototypeTable, nullptr, CREATE_METHOD_TABLE(JSReadableArrayBufferSinkControllerPrototype) }; const ClassInfo JSReadableArrayBufferSinkController::s_info = { "ReadableArrayBufferSinkController"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSReadableArrayBufferSinkController) }; @@ -637,7 +593,6 @@ JSArrayBufferSink::~JSArrayBufferSink() } } - JSReadableArrayBufferSinkController::~JSReadableArrayBufferSinkController() { if (m_sinkPtr) { @@ -655,7 +610,8 @@ JSObject* JSReadableArrayBufferSinkController::createPrototype(VM& vm, JSDOMGlob return JSReadableArrayBufferSinkControllerPrototype::create(vm, &globalObject, JSReadableArrayBufferSinkControllerPrototype::createStructure(vm, &globalObject, globalObject.objectPrototype())); } -void JSReadableArrayBufferSinkController::detach() { +void JSReadableArrayBufferSinkController::detach() +{ m_sinkPtr = nullptr; m_onPull.clear(); @@ -664,18 +620,17 @@ void JSReadableArrayBufferSinkController::detach() { m_onClose.clear(); if (readableStream && onClose) { - JSC::JSGlobalObject *globalObject = this->globalObject(); + JSC::JSGlobalObject* globalObject = this->globalObject(); auto callData = JSC::getCallData(onClose); JSC::MarkedArgumentBuffer arguments; arguments.append(readableStream); arguments.append(jsUndefined()); JSC::call(globalObject, onClose, callData, JSC::jsUndefined(), arguments); } - + m_weakReadableStream.clear(); } - JSArrayBufferSinkConstructor* JSArrayBufferSinkConstructor::create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure, JSObject* prototype) { JSArrayBufferSinkConstructor* ptr = new (NotNull, JSC::allocateCell<JSArrayBufferSinkConstructor>(vm)) JSArrayBufferSinkConstructor(vm, structure, ArrayBufferSink__construct); @@ -704,11 +659,11 @@ void JSArrayBufferSinkConstructor::finishCreation(VM& vm, JSC::JSGlobalObject* g initializeProperties(vm, globalObject, prototype); } -JSC::EncodedJSValue JSC_HOST_CALL_ATTRIBUTES JSArrayBufferSinkConstructor::construct(JSC::JSGlobalObject* globalObject, JSC::CallFrame* callFrame) { +JSC::EncodedJSValue JSC_HOST_CALL_ATTRIBUTES JSArrayBufferSinkConstructor::construct(JSC::JSGlobalObject* globalObject, JSC::CallFrame* callFrame) +{ return ArrayBufferSink__construct(globalObject, callFrame); } - void JSArrayBufferSinkConstructor::initializeProperties(VM& vm, JSC::JSGlobalObject* globalObject, JSObject* prototype) { putDirect(vm, vm.propertyNames->length, jsNumber(0), JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::DontEnum); @@ -745,7 +700,6 @@ void JSReadableArrayBufferSinkController::finishCreation(VM& vm) ASSERT(inherits(info())); } - void JSArrayBufferSink::analyzeHeap(JSCell* cell, HeapAnalyzer& analyzer) { auto* thisObject = jsCast<JSArrayBufferSink*>(cell); @@ -768,7 +722,6 @@ void JSReadableArrayBufferSinkController::analyzeHeap(JSCell* cell, HeapAnalyzer Base::analyzeHeap(cell, analyzer); } - template<typename Visitor> void JSReadableArrayBufferSinkController::visitChildrenImpl(JSCell* cell, Visitor& visitor) { @@ -777,13 +730,28 @@ void JSReadableArrayBufferSinkController::visitChildrenImpl(JSCell* cell, Visito Base::visitChildren(thisObject, visitor); visitor.append(thisObject->m_onPull); visitor.append(thisObject->m_onClose); - visitor.append(thisObject->m_weakReadableStream); + void* ptr = thisObject->m_sinkPtr; + if (ptr) + visitor.addOpaqueRoot(ptr); } DEFINE_VISIT_CHILDREN(JSReadableArrayBufferSinkController); +template<typename Visitor> +void JSArrayBufferSink::visitChildrenImpl(JSCell* cell, Visitor& visitor) +{ + JSArrayBufferSink* thisObject = jsCast<JSArrayBufferSink*>(cell); + ASSERT_GC_OBJECT_INHERITS(thisObject, info()); + Base::visitChildren(thisObject, visitor); + void* ptr = thisObject->m_sinkPtr; + if (ptr) + visitor.addOpaqueRoot(ptr); +} -void JSReadableArrayBufferSinkController::start(JSC::JSGlobalObject *globalObject, JSC::JSValue readableStream, JSC::JSFunction *onPull, JSC::JSFunction *onClose) { +DEFINE_VISIT_CHILDREN(JSArrayBufferSink); + +void JSReadableArrayBufferSinkController::start(JSC::JSGlobalObject* globalObject, JSC::JSValue readableStream, JSC::JSFunction* onPull, JSC::JSFunction* onClose) +{ this->m_weakReadableStream = JSC::Weak<JSC::JSObject>(readableStream.getObject()); this->m_onPull.set(globalObject->vm(), this, onPull); this->m_onClose.set(globalObject->vm(), this, onClose); @@ -794,14 +762,11 @@ void JSArrayBufferSink::destroy(JSCell* cell) static_cast<JSArrayBufferSink*>(cell)->JSArrayBufferSink::~JSArrayBufferSink(); } - void JSReadableArrayBufferSinkController::destroy(JSCell* cell) { static_cast<JSReadableArrayBufferSinkController*>(cell)->JSReadableArrayBufferSinkController::~JSReadableArrayBufferSinkController(); } - - #pragma mark - FileSink class JSFileSinkPrototype final : public JSC::JSNonFinalObject { @@ -837,42 +802,41 @@ private: STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(JSFileSinkPrototype, JSFileSinkPrototype::Base); class JSReadableFileSinkControllerPrototype final : public JSC::JSNonFinalObject { - public: - using Base = JSC::JSNonFinalObject; - - static JSReadableFileSinkControllerPrototype* create(JSC::VM& vm, JSGlobalObject* globalObject, JSC::Structure* structure) - { - JSReadableFileSinkControllerPrototype* ptr = new (NotNull, JSC::allocateCell<JSReadableFileSinkControllerPrototype>(vm)) JSReadableFileSinkControllerPrototype(vm, globalObject, structure); - ptr->finishCreation(vm, globalObject); - return ptr; - } - - DECLARE_INFO; - template<typename CellType, JSC::SubspaceAccess> - static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) - { - return &vm.plainObjectSpace(); - } - static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) - { - return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), info()); - } - - private: - JSReadableFileSinkControllerPrototype(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure) - : Base(vm, structure) - { - } - - void finishCreation(JSC::VM&, JSC::JSGlobalObject*); - }; - STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(JSReadableFileSinkControllerPrototype, JSReadableFileSinkControllerPrototype::Base); +public: + using Base = JSC::JSNonFinalObject; + + static JSReadableFileSinkControllerPrototype* create(JSC::VM& vm, JSGlobalObject* globalObject, JSC::Structure* structure) + { + JSReadableFileSinkControllerPrototype* ptr = new (NotNull, JSC::allocateCell<JSReadableFileSinkControllerPrototype>(vm)) JSReadableFileSinkControllerPrototype(vm, globalObject, structure); + ptr->finishCreation(vm, globalObject); + return ptr; + } + + DECLARE_INFO; + template<typename CellType, JSC::SubspaceAccess> + static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) + { + return &vm.plainObjectSpace(); + } + static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) + { + return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), info()); + } + +private: + JSReadableFileSinkControllerPrototype(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure) + : Base(vm, structure) + { + } + + void finishCreation(JSC::VM&, JSC::JSGlobalObject*); +}; +STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(JSReadableFileSinkControllerPrototype, JSReadableFileSinkControllerPrototype::Base); const ClassInfo JSFileSinkPrototype::s_info = { "FileSink"_s, &Base::s_info, &JSFileSinkPrototypeTable, nullptr, CREATE_METHOD_TABLE(JSFileSinkPrototype) }; const ClassInfo JSFileSink::s_info = { "FileSink"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSFileSink) }; const ClassInfo JSFileSinkConstructor::s_info = { "FileSink"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSFileSinkConstructor) }; - const ClassInfo JSReadableFileSinkControllerPrototype::s_info = { "ReadableFileSinkController"_s, &Base::s_info, &JSReadableFileSinkControllerPrototypeTable, nullptr, CREATE_METHOD_TABLE(JSReadableFileSinkControllerPrototype) }; const ClassInfo JSReadableFileSinkController::s_info = { "ReadableFileSinkController"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSReadableFileSinkController) }; @@ -883,7 +847,6 @@ JSFileSink::~JSFileSink() } } - JSReadableFileSinkController::~JSReadableFileSinkController() { if (m_sinkPtr) { @@ -901,7 +864,8 @@ JSObject* JSReadableFileSinkController::createPrototype(VM& vm, JSDOMGlobalObjec return JSReadableFileSinkControllerPrototype::create(vm, &globalObject, JSReadableFileSinkControllerPrototype::createStructure(vm, &globalObject, globalObject.objectPrototype())); } -void JSReadableFileSinkController::detach() { +void JSReadableFileSinkController::detach() +{ m_sinkPtr = nullptr; m_onPull.clear(); @@ -910,18 +874,17 @@ void JSReadableFileSinkController::detach() { m_onClose.clear(); if (readableStream && onClose) { - JSC::JSGlobalObject *globalObject = this->globalObject(); + JSC::JSGlobalObject* globalObject = this->globalObject(); auto callData = JSC::getCallData(onClose); JSC::MarkedArgumentBuffer arguments; arguments.append(readableStream); arguments.append(jsUndefined()); JSC::call(globalObject, onClose, callData, JSC::jsUndefined(), arguments); } - + m_weakReadableStream.clear(); } - JSFileSinkConstructor* JSFileSinkConstructor::create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure, JSObject* prototype) { JSFileSinkConstructor* ptr = new (NotNull, JSC::allocateCell<JSFileSinkConstructor>(vm)) JSFileSinkConstructor(vm, structure, FileSink__construct); @@ -950,11 +913,11 @@ void JSFileSinkConstructor::finishCreation(VM& vm, JSC::JSGlobalObject* globalOb initializeProperties(vm, globalObject, prototype); } -JSC::EncodedJSValue JSC_HOST_CALL_ATTRIBUTES JSFileSinkConstructor::construct(JSC::JSGlobalObject* globalObject, JSC::CallFrame* callFrame) { +JSC::EncodedJSValue JSC_HOST_CALL_ATTRIBUTES JSFileSinkConstructor::construct(JSC::JSGlobalObject* globalObject, JSC::CallFrame* callFrame) +{ return FileSink__construct(globalObject, callFrame); } - void JSFileSinkConstructor::initializeProperties(VM& vm, JSC::JSGlobalObject* globalObject, JSObject* prototype) { putDirect(vm, vm.propertyNames->length, jsNumber(0), JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::DontEnum); @@ -991,7 +954,6 @@ void JSReadableFileSinkController::finishCreation(VM& vm) ASSERT(inherits(info())); } - void JSFileSink::analyzeHeap(JSCell* cell, HeapAnalyzer& analyzer) { auto* thisObject = jsCast<JSFileSink*>(cell); @@ -1014,7 +976,6 @@ void JSReadableFileSinkController::analyzeHeap(JSCell* cell, HeapAnalyzer& analy Base::analyzeHeap(cell, analyzer); } - template<typename Visitor> void JSReadableFileSinkController::visitChildrenImpl(JSCell* cell, Visitor& visitor) { @@ -1023,13 +984,28 @@ void JSReadableFileSinkController::visitChildrenImpl(JSCell* cell, Visitor& visi Base::visitChildren(thisObject, visitor); visitor.append(thisObject->m_onPull); visitor.append(thisObject->m_onClose); - visitor.append(thisObject->m_weakReadableStream); + void* ptr = thisObject->m_sinkPtr; + if (ptr) + visitor.addOpaqueRoot(ptr); } DEFINE_VISIT_CHILDREN(JSReadableFileSinkController); +template<typename Visitor> +void JSFileSink::visitChildrenImpl(JSCell* cell, Visitor& visitor) +{ + JSFileSink* thisObject = jsCast<JSFileSink*>(cell); + ASSERT_GC_OBJECT_INHERITS(thisObject, info()); + Base::visitChildren(thisObject, visitor); + void* ptr = thisObject->m_sinkPtr; + if (ptr) + visitor.addOpaqueRoot(ptr); +} + +DEFINE_VISIT_CHILDREN(JSFileSink); -void JSReadableFileSinkController::start(JSC::JSGlobalObject *globalObject, JSC::JSValue readableStream, JSC::JSFunction *onPull, JSC::JSFunction *onClose) { +void JSReadableFileSinkController::start(JSC::JSGlobalObject* globalObject, JSC::JSValue readableStream, JSC::JSFunction* onPull, JSC::JSFunction* onClose) +{ this->m_weakReadableStream = JSC::Weak<JSC::JSObject>(readableStream.getObject()); this->m_onPull.set(globalObject->vm(), this, onPull); this->m_onClose.set(globalObject->vm(), this, onClose); @@ -1040,14 +1016,11 @@ void JSFileSink::destroy(JSCell* cell) static_cast<JSFileSink*>(cell)->JSFileSink::~JSFileSink(); } - void JSReadableFileSinkController::destroy(JSCell* cell) { static_cast<JSReadableFileSinkController*>(cell)->JSReadableFileSinkController::~JSReadableFileSinkController(); } - - #pragma mark - HTTPResponseSink class JSHTTPResponseSinkPrototype final : public JSC::JSNonFinalObject { @@ -1083,42 +1056,41 @@ private: STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(JSHTTPResponseSinkPrototype, JSHTTPResponseSinkPrototype::Base); class JSReadableHTTPResponseSinkControllerPrototype final : public JSC::JSNonFinalObject { - public: - using Base = JSC::JSNonFinalObject; - - static JSReadableHTTPResponseSinkControllerPrototype* create(JSC::VM& vm, JSGlobalObject* globalObject, JSC::Structure* structure) - { - JSReadableHTTPResponseSinkControllerPrototype* ptr = new (NotNull, JSC::allocateCell<JSReadableHTTPResponseSinkControllerPrototype>(vm)) JSReadableHTTPResponseSinkControllerPrototype(vm, globalObject, structure); - ptr->finishCreation(vm, globalObject); - return ptr; - } - - DECLARE_INFO; - template<typename CellType, JSC::SubspaceAccess> - static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) - { - return &vm.plainObjectSpace(); - } - static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) - { - return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), info()); - } - - private: - JSReadableHTTPResponseSinkControllerPrototype(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure) - : Base(vm, structure) - { - } - - void finishCreation(JSC::VM&, JSC::JSGlobalObject*); - }; - STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(JSReadableHTTPResponseSinkControllerPrototype, JSReadableHTTPResponseSinkControllerPrototype::Base); +public: + using Base = JSC::JSNonFinalObject; + + static JSReadableHTTPResponseSinkControllerPrototype* create(JSC::VM& vm, JSGlobalObject* globalObject, JSC::Structure* structure) + { + JSReadableHTTPResponseSinkControllerPrototype* ptr = new (NotNull, JSC::allocateCell<JSReadableHTTPResponseSinkControllerPrototype>(vm)) JSReadableHTTPResponseSinkControllerPrototype(vm, globalObject, structure); + ptr->finishCreation(vm, globalObject); + return ptr; + } + + DECLARE_INFO; + template<typename CellType, JSC::SubspaceAccess> + static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) + { + return &vm.plainObjectSpace(); + } + static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) + { + return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), info()); + } + +private: + JSReadableHTTPResponseSinkControllerPrototype(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure) + : Base(vm, structure) + { + } + + void finishCreation(JSC::VM&, JSC::JSGlobalObject*); +}; +STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(JSReadableHTTPResponseSinkControllerPrototype, JSReadableHTTPResponseSinkControllerPrototype::Base); const ClassInfo JSHTTPResponseSinkPrototype::s_info = { "HTTPResponseSink"_s, &Base::s_info, &JSHTTPResponseSinkPrototypeTable, nullptr, CREATE_METHOD_TABLE(JSHTTPResponseSinkPrototype) }; const ClassInfo JSHTTPResponseSink::s_info = { "HTTPResponseSink"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSHTTPResponseSink) }; const ClassInfo JSHTTPResponseSinkConstructor::s_info = { "HTTPResponseSink"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSHTTPResponseSinkConstructor) }; - const ClassInfo JSReadableHTTPResponseSinkControllerPrototype::s_info = { "ReadableHTTPResponseSinkController"_s, &Base::s_info, &JSReadableHTTPResponseSinkControllerPrototypeTable, nullptr, CREATE_METHOD_TABLE(JSReadableHTTPResponseSinkControllerPrototype) }; const ClassInfo JSReadableHTTPResponseSinkController::s_info = { "ReadableHTTPResponseSinkController"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSReadableHTTPResponseSinkController) }; @@ -1129,7 +1101,6 @@ JSHTTPResponseSink::~JSHTTPResponseSink() } } - JSReadableHTTPResponseSinkController::~JSReadableHTTPResponseSinkController() { if (m_sinkPtr) { @@ -1147,7 +1118,8 @@ JSObject* JSReadableHTTPResponseSinkController::createPrototype(VM& vm, JSDOMGlo return JSReadableHTTPResponseSinkControllerPrototype::create(vm, &globalObject, JSReadableHTTPResponseSinkControllerPrototype::createStructure(vm, &globalObject, globalObject.objectPrototype())); } -void JSReadableHTTPResponseSinkController::detach() { +void JSReadableHTTPResponseSinkController::detach() +{ m_sinkPtr = nullptr; m_onPull.clear(); @@ -1156,18 +1128,17 @@ void JSReadableHTTPResponseSinkController::detach() { m_onClose.clear(); if (readableStream && onClose) { - JSC::JSGlobalObject *globalObject = this->globalObject(); + JSC::JSGlobalObject* globalObject = this->globalObject(); auto callData = JSC::getCallData(onClose); JSC::MarkedArgumentBuffer arguments; arguments.append(readableStream); arguments.append(jsUndefined()); JSC::call(globalObject, onClose, callData, JSC::jsUndefined(), arguments); } - + m_weakReadableStream.clear(); } - JSHTTPResponseSinkConstructor* JSHTTPResponseSinkConstructor::create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure, JSObject* prototype) { JSHTTPResponseSinkConstructor* ptr = new (NotNull, JSC::allocateCell<JSHTTPResponseSinkConstructor>(vm)) JSHTTPResponseSinkConstructor(vm, structure, HTTPResponseSink__construct); @@ -1196,11 +1167,11 @@ void JSHTTPResponseSinkConstructor::finishCreation(VM& vm, JSC::JSGlobalObject* initializeProperties(vm, globalObject, prototype); } -JSC::EncodedJSValue JSC_HOST_CALL_ATTRIBUTES JSHTTPResponseSinkConstructor::construct(JSC::JSGlobalObject* globalObject, JSC::CallFrame* callFrame) { +JSC::EncodedJSValue JSC_HOST_CALL_ATTRIBUTES JSHTTPResponseSinkConstructor::construct(JSC::JSGlobalObject* globalObject, JSC::CallFrame* callFrame) +{ return HTTPResponseSink__construct(globalObject, callFrame); } - void JSHTTPResponseSinkConstructor::initializeProperties(VM& vm, JSC::JSGlobalObject* globalObject, JSObject* prototype) { putDirect(vm, vm.propertyNames->length, jsNumber(0), JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::DontEnum); @@ -1237,7 +1208,6 @@ void JSReadableHTTPResponseSinkController::finishCreation(VM& vm) ASSERT(inherits(info())); } - void JSHTTPResponseSink::analyzeHeap(JSCell* cell, HeapAnalyzer& analyzer) { auto* thisObject = jsCast<JSHTTPResponseSink*>(cell); @@ -1260,7 +1230,6 @@ void JSReadableHTTPResponseSinkController::analyzeHeap(JSCell* cell, HeapAnalyze Base::analyzeHeap(cell, analyzer); } - template<typename Visitor> void JSReadableHTTPResponseSinkController::visitChildrenImpl(JSCell* cell, Visitor& visitor) { @@ -1269,13 +1238,28 @@ void JSReadableHTTPResponseSinkController::visitChildrenImpl(JSCell* cell, Visit Base::visitChildren(thisObject, visitor); visitor.append(thisObject->m_onPull); visitor.append(thisObject->m_onClose); - visitor.append(thisObject->m_weakReadableStream); + void* ptr = thisObject->m_sinkPtr; + if (ptr) + visitor.addOpaqueRoot(ptr); } DEFINE_VISIT_CHILDREN(JSReadableHTTPResponseSinkController); +template<typename Visitor> +void JSHTTPResponseSink::visitChildrenImpl(JSCell* cell, Visitor& visitor) +{ + JSHTTPResponseSink* thisObject = jsCast<JSHTTPResponseSink*>(cell); + ASSERT_GC_OBJECT_INHERITS(thisObject, info()); + Base::visitChildren(thisObject, visitor); + void* ptr = thisObject->m_sinkPtr; + if (ptr) + visitor.addOpaqueRoot(ptr); +} -void JSReadableHTTPResponseSinkController::start(JSC::JSGlobalObject *globalObject, JSC::JSValue readableStream, JSC::JSFunction *onPull, JSC::JSFunction *onClose) { +DEFINE_VISIT_CHILDREN(JSHTTPResponseSink); + +void JSReadableHTTPResponseSinkController::start(JSC::JSGlobalObject* globalObject, JSC::JSValue readableStream, JSC::JSFunction* onPull, JSC::JSFunction* onClose) +{ this->m_weakReadableStream = JSC::Weak<JSC::JSObject>(readableStream.getObject()); this->m_onPull.set(globalObject->vm(), this, onPull); this->m_onClose.set(globalObject->vm(), this, onClose); @@ -1286,14 +1270,11 @@ void JSHTTPResponseSink::destroy(JSCell* cell) static_cast<JSHTTPResponseSink*>(cell)->JSHTTPResponseSink::~JSHTTPResponseSink(); } - void JSReadableHTTPResponseSinkController::destroy(JSCell* cell) { static_cast<JSReadableHTTPResponseSinkController*>(cell)->JSReadableHTTPResponseSinkController::~JSReadableHTTPResponseSinkController(); } - - #pragma mark - HTTPSResponseSink class JSHTTPSResponseSinkPrototype final : public JSC::JSNonFinalObject { @@ -1329,42 +1310,41 @@ private: STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(JSHTTPSResponseSinkPrototype, JSHTTPSResponseSinkPrototype::Base); class JSReadableHTTPSResponseSinkControllerPrototype final : public JSC::JSNonFinalObject { - public: - using Base = JSC::JSNonFinalObject; - - static JSReadableHTTPSResponseSinkControllerPrototype* create(JSC::VM& vm, JSGlobalObject* globalObject, JSC::Structure* structure) - { - JSReadableHTTPSResponseSinkControllerPrototype* ptr = new (NotNull, JSC::allocateCell<JSReadableHTTPSResponseSinkControllerPrototype>(vm)) JSReadableHTTPSResponseSinkControllerPrototype(vm, globalObject, structure); - ptr->finishCreation(vm, globalObject); - return ptr; - } - - DECLARE_INFO; - template<typename CellType, JSC::SubspaceAccess> - static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) - { - return &vm.plainObjectSpace(); - } - static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) - { - return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), info()); - } - - private: - JSReadableHTTPSResponseSinkControllerPrototype(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure) - : Base(vm, structure) - { - } - - void finishCreation(JSC::VM&, JSC::JSGlobalObject*); - }; - STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(JSReadableHTTPSResponseSinkControllerPrototype, JSReadableHTTPSResponseSinkControllerPrototype::Base); +public: + using Base = JSC::JSNonFinalObject; + + static JSReadableHTTPSResponseSinkControllerPrototype* create(JSC::VM& vm, JSGlobalObject* globalObject, JSC::Structure* structure) + { + JSReadableHTTPSResponseSinkControllerPrototype* ptr = new (NotNull, JSC::allocateCell<JSReadableHTTPSResponseSinkControllerPrototype>(vm)) JSReadableHTTPSResponseSinkControllerPrototype(vm, globalObject, structure); + ptr->finishCreation(vm, globalObject); + return ptr; + } + + DECLARE_INFO; + template<typename CellType, JSC::SubspaceAccess> + static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) + { + return &vm.plainObjectSpace(); + } + static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) + { + return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), info()); + } + +private: + JSReadableHTTPSResponseSinkControllerPrototype(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure) + : Base(vm, structure) + { + } + + void finishCreation(JSC::VM&, JSC::JSGlobalObject*); +}; +STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(JSReadableHTTPSResponseSinkControllerPrototype, JSReadableHTTPSResponseSinkControllerPrototype::Base); const ClassInfo JSHTTPSResponseSinkPrototype::s_info = { "HTTPSResponseSink"_s, &Base::s_info, &JSHTTPSResponseSinkPrototypeTable, nullptr, CREATE_METHOD_TABLE(JSHTTPSResponseSinkPrototype) }; const ClassInfo JSHTTPSResponseSink::s_info = { "HTTPSResponseSink"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSHTTPSResponseSink) }; const ClassInfo JSHTTPSResponseSinkConstructor::s_info = { "HTTPSResponseSink"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSHTTPSResponseSinkConstructor) }; - const ClassInfo JSReadableHTTPSResponseSinkControllerPrototype::s_info = { "ReadableHTTPSResponseSinkController"_s, &Base::s_info, &JSReadableHTTPSResponseSinkControllerPrototypeTable, nullptr, CREATE_METHOD_TABLE(JSReadableHTTPSResponseSinkControllerPrototype) }; const ClassInfo JSReadableHTTPSResponseSinkController::s_info = { "ReadableHTTPSResponseSinkController"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSReadableHTTPSResponseSinkController) }; @@ -1375,7 +1355,6 @@ JSHTTPSResponseSink::~JSHTTPSResponseSink() } } - JSReadableHTTPSResponseSinkController::~JSReadableHTTPSResponseSinkController() { if (m_sinkPtr) { @@ -1393,7 +1372,8 @@ JSObject* JSReadableHTTPSResponseSinkController::createPrototype(VM& vm, JSDOMGl return JSReadableHTTPSResponseSinkControllerPrototype::create(vm, &globalObject, JSReadableHTTPSResponseSinkControllerPrototype::createStructure(vm, &globalObject, globalObject.objectPrototype())); } -void JSReadableHTTPSResponseSinkController::detach() { +void JSReadableHTTPSResponseSinkController::detach() +{ m_sinkPtr = nullptr; m_onPull.clear(); @@ -1402,18 +1382,17 @@ void JSReadableHTTPSResponseSinkController::detach() { m_onClose.clear(); if (readableStream && onClose) { - JSC::JSGlobalObject *globalObject = this->globalObject(); + JSC::JSGlobalObject* globalObject = this->globalObject(); auto callData = JSC::getCallData(onClose); JSC::MarkedArgumentBuffer arguments; arguments.append(readableStream); arguments.append(jsUndefined()); JSC::call(globalObject, onClose, callData, JSC::jsUndefined(), arguments); } - + m_weakReadableStream.clear(); } - JSHTTPSResponseSinkConstructor* JSHTTPSResponseSinkConstructor::create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure, JSObject* prototype) { JSHTTPSResponseSinkConstructor* ptr = new (NotNull, JSC::allocateCell<JSHTTPSResponseSinkConstructor>(vm)) JSHTTPSResponseSinkConstructor(vm, structure, HTTPSResponseSink__construct); @@ -1442,11 +1421,11 @@ void JSHTTPSResponseSinkConstructor::finishCreation(VM& vm, JSC::JSGlobalObject* initializeProperties(vm, globalObject, prototype); } -JSC::EncodedJSValue JSC_HOST_CALL_ATTRIBUTES JSHTTPSResponseSinkConstructor::construct(JSC::JSGlobalObject* globalObject, JSC::CallFrame* callFrame) { +JSC::EncodedJSValue JSC_HOST_CALL_ATTRIBUTES JSHTTPSResponseSinkConstructor::construct(JSC::JSGlobalObject* globalObject, JSC::CallFrame* callFrame) +{ return HTTPSResponseSink__construct(globalObject, callFrame); } - void JSHTTPSResponseSinkConstructor::initializeProperties(VM& vm, JSC::JSGlobalObject* globalObject, JSObject* prototype) { putDirect(vm, vm.propertyNames->length, jsNumber(0), JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::DontEnum); @@ -1483,7 +1462,6 @@ void JSReadableHTTPSResponseSinkController::finishCreation(VM& vm) ASSERT(inherits(info())); } - void JSHTTPSResponseSink::analyzeHeap(JSCell* cell, HeapAnalyzer& analyzer) { auto* thisObject = jsCast<JSHTTPSResponseSink*>(cell); @@ -1506,7 +1484,6 @@ void JSReadableHTTPSResponseSinkController::analyzeHeap(JSCell* cell, HeapAnalyz Base::analyzeHeap(cell, analyzer); } - template<typename Visitor> void JSReadableHTTPSResponseSinkController::visitChildrenImpl(JSCell* cell, Visitor& visitor) { @@ -1515,13 +1492,28 @@ void JSReadableHTTPSResponseSinkController::visitChildrenImpl(JSCell* cell, Visi Base::visitChildren(thisObject, visitor); visitor.append(thisObject->m_onPull); visitor.append(thisObject->m_onClose); - visitor.append(thisObject->m_weakReadableStream); + void* ptr = thisObject->m_sinkPtr; + if (ptr) + visitor.addOpaqueRoot(ptr); } DEFINE_VISIT_CHILDREN(JSReadableHTTPSResponseSinkController); +template<typename Visitor> +void JSHTTPSResponseSink::visitChildrenImpl(JSCell* cell, Visitor& visitor) +{ + JSHTTPSResponseSink* thisObject = jsCast<JSHTTPSResponseSink*>(cell); + ASSERT_GC_OBJECT_INHERITS(thisObject, info()); + Base::visitChildren(thisObject, visitor); + void* ptr = thisObject->m_sinkPtr; + if (ptr) + visitor.addOpaqueRoot(ptr); +} + +DEFINE_VISIT_CHILDREN(JSHTTPSResponseSink); -void JSReadableHTTPSResponseSinkController::start(JSC::JSGlobalObject *globalObject, JSC::JSValue readableStream, JSC::JSFunction *onPull, JSC::JSFunction *onClose) { +void JSReadableHTTPSResponseSinkController::start(JSC::JSGlobalObject* globalObject, JSC::JSValue readableStream, JSC::JSFunction* onPull, JSC::JSFunction* onClose) +{ this->m_weakReadableStream = JSC::Weak<JSC::JSObject>(readableStream.getObject()); this->m_onPull.set(globalObject->vm(), this, onPull); this->m_onClose.set(globalObject->vm(), this, onClose); @@ -1532,18 +1524,15 @@ void JSHTTPSResponseSink::destroy(JSCell* cell) static_cast<JSHTTPSResponseSink*>(cell)->JSHTTPSResponseSink::~JSHTTPSResponseSink(); } - void JSReadableHTTPSResponseSinkController::destroy(JSCell* cell) { static_cast<JSReadableHTTPSResponseSinkController*>(cell)->JSReadableHTTPSResponseSinkController::~JSReadableHTTPSResponseSinkController(); } +JSObject* createJSSinkPrototype(JSC::VM& vm, JSC::JSGlobalObject* globalObject, SinkID sinkID) +{ + switch (sinkID) { - - JSObject* createJSSinkPrototype(JSC::VM& vm, JSC::JSGlobalObject* globalObject, SinkID sinkID) - { - switch (sinkID) { - case ArrayBufferSink: return JSArrayBufferSinkPrototype::create(vm, globalObject, JSArrayBufferSinkPrototype::createStructure(vm, globalObject, globalObject->objectPrototype())); @@ -1556,61 +1545,60 @@ void JSReadableHTTPSResponseSinkController::destroy(JSCell* cell) case HTTPSResponseSink: return JSHTTPSResponseSinkPrototype::create(vm, globalObject, JSHTTPSResponseSinkPrototype::createStructure(vm, globalObject, globalObject->objectPrototype())); -default: - RELEASE_ASSERT_NOT_REACHED(); + default: + RELEASE_ASSERT_NOT_REACHED(); } } JSObject* createJSSinkControllerPrototype(JSC::VM& vm, JSC::JSGlobalObject* globalObject, SinkID sinkID) { switch (sinkID) { - - case ArrayBufferSink: - return JSReadableArrayBufferSinkControllerPrototype::create(vm, globalObject, JSReadableArrayBufferSinkControllerPrototype::createStructure(vm, globalObject, globalObject->objectPrototype())); - case FileSink: - return JSReadableFileSinkControllerPrototype::create(vm, globalObject, JSReadableFileSinkControllerPrototype::createStructure(vm, globalObject, globalObject->objectPrototype())); + case ArrayBufferSink: + return JSReadableArrayBufferSinkControllerPrototype::create(vm, globalObject, JSReadableArrayBufferSinkControllerPrototype::createStructure(vm, globalObject, globalObject->objectPrototype())); - case HTTPResponseSink: - return JSReadableHTTPResponseSinkControllerPrototype::create(vm, globalObject, JSReadableHTTPResponseSinkControllerPrototype::createStructure(vm, globalObject, globalObject->objectPrototype())); + case FileSink: + return JSReadableFileSinkControllerPrototype::create(vm, globalObject, JSReadableFileSinkControllerPrototype::createStructure(vm, globalObject, globalObject->objectPrototype())); + + case HTTPResponseSink: + return JSReadableHTTPResponseSinkControllerPrototype::create(vm, globalObject, JSReadableHTTPResponseSinkControllerPrototype::createStructure(vm, globalObject, globalObject->objectPrototype())); - case HTTPSResponseSink: - return JSReadableHTTPSResponseSinkControllerPrototype::create(vm, globalObject, JSReadableHTTPSResponseSinkControllerPrototype::createStructure(vm, globalObject, globalObject->objectPrototype())); + case HTTPSResponseSink: + return JSReadableHTTPSResponseSinkControllerPrototype::create(vm, globalObject, JSReadableHTTPSResponseSinkControllerPrototype::createStructure(vm, globalObject, globalObject->objectPrototype())); -default: - RELEASE_ASSERT_NOT_REACHED(); - } + default: + RELEASE_ASSERT_NOT_REACHED(); + } } Structure* createJSSinkControllerStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, SinkID sinkID) { switch (sinkID) { - - case ArrayBufferSink: { - auto* prototype = createJSSinkControllerPrototype(vm, globalObject, sinkID); - return JSReadableArrayBufferSinkController::createStructure(vm, globalObject, prototype); - } - - case FileSink: { - auto* prototype = createJSSinkControllerPrototype(vm, globalObject, sinkID); - return JSReadableFileSinkController::createStructure(vm, globalObject, prototype); - } - - case HTTPResponseSink: { - auto* prototype = createJSSinkControllerPrototype(vm, globalObject, sinkID); - return JSReadableHTTPResponseSinkController::createStructure(vm, globalObject, prototype); - } - - case HTTPSResponseSink: { - auto* prototype = createJSSinkControllerPrototype(vm, globalObject, sinkID); - return JSReadableHTTPSResponseSinkController::createStructure(vm, globalObject, prototype); - } - -default: - RELEASE_ASSERT_NOT_REACHED(); - } + + case ArrayBufferSink: { + auto* prototype = createJSSinkControllerPrototype(vm, globalObject, sinkID); + return JSReadableArrayBufferSinkController::createStructure(vm, globalObject, prototype); + } + + case FileSink: { + auto* prototype = createJSSinkControllerPrototype(vm, globalObject, sinkID); + return JSReadableFileSinkController::createStructure(vm, globalObject, prototype); + } + + case HTTPResponseSink: { + auto* prototype = createJSSinkControllerPrototype(vm, globalObject, sinkID); + return JSReadableHTTPResponseSinkController::createStructure(vm, globalObject, prototype); + } + + case HTTPSResponseSink: { + auto* prototype = createJSSinkControllerPrototype(vm, globalObject, sinkID); + return JSReadableHTTPSResponseSinkController::createStructure(vm, globalObject, prototype); + } + + default: + RELEASE_ASSERT_NOT_REACHED(); + } } } // namespace WebCore - extern "C" JSC__JSValue ArrayBufferSink__createObject(JSC__JSGlobalObject* arg0, void* sinkPtr) { auto& vm = arg0->vm(); @@ -1638,7 +1626,6 @@ extern "C" void ArrayBufferSink__detachPtr(JSC__JSValue JSValue0) sink->detach(); return; } - if (auto* controller = JSC::jsDynamicCast<WebCore::JSReadableArrayBufferSinkController*>(JSC::JSValue::decode(JSValue0))) { controller->detach(); @@ -1646,13 +1633,13 @@ extern "C" void ArrayBufferSink__detachPtr(JSC__JSValue JSValue0) } } -extern "C" JSC__JSValue ArrayBufferSink__assignToStream(JSC__JSGlobalObject* arg0, JSC__JSValue stream, void* sinkPtr, void **controllerValue) +extern "C" JSC__JSValue ArrayBufferSink__assignToStream(JSC__JSGlobalObject* arg0, JSC__JSValue stream, void* sinkPtr, void** controllerValue) { auto& vm = arg0->vm(); Zig::GlobalObject* globalObject = reinterpret_cast<Zig::GlobalObject*>(arg0); JSC::Structure* structure = WebCore::getDOMStructure<WebCore::JSReadableArrayBufferSinkController>(vm, *globalObject); - WebCore::JSReadableArrayBufferSinkController *controller = WebCore::JSReadableArrayBufferSinkController::create(vm, globalObject, structure, sinkPtr); + WebCore::JSReadableArrayBufferSinkController* controller = WebCore::JSReadableArrayBufferSinkController::create(vm, globalObject, structure, sinkPtr); *controllerValue = reinterpret_cast<void*>(JSC::JSValue::encode(controller)); return globalObject->assignToStream(JSC::JSValue::decode(stream), controller); } @@ -1661,10 +1648,10 @@ extern "C" void ArrayBufferSink__onReady(JSC__JSValue controllerValue, JSC__JSVa { WebCore::JSReadableArrayBufferSinkController* controller = JSC::jsCast<WebCore::JSReadableArrayBufferSinkController*>(JSC::JSValue::decode(controllerValue).getObject()); - JSC::JSFunction *function = controller->m_onPull.get(); + JSC::JSFunction* function = controller->m_onPull.get(); if (function == nullptr) return; - JSC::JSGlobalObject *globalObject = controller->globalObject(); + JSC::JSGlobalObject* globalObject = controller->globalObject(); auto callData = JSC::getCallData(function); JSC::MarkedArgumentBuffer arguments; @@ -1677,19 +1664,18 @@ extern "C" void ArrayBufferSink__onReady(JSC__JSValue controllerValue, JSC__JSVa extern "C" void ArrayBufferSink__onStart(JSC__JSValue controllerValue) { - } extern "C" void ArrayBufferSink__onClose(JSC__JSValue controllerValue, JSC__JSValue reason) { WebCore::JSReadableArrayBufferSinkController* controller = JSC::jsCast<WebCore::JSReadableArrayBufferSinkController*>(JSC::JSValue::decode(controllerValue).getObject()); - JSC::JSFunction *function = controller->m_onClose.get(); + JSC::JSFunction* function = controller->m_onClose.get(); if (function == nullptr) return; // only call close once controller->m_onClose.clear(); - JSC::JSGlobalObject *globalObject = controller->globalObject(); + JSC::JSGlobalObject* globalObject = controller->globalObject(); auto callData = JSC::getCallData(function); JSC::MarkedArgumentBuffer arguments; @@ -1700,7 +1686,6 @@ extern "C" void ArrayBufferSink__onClose(JSC__JSValue controllerValue, JSC__JSVa JSC::call(globalObject, function, callData, JSC::jsUndefined(), arguments); } - extern "C" JSC__JSValue FileSink__createObject(JSC__JSGlobalObject* arg0, void* sinkPtr) { auto& vm = arg0->vm(); @@ -1728,7 +1713,6 @@ extern "C" void FileSink__detachPtr(JSC__JSValue JSValue0) sink->detach(); return; } - if (auto* controller = JSC::jsDynamicCast<WebCore::JSReadableFileSinkController*>(JSC::JSValue::decode(JSValue0))) { controller->detach(); @@ -1736,13 +1720,13 @@ extern "C" void FileSink__detachPtr(JSC__JSValue JSValue0) } } -extern "C" JSC__JSValue FileSink__assignToStream(JSC__JSGlobalObject* arg0, JSC__JSValue stream, void* sinkPtr, void **controllerValue) +extern "C" JSC__JSValue FileSink__assignToStream(JSC__JSGlobalObject* arg0, JSC__JSValue stream, void* sinkPtr, void** controllerValue) { auto& vm = arg0->vm(); Zig::GlobalObject* globalObject = reinterpret_cast<Zig::GlobalObject*>(arg0); JSC::Structure* structure = WebCore::getDOMStructure<WebCore::JSReadableFileSinkController>(vm, *globalObject); - WebCore::JSReadableFileSinkController *controller = WebCore::JSReadableFileSinkController::create(vm, globalObject, structure, sinkPtr); + WebCore::JSReadableFileSinkController* controller = WebCore::JSReadableFileSinkController::create(vm, globalObject, structure, sinkPtr); *controllerValue = reinterpret_cast<void*>(JSC::JSValue::encode(controller)); return globalObject->assignToStream(JSC::JSValue::decode(stream), controller); } @@ -1751,10 +1735,10 @@ extern "C" void FileSink__onReady(JSC__JSValue controllerValue, JSC__JSValue amt { WebCore::JSReadableFileSinkController* controller = JSC::jsCast<WebCore::JSReadableFileSinkController*>(JSC::JSValue::decode(controllerValue).getObject()); - JSC::JSFunction *function = controller->m_onPull.get(); + JSC::JSFunction* function = controller->m_onPull.get(); if (function == nullptr) return; - JSC::JSGlobalObject *globalObject = controller->globalObject(); + JSC::JSGlobalObject* globalObject = controller->globalObject(); auto callData = JSC::getCallData(function); JSC::MarkedArgumentBuffer arguments; @@ -1767,19 +1751,18 @@ extern "C" void FileSink__onReady(JSC__JSValue controllerValue, JSC__JSValue amt extern "C" void FileSink__onStart(JSC__JSValue controllerValue) { - } extern "C" void FileSink__onClose(JSC__JSValue controllerValue, JSC__JSValue reason) { WebCore::JSReadableFileSinkController* controller = JSC::jsCast<WebCore::JSReadableFileSinkController*>(JSC::JSValue::decode(controllerValue).getObject()); - JSC::JSFunction *function = controller->m_onClose.get(); + JSC::JSFunction* function = controller->m_onClose.get(); if (function == nullptr) return; // only call close once controller->m_onClose.clear(); - JSC::JSGlobalObject *globalObject = controller->globalObject(); + JSC::JSGlobalObject* globalObject = controller->globalObject(); auto callData = JSC::getCallData(function); JSC::MarkedArgumentBuffer arguments; @@ -1790,7 +1773,6 @@ extern "C" void FileSink__onClose(JSC__JSValue controllerValue, JSC__JSValue rea JSC::call(globalObject, function, callData, JSC::jsUndefined(), arguments); } - extern "C" JSC__JSValue HTTPResponseSink__createObject(JSC__JSGlobalObject* arg0, void* sinkPtr) { auto& vm = arg0->vm(); @@ -1818,7 +1800,6 @@ extern "C" void HTTPResponseSink__detachPtr(JSC__JSValue JSValue0) sink->detach(); return; } - if (auto* controller = JSC::jsDynamicCast<WebCore::JSReadableHTTPResponseSinkController*>(JSC::JSValue::decode(JSValue0))) { controller->detach(); @@ -1826,13 +1807,13 @@ extern "C" void HTTPResponseSink__detachPtr(JSC__JSValue JSValue0) } } -extern "C" JSC__JSValue HTTPResponseSink__assignToStream(JSC__JSGlobalObject* arg0, JSC__JSValue stream, void* sinkPtr, void **controllerValue) +extern "C" JSC__JSValue HTTPResponseSink__assignToStream(JSC__JSGlobalObject* arg0, JSC__JSValue stream, void* sinkPtr, void** controllerValue) { auto& vm = arg0->vm(); Zig::GlobalObject* globalObject = reinterpret_cast<Zig::GlobalObject*>(arg0); JSC::Structure* structure = WebCore::getDOMStructure<WebCore::JSReadableHTTPResponseSinkController>(vm, *globalObject); - WebCore::JSReadableHTTPResponseSinkController *controller = WebCore::JSReadableHTTPResponseSinkController::create(vm, globalObject, structure, sinkPtr); + WebCore::JSReadableHTTPResponseSinkController* controller = WebCore::JSReadableHTTPResponseSinkController::create(vm, globalObject, structure, sinkPtr); *controllerValue = reinterpret_cast<void*>(JSC::JSValue::encode(controller)); return globalObject->assignToStream(JSC::JSValue::decode(stream), controller); } @@ -1841,10 +1822,10 @@ extern "C" void HTTPResponseSink__onReady(JSC__JSValue controllerValue, JSC__JSV { WebCore::JSReadableHTTPResponseSinkController* controller = JSC::jsCast<WebCore::JSReadableHTTPResponseSinkController*>(JSC::JSValue::decode(controllerValue).getObject()); - JSC::JSFunction *function = controller->m_onPull.get(); + JSC::JSFunction* function = controller->m_onPull.get(); if (function == nullptr) return; - JSC::JSGlobalObject *globalObject = controller->globalObject(); + JSC::JSGlobalObject* globalObject = controller->globalObject(); auto callData = JSC::getCallData(function); JSC::MarkedArgumentBuffer arguments; @@ -1857,19 +1838,18 @@ extern "C" void HTTPResponseSink__onReady(JSC__JSValue controllerValue, JSC__JSV extern "C" void HTTPResponseSink__onStart(JSC__JSValue controllerValue) { - } extern "C" void HTTPResponseSink__onClose(JSC__JSValue controllerValue, JSC__JSValue reason) { WebCore::JSReadableHTTPResponseSinkController* controller = JSC::jsCast<WebCore::JSReadableHTTPResponseSinkController*>(JSC::JSValue::decode(controllerValue).getObject()); - JSC::JSFunction *function = controller->m_onClose.get(); + JSC::JSFunction* function = controller->m_onClose.get(); if (function == nullptr) return; // only call close once controller->m_onClose.clear(); - JSC::JSGlobalObject *globalObject = controller->globalObject(); + JSC::JSGlobalObject* globalObject = controller->globalObject(); auto callData = JSC::getCallData(function); JSC::MarkedArgumentBuffer arguments; @@ -1880,7 +1860,6 @@ extern "C" void HTTPResponseSink__onClose(JSC__JSValue controllerValue, JSC__JSV JSC::call(globalObject, function, callData, JSC::jsUndefined(), arguments); } - extern "C" JSC__JSValue HTTPSResponseSink__createObject(JSC__JSGlobalObject* arg0, void* sinkPtr) { auto& vm = arg0->vm(); @@ -1908,7 +1887,6 @@ extern "C" void HTTPSResponseSink__detachPtr(JSC__JSValue JSValue0) sink->detach(); return; } - if (auto* controller = JSC::jsDynamicCast<WebCore::JSReadableHTTPSResponseSinkController*>(JSC::JSValue::decode(JSValue0))) { controller->detach(); @@ -1916,13 +1894,13 @@ extern "C" void HTTPSResponseSink__detachPtr(JSC__JSValue JSValue0) } } -extern "C" JSC__JSValue HTTPSResponseSink__assignToStream(JSC__JSGlobalObject* arg0, JSC__JSValue stream, void* sinkPtr, void **controllerValue) +extern "C" JSC__JSValue HTTPSResponseSink__assignToStream(JSC__JSGlobalObject* arg0, JSC__JSValue stream, void* sinkPtr, void** controllerValue) { auto& vm = arg0->vm(); Zig::GlobalObject* globalObject = reinterpret_cast<Zig::GlobalObject*>(arg0); JSC::Structure* structure = WebCore::getDOMStructure<WebCore::JSReadableHTTPSResponseSinkController>(vm, *globalObject); - WebCore::JSReadableHTTPSResponseSinkController *controller = WebCore::JSReadableHTTPSResponseSinkController::create(vm, globalObject, structure, sinkPtr); + WebCore::JSReadableHTTPSResponseSinkController* controller = WebCore::JSReadableHTTPSResponseSinkController::create(vm, globalObject, structure, sinkPtr); *controllerValue = reinterpret_cast<void*>(JSC::JSValue::encode(controller)); return globalObject->assignToStream(JSC::JSValue::decode(stream), controller); } @@ -1931,10 +1909,10 @@ extern "C" void HTTPSResponseSink__onReady(JSC__JSValue controllerValue, JSC__JS { WebCore::JSReadableHTTPSResponseSinkController* controller = JSC::jsCast<WebCore::JSReadableHTTPSResponseSinkController*>(JSC::JSValue::decode(controllerValue).getObject()); - JSC::JSFunction *function = controller->m_onPull.get(); + JSC::JSFunction* function = controller->m_onPull.get(); if (function == nullptr) return; - JSC::JSGlobalObject *globalObject = controller->globalObject(); + JSC::JSGlobalObject* globalObject = controller->globalObject(); auto callData = JSC::getCallData(function); JSC::MarkedArgumentBuffer arguments; @@ -1947,19 +1925,18 @@ extern "C" void HTTPSResponseSink__onReady(JSC__JSValue controllerValue, JSC__JS extern "C" void HTTPSResponseSink__onStart(JSC__JSValue controllerValue) { - } extern "C" void HTTPSResponseSink__onClose(JSC__JSValue controllerValue, JSC__JSValue reason) { WebCore::JSReadableHTTPSResponseSinkController* controller = JSC::jsCast<WebCore::JSReadableHTTPSResponseSinkController*>(JSC::JSValue::decode(controllerValue).getObject()); - JSC::JSFunction *function = controller->m_onClose.get(); + JSC::JSFunction* function = controller->m_onClose.get(); if (function == nullptr) return; // only call close once controller->m_onClose.clear(); - JSC::JSGlobalObject *globalObject = controller->globalObject(); + JSC::JSGlobalObject* globalObject = controller->globalObject(); auto callData = JSC::getCallData(function); JSC::MarkedArgumentBuffer arguments; @@ -1969,4 +1946,3 @@ extern "C" void HTTPSResponseSink__onClose(JSC__JSValue controllerValue, JSC__JS arguments.append(JSC::JSValue::decode(reason)); JSC::call(globalObject, function, callData, JSC::jsUndefined(), arguments); } - diff --git a/src/bun.js/bindings/JSSink.h b/src/bun.js/bindings/JSSink.h index 2c9d5e2a6..68caf12fc 100644 --- a/src/bun.js/bindings/JSSink.h +++ b/src/bun.js/bindings/JSSink.h @@ -1,6 +1,6 @@ // AUTO-GENERATED FILE. DO NOT EDIT. -// Generated by 'make generate-sink' at 2022-11-13T22:44:00.279Z +// Generated by 'make generate-sink' at 2022-11-20T12:51:04.403Z // #pragma once @@ -17,683 +17,578 @@ namespace WebCore { using namespace JSC; JSC_DECLARE_HOST_FUNCTION(functionStartDirectStream); -class JSArrayBufferSinkConstructor final : public JSC::InternalFunction { - public: - using Base = JSC::InternalFunction; - static JSArrayBufferSinkConstructor* create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure, JSC::JSObject* prototype); - static constexpr SinkID Sink = SinkID::ArrayBufferSink; - - static constexpr unsigned StructureFlags = Base::StructureFlags; - static constexpr bool needsDestruction = false; - - DECLARE_EXPORT_INFO; - template<typename, JSC::SubspaceAccess mode> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) - { - if constexpr (mode == JSC::SubspaceAccess::Concurrently) - return nullptr; - return WebCore::subspaceForImpl<JSArrayBufferSinkConstructor, WebCore::UseCustomHeapCellType::No>( - vm, - [](auto& spaces) { return spaces.m_clientSubspaceForJSSinkConstructor.get(); }, - [](auto& spaces, auto&& space) { spaces.m_clientSubspaceForJSSinkConstructor = WTFMove(space); }, - [](auto& spaces) { return spaces.m_subspaceForJSSinkConstructor.get(); }, - [](auto& spaces, auto&& space) { spaces.m_subspaceForJSSinkConstructor = WTFMove(space); }); - } - - static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) - { - return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::InternalFunctionType, StructureFlags), info()); - } - void initializeProperties(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSObject* prototype); - - - // Must be defined for each specialization class. - static JSC::EncodedJSValue JSC_HOST_CALL_ATTRIBUTES construct(JSC::JSGlobalObject*, JSC::CallFrame*); - - private: - JSArrayBufferSinkConstructor(JSC::VM& vm, JSC::Structure* structure, JSC::NativeFunction nativeFunction) - : Base(vm, structure, nativeFunction, nativeFunction) - - { - } - - void finishCreation(JSC::VM&, JSC::JSGlobalObject* globalObject, JSC::JSObject* prototype); - }; - - class JSArrayBufferSink final : public JSC::JSDestructibleObject { - public: - using Base = JSC::JSDestructibleObject; - static JSArrayBufferSink* create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure, void* sinkPtr); - static constexpr SinkID Sink = SinkID::ArrayBufferSink; - - DECLARE_EXPORT_INFO; - template<typename, JSC::SubspaceAccess mode> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) - { - if constexpr (mode == JSC::SubspaceAccess::Concurrently) - return nullptr; - return WebCore::subspaceForImpl<JSArrayBufferSink, WebCore::UseCustomHeapCellType::No>( - vm, - [](auto& spaces) { return spaces.m_clientSubspaceForJSSink.get(); }, - [](auto& spaces, auto&& space) { spaces.m_clientSubspaceForJSSink = WTFMove(space); }, - [](auto& spaces) { return spaces.m_subspaceForJSSink.get(); }, - [](auto& spaces, auto&& space) { spaces.m_subspaceForJSSink = WTFMove(space); }); - } - - static void destroy(JSC::JSCell*); - static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) - { - return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), info()); - } - - static JSObject* createPrototype(VM& vm, JSDOMGlobalObject& globalObject); - - ~JSArrayBufferSink(); - - void* wrapped() const { return m_sinkPtr; } - - void detach() { - m_sinkPtr = nullptr; - - } - - static void analyzeHeap(JSCell*, JSC::HeapAnalyzer&); - - void* m_sinkPtr; - - JSArrayBufferSink(JSC::VM& vm, JSC::Structure* structure, void* sinkPtr) - : Base(vm, structure) - { - m_sinkPtr = sinkPtr; - } - - void finishCreation(JSC::VM&); - }; - - - - class JSReadableArrayBufferSinkController final : public JSC::JSDestructibleObject { - public: - using Base = JSC::JSDestructibleObject; - static JSReadableArrayBufferSinkController* create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure, void* sinkPtr); - static constexpr SinkID Sink = SinkID::ArrayBufferSink; - - DECLARE_EXPORT_INFO; - template<typename, JSC::SubspaceAccess mode> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) - { - if constexpr (mode == JSC::SubspaceAccess::Concurrently) - return nullptr; - return WebCore::subspaceForImpl<JSReadableArrayBufferSinkController, WebCore::UseCustomHeapCellType::No>( - vm, - [](auto& spaces) { return spaces.m_clientSubspaceForJSSinkController.get(); }, - [](auto& spaces, auto&& space) { spaces.m_clientSubspaceForJSSinkController = WTFMove(space); }, - [](auto& spaces) { return spaces.m_subspaceForJSSinkController.get(); }, - [](auto& spaces, auto&& space) { spaces.m_subspaceForJSSinkController = WTFMove(space); }); - } - - static void destroy(JSC::JSCell*); - static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) - { - return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), info()); - } - static JSObject* createPrototype(VM& vm, JSDOMGlobalObject& globalObject); - - ~JSReadableArrayBufferSinkController(); - - - void* wrapped() const { return m_sinkPtr; } - void detach(); - - void start(JSC::JSGlobalObject *globalObject, JSC::JSValue readableStream, JSC::JSFunction *onPull, JSC::JSFunction *onClose); - DECLARE_VISIT_CHILDREN; - - static void analyzeHeap(JSCell*, JSC::HeapAnalyzer&); - - bool hasPendingActivity() { return m_hasPendingActivity; } - - void* m_sinkPtr; - bool m_hasPendingActivity; - mutable WriteBarrier<JSC::JSFunction> m_onPull; - mutable WriteBarrier<JSC::JSFunction> m_onClose; - mutable JSC::Weak<JSObject> m_weakReadableStream; - JSC::Weak<JSReadableArrayBufferSinkController> m_weakThis; - - JSReadableArrayBufferSinkController(JSC::VM& vm, JSC::Structure* structure, void* sinkPtr) - : Base(vm, structure) - { - m_sinkPtr = sinkPtr; - m_hasPendingActivity = true; - m_weakThis = JSC::Weak<JSReadableArrayBufferSinkController>(this, getOwner()); - } - - void finishCreation(JSC::VM&); - - class Owner final : public JSC::WeakHandleOwner { - public: - bool isReachableFromOpaqueRoots(JSC::Handle<JSC::Unknown> handle, void* context, JSC::AbstractSlotVisitor&, const char**) final - { - auto* controller = JSC::jsCast<JSReadableArrayBufferSinkController*>(handle.slot()->asCell()); - return controller->hasPendingActivity(); - } - void finalize(JSC::Handle<JSC::Unknown>, void* context) final {} - }; - - static JSC::WeakHandleOwner* getOwner() - { - static NeverDestroyed<Owner> m_owner; - return &m_owner.get(); - } - }; +class JSArrayBufferSinkConstructor final : public JSC::InternalFunction { +public: + using Base = JSC::InternalFunction; + static JSArrayBufferSinkConstructor* create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure, JSC::JSObject* prototype); + static constexpr SinkID Sink = SinkID::ArrayBufferSink; + + static constexpr unsigned StructureFlags = Base::StructureFlags; + static constexpr bool needsDestruction = false; + + DECLARE_EXPORT_INFO; + template<typename, JSC::SubspaceAccess mode> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) + { + if constexpr (mode == JSC::SubspaceAccess::Concurrently) + return nullptr; + return WebCore::subspaceForImpl<JSArrayBufferSinkConstructor, WebCore::UseCustomHeapCellType::No>( + vm, + [](auto& spaces) { return spaces.m_clientSubspaceForJSSinkConstructor.get(); }, + [](auto& spaces, auto&& space) { spaces.m_clientSubspaceForJSSinkConstructor = WTFMove(space); }, + [](auto& spaces) { return spaces.m_subspaceForJSSinkConstructor.get(); }, + [](auto& spaces, auto&& space) { spaces.m_subspaceForJSSinkConstructor = WTFMove(space); }); + } + + static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) + { + return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::InternalFunctionType, StructureFlags), info()); + } + void initializeProperties(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSObject* prototype); + + // Must be defined for each specialization class. + static JSC::EncodedJSValue JSC_HOST_CALL_ATTRIBUTES construct(JSC::JSGlobalObject*, JSC::CallFrame*); + +private: + JSArrayBufferSinkConstructor(JSC::VM& vm, JSC::Structure* structure, JSC::NativeFunction nativeFunction) + : Base(vm, structure, nativeFunction, nativeFunction) + + { + } + + void finishCreation(JSC::VM&, JSC::JSGlobalObject* globalObject, JSC::JSObject* prototype); +}; + +class JSArrayBufferSink final : public JSC::JSDestructibleObject { +public: + using Base = JSC::JSDestructibleObject; + static JSArrayBufferSink* create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure, void* sinkPtr); + static constexpr SinkID Sink = SinkID::ArrayBufferSink; + + DECLARE_EXPORT_INFO; + template<typename, JSC::SubspaceAccess mode> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) + { + if constexpr (mode == JSC::SubspaceAccess::Concurrently) + return nullptr; + return WebCore::subspaceForImpl<JSArrayBufferSink, WebCore::UseCustomHeapCellType::No>( + vm, + [](auto& spaces) { return spaces.m_clientSubspaceForJSSink.get(); }, + [](auto& spaces, auto&& space) { spaces.m_clientSubspaceForJSSink = WTFMove(space); }, + [](auto& spaces) { return spaces.m_subspaceForJSSink.get(); }, + [](auto& spaces, auto&& space) { spaces.m_subspaceForJSSink = WTFMove(space); }); + } + + static void destroy(JSC::JSCell*); + static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) + { + return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), info()); + } + + static JSObject* createPrototype(VM& vm, JSDOMGlobalObject& globalObject); + + ~JSArrayBufferSink(); + + void* wrapped() const { return m_sinkPtr; } + DECLARE_VISIT_CHILDREN; + + void detach() + { + m_sinkPtr = nullptr; + } + + static void analyzeHeap(JSCell*, JSC::HeapAnalyzer&); + + void* m_sinkPtr; + + JSArrayBufferSink(JSC::VM& vm, JSC::Structure* structure, void* sinkPtr) + : Base(vm, structure) + { + m_sinkPtr = sinkPtr; + } + + void finishCreation(JSC::VM&); +}; + +class JSReadableArrayBufferSinkController final : public JSC::JSDestructibleObject { +public: + using Base = JSC::JSDestructibleObject; + static JSReadableArrayBufferSinkController* create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure, void* sinkPtr); + static constexpr SinkID Sink = SinkID::ArrayBufferSink; + + DECLARE_EXPORT_INFO; + template<typename, JSC::SubspaceAccess mode> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) + { + if constexpr (mode == JSC::SubspaceAccess::Concurrently) + return nullptr; + return WebCore::subspaceForImpl<JSReadableArrayBufferSinkController, WebCore::UseCustomHeapCellType::No>( + vm, + [](auto& spaces) { return spaces.m_clientSubspaceForJSSinkController.get(); }, + [](auto& spaces, auto&& space) { spaces.m_clientSubspaceForJSSinkController = WTFMove(space); }, + [](auto& spaces) { return spaces.m_subspaceForJSSinkController.get(); }, + [](auto& spaces, auto&& space) { spaces.m_subspaceForJSSinkController = WTFMove(space); }); + } + + static void destroy(JSC::JSCell*); + static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) + { + return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), info()); + } + static JSObject* createPrototype(VM& vm, JSDOMGlobalObject& globalObject); + + ~JSReadableArrayBufferSinkController(); + + void* wrapped() const { return m_sinkPtr; } + void detach(); + + void start(JSC::JSGlobalObject* globalObject, JSC::JSValue readableStream, JSC::JSFunction* onPull, JSC::JSFunction* onClose); + DECLARE_VISIT_CHILDREN; + + static void analyzeHeap(JSCell*, JSC::HeapAnalyzer&); + + void* m_sinkPtr; + mutable WriteBarrier<JSC::JSFunction> m_onPull; + mutable WriteBarrier<JSC::JSFunction> m_onClose; + mutable JSC::Weak<JSObject> m_weakReadableStream; + + JSReadableArrayBufferSinkController(JSC::VM& vm, JSC::Structure* structure, void* sinkPtr) + : Base(vm, structure) + { + m_sinkPtr = sinkPtr; + } + + void finishCreation(JSC::VM&); +}; JSC_DECLARE_CUSTOM_GETTER(functionArrayBufferSink__getter); - -class JSFileSinkConstructor final : public JSC::InternalFunction { - public: - using Base = JSC::InternalFunction; - static JSFileSinkConstructor* create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure, JSC::JSObject* prototype); - static constexpr SinkID Sink = SinkID::FileSink; - - static constexpr unsigned StructureFlags = Base::StructureFlags; - static constexpr bool needsDestruction = false; - - DECLARE_EXPORT_INFO; - template<typename, JSC::SubspaceAccess mode> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) - { - if constexpr (mode == JSC::SubspaceAccess::Concurrently) - return nullptr; - return WebCore::subspaceForImpl<JSFileSinkConstructor, WebCore::UseCustomHeapCellType::No>( - vm, - [](auto& spaces) { return spaces.m_clientSubspaceForJSSinkConstructor.get(); }, - [](auto& spaces, auto&& space) { spaces.m_clientSubspaceForJSSinkConstructor = WTFMove(space); }, - [](auto& spaces) { return spaces.m_subspaceForJSSinkConstructor.get(); }, - [](auto& spaces, auto&& space) { spaces.m_subspaceForJSSinkConstructor = WTFMove(space); }); - } - - static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) - { - return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::InternalFunctionType, StructureFlags), info()); - } - void initializeProperties(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSObject* prototype); - - - // Must be defined for each specialization class. - static JSC::EncodedJSValue JSC_HOST_CALL_ATTRIBUTES construct(JSC::JSGlobalObject*, JSC::CallFrame*); - - private: - JSFileSinkConstructor(JSC::VM& vm, JSC::Structure* structure, JSC::NativeFunction nativeFunction) - : Base(vm, structure, nativeFunction, nativeFunction) - - { - } - - void finishCreation(JSC::VM&, JSC::JSGlobalObject* globalObject, JSC::JSObject* prototype); - }; - - class JSFileSink final : public JSC::JSDestructibleObject { - public: - using Base = JSC::JSDestructibleObject; - static JSFileSink* create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure, void* sinkPtr); - static constexpr SinkID Sink = SinkID::FileSink; - - DECLARE_EXPORT_INFO; - template<typename, JSC::SubspaceAccess mode> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) - { - if constexpr (mode == JSC::SubspaceAccess::Concurrently) - return nullptr; - return WebCore::subspaceForImpl<JSFileSink, WebCore::UseCustomHeapCellType::No>( - vm, - [](auto& spaces) { return spaces.m_clientSubspaceForJSSink.get(); }, - [](auto& spaces, auto&& space) { spaces.m_clientSubspaceForJSSink = WTFMove(space); }, - [](auto& spaces) { return spaces.m_subspaceForJSSink.get(); }, - [](auto& spaces, auto&& space) { spaces.m_subspaceForJSSink = WTFMove(space); }); - } - - static void destroy(JSC::JSCell*); - static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) - { - return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), info()); - } - - static JSObject* createPrototype(VM& vm, JSDOMGlobalObject& globalObject); - - ~JSFileSink(); - - void* wrapped() const { return m_sinkPtr; } - - void detach() { - m_sinkPtr = nullptr; - - } - - static void analyzeHeap(JSCell*, JSC::HeapAnalyzer&); - - void* m_sinkPtr; - - JSFileSink(JSC::VM& vm, JSC::Structure* structure, void* sinkPtr) - : Base(vm, structure) - { - m_sinkPtr = sinkPtr; - } - - void finishCreation(JSC::VM&); - }; - - - - class JSReadableFileSinkController final : public JSC::JSDestructibleObject { - public: - using Base = JSC::JSDestructibleObject; - static JSReadableFileSinkController* create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure, void* sinkPtr); - static constexpr SinkID Sink = SinkID::FileSink; - - DECLARE_EXPORT_INFO; - template<typename, JSC::SubspaceAccess mode> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) - { - if constexpr (mode == JSC::SubspaceAccess::Concurrently) - return nullptr; - return WebCore::subspaceForImpl<JSReadableFileSinkController, WebCore::UseCustomHeapCellType::No>( - vm, - [](auto& spaces) { return spaces.m_clientSubspaceForJSSinkController.get(); }, - [](auto& spaces, auto&& space) { spaces.m_clientSubspaceForJSSinkController = WTFMove(space); }, - [](auto& spaces) { return spaces.m_subspaceForJSSinkController.get(); }, - [](auto& spaces, auto&& space) { spaces.m_subspaceForJSSinkController = WTFMove(space); }); - } - - static void destroy(JSC::JSCell*); - static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) - { - return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), info()); - } - static JSObject* createPrototype(VM& vm, JSDOMGlobalObject& globalObject); - - ~JSReadableFileSinkController(); - - - void* wrapped() const { return m_sinkPtr; } - void detach(); - - void start(JSC::JSGlobalObject *globalObject, JSC::JSValue readableStream, JSC::JSFunction *onPull, JSC::JSFunction *onClose); - DECLARE_VISIT_CHILDREN; - - static void analyzeHeap(JSCell*, JSC::HeapAnalyzer&); - - bool hasPendingActivity() { return m_hasPendingActivity; } - - void* m_sinkPtr; - bool m_hasPendingActivity; - mutable WriteBarrier<JSC::JSFunction> m_onPull; - mutable WriteBarrier<JSC::JSFunction> m_onClose; - mutable JSC::Weak<JSObject> m_weakReadableStream; - JSC::Weak<JSReadableFileSinkController> m_weakThis; - - JSReadableFileSinkController(JSC::VM& vm, JSC::Structure* structure, void* sinkPtr) - : Base(vm, structure) - { - m_sinkPtr = sinkPtr; - m_hasPendingActivity = true; - m_weakThis = JSC::Weak<JSReadableFileSinkController>(this, getOwner()); - } - - void finishCreation(JSC::VM&); - - class Owner final : public JSC::WeakHandleOwner { - public: - bool isReachableFromOpaqueRoots(JSC::Handle<JSC::Unknown> handle, void* context, JSC::AbstractSlotVisitor&, const char**) final - { - auto* controller = JSC::jsCast<JSReadableFileSinkController*>(handle.slot()->asCell()); - return controller->hasPendingActivity(); - } - void finalize(JSC::Handle<JSC::Unknown>, void* context) final {} - }; - - static JSC::WeakHandleOwner* getOwner() - { - static NeverDestroyed<Owner> m_owner; - return &m_owner.get(); - } - }; +class JSFileSinkConstructor final : public JSC::InternalFunction { +public: + using Base = JSC::InternalFunction; + static JSFileSinkConstructor* create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure, JSC::JSObject* prototype); + static constexpr SinkID Sink = SinkID::FileSink; + + static constexpr unsigned StructureFlags = Base::StructureFlags; + static constexpr bool needsDestruction = false; + + DECLARE_EXPORT_INFO; + template<typename, JSC::SubspaceAccess mode> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) + { + if constexpr (mode == JSC::SubspaceAccess::Concurrently) + return nullptr; + return WebCore::subspaceForImpl<JSFileSinkConstructor, WebCore::UseCustomHeapCellType::No>( + vm, + [](auto& spaces) { return spaces.m_clientSubspaceForJSSinkConstructor.get(); }, + [](auto& spaces, auto&& space) { spaces.m_clientSubspaceForJSSinkConstructor = WTFMove(space); }, + [](auto& spaces) { return spaces.m_subspaceForJSSinkConstructor.get(); }, + [](auto& spaces, auto&& space) { spaces.m_subspaceForJSSinkConstructor = WTFMove(space); }); + } + + static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) + { + return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::InternalFunctionType, StructureFlags), info()); + } + void initializeProperties(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSObject* prototype); + + // Must be defined for each specialization class. + static JSC::EncodedJSValue JSC_HOST_CALL_ATTRIBUTES construct(JSC::JSGlobalObject*, JSC::CallFrame*); + +private: + JSFileSinkConstructor(JSC::VM& vm, JSC::Structure* structure, JSC::NativeFunction nativeFunction) + : Base(vm, structure, nativeFunction, nativeFunction) + + { + } + + void finishCreation(JSC::VM&, JSC::JSGlobalObject* globalObject, JSC::JSObject* prototype); +}; + +class JSFileSink final : public JSC::JSDestructibleObject { +public: + using Base = JSC::JSDestructibleObject; + static JSFileSink* create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure, void* sinkPtr); + static constexpr SinkID Sink = SinkID::FileSink; + + DECLARE_EXPORT_INFO; + template<typename, JSC::SubspaceAccess mode> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) + { + if constexpr (mode == JSC::SubspaceAccess::Concurrently) + return nullptr; + return WebCore::subspaceForImpl<JSFileSink, WebCore::UseCustomHeapCellType::No>( + vm, + [](auto& spaces) { return spaces.m_clientSubspaceForJSSink.get(); }, + [](auto& spaces, auto&& space) { spaces.m_clientSubspaceForJSSink = WTFMove(space); }, + [](auto& spaces) { return spaces.m_subspaceForJSSink.get(); }, + [](auto& spaces, auto&& space) { spaces.m_subspaceForJSSink = WTFMove(space); }); + } + + static void destroy(JSC::JSCell*); + static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) + { + return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), info()); + } + + static JSObject* createPrototype(VM& vm, JSDOMGlobalObject& globalObject); + + ~JSFileSink(); + + void* wrapped() const { return m_sinkPtr; } + DECLARE_VISIT_CHILDREN; + + void detach() + { + m_sinkPtr = nullptr; + } + + static void analyzeHeap(JSCell*, JSC::HeapAnalyzer&); + + void* m_sinkPtr; + + JSFileSink(JSC::VM& vm, JSC::Structure* structure, void* sinkPtr) + : Base(vm, structure) + { + m_sinkPtr = sinkPtr; + } + + void finishCreation(JSC::VM&); +}; + +class JSReadableFileSinkController final : public JSC::JSDestructibleObject { +public: + using Base = JSC::JSDestructibleObject; + static JSReadableFileSinkController* create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure, void* sinkPtr); + static constexpr SinkID Sink = SinkID::FileSink; + + DECLARE_EXPORT_INFO; + template<typename, JSC::SubspaceAccess mode> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) + { + if constexpr (mode == JSC::SubspaceAccess::Concurrently) + return nullptr; + return WebCore::subspaceForImpl<JSReadableFileSinkController, WebCore::UseCustomHeapCellType::No>( + vm, + [](auto& spaces) { return spaces.m_clientSubspaceForJSSinkController.get(); }, + [](auto& spaces, auto&& space) { spaces.m_clientSubspaceForJSSinkController = WTFMove(space); }, + [](auto& spaces) { return spaces.m_subspaceForJSSinkController.get(); }, + [](auto& spaces, auto&& space) { spaces.m_subspaceForJSSinkController = WTFMove(space); }); + } + + static void destroy(JSC::JSCell*); + static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) + { + return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), info()); + } + static JSObject* createPrototype(VM& vm, JSDOMGlobalObject& globalObject); + + ~JSReadableFileSinkController(); + + void* wrapped() const { return m_sinkPtr; } + void detach(); + + void start(JSC::JSGlobalObject* globalObject, JSC::JSValue readableStream, JSC::JSFunction* onPull, JSC::JSFunction* onClose); + DECLARE_VISIT_CHILDREN; + + static void analyzeHeap(JSCell*, JSC::HeapAnalyzer&); + + void* m_sinkPtr; + mutable WriteBarrier<JSC::JSFunction> m_onPull; + mutable WriteBarrier<JSC::JSFunction> m_onClose; + mutable JSC::Weak<JSObject> m_weakReadableStream; + + JSReadableFileSinkController(JSC::VM& vm, JSC::Structure* structure, void* sinkPtr) + : Base(vm, structure) + { + m_sinkPtr = sinkPtr; + } + + void finishCreation(JSC::VM&); +}; JSC_DECLARE_CUSTOM_GETTER(functionFileSink__getter); - -class JSHTTPResponseSinkConstructor final : public JSC::InternalFunction { - public: - using Base = JSC::InternalFunction; - static JSHTTPResponseSinkConstructor* create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure, JSC::JSObject* prototype); - static constexpr SinkID Sink = SinkID::HTTPResponseSink; - - static constexpr unsigned StructureFlags = Base::StructureFlags; - static constexpr bool needsDestruction = false; - - DECLARE_EXPORT_INFO; - template<typename, JSC::SubspaceAccess mode> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) - { - if constexpr (mode == JSC::SubspaceAccess::Concurrently) - return nullptr; - return WebCore::subspaceForImpl<JSHTTPResponseSinkConstructor, WebCore::UseCustomHeapCellType::No>( - vm, - [](auto& spaces) { return spaces.m_clientSubspaceForJSSinkConstructor.get(); }, - [](auto& spaces, auto&& space) { spaces.m_clientSubspaceForJSSinkConstructor = WTFMove(space); }, - [](auto& spaces) { return spaces.m_subspaceForJSSinkConstructor.get(); }, - [](auto& spaces, auto&& space) { spaces.m_subspaceForJSSinkConstructor = WTFMove(space); }); - } - - static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) - { - return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::InternalFunctionType, StructureFlags), info()); - } - void initializeProperties(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSObject* prototype); - - - // Must be defined for each specialization class. - static JSC::EncodedJSValue JSC_HOST_CALL_ATTRIBUTES construct(JSC::JSGlobalObject*, JSC::CallFrame*); - - private: - JSHTTPResponseSinkConstructor(JSC::VM& vm, JSC::Structure* structure, JSC::NativeFunction nativeFunction) - : Base(vm, structure, nativeFunction, nativeFunction) - - { - } - - void finishCreation(JSC::VM&, JSC::JSGlobalObject* globalObject, JSC::JSObject* prototype); - }; - - class JSHTTPResponseSink final : public JSC::JSDestructibleObject { - public: - using Base = JSC::JSDestructibleObject; - static JSHTTPResponseSink* create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure, void* sinkPtr); - static constexpr SinkID Sink = SinkID::HTTPResponseSink; - - DECLARE_EXPORT_INFO; - template<typename, JSC::SubspaceAccess mode> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) - { - if constexpr (mode == JSC::SubspaceAccess::Concurrently) - return nullptr; - return WebCore::subspaceForImpl<JSHTTPResponseSink, WebCore::UseCustomHeapCellType::No>( - vm, - [](auto& spaces) { return spaces.m_clientSubspaceForJSSink.get(); }, - [](auto& spaces, auto&& space) { spaces.m_clientSubspaceForJSSink = WTFMove(space); }, - [](auto& spaces) { return spaces.m_subspaceForJSSink.get(); }, - [](auto& spaces, auto&& space) { spaces.m_subspaceForJSSink = WTFMove(space); }); - } - - static void destroy(JSC::JSCell*); - static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) - { - return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), info()); - } - - static JSObject* createPrototype(VM& vm, JSDOMGlobalObject& globalObject); - - ~JSHTTPResponseSink(); - - void* wrapped() const { return m_sinkPtr; } - - void detach() { - m_sinkPtr = nullptr; - - } - - static void analyzeHeap(JSCell*, JSC::HeapAnalyzer&); - - void* m_sinkPtr; - - JSHTTPResponseSink(JSC::VM& vm, JSC::Structure* structure, void* sinkPtr) - : Base(vm, structure) - { - m_sinkPtr = sinkPtr; - } - - void finishCreation(JSC::VM&); - }; - - - - class JSReadableHTTPResponseSinkController final : public JSC::JSDestructibleObject { - public: - using Base = JSC::JSDestructibleObject; - static JSReadableHTTPResponseSinkController* create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure, void* sinkPtr); - static constexpr SinkID Sink = SinkID::HTTPResponseSink; - - DECLARE_EXPORT_INFO; - template<typename, JSC::SubspaceAccess mode> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) - { - if constexpr (mode == JSC::SubspaceAccess::Concurrently) - return nullptr; - return WebCore::subspaceForImpl<JSReadableHTTPResponseSinkController, WebCore::UseCustomHeapCellType::No>( - vm, - [](auto& spaces) { return spaces.m_clientSubspaceForJSSinkController.get(); }, - [](auto& spaces, auto&& space) { spaces.m_clientSubspaceForJSSinkController = WTFMove(space); }, - [](auto& spaces) { return spaces.m_subspaceForJSSinkController.get(); }, - [](auto& spaces, auto&& space) { spaces.m_subspaceForJSSinkController = WTFMove(space); }); - } - - static void destroy(JSC::JSCell*); - static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) - { - return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), info()); - } - static JSObject* createPrototype(VM& vm, JSDOMGlobalObject& globalObject); - - ~JSReadableHTTPResponseSinkController(); - - - void* wrapped() const { return m_sinkPtr; } - void detach(); - - void start(JSC::JSGlobalObject *globalObject, JSC::JSValue readableStream, JSC::JSFunction *onPull, JSC::JSFunction *onClose); - DECLARE_VISIT_CHILDREN; - - static void analyzeHeap(JSCell*, JSC::HeapAnalyzer&); - - bool hasPendingActivity() { return m_hasPendingActivity; } - - void* m_sinkPtr; - bool m_hasPendingActivity; - mutable WriteBarrier<JSC::JSFunction> m_onPull; - mutable WriteBarrier<JSC::JSFunction> m_onClose; - mutable JSC::Weak<JSObject> m_weakReadableStream; - JSC::Weak<JSReadableHTTPResponseSinkController> m_weakThis; - - JSReadableHTTPResponseSinkController(JSC::VM& vm, JSC::Structure* structure, void* sinkPtr) - : Base(vm, structure) - { - m_sinkPtr = sinkPtr; - m_hasPendingActivity = true; - m_weakThis = JSC::Weak<JSReadableHTTPResponseSinkController>(this, getOwner()); - } - - void finishCreation(JSC::VM&); - - class Owner final : public JSC::WeakHandleOwner { - public: - bool isReachableFromOpaqueRoots(JSC::Handle<JSC::Unknown> handle, void* context, JSC::AbstractSlotVisitor&, const char**) final - { - auto* controller = JSC::jsCast<JSReadableHTTPResponseSinkController*>(handle.slot()->asCell()); - return controller->hasPendingActivity(); - } - void finalize(JSC::Handle<JSC::Unknown>, void* context) final {} - }; - - static JSC::WeakHandleOwner* getOwner() - { - static NeverDestroyed<Owner> m_owner; - return &m_owner.get(); - } - }; +class JSHTTPResponseSinkConstructor final : public JSC::InternalFunction { +public: + using Base = JSC::InternalFunction; + static JSHTTPResponseSinkConstructor* create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure, JSC::JSObject* prototype); + static constexpr SinkID Sink = SinkID::HTTPResponseSink; + + static constexpr unsigned StructureFlags = Base::StructureFlags; + static constexpr bool needsDestruction = false; + + DECLARE_EXPORT_INFO; + template<typename, JSC::SubspaceAccess mode> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) + { + if constexpr (mode == JSC::SubspaceAccess::Concurrently) + return nullptr; + return WebCore::subspaceForImpl<JSHTTPResponseSinkConstructor, WebCore::UseCustomHeapCellType::No>( + vm, + [](auto& spaces) { return spaces.m_clientSubspaceForJSSinkConstructor.get(); }, + [](auto& spaces, auto&& space) { spaces.m_clientSubspaceForJSSinkConstructor = WTFMove(space); }, + [](auto& spaces) { return spaces.m_subspaceForJSSinkConstructor.get(); }, + [](auto& spaces, auto&& space) { spaces.m_subspaceForJSSinkConstructor = WTFMove(space); }); + } + + static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) + { + return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::InternalFunctionType, StructureFlags), info()); + } + void initializeProperties(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSObject* prototype); + + // Must be defined for each specialization class. + static JSC::EncodedJSValue JSC_HOST_CALL_ATTRIBUTES construct(JSC::JSGlobalObject*, JSC::CallFrame*); + +private: + JSHTTPResponseSinkConstructor(JSC::VM& vm, JSC::Structure* structure, JSC::NativeFunction nativeFunction) + : Base(vm, structure, nativeFunction, nativeFunction) + + { + } + + void finishCreation(JSC::VM&, JSC::JSGlobalObject* globalObject, JSC::JSObject* prototype); +}; + +class JSHTTPResponseSink final : public JSC::JSDestructibleObject { +public: + using Base = JSC::JSDestructibleObject; + static JSHTTPResponseSink* create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure, void* sinkPtr); + static constexpr SinkID Sink = SinkID::HTTPResponseSink; + + DECLARE_EXPORT_INFO; + template<typename, JSC::SubspaceAccess mode> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) + { + if constexpr (mode == JSC::SubspaceAccess::Concurrently) + return nullptr; + return WebCore::subspaceForImpl<JSHTTPResponseSink, WebCore::UseCustomHeapCellType::No>( + vm, + [](auto& spaces) { return spaces.m_clientSubspaceForJSSink.get(); }, + [](auto& spaces, auto&& space) { spaces.m_clientSubspaceForJSSink = WTFMove(space); }, + [](auto& spaces) { return spaces.m_subspaceForJSSink.get(); }, + [](auto& spaces, auto&& space) { spaces.m_subspaceForJSSink = WTFMove(space); }); + } + + static void destroy(JSC::JSCell*); + static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) + { + return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), info()); + } + + static JSObject* createPrototype(VM& vm, JSDOMGlobalObject& globalObject); + + ~JSHTTPResponseSink(); + + void* wrapped() const { return m_sinkPtr; } + DECLARE_VISIT_CHILDREN; + + void detach() + { + m_sinkPtr = nullptr; + } + + static void analyzeHeap(JSCell*, JSC::HeapAnalyzer&); + + void* m_sinkPtr; + + JSHTTPResponseSink(JSC::VM& vm, JSC::Structure* structure, void* sinkPtr) + : Base(vm, structure) + { + m_sinkPtr = sinkPtr; + } + + void finishCreation(JSC::VM&); +}; + +class JSReadableHTTPResponseSinkController final : public JSC::JSDestructibleObject { +public: + using Base = JSC::JSDestructibleObject; + static JSReadableHTTPResponseSinkController* create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure, void* sinkPtr); + static constexpr SinkID Sink = SinkID::HTTPResponseSink; + + DECLARE_EXPORT_INFO; + template<typename, JSC::SubspaceAccess mode> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) + { + if constexpr (mode == JSC::SubspaceAccess::Concurrently) + return nullptr; + return WebCore::subspaceForImpl<JSReadableHTTPResponseSinkController, WebCore::UseCustomHeapCellType::No>( + vm, + [](auto& spaces) { return spaces.m_clientSubspaceForJSSinkController.get(); }, + [](auto& spaces, auto&& space) { spaces.m_clientSubspaceForJSSinkController = WTFMove(space); }, + [](auto& spaces) { return spaces.m_subspaceForJSSinkController.get(); }, + [](auto& spaces, auto&& space) { spaces.m_subspaceForJSSinkController = WTFMove(space); }); + } + + static void destroy(JSC::JSCell*); + static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) + { + return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), info()); + } + static JSObject* createPrototype(VM& vm, JSDOMGlobalObject& globalObject); + + ~JSReadableHTTPResponseSinkController(); + + void* wrapped() const { return m_sinkPtr; } + void detach(); + + void start(JSC::JSGlobalObject* globalObject, JSC::JSValue readableStream, JSC::JSFunction* onPull, JSC::JSFunction* onClose); + DECLARE_VISIT_CHILDREN; + + static void analyzeHeap(JSCell*, JSC::HeapAnalyzer&); + + void* m_sinkPtr; + mutable WriteBarrier<JSC::JSFunction> m_onPull; + mutable WriteBarrier<JSC::JSFunction> m_onClose; + mutable JSC::Weak<JSObject> m_weakReadableStream; + + JSReadableHTTPResponseSinkController(JSC::VM& vm, JSC::Structure* structure, void* sinkPtr) + : Base(vm, structure) + { + m_sinkPtr = sinkPtr; + } + + void finishCreation(JSC::VM&); +}; JSC_DECLARE_CUSTOM_GETTER(functionHTTPResponseSink__getter); - -class JSHTTPSResponseSinkConstructor final : public JSC::InternalFunction { - public: - using Base = JSC::InternalFunction; - static JSHTTPSResponseSinkConstructor* create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure, JSC::JSObject* prototype); - static constexpr SinkID Sink = SinkID::HTTPSResponseSink; - - static constexpr unsigned StructureFlags = Base::StructureFlags; - static constexpr bool needsDestruction = false; - - DECLARE_EXPORT_INFO; - template<typename, JSC::SubspaceAccess mode> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) - { - if constexpr (mode == JSC::SubspaceAccess::Concurrently) - return nullptr; - return WebCore::subspaceForImpl<JSHTTPSResponseSinkConstructor, WebCore::UseCustomHeapCellType::No>( - vm, - [](auto& spaces) { return spaces.m_clientSubspaceForJSSinkConstructor.get(); }, - [](auto& spaces, auto&& space) { spaces.m_clientSubspaceForJSSinkConstructor = WTFMove(space); }, - [](auto& spaces) { return spaces.m_subspaceForJSSinkConstructor.get(); }, - [](auto& spaces, auto&& space) { spaces.m_subspaceForJSSinkConstructor = WTFMove(space); }); - } - - static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) - { - return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::InternalFunctionType, StructureFlags), info()); - } - void initializeProperties(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSObject* prototype); - - - // Must be defined for each specialization class. - static JSC::EncodedJSValue JSC_HOST_CALL_ATTRIBUTES construct(JSC::JSGlobalObject*, JSC::CallFrame*); - - private: - JSHTTPSResponseSinkConstructor(JSC::VM& vm, JSC::Structure* structure, JSC::NativeFunction nativeFunction) - : Base(vm, structure, nativeFunction, nativeFunction) - - { - } - - void finishCreation(JSC::VM&, JSC::JSGlobalObject* globalObject, JSC::JSObject* prototype); - }; - - class JSHTTPSResponseSink final : public JSC::JSDestructibleObject { - public: - using Base = JSC::JSDestructibleObject; - static JSHTTPSResponseSink* create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure, void* sinkPtr); - static constexpr SinkID Sink = SinkID::HTTPSResponseSink; - - DECLARE_EXPORT_INFO; - template<typename, JSC::SubspaceAccess mode> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) - { - if constexpr (mode == JSC::SubspaceAccess::Concurrently) - return nullptr; - return WebCore::subspaceForImpl<JSHTTPSResponseSink, WebCore::UseCustomHeapCellType::No>( - vm, - [](auto& spaces) { return spaces.m_clientSubspaceForJSSink.get(); }, - [](auto& spaces, auto&& space) { spaces.m_clientSubspaceForJSSink = WTFMove(space); }, - [](auto& spaces) { return spaces.m_subspaceForJSSink.get(); }, - [](auto& spaces, auto&& space) { spaces.m_subspaceForJSSink = WTFMove(space); }); - } - - static void destroy(JSC::JSCell*); - static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) - { - return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), info()); - } - - static JSObject* createPrototype(VM& vm, JSDOMGlobalObject& globalObject); - - ~JSHTTPSResponseSink(); - - void* wrapped() const { return m_sinkPtr; } - - void detach() { - m_sinkPtr = nullptr; - - } - - static void analyzeHeap(JSCell*, JSC::HeapAnalyzer&); - - void* m_sinkPtr; - - JSHTTPSResponseSink(JSC::VM& vm, JSC::Structure* structure, void* sinkPtr) - : Base(vm, structure) - { - m_sinkPtr = sinkPtr; - } - - void finishCreation(JSC::VM&); - }; - - - - class JSReadableHTTPSResponseSinkController final : public JSC::JSDestructibleObject { - public: - using Base = JSC::JSDestructibleObject; - static JSReadableHTTPSResponseSinkController* create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure, void* sinkPtr); - static constexpr SinkID Sink = SinkID::HTTPSResponseSink; - - DECLARE_EXPORT_INFO; - template<typename, JSC::SubspaceAccess mode> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) - { - if constexpr (mode == JSC::SubspaceAccess::Concurrently) - return nullptr; - return WebCore::subspaceForImpl<JSReadableHTTPSResponseSinkController, WebCore::UseCustomHeapCellType::No>( - vm, - [](auto& spaces) { return spaces.m_clientSubspaceForJSSinkController.get(); }, - [](auto& spaces, auto&& space) { spaces.m_clientSubspaceForJSSinkController = WTFMove(space); }, - [](auto& spaces) { return spaces.m_subspaceForJSSinkController.get(); }, - [](auto& spaces, auto&& space) { spaces.m_subspaceForJSSinkController = WTFMove(space); }); - } - - static void destroy(JSC::JSCell*); - static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) - { - return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), info()); - } - static JSObject* createPrototype(VM& vm, JSDOMGlobalObject& globalObject); - - ~JSReadableHTTPSResponseSinkController(); - - - void* wrapped() const { return m_sinkPtr; } - void detach(); - - void start(JSC::JSGlobalObject *globalObject, JSC::JSValue readableStream, JSC::JSFunction *onPull, JSC::JSFunction *onClose); - DECLARE_VISIT_CHILDREN; - - static void analyzeHeap(JSCell*, JSC::HeapAnalyzer&); - - bool hasPendingActivity() { return m_hasPendingActivity; } - - void* m_sinkPtr; - bool m_hasPendingActivity; - mutable WriteBarrier<JSC::JSFunction> m_onPull; - mutable WriteBarrier<JSC::JSFunction> m_onClose; - mutable JSC::Weak<JSObject> m_weakReadableStream; - JSC::Weak<JSReadableHTTPSResponseSinkController> m_weakThis; - - JSReadableHTTPSResponseSinkController(JSC::VM& vm, JSC::Structure* structure, void* sinkPtr) - : Base(vm, structure) - { - m_sinkPtr = sinkPtr; - m_hasPendingActivity = true; - m_weakThis = JSC::Weak<JSReadableHTTPSResponseSinkController>(this, getOwner()); - } - - void finishCreation(JSC::VM&); - - class Owner final : public JSC::WeakHandleOwner { - public: - bool isReachableFromOpaqueRoots(JSC::Handle<JSC::Unknown> handle, void* context, JSC::AbstractSlotVisitor&, const char**) final - { - auto* controller = JSC::jsCast<JSReadableHTTPSResponseSinkController*>(handle.slot()->asCell()); - return controller->hasPendingActivity(); - } - void finalize(JSC::Handle<JSC::Unknown>, void* context) final {} - }; - - static JSC::WeakHandleOwner* getOwner() - { - static NeverDestroyed<Owner> m_owner; - return &m_owner.get(); - } - }; +class JSHTTPSResponseSinkConstructor final : public JSC::InternalFunction { +public: + using Base = JSC::InternalFunction; + static JSHTTPSResponseSinkConstructor* create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure, JSC::JSObject* prototype); + static constexpr SinkID Sink = SinkID::HTTPSResponseSink; + + static constexpr unsigned StructureFlags = Base::StructureFlags; + static constexpr bool needsDestruction = false; + + DECLARE_EXPORT_INFO; + template<typename, JSC::SubspaceAccess mode> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) + { + if constexpr (mode == JSC::SubspaceAccess::Concurrently) + return nullptr; + return WebCore::subspaceForImpl<JSHTTPSResponseSinkConstructor, WebCore::UseCustomHeapCellType::No>( + vm, + [](auto& spaces) { return spaces.m_clientSubspaceForJSSinkConstructor.get(); }, + [](auto& spaces, auto&& space) { spaces.m_clientSubspaceForJSSinkConstructor = WTFMove(space); }, + [](auto& spaces) { return spaces.m_subspaceForJSSinkConstructor.get(); }, + [](auto& spaces, auto&& space) { spaces.m_subspaceForJSSinkConstructor = WTFMove(space); }); + } + + static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) + { + return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::InternalFunctionType, StructureFlags), info()); + } + void initializeProperties(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSObject* prototype); + + // Must be defined for each specialization class. + static JSC::EncodedJSValue JSC_HOST_CALL_ATTRIBUTES construct(JSC::JSGlobalObject*, JSC::CallFrame*); + +private: + JSHTTPSResponseSinkConstructor(JSC::VM& vm, JSC::Structure* structure, JSC::NativeFunction nativeFunction) + : Base(vm, structure, nativeFunction, nativeFunction) + + { + } + + void finishCreation(JSC::VM&, JSC::JSGlobalObject* globalObject, JSC::JSObject* prototype); +}; + +class JSHTTPSResponseSink final : public JSC::JSDestructibleObject { +public: + using Base = JSC::JSDestructibleObject; + static JSHTTPSResponseSink* create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure, void* sinkPtr); + static constexpr SinkID Sink = SinkID::HTTPSResponseSink; + + DECLARE_EXPORT_INFO; + template<typename, JSC::SubspaceAccess mode> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) + { + if constexpr (mode == JSC::SubspaceAccess::Concurrently) + return nullptr; + return WebCore::subspaceForImpl<JSHTTPSResponseSink, WebCore::UseCustomHeapCellType::No>( + vm, + [](auto& spaces) { return spaces.m_clientSubspaceForJSSink.get(); }, + [](auto& spaces, auto&& space) { spaces.m_clientSubspaceForJSSink = WTFMove(space); }, + [](auto& spaces) { return spaces.m_subspaceForJSSink.get(); }, + [](auto& spaces, auto&& space) { spaces.m_subspaceForJSSink = WTFMove(space); }); + } + + static void destroy(JSC::JSCell*); + static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) + { + return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), info()); + } + + static JSObject* createPrototype(VM& vm, JSDOMGlobalObject& globalObject); + + ~JSHTTPSResponseSink(); + + void* wrapped() const { return m_sinkPtr; } + DECLARE_VISIT_CHILDREN; + + void detach() + { + m_sinkPtr = nullptr; + } + + static void analyzeHeap(JSCell*, JSC::HeapAnalyzer&); + + void* m_sinkPtr; + + JSHTTPSResponseSink(JSC::VM& vm, JSC::Structure* structure, void* sinkPtr) + : Base(vm, structure) + { + m_sinkPtr = sinkPtr; + } + + void finishCreation(JSC::VM&); +}; + +class JSReadableHTTPSResponseSinkController final : public JSC::JSDestructibleObject { +public: + using Base = JSC::JSDestructibleObject; + static JSReadableHTTPSResponseSinkController* create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure, void* sinkPtr); + static constexpr SinkID Sink = SinkID::HTTPSResponseSink; + + DECLARE_EXPORT_INFO; + template<typename, JSC::SubspaceAccess mode> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) + { + if constexpr (mode == JSC::SubspaceAccess::Concurrently) + return nullptr; + return WebCore::subspaceForImpl<JSReadableHTTPSResponseSinkController, WebCore::UseCustomHeapCellType::No>( + vm, + [](auto& spaces) { return spaces.m_clientSubspaceForJSSinkController.get(); }, + [](auto& spaces, auto&& space) { spaces.m_clientSubspaceForJSSinkController = WTFMove(space); }, + [](auto& spaces) { return spaces.m_subspaceForJSSinkController.get(); }, + [](auto& spaces, auto&& space) { spaces.m_subspaceForJSSinkController = WTFMove(space); }); + } + + static void destroy(JSC::JSCell*); + static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) + { + return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), info()); + } + static JSObject* createPrototype(VM& vm, JSDOMGlobalObject& globalObject); + + ~JSReadableHTTPSResponseSinkController(); + + void* wrapped() const { return m_sinkPtr; } + void detach(); + + void start(JSC::JSGlobalObject* globalObject, JSC::JSValue readableStream, JSC::JSFunction* onPull, JSC::JSFunction* onClose); + DECLARE_VISIT_CHILDREN; + + static void analyzeHeap(JSCell*, JSC::HeapAnalyzer&); + + void* m_sinkPtr; + mutable WriteBarrier<JSC::JSFunction> m_onPull; + mutable WriteBarrier<JSC::JSFunction> m_onClose; + mutable JSC::Weak<JSObject> m_weakReadableStream; + + JSReadableHTTPSResponseSinkController(JSC::VM& vm, JSC::Structure* structure, void* sinkPtr) + : Base(vm, structure) + { + m_sinkPtr = sinkPtr; + } + + void finishCreation(JSC::VM&); +}; JSC_DECLARE_CUSTOM_GETTER(functionHTTPSResponseSink__getter); - - JSObject* createJSSinkPrototype(JSC::VM& vm, JSC::JSGlobalObject* globalObject, WebCore::SinkID sinkID); JSObject* createJSSinkControllerPrototype(JSC::VM& vm, JSC::JSGlobalObject* globalObject, WebCore::SinkID sinkID); Structure* createJSSinkControllerStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, WebCore::SinkID sinkID); diff --git a/src/bun.js/bindings/OnigurumaRegExp.cpp b/src/bun.js/bindings/OnigurumaRegExp.cpp index 513b650f8..496a3de67 100644 --- a/src/bun.js/bindings/OnigurumaRegExp.cpp +++ b/src/bun.js/bindings/OnigurumaRegExp.cpp @@ -63,14 +63,17 @@ static WTF::String to16Bit(JSValue jsValue, JSC::JSGlobalObject* globalObject, A return to16Bit(jsString, globalObject); } -static WTF::String extendMultibyteHexCharacters(const WTF::String& string) +static WTF::String convertToOnigurumaSyntax(const WTF::String& string) { WTF::StringBuilder sb; uint32_t length = string.length(); const UChar* characters = string.characters16(); bool inCharacterClass = false; + bool inCharacterProperty = false; for (int i = 0; i < length; i++) { + + // extend multibyte hex characters while (characters[i] == '\\') { if (i + 1 < length && characters[i + 1] == 'x') { if (i + 2 < length && isxdigit(characters[i + 2])) { @@ -95,6 +98,58 @@ static WTF::String extendMultibyteHexCharacters(const WTF::String& string) break; } + // convert character properties + if (UNLIKELY(characters[i] == '{' && i - 2 >= 0 && (characters[i - 1] == 'p' || characters[i - 1] == 'P') && characters[i - 2] == '\\')) { + sb.append(characters[i]); + i += 1; + if (i == length) { + break; + } + + // handle negative + if (characters[i] == '^') { + sb.append(characters[i]); + i += 1; + if (i == length) { + break; + } + } + + // could be \p{propName=propValue} or \p{propValue}. + bool foundEquals = false; + WTF::StringBuilder propName; + while (characters[i] != '}') { + if (characters[i] == '=') { + foundEquals = true; + i += 1; + if (i == length) { + break; + } + continue; + } + + if (foundEquals) { + sb.append(characters[i]); + } else { + propName.append(characters[i]); + } + + i += 1; + if (i == length) { + break; + } + } + + if (!foundEquals) { + sb.append(propName.toString()); + } + } + + if (i >= length) { + break; + } + + // escape brackets in character classes if (inCharacterClass) { // we know ']' will be escaped so there isn't a need to scan for the closing bracket if (characters[i] == '[' || characters[i] == ']') { @@ -518,13 +573,13 @@ JSC_DEFINE_HOST_FUNCTION(onigurumaRegExpProtoFuncCompile, (JSGlobalObject * glob return JSValue::encode({}); } thisRegExp->setPatternString(regExpObject->patternString()); - patternStringExtended = extendMultibyteHexCharacters(thisRegExp->patternString()); + patternStringExtended = convertToOnigurumaSyntax(thisRegExp->patternString()); thisRegExp->setFlagsString(regExpObject->flagsString()); } else { WTF::String newPatternString = to16Bit(arg0, globalObject, "(?:)"_s); RETURN_IF_EXCEPTION(scope, {}); - patternStringExtended = extendMultibyteHexCharacters(newPatternString); + patternStringExtended = convertToOnigurumaSyntax(newPatternString); WTF::String newFlagsString = to16Bit(arg1, globalObject, ""_s); RETURN_IF_EXCEPTION(scope, {}); @@ -543,7 +598,7 @@ JSC_DEFINE_HOST_FUNCTION(onigurumaRegExpProtoFuncCompile, (JSGlobalObject * glob // for pattern syntax checking int errorCode = 0; OnigErrorInfo errorInfo = { 0 }; - regex_t* onigurumaRegExp = createOnigurumaRegExp(globalObject, extendMultibyteHexCharacters(thisRegExp->patternString()), thisRegExp->flagsString(), errorCode, errorInfo); + regex_t* onigurumaRegExp = createOnigurumaRegExp(globalObject, convertToOnigurumaSyntax(thisRegExp->patternString()), thisRegExp->flagsString(), errorCode, errorInfo); if (errorCode != ONIG_NORMAL) { OnigUChar errorBuff[ONIG_MAX_ERROR_MESSAGE_LEN] = { 0 }; int length = onig_error_code_to_str(errorBuff, errorCode, &errorInfo); @@ -588,7 +643,7 @@ JSC_DEFINE_HOST_FUNCTION(onigurumaRegExpProtoFuncTest, (JSGlobalObject * globalO int errorCode = 0; OnigErrorInfo errorInfo = { 0 }; - regex_t* onigurumaRegExp = createOnigurumaRegExp(globalObject, extendMultibyteHexCharacters(thisValue->patternString()), thisValue->flagsString(), errorCode, errorInfo); + regex_t* onigurumaRegExp = createOnigurumaRegExp(globalObject, convertToOnigurumaSyntax(thisValue->patternString()), thisValue->flagsString(), errorCode, errorInfo); if (errorCode != ONIG_NORMAL) { OnigUChar errorBuff[ONIG_MAX_ERROR_MESSAGE_LEN] = { 0 }; int length = onig_error_code_to_str(errorBuff, errorCode, &errorInfo); @@ -674,7 +729,7 @@ JSC_DEFINE_HOST_FUNCTION(onigurumaRegExpProtoFuncExec, (JSGlobalObject * globalO int errorCode = 0; OnigErrorInfo errorInfo = { 0 }; - regex_t* onigurumaRegExp = createOnigurumaRegExp(globalObject, extendMultibyteHexCharacters(thisValue->patternString()), thisValue->flagsString(), errorCode, errorInfo); + regex_t* onigurumaRegExp = createOnigurumaRegExp(globalObject, convertToOnigurumaSyntax(thisValue->patternString()), thisValue->flagsString(), errorCode, errorInfo); if (errorCode != ONIG_NORMAL) { OnigUChar errorBuff[ONIG_MAX_ERROR_MESSAGE_LEN] = { 0 }; int length = onig_error_code_to_str(errorBuff, errorCode, &errorInfo); @@ -859,7 +914,7 @@ static JSC::EncodedJSValue constructOrCall(Zig::GlobalObject* globalObject, JSVa // create for pattern compilation errors, but need to create another for each exec/test int errorCode = 0; OnigErrorInfo errorInfo = { 0 }; - regex_t* onigurumaRegExp = createOnigurumaRegExp(globalObject, extendMultibyteHexCharacters(patternString), flagsString, errorCode, errorInfo); + regex_t* onigurumaRegExp = createOnigurumaRegExp(globalObject, convertToOnigurumaSyntax(patternString), flagsString, errorCode, errorInfo); if (errorCode != ONIG_NORMAL) { OnigUChar errorBuff[ONIG_MAX_ERROR_MESSAGE_LEN] = { 0 }; int length = onig_error_code_to_str(errorBuff, errorCode, &errorInfo); diff --git a/src/bun.js/bindings/ZigGeneratedClasses+DOMClientIsoSubspaces.h b/src/bun.js/bindings/ZigGeneratedClasses+DOMClientIsoSubspaces.h index 368708fe9..21e6d1185 100644 --- a/src/bun.js/bindings/ZigGeneratedClasses+DOMClientIsoSubspaces.h +++ b/src/bun.js/bindings/ZigGeneratedClasses+DOMClientIsoSubspaces.h @@ -1,8 +1,8 @@ std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForTCPSocket; -std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForTCPSocketConstructor;std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForTLSSocket; -std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForTLSSocketConstructor;std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForListener; -std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForListenerConstructor;std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForSubprocess; -std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForSubprocessConstructor;std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForSHA1; +std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForTLSSocket; +std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForListener; +std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForSubprocess; +std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForSHA1; std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForSHA1Constructor;std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForMD5; std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForMD5Constructor;std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForMD4; std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForMD4Constructor;std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForSHA224; @@ -11,7 +11,9 @@ std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForSHA512Constructor;std: std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForSHA384Constructor;std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForSHA256; std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForSHA256Constructor;std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForSHA512_256; std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForSHA512_256Constructor;std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForServerWebSocket; -std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForServerWebSocketConstructor;std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForExpect; +std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForServerWebSocketConstructor;std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForFileSystemRouter; +std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForFileSystemRouterConstructor;std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForMatchedRoute; +std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForExpect; std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForExpectConstructor;std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForTextDecoder; std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForTextDecoderConstructor;std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForRequest; std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForRequestConstructor;std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForResponse; diff --git a/src/bun.js/bindings/ZigGeneratedClasses+DOMIsoSubspaces.h b/src/bun.js/bindings/ZigGeneratedClasses+DOMIsoSubspaces.h index 752456c7b..f8e81b0c1 100644 --- a/src/bun.js/bindings/ZigGeneratedClasses+DOMIsoSubspaces.h +++ b/src/bun.js/bindings/ZigGeneratedClasses+DOMIsoSubspaces.h @@ -1,8 +1,8 @@ std::unique_ptr<IsoSubspace> m_subspaceForTCPSocket; -std::unique_ptr<IsoSubspace> m_subspaceForTCPSocketConstructor;std::unique_ptr<IsoSubspace> m_subspaceForTLSSocket; -std::unique_ptr<IsoSubspace> m_subspaceForTLSSocketConstructor;std::unique_ptr<IsoSubspace> m_subspaceForListener; -std::unique_ptr<IsoSubspace> m_subspaceForListenerConstructor;std::unique_ptr<IsoSubspace> m_subspaceForSubprocess; -std::unique_ptr<IsoSubspace> m_subspaceForSubprocessConstructor;std::unique_ptr<IsoSubspace> m_subspaceForSHA1; +std::unique_ptr<IsoSubspace> m_subspaceForTLSSocket; +std::unique_ptr<IsoSubspace> m_subspaceForListener; +std::unique_ptr<IsoSubspace> m_subspaceForSubprocess; +std::unique_ptr<IsoSubspace> m_subspaceForSHA1; std::unique_ptr<IsoSubspace> m_subspaceForSHA1Constructor;std::unique_ptr<IsoSubspace> m_subspaceForMD5; std::unique_ptr<IsoSubspace> m_subspaceForMD5Constructor;std::unique_ptr<IsoSubspace> m_subspaceForMD4; std::unique_ptr<IsoSubspace> m_subspaceForMD4Constructor;std::unique_ptr<IsoSubspace> m_subspaceForSHA224; @@ -11,7 +11,9 @@ std::unique_ptr<IsoSubspace> m_subspaceForSHA512Constructor;std::unique_ptr<IsoS std::unique_ptr<IsoSubspace> m_subspaceForSHA384Constructor;std::unique_ptr<IsoSubspace> m_subspaceForSHA256; std::unique_ptr<IsoSubspace> m_subspaceForSHA256Constructor;std::unique_ptr<IsoSubspace> m_subspaceForSHA512_256; std::unique_ptr<IsoSubspace> m_subspaceForSHA512_256Constructor;std::unique_ptr<IsoSubspace> m_subspaceForServerWebSocket; -std::unique_ptr<IsoSubspace> m_subspaceForServerWebSocketConstructor;std::unique_ptr<IsoSubspace> m_subspaceForExpect; +std::unique_ptr<IsoSubspace> m_subspaceForServerWebSocketConstructor;std::unique_ptr<IsoSubspace> m_subspaceForFileSystemRouter; +std::unique_ptr<IsoSubspace> m_subspaceForFileSystemRouterConstructor;std::unique_ptr<IsoSubspace> m_subspaceForMatchedRoute; +std::unique_ptr<IsoSubspace> m_subspaceForExpect; std::unique_ptr<IsoSubspace> m_subspaceForExpectConstructor;std::unique_ptr<IsoSubspace> m_subspaceForTextDecoder; std::unique_ptr<IsoSubspace> m_subspaceForTextDecoderConstructor;std::unique_ptr<IsoSubspace> m_subspaceForRequest; std::unique_ptr<IsoSubspace> m_subspaceForRequestConstructor;std::unique_ptr<IsoSubspace> m_subspaceForResponse; diff --git a/src/bun.js/bindings/ZigGeneratedClasses+lazyStructureHeader.h b/src/bun.js/bindings/ZigGeneratedClasses+lazyStructureHeader.h index ff158b59e..f2d881bb5 100644 --- a/src/bun.js/bindings/ZigGeneratedClasses+lazyStructureHeader.h +++ b/src/bun.js/bindings/ZigGeneratedClasses+lazyStructureHeader.h @@ -76,6 +76,18 @@ JSC::Structure* JSServerWebSocketStructure() { return m_JSServerWebSocket.getIni JSC::LazyClassStructure m_JSServerWebSocket; bool hasJSServerWebSocketSetterValue { false }; mutable JSC::WriteBarrier<JSC::Unknown> m_JSServerWebSocketSetterValue; +JSC::Structure* JSFileSystemRouterStructure() { return m_JSFileSystemRouter.getInitializedOnMainThread(this); } + JSC::JSObject* JSFileSystemRouterConstructor() { return m_JSFileSystemRouter.constructorInitializedOnMainThread(this); } + JSC::JSValue JSFileSystemRouterPrototype() { return m_JSFileSystemRouter.prototypeInitializedOnMainThread(this); } + JSC::LazyClassStructure m_JSFileSystemRouter; + bool hasJSFileSystemRouterSetterValue { false }; + mutable JSC::WriteBarrier<JSC::Unknown> m_JSFileSystemRouterSetterValue; +JSC::Structure* JSMatchedRouteStructure() { return m_JSMatchedRoute.getInitializedOnMainThread(this); } + JSC::JSObject* JSMatchedRouteConstructor() { return m_JSMatchedRoute.constructorInitializedOnMainThread(this); } + JSC::JSValue JSMatchedRoutePrototype() { return m_JSMatchedRoute.prototypeInitializedOnMainThread(this); } + JSC::LazyClassStructure m_JSMatchedRoute; + bool hasJSMatchedRouteSetterValue { false }; + mutable JSC::WriteBarrier<JSC::Unknown> m_JSMatchedRouteSetterValue; JSC::Structure* JSExpectStructure() { return m_JSExpect.getInitializedOnMainThread(this); } JSC::JSObject* JSExpectConstructor() { return m_JSExpect.constructorInitializedOnMainThread(this); } JSC::JSValue JSExpectPrototype() { return m_JSExpect.prototypeInitializedOnMainThread(this); } diff --git a/src/bun.js/bindings/ZigGeneratedClasses+lazyStructureImpl.h b/src/bun.js/bindings/ZigGeneratedClasses+lazyStructureImpl.h index b04e10089..ade20e72a 100644 --- a/src/bun.js/bindings/ZigGeneratedClasses+lazyStructureImpl.h +++ b/src/bun.js/bindings/ZigGeneratedClasses+lazyStructureImpl.h @@ -3,25 +3,25 @@ void GlobalObject::initGeneratedLazyClasses() { [](LazyClassStructure::Initializer& init) { init.setPrototype(WebCore::JSTCPSocket::createPrototype(init.vm, reinterpret_cast<Zig::GlobalObject*>(init.global))); init.setStructure(WebCore::JSTCPSocket::createStructure(init.vm, init.global, init.prototype)); - init.setConstructor(WebCore::JSTCPSocket::createConstructor(init.vm, init.global, init.prototype)); + }); m_JSTLSSocket.initLater( [](LazyClassStructure::Initializer& init) { init.setPrototype(WebCore::JSTLSSocket::createPrototype(init.vm, reinterpret_cast<Zig::GlobalObject*>(init.global))); init.setStructure(WebCore::JSTLSSocket::createStructure(init.vm, init.global, init.prototype)); - init.setConstructor(WebCore::JSTLSSocket::createConstructor(init.vm, init.global, init.prototype)); + }); m_JSListener.initLater( [](LazyClassStructure::Initializer& init) { init.setPrototype(WebCore::JSListener::createPrototype(init.vm, reinterpret_cast<Zig::GlobalObject*>(init.global))); init.setStructure(WebCore::JSListener::createStructure(init.vm, init.global, init.prototype)); - init.setConstructor(WebCore::JSListener::createConstructor(init.vm, init.global, init.prototype)); + }); m_JSSubprocess.initLater( [](LazyClassStructure::Initializer& init) { init.setPrototype(WebCore::JSSubprocess::createPrototype(init.vm, reinterpret_cast<Zig::GlobalObject*>(init.global))); init.setStructure(WebCore::JSSubprocess::createStructure(init.vm, init.global, init.prototype)); - init.setConstructor(WebCore::JSSubprocess::createConstructor(init.vm, init.global, init.prototype)); + }); m_JSSHA1.initLater( [](LazyClassStructure::Initializer& init) { @@ -77,6 +77,18 @@ void GlobalObject::initGeneratedLazyClasses() { init.setStructure(WebCore::JSServerWebSocket::createStructure(init.vm, init.global, init.prototype)); init.setConstructor(WebCore::JSServerWebSocket::createConstructor(init.vm, init.global, init.prototype)); }); + m_JSFileSystemRouter.initLater( + [](LazyClassStructure::Initializer& init) { + init.setPrototype(WebCore::JSFileSystemRouter::createPrototype(init.vm, reinterpret_cast<Zig::GlobalObject*>(init.global))); + init.setStructure(WebCore::JSFileSystemRouter::createStructure(init.vm, init.global, init.prototype)); + init.setConstructor(WebCore::JSFileSystemRouter::createConstructor(init.vm, init.global, init.prototype)); + }); + m_JSMatchedRoute.initLater( + [](LazyClassStructure::Initializer& init) { + init.setPrototype(WebCore::JSMatchedRoute::createPrototype(init.vm, reinterpret_cast<Zig::GlobalObject*>(init.global))); + init.setStructure(WebCore::JSMatchedRoute::createStructure(init.vm, init.global, init.prototype)); + + }); m_JSExpect.initLater( [](LazyClassStructure::Initializer& init) { init.setPrototype(WebCore::JSExpect::createPrototype(init.vm, reinterpret_cast<Zig::GlobalObject*>(init.global))); @@ -124,6 +136,8 @@ void GlobalObject::visitGeneratedLazyClasses(GlobalObject *thisObject, Visitor& thisObject->m_JSSHA256.visit(visitor); visitor.append(thisObject->m_JSSHA256SetterValue); thisObject->m_JSSHA512_256.visit(visitor); visitor.append(thisObject->m_JSSHA512_256SetterValue); thisObject->m_JSServerWebSocket.visit(visitor); visitor.append(thisObject->m_JSServerWebSocketSetterValue); + thisObject->m_JSFileSystemRouter.visit(visitor); visitor.append(thisObject->m_JSFileSystemRouterSetterValue); + thisObject->m_JSMatchedRoute.visit(visitor); visitor.append(thisObject->m_JSMatchedRouteSetterValue); thisObject->m_JSExpect.visit(visitor); visitor.append(thisObject->m_JSExpectSetterValue); thisObject->m_JSTextDecoder.visit(visitor); visitor.append(thisObject->m_JSTextDecoderSetterValue); thisObject->m_JSRequest.visit(visitor); visitor.append(thisObject->m_JSRequestSetterValue); diff --git a/src/bun.js/bindings/ZigGeneratedClasses.cpp b/src/bun.js/bindings/ZigGeneratedClasses.cpp index 5f44ef093..5673acb60 100644 --- a/src/bun.js/bindings/ZigGeneratedClasses.cpp +++ b/src/bun.js/bindings/ZigGeneratedClasses.cpp @@ -2,15 +2,16 @@ // GENERATED CODE - DO NOT MODIFY BY HAND // Generated by make codegen #include "root.h" - + +#include "BunClientData.h" +#include "ZigGlobalObject.h" + #include <JavaScriptCore/JSFunction.h> #include <JavaScriptCore/InternalFunction.h> #include <JavaScriptCore/LazyClassStructure.h> #include <JavaScriptCore/LazyClassStructureInlines.h> #include <JavaScriptCore/FunctionPrototype.h> -#include "ZigGlobalObject.h" - #include <JavaScriptCore/DOMJITAbstractHeap.h> #include "DOMJITIDLConvert.h" #include "DOMJITIDLType.h" @@ -97,6 +98,8 @@ class JSTCPSocketPrototype final : public JSC::JSNonFinalObject { void finishCreation(JSC::VM&, JSC::JSGlobalObject* globalObject, JSTCPSocketPrototype* prototype); }; + void finishCreation(JSC::VM&, JSC::JSGlobalObject*); +}; extern "C" void* TCPSocketClass__construct(JSC::JSGlobalObject*, JSC::CallFrame*); JSC_DECLARE_CUSTOM_GETTER(jsTCPSocketConstructor); @@ -462,78 +465,12 @@ void JSTCPSocketPrototype::finishCreation(JSC::VM& vm, JSC::JSGlobalObject* glob JSC_TO_STRING_TAG_WITHOUT_TRANSITION(); } -void JSTCPSocketConstructor::finishCreation(VM& vm, JSC::JSGlobalObject* globalObject, JSTCPSocketPrototype* prototype) -{ - Base::finishCreation(vm, 0, "TCPSocket"_s, PropertyAdditionMode::WithoutStructureTransition); - - putDirectWithoutTransition(vm, vm.propertyNames->prototype, prototype, PropertyAttribute::DontEnum | PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly); - ASSERT(inherits(info())); -} - -JSTCPSocketConstructor::JSTCPSocketConstructor(JSC::VM& vm, JSC::Structure* structure) : Base(vm, structure, construct, construct) { - - } - -JSTCPSocketConstructor* JSTCPSocketConstructor::create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure, JSTCPSocketPrototype* prototype) { - JSTCPSocketConstructor* ptr = new (NotNull, JSC::allocateCell<JSTCPSocketConstructor>(vm)) JSTCPSocketConstructor(vm, structure); - ptr->finishCreation(vm, globalObject, prototype); - return ptr; -} - -JSC::EncodedJSValue JSC_HOST_CALL_ATTRIBUTES JSTCPSocketConstructor::construct(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame) -{ - Zig::GlobalObject *globalObject = reinterpret_cast<Zig::GlobalObject*>(lexicalGlobalObject); - JSC::VM &vm = globalObject->vm(); - JSObject* newTarget = asObject(callFrame->newTarget()); - auto* constructor = globalObject->JSTCPSocketConstructor(); - Structure* structure = globalObject->JSTCPSocketStructure(); - if (constructor != newTarget) { - auto scope = DECLARE_THROW_SCOPE(vm); - - auto* functionGlobalObject = reinterpret_cast<Zig::GlobalObject*>( - // ShadowRealm functions belong to a different global object. - getFunctionRealm(globalObject, newTarget) - ); - RETURN_IF_EXCEPTION(scope, {}); - structure = InternalFunction::createSubclassStructure( - globalObject, - newTarget, - functionGlobalObject->JSTCPSocketStructure() - ); - } - - void* ptr = TCPSocketClass__construct(globalObject, callFrame); - - if (UNLIKELY(!ptr)) { - return JSValue::encode(JSC::jsUndefined()); - } - - JSTCPSocket* instance = JSTCPSocket::create(vm, globalObject, structure, ptr); - - - return JSValue::encode(instance); -} - -extern "C" EncodedJSValue TCPSocket__create(Zig::GlobalObject* globalObject, void* ptr) { - auto &vm = globalObject->vm(); - JSC::Structure* structure = globalObject->JSTCPSocketStructure(); - JSTCPSocket* instance = JSTCPSocket::create(vm, globalObject, structure, ptr); - - return JSValue::encode(instance); -} - -void JSTCPSocketConstructor::initializeProperties(VM& vm, JSC::JSGlobalObject* globalObject, JSTCPSocketPrototype* prototype) +extern "C" bool TCPSocket__hasPendingActivity(void* ptr); +bool JSTCPSocket::hasPendingActivity(void* ctx) { - + return TCPSocket__hasPendingActivity(ctx); } -const ClassInfo JSTCPSocketConstructor::s_info = { "Function"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSTCPSocketConstructor) }; - - - extern "C" EncodedJSValue TCPSocket__getConstructor(Zig::GlobalObject* globalObject) { - return JSValue::encode(globalObject->JSTCPSocketConstructor()); - } - JSTCPSocket::~JSTCPSocket() { if (m_ctx) { @@ -595,16 +532,20 @@ void JSTCPSocket::analyzeHeap(JSCell* cell, HeapAnalyzer& analyzer) Base::analyzeHeap(cell, analyzer); } -JSObject* JSTCPSocket::createConstructor(VM& vm, JSGlobalObject* globalObject, JSValue prototype) +JSObject* JSTCPSocket::createPrototype(VM& vm, JSDOMGlobalObject* globalObject) { - return WebCore::JSTCPSocketConstructor::create(vm, globalObject, WebCore::JSTCPSocketConstructor::createStructure(vm, globalObject, globalObject->functionPrototype()), jsCast<WebCore::JSTCPSocketPrototype*>(prototype)); + return JSTCPSocketPrototype::create(vm, globalObject, JSTCPSocketPrototype::createStructure(vm, globalObject, globalObject->objectPrototype())); } -JSObject* JSTCPSocket::createPrototype(VM& vm, JSDOMGlobalObject* globalObject) +extern "C" EncodedJSValue TCPSocket__create(Zig::GlobalObject* globalObject, void* ptr) { - return JSTCPSocketPrototype::create(vm, globalObject, JSTCPSocketPrototype::createStructure(vm, globalObject, globalObject->objectPrototype())); + auto& vm = globalObject->vm(); + JSC::Structure* structure = globalObject->JSTCPSocketStructure(); + JSTCPSocket* instance = JSTCPSocket::create(vm, globalObject, structure, ptr); + + return JSValue::encode(instance); } - + template<typename Visitor> void JSTCPSocket::visitChildrenImpl(JSCell* cell, Visitor& visitor) { @@ -615,51 +556,36 @@ void JSTCPSocket::visitChildrenImpl(JSCell* cell, Visitor& visitor) visitor.append(thisObject->m_data); visitor.append(thisObject->m_remoteAddress); + visitor.addOpaqueRoot(thisObject->wrapped()); } -DEFINE_VISIT_CHILDREN(JSTCPSocket);class JSTLSSocketPrototype final : public JSC::JSNonFinalObject { - public: - using Base = JSC::JSNonFinalObject; - - static JSTLSSocketPrototype* create(JSC::VM& vm, JSGlobalObject* globalObject, JSC::Structure* structure) - { - JSTLSSocketPrototype* ptr = new (NotNull, JSC::allocateCell<JSTLSSocketPrototype>(vm)) JSTLSSocketPrototype(vm, globalObject, structure); - ptr->finishCreation(vm, globalObject); - return ptr; - } - - DECLARE_INFO; - template<typename CellType, JSC::SubspaceAccess> - static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) - { - return &vm.plainObjectSpace(); - } - static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) - { - return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), info()); - } - - private: - JSTLSSocketPrototype(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure) - : Base(vm, structure) - { - } - - void finishCreation(JSC::VM&, JSC::JSGlobalObject*); - }; - - class JSTLSSocketConstructor final : public JSC::InternalFunction { - public: - using Base = JSC::InternalFunction; - static JSTLSSocketConstructor* create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure, JSTLSSocketPrototype* prototype); - - static constexpr unsigned StructureFlags = Base::StructureFlags; - static constexpr bool needsDestruction = false; - - static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) - { - return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::InternalFunctionType, StructureFlags), info()); - } +DEFINE_VISIT_CHILDREN(JSTCPSocket); + +template<typename Visitor> +void JSTCPSocket::visitAdditionalChildren(Visitor& visitor) +{ + JSTCPSocket* thisObject = this; + ASSERT_GC_OBJECT_INHERITS(thisObject, info()); + + visitor.append(thisObject->m_data); + visitor.append(thisObject->m_remoteAddress); + visitor.addOpaqueRoot(this->wrapped()); +} + +DEFINE_VISIT_ADDITIONAL_CHILDREN(JSTCPSocket); + +template<typename Visitor> +void JSTCPSocket::visitOutputConstraintsImpl(JSCell* cell, Visitor& visitor) +{ + JSTCPSocket* thisObject = jsCast<JSTCPSocket*>(cell); + ASSERT_GC_OBJECT_INHERITS(thisObject, info()); + thisObject->visitAdditionalChildren<Visitor>(visitor); +} + +DEFINE_VISIT_OUTPUT_CONSTRAINTS(JSTCPSocket); +class JSTLSSocketPrototype final : public JSC::JSNonFinalObject { +public: + using Base = JSC::JSNonFinalObject; template<typename, JSC::SubspaceAccess mode> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) { @@ -685,6 +611,8 @@ DEFINE_VISIT_CHILDREN(JSTCPSocket);class JSTLSSocketPrototype final : public JSC void finishCreation(JSC::VM&, JSC::JSGlobalObject* globalObject, JSTLSSocketPrototype* prototype); }; + void finishCreation(JSC::VM&, JSC::JSGlobalObject*); +}; extern "C" void* TLSSocketClass__construct(JSC::JSGlobalObject*, JSC::CallFrame*); JSC_DECLARE_CUSTOM_GETTER(jsTLSSocketConstructor); @@ -1050,78 +978,12 @@ void JSTLSSocketPrototype::finishCreation(JSC::VM& vm, JSC::JSGlobalObject* glob JSC_TO_STRING_TAG_WITHOUT_TRANSITION(); } -void JSTLSSocketConstructor::finishCreation(VM& vm, JSC::JSGlobalObject* globalObject, JSTLSSocketPrototype* prototype) -{ - Base::finishCreation(vm, 0, "TLSSocket"_s, PropertyAdditionMode::WithoutStructureTransition); - - putDirectWithoutTransition(vm, vm.propertyNames->prototype, prototype, PropertyAttribute::DontEnum | PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly); - ASSERT(inherits(info())); -} - -JSTLSSocketConstructor::JSTLSSocketConstructor(JSC::VM& vm, JSC::Structure* structure) : Base(vm, structure, construct, construct) { - - } - -JSTLSSocketConstructor* JSTLSSocketConstructor::create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure, JSTLSSocketPrototype* prototype) { - JSTLSSocketConstructor* ptr = new (NotNull, JSC::allocateCell<JSTLSSocketConstructor>(vm)) JSTLSSocketConstructor(vm, structure); - ptr->finishCreation(vm, globalObject, prototype); - return ptr; -} - -JSC::EncodedJSValue JSC_HOST_CALL_ATTRIBUTES JSTLSSocketConstructor::construct(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame) -{ - Zig::GlobalObject *globalObject = reinterpret_cast<Zig::GlobalObject*>(lexicalGlobalObject); - JSC::VM &vm = globalObject->vm(); - JSObject* newTarget = asObject(callFrame->newTarget()); - auto* constructor = globalObject->JSTLSSocketConstructor(); - Structure* structure = globalObject->JSTLSSocketStructure(); - if (constructor != newTarget) { - auto scope = DECLARE_THROW_SCOPE(vm); - - auto* functionGlobalObject = reinterpret_cast<Zig::GlobalObject*>( - // ShadowRealm functions belong to a different global object. - getFunctionRealm(globalObject, newTarget) - ); - RETURN_IF_EXCEPTION(scope, {}); - structure = InternalFunction::createSubclassStructure( - globalObject, - newTarget, - functionGlobalObject->JSTLSSocketStructure() - ); - } - - void* ptr = TLSSocketClass__construct(globalObject, callFrame); - - if (UNLIKELY(!ptr)) { - return JSValue::encode(JSC::jsUndefined()); - } - - JSTLSSocket* instance = JSTLSSocket::create(vm, globalObject, structure, ptr); - - - return JSValue::encode(instance); -} - -extern "C" EncodedJSValue TLSSocket__create(Zig::GlobalObject* globalObject, void* ptr) { - auto &vm = globalObject->vm(); - JSC::Structure* structure = globalObject->JSTLSSocketStructure(); - JSTLSSocket* instance = JSTLSSocket::create(vm, globalObject, structure, ptr); - - return JSValue::encode(instance); -} - -void JSTLSSocketConstructor::initializeProperties(VM& vm, JSC::JSGlobalObject* globalObject, JSTLSSocketPrototype* prototype) +extern "C" bool TLSSocket__hasPendingActivity(void* ptr); +bool JSTLSSocket::hasPendingActivity(void* ctx) { - + return TLSSocket__hasPendingActivity(ctx); } -const ClassInfo JSTLSSocketConstructor::s_info = { "Function"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSTLSSocketConstructor) }; - - - extern "C" EncodedJSValue TLSSocket__getConstructor(Zig::GlobalObject* globalObject) { - return JSValue::encode(globalObject->JSTLSSocketConstructor()); - } - JSTLSSocket::~JSTLSSocket() { if (m_ctx) { @@ -1183,16 +1045,20 @@ void JSTLSSocket::analyzeHeap(JSCell* cell, HeapAnalyzer& analyzer) Base::analyzeHeap(cell, analyzer); } -JSObject* JSTLSSocket::createConstructor(VM& vm, JSGlobalObject* globalObject, JSValue prototype) +JSObject* JSTLSSocket::createPrototype(VM& vm, JSDOMGlobalObject* globalObject) { - return WebCore::JSTLSSocketConstructor::create(vm, globalObject, WebCore::JSTLSSocketConstructor::createStructure(vm, globalObject, globalObject->functionPrototype()), jsCast<WebCore::JSTLSSocketPrototype*>(prototype)); + return JSTLSSocketPrototype::create(vm, globalObject, JSTLSSocketPrototype::createStructure(vm, globalObject, globalObject->objectPrototype())); } -JSObject* JSTLSSocket::createPrototype(VM& vm, JSDOMGlobalObject* globalObject) +extern "C" EncodedJSValue TLSSocket__create(Zig::GlobalObject* globalObject, void* ptr) { - return JSTLSSocketPrototype::create(vm, globalObject, JSTLSSocketPrototype::createStructure(vm, globalObject, globalObject->objectPrototype())); + auto& vm = globalObject->vm(); + JSC::Structure* structure = globalObject->JSTLSSocketStructure(); + JSTLSSocket* instance = JSTLSSocket::create(vm, globalObject, structure, ptr); + + return JSValue::encode(instance); } - + template<typename Visitor> void JSTLSSocket::visitChildrenImpl(JSCell* cell, Visitor& visitor) { @@ -1203,51 +1069,36 @@ void JSTLSSocket::visitChildrenImpl(JSCell* cell, Visitor& visitor) visitor.append(thisObject->m_data); visitor.append(thisObject->m_remoteAddress); + visitor.addOpaqueRoot(thisObject->wrapped()); } -DEFINE_VISIT_CHILDREN(JSTLSSocket);class JSListenerPrototype final : public JSC::JSNonFinalObject { - public: - using Base = JSC::JSNonFinalObject; - - static JSListenerPrototype* create(JSC::VM& vm, JSGlobalObject* globalObject, JSC::Structure* structure) - { - JSListenerPrototype* ptr = new (NotNull, JSC::allocateCell<JSListenerPrototype>(vm)) JSListenerPrototype(vm, globalObject, structure); - ptr->finishCreation(vm, globalObject); - return ptr; - } - - DECLARE_INFO; - template<typename CellType, JSC::SubspaceAccess> - static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) - { - return &vm.plainObjectSpace(); - } - static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) - { - return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), info()); - } - - private: - JSListenerPrototype(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure) - : Base(vm, structure) - { - } - - void finishCreation(JSC::VM&, JSC::JSGlobalObject*); - }; - - class JSListenerConstructor final : public JSC::InternalFunction { - public: - using Base = JSC::InternalFunction; - static JSListenerConstructor* create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure, JSListenerPrototype* prototype); - - static constexpr unsigned StructureFlags = Base::StructureFlags; - static constexpr bool needsDestruction = false; - - static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) - { - return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::InternalFunctionType, StructureFlags), info()); - } +DEFINE_VISIT_CHILDREN(JSTLSSocket); + +template<typename Visitor> +void JSTLSSocket::visitAdditionalChildren(Visitor& visitor) +{ + JSTLSSocket* thisObject = this; + ASSERT_GC_OBJECT_INHERITS(thisObject, info()); + + visitor.append(thisObject->m_data); + visitor.append(thisObject->m_remoteAddress); + visitor.addOpaqueRoot(this->wrapped()); +} + +DEFINE_VISIT_ADDITIONAL_CHILDREN(JSTLSSocket); + +template<typename Visitor> +void JSTLSSocket::visitOutputConstraintsImpl(JSCell* cell, Visitor& visitor) +{ + JSTLSSocket* thisObject = jsCast<JSTLSSocket*>(cell); + ASSERT_GC_OBJECT_INHERITS(thisObject, info()); + thisObject->visitAdditionalChildren<Visitor>(visitor); +} + +DEFINE_VISIT_OUTPUT_CONSTRAINTS(JSTLSSocket); +class JSListenerPrototype final : public JSC::JSNonFinalObject { +public: + using Base = JSC::JSNonFinalObject; template<typename, JSC::SubspaceAccess mode> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) { @@ -1273,6 +1124,8 @@ DEFINE_VISIT_CHILDREN(JSTLSSocket);class JSListenerPrototype final : public JSC: void finishCreation(JSC::VM&, JSC::JSGlobalObject* globalObject, JSListenerPrototype* prototype); }; + void finishCreation(JSC::VM&, JSC::JSGlobalObject*); +}; extern "C" void* ListenerClass__construct(JSC::JSGlobalObject*, JSC::CallFrame*); JSC_DECLARE_CUSTOM_GETTER(jsListenerConstructor); @@ -1532,78 +1385,6 @@ void JSListenerPrototype::finishCreation(JSC::VM& vm, JSC::JSGlobalObject* globa JSC_TO_STRING_TAG_WITHOUT_TRANSITION(); } -void JSListenerConstructor::finishCreation(VM& vm, JSC::JSGlobalObject* globalObject, JSListenerPrototype* prototype) -{ - Base::finishCreation(vm, 0, "Listener"_s, PropertyAdditionMode::WithoutStructureTransition); - - putDirectWithoutTransition(vm, vm.propertyNames->prototype, prototype, PropertyAttribute::DontEnum | PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly); - ASSERT(inherits(info())); -} - -JSListenerConstructor::JSListenerConstructor(JSC::VM& vm, JSC::Structure* structure) : Base(vm, structure, construct, construct) { - - } - -JSListenerConstructor* JSListenerConstructor::create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure, JSListenerPrototype* prototype) { - JSListenerConstructor* ptr = new (NotNull, JSC::allocateCell<JSListenerConstructor>(vm)) JSListenerConstructor(vm, structure); - ptr->finishCreation(vm, globalObject, prototype); - return ptr; -} - -JSC::EncodedJSValue JSC_HOST_CALL_ATTRIBUTES JSListenerConstructor::construct(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame) -{ - Zig::GlobalObject *globalObject = reinterpret_cast<Zig::GlobalObject*>(lexicalGlobalObject); - JSC::VM &vm = globalObject->vm(); - JSObject* newTarget = asObject(callFrame->newTarget()); - auto* constructor = globalObject->JSListenerConstructor(); - Structure* structure = globalObject->JSListenerStructure(); - if (constructor != newTarget) { - auto scope = DECLARE_THROW_SCOPE(vm); - - auto* functionGlobalObject = reinterpret_cast<Zig::GlobalObject*>( - // ShadowRealm functions belong to a different global object. - getFunctionRealm(globalObject, newTarget) - ); - RETURN_IF_EXCEPTION(scope, {}); - structure = InternalFunction::createSubclassStructure( - globalObject, - newTarget, - functionGlobalObject->JSListenerStructure() - ); - } - - void* ptr = ListenerClass__construct(globalObject, callFrame); - - if (UNLIKELY(!ptr)) { - return JSValue::encode(JSC::jsUndefined()); - } - - JSListener* instance = JSListener::create(vm, globalObject, structure, ptr); - - - return JSValue::encode(instance); -} - -extern "C" EncodedJSValue Listener__create(Zig::GlobalObject* globalObject, void* ptr) { - auto &vm = globalObject->vm(); - JSC::Structure* structure = globalObject->JSListenerStructure(); - JSListener* instance = JSListener::create(vm, globalObject, structure, ptr); - - return JSValue::encode(instance); -} - -void JSListenerConstructor::initializeProperties(VM& vm, JSC::JSGlobalObject* globalObject, JSListenerPrototype* prototype) -{ - -} - -const ClassInfo JSListenerConstructor::s_info = { "Function"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSListenerConstructor) }; - - - extern "C" EncodedJSValue Listener__getConstructor(Zig::GlobalObject* globalObject) { - return JSValue::encode(globalObject->JSListenerConstructor()); - } - JSListener::~JSListener() { if (m_ctx) { @@ -1665,16 +1446,20 @@ void JSListener::analyzeHeap(JSCell* cell, HeapAnalyzer& analyzer) Base::analyzeHeap(cell, analyzer); } -JSObject* JSListener::createConstructor(VM& vm, JSGlobalObject* globalObject, JSValue prototype) +JSObject* JSListener::createPrototype(VM& vm, JSDOMGlobalObject* globalObject) { - return WebCore::JSListenerConstructor::create(vm, globalObject, WebCore::JSListenerConstructor::createStructure(vm, globalObject, globalObject->functionPrototype()), jsCast<WebCore::JSListenerPrototype*>(prototype)); + return JSListenerPrototype::create(vm, globalObject, JSListenerPrototype::createStructure(vm, globalObject, globalObject->objectPrototype())); } -JSObject* JSListener::createPrototype(VM& vm, JSDOMGlobalObject* globalObject) +extern "C" EncodedJSValue Listener__create(Zig::GlobalObject* globalObject, void* ptr) { - return JSListenerPrototype::create(vm, globalObject, JSListenerPrototype::createStructure(vm, globalObject, globalObject->objectPrototype())); + auto& vm = globalObject->vm(); + JSC::Structure* structure = globalObject->JSListenerStructure(); + JSListener* instance = JSListener::create(vm, globalObject, structure, ptr); + + return JSValue::encode(instance); } - + template<typename Visitor> void JSListener::visitChildrenImpl(JSCell* cell, Visitor& visitor) { @@ -1687,49 +1472,33 @@ void JSListener::visitChildrenImpl(JSCell* cell, Visitor& visitor) visitor.append(thisObject->m_unix); } -DEFINE_VISIT_CHILDREN(JSListener);class JSSubprocessPrototype final : public JSC::JSNonFinalObject { - public: - using Base = JSC::JSNonFinalObject; - - static JSSubprocessPrototype* create(JSC::VM& vm, JSGlobalObject* globalObject, JSC::Structure* structure) - { - JSSubprocessPrototype* ptr = new (NotNull, JSC::allocateCell<JSSubprocessPrototype>(vm)) JSSubprocessPrototype(vm, globalObject, structure); - ptr->finishCreation(vm, globalObject); - return ptr; - } - - DECLARE_INFO; - template<typename CellType, JSC::SubspaceAccess> - static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) - { - return &vm.plainObjectSpace(); - } - static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) - { - return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), info()); - } - - private: - JSSubprocessPrototype(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure) - : Base(vm, structure) - { - } - - void finishCreation(JSC::VM&, JSC::JSGlobalObject*); - }; - - class JSSubprocessConstructor final : public JSC::InternalFunction { - public: - using Base = JSC::InternalFunction; - static JSSubprocessConstructor* create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure, JSSubprocessPrototype* prototype); - - static constexpr unsigned StructureFlags = Base::StructureFlags; - static constexpr bool needsDestruction = false; - - static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) - { - return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::InternalFunctionType, StructureFlags), info()); - } +DEFINE_VISIT_CHILDREN(JSListener); + +template<typename Visitor> +void JSListener::visitAdditionalChildren(Visitor& visitor) +{ + JSListener* thisObject = this; + ASSERT_GC_OBJECT_INHERITS(thisObject, info()); + + visitor.append(thisObject->m_hostname); + visitor.append(thisObject->m_unix); + ; +} + +DEFINE_VISIT_ADDITIONAL_CHILDREN(JSListener); + +template<typename Visitor> +void JSListener::visitOutputConstraintsImpl(JSCell* cell, Visitor& visitor) +{ + JSListener* thisObject = jsCast<JSListener*>(cell); + ASSERT_GC_OBJECT_INHERITS(thisObject, info()); + thisObject->visitAdditionalChildren<Visitor>(visitor); +} + +DEFINE_VISIT_OUTPUT_CONSTRAINTS(JSListener); +class JSSubprocessPrototype final : public JSC::JSNonFinalObject { +public: + using Base = JSC::JSNonFinalObject; template<typename, JSC::SubspaceAccess mode> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) { @@ -1755,6 +1524,8 @@ DEFINE_VISIT_CHILDREN(JSListener);class JSSubprocessPrototype final : public JSC void finishCreation(JSC::VM&, JSC::JSGlobalObject* globalObject, JSSubprocessPrototype* prototype); }; + void finishCreation(JSC::VM&, JSC::JSGlobalObject*); +}; extern "C" void* SubprocessClass__construct(JSC::JSGlobalObject*, JSC::CallFrame*); JSC_DECLARE_CUSTOM_GETTER(jsSubprocessConstructor); @@ -2132,83 +1903,12 @@ void JSSubprocessPrototype::finishCreation(JSC::VM& vm, JSC::JSGlobalObject* glo JSC_TO_STRING_TAG_WITHOUT_TRANSITION(); } -void JSSubprocessConstructor::finishCreation(VM& vm, JSC::JSGlobalObject* globalObject, JSSubprocessPrototype* prototype) -{ - Base::finishCreation(vm, 0, "Subprocess"_s, PropertyAdditionMode::WithoutStructureTransition); - - putDirectWithoutTransition(vm, vm.propertyNames->prototype, prototype, PropertyAttribute::DontEnum | PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly); - ASSERT(inherits(info())); -} - -JSSubprocessConstructor::JSSubprocessConstructor(JSC::VM& vm, JSC::Structure* structure) : Base(vm, structure, construct, construct) { - - } - -JSSubprocessConstructor* JSSubprocessConstructor::create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure, JSSubprocessPrototype* prototype) { - JSSubprocessConstructor* ptr = new (NotNull, JSC::allocateCell<JSSubprocessConstructor>(vm)) JSSubprocessConstructor(vm, structure); - ptr->finishCreation(vm, globalObject, prototype); - return ptr; -} - -JSC::EncodedJSValue JSC_HOST_CALL_ATTRIBUTES JSSubprocessConstructor::construct(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame) -{ - Zig::GlobalObject *globalObject = reinterpret_cast<Zig::GlobalObject*>(lexicalGlobalObject); - JSC::VM &vm = globalObject->vm(); - JSObject* newTarget = asObject(callFrame->newTarget()); - auto* constructor = globalObject->JSSubprocessConstructor(); - Structure* structure = globalObject->JSSubprocessStructure(); - if (constructor != newTarget) { - auto scope = DECLARE_THROW_SCOPE(vm); - - auto* functionGlobalObject = reinterpret_cast<Zig::GlobalObject*>( - // ShadowRealm functions belong to a different global object. - getFunctionRealm(globalObject, newTarget) - ); - RETURN_IF_EXCEPTION(scope, {}); - structure = InternalFunction::createSubclassStructure( - globalObject, - newTarget, - functionGlobalObject->JSSubprocessStructure() - ); - } - - void* ptr = SubprocessClass__construct(globalObject, callFrame); - - if (UNLIKELY(!ptr)) { - return JSValue::encode(JSC::jsUndefined()); - } - - JSSubprocess* instance = JSSubprocess::create(vm, globalObject, structure, ptr); - - - return JSValue::encode(instance); -} - -extern "C" EncodedJSValue Subprocess__create(Zig::GlobalObject* globalObject, void* ptr) { - auto &vm = globalObject->vm(); - JSC::Structure* structure = globalObject->JSSubprocessStructure(); - JSSubprocess* instance = JSSubprocess::create(vm, globalObject, structure, ptr); - - return JSValue::encode(instance); -} - -void JSSubprocessConstructor::initializeProperties(VM& vm, JSC::JSGlobalObject* globalObject, JSSubprocessPrototype* prototype) +extern "C" bool Subprocess__hasPendingActivity(void* ptr); +bool JSSubprocess::hasPendingActivity(void* ctx) { - + return Subprocess__hasPendingActivity(ctx); } -const ClassInfo JSSubprocessConstructor::s_info = { "Function"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSSubprocessConstructor) }; - - - extern "C" EncodedJSValue Subprocess__getConstructor(Zig::GlobalObject* globalObject) { - return JSValue::encode(globalObject->JSSubprocessConstructor()); - } - -extern "C" bool Subprocess__hasPendingActivity(void* ptr); - bool JSSubprocess::internalHasPendingActivity() { - return Subprocess__hasPendingActivity(m_ctx); - } - JSSubprocess::~JSSubprocess() { if (m_ctx) { @@ -2270,16 +1970,20 @@ void JSSubprocess::analyzeHeap(JSCell* cell, HeapAnalyzer& analyzer) Base::analyzeHeap(cell, analyzer); } -JSObject* JSSubprocess::createConstructor(VM& vm, JSGlobalObject* globalObject, JSValue prototype) +JSObject* JSSubprocess::createPrototype(VM& vm, JSDOMGlobalObject* globalObject) { - return WebCore::JSSubprocessConstructor::create(vm, globalObject, WebCore::JSSubprocessConstructor::createStructure(vm, globalObject, globalObject->functionPrototype()), jsCast<WebCore::JSSubprocessPrototype*>(prototype)); + return JSSubprocessPrototype::create(vm, globalObject, JSSubprocessPrototype::createStructure(vm, globalObject, globalObject->objectPrototype())); } -JSObject* JSSubprocess::createPrototype(VM& vm, JSDOMGlobalObject* globalObject) +extern "C" EncodedJSValue Subprocess__create(Zig::GlobalObject* globalObject, void* ptr) { - return JSSubprocessPrototype::create(vm, globalObject, JSSubprocessPrototype::createStructure(vm, globalObject, globalObject->objectPrototype())); + auto& vm = globalObject->vm(); + JSC::Structure* structure = globalObject->JSSubprocessStructure(); + JSSubprocess* instance = JSSubprocess::create(vm, globalObject, structure, ptr); + + return JSValue::encode(instance); } - + template<typename Visitor> void JSSubprocess::visitChildrenImpl(JSCell* cell, Visitor& visitor) { @@ -2291,51 +1995,37 @@ void JSSubprocess::visitChildrenImpl(JSCell* cell, Visitor& visitor) visitor.append(thisObject->m_stderr); visitor.append(thisObject->m_stdin); visitor.append(thisObject->m_stdout); + visitor.addOpaqueRoot(thisObject->wrapped()); } -DEFINE_VISIT_CHILDREN(JSSubprocess);class JSSHA1Prototype final : public JSC::JSNonFinalObject { - public: - using Base = JSC::JSNonFinalObject; - - static JSSHA1Prototype* create(JSC::VM& vm, JSGlobalObject* globalObject, JSC::Structure* structure) - { - JSSHA1Prototype* ptr = new (NotNull, JSC::allocateCell<JSSHA1Prototype>(vm)) JSSHA1Prototype(vm, globalObject, structure); - ptr->finishCreation(vm, globalObject); - return ptr; - } - - DECLARE_INFO; - template<typename CellType, JSC::SubspaceAccess> - static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) - { - return &vm.plainObjectSpace(); - } - static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) - { - return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), info()); - } - - private: - JSSHA1Prototype(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure) - : Base(vm, structure) - { - } - - void finishCreation(JSC::VM&, JSC::JSGlobalObject*); - }; - - class JSSHA1Constructor final : public JSC::InternalFunction { - public: - using Base = JSC::InternalFunction; - static JSSHA1Constructor* create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure, JSSHA1Prototype* prototype); - - static constexpr unsigned StructureFlags = Base::StructureFlags; - static constexpr bool needsDestruction = false; - - static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) - { - return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::InternalFunctionType, StructureFlags), info()); - } +DEFINE_VISIT_CHILDREN(JSSubprocess); + +template<typename Visitor> +void JSSubprocess::visitAdditionalChildren(Visitor& visitor) +{ + JSSubprocess* thisObject = this; + ASSERT_GC_OBJECT_INHERITS(thisObject, info()); + + visitor.append(thisObject->m_stderr); + visitor.append(thisObject->m_stdin); + visitor.append(thisObject->m_stdout); + visitor.addOpaqueRoot(this->wrapped()); +} + +DEFINE_VISIT_ADDITIONAL_CHILDREN(JSSubprocess); + +template<typename Visitor> +void JSSubprocess::visitOutputConstraintsImpl(JSCell* cell, Visitor& visitor) +{ + JSSubprocess* thisObject = jsCast<JSSubprocess*>(cell); + ASSERT_GC_OBJECT_INHERITS(thisObject, info()); + thisObject->visitAdditionalChildren<Visitor>(visitor); +} + +DEFINE_VISIT_OUTPUT_CONSTRAINTS(JSSubprocess); +class JSSHA1Prototype final : public JSC::JSNonFinalObject { +public: + using Base = JSC::JSNonFinalObject; template<typename, JSC::SubspaceAccess mode> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) { @@ -2523,14 +2213,6 @@ JSC::EncodedJSValue JSC_HOST_CALL_ATTRIBUTES JSSHA1Constructor::construct(JSC::J return JSValue::encode(instance); } -extern "C" EncodedJSValue SHA1__create(Zig::GlobalObject* globalObject, void* ptr) { - auto &vm = globalObject->vm(); - JSC::Structure* structure = globalObject->JSSHA1Structure(); - JSSHA1* instance = JSSHA1::create(vm, globalObject, structure, ptr); - - return JSValue::encode(instance); -} - void JSSHA1Constructor::initializeProperties(VM& vm, JSC::JSGlobalObject* globalObject, JSSHA1Prototype* prototype) { @@ -2612,49 +2294,19 @@ JSObject* JSSHA1::createConstructor(VM& vm, JSGlobalObject* globalObject, JSValu JSObject* JSSHA1::createPrototype(VM& vm, JSDOMGlobalObject* globalObject) { return JSSHA1Prototype::create(vm, globalObject, JSSHA1Prototype::createStructure(vm, globalObject, globalObject->objectPrototype())); -}class JSMD5Prototype final : public JSC::JSNonFinalObject { - public: - using Base = JSC::JSNonFinalObject; - - static JSMD5Prototype* create(JSC::VM& vm, JSGlobalObject* globalObject, JSC::Structure* structure) - { - JSMD5Prototype* ptr = new (NotNull, JSC::allocateCell<JSMD5Prototype>(vm)) JSMD5Prototype(vm, globalObject, structure); - ptr->finishCreation(vm, globalObject); - return ptr; - } - - DECLARE_INFO; - template<typename CellType, JSC::SubspaceAccess> - static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) - { - return &vm.plainObjectSpace(); - } - static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) - { - return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), info()); - } - - private: - JSMD5Prototype(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure) - : Base(vm, structure) - { - } - - void finishCreation(JSC::VM&, JSC::JSGlobalObject*); - }; - - class JSMD5Constructor final : public JSC::InternalFunction { - public: - using Base = JSC::InternalFunction; - static JSMD5Constructor* create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure, JSMD5Prototype* prototype); - - static constexpr unsigned StructureFlags = Base::StructureFlags; - static constexpr bool needsDestruction = false; - - static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) - { - return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::InternalFunctionType, StructureFlags), info()); - } +} + +extern "C" EncodedJSValue SHA1__create(Zig::GlobalObject* globalObject, void* ptr) +{ + auto& vm = globalObject->vm(); + JSC::Structure* structure = globalObject->JSSHA1Structure(); + JSSHA1* instance = JSSHA1::create(vm, globalObject, structure, ptr); + + return JSValue::encode(instance); +} +class JSMD5Prototype final : public JSC::JSNonFinalObject { +public: + using Base = JSC::JSNonFinalObject; template<typename, JSC::SubspaceAccess mode> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) { @@ -2842,14 +2494,6 @@ JSC::EncodedJSValue JSC_HOST_CALL_ATTRIBUTES JSMD5Constructor::construct(JSC::JS return JSValue::encode(instance); } -extern "C" EncodedJSValue MD5__create(Zig::GlobalObject* globalObject, void* ptr) { - auto &vm = globalObject->vm(); - JSC::Structure* structure = globalObject->JSMD5Structure(); - JSMD5* instance = JSMD5::create(vm, globalObject, structure, ptr); - - return JSValue::encode(instance); -} - void JSMD5Constructor::initializeProperties(VM& vm, JSC::JSGlobalObject* globalObject, JSMD5Prototype* prototype) { @@ -2931,49 +2575,19 @@ JSObject* JSMD5::createConstructor(VM& vm, JSGlobalObject* globalObject, JSValue JSObject* JSMD5::createPrototype(VM& vm, JSDOMGlobalObject* globalObject) { return JSMD5Prototype::create(vm, globalObject, JSMD5Prototype::createStructure(vm, globalObject, globalObject->objectPrototype())); -}class JSMD4Prototype final : public JSC::JSNonFinalObject { - public: - using Base = JSC::JSNonFinalObject; - - static JSMD4Prototype* create(JSC::VM& vm, JSGlobalObject* globalObject, JSC::Structure* structure) - { - JSMD4Prototype* ptr = new (NotNull, JSC::allocateCell<JSMD4Prototype>(vm)) JSMD4Prototype(vm, globalObject, structure); - ptr->finishCreation(vm, globalObject); - return ptr; - } - - DECLARE_INFO; - template<typename CellType, JSC::SubspaceAccess> - static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) - { - return &vm.plainObjectSpace(); - } - static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) - { - return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), info()); - } - - private: - JSMD4Prototype(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure) - : Base(vm, structure) - { - } - - void finishCreation(JSC::VM&, JSC::JSGlobalObject*); - }; - - class JSMD4Constructor final : public JSC::InternalFunction { - public: - using Base = JSC::InternalFunction; - static JSMD4Constructor* create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure, JSMD4Prototype* prototype); - - static constexpr unsigned StructureFlags = Base::StructureFlags; - static constexpr bool needsDestruction = false; - - static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) - { - return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::InternalFunctionType, StructureFlags), info()); - } +} + +extern "C" EncodedJSValue MD5__create(Zig::GlobalObject* globalObject, void* ptr) +{ + auto& vm = globalObject->vm(); + JSC::Structure* structure = globalObject->JSMD5Structure(); + JSMD5* instance = JSMD5::create(vm, globalObject, structure, ptr); + + return JSValue::encode(instance); +} +class JSMD4Prototype final : public JSC::JSNonFinalObject { +public: + using Base = JSC::JSNonFinalObject; template<typename, JSC::SubspaceAccess mode> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) { @@ -3161,14 +2775,6 @@ JSC::EncodedJSValue JSC_HOST_CALL_ATTRIBUTES JSMD4Constructor::construct(JSC::JS return JSValue::encode(instance); } -extern "C" EncodedJSValue MD4__create(Zig::GlobalObject* globalObject, void* ptr) { - auto &vm = globalObject->vm(); - JSC::Structure* structure = globalObject->JSMD4Structure(); - JSMD4* instance = JSMD4::create(vm, globalObject, structure, ptr); - - return JSValue::encode(instance); -} - void JSMD4Constructor::initializeProperties(VM& vm, JSC::JSGlobalObject* globalObject, JSMD4Prototype* prototype) { @@ -3250,49 +2856,19 @@ JSObject* JSMD4::createConstructor(VM& vm, JSGlobalObject* globalObject, JSValue JSObject* JSMD4::createPrototype(VM& vm, JSDOMGlobalObject* globalObject) { return JSMD4Prototype::create(vm, globalObject, JSMD4Prototype::createStructure(vm, globalObject, globalObject->objectPrototype())); -}class JSSHA224Prototype final : public JSC::JSNonFinalObject { - public: - using Base = JSC::JSNonFinalObject; - - static JSSHA224Prototype* create(JSC::VM& vm, JSGlobalObject* globalObject, JSC::Structure* structure) - { - JSSHA224Prototype* ptr = new (NotNull, JSC::allocateCell<JSSHA224Prototype>(vm)) JSSHA224Prototype(vm, globalObject, structure); - ptr->finishCreation(vm, globalObject); - return ptr; - } - - DECLARE_INFO; - template<typename CellType, JSC::SubspaceAccess> - static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) - { - return &vm.plainObjectSpace(); - } - static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) - { - return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), info()); - } - - private: - JSSHA224Prototype(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure) - : Base(vm, structure) - { - } - - void finishCreation(JSC::VM&, JSC::JSGlobalObject*); - }; - - class JSSHA224Constructor final : public JSC::InternalFunction { - public: - using Base = JSC::InternalFunction; - static JSSHA224Constructor* create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure, JSSHA224Prototype* prototype); - - static constexpr unsigned StructureFlags = Base::StructureFlags; - static constexpr bool needsDestruction = false; - - static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) - { - return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::InternalFunctionType, StructureFlags), info()); - } +} + +extern "C" EncodedJSValue MD4__create(Zig::GlobalObject* globalObject, void* ptr) +{ + auto& vm = globalObject->vm(); + JSC::Structure* structure = globalObject->JSMD4Structure(); + JSMD4* instance = JSMD4::create(vm, globalObject, structure, ptr); + + return JSValue::encode(instance); +} +class JSSHA224Prototype final : public JSC::JSNonFinalObject { +public: + using Base = JSC::JSNonFinalObject; template<typename, JSC::SubspaceAccess mode> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) { @@ -3480,14 +3056,6 @@ JSC::EncodedJSValue JSC_HOST_CALL_ATTRIBUTES JSSHA224Constructor::construct(JSC: return JSValue::encode(instance); } -extern "C" EncodedJSValue SHA224__create(Zig::GlobalObject* globalObject, void* ptr) { - auto &vm = globalObject->vm(); - JSC::Structure* structure = globalObject->JSSHA224Structure(); - JSSHA224* instance = JSSHA224::create(vm, globalObject, structure, ptr); - - return JSValue::encode(instance); -} - void JSSHA224Constructor::initializeProperties(VM& vm, JSC::JSGlobalObject* globalObject, JSSHA224Prototype* prototype) { @@ -3569,49 +3137,19 @@ JSObject* JSSHA224::createConstructor(VM& vm, JSGlobalObject* globalObject, JSVa JSObject* JSSHA224::createPrototype(VM& vm, JSDOMGlobalObject* globalObject) { return JSSHA224Prototype::create(vm, globalObject, JSSHA224Prototype::createStructure(vm, globalObject, globalObject->objectPrototype())); -}class JSSHA512Prototype final : public JSC::JSNonFinalObject { - public: - using Base = JSC::JSNonFinalObject; - - static JSSHA512Prototype* create(JSC::VM& vm, JSGlobalObject* globalObject, JSC::Structure* structure) - { - JSSHA512Prototype* ptr = new (NotNull, JSC::allocateCell<JSSHA512Prototype>(vm)) JSSHA512Prototype(vm, globalObject, structure); - ptr->finishCreation(vm, globalObject); - return ptr; - } - - DECLARE_INFO; - template<typename CellType, JSC::SubspaceAccess> - static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) - { - return &vm.plainObjectSpace(); - } - static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) - { - return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), info()); - } - - private: - JSSHA512Prototype(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure) - : Base(vm, structure) - { - } - - void finishCreation(JSC::VM&, JSC::JSGlobalObject*); - }; - - class JSSHA512Constructor final : public JSC::InternalFunction { - public: - using Base = JSC::InternalFunction; - static JSSHA512Constructor* create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure, JSSHA512Prototype* prototype); - - static constexpr unsigned StructureFlags = Base::StructureFlags; - static constexpr bool needsDestruction = false; - - static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) - { - return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::InternalFunctionType, StructureFlags), info()); - } +} + +extern "C" EncodedJSValue SHA224__create(Zig::GlobalObject* globalObject, void* ptr) +{ + auto& vm = globalObject->vm(); + JSC::Structure* structure = globalObject->JSSHA224Structure(); + JSSHA224* instance = JSSHA224::create(vm, globalObject, structure, ptr); + + return JSValue::encode(instance); +} +class JSSHA512Prototype final : public JSC::JSNonFinalObject { +public: + using Base = JSC::JSNonFinalObject; template<typename, JSC::SubspaceAccess mode> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) { @@ -3799,14 +3337,6 @@ JSC::EncodedJSValue JSC_HOST_CALL_ATTRIBUTES JSSHA512Constructor::construct(JSC: return JSValue::encode(instance); } -extern "C" EncodedJSValue SHA512__create(Zig::GlobalObject* globalObject, void* ptr) { - auto &vm = globalObject->vm(); - JSC::Structure* structure = globalObject->JSSHA512Structure(); - JSSHA512* instance = JSSHA512::create(vm, globalObject, structure, ptr); - - return JSValue::encode(instance); -} - void JSSHA512Constructor::initializeProperties(VM& vm, JSC::JSGlobalObject* globalObject, JSSHA512Prototype* prototype) { @@ -3888,49 +3418,19 @@ JSObject* JSSHA512::createConstructor(VM& vm, JSGlobalObject* globalObject, JSVa JSObject* JSSHA512::createPrototype(VM& vm, JSDOMGlobalObject* globalObject) { return JSSHA512Prototype::create(vm, globalObject, JSSHA512Prototype::createStructure(vm, globalObject, globalObject->objectPrototype())); -}class JSSHA384Prototype final : public JSC::JSNonFinalObject { - public: - using Base = JSC::JSNonFinalObject; - - static JSSHA384Prototype* create(JSC::VM& vm, JSGlobalObject* globalObject, JSC::Structure* structure) - { - JSSHA384Prototype* ptr = new (NotNull, JSC::allocateCell<JSSHA384Prototype>(vm)) JSSHA384Prototype(vm, globalObject, structure); - ptr->finishCreation(vm, globalObject); - return ptr; - } - - DECLARE_INFO; - template<typename CellType, JSC::SubspaceAccess> - static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) - { - return &vm.plainObjectSpace(); - } - static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) - { - return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), info()); - } - - private: - JSSHA384Prototype(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure) - : Base(vm, structure) - { - } - - void finishCreation(JSC::VM&, JSC::JSGlobalObject*); - }; - - class JSSHA384Constructor final : public JSC::InternalFunction { - public: - using Base = JSC::InternalFunction; - static JSSHA384Constructor* create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure, JSSHA384Prototype* prototype); - - static constexpr unsigned StructureFlags = Base::StructureFlags; - static constexpr bool needsDestruction = false; - - static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) - { - return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::InternalFunctionType, StructureFlags), info()); - } +} + +extern "C" EncodedJSValue SHA512__create(Zig::GlobalObject* globalObject, void* ptr) +{ + auto& vm = globalObject->vm(); + JSC::Structure* structure = globalObject->JSSHA512Structure(); + JSSHA512* instance = JSSHA512::create(vm, globalObject, structure, ptr); + + return JSValue::encode(instance); +} +class JSSHA384Prototype final : public JSC::JSNonFinalObject { +public: + using Base = JSC::JSNonFinalObject; template<typename, JSC::SubspaceAccess mode> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) { @@ -4118,14 +3618,6 @@ JSC::EncodedJSValue JSC_HOST_CALL_ATTRIBUTES JSSHA384Constructor::construct(JSC: return JSValue::encode(instance); } -extern "C" EncodedJSValue SHA384__create(Zig::GlobalObject* globalObject, void* ptr) { - auto &vm = globalObject->vm(); - JSC::Structure* structure = globalObject->JSSHA384Structure(); - JSSHA384* instance = JSSHA384::create(vm, globalObject, structure, ptr); - - return JSValue::encode(instance); -} - void JSSHA384Constructor::initializeProperties(VM& vm, JSC::JSGlobalObject* globalObject, JSSHA384Prototype* prototype) { @@ -4207,49 +3699,19 @@ JSObject* JSSHA384::createConstructor(VM& vm, JSGlobalObject* globalObject, JSVa JSObject* JSSHA384::createPrototype(VM& vm, JSDOMGlobalObject* globalObject) { return JSSHA384Prototype::create(vm, globalObject, JSSHA384Prototype::createStructure(vm, globalObject, globalObject->objectPrototype())); -}class JSSHA256Prototype final : public JSC::JSNonFinalObject { - public: - using Base = JSC::JSNonFinalObject; - - static JSSHA256Prototype* create(JSC::VM& vm, JSGlobalObject* globalObject, JSC::Structure* structure) - { - JSSHA256Prototype* ptr = new (NotNull, JSC::allocateCell<JSSHA256Prototype>(vm)) JSSHA256Prototype(vm, globalObject, structure); - ptr->finishCreation(vm, globalObject); - return ptr; - } - - DECLARE_INFO; - template<typename CellType, JSC::SubspaceAccess> - static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) - { - return &vm.plainObjectSpace(); - } - static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) - { - return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), info()); - } - - private: - JSSHA256Prototype(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure) - : Base(vm, structure) - { - } - - void finishCreation(JSC::VM&, JSC::JSGlobalObject*); - }; - - class JSSHA256Constructor final : public JSC::InternalFunction { - public: - using Base = JSC::InternalFunction; - static JSSHA256Constructor* create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure, JSSHA256Prototype* prototype); - - static constexpr unsigned StructureFlags = Base::StructureFlags; - static constexpr bool needsDestruction = false; - - static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) - { - return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::InternalFunctionType, StructureFlags), info()); - } +} + +extern "C" EncodedJSValue SHA384__create(Zig::GlobalObject* globalObject, void* ptr) +{ + auto& vm = globalObject->vm(); + JSC::Structure* structure = globalObject->JSSHA384Structure(); + JSSHA384* instance = JSSHA384::create(vm, globalObject, structure, ptr); + + return JSValue::encode(instance); +} +class JSSHA256Prototype final : public JSC::JSNonFinalObject { +public: + using Base = JSC::JSNonFinalObject; template<typename, JSC::SubspaceAccess mode> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) { @@ -4437,14 +3899,6 @@ JSC::EncodedJSValue JSC_HOST_CALL_ATTRIBUTES JSSHA256Constructor::construct(JSC: return JSValue::encode(instance); } -extern "C" EncodedJSValue SHA256__create(Zig::GlobalObject* globalObject, void* ptr) { - auto &vm = globalObject->vm(); - JSC::Structure* structure = globalObject->JSSHA256Structure(); - JSSHA256* instance = JSSHA256::create(vm, globalObject, structure, ptr); - - return JSValue::encode(instance); -} - void JSSHA256Constructor::initializeProperties(VM& vm, JSC::JSGlobalObject* globalObject, JSSHA256Prototype* prototype) { @@ -4526,49 +3980,19 @@ JSObject* JSSHA256::createConstructor(VM& vm, JSGlobalObject* globalObject, JSVa JSObject* JSSHA256::createPrototype(VM& vm, JSDOMGlobalObject* globalObject) { return JSSHA256Prototype::create(vm, globalObject, JSSHA256Prototype::createStructure(vm, globalObject, globalObject->objectPrototype())); -}class JSSHA512_256Prototype final : public JSC::JSNonFinalObject { - public: - using Base = JSC::JSNonFinalObject; - - static JSSHA512_256Prototype* create(JSC::VM& vm, JSGlobalObject* globalObject, JSC::Structure* structure) - { - JSSHA512_256Prototype* ptr = new (NotNull, JSC::allocateCell<JSSHA512_256Prototype>(vm)) JSSHA512_256Prototype(vm, globalObject, structure); - ptr->finishCreation(vm, globalObject); - return ptr; - } - - DECLARE_INFO; - template<typename CellType, JSC::SubspaceAccess> - static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) - { - return &vm.plainObjectSpace(); - } - static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) - { - return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), info()); - } - - private: - JSSHA512_256Prototype(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure) - : Base(vm, structure) - { - } - - void finishCreation(JSC::VM&, JSC::JSGlobalObject*); - }; - - class JSSHA512_256Constructor final : public JSC::InternalFunction { - public: - using Base = JSC::InternalFunction; - static JSSHA512_256Constructor* create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure, JSSHA512_256Prototype* prototype); - - static constexpr unsigned StructureFlags = Base::StructureFlags; - static constexpr bool needsDestruction = false; - - static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) - { - return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::InternalFunctionType, StructureFlags), info()); - } +} + +extern "C" EncodedJSValue SHA256__create(Zig::GlobalObject* globalObject, void* ptr) +{ + auto& vm = globalObject->vm(); + JSC::Structure* structure = globalObject->JSSHA256Structure(); + JSSHA256* instance = JSSHA256::create(vm, globalObject, structure, ptr); + + return JSValue::encode(instance); +} +class JSSHA512_256Prototype final : public JSC::JSNonFinalObject { +public: + using Base = JSC::JSNonFinalObject; template<typename, JSC::SubspaceAccess mode> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) { @@ -4756,14 +4180,6 @@ JSC::EncodedJSValue JSC_HOST_CALL_ATTRIBUTES JSSHA512_256Constructor::construct( return JSValue::encode(instance); } -extern "C" EncodedJSValue SHA512_256__create(Zig::GlobalObject* globalObject, void* ptr) { - auto &vm = globalObject->vm(); - JSC::Structure* structure = globalObject->JSSHA512_256Structure(); - JSSHA512_256* instance = JSSHA512_256::create(vm, globalObject, structure, ptr); - - return JSValue::encode(instance); -} - void JSSHA512_256Constructor::initializeProperties(VM& vm, JSC::JSGlobalObject* globalObject, JSSHA512_256Prototype* prototype) { @@ -4845,49 +4261,19 @@ JSObject* JSSHA512_256::createConstructor(VM& vm, JSGlobalObject* globalObject, JSObject* JSSHA512_256::createPrototype(VM& vm, JSDOMGlobalObject* globalObject) { return JSSHA512_256Prototype::create(vm, globalObject, JSSHA512_256Prototype::createStructure(vm, globalObject, globalObject->objectPrototype())); -}class JSServerWebSocketPrototype final : public JSC::JSNonFinalObject { - public: - using Base = JSC::JSNonFinalObject; - - static JSServerWebSocketPrototype* create(JSC::VM& vm, JSGlobalObject* globalObject, JSC::Structure* structure) - { - JSServerWebSocketPrototype* ptr = new (NotNull, JSC::allocateCell<JSServerWebSocketPrototype>(vm)) JSServerWebSocketPrototype(vm, globalObject, structure); - ptr->finishCreation(vm, globalObject); - return ptr; - } - - DECLARE_INFO; - template<typename CellType, JSC::SubspaceAccess> - static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) - { - return &vm.plainObjectSpace(); - } - static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) - { - return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), info()); - } - - private: - JSServerWebSocketPrototype(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure) - : Base(vm, structure) - { - } - - void finishCreation(JSC::VM&, JSC::JSGlobalObject*); - }; - - class JSServerWebSocketConstructor final : public JSC::InternalFunction { - public: - using Base = JSC::InternalFunction; - static JSServerWebSocketConstructor* create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure, JSServerWebSocketPrototype* prototype); - - static constexpr unsigned StructureFlags = Base::StructureFlags; - static constexpr bool needsDestruction = false; - - static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) - { - return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::InternalFunctionType, StructureFlags), info()); - } +} + +extern "C" EncodedJSValue SHA512_256__create(Zig::GlobalObject* globalObject, void* ptr) +{ + auto& vm = globalObject->vm(); + JSC::Structure* structure = globalObject->JSSHA512_256Structure(); + JSSHA512_256* instance = JSSHA512_256::create(vm, globalObject, structure, ptr); + + return JSValue::encode(instance); +} +class JSServerWebSocketPrototype final : public JSC::JSNonFinalObject { +public: + using Base = JSC::JSNonFinalObject; template<typename, JSC::SubspaceAccess mode> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) { @@ -5488,14 +4874,6 @@ JSC::EncodedJSValue JSC_HOST_CALL_ATTRIBUTES JSServerWebSocketConstructor::const return JSValue::encode(instance); } -extern "C" EncodedJSValue ServerWebSocket__create(Zig::GlobalObject* globalObject, void* ptr) { - auto &vm = globalObject->vm(); - JSC::Structure* structure = globalObject->JSServerWebSocketStructure(); - JSServerWebSocket* instance = JSServerWebSocket::create(vm, globalObject, structure, ptr); - - return JSValue::encode(instance); -} - void JSServerWebSocketConstructor::initializeProperties(VM& vm, JSC::JSGlobalObject* globalObject, JSServerWebSocketPrototype* prototype) { @@ -5578,7 +4956,16 @@ JSObject* JSServerWebSocket::createPrototype(VM& vm, JSDOMGlobalObject* globalOb { return JSServerWebSocketPrototype::create(vm, globalObject, JSServerWebSocketPrototype::createStructure(vm, globalObject, globalObject->objectPrototype())); } - + +extern "C" EncodedJSValue ServerWebSocket__create(Zig::GlobalObject* globalObject, void* ptr) +{ + auto& vm = globalObject->vm(); + JSC::Structure* structure = globalObject->JSServerWebSocketStructure(); + JSServerWebSocket* instance = JSServerWebSocket::create(vm, globalObject, structure, ptr); + + return JSValue::encode(instance); +} + template<typename Visitor> void JSServerWebSocket::visitChildrenImpl(JSCell* cell, Visitor& visitor) { @@ -5591,49 +4978,918 @@ void JSServerWebSocket::visitChildrenImpl(JSCell* cell, Visitor& visitor) visitor.append(thisObject->m_remoteAddress); } -DEFINE_VISIT_CHILDREN(JSServerWebSocket);class JSExpectPrototype final : public JSC::JSNonFinalObject { - public: - using Base = JSC::JSNonFinalObject; - - static JSExpectPrototype* create(JSC::VM& vm, JSGlobalObject* globalObject, JSC::Structure* structure) - { - JSExpectPrototype* ptr = new (NotNull, JSC::allocateCell<JSExpectPrototype>(vm)) JSExpectPrototype(vm, globalObject, structure); - ptr->finishCreation(vm, globalObject); - return ptr; - } - - DECLARE_INFO; - template<typename CellType, JSC::SubspaceAccess> - static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) - { - return &vm.plainObjectSpace(); - } - static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) - { - return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), info()); - } - - private: - JSExpectPrototype(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure) - : Base(vm, structure) - { - } - - void finishCreation(JSC::VM&, JSC::JSGlobalObject*); - }; - - class JSExpectConstructor final : public JSC::InternalFunction { - public: - using Base = JSC::InternalFunction; - static JSExpectConstructor* create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure, JSExpectPrototype* prototype); - - static constexpr unsigned StructureFlags = Base::StructureFlags; - static constexpr bool needsDestruction = false; - - static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) - { - return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::InternalFunctionType, StructureFlags), info()); - } +DEFINE_VISIT_CHILDREN(JSServerWebSocket); + +template<typename Visitor> +void JSServerWebSocket::visitAdditionalChildren(Visitor& visitor) +{ + JSServerWebSocket* thisObject = this; + ASSERT_GC_OBJECT_INHERITS(thisObject, info()); + + visitor.append(thisObject->m_data); + visitor.append(thisObject->m_remoteAddress); + ; +} + +DEFINE_VISIT_ADDITIONAL_CHILDREN(JSServerWebSocket); + +template<typename Visitor> +void JSServerWebSocket::visitOutputConstraintsImpl(JSCell* cell, Visitor& visitor) +{ + JSServerWebSocket* thisObject = jsCast<JSServerWebSocket*>(cell); + ASSERT_GC_OBJECT_INHERITS(thisObject, info()); + thisObject->visitAdditionalChildren<Visitor>(visitor); +} + +DEFINE_VISIT_OUTPUT_CONSTRAINTS(JSServerWebSocket); +class JSFileSystemRouterPrototype final : public JSC::JSNonFinalObject { +public: + using Base = JSC::JSNonFinalObject; + + static JSFileSystemRouterPrototype* create(JSC::VM& vm, JSGlobalObject* globalObject, JSC::Structure* structure) + { + JSFileSystemRouterPrototype* ptr = new (NotNull, JSC::allocateCell<JSFileSystemRouterPrototype>(vm)) JSFileSystemRouterPrototype(vm, globalObject, structure); + ptr->finishCreation(vm, globalObject); + return ptr; + } + + DECLARE_INFO; + template<typename CellType, JSC::SubspaceAccess> + static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) + { + return &vm.plainObjectSpace(); + } + static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) + { + return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), info()); + } + +private: + JSFileSystemRouterPrototype(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure) + : Base(vm, structure) + { + } + + void finishCreation(JSC::VM&, JSC::JSGlobalObject*); +}; + +class JSFileSystemRouterConstructor final : public JSC::InternalFunction { +public: + using Base = JSC::InternalFunction; + static JSFileSystemRouterConstructor* create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure, JSFileSystemRouterPrototype* prototype); + + static constexpr unsigned StructureFlags = Base::StructureFlags; + static constexpr bool needsDestruction = false; + + static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) + { + return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::InternalFunctionType, StructureFlags), info()); + } + + template<typename, JSC::SubspaceAccess mode> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) + { + if constexpr (mode == JSC::SubspaceAccess::Concurrently) + return nullptr; + return WebCore::subspaceForImpl<JSFileSystemRouterConstructor, WebCore::UseCustomHeapCellType::No>( + vm, + [](auto& spaces) { return spaces.m_clientSubspaceForFileSystemRouterConstructor.get(); }, + [](auto& spaces, auto&& space) { spaces.m_clientSubspaceForFileSystemRouterConstructor = WTFMove(space); }, + [](auto& spaces) { return spaces.m_subspaceForFileSystemRouterConstructor.get(); }, + [](auto& spaces, auto&& space) { spaces.m_subspaceForFileSystemRouterConstructor = WTFMove(space); }); + } + + void initializeProperties(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSFileSystemRouterPrototype* prototype); + + // Must be defined for each specialization class. + static JSC::EncodedJSValue JSC_HOST_CALL_ATTRIBUTES construct(JSC::JSGlobalObject*, JSC::CallFrame*); + + DECLARE_EXPORT_INFO; + +private: + JSFileSystemRouterConstructor(JSC::VM& vm, JSC::Structure* structure); + void finishCreation(JSC::VM&, JSC::JSGlobalObject* globalObject, JSFileSystemRouterPrototype* prototype); +}; + +extern "C" void* FileSystemRouterClass__construct(JSC::JSGlobalObject*, JSC::CallFrame*); +JSC_DECLARE_CUSTOM_GETTER(jsFileSystemRouterConstructor); +extern "C" void FileSystemRouterClass__finalize(void*); + +extern "C" EncodedJSValue FileSystemRouterPrototype__match(void* ptr, JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame); +JSC_DECLARE_HOST_FUNCTION(FileSystemRouterPrototype__matchCallback); + +extern "C" JSC::EncodedJSValue FileSystemRouterPrototype__getOrigin(void* ptr, JSC::JSGlobalObject* lexicalGlobalObject); +JSC_DECLARE_CUSTOM_GETTER(FileSystemRouterPrototype__originGetterWrap); + +extern "C" EncodedJSValue FileSystemRouterPrototype__reload(void* ptr, JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame); +JSC_DECLARE_HOST_FUNCTION(FileSystemRouterPrototype__reloadCallback); + +extern "C" JSC::EncodedJSValue FileSystemRouterPrototype__getRoutes(void* ptr, JSC::JSGlobalObject* lexicalGlobalObject); +JSC_DECLARE_CUSTOM_GETTER(FileSystemRouterPrototype__routesGetterWrap); + +extern "C" JSC::EncodedJSValue FileSystemRouterPrototype__getStyle(void* ptr, JSC::JSGlobalObject* lexicalGlobalObject); +JSC_DECLARE_CUSTOM_GETTER(FileSystemRouterPrototype__styleGetterWrap); + +STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(JSFileSystemRouterPrototype, JSFileSystemRouterPrototype::Base); + +static const HashTableValue JSFileSystemRouterPrototypeTableValues[] = { + { "match"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, FileSystemRouterPrototype__matchCallback, 1 } }, + { "origin"_s, static_cast<unsigned>(JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DOMAttribute), NoIntrinsic, { HashTableValue::GetterSetterType, FileSystemRouterPrototype__originGetterWrap, 0 } }, + { "reload"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, FileSystemRouterPrototype__reloadCallback, 0 } }, + { "routes"_s, static_cast<unsigned>(JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DOMAttribute), NoIntrinsic, { HashTableValue::GetterSetterType, FileSystemRouterPrototype__routesGetterWrap, 0 } }, + { "style"_s, static_cast<unsigned>(JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DOMAttribute), NoIntrinsic, { HashTableValue::GetterSetterType, FileSystemRouterPrototype__styleGetterWrap, 0 } } +}; + +const ClassInfo JSFileSystemRouterPrototype::s_info = { "FileSystemRouter"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSFileSystemRouterPrototype) }; + +JSC_DEFINE_CUSTOM_GETTER(jsFileSystemRouterConstructor, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue thisValue, PropertyName)) +{ + VM& vm = JSC::getVM(lexicalGlobalObject); + auto throwScope = DECLARE_THROW_SCOPE(vm); + auto* globalObject = reinterpret_cast<Zig::GlobalObject*>(lexicalGlobalObject); + auto* prototype = jsDynamicCast<JSFileSystemRouterPrototype*>(JSValue::decode(thisValue)); + + if (UNLIKELY(!prototype)) + return throwVMTypeError(lexicalGlobalObject, throwScope); + return JSValue::encode(globalObject->JSFileSystemRouterConstructor()); +} + +JSC_DEFINE_HOST_FUNCTION(FileSystemRouterPrototype__matchCallback, (JSGlobalObject * lexicalGlobalObject, CallFrame* callFrame)) +{ + auto& vm = lexicalGlobalObject->vm(); + + JSFileSystemRouter* thisObject = jsDynamicCast<JSFileSystemRouter*>(callFrame->thisValue()); + + if (UNLIKELY(!thisObject)) { + auto throwScope = DECLARE_THROW_SCOPE(vm); + return throwVMTypeError(lexicalGlobalObject, throwScope); + } + + JSC::EnsureStillAliveScope thisArg = JSC::EnsureStillAliveScope(thisObject); + + return FileSystemRouterPrototype__match(thisObject->wrapped(), lexicalGlobalObject, callFrame); +} + +JSC_DEFINE_CUSTOM_GETTER(FileSystemRouterPrototype__originGetterWrap, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue thisValue, PropertyName attributeName)) +{ + auto& vm = lexicalGlobalObject->vm(); + Zig::GlobalObject* globalObject = reinterpret_cast<Zig::GlobalObject*>(lexicalGlobalObject); + auto throwScope = DECLARE_THROW_SCOPE(vm); + JSFileSystemRouter* thisObject = jsCast<JSFileSystemRouter*>(JSValue::decode(thisValue)); + JSC::EnsureStillAliveScope thisArg = JSC::EnsureStillAliveScope(thisObject); + + if (JSValue cachedValue = thisObject->m_origin.get()) + return JSValue::encode(cachedValue); + + JSC::JSValue result = JSC::JSValue::decode( + FileSystemRouterPrototype__getOrigin(thisObject->wrapped(), globalObject)); + RETURN_IF_EXCEPTION(throwScope, {}); + thisObject->m_origin.set(vm, thisObject, result); + RELEASE_AND_RETURN(throwScope, JSValue::encode(result)); +} + +extern "C" void FileSystemRouterPrototype__originSetCachedValue(JSC::EncodedJSValue thisValue, JSC::JSGlobalObject* globalObject, JSC::EncodedJSValue value) +{ + auto& vm = globalObject->vm(); + auto* thisObject = jsCast<JSFileSystemRouter*>(JSValue::decode(thisValue)); + thisObject->m_origin.set(vm, thisObject, JSValue::decode(value)); +} + +extern "C" EncodedJSValue FileSystemRouterPrototype__originGetCachedValue(JSC::EncodedJSValue thisValue) +{ + auto* thisObject = jsCast<JSFileSystemRouter*>(JSValue::decode(thisValue)); + return JSValue::encode(thisObject->m_origin.get()); +} + +JSC_DEFINE_HOST_FUNCTION(FileSystemRouterPrototype__reloadCallback, (JSGlobalObject * lexicalGlobalObject, CallFrame* callFrame)) +{ + auto& vm = lexicalGlobalObject->vm(); + + JSFileSystemRouter* thisObject = jsDynamicCast<JSFileSystemRouter*>(callFrame->thisValue()); + + if (UNLIKELY(!thisObject)) { + auto throwScope = DECLARE_THROW_SCOPE(vm); + return throwVMTypeError(lexicalGlobalObject, throwScope); + } + + JSC::EnsureStillAliveScope thisArg = JSC::EnsureStillAliveScope(thisObject); + + return FileSystemRouterPrototype__reload(thisObject->wrapped(), lexicalGlobalObject, callFrame); +} + +JSC_DEFINE_CUSTOM_GETTER(FileSystemRouterPrototype__routesGetterWrap, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue thisValue, PropertyName attributeName)) +{ + auto& vm = lexicalGlobalObject->vm(); + Zig::GlobalObject* globalObject = reinterpret_cast<Zig::GlobalObject*>(lexicalGlobalObject); + auto throwScope = DECLARE_THROW_SCOPE(vm); + JSFileSystemRouter* thisObject = jsCast<JSFileSystemRouter*>(JSValue::decode(thisValue)); + JSC::EnsureStillAliveScope thisArg = JSC::EnsureStillAliveScope(thisObject); + + if (JSValue cachedValue = thisObject->m_routes.get()) + return JSValue::encode(cachedValue); + + JSC::JSValue result = JSC::JSValue::decode( + FileSystemRouterPrototype__getRoutes(thisObject->wrapped(), globalObject)); + RETURN_IF_EXCEPTION(throwScope, {}); + thisObject->m_routes.set(vm, thisObject, result); + RELEASE_AND_RETURN(throwScope, JSValue::encode(result)); +} + +extern "C" void FileSystemRouterPrototype__routesSetCachedValue(JSC::EncodedJSValue thisValue, JSC::JSGlobalObject* globalObject, JSC::EncodedJSValue value) +{ + auto& vm = globalObject->vm(); + auto* thisObject = jsCast<JSFileSystemRouter*>(JSValue::decode(thisValue)); + thisObject->m_routes.set(vm, thisObject, JSValue::decode(value)); +} + +extern "C" EncodedJSValue FileSystemRouterPrototype__routesGetCachedValue(JSC::EncodedJSValue thisValue) +{ + auto* thisObject = jsCast<JSFileSystemRouter*>(JSValue::decode(thisValue)); + return JSValue::encode(thisObject->m_routes.get()); +} + +JSC_DEFINE_CUSTOM_GETTER(FileSystemRouterPrototype__styleGetterWrap, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue thisValue, PropertyName attributeName)) +{ + auto& vm = lexicalGlobalObject->vm(); + Zig::GlobalObject* globalObject = reinterpret_cast<Zig::GlobalObject*>(lexicalGlobalObject); + auto throwScope = DECLARE_THROW_SCOPE(vm); + JSFileSystemRouter* thisObject = jsCast<JSFileSystemRouter*>(JSValue::decode(thisValue)); + JSC::EnsureStillAliveScope thisArg = JSC::EnsureStillAliveScope(thisObject); + + if (JSValue cachedValue = thisObject->m_style.get()) + return JSValue::encode(cachedValue); + + JSC::JSValue result = JSC::JSValue::decode( + FileSystemRouterPrototype__getStyle(thisObject->wrapped(), globalObject)); + RETURN_IF_EXCEPTION(throwScope, {}); + thisObject->m_style.set(vm, thisObject, result); + RELEASE_AND_RETURN(throwScope, JSValue::encode(result)); +} + +extern "C" void FileSystemRouterPrototype__styleSetCachedValue(JSC::EncodedJSValue thisValue, JSC::JSGlobalObject* globalObject, JSC::EncodedJSValue value) +{ + auto& vm = globalObject->vm(); + auto* thisObject = jsCast<JSFileSystemRouter*>(JSValue::decode(thisValue)); + thisObject->m_style.set(vm, thisObject, JSValue::decode(value)); +} + +extern "C" EncodedJSValue FileSystemRouterPrototype__styleGetCachedValue(JSC::EncodedJSValue thisValue) +{ + auto* thisObject = jsCast<JSFileSystemRouter*>(JSValue::decode(thisValue)); + return JSValue::encode(thisObject->m_style.get()); +} + +void JSFileSystemRouterPrototype::finishCreation(JSC::VM& vm, JSC::JSGlobalObject* globalObject) +{ + Base::finishCreation(vm); + reifyStaticProperties(vm, JSFileSystemRouter::info(), JSFileSystemRouterPrototypeTableValues, *this); + JSC_TO_STRING_TAG_WITHOUT_TRANSITION(); +} + +void JSFileSystemRouterConstructor::finishCreation(VM& vm, JSC::JSGlobalObject* globalObject, JSFileSystemRouterPrototype* prototype) +{ + Base::finishCreation(vm, 0, "FileSystemRouter"_s, PropertyAdditionMode::WithoutStructureTransition); + + putDirectWithoutTransition(vm, vm.propertyNames->prototype, prototype, PropertyAttribute::DontEnum | PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly); + ASSERT(inherits(info())); +} + +JSFileSystemRouterConstructor::JSFileSystemRouterConstructor(JSC::VM& vm, JSC::Structure* structure) + : Base(vm, structure, construct, construct) +{ +} + +JSFileSystemRouterConstructor* JSFileSystemRouterConstructor::create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure, JSFileSystemRouterPrototype* prototype) +{ + JSFileSystemRouterConstructor* ptr = new (NotNull, JSC::allocateCell<JSFileSystemRouterConstructor>(vm)) JSFileSystemRouterConstructor(vm, structure); + ptr->finishCreation(vm, globalObject, prototype); + return ptr; +} + +JSC::EncodedJSValue JSC_HOST_CALL_ATTRIBUTES JSFileSystemRouterConstructor::construct(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame) +{ + Zig::GlobalObject* globalObject = reinterpret_cast<Zig::GlobalObject*>(lexicalGlobalObject); + JSC::VM& vm = globalObject->vm(); + JSObject* newTarget = asObject(callFrame->newTarget()); + auto* constructor = globalObject->JSFileSystemRouterConstructor(); + Structure* structure = globalObject->JSFileSystemRouterStructure(); + if (constructor != newTarget) { + auto scope = DECLARE_THROW_SCOPE(vm); + + auto* functionGlobalObject = reinterpret_cast<Zig::GlobalObject*>( + // ShadowRealm functions belong to a different global object. + getFunctionRealm(globalObject, newTarget)); + RETURN_IF_EXCEPTION(scope, {}); + structure = InternalFunction::createSubclassStructure( + globalObject, + newTarget, + functionGlobalObject->JSFileSystemRouterStructure()); + } + + void* ptr = FileSystemRouterClass__construct(globalObject, callFrame); + + if (UNLIKELY(!ptr)) { + return JSValue::encode(JSC::jsUndefined()); + } + + JSFileSystemRouter* instance = JSFileSystemRouter::create(vm, globalObject, structure, ptr); + + return JSValue::encode(instance); +} + +void JSFileSystemRouterConstructor::initializeProperties(VM& vm, JSC::JSGlobalObject* globalObject, JSFileSystemRouterPrototype* prototype) +{ +} + +const ClassInfo JSFileSystemRouterConstructor::s_info = { "Function"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSFileSystemRouterConstructor) }; + +extern "C" EncodedJSValue FileSystemRouter__getConstructor(Zig::GlobalObject* globalObject) +{ + return JSValue::encode(globalObject->JSFileSystemRouterConstructor()); +} + +JSFileSystemRouter::~JSFileSystemRouter() +{ + if (m_ctx) { + FileSystemRouterClass__finalize(m_ctx); + } +} +void JSFileSystemRouter::destroy(JSCell* cell) +{ + static_cast<JSFileSystemRouter*>(cell)->JSFileSystemRouter::~JSFileSystemRouter(); +} + +const ClassInfo JSFileSystemRouter::s_info = { "FileSystemRouter"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSFileSystemRouter) }; + +void JSFileSystemRouter::finishCreation(VM& vm) +{ + Base::finishCreation(vm); + ASSERT(inherits(info())); +} + +JSFileSystemRouter* JSFileSystemRouter::create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure, void* ctx) +{ + JSFileSystemRouter* ptr = new (NotNull, JSC::allocateCell<JSFileSystemRouter>(vm)) JSFileSystemRouter(vm, structure, ctx); + ptr->finishCreation(vm); + return ptr; +} + +extern "C" void* FileSystemRouter__fromJS(JSC::EncodedJSValue value) +{ + JSC::JSValue decodedValue = JSC::JSValue::decode(value); + if (!decodedValue || decodedValue.isUndefinedOrNull()) + return nullptr; + + JSFileSystemRouter* object = JSC::jsDynamicCast<JSFileSystemRouter*>(decodedValue); + + if (!object) + return nullptr; + + return object->wrapped(); +} + +extern "C" bool FileSystemRouter__dangerouslySetPtr(JSC::EncodedJSValue value, void* ptr) +{ + JSFileSystemRouter* object = JSC::jsDynamicCast<JSFileSystemRouter*>(JSValue::decode(value)); + if (!object) + return false; + + object->m_ctx = ptr; + return true; +} + +extern "C" const size_t FileSystemRouter__ptrOffset = JSFileSystemRouter::offsetOfWrapped(); + +void JSFileSystemRouter::analyzeHeap(JSCell* cell, HeapAnalyzer& analyzer) +{ + auto* thisObject = jsCast<JSFileSystemRouter*>(cell); + if (void* wrapped = thisObject->wrapped()) { + // if (thisObject->scriptExecutionContext()) + // analyzer.setLabelForCell(cell, "url " + thisObject->scriptExecutionContext()->url().string()); + } + Base::analyzeHeap(cell, analyzer); +} + +JSObject* JSFileSystemRouter::createConstructor(VM& vm, JSGlobalObject* globalObject, JSValue prototype) +{ + return WebCore::JSFileSystemRouterConstructor::create(vm, globalObject, WebCore::JSFileSystemRouterConstructor::createStructure(vm, globalObject, globalObject->functionPrototype()), jsCast<WebCore::JSFileSystemRouterPrototype*>(prototype)); +} + +JSObject* JSFileSystemRouter::createPrototype(VM& vm, JSDOMGlobalObject* globalObject) +{ + return JSFileSystemRouterPrototype::create(vm, globalObject, JSFileSystemRouterPrototype::createStructure(vm, globalObject, globalObject->objectPrototype())); +} + +extern "C" EncodedJSValue FileSystemRouter__create(Zig::GlobalObject* globalObject, void* ptr) +{ + auto& vm = globalObject->vm(); + JSC::Structure* structure = globalObject->JSFileSystemRouterStructure(); + JSFileSystemRouter* instance = JSFileSystemRouter::create(vm, globalObject, structure, ptr); + + return JSValue::encode(instance); +} + +template<typename Visitor> +void JSFileSystemRouter::visitChildrenImpl(JSCell* cell, Visitor& visitor) +{ + JSFileSystemRouter* thisObject = jsCast<JSFileSystemRouter*>(cell); + ASSERT_GC_OBJECT_INHERITS(thisObject, info()); + Base::visitChildren(thisObject, visitor); + + visitor.append(thisObject->m_origin); + visitor.append(thisObject->m_routes); + visitor.append(thisObject->m_style); +} + +DEFINE_VISIT_CHILDREN(JSFileSystemRouter); + +template<typename Visitor> +void JSFileSystemRouter::visitAdditionalChildren(Visitor& visitor) +{ + JSFileSystemRouter* thisObject = this; + ASSERT_GC_OBJECT_INHERITS(thisObject, info()); + + visitor.append(thisObject->m_origin); + visitor.append(thisObject->m_routes); + visitor.append(thisObject->m_style); + ; +} + +DEFINE_VISIT_ADDITIONAL_CHILDREN(JSFileSystemRouter); + +template<typename Visitor> +void JSFileSystemRouter::visitOutputConstraintsImpl(JSCell* cell, Visitor& visitor) +{ + JSFileSystemRouter* thisObject = jsCast<JSFileSystemRouter*>(cell); + ASSERT_GC_OBJECT_INHERITS(thisObject, info()); + thisObject->visitAdditionalChildren<Visitor>(visitor); +} + +DEFINE_VISIT_OUTPUT_CONSTRAINTS(JSFileSystemRouter); +class JSMatchedRoutePrototype final : public JSC::JSNonFinalObject { +public: + using Base = JSC::JSNonFinalObject; + + static JSMatchedRoutePrototype* create(JSC::VM& vm, JSGlobalObject* globalObject, JSC::Structure* structure) + { + JSMatchedRoutePrototype* ptr = new (NotNull, JSC::allocateCell<JSMatchedRoutePrototype>(vm)) JSMatchedRoutePrototype(vm, globalObject, structure); + ptr->finishCreation(vm, globalObject); + return ptr; + } + + DECLARE_INFO; + template<typename CellType, JSC::SubspaceAccess> + static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) + { + return &vm.plainObjectSpace(); + } + static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) + { + return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), info()); + } + +private: + JSMatchedRoutePrototype(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure) + : Base(vm, structure) + { + } + + void finishCreation(JSC::VM&, JSC::JSGlobalObject*); +}; + +extern "C" void* MatchedRouteClass__construct(JSC::JSGlobalObject*, JSC::CallFrame*); +JSC_DECLARE_CUSTOM_GETTER(jsMatchedRouteConstructor); +extern "C" void MatchedRouteClass__finalize(void*); + +extern "C" JSC::EncodedJSValue MatchedRoutePrototype__getFilePath(void* ptr, JSC::JSGlobalObject* lexicalGlobalObject); +JSC_DECLARE_CUSTOM_GETTER(MatchedRoutePrototype__filePathGetterWrap); + +extern "C" JSC::EncodedJSValue MatchedRoutePrototype__getKind(void* ptr, JSC::JSGlobalObject* lexicalGlobalObject); +JSC_DECLARE_CUSTOM_GETTER(MatchedRoutePrototype__kindGetterWrap); + +extern "C" JSC::EncodedJSValue MatchedRoutePrototype__getName(void* ptr, JSC::JSGlobalObject* lexicalGlobalObject); +JSC_DECLARE_CUSTOM_GETTER(MatchedRoutePrototype__nameGetterWrap); + +extern "C" JSC::EncodedJSValue MatchedRoutePrototype__getParams(void* ptr, JSC::JSGlobalObject* lexicalGlobalObject); +JSC_DECLARE_CUSTOM_GETTER(MatchedRoutePrototype__paramsGetterWrap); + +extern "C" JSC::EncodedJSValue MatchedRoutePrototype__getPathname(void* ptr, JSC::JSGlobalObject* lexicalGlobalObject); +JSC_DECLARE_CUSTOM_GETTER(MatchedRoutePrototype__pathnameGetterWrap); + +extern "C" JSC::EncodedJSValue MatchedRoutePrototype__getQuery(void* ptr, JSC::JSGlobalObject* lexicalGlobalObject); +JSC_DECLARE_CUSTOM_GETTER(MatchedRoutePrototype__queryGetterWrap); + +extern "C" JSC::EncodedJSValue MatchedRoutePrototype__getScriptSrc(void* ptr, JSC::JSGlobalObject* lexicalGlobalObject); +JSC_DECLARE_CUSTOM_GETTER(MatchedRoutePrototype__scriptSrcGetterWrap); + +extern "C" JSC::EncodedJSValue MatchedRoutePrototype__getScriptSrc(void* ptr, JSC::JSGlobalObject* lexicalGlobalObject); +JSC_DECLARE_CUSTOM_GETTER(MatchedRoutePrototype__srcGetterWrap); + +STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(JSMatchedRoutePrototype, JSMatchedRoutePrototype::Base); + +static const HashTableValue JSMatchedRoutePrototypeTableValues[] = { + { "filePath"_s, static_cast<unsigned>(JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DOMAttribute), NoIntrinsic, { HashTableValue::GetterSetterType, MatchedRoutePrototype__filePathGetterWrap, 0 } }, + { "kind"_s, static_cast<unsigned>(JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DOMAttribute), NoIntrinsic, { HashTableValue::GetterSetterType, MatchedRoutePrototype__kindGetterWrap, 0 } }, + { "name"_s, static_cast<unsigned>(JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DOMAttribute), NoIntrinsic, { HashTableValue::GetterSetterType, MatchedRoutePrototype__nameGetterWrap, 0 } }, + { "params"_s, static_cast<unsigned>(JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DOMAttribute), NoIntrinsic, { HashTableValue::GetterSetterType, MatchedRoutePrototype__paramsGetterWrap, 0 } }, + { "pathname"_s, static_cast<unsigned>(JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DOMAttribute), NoIntrinsic, { HashTableValue::GetterSetterType, MatchedRoutePrototype__pathnameGetterWrap, 0 } }, + { "query"_s, static_cast<unsigned>(JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DOMAttribute), NoIntrinsic, { HashTableValue::GetterSetterType, MatchedRoutePrototype__queryGetterWrap, 0 } }, + { "scriptSrc"_s, static_cast<unsigned>(JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DOMAttribute), NoIntrinsic, { HashTableValue::GetterSetterType, MatchedRoutePrototype__scriptSrcGetterWrap, 0 } }, + { "src"_s, static_cast<unsigned>(JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DOMAttribute), NoIntrinsic, { HashTableValue::GetterSetterType, MatchedRoutePrototype__srcGetterWrap, 0 } } +}; + +const ClassInfo JSMatchedRoutePrototype::s_info = { "MatchedRoute"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSMatchedRoutePrototype) }; + +JSC_DEFINE_CUSTOM_GETTER(jsMatchedRouteConstructor, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue thisValue, PropertyName)) +{ + VM& vm = JSC::getVM(lexicalGlobalObject); + auto throwScope = DECLARE_THROW_SCOPE(vm); + auto* globalObject = reinterpret_cast<Zig::GlobalObject*>(lexicalGlobalObject); + auto* prototype = jsDynamicCast<JSMatchedRoutePrototype*>(JSValue::decode(thisValue)); + + if (UNLIKELY(!prototype)) + return throwVMTypeError(lexicalGlobalObject, throwScope); + return JSValue::encode(globalObject->JSMatchedRouteConstructor()); +} + +JSC_DEFINE_CUSTOM_GETTER(MatchedRoutePrototype__filePathGetterWrap, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue thisValue, PropertyName attributeName)) +{ + auto& vm = lexicalGlobalObject->vm(); + Zig::GlobalObject* globalObject = reinterpret_cast<Zig::GlobalObject*>(lexicalGlobalObject); + auto throwScope = DECLARE_THROW_SCOPE(vm); + JSMatchedRoute* thisObject = jsCast<JSMatchedRoute*>(JSValue::decode(thisValue)); + JSC::EnsureStillAliveScope thisArg = JSC::EnsureStillAliveScope(thisObject); + + if (JSValue cachedValue = thisObject->m_filePath.get()) + return JSValue::encode(cachedValue); + + JSC::JSValue result = JSC::JSValue::decode( + MatchedRoutePrototype__getFilePath(thisObject->wrapped(), globalObject)); + RETURN_IF_EXCEPTION(throwScope, {}); + thisObject->m_filePath.set(vm, thisObject, result); + RELEASE_AND_RETURN(throwScope, JSValue::encode(result)); +} + +extern "C" void MatchedRoutePrototype__filePathSetCachedValue(JSC::EncodedJSValue thisValue, JSC::JSGlobalObject* globalObject, JSC::EncodedJSValue value) +{ + auto& vm = globalObject->vm(); + auto* thisObject = jsCast<JSMatchedRoute*>(JSValue::decode(thisValue)); + thisObject->m_filePath.set(vm, thisObject, JSValue::decode(value)); +} + +extern "C" EncodedJSValue MatchedRoutePrototype__filePathGetCachedValue(JSC::EncodedJSValue thisValue) +{ + auto* thisObject = jsCast<JSMatchedRoute*>(JSValue::decode(thisValue)); + return JSValue::encode(thisObject->m_filePath.get()); +} + +JSC_DEFINE_CUSTOM_GETTER(MatchedRoutePrototype__kindGetterWrap, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue thisValue, PropertyName attributeName)) +{ + auto& vm = lexicalGlobalObject->vm(); + Zig::GlobalObject* globalObject = reinterpret_cast<Zig::GlobalObject*>(lexicalGlobalObject); + auto throwScope = DECLARE_THROW_SCOPE(vm); + JSMatchedRoute* thisObject = jsCast<JSMatchedRoute*>(JSValue::decode(thisValue)); + JSC::EnsureStillAliveScope thisArg = JSC::EnsureStillAliveScope(thisObject); + + if (JSValue cachedValue = thisObject->m_kind.get()) + return JSValue::encode(cachedValue); + + JSC::JSValue result = JSC::JSValue::decode( + MatchedRoutePrototype__getKind(thisObject->wrapped(), globalObject)); + RETURN_IF_EXCEPTION(throwScope, {}); + thisObject->m_kind.set(vm, thisObject, result); + RELEASE_AND_RETURN(throwScope, JSValue::encode(result)); +} + +extern "C" void MatchedRoutePrototype__kindSetCachedValue(JSC::EncodedJSValue thisValue, JSC::JSGlobalObject* globalObject, JSC::EncodedJSValue value) +{ + auto& vm = globalObject->vm(); + auto* thisObject = jsCast<JSMatchedRoute*>(JSValue::decode(thisValue)); + thisObject->m_kind.set(vm, thisObject, JSValue::decode(value)); +} + +extern "C" EncodedJSValue MatchedRoutePrototype__kindGetCachedValue(JSC::EncodedJSValue thisValue) +{ + auto* thisObject = jsCast<JSMatchedRoute*>(JSValue::decode(thisValue)); + return JSValue::encode(thisObject->m_kind.get()); +} + +JSC_DEFINE_CUSTOM_GETTER(MatchedRoutePrototype__nameGetterWrap, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue thisValue, PropertyName attributeName)) +{ + auto& vm = lexicalGlobalObject->vm(); + Zig::GlobalObject* globalObject = reinterpret_cast<Zig::GlobalObject*>(lexicalGlobalObject); + auto throwScope = DECLARE_THROW_SCOPE(vm); + JSMatchedRoute* thisObject = jsCast<JSMatchedRoute*>(JSValue::decode(thisValue)); + JSC::EnsureStillAliveScope thisArg = JSC::EnsureStillAliveScope(thisObject); + + if (JSValue cachedValue = thisObject->m_name.get()) + return JSValue::encode(cachedValue); + + JSC::JSValue result = JSC::JSValue::decode( + MatchedRoutePrototype__getName(thisObject->wrapped(), globalObject)); + RETURN_IF_EXCEPTION(throwScope, {}); + thisObject->m_name.set(vm, thisObject, result); + RELEASE_AND_RETURN(throwScope, JSValue::encode(result)); +} + +extern "C" void MatchedRoutePrototype__nameSetCachedValue(JSC::EncodedJSValue thisValue, JSC::JSGlobalObject* globalObject, JSC::EncodedJSValue value) +{ + auto& vm = globalObject->vm(); + auto* thisObject = jsCast<JSMatchedRoute*>(JSValue::decode(thisValue)); + thisObject->m_name.set(vm, thisObject, JSValue::decode(value)); +} + +extern "C" EncodedJSValue MatchedRoutePrototype__nameGetCachedValue(JSC::EncodedJSValue thisValue) +{ + auto* thisObject = jsCast<JSMatchedRoute*>(JSValue::decode(thisValue)); + return JSValue::encode(thisObject->m_name.get()); +} + +JSC_DEFINE_CUSTOM_GETTER(MatchedRoutePrototype__paramsGetterWrap, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue thisValue, PropertyName attributeName)) +{ + auto& vm = lexicalGlobalObject->vm(); + Zig::GlobalObject* globalObject = reinterpret_cast<Zig::GlobalObject*>(lexicalGlobalObject); + auto throwScope = DECLARE_THROW_SCOPE(vm); + JSMatchedRoute* thisObject = jsCast<JSMatchedRoute*>(JSValue::decode(thisValue)); + JSC::EnsureStillAliveScope thisArg = JSC::EnsureStillAliveScope(thisObject); + + if (JSValue cachedValue = thisObject->m_params.get()) + return JSValue::encode(cachedValue); + + JSC::JSValue result = JSC::JSValue::decode( + MatchedRoutePrototype__getParams(thisObject->wrapped(), globalObject)); + RETURN_IF_EXCEPTION(throwScope, {}); + thisObject->m_params.set(vm, thisObject, result); + RELEASE_AND_RETURN(throwScope, JSValue::encode(result)); +} + +extern "C" void MatchedRoutePrototype__paramsSetCachedValue(JSC::EncodedJSValue thisValue, JSC::JSGlobalObject* globalObject, JSC::EncodedJSValue value) +{ + auto& vm = globalObject->vm(); + auto* thisObject = jsCast<JSMatchedRoute*>(JSValue::decode(thisValue)); + thisObject->m_params.set(vm, thisObject, JSValue::decode(value)); +} + +extern "C" EncodedJSValue MatchedRoutePrototype__paramsGetCachedValue(JSC::EncodedJSValue thisValue) +{ + auto* thisObject = jsCast<JSMatchedRoute*>(JSValue::decode(thisValue)); + return JSValue::encode(thisObject->m_params.get()); +} + +JSC_DEFINE_CUSTOM_GETTER(MatchedRoutePrototype__pathnameGetterWrap, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue thisValue, PropertyName attributeName)) +{ + auto& vm = lexicalGlobalObject->vm(); + Zig::GlobalObject* globalObject = reinterpret_cast<Zig::GlobalObject*>(lexicalGlobalObject); + auto throwScope = DECLARE_THROW_SCOPE(vm); + JSMatchedRoute* thisObject = jsCast<JSMatchedRoute*>(JSValue::decode(thisValue)); + JSC::EnsureStillAliveScope thisArg = JSC::EnsureStillAliveScope(thisObject); + + if (JSValue cachedValue = thisObject->m_pathname.get()) + return JSValue::encode(cachedValue); + + JSC::JSValue result = JSC::JSValue::decode( + MatchedRoutePrototype__getPathname(thisObject->wrapped(), globalObject)); + RETURN_IF_EXCEPTION(throwScope, {}); + thisObject->m_pathname.set(vm, thisObject, result); + RELEASE_AND_RETURN(throwScope, JSValue::encode(result)); +} + +extern "C" void MatchedRoutePrototype__pathnameSetCachedValue(JSC::EncodedJSValue thisValue, JSC::JSGlobalObject* globalObject, JSC::EncodedJSValue value) +{ + auto& vm = globalObject->vm(); + auto* thisObject = jsCast<JSMatchedRoute*>(JSValue::decode(thisValue)); + thisObject->m_pathname.set(vm, thisObject, JSValue::decode(value)); +} + +extern "C" EncodedJSValue MatchedRoutePrototype__pathnameGetCachedValue(JSC::EncodedJSValue thisValue) +{ + auto* thisObject = jsCast<JSMatchedRoute*>(JSValue::decode(thisValue)); + return JSValue::encode(thisObject->m_pathname.get()); +} + +JSC_DEFINE_CUSTOM_GETTER(MatchedRoutePrototype__queryGetterWrap, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue thisValue, PropertyName attributeName)) +{ + auto& vm = lexicalGlobalObject->vm(); + Zig::GlobalObject* globalObject = reinterpret_cast<Zig::GlobalObject*>(lexicalGlobalObject); + auto throwScope = DECLARE_THROW_SCOPE(vm); + JSMatchedRoute* thisObject = jsCast<JSMatchedRoute*>(JSValue::decode(thisValue)); + JSC::EnsureStillAliveScope thisArg = JSC::EnsureStillAliveScope(thisObject); + + if (JSValue cachedValue = thisObject->m_query.get()) + return JSValue::encode(cachedValue); + + JSC::JSValue result = JSC::JSValue::decode( + MatchedRoutePrototype__getQuery(thisObject->wrapped(), globalObject)); + RETURN_IF_EXCEPTION(throwScope, {}); + thisObject->m_query.set(vm, thisObject, result); + RELEASE_AND_RETURN(throwScope, JSValue::encode(result)); +} + +extern "C" void MatchedRoutePrototype__querySetCachedValue(JSC::EncodedJSValue thisValue, JSC::JSGlobalObject* globalObject, JSC::EncodedJSValue value) +{ + auto& vm = globalObject->vm(); + auto* thisObject = jsCast<JSMatchedRoute*>(JSValue::decode(thisValue)); + thisObject->m_query.set(vm, thisObject, JSValue::decode(value)); +} + +extern "C" EncodedJSValue MatchedRoutePrototype__queryGetCachedValue(JSC::EncodedJSValue thisValue) +{ + auto* thisObject = jsCast<JSMatchedRoute*>(JSValue::decode(thisValue)); + return JSValue::encode(thisObject->m_query.get()); +} + +JSC_DEFINE_CUSTOM_GETTER(MatchedRoutePrototype__scriptSrcGetterWrap, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue thisValue, PropertyName attributeName)) +{ + auto& vm = lexicalGlobalObject->vm(); + Zig::GlobalObject* globalObject = reinterpret_cast<Zig::GlobalObject*>(lexicalGlobalObject); + auto throwScope = DECLARE_THROW_SCOPE(vm); + JSMatchedRoute* thisObject = jsCast<JSMatchedRoute*>(JSValue::decode(thisValue)); + JSC::EnsureStillAliveScope thisArg = JSC::EnsureStillAliveScope(thisObject); + + if (JSValue cachedValue = thisObject->m_scriptSrc.get()) + return JSValue::encode(cachedValue); + + JSC::JSValue result = JSC::JSValue::decode( + MatchedRoutePrototype__getScriptSrc(thisObject->wrapped(), globalObject)); + RETURN_IF_EXCEPTION(throwScope, {}); + thisObject->m_scriptSrc.set(vm, thisObject, result); + RELEASE_AND_RETURN(throwScope, JSValue::encode(result)); +} + +extern "C" void MatchedRoutePrototype__scriptSrcSetCachedValue(JSC::EncodedJSValue thisValue, JSC::JSGlobalObject* globalObject, JSC::EncodedJSValue value) +{ + auto& vm = globalObject->vm(); + auto* thisObject = jsCast<JSMatchedRoute*>(JSValue::decode(thisValue)); + thisObject->m_scriptSrc.set(vm, thisObject, JSValue::decode(value)); +} + +extern "C" EncodedJSValue MatchedRoutePrototype__scriptSrcGetCachedValue(JSC::EncodedJSValue thisValue) +{ + auto* thisObject = jsCast<JSMatchedRoute*>(JSValue::decode(thisValue)); + return JSValue::encode(thisObject->m_scriptSrc.get()); +} + +JSC_DEFINE_CUSTOM_GETTER(MatchedRoutePrototype__srcGetterWrap, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue thisValue, PropertyName attributeName)) +{ + auto& vm = lexicalGlobalObject->vm(); + Zig::GlobalObject* globalObject = reinterpret_cast<Zig::GlobalObject*>(lexicalGlobalObject); + auto throwScope = DECLARE_THROW_SCOPE(vm); + JSMatchedRoute* thisObject = jsCast<JSMatchedRoute*>(JSValue::decode(thisValue)); + JSC::EnsureStillAliveScope thisArg = JSC::EnsureStillAliveScope(thisObject); + + if (JSValue cachedValue = thisObject->m_scriptSrc.get()) + return JSValue::encode(cachedValue); + + JSC::JSValue result = JSC::JSValue::decode( + MatchedRoutePrototype__getScriptSrc(thisObject->wrapped(), globalObject)); + RETURN_IF_EXCEPTION(throwScope, {}); + thisObject->m_scriptSrc.set(vm, thisObject, result); + RELEASE_AND_RETURN(throwScope, JSValue::encode(result)); +} + +extern "C" void MatchedRoutePrototype__srcSetCachedValue(JSC::EncodedJSValue thisValue, JSC::JSGlobalObject* globalObject, JSC::EncodedJSValue value) +{ + auto& vm = globalObject->vm(); + auto* thisObject = jsCast<JSMatchedRoute*>(JSValue::decode(thisValue)); + thisObject->m_scriptSrc.set(vm, thisObject, JSValue::decode(value)); +} + +extern "C" EncodedJSValue MatchedRoutePrototype__srcGetCachedValue(JSC::EncodedJSValue thisValue) +{ + auto* thisObject = jsCast<JSMatchedRoute*>(JSValue::decode(thisValue)); + return JSValue::encode(thisObject->m_scriptSrc.get()); +} + +void JSMatchedRoutePrototype::finishCreation(JSC::VM& vm, JSC::JSGlobalObject* globalObject) +{ + Base::finishCreation(vm); + reifyStaticProperties(vm, JSMatchedRoute::info(), JSMatchedRoutePrototypeTableValues, *this); + JSC_TO_STRING_TAG_WITHOUT_TRANSITION(); +} + +JSMatchedRoute::~JSMatchedRoute() +{ + if (m_ctx) { + MatchedRouteClass__finalize(m_ctx); + } +} +void JSMatchedRoute::destroy(JSCell* cell) +{ + static_cast<JSMatchedRoute*>(cell)->JSMatchedRoute::~JSMatchedRoute(); +} + +const ClassInfo JSMatchedRoute::s_info = { "MatchedRoute"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSMatchedRoute) }; + +void JSMatchedRoute::finishCreation(VM& vm) +{ + Base::finishCreation(vm); + ASSERT(inherits(info())); +} + +JSMatchedRoute* JSMatchedRoute::create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure, void* ctx) +{ + JSMatchedRoute* ptr = new (NotNull, JSC::allocateCell<JSMatchedRoute>(vm)) JSMatchedRoute(vm, structure, ctx); + ptr->finishCreation(vm); + return ptr; +} + +extern "C" void* MatchedRoute__fromJS(JSC::EncodedJSValue value) +{ + JSC::JSValue decodedValue = JSC::JSValue::decode(value); + if (!decodedValue || decodedValue.isUndefinedOrNull()) + return nullptr; + + JSMatchedRoute* object = JSC::jsDynamicCast<JSMatchedRoute*>(decodedValue); + + if (!object) + return nullptr; + + return object->wrapped(); +} + +extern "C" bool MatchedRoute__dangerouslySetPtr(JSC::EncodedJSValue value, void* ptr) +{ + JSMatchedRoute* object = JSC::jsDynamicCast<JSMatchedRoute*>(JSValue::decode(value)); + if (!object) + return false; + + object->m_ctx = ptr; + return true; +} + +extern "C" const size_t MatchedRoute__ptrOffset = JSMatchedRoute::offsetOfWrapped(); + +void JSMatchedRoute::analyzeHeap(JSCell* cell, HeapAnalyzer& analyzer) +{ + auto* thisObject = jsCast<JSMatchedRoute*>(cell); + if (void* wrapped = thisObject->wrapped()) { + // if (thisObject->scriptExecutionContext()) + // analyzer.setLabelForCell(cell, "url " + thisObject->scriptExecutionContext()->url().string()); + } + Base::analyzeHeap(cell, analyzer); +} + +JSObject* JSMatchedRoute::createPrototype(VM& vm, JSDOMGlobalObject* globalObject) +{ + return JSMatchedRoutePrototype::create(vm, globalObject, JSMatchedRoutePrototype::createStructure(vm, globalObject, globalObject->objectPrototype())); +} + +extern "C" EncodedJSValue MatchedRoute__create(Zig::GlobalObject* globalObject, void* ptr) +{ + auto& vm = globalObject->vm(); + JSC::Structure* structure = globalObject->JSMatchedRouteStructure(); + JSMatchedRoute* instance = JSMatchedRoute::create(vm, globalObject, structure, ptr); + + return JSValue::encode(instance); +} + +template<typename Visitor> +void JSMatchedRoute::visitChildrenImpl(JSCell* cell, Visitor& visitor) +{ + JSMatchedRoute* thisObject = jsCast<JSMatchedRoute*>(cell); + ASSERT_GC_OBJECT_INHERITS(thisObject, info()); + Base::visitChildren(thisObject, visitor); + + visitor.append(thisObject->m_filePath); + visitor.append(thisObject->m_kind); + visitor.append(thisObject->m_name); + visitor.append(thisObject->m_params); + visitor.append(thisObject->m_pathname); + visitor.append(thisObject->m_query); + visitor.append(thisObject->m_scriptSrc); +} + +DEFINE_VISIT_CHILDREN(JSMatchedRoute); + +template<typename Visitor> +void JSMatchedRoute::visitAdditionalChildren(Visitor& visitor) +{ + JSMatchedRoute* thisObject = this; + ASSERT_GC_OBJECT_INHERITS(thisObject, info()); + + visitor.append(thisObject->m_filePath); + visitor.append(thisObject->m_kind); + visitor.append(thisObject->m_name); + visitor.append(thisObject->m_params); + visitor.append(thisObject->m_pathname); + visitor.append(thisObject->m_query); + visitor.append(thisObject->m_scriptSrc); + ; +} + +DEFINE_VISIT_ADDITIONAL_CHILDREN(JSMatchedRoute); + +template<typename Visitor> +void JSMatchedRoute::visitOutputConstraintsImpl(JSCell* cell, Visitor& visitor) +{ + JSMatchedRoute* thisObject = jsCast<JSMatchedRoute*>(cell); + ASSERT_GC_OBJECT_INHERITS(thisObject, info()); + thisObject->visitAdditionalChildren<Visitor>(visitor); +} + +DEFINE_VISIT_OUTPUT_CONSTRAINTS(JSMatchedRoute); +class JSExpectPrototype final : public JSC::JSNonFinalObject { +public: + using Base = JSC::JSNonFinalObject; template<typename, JSC::SubspaceAccess mode> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) { @@ -5684,6 +5940,11 @@ JSC_DECLARE_HOST_FUNCTION(ExpectPrototype__toBeCallback); extern "C" EncodedJSValue ExpectPrototype__toBeCloseTo(void* ptr, JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame); JSC_DECLARE_HOST_FUNCTION(ExpectPrototype__toBeCloseToCallback); +extern "C" EncodedJSValue ExpectPrototype__toBeDefined(void* ptr, JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame); +JSC_DECLARE_HOST_FUNCTION(ExpectPrototype__toBeDefinedCallback); + +extern "C" EncodedJSValue ExpectPrototype__toBeFalsy(void* ptr, JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame); +JSC_DECLARE_HOST_FUNCTION(ExpectPrototype__toBeFalsyCallback); extern "C" EncodedJSValue ExpectPrototype__toBeGreaterThan(void* ptr, JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame); JSC_DECLARE_HOST_FUNCTION(ExpectPrototype__toBeGreaterThanCallback); @@ -5704,6 +5965,17 @@ JSC_DECLARE_HOST_FUNCTION(ExpectPrototype__toBeLessThanCallback); extern "C" EncodedJSValue ExpectPrototype__toBeLessThanOrEqual(void* ptr, JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame); JSC_DECLARE_HOST_FUNCTION(ExpectPrototype__toBeLessThanOrEqualCallback); +extern "C" EncodedJSValue ExpectPrototype__toBeNaN(void* ptr, JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame); +JSC_DECLARE_HOST_FUNCTION(ExpectPrototype__toBeNaNCallback); + +extern "C" EncodedJSValue ExpectPrototype__toBeNull(void* ptr, JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame); +JSC_DECLARE_HOST_FUNCTION(ExpectPrototype__toBeNullCallback); + +extern "C" EncodedJSValue ExpectPrototype__toBeTruthy(void* ptr, JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame); +JSC_DECLARE_HOST_FUNCTION(ExpectPrototype__toBeTruthyCallback); + +extern "C" EncodedJSValue ExpectPrototype__toBeUndefined(void* ptr, JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame); +JSC_DECLARE_HOST_FUNCTION(ExpectPrototype__toBeUndefinedCallback); extern "C" EncodedJSValue ExpectPrototype__toContain(void* ptr, JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame); JSC_DECLARE_HOST_FUNCTION(ExpectPrototype__toContainCallback); @@ -5791,42 +6063,45 @@ JSC_DECLARE_HOST_FUNCTION(ExpectPrototype__toThrowErrorMatchingSnapshotCallback) STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(JSExpectPrototype, JSExpectPrototype::Base); - - static const HashTableValue JSExpectPrototypeTableValues[] = { -{ "not"_s, static_cast<unsigned>(JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DOMAttribute), NoIntrinsic, { HashTableValue::GetterSetterType, ExpectPrototype__notGetterWrap, 0 } } , -{ "rejects"_s, static_cast<unsigned>(JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DOMAttribute), NoIntrinsic, { HashTableValue::GetterSetterType, ExpectPrototype__rejectsGetterWrap, 0 } } , -{ "resolves"_s, static_cast<unsigned>(JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DOMAttribute), NoIntrinsic, { HashTableValue::GetterSetterType, ExpectPrototype__resolvesGetterWrap, 0 } } , -{ "toBe"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, ExpectPrototype__toBeCallback, 1 } } , -{ "toBeCloseTo"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, ExpectPrototype__toBeCloseToCallback, 1 } } , -{ "toBeGreaterThan"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, ExpectPrototype__toBeGreaterThanCallback, 1 } } , -{ "toBeGreaterThanOrEqual"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, ExpectPrototype__toBeGreaterThanOrEqualCallback, 1 } } , -{ "toBeInstanceOf"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, ExpectPrototype__toBeInstanceOfCallback, 1 } } , -{ "toBeLessThan"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, ExpectPrototype__toBeLessThanCallback, 1 } } , -{ "toBeLessThanOrEqual"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, ExpectPrototype__toBeLessThanOrEqualCallback, 1 } } , -{ "toContain"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, ExpectPrototype__toContainCallback, 1 } } , -{ "toContainEqual"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, ExpectPrototype__toContainEqualCallback, 1 } } , -{ "toEqual"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, ExpectPrototype__toEqualCallback, 1 } } , -{ "toHaveBeenCalledTimes"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, ExpectPrototype__toHaveBeenCalledTimesCallback, 1 } } , -{ "toHaveBeenCalledWith"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, ExpectPrototype__toHaveBeenCalledWithCallback, 1 } } , -{ "toHaveBeenLastCalledWith"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, ExpectPrototype__toHaveBeenLastCalledWithCallback, 1 } } , -{ "toHaveBeenNthCalledWith"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, ExpectPrototype__toHaveBeenNthCalledWithCallback, 1 } } , -{ "toHaveLastReturnedWith"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, ExpectPrototype__toHaveLastReturnedWithCallback, 1 } } , -{ "toHaveLength"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, ExpectPrototype__toHaveLengthCallback, 1 } } , -{ "toHaveNthReturnedWith"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, ExpectPrototype__toHaveNthReturnedWithCallback, 1 } } , -{ "toHaveProperty"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, ExpectPrototype__toHavePropertyCallback, 1 } } , -{ "toHaveReturnedTimes"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, ExpectPrototype__toHaveReturnedTimesCallback, 1 } } , -{ "toHaveReturnedWith"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, ExpectPrototype__toHaveReturnedWithCallback, 1 } } , -{ "toMatch"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, ExpectPrototype__toMatchCallback, 1 } } , -{ "toMatchInlineSnapshot"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, ExpectPrototype__toMatchInlineSnapshotCallback, 1 } } , -{ "toMatchObject"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, ExpectPrototype__toMatchObjectCallback, 1 } } , -{ "toMatchSnapshot"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, ExpectPrototype__toMatchSnapshotCallback, 1 } } , -{ "toStrictEqual"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, ExpectPrototype__toStrictEqualCallback, 1 } } , -{ "toThrow"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, ExpectPrototype__toThrowCallback, 1 } } , -{ "toThrowErrorMatchingInlineSnapshot"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, ExpectPrototype__toThrowErrorMatchingInlineSnapshotCallback, 1 } } , -{ "toThrowErrorMatchingSnapshot"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, ExpectPrototype__toThrowErrorMatchingSnapshotCallback, 1 } } - }; - - +static const HashTableValue JSExpectPrototypeTableValues[] = { + { "not"_s, static_cast<unsigned>(JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DOMAttribute), NoIntrinsic, { HashTableValue::GetterSetterType, ExpectPrototype__notGetterWrap, 0 } }, + { "rejects"_s, static_cast<unsigned>(JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DOMAttribute), NoIntrinsic, { HashTableValue::GetterSetterType, ExpectPrototype__rejectsGetterWrap, 0 } }, + { "resolves"_s, static_cast<unsigned>(JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DOMAttribute), NoIntrinsic, { HashTableValue::GetterSetterType, ExpectPrototype__resolvesGetterWrap, 0 } }, + { "toBe"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, ExpectPrototype__toBeCallback, 1 } }, + { "toBeCloseTo"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, ExpectPrototype__toBeCloseToCallback, 1 } }, + { "toBeDefined"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, ExpectPrototype__toBeDefinedCallback, 0 } }, + { "toBeFalsy"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, ExpectPrototype__toBeFalsyCallback, 0 } }, + { "toBeGreaterThan"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, ExpectPrototype__toBeGreaterThanCallback, 1 } }, + { "toBeGreaterThanOrEqual"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, ExpectPrototype__toBeGreaterThanOrEqualCallback, 1 } }, + { "toBeInstanceOf"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, ExpectPrototype__toBeInstanceOfCallback, 1 } }, + { "toBeLessThan"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, ExpectPrototype__toBeLessThanCallback, 1 } }, + { "toBeLessThanOrEqual"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, ExpectPrototype__toBeLessThanOrEqualCallback, 1 } }, + { "toBeNaN"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, ExpectPrototype__toBeNaNCallback, 0 } }, + { "toBeNull"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, ExpectPrototype__toBeNullCallback, 0 } }, + { "toBeTruthy"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, ExpectPrototype__toBeTruthyCallback, 0 } }, + { "toBeUndefined"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, ExpectPrototype__toBeUndefinedCallback, 0 } }, + { "toContain"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, ExpectPrototype__toContainCallback, 1 } }, + { "toContainEqual"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, ExpectPrototype__toContainEqualCallback, 1 } }, + { "toEqual"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, ExpectPrototype__toEqualCallback, 1 } }, + { "toHaveBeenCalledTimes"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, ExpectPrototype__toHaveBeenCalledTimesCallback, 1 } }, + { "toHaveBeenCalledWith"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, ExpectPrototype__toHaveBeenCalledWithCallback, 1 } }, + { "toHaveBeenLastCalledWith"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, ExpectPrototype__toHaveBeenLastCalledWithCallback, 1 } }, + { "toHaveBeenNthCalledWith"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, ExpectPrototype__toHaveBeenNthCalledWithCallback, 1 } }, + { "toHaveLastReturnedWith"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, ExpectPrototype__toHaveLastReturnedWithCallback, 1 } }, + { "toHaveLength"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, ExpectPrototype__toHaveLengthCallback, 1 } }, + { "toHaveNthReturnedWith"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, ExpectPrototype__toHaveNthReturnedWithCallback, 1 } }, + { "toHaveProperty"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, ExpectPrototype__toHavePropertyCallback, 1 } }, + { "toHaveReturnedTimes"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, ExpectPrototype__toHaveReturnedTimesCallback, 1 } }, + { "toHaveReturnedWith"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, ExpectPrototype__toHaveReturnedWithCallback, 1 } }, + { "toMatch"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, ExpectPrototype__toMatchCallback, 1 } }, + { "toMatchInlineSnapshot"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, ExpectPrototype__toMatchInlineSnapshotCallback, 1 } }, + { "toMatchObject"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, ExpectPrototype__toMatchObjectCallback, 1 } }, + { "toMatchSnapshot"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, ExpectPrototype__toMatchSnapshotCallback, 1 } }, + { "toStrictEqual"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, ExpectPrototype__toStrictEqualCallback, 1 } }, + { "toThrow"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, ExpectPrototype__toThrowCallback, 1 } }, + { "toThrowErrorMatchingInlineSnapshot"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, ExpectPrototype__toThrowErrorMatchingInlineSnapshotCallback, 1 } }, + { "toThrowErrorMatchingSnapshot"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, ExpectPrototype__toThrowErrorMatchingSnapshotCallback, 1 } } +}; const ClassInfo JSExpectPrototype::s_info = { "Expect"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSExpectPrototype) }; @@ -5925,10 +6200,41 @@ JSC_DEFINE_CUSTOM_GETTER(ExpectPrototype__resolvesGetterWrap, (JSGlobalObject * JSExpect* thisObject = jsDynamicCast<JSExpect*>(callFrame->thisValue()); - if (UNLIKELY(!thisObject)) { - auto throwScope = DECLARE_THROW_SCOPE(vm); - return throwVMTypeError(lexicalGlobalObject, throwScope); - } +JSC_DEFINE_HOST_FUNCTION(ExpectPrototype__toBeDefinedCallback, (JSGlobalObject * lexicalGlobalObject, CallFrame* callFrame)) +{ + auto& vm = lexicalGlobalObject->vm(); + + JSExpect* thisObject = jsDynamicCast<JSExpect*>(callFrame->thisValue()); + + if (UNLIKELY(!thisObject)) { + auto throwScope = DECLARE_THROW_SCOPE(vm); + return throwVMTypeError(lexicalGlobalObject, throwScope); + } + + JSC::EnsureStillAliveScope thisArg = JSC::EnsureStillAliveScope(thisObject); + + return ExpectPrototype__toBeDefined(thisObject->wrapped(), lexicalGlobalObject, callFrame); +} + +JSC_DEFINE_HOST_FUNCTION(ExpectPrototype__toBeFalsyCallback, (JSGlobalObject * lexicalGlobalObject, CallFrame* callFrame)) +{ + auto& vm = lexicalGlobalObject->vm(); + + JSExpect* thisObject = jsDynamicCast<JSExpect*>(callFrame->thisValue()); + + if (UNLIKELY(!thisObject)) { + auto throwScope = DECLARE_THROW_SCOPE(vm); + return throwVMTypeError(lexicalGlobalObject, throwScope); + } + + JSC::EnsureStillAliveScope thisArg = JSC::EnsureStillAliveScope(thisObject); + + return ExpectPrototype__toBeFalsy(thisObject->wrapped(), lexicalGlobalObject, callFrame); +} + +JSC_DEFINE_HOST_FUNCTION(ExpectPrototype__toBeGreaterThanCallback, (JSGlobalObject * lexicalGlobalObject, CallFrame* callFrame)) +{ + auto& vm = lexicalGlobalObject->vm(); JSC::EnsureStillAliveScope thisArg = JSC::EnsureStillAliveScope(thisObject); @@ -6010,10 +6316,73 @@ JSC_DEFINE_CUSTOM_GETTER(ExpectPrototype__resolvesGetterWrap, (JSGlobalObject * JSExpect* thisObject = jsDynamicCast<JSExpect*>(callFrame->thisValue()); - if (UNLIKELY(!thisObject)) { - auto throwScope = DECLARE_THROW_SCOPE(vm); - return throwVMTypeError(lexicalGlobalObject, throwScope); - } +JSC_DEFINE_HOST_FUNCTION(ExpectPrototype__toBeNaNCallback, (JSGlobalObject * lexicalGlobalObject, CallFrame* callFrame)) +{ + auto& vm = lexicalGlobalObject->vm(); + + JSExpect* thisObject = jsDynamicCast<JSExpect*>(callFrame->thisValue()); + + if (UNLIKELY(!thisObject)) { + auto throwScope = DECLARE_THROW_SCOPE(vm); + return throwVMTypeError(lexicalGlobalObject, throwScope); + } + + JSC::EnsureStillAliveScope thisArg = JSC::EnsureStillAliveScope(thisObject); + + return ExpectPrototype__toBeNaN(thisObject->wrapped(), lexicalGlobalObject, callFrame); +} + +JSC_DEFINE_HOST_FUNCTION(ExpectPrototype__toBeNullCallback, (JSGlobalObject * lexicalGlobalObject, CallFrame* callFrame)) +{ + auto& vm = lexicalGlobalObject->vm(); + + JSExpect* thisObject = jsDynamicCast<JSExpect*>(callFrame->thisValue()); + + if (UNLIKELY(!thisObject)) { + auto throwScope = DECLARE_THROW_SCOPE(vm); + return throwVMTypeError(lexicalGlobalObject, throwScope); + } + + JSC::EnsureStillAliveScope thisArg = JSC::EnsureStillAliveScope(thisObject); + + return ExpectPrototype__toBeNull(thisObject->wrapped(), lexicalGlobalObject, callFrame); +} + +JSC_DEFINE_HOST_FUNCTION(ExpectPrototype__toBeTruthyCallback, (JSGlobalObject * lexicalGlobalObject, CallFrame* callFrame)) +{ + auto& vm = lexicalGlobalObject->vm(); + + JSExpect* thisObject = jsDynamicCast<JSExpect*>(callFrame->thisValue()); + + if (UNLIKELY(!thisObject)) { + auto throwScope = DECLARE_THROW_SCOPE(vm); + return throwVMTypeError(lexicalGlobalObject, throwScope); + } + + JSC::EnsureStillAliveScope thisArg = JSC::EnsureStillAliveScope(thisObject); + + return ExpectPrototype__toBeTruthy(thisObject->wrapped(), lexicalGlobalObject, callFrame); +} + +JSC_DEFINE_HOST_FUNCTION(ExpectPrototype__toBeUndefinedCallback, (JSGlobalObject * lexicalGlobalObject, CallFrame* callFrame)) +{ + auto& vm = lexicalGlobalObject->vm(); + + JSExpect* thisObject = jsDynamicCast<JSExpect*>(callFrame->thisValue()); + + if (UNLIKELY(!thisObject)) { + auto throwScope = DECLARE_THROW_SCOPE(vm); + return throwVMTypeError(lexicalGlobalObject, throwScope); + } + + JSC::EnsureStillAliveScope thisArg = JSC::EnsureStillAliveScope(thisObject); + + return ExpectPrototype__toBeUndefined(thisObject->wrapped(), lexicalGlobalObject, callFrame); +} + +JSC_DEFINE_HOST_FUNCTION(ExpectPrototype__toContainCallback, (JSGlobalObject * lexicalGlobalObject, CallFrame* callFrame)) +{ + auto& vm = lexicalGlobalObject->vm(); JSC::EnsureStillAliveScope thisArg = JSC::EnsureStillAliveScope(thisObject); @@ -6483,14 +6852,6 @@ JSC::EncodedJSValue JSC_HOST_CALL_ATTRIBUTES JSExpectConstructor::construct(JSC: return JSValue::encode(instance); } -extern "C" EncodedJSValue Expect__create(Zig::GlobalObject* globalObject, void* ptr) { - auto &vm = globalObject->vm(); - JSC::Structure* structure = globalObject->JSExpectStructure(); - JSExpect* instance = JSExpect::create(vm, globalObject, structure, ptr); - - return JSValue::encode(instance); -} - void JSExpectConstructor::initializeProperties(VM& vm, JSC::JSGlobalObject* globalObject, JSExpectPrototype* prototype) { @@ -6573,7 +6934,16 @@ JSObject* JSExpect::createPrototype(VM& vm, JSDOMGlobalObject* globalObject) { return JSExpectPrototype::create(vm, globalObject, JSExpectPrototype::createStructure(vm, globalObject, globalObject->objectPrototype())); } - + +extern "C" EncodedJSValue Expect__create(Zig::GlobalObject* globalObject, void* ptr) +{ + auto& vm = globalObject->vm(); + JSC::Structure* structure = globalObject->JSExpectStructure(); + JSExpect* instance = JSExpect::create(vm, globalObject, structure, ptr); + + return JSValue::encode(instance); +} + template<typename Visitor> void JSExpect::visitChildrenImpl(JSCell* cell, Visitor& visitor) { @@ -6586,49 +6956,33 @@ visitor.append(thisObject->m_resultValue); } -DEFINE_VISIT_CHILDREN(JSExpect);class JSTextDecoderPrototype final : public JSC::JSNonFinalObject { - public: - using Base = JSC::JSNonFinalObject; - - static JSTextDecoderPrototype* create(JSC::VM& vm, JSGlobalObject* globalObject, JSC::Structure* structure) - { - JSTextDecoderPrototype* ptr = new (NotNull, JSC::allocateCell<JSTextDecoderPrototype>(vm)) JSTextDecoderPrototype(vm, globalObject, structure); - ptr->finishCreation(vm, globalObject); - return ptr; - } - - DECLARE_INFO; - template<typename CellType, JSC::SubspaceAccess> - static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) - { - return &vm.plainObjectSpace(); - } - static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) - { - return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), info()); - } - - private: - JSTextDecoderPrototype(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure) - : Base(vm, structure) - { - } - - void finishCreation(JSC::VM&, JSC::JSGlobalObject*); - }; - - class JSTextDecoderConstructor final : public JSC::InternalFunction { - public: - using Base = JSC::InternalFunction; - static JSTextDecoderConstructor* create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure, JSTextDecoderPrototype* prototype); - - static constexpr unsigned StructureFlags = Base::StructureFlags; - static constexpr bool needsDestruction = false; - - static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) - { - return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::InternalFunctionType, StructureFlags), info()); - } +DEFINE_VISIT_CHILDREN(JSExpect); + +template<typename Visitor> +void JSExpect::visitAdditionalChildren(Visitor& visitor) +{ + JSExpect* thisObject = this; + ASSERT_GC_OBJECT_INHERITS(thisObject, info()); + visitor.append(thisObject->m_capturedValue); + visitor.append(thisObject->m_resultValue); + + ; +} + +DEFINE_VISIT_ADDITIONAL_CHILDREN(JSExpect); + +template<typename Visitor> +void JSExpect::visitOutputConstraintsImpl(JSCell* cell, Visitor& visitor) +{ + JSExpect* thisObject = jsCast<JSExpect*>(cell); + ASSERT_GC_OBJECT_INHERITS(thisObject, info()); + thisObject->visitAdditionalChildren<Visitor>(visitor); +} + +DEFINE_VISIT_OUTPUT_CONSTRAINTS(JSExpect); +class JSTextDecoderPrototype final : public JSC::JSNonFinalObject { +public: + using Base = JSC::JSNonFinalObject; template<typename, JSC::SubspaceAccess mode> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) { @@ -6843,14 +7197,6 @@ JSC::EncodedJSValue JSC_HOST_CALL_ATTRIBUTES JSTextDecoderConstructor::construct return JSValue::encode(instance); } -extern "C" EncodedJSValue TextDecoder__create(Zig::GlobalObject* globalObject, void* ptr) { - auto &vm = globalObject->vm(); - JSC::Structure* structure = globalObject->JSTextDecoderStructure(); - JSTextDecoder* instance = JSTextDecoder::create(vm, globalObject, structure, ptr); - - return JSValue::encode(instance); -} - void JSTextDecoderConstructor::initializeProperties(VM& vm, JSC::JSGlobalObject* globalObject, JSTextDecoderPrototype* prototype) { @@ -6933,7 +7279,16 @@ JSObject* JSTextDecoder::createPrototype(VM& vm, JSDOMGlobalObject* globalObject { return JSTextDecoderPrototype::create(vm, globalObject, JSTextDecoderPrototype::createStructure(vm, globalObject, globalObject->objectPrototype())); } - + +extern "C" EncodedJSValue TextDecoder__create(Zig::GlobalObject* globalObject, void* ptr) +{ + auto& vm = globalObject->vm(); + JSC::Structure* structure = globalObject->JSTextDecoderStructure(); + JSTextDecoder* instance = JSTextDecoder::create(vm, globalObject, structure, ptr); + + return JSValue::encode(instance); +} + template<typename Visitor> void JSTextDecoder::visitChildrenImpl(JSCell* cell, Visitor& visitor) { @@ -6945,49 +7300,32 @@ void JSTextDecoder::visitChildrenImpl(JSCell* cell, Visitor& visitor) visitor.append(thisObject->m_encoding); } -DEFINE_VISIT_CHILDREN(JSTextDecoder);class JSRequestPrototype final : public JSC::JSNonFinalObject { - public: - using Base = JSC::JSNonFinalObject; - - static JSRequestPrototype* create(JSC::VM& vm, JSGlobalObject* globalObject, JSC::Structure* structure) - { - JSRequestPrototype* ptr = new (NotNull, JSC::allocateCell<JSRequestPrototype>(vm)) JSRequestPrototype(vm, globalObject, structure); - ptr->finishCreation(vm, globalObject); - return ptr; - } - - DECLARE_INFO; - template<typename CellType, JSC::SubspaceAccess> - static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) - { - return &vm.plainObjectSpace(); - } - static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) - { - return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), info()); - } - - private: - JSRequestPrototype(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure) - : Base(vm, structure) - { - } - - void finishCreation(JSC::VM&, JSC::JSGlobalObject*); - }; - - class JSRequestConstructor final : public JSC::InternalFunction { - public: - using Base = JSC::InternalFunction; - static JSRequestConstructor* create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure, JSRequestPrototype* prototype); - - static constexpr unsigned StructureFlags = Base::StructureFlags; - static constexpr bool needsDestruction = false; - - static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) - { - return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::InternalFunctionType, StructureFlags), info()); - } +DEFINE_VISIT_CHILDREN(JSTextDecoder); + +template<typename Visitor> +void JSTextDecoder::visitAdditionalChildren(Visitor& visitor) +{ + JSTextDecoder* thisObject = this; + ASSERT_GC_OBJECT_INHERITS(thisObject, info()); + + visitor.append(thisObject->m_encoding); + ; +} + +DEFINE_VISIT_ADDITIONAL_CHILDREN(JSTextDecoder); + +template<typename Visitor> +void JSTextDecoder::visitOutputConstraintsImpl(JSCell* cell, Visitor& visitor) +{ + JSTextDecoder* thisObject = jsCast<JSTextDecoder*>(cell); + ASSERT_GC_OBJECT_INHERITS(thisObject, info()); + thisObject->visitAdditionalChildren<Visitor>(visitor); +} + +DEFINE_VISIT_OUTPUT_CONSTRAINTS(JSTextDecoder); +class JSRequestPrototype final : public JSC::JSNonFinalObject { +public: + using Base = JSC::JSNonFinalObject; template<typename, JSC::SubspaceAccess mode> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) { @@ -7518,14 +7856,6 @@ JSC::EncodedJSValue JSC_HOST_CALL_ATTRIBUTES JSRequestConstructor::construct(JSC return JSValue::encode(instance); } -extern "C" EncodedJSValue Request__create(Zig::GlobalObject* globalObject, void* ptr) { - auto &vm = globalObject->vm(); - JSC::Structure* structure = globalObject->JSRequestStructure(); - JSRequest* instance = JSRequest::create(vm, globalObject, structure, ptr); - vm.heap.reportExtraMemoryAllocated(Request__estimatedSize(ptr)); - return JSValue::encode(instance); -} - void JSRequestConstructor::initializeProperties(VM& vm, JSC::JSGlobalObject* globalObject, JSRequestPrototype* prototype) { @@ -7608,7 +7938,16 @@ JSObject* JSRequest::createPrototype(VM& vm, JSDOMGlobalObject* globalObject) { return JSRequestPrototype::create(vm, globalObject, JSRequestPrototype::createStructure(vm, globalObject, globalObject->objectPrototype())); } - + +extern "C" EncodedJSValue Request__create(Zig::GlobalObject* globalObject, void* ptr) +{ + auto& vm = globalObject->vm(); + JSC::Structure* structure = globalObject->JSRequestStructure(); + JSRequest* instance = JSRequest::create(vm, globalObject, structure, ptr); + vm.heap.reportExtraMemoryAllocated(Request__estimatedSize(ptr)); + return JSValue::encode(instance); +} + template<typename Visitor> void JSRequest::visitChildrenImpl(JSCell* cell, Visitor& visitor) { @@ -7624,49 +7963,34 @@ visitor.reportExtraMemoryVisited(Request__estimatedSize(ptr)); visitor.append(thisObject->m_url); } -DEFINE_VISIT_CHILDREN(JSRequest);class JSResponsePrototype final : public JSC::JSNonFinalObject { - public: - using Base = JSC::JSNonFinalObject; - - static JSResponsePrototype* create(JSC::VM& vm, JSGlobalObject* globalObject, JSC::Structure* structure) - { - JSResponsePrototype* ptr = new (NotNull, JSC::allocateCell<JSResponsePrototype>(vm)) JSResponsePrototype(vm, globalObject, structure); - ptr->finishCreation(vm, globalObject); - return ptr; - } - - DECLARE_INFO; - template<typename CellType, JSC::SubspaceAccess> - static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) - { - return &vm.plainObjectSpace(); - } - static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) - { - return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), info()); - } - - private: - JSResponsePrototype(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure) - : Base(vm, structure) - { - } - - void finishCreation(JSC::VM&, JSC::JSGlobalObject*); - }; - - class JSResponseConstructor final : public JSC::InternalFunction { - public: - using Base = JSC::InternalFunction; - static JSResponseConstructor* create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure, JSResponsePrototype* prototype); - - static constexpr unsigned StructureFlags = Base::StructureFlags; - static constexpr bool needsDestruction = false; - - static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) - { - return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::InternalFunctionType, StructureFlags), info()); - } +DEFINE_VISIT_CHILDREN(JSRequest); + +template<typename Visitor> +void JSRequest::visitAdditionalChildren(Visitor& visitor) +{ + JSRequest* thisObject = this; + ASSERT_GC_OBJECT_INHERITS(thisObject, info()); + + visitor.append(thisObject->m_body); + visitor.append(thisObject->m_headers); + visitor.append(thisObject->m_url); + ; +} + +DEFINE_VISIT_ADDITIONAL_CHILDREN(JSRequest); + +template<typename Visitor> +void JSRequest::visitOutputConstraintsImpl(JSCell* cell, Visitor& visitor) +{ + JSRequest* thisObject = jsCast<JSRequest*>(cell); + ASSERT_GC_OBJECT_INHERITS(thisObject, info()); + thisObject->visitAdditionalChildren<Visitor>(visitor); +} + +DEFINE_VISIT_OUTPUT_CONSTRAINTS(JSRequest); +class JSResponsePrototype final : public JSC::JSNonFinalObject { +public: + using Base = JSC::JSNonFinalObject; template<typename, JSC::SubspaceAccess mode> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) { @@ -8155,14 +8479,6 @@ JSC::EncodedJSValue JSC_HOST_CALL_ATTRIBUTES JSResponseConstructor::construct(JS return JSValue::encode(instance); } -extern "C" EncodedJSValue Response__create(Zig::GlobalObject* globalObject, void* ptr) { - auto &vm = globalObject->vm(); - JSC::Structure* structure = globalObject->JSResponseStructure(); - JSResponse* instance = JSResponse::create(vm, globalObject, structure, ptr); - vm.heap.reportExtraMemoryAllocated(Response__estimatedSize(ptr)); - return JSValue::encode(instance); -} - void JSResponseConstructor::initializeProperties(VM& vm, JSC::JSGlobalObject* globalObject, JSResponsePrototype* prototype) { @@ -8245,7 +8561,16 @@ JSObject* JSResponse::createPrototype(VM& vm, JSDOMGlobalObject* globalObject) { return JSResponsePrototype::create(vm, globalObject, JSResponsePrototype::createStructure(vm, globalObject, globalObject->objectPrototype())); } - + +extern "C" EncodedJSValue Response__create(Zig::GlobalObject* globalObject, void* ptr) +{ + auto& vm = globalObject->vm(); + JSC::Structure* structure = globalObject->JSResponseStructure(); + JSResponse* instance = JSResponse::create(vm, globalObject, structure, ptr); + vm.heap.reportExtraMemoryAllocated(Response__estimatedSize(ptr)); + return JSValue::encode(instance); +} + template<typename Visitor> void JSResponse::visitChildrenImpl(JSCell* cell, Visitor& visitor) { @@ -8262,49 +8587,35 @@ visitor.reportExtraMemoryVisited(Response__estimatedSize(ptr)); visitor.append(thisObject->m_url); } -DEFINE_VISIT_CHILDREN(JSResponse);class JSBlobPrototype final : public JSC::JSNonFinalObject { - public: - using Base = JSC::JSNonFinalObject; - - static JSBlobPrototype* create(JSC::VM& vm, JSGlobalObject* globalObject, JSC::Structure* structure) - { - JSBlobPrototype* ptr = new (NotNull, JSC::allocateCell<JSBlobPrototype>(vm)) JSBlobPrototype(vm, globalObject, structure); - ptr->finishCreation(vm, globalObject); - return ptr; - } - - DECLARE_INFO; - template<typename CellType, JSC::SubspaceAccess> - static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) - { - return &vm.plainObjectSpace(); - } - static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) - { - return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), info()); - } - - private: - JSBlobPrototype(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure) - : Base(vm, structure) - { - } - - void finishCreation(JSC::VM&, JSC::JSGlobalObject*); - }; - - class JSBlobConstructor final : public JSC::InternalFunction { - public: - using Base = JSC::InternalFunction; - static JSBlobConstructor* create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure, JSBlobPrototype* prototype); - - static constexpr unsigned StructureFlags = Base::StructureFlags; - static constexpr bool needsDestruction = false; - - static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) - { - return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::InternalFunctionType, StructureFlags), info()); - } +DEFINE_VISIT_CHILDREN(JSResponse); + +template<typename Visitor> +void JSResponse::visitAdditionalChildren(Visitor& visitor) +{ + JSResponse* thisObject = this; + ASSERT_GC_OBJECT_INHERITS(thisObject, info()); + + visitor.append(thisObject->m_body); + visitor.append(thisObject->m_headers); + visitor.append(thisObject->m_statusText); + visitor.append(thisObject->m_url); + ; +} + +DEFINE_VISIT_ADDITIONAL_CHILDREN(JSResponse); + +template<typename Visitor> +void JSResponse::visitOutputConstraintsImpl(JSCell* cell, Visitor& visitor) +{ + JSResponse* thisObject = jsCast<JSResponse*>(cell); + ASSERT_GC_OBJECT_INHERITS(thisObject, info()); + thisObject->visitAdditionalChildren<Visitor>(visitor); +} + +DEFINE_VISIT_OUTPUT_CONSTRAINTS(JSResponse); +class JSBlobPrototype final : public JSC::JSNonFinalObject { +public: + using Base = JSC::JSNonFinalObject; template<typename, JSC::SubspaceAccess mode> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) { @@ -8605,14 +8916,6 @@ JSC::EncodedJSValue JSC_HOST_CALL_ATTRIBUTES JSBlobConstructor::construct(JSC::J return JSValue::encode(instance); } -extern "C" EncodedJSValue Blob__create(Zig::GlobalObject* globalObject, void* ptr) { - auto &vm = globalObject->vm(); - JSC::Structure* structure = globalObject->JSBlobStructure(); - JSBlob* instance = JSBlob::create(vm, globalObject, structure, ptr); - - return JSValue::encode(instance); -} - void JSBlobConstructor::initializeProperties(VM& vm, JSC::JSGlobalObject* globalObject, JSBlobPrototype* prototype) { @@ -8696,5 +8999,14 @@ JSObject* JSBlob::createPrototype(VM& vm, JSDOMGlobalObject* globalObject) return JSBlobPrototype::create(vm, globalObject, JSBlobPrototype::createStructure(vm, globalObject, globalObject->objectPrototype())); } +extern "C" EncodedJSValue Blob__create(Zig::GlobalObject* globalObject, void* ptr) +{ + auto& vm = globalObject->vm(); + JSC::Structure* structure = globalObject->JSBlobStructure(); + JSBlob* instance = JSBlob::create(vm, globalObject, structure, ptr); + + return JSValue::encode(instance); +} + } // namespace WebCore diff --git a/src/bun.js/bindings/ZigGeneratedClasses.h b/src/bun.js/bindings/ZigGeneratedClasses.h index 4fc128002..700d7bab3 100644 --- a/src/bun.js/bindings/ZigGeneratedClasses.h +++ b/src/bun.js/bindings/ZigGeneratedClasses.h @@ -16,1050 +16,1170 @@ using namespace Zig; using namespace JSC; class JSTCPSocket final : public JSC::JSDestructibleObject { - public: - using Base = JSC::JSDestructibleObject; - static JSTCPSocket* create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure, void* ctx); - - DECLARE_EXPORT_INFO; - template<typename, JSC::SubspaceAccess mode> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) - { - if constexpr (mode == JSC::SubspaceAccess::Concurrently) - return nullptr; - return WebCore::subspaceForImpl<JSTCPSocket, WebCore::UseCustomHeapCellType::No>( - vm, - [](auto& spaces) { return spaces.m_clientSubspaceForTCPSocket.get(); }, - [](auto& spaces, auto&& space) { spaces.m_clientSubspaceForTCPSocket = WTFMove(space); }, - [](auto& spaces) { return spaces.m_subspaceForTCPSocket.get(); }, - [](auto& spaces, auto&& space) { spaces.m_subspaceForTCPSocket = WTFMove(space); }); - } - - static void destroy(JSC::JSCell*); - static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) - { - return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(static_cast<JSC::JSType>(0b11101110), StructureFlags), info()); - } - - static JSObject* createPrototype(VM& vm, JSDOMGlobalObject* globalObject); - static JSObject* createConstructor(VM& vm, JSGlobalObject* globalObject, JSValue prototype); - - ~JSTCPSocket(); - - void* wrapped() const { return m_ctx; } - - void detach() - { - m_ctx = nullptr; - } - - static void analyzeHeap(JSCell*, JSC::HeapAnalyzer&); - static ptrdiff_t offsetOfWrapped() { return OBJECT_OFFSETOF(JSTCPSocket, m_ctx); } - - void* m_ctx { nullptr }; - - - JSTCPSocket(JSC::VM& vm, JSC::Structure* structure, void* sinkPtr) - : Base(vm, structure) - { - m_ctx = sinkPtr; - - } - - void finishCreation(JSC::VM&); +public: + using Base = JSC::JSDestructibleObject; + static JSTCPSocket* create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure, void* ctx); - + DECLARE_EXPORT_INFO; + template<typename, JSC::SubspaceAccess mode> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) + { + if constexpr (mode == JSC::SubspaceAccess::Concurrently) + return nullptr; + return WebCore::subspaceForImpl<JSTCPSocket, WebCore::UseCustomHeapCellType::No>( + vm, + [](auto& spaces) { return spaces.m_clientSubspaceForTCPSocket.get(); }, + [](auto& spaces, auto&& space) { spaces.m_clientSubspaceForTCPSocket = WTFMove(space); }, + [](auto& spaces) { return spaces.m_subspaceForTCPSocket.get(); }, + [](auto& spaces, auto&& space) { spaces.m_subspaceForTCPSocket = WTFMove(space); }); + } - DECLARE_VISIT_CHILDREN; - - mutable JSC::WriteBarrier<JSC::Unknown> m_data; -mutable JSC::WriteBarrier<JSC::Unknown> m_remoteAddress; - };class JSTLSSocket final : public JSC::JSDestructibleObject { - public: - using Base = JSC::JSDestructibleObject; - static JSTLSSocket* create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure, void* ctx); - - DECLARE_EXPORT_INFO; - template<typename, JSC::SubspaceAccess mode> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) - { - if constexpr (mode == JSC::SubspaceAccess::Concurrently) - return nullptr; - return WebCore::subspaceForImpl<JSTLSSocket, WebCore::UseCustomHeapCellType::No>( - vm, - [](auto& spaces) { return spaces.m_clientSubspaceForTLSSocket.get(); }, - [](auto& spaces, auto&& space) { spaces.m_clientSubspaceForTLSSocket = WTFMove(space); }, - [](auto& spaces) { return spaces.m_subspaceForTLSSocket.get(); }, - [](auto& spaces, auto&& space) { spaces.m_subspaceForTLSSocket = WTFMove(space); }); - } - - static void destroy(JSC::JSCell*); - static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) - { - return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(static_cast<JSC::JSType>(0b11101110), StructureFlags), info()); - } - - static JSObject* createPrototype(VM& vm, JSDOMGlobalObject* globalObject); - static JSObject* createConstructor(VM& vm, JSGlobalObject* globalObject, JSValue prototype); - - ~JSTLSSocket(); - - void* wrapped() const { return m_ctx; } - - void detach() - { - m_ctx = nullptr; - } - - static void analyzeHeap(JSCell*, JSC::HeapAnalyzer&); - static ptrdiff_t offsetOfWrapped() { return OBJECT_OFFSETOF(JSTLSSocket, m_ctx); } - - void* m_ctx { nullptr }; - - - JSTLSSocket(JSC::VM& vm, JSC::Structure* structure, void* sinkPtr) - : Base(vm, structure) - { - m_ctx = sinkPtr; - - } - - void finishCreation(JSC::VM&); - - - - DECLARE_VISIT_CHILDREN; - - mutable JSC::WriteBarrier<JSC::Unknown> m_data; -mutable JSC::WriteBarrier<JSC::Unknown> m_remoteAddress; - };class JSListener final : public JSC::JSDestructibleObject { - public: - using Base = JSC::JSDestructibleObject; - static JSListener* create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure, void* ctx); - - DECLARE_EXPORT_INFO; - template<typename, JSC::SubspaceAccess mode> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) - { - if constexpr (mode == JSC::SubspaceAccess::Concurrently) - return nullptr; - return WebCore::subspaceForImpl<JSListener, WebCore::UseCustomHeapCellType::No>( - vm, - [](auto& spaces) { return spaces.m_clientSubspaceForListener.get(); }, - [](auto& spaces, auto&& space) { spaces.m_clientSubspaceForListener = WTFMove(space); }, - [](auto& spaces) { return spaces.m_subspaceForListener.get(); }, - [](auto& spaces, auto&& space) { spaces.m_subspaceForListener = WTFMove(space); }); - } - - static void destroy(JSC::JSCell*); - static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) - { - return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(static_cast<JSC::JSType>(0b11101110), StructureFlags), info()); - } - - static JSObject* createPrototype(VM& vm, JSDOMGlobalObject* globalObject); - static JSObject* createConstructor(VM& vm, JSGlobalObject* globalObject, JSValue prototype); - - ~JSListener(); - - void* wrapped() const { return m_ctx; } - - void detach() - { - m_ctx = nullptr; - } - - static void analyzeHeap(JSCell*, JSC::HeapAnalyzer&); - static ptrdiff_t offsetOfWrapped() { return OBJECT_OFFSETOF(JSListener, m_ctx); } - - void* m_ctx { nullptr }; - - - JSListener(JSC::VM& vm, JSC::Structure* structure, void* sinkPtr) - : Base(vm, structure) - { - m_ctx = sinkPtr; - - } - - void finishCreation(JSC::VM&); - - - - DECLARE_VISIT_CHILDREN; - - mutable JSC::WriteBarrier<JSC::Unknown> m_hostname; -mutable JSC::WriteBarrier<JSC::Unknown> m_unix; - };class JSSubprocess final : public JSC::JSDestructibleObject { - public: - using Base = JSC::JSDestructibleObject; - static JSSubprocess* create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure, void* ctx); - - DECLARE_EXPORT_INFO; - template<typename, JSC::SubspaceAccess mode> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) - { - if constexpr (mode == JSC::SubspaceAccess::Concurrently) - return nullptr; - return WebCore::subspaceForImpl<JSSubprocess, WebCore::UseCustomHeapCellType::No>( - vm, - [](auto& spaces) { return spaces.m_clientSubspaceForSubprocess.get(); }, - [](auto& spaces, auto&& space) { spaces.m_clientSubspaceForSubprocess = WTFMove(space); }, - [](auto& spaces) { return spaces.m_subspaceForSubprocess.get(); }, - [](auto& spaces, auto&& space) { spaces.m_subspaceForSubprocess = WTFMove(space); }); - } - - static void destroy(JSC::JSCell*); - static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) - { - return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(static_cast<JSC::JSType>(0b11101110), StructureFlags), info()); - } - - static JSObject* createPrototype(VM& vm, JSDOMGlobalObject* globalObject); - static JSObject* createConstructor(VM& vm, JSGlobalObject* globalObject, JSValue prototype); - - ~JSSubprocess(); - - void* wrapped() const { return m_ctx; } - - void detach() - { - m_ctx = nullptr; - } - - static void analyzeHeap(JSCell*, JSC::HeapAnalyzer&); - static ptrdiff_t offsetOfWrapped() { return OBJECT_OFFSETOF(JSSubprocess, m_ctx); } - - void* m_ctx { nullptr }; - - - JSSubprocess(JSC::VM& vm, JSC::Structure* structure, void* sinkPtr) - : Base(vm, structure) - { - m_ctx = sinkPtr; - m_weakThis = JSC::Weak<JSSubprocess>(this, getOwner()); - } - - void finishCreation(JSC::VM&); - - - JSC::Weak<JSSubprocess> m_weakThis; - bool internalHasPendingActivity(); - bool hasPendingActivity() { - if (!m_ctx) - return false; - - return this->internalHasPendingActivity(); - } - - class Owner final : public JSC::WeakHandleOwner { - public: - bool isReachableFromOpaqueRoots(JSC::Handle<JSC::Unknown> handle, void* context, JSC::AbstractSlotVisitor&, const char**) final - { - auto* controller = JSC::jsCast<JSSubprocess*>(handle.slot()->asCell()); - return controller->hasPendingActivity(); - } - void finalize(JSC::Handle<JSC::Unknown>, void* context) final {} - }; - - static JSC::WeakHandleOwner* getOwner() - { - static NeverDestroyed<Owner> m_owner; - return &m_owner.get(); - } - + static void destroy(JSC::JSCell*); + static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) + { + return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(static_cast<JSC::JSType>(0b11101110), StructureFlags), info()); + } - DECLARE_VISIT_CHILDREN; + static JSObject* createPrototype(VM& vm, JSDOMGlobalObject* globalObject); + ; - mutable JSC::WriteBarrier<JSC::Unknown> m_stderr; -mutable JSC::WriteBarrier<JSC::Unknown> m_stdin; -mutable JSC::WriteBarrier<JSC::Unknown> m_stdout; - };class JSSHA1 final : public JSC::JSDestructibleObject { - public: - using Base = JSC::JSDestructibleObject; - static JSSHA1* create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure, void* ctx); - - DECLARE_EXPORT_INFO; - template<typename, JSC::SubspaceAccess mode> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) - { - if constexpr (mode == JSC::SubspaceAccess::Concurrently) - return nullptr; - return WebCore::subspaceForImpl<JSSHA1, WebCore::UseCustomHeapCellType::No>( - vm, - [](auto& spaces) { return spaces.m_clientSubspaceForSHA1.get(); }, - [](auto& spaces, auto&& space) { spaces.m_clientSubspaceForSHA1 = WTFMove(space); }, - [](auto& spaces) { return spaces.m_subspaceForSHA1.get(); }, - [](auto& spaces, auto&& space) { spaces.m_subspaceForSHA1 = WTFMove(space); }); - } - - static void destroy(JSC::JSCell*); - static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) - { - return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(static_cast<JSC::JSType>(0b11101110), StructureFlags), info()); - } - - static JSObject* createPrototype(VM& vm, JSDOMGlobalObject* globalObject); - static JSObject* createConstructor(VM& vm, JSGlobalObject* globalObject, JSValue prototype); - - ~JSSHA1(); - - void* wrapped() const { return m_ctx; } - - void detach() - { - m_ctx = nullptr; - } - - static void analyzeHeap(JSCell*, JSC::HeapAnalyzer&); - static ptrdiff_t offsetOfWrapped() { return OBJECT_OFFSETOF(JSSHA1, m_ctx); } - - void* m_ctx { nullptr }; - - - JSSHA1(JSC::VM& vm, JSC::Structure* structure, void* sinkPtr) - : Base(vm, structure) - { - m_ctx = sinkPtr; - - } - - void finishCreation(JSC::VM&); + ~JSTCPSocket(); - + void* wrapped() const { return m_ctx; } - + void detach() + { + m_ctx = nullptr; + } - - };class JSMD5 final : public JSC::JSDestructibleObject { - public: - using Base = JSC::JSDestructibleObject; - static JSMD5* create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure, void* ctx); - - DECLARE_EXPORT_INFO; - template<typename, JSC::SubspaceAccess mode> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) - { - if constexpr (mode == JSC::SubspaceAccess::Concurrently) - return nullptr; - return WebCore::subspaceForImpl<JSMD5, WebCore::UseCustomHeapCellType::No>( - vm, - [](auto& spaces) { return spaces.m_clientSubspaceForMD5.get(); }, - [](auto& spaces, auto&& space) { spaces.m_clientSubspaceForMD5 = WTFMove(space); }, - [](auto& spaces) { return spaces.m_subspaceForMD5.get(); }, - [](auto& spaces, auto&& space) { spaces.m_subspaceForMD5 = WTFMove(space); }); - } - - static void destroy(JSC::JSCell*); - static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) - { - return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(static_cast<JSC::JSType>(0b11101110), StructureFlags), info()); - } - - static JSObject* createPrototype(VM& vm, JSDOMGlobalObject* globalObject); - static JSObject* createConstructor(VM& vm, JSGlobalObject* globalObject, JSValue prototype); - - ~JSMD5(); - - void* wrapped() const { return m_ctx; } - - void detach() - { - m_ctx = nullptr; - } - - static void analyzeHeap(JSCell*, JSC::HeapAnalyzer&); - static ptrdiff_t offsetOfWrapped() { return OBJECT_OFFSETOF(JSMD5, m_ctx); } - - void* m_ctx { nullptr }; - - - JSMD5(JSC::VM& vm, JSC::Structure* structure, void* sinkPtr) - : Base(vm, structure) - { - m_ctx = sinkPtr; - - } - - void finishCreation(JSC::VM&); + static void analyzeHeap(JSCell*, JSC::HeapAnalyzer&); + static ptrdiff_t offsetOfWrapped() { return OBJECT_OFFSETOF(JSTCPSocket, m_ctx); } - + void* m_ctx { nullptr }; - + JSTCPSocket(JSC::VM& vm, JSC::Structure* structure, void* sinkPtr) + : Base(vm, structure) + { + m_ctx = sinkPtr; + m_weakThis = JSC::Weak<JSTCPSocket>(this, getOwner()); + } - - };class JSMD4 final : public JSC::JSDestructibleObject { - public: - using Base = JSC::JSDestructibleObject; - static JSMD4* create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure, void* ctx); - - DECLARE_EXPORT_INFO; - template<typename, JSC::SubspaceAccess mode> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) - { - if constexpr (mode == JSC::SubspaceAccess::Concurrently) - return nullptr; - return WebCore::subspaceForImpl<JSMD4, WebCore::UseCustomHeapCellType::No>( - vm, - [](auto& spaces) { return spaces.m_clientSubspaceForMD4.get(); }, - [](auto& spaces, auto&& space) { spaces.m_clientSubspaceForMD4 = WTFMove(space); }, - [](auto& spaces) { return spaces.m_subspaceForMD4.get(); }, - [](auto& spaces, auto&& space) { spaces.m_subspaceForMD4 = WTFMove(space); }); - } - - static void destroy(JSC::JSCell*); - static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) - { - return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(static_cast<JSC::JSType>(0b11101110), StructureFlags), info()); - } - - static JSObject* createPrototype(VM& vm, JSDOMGlobalObject* globalObject); - static JSObject* createConstructor(VM& vm, JSGlobalObject* globalObject, JSValue prototype); - - ~JSMD4(); - - void* wrapped() const { return m_ctx; } - - void detach() - { - m_ctx = nullptr; - } - - static void analyzeHeap(JSCell*, JSC::HeapAnalyzer&); - static ptrdiff_t offsetOfWrapped() { return OBJECT_OFFSETOF(JSMD4, m_ctx); } - - void* m_ctx { nullptr }; - - - JSMD4(JSC::VM& vm, JSC::Structure* structure, void* sinkPtr) - : Base(vm, structure) - { - m_ctx = sinkPtr; - - } - - void finishCreation(JSC::VM&); + void finishCreation(JSC::VM&); - + JSC::Weak<JSTCPSocket> m_weakThis; - + static bool hasPendingActivity(void* ctx); - - };class JSSHA224 final : public JSC::JSDestructibleObject { + class Owner final : public JSC::WeakHandleOwner { public: - using Base = JSC::JSDestructibleObject; - static JSSHA224* create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure, void* ctx); - - DECLARE_EXPORT_INFO; - template<typename, JSC::SubspaceAccess mode> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) - { - if constexpr (mode == JSC::SubspaceAccess::Concurrently) - return nullptr; - return WebCore::subspaceForImpl<JSSHA224, WebCore::UseCustomHeapCellType::No>( - vm, - [](auto& spaces) { return spaces.m_clientSubspaceForSHA224.get(); }, - [](auto& spaces, auto&& space) { spaces.m_clientSubspaceForSHA224 = WTFMove(space); }, - [](auto& spaces) { return spaces.m_subspaceForSHA224.get(); }, - [](auto& spaces, auto&& space) { spaces.m_subspaceForSHA224 = WTFMove(space); }); - } - - static void destroy(JSC::JSCell*); - static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) - { - return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(static_cast<JSC::JSType>(0b11101110), StructureFlags), info()); - } - - static JSObject* createPrototype(VM& vm, JSDOMGlobalObject* globalObject); - static JSObject* createConstructor(VM& vm, JSGlobalObject* globalObject, JSValue prototype); - - ~JSSHA224(); - - void* wrapped() const { return m_ctx; } - - void detach() - { - m_ctx = nullptr; - } - - static void analyzeHeap(JSCell*, JSC::HeapAnalyzer&); - static ptrdiff_t offsetOfWrapped() { return OBJECT_OFFSETOF(JSSHA224, m_ctx); } - - void* m_ctx { nullptr }; - - - JSSHA224(JSC::VM& vm, JSC::Structure* structure, void* sinkPtr) - : Base(vm, structure) + bool isReachableFromOpaqueRoots(JSC::Handle<JSC::Unknown> handle, void* context, JSC::AbstractSlotVisitor& visitor, const char** reason) final { - m_ctx = sinkPtr; - - } - - void finishCreation(JSC::VM&); - - - - + auto* controller = JSC::jsCast<JSTCPSocket*>(handle.slot()->asCell()); + if (JSTCPSocket::hasPendingActivity(controller->wrapped())) { + if (UNLIKELY(reason)) + *reason = "has pending activity"; + return true; + } - - };class JSSHA512 final : public JSC::JSDestructibleObject { - public: - using Base = JSC::JSDestructibleObject; - static JSSHA512* create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure, void* ctx); - - DECLARE_EXPORT_INFO; - template<typename, JSC::SubspaceAccess mode> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) - { - if constexpr (mode == JSC::SubspaceAccess::Concurrently) - return nullptr; - return WebCore::subspaceForImpl<JSSHA512, WebCore::UseCustomHeapCellType::No>( - vm, - [](auto& spaces) { return spaces.m_clientSubspaceForSHA512.get(); }, - [](auto& spaces, auto&& space) { spaces.m_clientSubspaceForSHA512 = WTFMove(space); }, - [](auto& spaces) { return spaces.m_subspaceForSHA512.get(); }, - [](auto& spaces, auto&& space) { spaces.m_subspaceForSHA512 = WTFMove(space); }); - } - - static void destroy(JSC::JSCell*); - static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) - { - return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(static_cast<JSC::JSType>(0b11101110), StructureFlags), info()); - } - - static JSObject* createPrototype(VM& vm, JSDOMGlobalObject* globalObject); - static JSObject* createConstructor(VM& vm, JSGlobalObject* globalObject, JSValue prototype); - - ~JSSHA512(); - - void* wrapped() const { return m_ctx; } - - void detach() - { - m_ctx = nullptr; - } - - static void analyzeHeap(JSCell*, JSC::HeapAnalyzer&); - static ptrdiff_t offsetOfWrapped() { return OBJECT_OFFSETOF(JSSHA512, m_ctx); } - - void* m_ctx { nullptr }; - - - JSSHA512(JSC::VM& vm, JSC::Structure* structure, void* sinkPtr) - : Base(vm, structure) - { - m_ctx = sinkPtr; - + return visitor.containsOpaqueRoot(context); } - - void finishCreation(JSC::VM&); + void finalize(JSC::Handle<JSC::Unknown>, void* context) final {} + }; - + static JSC::WeakHandleOwner* getOwner() + { + static NeverDestroyed<Owner> m_owner; + return &m_owner.get(); + } - + DECLARE_VISIT_CHILDREN; + template<typename Visitor> void visitAdditionalChildren(Visitor&); + DECLARE_VISIT_OUTPUT_CONSTRAINTS; - - };class JSSHA384 final : public JSC::JSDestructibleObject { - public: - using Base = JSC::JSDestructibleObject; - static JSSHA384* create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure, void* ctx); - - DECLARE_EXPORT_INFO; - template<typename, JSC::SubspaceAccess mode> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) - { - if constexpr (mode == JSC::SubspaceAccess::Concurrently) - return nullptr; - return WebCore::subspaceForImpl<JSSHA384, WebCore::UseCustomHeapCellType::No>( - vm, - [](auto& spaces) { return spaces.m_clientSubspaceForSHA384.get(); }, - [](auto& spaces, auto&& space) { spaces.m_clientSubspaceForSHA384 = WTFMove(space); }, - [](auto& spaces) { return spaces.m_subspaceForSHA384.get(); }, - [](auto& spaces, auto&& space) { spaces.m_subspaceForSHA384 = WTFMove(space); }); - } - - static void destroy(JSC::JSCell*); - static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) - { - return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(static_cast<JSC::JSType>(0b11101110), StructureFlags), info()); - } - - static JSObject* createPrototype(VM& vm, JSDOMGlobalObject* globalObject); - static JSObject* createConstructor(VM& vm, JSGlobalObject* globalObject, JSValue prototype); - - ~JSSHA384(); - - void* wrapped() const { return m_ctx; } - - void detach() - { - m_ctx = nullptr; - } - - static void analyzeHeap(JSCell*, JSC::HeapAnalyzer&); - static ptrdiff_t offsetOfWrapped() { return OBJECT_OFFSETOF(JSSHA384, m_ctx); } - - void* m_ctx { nullptr }; - - - JSSHA384(JSC::VM& vm, JSC::Structure* structure, void* sinkPtr) - : Base(vm, structure) - { - m_ctx = sinkPtr; - - } - - void finishCreation(JSC::VM&); + mutable JSC::WriteBarrier<JSC::Unknown> m_data; + mutable JSC::WriteBarrier<JSC::Unknown> m_remoteAddress; +}; - +class JSTLSSocket final : public JSC::JSDestructibleObject { +public: + using Base = JSC::JSDestructibleObject; + static JSTLSSocket* create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure, void* ctx); - + DECLARE_EXPORT_INFO; + template<typename, JSC::SubspaceAccess mode> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) + { + if constexpr (mode == JSC::SubspaceAccess::Concurrently) + return nullptr; + return WebCore::subspaceForImpl<JSTLSSocket, WebCore::UseCustomHeapCellType::No>( + vm, + [](auto& spaces) { return spaces.m_clientSubspaceForTLSSocket.get(); }, + [](auto& spaces, auto&& space) { spaces.m_clientSubspaceForTLSSocket = WTFMove(space); }, + [](auto& spaces) { return spaces.m_subspaceForTLSSocket.get(); }, + [](auto& spaces, auto&& space) { spaces.m_subspaceForTLSSocket = WTFMove(space); }); + } - - };class JSSHA256 final : public JSC::JSDestructibleObject { - public: - using Base = JSC::JSDestructibleObject; - static JSSHA256* create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure, void* ctx); - - DECLARE_EXPORT_INFO; - template<typename, JSC::SubspaceAccess mode> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) - { - if constexpr (mode == JSC::SubspaceAccess::Concurrently) - return nullptr; - return WebCore::subspaceForImpl<JSSHA256, WebCore::UseCustomHeapCellType::No>( - vm, - [](auto& spaces) { return spaces.m_clientSubspaceForSHA256.get(); }, - [](auto& spaces, auto&& space) { spaces.m_clientSubspaceForSHA256 = WTFMove(space); }, - [](auto& spaces) { return spaces.m_subspaceForSHA256.get(); }, - [](auto& spaces, auto&& space) { spaces.m_subspaceForSHA256 = WTFMove(space); }); - } - - static void destroy(JSC::JSCell*); - static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) - { - return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(static_cast<JSC::JSType>(0b11101110), StructureFlags), info()); - } - - static JSObject* createPrototype(VM& vm, JSDOMGlobalObject* globalObject); - static JSObject* createConstructor(VM& vm, JSGlobalObject* globalObject, JSValue prototype); - - ~JSSHA256(); - - void* wrapped() const { return m_ctx; } - - void detach() - { - m_ctx = nullptr; - } - - static void analyzeHeap(JSCell*, JSC::HeapAnalyzer&); - static ptrdiff_t offsetOfWrapped() { return OBJECT_OFFSETOF(JSSHA256, m_ctx); } - - void* m_ctx { nullptr }; - - - JSSHA256(JSC::VM& vm, JSC::Structure* structure, void* sinkPtr) - : Base(vm, structure) - { - m_ctx = sinkPtr; - - } - - void finishCreation(JSC::VM&); + static void destroy(JSC::JSCell*); + static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) + { + return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(static_cast<JSC::JSType>(0b11101110), StructureFlags), info()); + } - + static JSObject* createPrototype(VM& vm, JSDOMGlobalObject* globalObject); + ; - + ~JSTLSSocket(); - - };class JSSHA512_256 final : public JSC::JSDestructibleObject { - public: - using Base = JSC::JSDestructibleObject; - static JSSHA512_256* create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure, void* ctx); - - DECLARE_EXPORT_INFO; - template<typename, JSC::SubspaceAccess mode> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) - { - if constexpr (mode == JSC::SubspaceAccess::Concurrently) - return nullptr; - return WebCore::subspaceForImpl<JSSHA512_256, WebCore::UseCustomHeapCellType::No>( - vm, - [](auto& spaces) { return spaces.m_clientSubspaceForSHA512_256.get(); }, - [](auto& spaces, auto&& space) { spaces.m_clientSubspaceForSHA512_256 = WTFMove(space); }, - [](auto& spaces) { return spaces.m_subspaceForSHA512_256.get(); }, - [](auto& spaces, auto&& space) { spaces.m_subspaceForSHA512_256 = WTFMove(space); }); - } - - static void destroy(JSC::JSCell*); - static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) - { - return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(static_cast<JSC::JSType>(0b11101110), StructureFlags), info()); - } - - static JSObject* createPrototype(VM& vm, JSDOMGlobalObject* globalObject); - static JSObject* createConstructor(VM& vm, JSGlobalObject* globalObject, JSValue prototype); - - ~JSSHA512_256(); - - void* wrapped() const { return m_ctx; } - - void detach() - { - m_ctx = nullptr; - } - - static void analyzeHeap(JSCell*, JSC::HeapAnalyzer&); - static ptrdiff_t offsetOfWrapped() { return OBJECT_OFFSETOF(JSSHA512_256, m_ctx); } - - void* m_ctx { nullptr }; - - - JSSHA512_256(JSC::VM& vm, JSC::Structure* structure, void* sinkPtr) - : Base(vm, structure) - { - m_ctx = sinkPtr; - - } - - void finishCreation(JSC::VM&); + void* wrapped() const { return m_ctx; } - + void detach() + { + m_ctx = nullptr; + } - - - - };class JSServerWebSocket final : public JSC::JSDestructibleObject { - public: - using Base = JSC::JSDestructibleObject; - static JSServerWebSocket* create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure, void* ctx); - - DECLARE_EXPORT_INFO; - template<typename, JSC::SubspaceAccess mode> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) - { - if constexpr (mode == JSC::SubspaceAccess::Concurrently) - return nullptr; - return WebCore::subspaceForImpl<JSServerWebSocket, WebCore::UseCustomHeapCellType::No>( - vm, - [](auto& spaces) { return spaces.m_clientSubspaceForServerWebSocket.get(); }, - [](auto& spaces, auto&& space) { spaces.m_clientSubspaceForServerWebSocket = WTFMove(space); }, - [](auto& spaces) { return spaces.m_subspaceForServerWebSocket.get(); }, - [](auto& spaces, auto&& space) { spaces.m_subspaceForServerWebSocket = WTFMove(space); }); - } - - static void destroy(JSC::JSCell*); - static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) - { - return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(static_cast<JSC::JSType>(0b11101110), StructureFlags), info()); - } - - static JSObject* createPrototype(VM& vm, JSDOMGlobalObject* globalObject); - static JSObject* createConstructor(VM& vm, JSGlobalObject* globalObject, JSValue prototype); - - ~JSServerWebSocket(); - - void* wrapped() const { return m_ctx; } - - void detach() - { - m_ctx = nullptr; - } - - static void analyzeHeap(JSCell*, JSC::HeapAnalyzer&); - static ptrdiff_t offsetOfWrapped() { return OBJECT_OFFSETOF(JSServerWebSocket, m_ctx); } - - void* m_ctx { nullptr }; - - - JSServerWebSocket(JSC::VM& vm, JSC::Structure* structure, void* sinkPtr) - : Base(vm, structure) - { - m_ctx = sinkPtr; - - } - - void finishCreation(JSC::VM&); + static void analyzeHeap(JSCell*, JSC::HeapAnalyzer&); + static ptrdiff_t offsetOfWrapped() { return OBJECT_OFFSETOF(JSTLSSocket, m_ctx); } - + void* m_ctx { nullptr }; - DECLARE_VISIT_CHILDREN; + JSTLSSocket(JSC::VM& vm, JSC::Structure* structure, void* sinkPtr) + : Base(vm, structure) + { + m_ctx = sinkPtr; + m_weakThis = JSC::Weak<JSTLSSocket>(this, getOwner()); + } - mutable JSC::WriteBarrier<JSC::Unknown> m_data; -mutable JSC::WriteBarrier<JSC::Unknown> m_remoteAddress; - };class JSExpect final : public JSC::JSDestructibleObject { - public: - using Base = JSC::JSDestructibleObject; - static JSExpect* create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure, void* ctx); - - DECLARE_EXPORT_INFO; - template<typename, JSC::SubspaceAccess mode> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) - { - if constexpr (mode == JSC::SubspaceAccess::Concurrently) - return nullptr; - return WebCore::subspaceForImpl<JSExpect, WebCore::UseCustomHeapCellType::No>( - vm, - [](auto& spaces) { return spaces.m_clientSubspaceForExpect.get(); }, - [](auto& spaces, auto&& space) { spaces.m_clientSubspaceForExpect = WTFMove(space); }, - [](auto& spaces) { return spaces.m_subspaceForExpect.get(); }, - [](auto& spaces, auto&& space) { spaces.m_subspaceForExpect = WTFMove(space); }); - } - - static void destroy(JSC::JSCell*); - static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) - { - return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(static_cast<JSC::JSType>(0b11101110), StructureFlags), info()); - } - - static JSObject* createPrototype(VM& vm, JSDOMGlobalObject* globalObject); - static JSObject* createConstructor(VM& vm, JSGlobalObject* globalObject, JSValue prototype); - - ~JSExpect(); - - void* wrapped() const { return m_ctx; } - - void detach() - { - m_ctx = nullptr; - } - - static void analyzeHeap(JSCell*, JSC::HeapAnalyzer&); - static ptrdiff_t offsetOfWrapped() { return OBJECT_OFFSETOF(JSExpect, m_ctx); } - - void* m_ctx { nullptr }; - - - JSExpect(JSC::VM& vm, JSC::Structure* structure, void* sinkPtr) - : Base(vm, structure) - { - m_ctx = sinkPtr; - - } - - void finishCreation(JSC::VM&); + void finishCreation(JSC::VM&); - + JSC::Weak<JSTLSSocket> m_weakThis; - DECLARE_VISIT_CHILDREN; + static bool hasPendingActivity(void* ctx); - mutable JSC::WriteBarrier<JSC::Unknown> m_capturedValue; -mutable JSC::WriteBarrier<JSC::Unknown> m_resultValue; - };class JSTextDecoder final : public JSC::JSDestructibleObject { + class Owner final : public JSC::WeakHandleOwner { public: - using Base = JSC::JSDestructibleObject; - static JSTextDecoder* create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure, void* ctx); - - DECLARE_EXPORT_INFO; - template<typename, JSC::SubspaceAccess mode> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) - { - if constexpr (mode == JSC::SubspaceAccess::Concurrently) - return nullptr; - return WebCore::subspaceForImpl<JSTextDecoder, WebCore::UseCustomHeapCellType::No>( - vm, - [](auto& spaces) { return spaces.m_clientSubspaceForTextDecoder.get(); }, - [](auto& spaces, auto&& space) { spaces.m_clientSubspaceForTextDecoder = WTFMove(space); }, - [](auto& spaces) { return spaces.m_subspaceForTextDecoder.get(); }, - [](auto& spaces, auto&& space) { spaces.m_subspaceForTextDecoder = WTFMove(space); }); - } - - static void destroy(JSC::JSCell*); - static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) - { - return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(static_cast<JSC::JSType>(0b11101110), StructureFlags), info()); - } - - static JSObject* createPrototype(VM& vm, JSDOMGlobalObject* globalObject); - static JSObject* createConstructor(VM& vm, JSGlobalObject* globalObject, JSValue prototype); - - ~JSTextDecoder(); - - void* wrapped() const { return m_ctx; } - - void detach() - { - m_ctx = nullptr; - } - - static void analyzeHeap(JSCell*, JSC::HeapAnalyzer&); - static ptrdiff_t offsetOfWrapped() { return OBJECT_OFFSETOF(JSTextDecoder, m_ctx); } - - void* m_ctx { nullptr }; - - - JSTextDecoder(JSC::VM& vm, JSC::Structure* structure, void* sinkPtr) - : Base(vm, structure) + bool isReachableFromOpaqueRoots(JSC::Handle<JSC::Unknown> handle, void* context, JSC::AbstractSlotVisitor& visitor, const char** reason) final { - m_ctx = sinkPtr; - - } - - void finishCreation(JSC::VM&); - - - - DECLARE_VISIT_CHILDREN; + auto* controller = JSC::jsCast<JSTLSSocket*>(handle.slot()->asCell()); + if (JSTLSSocket::hasPendingActivity(controller->wrapped())) { + if (UNLIKELY(reason)) + *reason = "has pending activity"; + return true; + } - mutable JSC::WriteBarrier<JSC::Unknown> m_encoding; - };class JSRequest final : public JSC::JSDestructibleObject { - public: - using Base = JSC::JSDestructibleObject; - static JSRequest* create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure, void* ctx); - - DECLARE_EXPORT_INFO; - template<typename, JSC::SubspaceAccess mode> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) - { - if constexpr (mode == JSC::SubspaceAccess::Concurrently) - return nullptr; - return WebCore::subspaceForImpl<JSRequest, WebCore::UseCustomHeapCellType::No>( - vm, - [](auto& spaces) { return spaces.m_clientSubspaceForRequest.get(); }, - [](auto& spaces, auto&& space) { spaces.m_clientSubspaceForRequest = WTFMove(space); }, - [](auto& spaces) { return spaces.m_subspaceForRequest.get(); }, - [](auto& spaces, auto&& space) { spaces.m_subspaceForRequest = WTFMove(space); }); + return visitor.containsOpaqueRoot(context); } - - static void destroy(JSC::JSCell*); - static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) - { - return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(static_cast<JSC::JSType>(0b11101110), StructureFlags), info()); - } - - static JSObject* createPrototype(VM& vm, JSDOMGlobalObject* globalObject); - static JSObject* createConstructor(VM& vm, JSGlobalObject* globalObject, JSValue prototype); - - ~JSRequest(); - - void* wrapped() const { return m_ctx; } - - void detach() - { - m_ctx = nullptr; - } - - static void analyzeHeap(JSCell*, JSC::HeapAnalyzer&); - static ptrdiff_t offsetOfWrapped() { return OBJECT_OFFSETOF(JSRequest, m_ctx); } - - void* m_ctx { nullptr }; - - - JSRequest(JSC::VM& vm, JSC::Structure* structure, void* sinkPtr) - : Base(vm, structure) - { - m_ctx = sinkPtr; - - } - - void finishCreation(JSC::VM&); - - + void finalize(JSC::Handle<JSC::Unknown>, void* context) final {} + }; - DECLARE_VISIT_CHILDREN; + static JSC::WeakHandleOwner* getOwner() + { + static NeverDestroyed<Owner> m_owner; + return &m_owner.get(); + } + + DECLARE_VISIT_CHILDREN; + template<typename Visitor> void visitAdditionalChildren(Visitor&); + DECLARE_VISIT_OUTPUT_CONSTRAINTS; + + mutable JSC::WriteBarrier<JSC::Unknown> m_data; + mutable JSC::WriteBarrier<JSC::Unknown> m_remoteAddress; +}; + +class JSListener final : public JSC::JSDestructibleObject { +public: + using Base = JSC::JSDestructibleObject; + static JSListener* create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure, void* ctx); + + DECLARE_EXPORT_INFO; + template<typename, JSC::SubspaceAccess mode> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) + { + if constexpr (mode == JSC::SubspaceAccess::Concurrently) + return nullptr; + return WebCore::subspaceForImpl<JSListener, WebCore::UseCustomHeapCellType::No>( + vm, + [](auto& spaces) { return spaces.m_clientSubspaceForListener.get(); }, + [](auto& spaces, auto&& space) { spaces.m_clientSubspaceForListener = WTFMove(space); }, + [](auto& spaces) { return spaces.m_subspaceForListener.get(); }, + [](auto& spaces, auto&& space) { spaces.m_subspaceForListener = WTFMove(space); }); + } + + static void destroy(JSC::JSCell*); + static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) + { + return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(static_cast<JSC::JSType>(0b11101110), StructureFlags), info()); + } + + static JSObject* createPrototype(VM& vm, JSDOMGlobalObject* globalObject); + ; + + ~JSListener(); + + void* wrapped() const { return m_ctx; } + + void detach() + { + m_ctx = nullptr; + } + + static void analyzeHeap(JSCell*, JSC::HeapAnalyzer&); + static ptrdiff_t offsetOfWrapped() { return OBJECT_OFFSETOF(JSListener, m_ctx); } + + void* m_ctx { nullptr }; + + JSListener(JSC::VM& vm, JSC::Structure* structure, void* sinkPtr) + : Base(vm, structure) + { + m_ctx = sinkPtr; + } + + void finishCreation(JSC::VM&); + + DECLARE_VISIT_CHILDREN; + template<typename Visitor> void visitAdditionalChildren(Visitor&); + DECLARE_VISIT_OUTPUT_CONSTRAINTS; + + mutable JSC::WriteBarrier<JSC::Unknown> m_hostname; + mutable JSC::WriteBarrier<JSC::Unknown> m_unix; +}; + +class JSSubprocess final : public JSC::JSDestructibleObject { +public: + using Base = JSC::JSDestructibleObject; + static JSSubprocess* create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure, void* ctx); + + DECLARE_EXPORT_INFO; + template<typename, JSC::SubspaceAccess mode> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) + { + if constexpr (mode == JSC::SubspaceAccess::Concurrently) + return nullptr; + return WebCore::subspaceForImpl<JSSubprocess, WebCore::UseCustomHeapCellType::No>( + vm, + [](auto& spaces) { return spaces.m_clientSubspaceForSubprocess.get(); }, + [](auto& spaces, auto&& space) { spaces.m_clientSubspaceForSubprocess = WTFMove(space); }, + [](auto& spaces) { return spaces.m_subspaceForSubprocess.get(); }, + [](auto& spaces, auto&& space) { spaces.m_subspaceForSubprocess = WTFMove(space); }); + } + + static void destroy(JSC::JSCell*); + static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) + { + return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(static_cast<JSC::JSType>(0b11101110), StructureFlags), info()); + } + + static JSObject* createPrototype(VM& vm, JSDOMGlobalObject* globalObject); + ; + + ~JSSubprocess(); + + void* wrapped() const { return m_ctx; } + + void detach() + { + m_ctx = nullptr; + } + + static void analyzeHeap(JSCell*, JSC::HeapAnalyzer&); + static ptrdiff_t offsetOfWrapped() { return OBJECT_OFFSETOF(JSSubprocess, m_ctx); } + + void* m_ctx { nullptr }; + + JSSubprocess(JSC::VM& vm, JSC::Structure* structure, void* sinkPtr) + : Base(vm, structure) + { + m_ctx = sinkPtr; + m_weakThis = JSC::Weak<JSSubprocess>(this, getOwner()); + } + + void finishCreation(JSC::VM&); + + JSC::Weak<JSSubprocess> m_weakThis; + + static bool hasPendingActivity(void* ctx); - mutable JSC::WriteBarrier<JSC::Unknown> m_body; -mutable JSC::WriteBarrier<JSC::Unknown> m_headers; -mutable JSC::WriteBarrier<JSC::Unknown> m_url; - };class JSResponse final : public JSC::JSDestructibleObject { + class Owner final : public JSC::WeakHandleOwner { public: - using Base = JSC::JSDestructibleObject; - static JSResponse* create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure, void* ctx); - - DECLARE_EXPORT_INFO; - template<typename, JSC::SubspaceAccess mode> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) + bool isReachableFromOpaqueRoots(JSC::Handle<JSC::Unknown> handle, void* context, JSC::AbstractSlotVisitor& visitor, const char** reason) final { - if constexpr (mode == JSC::SubspaceAccess::Concurrently) - return nullptr; - return WebCore::subspaceForImpl<JSResponse, WebCore::UseCustomHeapCellType::No>( - vm, - [](auto& spaces) { return spaces.m_clientSubspaceForResponse.get(); }, - [](auto& spaces, auto&& space) { spaces.m_clientSubspaceForResponse = WTFMove(space); }, - [](auto& spaces) { return spaces.m_subspaceForResponse.get(); }, - [](auto& spaces, auto&& space) { spaces.m_subspaceForResponse = WTFMove(space); }); - } - - static void destroy(JSC::JSCell*); - static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) - { - return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(static_cast<JSC::JSType>(0b11101110), StructureFlags), info()); - } - - static JSObject* createPrototype(VM& vm, JSDOMGlobalObject* globalObject); - static JSObject* createConstructor(VM& vm, JSGlobalObject* globalObject, JSValue prototype); - - ~JSResponse(); - - void* wrapped() const { return m_ctx; } - - void detach() - { - m_ctx = nullptr; - } - - static void analyzeHeap(JSCell*, JSC::HeapAnalyzer&); - static ptrdiff_t offsetOfWrapped() { return OBJECT_OFFSETOF(JSResponse, m_ctx); } - - void* m_ctx { nullptr }; - - - JSResponse(JSC::VM& vm, JSC::Structure* structure, void* sinkPtr) - : Base(vm, structure) - { - m_ctx = sinkPtr; - - } - - void finishCreation(JSC::VM&); - - - - DECLARE_VISIT_CHILDREN; + auto* controller = JSC::jsCast<JSSubprocess*>(handle.slot()->asCell()); + if (JSSubprocess::hasPendingActivity(controller->wrapped())) { + if (UNLIKELY(reason)) + *reason = "has pending activity"; + return true; + } - mutable JSC::WriteBarrier<JSC::Unknown> m_body; -mutable JSC::WriteBarrier<JSC::Unknown> m_headers; -mutable JSC::WriteBarrier<JSC::Unknown> m_statusText; -mutable JSC::WriteBarrier<JSC::Unknown> m_url; - };class JSBlob final : public JSC::JSDestructibleObject { - public: - using Base = JSC::JSDestructibleObject; - static JSBlob* create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure, void* ctx); - - DECLARE_EXPORT_INFO; - template<typename, JSC::SubspaceAccess mode> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) - { - if constexpr (mode == JSC::SubspaceAccess::Concurrently) - return nullptr; - return WebCore::subspaceForImpl<JSBlob, WebCore::UseCustomHeapCellType::No>( - vm, - [](auto& spaces) { return spaces.m_clientSubspaceForBlob.get(); }, - [](auto& spaces, auto&& space) { spaces.m_clientSubspaceForBlob = WTFMove(space); }, - [](auto& spaces) { return spaces.m_subspaceForBlob.get(); }, - [](auto& spaces, auto&& space) { spaces.m_subspaceForBlob = WTFMove(space); }); - } - - static void destroy(JSC::JSCell*); - static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) - { - return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(static_cast<JSC::JSType>(0b11101110), StructureFlags), info()); + return visitor.containsOpaqueRoot(context); } - - static JSObject* createPrototype(VM& vm, JSDOMGlobalObject* globalObject); - static JSObject* createConstructor(VM& vm, JSGlobalObject* globalObject, JSValue prototype); - - ~JSBlob(); - - void* wrapped() const { return m_ctx; } - - void detach() - { - m_ctx = nullptr; - } - - static void analyzeHeap(JSCell*, JSC::HeapAnalyzer&); - static ptrdiff_t offsetOfWrapped() { return OBJECT_OFFSETOF(JSBlob, m_ctx); } - - void* m_ctx { nullptr }; - - - JSBlob(JSC::VM& vm, JSC::Structure* structure, void* sinkPtr) - : Base(vm, structure) - { - m_ctx = sinkPtr; - - } - - void finishCreation(JSC::VM&); - - + void finalize(JSC::Handle<JSC::Unknown>, void* context) final {} + }; - + static JSC::WeakHandleOwner* getOwner() + { + static NeverDestroyed<Owner> m_owner; + return &m_owner.get(); + } + + DECLARE_VISIT_CHILDREN; + template<typename Visitor> void visitAdditionalChildren(Visitor&); + DECLARE_VISIT_OUTPUT_CONSTRAINTS; + + mutable JSC::WriteBarrier<JSC::Unknown> m_stderr; + mutable JSC::WriteBarrier<JSC::Unknown> m_stdin; + mutable JSC::WriteBarrier<JSC::Unknown> m_stdout; +}; + +class JSSHA1 final : public JSC::JSDestructibleObject { +public: + using Base = JSC::JSDestructibleObject; + static JSSHA1* create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure, void* ctx); + + DECLARE_EXPORT_INFO; + template<typename, JSC::SubspaceAccess mode> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) + { + if constexpr (mode == JSC::SubspaceAccess::Concurrently) + return nullptr; + return WebCore::subspaceForImpl<JSSHA1, WebCore::UseCustomHeapCellType::No>( + vm, + [](auto& spaces) { return spaces.m_clientSubspaceForSHA1.get(); }, + [](auto& spaces, auto&& space) { spaces.m_clientSubspaceForSHA1 = WTFMove(space); }, + [](auto& spaces) { return spaces.m_subspaceForSHA1.get(); }, + [](auto& spaces, auto&& space) { spaces.m_subspaceForSHA1 = WTFMove(space); }); + } + + static void destroy(JSC::JSCell*); + static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) + { + return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(static_cast<JSC::JSType>(0b11101110), StructureFlags), info()); + } + + static JSObject* createPrototype(VM& vm, JSDOMGlobalObject* globalObject); + static JSObject* createConstructor(VM& vm, JSGlobalObject* globalObject, JSValue prototype); + + ~JSSHA1(); + + void* wrapped() const { return m_ctx; } + + void detach() + { + m_ctx = nullptr; + } + + static void analyzeHeap(JSCell*, JSC::HeapAnalyzer&); + static ptrdiff_t offsetOfWrapped() { return OBJECT_OFFSETOF(JSSHA1, m_ctx); } + + void* m_ctx { nullptr }; + + JSSHA1(JSC::VM& vm, JSC::Structure* structure, void* sinkPtr) + : Base(vm, structure) + { + m_ctx = sinkPtr; + } + + void finishCreation(JSC::VM&); +}; + +class JSMD5 final : public JSC::JSDestructibleObject { +public: + using Base = JSC::JSDestructibleObject; + static JSMD5* create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure, void* ctx); + + DECLARE_EXPORT_INFO; + template<typename, JSC::SubspaceAccess mode> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) + { + if constexpr (mode == JSC::SubspaceAccess::Concurrently) + return nullptr; + return WebCore::subspaceForImpl<JSMD5, WebCore::UseCustomHeapCellType::No>( + vm, + [](auto& spaces) { return spaces.m_clientSubspaceForMD5.get(); }, + [](auto& spaces, auto&& space) { spaces.m_clientSubspaceForMD5 = WTFMove(space); }, + [](auto& spaces) { return spaces.m_subspaceForMD5.get(); }, + [](auto& spaces, auto&& space) { spaces.m_subspaceForMD5 = WTFMove(space); }); + } + + static void destroy(JSC::JSCell*); + static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) + { + return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(static_cast<JSC::JSType>(0b11101110), StructureFlags), info()); + } + + static JSObject* createPrototype(VM& vm, JSDOMGlobalObject* globalObject); + static JSObject* createConstructor(VM& vm, JSGlobalObject* globalObject, JSValue prototype); + + ~JSMD5(); + + void* wrapped() const { return m_ctx; } + + void detach() + { + m_ctx = nullptr; + } + + static void analyzeHeap(JSCell*, JSC::HeapAnalyzer&); + static ptrdiff_t offsetOfWrapped() { return OBJECT_OFFSETOF(JSMD5, m_ctx); } + + void* m_ctx { nullptr }; + + JSMD5(JSC::VM& vm, JSC::Structure* structure, void* sinkPtr) + : Base(vm, structure) + { + m_ctx = sinkPtr; + } + + void finishCreation(JSC::VM&); +}; + +class JSMD4 final : public JSC::JSDestructibleObject { +public: + using Base = JSC::JSDestructibleObject; + static JSMD4* create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure, void* ctx); + + DECLARE_EXPORT_INFO; + template<typename, JSC::SubspaceAccess mode> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) + { + if constexpr (mode == JSC::SubspaceAccess::Concurrently) + return nullptr; + return WebCore::subspaceForImpl<JSMD4, WebCore::UseCustomHeapCellType::No>( + vm, + [](auto& spaces) { return spaces.m_clientSubspaceForMD4.get(); }, + [](auto& spaces, auto&& space) { spaces.m_clientSubspaceForMD4 = WTFMove(space); }, + [](auto& spaces) { return spaces.m_subspaceForMD4.get(); }, + [](auto& spaces, auto&& space) { spaces.m_subspaceForMD4 = WTFMove(space); }); + } + + static void destroy(JSC::JSCell*); + static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) + { + return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(static_cast<JSC::JSType>(0b11101110), StructureFlags), info()); + } + + static JSObject* createPrototype(VM& vm, JSDOMGlobalObject* globalObject); + static JSObject* createConstructor(VM& vm, JSGlobalObject* globalObject, JSValue prototype); + + ~JSMD4(); + + void* wrapped() const { return m_ctx; } + + void detach() + { + m_ctx = nullptr; + } + + static void analyzeHeap(JSCell*, JSC::HeapAnalyzer&); + static ptrdiff_t offsetOfWrapped() { return OBJECT_OFFSETOF(JSMD4, m_ctx); } + + void* m_ctx { nullptr }; + + JSMD4(JSC::VM& vm, JSC::Structure* structure, void* sinkPtr) + : Base(vm, structure) + { + m_ctx = sinkPtr; + } + + void finishCreation(JSC::VM&); +}; + +class JSSHA224 final : public JSC::JSDestructibleObject { +public: + using Base = JSC::JSDestructibleObject; + static JSSHA224* create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure, void* ctx); + + DECLARE_EXPORT_INFO; + template<typename, JSC::SubspaceAccess mode> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) + { + if constexpr (mode == JSC::SubspaceAccess::Concurrently) + return nullptr; + return WebCore::subspaceForImpl<JSSHA224, WebCore::UseCustomHeapCellType::No>( + vm, + [](auto& spaces) { return spaces.m_clientSubspaceForSHA224.get(); }, + [](auto& spaces, auto&& space) { spaces.m_clientSubspaceForSHA224 = WTFMove(space); }, + [](auto& spaces) { return spaces.m_subspaceForSHA224.get(); }, + [](auto& spaces, auto&& space) { spaces.m_subspaceForSHA224 = WTFMove(space); }); + } + + static void destroy(JSC::JSCell*); + static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) + { + return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(static_cast<JSC::JSType>(0b11101110), StructureFlags), info()); + } + + static JSObject* createPrototype(VM& vm, JSDOMGlobalObject* globalObject); + static JSObject* createConstructor(VM& vm, JSGlobalObject* globalObject, JSValue prototype); + + ~JSSHA224(); + + void* wrapped() const { return m_ctx; } + + void detach() + { + m_ctx = nullptr; + } + + static void analyzeHeap(JSCell*, JSC::HeapAnalyzer&); + static ptrdiff_t offsetOfWrapped() { return OBJECT_OFFSETOF(JSSHA224, m_ctx); } + + void* m_ctx { nullptr }; + + JSSHA224(JSC::VM& vm, JSC::Structure* structure, void* sinkPtr) + : Base(vm, structure) + { + m_ctx = sinkPtr; + } + + void finishCreation(JSC::VM&); +}; + +class JSSHA512 final : public JSC::JSDestructibleObject { +public: + using Base = JSC::JSDestructibleObject; + static JSSHA512* create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure, void* ctx); + + DECLARE_EXPORT_INFO; + template<typename, JSC::SubspaceAccess mode> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) + { + if constexpr (mode == JSC::SubspaceAccess::Concurrently) + return nullptr; + return WebCore::subspaceForImpl<JSSHA512, WebCore::UseCustomHeapCellType::No>( + vm, + [](auto& spaces) { return spaces.m_clientSubspaceForSHA512.get(); }, + [](auto& spaces, auto&& space) { spaces.m_clientSubspaceForSHA512 = WTFMove(space); }, + [](auto& spaces) { return spaces.m_subspaceForSHA512.get(); }, + [](auto& spaces, auto&& space) { spaces.m_subspaceForSHA512 = WTFMove(space); }); + } + + static void destroy(JSC::JSCell*); + static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) + { + return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(static_cast<JSC::JSType>(0b11101110), StructureFlags), info()); + } + + static JSObject* createPrototype(VM& vm, JSDOMGlobalObject* globalObject); + static JSObject* createConstructor(VM& vm, JSGlobalObject* globalObject, JSValue prototype); + + ~JSSHA512(); + + void* wrapped() const { return m_ctx; } + + void detach() + { + m_ctx = nullptr; + } + + static void analyzeHeap(JSCell*, JSC::HeapAnalyzer&); + static ptrdiff_t offsetOfWrapped() { return OBJECT_OFFSETOF(JSSHA512, m_ctx); } + + void* m_ctx { nullptr }; + + JSSHA512(JSC::VM& vm, JSC::Structure* structure, void* sinkPtr) + : Base(vm, structure) + { + m_ctx = sinkPtr; + } + + void finishCreation(JSC::VM&); +}; + +class JSSHA384 final : public JSC::JSDestructibleObject { +public: + using Base = JSC::JSDestructibleObject; + static JSSHA384* create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure, void* ctx); + + DECLARE_EXPORT_INFO; + template<typename, JSC::SubspaceAccess mode> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) + { + if constexpr (mode == JSC::SubspaceAccess::Concurrently) + return nullptr; + return WebCore::subspaceForImpl<JSSHA384, WebCore::UseCustomHeapCellType::No>( + vm, + [](auto& spaces) { return spaces.m_clientSubspaceForSHA384.get(); }, + [](auto& spaces, auto&& space) { spaces.m_clientSubspaceForSHA384 = WTFMove(space); }, + [](auto& spaces) { return spaces.m_subspaceForSHA384.get(); }, + [](auto& spaces, auto&& space) { spaces.m_subspaceForSHA384 = WTFMove(space); }); + } + + static void destroy(JSC::JSCell*); + static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) + { + return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(static_cast<JSC::JSType>(0b11101110), StructureFlags), info()); + } + + static JSObject* createPrototype(VM& vm, JSDOMGlobalObject* globalObject); + static JSObject* createConstructor(VM& vm, JSGlobalObject* globalObject, JSValue prototype); + + ~JSSHA384(); + + void* wrapped() const { return m_ctx; } + + void detach() + { + m_ctx = nullptr; + } + + static void analyzeHeap(JSCell*, JSC::HeapAnalyzer&); + static ptrdiff_t offsetOfWrapped() { return OBJECT_OFFSETOF(JSSHA384, m_ctx); } + + void* m_ctx { nullptr }; + + JSSHA384(JSC::VM& vm, JSC::Structure* structure, void* sinkPtr) + : Base(vm, structure) + { + m_ctx = sinkPtr; + } + + void finishCreation(JSC::VM&); +}; + +class JSSHA256 final : public JSC::JSDestructibleObject { +public: + using Base = JSC::JSDestructibleObject; + static JSSHA256* create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure, void* ctx); + + DECLARE_EXPORT_INFO; + template<typename, JSC::SubspaceAccess mode> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) + { + if constexpr (mode == JSC::SubspaceAccess::Concurrently) + return nullptr; + return WebCore::subspaceForImpl<JSSHA256, WebCore::UseCustomHeapCellType::No>( + vm, + [](auto& spaces) { return spaces.m_clientSubspaceForSHA256.get(); }, + [](auto& spaces, auto&& space) { spaces.m_clientSubspaceForSHA256 = WTFMove(space); }, + [](auto& spaces) { return spaces.m_subspaceForSHA256.get(); }, + [](auto& spaces, auto&& space) { spaces.m_subspaceForSHA256 = WTFMove(space); }); + } + + static void destroy(JSC::JSCell*); + static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) + { + return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(static_cast<JSC::JSType>(0b11101110), StructureFlags), info()); + } + + static JSObject* createPrototype(VM& vm, JSDOMGlobalObject* globalObject); + static JSObject* createConstructor(VM& vm, JSGlobalObject* globalObject, JSValue prototype); + + ~JSSHA256(); + + void* wrapped() const { return m_ctx; } + + void detach() + { + m_ctx = nullptr; + } + + static void analyzeHeap(JSCell*, JSC::HeapAnalyzer&); + static ptrdiff_t offsetOfWrapped() { return OBJECT_OFFSETOF(JSSHA256, m_ctx); } + + void* m_ctx { nullptr }; + + JSSHA256(JSC::VM& vm, JSC::Structure* structure, void* sinkPtr) + : Base(vm, structure) + { + m_ctx = sinkPtr; + } + + void finishCreation(JSC::VM&); +}; + +class JSSHA512_256 final : public JSC::JSDestructibleObject { +public: + using Base = JSC::JSDestructibleObject; + static JSSHA512_256* create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure, void* ctx); + + DECLARE_EXPORT_INFO; + template<typename, JSC::SubspaceAccess mode> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) + { + if constexpr (mode == JSC::SubspaceAccess::Concurrently) + return nullptr; + return WebCore::subspaceForImpl<JSSHA512_256, WebCore::UseCustomHeapCellType::No>( + vm, + [](auto& spaces) { return spaces.m_clientSubspaceForSHA512_256.get(); }, + [](auto& spaces, auto&& space) { spaces.m_clientSubspaceForSHA512_256 = WTFMove(space); }, + [](auto& spaces) { return spaces.m_subspaceForSHA512_256.get(); }, + [](auto& spaces, auto&& space) { spaces.m_subspaceForSHA512_256 = WTFMove(space); }); + } + + static void destroy(JSC::JSCell*); + static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) + { + return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(static_cast<JSC::JSType>(0b11101110), StructureFlags), info()); + } + + static JSObject* createPrototype(VM& vm, JSDOMGlobalObject* globalObject); + static JSObject* createConstructor(VM& vm, JSGlobalObject* globalObject, JSValue prototype); + + ~JSSHA512_256(); + + void* wrapped() const { return m_ctx; } + + void detach() + { + m_ctx = nullptr; + } + + static void analyzeHeap(JSCell*, JSC::HeapAnalyzer&); + static ptrdiff_t offsetOfWrapped() { return OBJECT_OFFSETOF(JSSHA512_256, m_ctx); } + + void* m_ctx { nullptr }; + + JSSHA512_256(JSC::VM& vm, JSC::Structure* structure, void* sinkPtr) + : Base(vm, structure) + { + m_ctx = sinkPtr; + } + + void finishCreation(JSC::VM&); +}; + +class JSServerWebSocket final : public JSC::JSDestructibleObject { +public: + using Base = JSC::JSDestructibleObject; + static JSServerWebSocket* create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure, void* ctx); + + DECLARE_EXPORT_INFO; + template<typename, JSC::SubspaceAccess mode> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) + { + if constexpr (mode == JSC::SubspaceAccess::Concurrently) + return nullptr; + return WebCore::subspaceForImpl<JSServerWebSocket, WebCore::UseCustomHeapCellType::No>( + vm, + [](auto& spaces) { return spaces.m_clientSubspaceForServerWebSocket.get(); }, + [](auto& spaces, auto&& space) { spaces.m_clientSubspaceForServerWebSocket = WTFMove(space); }, + [](auto& spaces) { return spaces.m_subspaceForServerWebSocket.get(); }, + [](auto& spaces, auto&& space) { spaces.m_subspaceForServerWebSocket = WTFMove(space); }); + } + + static void destroy(JSC::JSCell*); + static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) + { + return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(static_cast<JSC::JSType>(0b11101110), StructureFlags), info()); + } + + static JSObject* createPrototype(VM& vm, JSDOMGlobalObject* globalObject); + static JSObject* createConstructor(VM& vm, JSGlobalObject* globalObject, JSValue prototype); + + ~JSServerWebSocket(); + + void* wrapped() const { return m_ctx; } + + void detach() + { + m_ctx = nullptr; + } + + static void analyzeHeap(JSCell*, JSC::HeapAnalyzer&); + static ptrdiff_t offsetOfWrapped() { return OBJECT_OFFSETOF(JSServerWebSocket, m_ctx); } + + void* m_ctx { nullptr }; + + JSServerWebSocket(JSC::VM& vm, JSC::Structure* structure, void* sinkPtr) + : Base(vm, structure) + { + m_ctx = sinkPtr; + } + + void finishCreation(JSC::VM&); + + DECLARE_VISIT_CHILDREN; + template<typename Visitor> void visitAdditionalChildren(Visitor&); + DECLARE_VISIT_OUTPUT_CONSTRAINTS; + + mutable JSC::WriteBarrier<JSC::Unknown> m_data; + mutable JSC::WriteBarrier<JSC::Unknown> m_remoteAddress; +}; + +class JSFileSystemRouter final : public JSC::JSDestructibleObject { +public: + using Base = JSC::JSDestructibleObject; + static JSFileSystemRouter* create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure, void* ctx); + + DECLARE_EXPORT_INFO; + template<typename, JSC::SubspaceAccess mode> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) + { + if constexpr (mode == JSC::SubspaceAccess::Concurrently) + return nullptr; + return WebCore::subspaceForImpl<JSFileSystemRouter, WebCore::UseCustomHeapCellType::No>( + vm, + [](auto& spaces) { return spaces.m_clientSubspaceForFileSystemRouter.get(); }, + [](auto& spaces, auto&& space) { spaces.m_clientSubspaceForFileSystemRouter = WTFMove(space); }, + [](auto& spaces) { return spaces.m_subspaceForFileSystemRouter.get(); }, + [](auto& spaces, auto&& space) { spaces.m_subspaceForFileSystemRouter = WTFMove(space); }); + } + + static void destroy(JSC::JSCell*); + static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) + { + return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(static_cast<JSC::JSType>(0b11101110), StructureFlags), info()); + } + + static JSObject* createPrototype(VM& vm, JSDOMGlobalObject* globalObject); + static JSObject* createConstructor(VM& vm, JSGlobalObject* globalObject, JSValue prototype); + + ~JSFileSystemRouter(); + + void* wrapped() const { return m_ctx; } + + void detach() + { + m_ctx = nullptr; + } + + static void analyzeHeap(JSCell*, JSC::HeapAnalyzer&); + static ptrdiff_t offsetOfWrapped() { return OBJECT_OFFSETOF(JSFileSystemRouter, m_ctx); } + + void* m_ctx { nullptr }; + + JSFileSystemRouter(JSC::VM& vm, JSC::Structure* structure, void* sinkPtr) + : Base(vm, structure) + { + m_ctx = sinkPtr; + } + + void finishCreation(JSC::VM&); + + DECLARE_VISIT_CHILDREN; + template<typename Visitor> void visitAdditionalChildren(Visitor&); + DECLARE_VISIT_OUTPUT_CONSTRAINTS; + + mutable JSC::WriteBarrier<JSC::Unknown> m_origin; + mutable JSC::WriteBarrier<JSC::Unknown> m_routes; + mutable JSC::WriteBarrier<JSC::Unknown> m_style; +}; + +class JSMatchedRoute final : public JSC::JSDestructibleObject { +public: + using Base = JSC::JSDestructibleObject; + static JSMatchedRoute* create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure, void* ctx); + + DECLARE_EXPORT_INFO; + template<typename, JSC::SubspaceAccess mode> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) + { + if constexpr (mode == JSC::SubspaceAccess::Concurrently) + return nullptr; + return WebCore::subspaceForImpl<JSMatchedRoute, WebCore::UseCustomHeapCellType::No>( + vm, + [](auto& spaces) { return spaces.m_clientSubspaceForMatchedRoute.get(); }, + [](auto& spaces, auto&& space) { spaces.m_clientSubspaceForMatchedRoute = WTFMove(space); }, + [](auto& spaces) { return spaces.m_subspaceForMatchedRoute.get(); }, + [](auto& spaces, auto&& space) { spaces.m_subspaceForMatchedRoute = WTFMove(space); }); + } + + static void destroy(JSC::JSCell*); + static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) + { + return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(static_cast<JSC::JSType>(0b11101110), StructureFlags), info()); + } + + static JSObject* createPrototype(VM& vm, JSDOMGlobalObject* globalObject); + ; + + ~JSMatchedRoute(); + + void* wrapped() const { return m_ctx; } + + void detach() + { + m_ctx = nullptr; + } + + static void analyzeHeap(JSCell*, JSC::HeapAnalyzer&); + static ptrdiff_t offsetOfWrapped() { return OBJECT_OFFSETOF(JSMatchedRoute, m_ctx); } + + void* m_ctx { nullptr }; + + JSMatchedRoute(JSC::VM& vm, JSC::Structure* structure, void* sinkPtr) + : Base(vm, structure) + { + m_ctx = sinkPtr; + } + + void finishCreation(JSC::VM&); + + DECLARE_VISIT_CHILDREN; + template<typename Visitor> void visitAdditionalChildren(Visitor&); + DECLARE_VISIT_OUTPUT_CONSTRAINTS; + + mutable JSC::WriteBarrier<JSC::Unknown> m_filePath; + mutable JSC::WriteBarrier<JSC::Unknown> m_kind; + mutable JSC::WriteBarrier<JSC::Unknown> m_name; + mutable JSC::WriteBarrier<JSC::Unknown> m_params; + mutable JSC::WriteBarrier<JSC::Unknown> m_pathname; + mutable JSC::WriteBarrier<JSC::Unknown> m_query; + mutable JSC::WriteBarrier<JSC::Unknown> m_scriptSrc; +}; + +class JSExpect final : public JSC::JSDestructibleObject { +public: + using Base = JSC::JSDestructibleObject; + static JSExpect* create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure, void* ctx); + + DECLARE_EXPORT_INFO; + template<typename, JSC::SubspaceAccess mode> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) + { + if constexpr (mode == JSC::SubspaceAccess::Concurrently) + return nullptr; + return WebCore::subspaceForImpl<JSExpect, WebCore::UseCustomHeapCellType::No>( + vm, + [](auto& spaces) { return spaces.m_clientSubspaceForExpect.get(); }, + [](auto& spaces, auto&& space) { spaces.m_clientSubspaceForExpect = WTFMove(space); }, + [](auto& spaces) { return spaces.m_subspaceForExpect.get(); }, + [](auto& spaces, auto&& space) { spaces.m_subspaceForExpect = WTFMove(space); }); + } + + static void destroy(JSC::JSCell*); + static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) + { + return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(static_cast<JSC::JSType>(0b11101110), StructureFlags), info()); + } + + static JSObject* createPrototype(VM& vm, JSDOMGlobalObject* globalObject); + static JSObject* createConstructor(VM& vm, JSGlobalObject* globalObject, JSValue prototype); + + ~JSExpect(); + + void* wrapped() const { return m_ctx; } + + void detach() + { + m_ctx = nullptr; + } + + static void analyzeHeap(JSCell*, JSC::HeapAnalyzer&); + static ptrdiff_t offsetOfWrapped() { return OBJECT_OFFSETOF(JSExpect, m_ctx); } + + void* m_ctx { nullptr }; + + JSExpect(JSC::VM& vm, JSC::Structure* structure, void* sinkPtr) + : Base(vm, structure) + { + m_ctx = sinkPtr; + } + + void finishCreation(JSC::VM&); + + DECLARE_VISIT_CHILDREN; + template<typename Visitor> void visitAdditionalChildren(Visitor&); + DECLARE_VISIT_OUTPUT_CONSTRAINTS; + + mutable JSC::WriteBarrier<JSC::Unknown> m_capturedValue; + mutable JSC::WriteBarrier<JSC::Unknown> m_resultValue; +}; + +class JSTextDecoder final : public JSC::JSDestructibleObject { +public: + using Base = JSC::JSDestructibleObject; + static JSTextDecoder* create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure, void* ctx); + + DECLARE_EXPORT_INFO; + template<typename, JSC::SubspaceAccess mode> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) + { + if constexpr (mode == JSC::SubspaceAccess::Concurrently) + return nullptr; + return WebCore::subspaceForImpl<JSTextDecoder, WebCore::UseCustomHeapCellType::No>( + vm, + [](auto& spaces) { return spaces.m_clientSubspaceForTextDecoder.get(); }, + [](auto& spaces, auto&& space) { spaces.m_clientSubspaceForTextDecoder = WTFMove(space); }, + [](auto& spaces) { return spaces.m_subspaceForTextDecoder.get(); }, + [](auto& spaces, auto&& space) { spaces.m_subspaceForTextDecoder = WTFMove(space); }); + } + + static void destroy(JSC::JSCell*); + static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) + { + return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(static_cast<JSC::JSType>(0b11101110), StructureFlags), info()); + } + + static JSObject* createPrototype(VM& vm, JSDOMGlobalObject* globalObject); + static JSObject* createConstructor(VM& vm, JSGlobalObject* globalObject, JSValue prototype); + + ~JSTextDecoder(); + + void* wrapped() const { return m_ctx; } + + void detach() + { + m_ctx = nullptr; + } + + static void analyzeHeap(JSCell*, JSC::HeapAnalyzer&); + static ptrdiff_t offsetOfWrapped() { return OBJECT_OFFSETOF(JSTextDecoder, m_ctx); } + + void* m_ctx { nullptr }; + + JSTextDecoder(JSC::VM& vm, JSC::Structure* structure, void* sinkPtr) + : Base(vm, structure) + { + m_ctx = sinkPtr; + } + + void finishCreation(JSC::VM&); + + DECLARE_VISIT_CHILDREN; + template<typename Visitor> void visitAdditionalChildren(Visitor&); + DECLARE_VISIT_OUTPUT_CONSTRAINTS; + + mutable JSC::WriteBarrier<JSC::Unknown> m_encoding; +}; + +class JSRequest final : public JSC::JSDestructibleObject { +public: + using Base = JSC::JSDestructibleObject; + static JSRequest* create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure, void* ctx); + + DECLARE_EXPORT_INFO; + template<typename, JSC::SubspaceAccess mode> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) + { + if constexpr (mode == JSC::SubspaceAccess::Concurrently) + return nullptr; + return WebCore::subspaceForImpl<JSRequest, WebCore::UseCustomHeapCellType::No>( + vm, + [](auto& spaces) { return spaces.m_clientSubspaceForRequest.get(); }, + [](auto& spaces, auto&& space) { spaces.m_clientSubspaceForRequest = WTFMove(space); }, + [](auto& spaces) { return spaces.m_subspaceForRequest.get(); }, + [](auto& spaces, auto&& space) { spaces.m_subspaceForRequest = WTFMove(space); }); + } + + static void destroy(JSC::JSCell*); + static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) + { + return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(static_cast<JSC::JSType>(0b11101110), StructureFlags), info()); + } + + static JSObject* createPrototype(VM& vm, JSDOMGlobalObject* globalObject); + static JSObject* createConstructor(VM& vm, JSGlobalObject* globalObject, JSValue prototype); + + ~JSRequest(); + + void* wrapped() const { return m_ctx; } + + void detach() + { + m_ctx = nullptr; + } + + static void analyzeHeap(JSCell*, JSC::HeapAnalyzer&); + static ptrdiff_t offsetOfWrapped() { return OBJECT_OFFSETOF(JSRequest, m_ctx); } + + void* m_ctx { nullptr }; + + JSRequest(JSC::VM& vm, JSC::Structure* structure, void* sinkPtr) + : Base(vm, structure) + { + m_ctx = sinkPtr; + } + + void finishCreation(JSC::VM&); + + DECLARE_VISIT_CHILDREN; + template<typename Visitor> void visitAdditionalChildren(Visitor&); + DECLARE_VISIT_OUTPUT_CONSTRAINTS; + + mutable JSC::WriteBarrier<JSC::Unknown> m_body; + mutable JSC::WriteBarrier<JSC::Unknown> m_headers; + mutable JSC::WriteBarrier<JSC::Unknown> m_url; +}; + +class JSResponse final : public JSC::JSDestructibleObject { +public: + using Base = JSC::JSDestructibleObject; + static JSResponse* create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure, void* ctx); + + DECLARE_EXPORT_INFO; + template<typename, JSC::SubspaceAccess mode> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) + { + if constexpr (mode == JSC::SubspaceAccess::Concurrently) + return nullptr; + return WebCore::subspaceForImpl<JSResponse, WebCore::UseCustomHeapCellType::No>( + vm, + [](auto& spaces) { return spaces.m_clientSubspaceForResponse.get(); }, + [](auto& spaces, auto&& space) { spaces.m_clientSubspaceForResponse = WTFMove(space); }, + [](auto& spaces) { return spaces.m_subspaceForResponse.get(); }, + [](auto& spaces, auto&& space) { spaces.m_subspaceForResponse = WTFMove(space); }); + } + + static void destroy(JSC::JSCell*); + static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) + { + return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(static_cast<JSC::JSType>(0b11101110), StructureFlags), info()); + } + + static JSObject* createPrototype(VM& vm, JSDOMGlobalObject* globalObject); + static JSObject* createConstructor(VM& vm, JSGlobalObject* globalObject, JSValue prototype); + + ~JSResponse(); + + void* wrapped() const { return m_ctx; } + + void detach() + { + m_ctx = nullptr; + } + + static void analyzeHeap(JSCell*, JSC::HeapAnalyzer&); + static ptrdiff_t offsetOfWrapped() { return OBJECT_OFFSETOF(JSResponse, m_ctx); } + + void* m_ctx { nullptr }; + + JSResponse(JSC::VM& vm, JSC::Structure* structure, void* sinkPtr) + : Base(vm, structure) + { + m_ctx = sinkPtr; + } + + void finishCreation(JSC::VM&); + + DECLARE_VISIT_CHILDREN; + template<typename Visitor> void visitAdditionalChildren(Visitor&); + DECLARE_VISIT_OUTPUT_CONSTRAINTS; + + mutable JSC::WriteBarrier<JSC::Unknown> m_body; + mutable JSC::WriteBarrier<JSC::Unknown> m_headers; + mutable JSC::WriteBarrier<JSC::Unknown> m_statusText; + mutable JSC::WriteBarrier<JSC::Unknown> m_url; +}; + +class JSBlob final : public JSC::JSDestructibleObject { +public: + using Base = JSC::JSDestructibleObject; + static JSBlob* create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure, void* ctx); + + DECLARE_EXPORT_INFO; + template<typename, JSC::SubspaceAccess mode> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) + { + if constexpr (mode == JSC::SubspaceAccess::Concurrently) + return nullptr; + return WebCore::subspaceForImpl<JSBlob, WebCore::UseCustomHeapCellType::No>( + vm, + [](auto& spaces) { return spaces.m_clientSubspaceForBlob.get(); }, + [](auto& spaces, auto&& space) { spaces.m_clientSubspaceForBlob = WTFMove(space); }, + [](auto& spaces) { return spaces.m_subspaceForBlob.get(); }, + [](auto& spaces, auto&& space) { spaces.m_subspaceForBlob = WTFMove(space); }); + } + + static void destroy(JSC::JSCell*); + static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) + { + return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(static_cast<JSC::JSType>(0b11101110), StructureFlags), info()); + } + + static JSObject* createPrototype(VM& vm, JSDOMGlobalObject* globalObject); + static JSObject* createConstructor(VM& vm, JSGlobalObject* globalObject, JSValue prototype); + + ~JSBlob(); + + void* wrapped() const { return m_ctx; } + + void detach() + { + m_ctx = nullptr; + } + + static void analyzeHeap(JSCell*, JSC::HeapAnalyzer&); + static ptrdiff_t offsetOfWrapped() { return OBJECT_OFFSETOF(JSBlob, m_ctx); } + + void* m_ctx { nullptr }; + + JSBlob(JSC::VM& vm, JSC::Structure* structure, void* sinkPtr) + : Base(vm, structure) + { + m_ctx = sinkPtr; + } + + void finishCreation(JSC::VM&); +}; - - }; } - diff --git a/src/bun.js/bindings/ZigGlobalObject.cpp b/src/bun.js/bindings/ZigGlobalObject.cpp index 42b5d07f4..5d7c49292 100644 --- a/src/bun.js/bindings/ZigGlobalObject.cpp +++ b/src/bun.js/bindings/ZigGlobalObject.cpp @@ -435,6 +435,11 @@ GlobalObject::GlobalObject(JSC::VM& vm, JSC::Structure* structure) GlobalObject::~GlobalObject() { + if (napiInstanceDataFinalizer) { + napi_finalize finalizer = reinterpret_cast<napi_finalize>(napiInstanceDataFinalizer); + finalizer(toNapi(this), napiInstanceData, napiInstanceDataFinalizerHint); + } + delete crypto; scriptExecutionContext()->removeFromContextsMap(); } diff --git a/src/bun.js/bindings/ZigGlobalObject.h b/src/bun.js/bindings/ZigGlobalObject.h index 142065e35..1aee587cf 100644 --- a/src/bun.js/bindings/ZigGlobalObject.h +++ b/src/bun.js/bindings/ZigGlobalObject.h @@ -423,6 +423,13 @@ public: // To do that, we count the number of times we register a module. int napiModuleRegisterCallCount = 0; + // NAPI instance data + // This is not a correct implementation + // Addon modules can override each other's data + void* napiInstanceData = nullptr; + void* napiInstanceDataFinalizer = nullptr; + void* napiInstanceDataFinalizerHint = nullptr; + #include "ZigGeneratedClasses+lazyStructureHeader.h" private: diff --git a/src/bun.js/bindings/bindings.cpp b/src/bun.js/bindings/bindings.cpp index 25a1b3fc7..977f1ca26 100644 --- a/src/bun.js/bindings/bindings.cpp +++ b/src/bun.js/bindings/bindings.cpp @@ -456,7 +456,7 @@ JSC__JSValue JSC__JSValue__createEmptyObject(JSC__JSGlobalObject* globalObject, JSC::constructEmptyObject(globalObject, globalObject->objectPrototype(), initialCapacity)); } -uint32_t JSC__JSValue__getLengthOfArray(JSC__JSValue value, JSC__JSGlobalObject* globalObject) +uint64_t JSC__JSValue__getLengthOfArray(JSC__JSValue value, JSC__JSGlobalObject* globalObject) { JSC::JSValue jsValue = JSC::JSValue::decode(value); JSC::JSObject* object = jsValue.toObject(globalObject); @@ -467,7 +467,7 @@ void JSC__JSObject__putRecord(JSC__JSObject* object, JSC__JSGlobalObject* global ZigString* values, size_t valuesLen) { auto scope = DECLARE_THROW_SCOPE(global->vm()); - auto ident = Zig::toIdentifier(*key, global); + auto ident = Identifier::fromString(global->vm(), Zig::toStringCopy(*key)); JSC::PropertyDescriptor descriptor; descriptor.setEnumerable(1); @@ -475,7 +475,7 @@ void JSC__JSObject__putRecord(JSC__JSObject* object, JSC__JSGlobalObject* global descriptor.setWritable(1); if (valuesLen == 1) { - descriptor.setValue(JSC::jsString(global->vm(), Zig::toString(values[0]))); + descriptor.setValue(JSC::jsString(global->vm(), Zig::toStringCopy(values[0]))); } else { JSC::JSArray* array = nullptr; @@ -488,7 +488,7 @@ void JSC__JSObject__putRecord(JSC__JSObject* object, JSC__JSGlobalObject* global for (size_t i = 0; i < valuesLen; ++i) { array->initializeIndexWithoutBarrier( - initializationScope, i, JSC::jsString(global->vm(), Zig::toString(values[i]))); + initializationScope, i, JSC::jsString(global->vm(), Zig::toStringCopy(values[i]))); } } } @@ -1431,10 +1431,28 @@ JSC__JSPromise* JSC__JSPromise__resolvedPromise(JSC__JSGlobalObject* arg0, JSC__ return promise; } -JSC__JSValue JSC__JSPromise__result(const JSC__JSPromise* arg0, JSC__VM* arg1) +JSC__JSValue JSC__JSPromise__result(JSC__JSPromise* promise, JSC__VM* arg1) { - return JSC::JSValue::encode(arg0->result(reinterpret_cast<JSC::VM&>(arg1))); + auto& vm = *arg1; + + // if the promise is rejected we automatically mark it as handled so it + // doesn't end up in the promise rejection tracker + switch (promise->status(vm)) { + case JSC::JSPromise::Status::Rejected: { + uint32_t flags = promise->internalField(JSC::JSPromise::Field::Flags).get().asUInt32(); + if (!(flags & JSC::JSPromise::isFirstResolvingFunctionCalledFlag)) { + promise->internalField(JSC::JSPromise::Field::Flags).set(vm, promise, jsNumber(flags | JSC::JSPromise::isHandledFlag)); + } + } + // fallthrough intended + case JSC::JSPromise::Status::Fulfilled: { + return JSValue::encode(promise->result(vm)); + } + default: + return JSValue::encode(JSValue {}); + } } + uint32_t JSC__JSPromise__status(const JSC__JSPromise* arg0, JSC__VM* arg1) { switch (arg0->status(reinterpret_cast<JSC::VM&>(arg1))) { @@ -3161,3 +3179,8 @@ JSC__JSValue JSC__JSValue__fastGet_(JSC__JSValue JSValue0, JSC__JSGlobalObject* return JSValue::encode( value.getObject()->getIfPropertyExists(globalObject, builtinNameMap(globalObject, arg2))); } + +bool JSC__JSValue__toBooleanSlow(JSC__JSValue JSValue0, JSC__JSGlobalObject* globalObject) +{ + return JSValue::decode(JSValue0).toBoolean(globalObject); +} diff --git a/src/bun.js/bindings/bindings.zig b/src/bun.js/bindings/bindings.zig index e9e4d5cbf..b769625ec 100644 --- a/src/bun.js/bindings/bindings.zig +++ b/src/bun.js/bindings/bindings.zig @@ -200,8 +200,8 @@ pub const ZigString = extern struct { pub const Slice = struct { allocator: NullableAllocator = .{}, - ptr: [*]const u8, - len: u32, + ptr: [*]const u8 = undefined, + len: u32 = 0, pub fn fromUTF8NeverFree(input: []const u8) Slice { return .{ @@ -235,6 +235,11 @@ pub const ZigString = extern struct { return Slice{ .allocator = NullableAllocator.init(allocator), .ptr = duped.ptr, .len = this.len }; } + pub fn cloneWithTrailingSlash(this: Slice, allocator: std.mem.Allocator) !Slice { + var buf = try strings.cloneNormalizingSeparators(allocator, this.slice()); + return Slice{ .allocator = NullableAllocator.init(allocator), .ptr = buf.ptr, .len = @truncate(u32, buf.len) }; + } + pub fn cloneZ(this: Slice, allocator: std.mem.Allocator) !Slice { if (this.isAllocated() or this.len == 0) { return this; @@ -1472,6 +1477,30 @@ pub const JSPromise = extern struct { Rejected = 2, }; + pub const Strong = struct { + strong: JSC.Strong = .{}, + + pub fn init(globalThis: *JSC.JSGlobalObject) Strong { + return Strong{ + .strong = JSC.Strong.create(globalThis, JSC.JSPromise.create(globalThis).asValue(globalThis)), + }; + } + + pub fn get(this: *Strong) *JSC.JSPromise { + return this.strong.get().?.asPromise().?; + } + + pub fn value(this: *Strong) JSValue { + return this.strong.get().?; + } + + pub fn swap(this: *Strong) *JSC.JSPromise { + var prom = this.strong.swap().asPromise().?; + this.strong.deinit(); + return prom; + } + }; + pub fn wrap( globalObject: *JSGlobalObject, value: JSValue, @@ -1495,7 +1524,7 @@ pub const JSPromise = extern struct { pub fn status(this: *const JSPromise, vm: *VM) Status { return shim.cppFn("status", .{ this, vm }); } - pub fn result(this: *const JSPromise, vm: *VM) JSValue { + pub fn result(this: *JSPromise, vm: *VM) JSValue { return cppFn("result", .{ this, vm }); } pub fn isHandled(this: *const JSPromise, vm: *VM) bool { @@ -2368,7 +2397,7 @@ pub const JSArrayIterator = struct { return .{ .array = value, .global = global, - .len = value.getLengthOfArray(global), + .len = @truncate(u32, value.getLengthOfArray(global)), }; } @@ -2779,6 +2808,7 @@ pub const JSValue = enum(JSValueReprInt) { pub fn coerce(this: JSValue, comptime T: type, globalThis: *JSC.JSGlobalObject) T { return switch (T) { ZigString => this.getZigString(globalThis), + bool => this.toBooleanSlow(globalThis), i32 => { if (this.isInt32()) { return this.asInt32(); @@ -3463,6 +3493,10 @@ pub const JSValue = enum(JSValueReprInt) { return fromPtrAddress(@ptrToInt(addr)); } + pub fn toBooleanSlow(this: JSValue, global: *JSGlobalObject) bool { + return cppFn("toBooleanSlow", .{ this, global }); + } + pub fn toBoolean(this: JSValue) bool { if (isUndefinedOrNull(this)) { return false; @@ -3506,7 +3540,7 @@ pub const JSValue = enum(JSValueReprInt) { return @intCast(u32, @maximum(this.toInt32(), 0)); } - pub fn getLengthOfArray(this: JSValue, globalThis: *JSGlobalObject) u32 { + pub fn getLengthOfArray(this: JSValue, globalThis: *JSGlobalObject) u64 { return cppFn("getLengthOfArray", .{ this, globalThis, @@ -3577,7 +3611,7 @@ pub const JSValue = enum(JSValueReprInt) { return this.asNullableVoid().?; } - pub const Extern = [_][]const u8{ "coerceToInt32", "fastGet_", "getStaticProperty", "createUninitializedUint8Array", "fromInt64NoTruncate", "fromUInt64NoTruncate", "toUInt64NoTruncate", "asPromise", "toInt64", "_then", "put", "makeWithNameAndPrototype", "parseJSON", "symbolKeyFor", "symbolFor", "getSymbolDescription", "createInternalPromise", "asInternalPromise", "asArrayBuffer_", "fromEntries", "createTypeError", "createRangeError", "createObject2", "getIfPropertyExistsImpl", "jsType", "jsonStringify", "kind_", "isTerminationException", "isSameValue", "getLengthOfArray", "toZigString", "createStringArray", "createEmptyObject", "putRecord", "asPromise", "isClass", "getNameProperty", "getClassName", "getErrorsProperty", "toInt32", "toBoolean", "isInt32", "isIterable", "forEach", "isAggregateError", "toError", "toZigException", "isException", "toWTFString", "hasProperty", "getPropertyNames", "getDirect", "putDirect", "getIfExists", "asString", "asObject", "asNumber", "isError", "jsNull", "jsUndefined", "jsTDZValue", "jsBoolean", "jsDoubleNumber", "jsNumberFromDouble", "jsNumberFromChar", "jsNumberFromU16", "jsNumberFromInt64", "isBoolean", "isAnyInt", "isUInt32AsAnyInt", "isInt32AsAnyInt", "isNumber", "isString", "isBigInt", "isHeapBigInt", "isBigInt32", "isSymbol", "isPrimitive", "isGetterSetter", "isCustomGetterSetter", "isObject", "isCell", "asCell", "toString", "toStringOrNull", "toPropertyKey", "toPropertyKeyValue", "toObject", "toString", "getPrototype", "getPropertyByPropertyName", "eqlValue", "eqlCell", "isCallable" }; + pub const Extern = [_][]const u8{ "coerceToInt32", "fastGet_", "getStaticProperty", "createUninitializedUint8Array", "fromInt64NoTruncate", "fromUInt64NoTruncate", "toUInt64NoTruncate", "asPromise", "toInt64", "_then", "put", "makeWithNameAndPrototype", "parseJSON", "symbolKeyFor", "symbolFor", "getSymbolDescription", "createInternalPromise", "asInternalPromise", "asArrayBuffer_", "fromEntries", "createTypeError", "createRangeError", "createObject2", "getIfPropertyExistsImpl", "jsType", "jsonStringify", "kind_", "isTerminationException", "isSameValue", "getLengthOfArray", "toZigString", "createStringArray", "createEmptyObject", "putRecord", "asPromise", "isClass", "getNameProperty", "getClassName", "getErrorsProperty", "toInt32", "toBoolean", "isInt32", "isIterable", "forEach", "isAggregateError", "toError", "toZigException", "isException", "toWTFString", "hasProperty", "getPropertyNames", "getDirect", "putDirect", "getIfExists", "asString", "asObject", "asNumber", "isError", "jsNull", "jsUndefined", "jsTDZValue", "jsBoolean", "jsDoubleNumber", "jsNumberFromDouble", "jsNumberFromChar", "jsNumberFromU16", "jsNumberFromInt64", "isBoolean", "isAnyInt", "isUInt32AsAnyInt", "isInt32AsAnyInt", "isNumber", "isString", "isBigInt", "isHeapBigInt", "isBigInt32", "isSymbol", "isPrimitive", "isGetterSetter", "isCustomGetterSetter", "isObject", "isCell", "asCell", "toString", "toStringOrNull", "toPropertyKey", "toPropertyKeyValue", "toObject", "toString", "getPrototype", "getPropertyByPropertyName", "eqlValue", "eqlCell", "isCallable", "toBooleanSlow" }; }; extern "c" fn Microtask__run(*Microtask, *JSGlobalObject) void; diff --git a/src/bun.js/bindings/exports.zig b/src/bun.js/bindings/exports.zig index 1c0a393ce..acc1e136e 100644 --- a/src/bun.js/bindings/exports.zig +++ b/src/bun.js/bindings/exports.zig @@ -271,11 +271,12 @@ export fn ZigString__free(raw: [*]const u8, len: usize, allocator_: ?*anyopaque) } export fn ZigString__free_global(ptr: [*]const u8, len: usize) void { - // if (comptime Environment.allow_assert) { - // std.debug.assert(Mimalloc.mi_check_owned(ptr)); - // } + var untagged = @intToPtr(*anyopaque, @ptrToInt(ZigString.init(ptr[0..len]).slice().ptr)); + if (comptime Environment.allow_assert) { + std.debug.assert(Mimalloc.mi_is_in_heap_region(ptr)); + } // we must untag the string pointer - Mimalloc.mi_free(@intToPtr(*anyopaque, @ptrToInt(ZigString.init(ptr[0..len]).slice().ptr))); + Mimalloc.mi_free(untagged); } export fn Zig__getAPIGlobals(count: *usize) [*]JSC.C.JSClassRef { @@ -1766,7 +1767,7 @@ pub const ZigConsoleClient = struct { } }, .Array => { - const len = value.getLengthOfArray(this.globalThis); + const len = @truncate(u32, value.getLengthOfArray(this.globalThis)); if (len == 0) { writer.writeAll("[]"); return; diff --git a/src/bun.js/bindings/generated_classes.zig b/src/bun.js/bindings/generated_classes.zig index 83402278b..52e99fb82 100644 --- a/src/bun.js/bindings/generated_classes.zig +++ b/src/bun.js/bindings/generated_classes.zig @@ -66,13 +66,6 @@ pub const JSTCPSocket = struct { return result; } - /// Get the TCPSocket constructor value. - /// This loads lazily from the global object. - pub fn getConstructor(globalObject: *JSC.JSGlobalObject) JSC.JSValue { - JSC.markBinding(@src()); - return TCPSocket__getConstructor(globalObject); - } - /// Create a new instance of TCPSocket pub fn toJS(this: *TCPSocket, globalObject: *JSC.JSGlobalObject) JSC.JSValue { JSC.markBinding(@src()); @@ -105,10 +98,6 @@ pub const JSTCPSocket = struct { extern fn TCPSocket__dangerouslySetPtr(JSC.JSValue, ?*TCPSocket) bool; comptime { - if (@TypeOf(TCPSocket.constructor) != (fn (*JSC.JSGlobalObject, *JSC.CallFrame) callconv(.C) ?*TCPSocket)) { - @compileLog("TCPSocket.constructor is not a constructor"); - } - if (@TypeOf(TCPSocket.finalize) != (fn (*TCPSocket) callconv(.C) void)) { @compileLog("TCPSocket.finalize is not a finalizer"); } @@ -147,7 +136,6 @@ pub const JSTCPSocket = struct { if (@TypeOf(TCPSocket.write) != CallbackType) @compileLog("Expected TCPSocket.write to be a callback"); if (!JSC.is_bindgen) { - @export(TCPSocket.constructor, .{ .name = "TCPSocketClass__construct" }); @export(TCPSocket.end, .{ .name = "TCPSocketPrototype__end" }); @export(TCPSocket.finalize, .{ .name = "TCPSocketClass__finalize" }); @export(TCPSocket.flush, .{ .name = "TCPSocketPrototype__flush" }); @@ -156,6 +144,7 @@ pub const JSTCPSocket = struct { @export(TCPSocket.getLocalPort, .{ .name = "TCPSocketPrototype__getLocalPort" }); @export(TCPSocket.getReadyState, .{ .name = "TCPSocketPrototype__getReadyState" }); @export(TCPSocket.getRemoteAddress, .{ .name = "TCPSocketPrototype__getRemoteAddress" }); + @export(TCPSocket.hasPendingActivity, .{ .name = "TCPSocket__hasPendingActivity" }); @export(TCPSocket.ref, .{ .name = "TCPSocketPrototype__ref" }); @export(TCPSocket.reload, .{ .name = "TCPSocketPrototype__reload" }); @export(TCPSocket.setData, .{ .name = "TCPSocketPrototype__setData" }); @@ -225,13 +214,6 @@ pub const JSTLSSocket = struct { return result; } - /// Get the TLSSocket constructor value. - /// This loads lazily from the global object. - pub fn getConstructor(globalObject: *JSC.JSGlobalObject) JSC.JSValue { - JSC.markBinding(@src()); - return TLSSocket__getConstructor(globalObject); - } - /// Create a new instance of TLSSocket pub fn toJS(this: *TLSSocket, globalObject: *JSC.JSGlobalObject) JSC.JSValue { JSC.markBinding(@src()); @@ -264,10 +246,6 @@ pub const JSTLSSocket = struct { extern fn TLSSocket__dangerouslySetPtr(JSC.JSValue, ?*TLSSocket) bool; comptime { - if (@TypeOf(TLSSocket.constructor) != (fn (*JSC.JSGlobalObject, *JSC.CallFrame) callconv(.C) ?*TLSSocket)) { - @compileLog("TLSSocket.constructor is not a constructor"); - } - if (@TypeOf(TLSSocket.finalize) != (fn (*TLSSocket) callconv(.C) void)) { @compileLog("TLSSocket.finalize is not a finalizer"); } @@ -306,7 +284,6 @@ pub const JSTLSSocket = struct { if (@TypeOf(TLSSocket.write) != CallbackType) @compileLog("Expected TLSSocket.write to be a callback"); if (!JSC.is_bindgen) { - @export(TLSSocket.constructor, .{ .name = "TLSSocketClass__construct" }); @export(TLSSocket.end, .{ .name = "TLSSocketPrototype__end" }); @export(TLSSocket.finalize, .{ .name = "TLSSocketClass__finalize" }); @export(TLSSocket.flush, .{ .name = "TLSSocketPrototype__flush" }); @@ -315,6 +292,7 @@ pub const JSTLSSocket = struct { @export(TLSSocket.getLocalPort, .{ .name = "TLSSocketPrototype__getLocalPort" }); @export(TLSSocket.getReadyState, .{ .name = "TLSSocketPrototype__getReadyState" }); @export(TLSSocket.getRemoteAddress, .{ .name = "TLSSocketPrototype__getRemoteAddress" }); + @export(TLSSocket.hasPendingActivity, .{ .name = "TLSSocket__hasPendingActivity" }); @export(TLSSocket.ref, .{ .name = "TLSSocketPrototype__ref" }); @export(TLSSocket.reload, .{ .name = "TLSSocketPrototype__reload" }); @export(TLSSocket.setData, .{ .name = "TLSSocketPrototype__setData" }); @@ -384,13 +362,6 @@ pub const JSListener = struct { return result; } - /// Get the Listener constructor value. - /// This loads lazily from the global object. - pub fn getConstructor(globalObject: *JSC.JSGlobalObject) JSC.JSValue { - JSC.markBinding(@src()); - return Listener__getConstructor(globalObject); - } - /// Create a new instance of Listener pub fn toJS(this: *Listener, globalObject: *JSC.JSGlobalObject) JSC.JSValue { JSC.markBinding(@src()); @@ -423,10 +394,6 @@ pub const JSListener = struct { extern fn Listener__dangerouslySetPtr(JSC.JSValue, ?*Listener) bool; comptime { - if (@TypeOf(Listener.constructor) != (fn (*JSC.JSGlobalObject, *JSC.CallFrame) callconv(.C) ?*Listener)) { - @compileLog("Listener.constructor is not a constructor"); - } - if (@TypeOf(Listener.finalize) != (fn (*Listener) callconv(.C) void)) { @compileLog("Listener.finalize is not a finalizer"); } @@ -454,7 +421,6 @@ pub const JSListener = struct { if (@TypeOf(Listener.unref) != CallbackType) @compileLog("Expected Listener.unref to be a callback"); if (!JSC.is_bindgen) { - @export(Listener.constructor, .{ .name = "ListenerClass__construct" }); @export(Listener.finalize, .{ .name = "ListenerClass__finalize" }); @export(Listener.getData, .{ .name = "ListenerPrototype__getData" }); @export(Listener.getHostname, .{ .name = "ListenerPrototype__getHostname" }); @@ -549,13 +515,6 @@ pub const JSSubprocess = struct { return result; } - /// Get the Subprocess constructor value. - /// This loads lazily from the global object. - pub fn getConstructor(globalObject: *JSC.JSGlobalObject) JSC.JSValue { - JSC.markBinding(@src()); - return Subprocess__getConstructor(globalObject); - } - /// Create a new instance of Subprocess pub fn toJS(this: *Subprocess, globalObject: *JSC.JSGlobalObject) JSC.JSValue { JSC.markBinding(@src()); @@ -588,10 +547,6 @@ pub const JSSubprocess = struct { extern fn Subprocess__dangerouslySetPtr(JSC.JSValue, ?*Subprocess) bool; comptime { - if (@TypeOf(Subprocess.constructor) != (fn (*JSC.JSGlobalObject, *JSC.CallFrame) callconv(.C) ?*Subprocess)) { - @compileLog("Subprocess.constructor is not a constructor"); - } - if (@TypeOf(Subprocess.finalize) != (fn (*Subprocess) callconv(.C) void)) { @compileLog("Subprocess.finalize is not a finalizer"); } @@ -630,7 +585,6 @@ pub const JSSubprocess = struct { @compileLog("Expected Subprocess.getStdin to be a getter"); if (!JSC.is_bindgen) { - @export(Subprocess.constructor, .{ .name = "SubprocessClass__construct" }); @export(Subprocess.doRef, .{ .name = "SubprocessPrototype__doRef" }); @export(Subprocess.doUnref, .{ .name = "SubprocessPrototype__doUnref" }); @export(Subprocess.finalize, .{ .name = "SubprocessClass__finalize" }); @@ -1508,6 +1462,399 @@ pub const JSServerWebSocket = struct { } } }; +pub const JSFileSystemRouter = struct { + const FileSystemRouter = Classes.FileSystemRouter; + const GetterType = fn (*FileSystemRouter, *JSC.JSGlobalObject) callconv(.C) JSC.JSValue; + const GetterTypeWithThisValue = fn (*FileSystemRouter, JSC.JSValue, *JSC.JSGlobalObject) callconv(.C) JSC.JSValue; + const SetterType = fn (*FileSystemRouter, *JSC.JSGlobalObject, JSC.JSValue) callconv(.C) bool; + const SetterTypeWithThisValue = fn (*FileSystemRouter, JSC.JSValue, *JSC.JSGlobalObject, JSC.JSValue) callconv(.C) bool; + const CallbackType = fn (*FileSystemRouter, *JSC.JSGlobalObject, *JSC.CallFrame) callconv(.C) JSC.JSValue; + + /// Return the pointer to the wrapped object. + /// If the object does not match the type, return null. + pub fn fromJS(value: JSC.JSValue) ?*FileSystemRouter { + JSC.markBinding(@src()); + return FileSystemRouter__fromJS(value); + } + + extern fn FileSystemRouterPrototype__originSetCachedValue(JSC.JSValue, *JSC.JSGlobalObject, JSC.JSValue) void; + + extern fn FileSystemRouterPrototype__originGetCachedValue(JSC.JSValue) JSC.JSValue; + + /// `FileSystemRouter.origin` setter + /// This value will be visited by the garbage collector. + pub fn originSetCached(thisValue: JSC.JSValue, globalObject: *JSC.JSGlobalObject, value: JSC.JSValue) void { + JSC.markBinding(@src()); + FileSystemRouterPrototype__originSetCachedValue(thisValue, globalObject, value); + } + + /// `FileSystemRouter.origin` getter + /// This value will be visited by the garbage collector. + pub fn originGetCached(thisValue: JSC.JSValue) ?JSC.JSValue { + JSC.markBinding(@src()); + const result = FileSystemRouterPrototype__originGetCachedValue(thisValue); + if (result == .zero) + return null; + + return result; + } + + extern fn FileSystemRouterPrototype__routesSetCachedValue(JSC.JSValue, *JSC.JSGlobalObject, JSC.JSValue) void; + + extern fn FileSystemRouterPrototype__routesGetCachedValue(JSC.JSValue) JSC.JSValue; + + /// `FileSystemRouter.routes` setter + /// This value will be visited by the garbage collector. + pub fn routesSetCached(thisValue: JSC.JSValue, globalObject: *JSC.JSGlobalObject, value: JSC.JSValue) void { + JSC.markBinding(@src()); + FileSystemRouterPrototype__routesSetCachedValue(thisValue, globalObject, value); + } + + /// `FileSystemRouter.routes` getter + /// This value will be visited by the garbage collector. + pub fn routesGetCached(thisValue: JSC.JSValue) ?JSC.JSValue { + JSC.markBinding(@src()); + const result = FileSystemRouterPrototype__routesGetCachedValue(thisValue); + if (result == .zero) + return null; + + return result; + } + + extern fn FileSystemRouterPrototype__styleSetCachedValue(JSC.JSValue, *JSC.JSGlobalObject, JSC.JSValue) void; + + extern fn FileSystemRouterPrototype__styleGetCachedValue(JSC.JSValue) JSC.JSValue; + + /// `FileSystemRouter.style` setter + /// This value will be visited by the garbage collector. + pub fn styleSetCached(thisValue: JSC.JSValue, globalObject: *JSC.JSGlobalObject, value: JSC.JSValue) void { + JSC.markBinding(@src()); + FileSystemRouterPrototype__styleSetCachedValue(thisValue, globalObject, value); + } + + /// `FileSystemRouter.style` getter + /// This value will be visited by the garbage collector. + pub fn styleGetCached(thisValue: JSC.JSValue) ?JSC.JSValue { + JSC.markBinding(@src()); + const result = FileSystemRouterPrototype__styleGetCachedValue(thisValue); + if (result == .zero) + return null; + + return result; + } + + /// Get the FileSystemRouter constructor value. + /// This loads lazily from the global object. + pub fn getConstructor(globalObject: *JSC.JSGlobalObject) JSC.JSValue { + JSC.markBinding(@src()); + return FileSystemRouter__getConstructor(globalObject); + } + + /// Create a new instance of FileSystemRouter + pub fn toJS(this: *FileSystemRouter, globalObject: *JSC.JSGlobalObject) JSC.JSValue { + JSC.markBinding(@src()); + if (comptime Environment.allow_assert) { + const value__ = FileSystemRouter__create(globalObject, this); + std.debug.assert(value__.as(FileSystemRouter).? == this); // If this fails, likely a C ABI issue. + return value__; + } else { + return FileSystemRouter__create(globalObject, this); + } + } + + /// Modify the internal ptr to point to a new instance of FileSystemRouter. + pub fn dangerouslySetPtr(value: JSC.JSValue, ptr: ?*FileSystemRouter) bool { + JSC.markBinding(@src()); + return FileSystemRouter__dangerouslySetPtr(value, ptr); + } + + /// Detach the ptr from the thisValue + pub fn detachPtr(_: *FileSystemRouter, value: JSC.JSValue) void { + JSC.markBinding(@src()); + std.debug.assert(FileSystemRouter__dangerouslySetPtr(value, null)); + } + + extern fn FileSystemRouter__fromJS(JSC.JSValue) ?*FileSystemRouter; + extern fn FileSystemRouter__getConstructor(*JSC.JSGlobalObject) JSC.JSValue; + + extern fn FileSystemRouter__create(globalObject: *JSC.JSGlobalObject, ptr: ?*FileSystemRouter) JSC.JSValue; + + extern fn FileSystemRouter__dangerouslySetPtr(JSC.JSValue, ?*FileSystemRouter) bool; + + comptime { + if (@TypeOf(FileSystemRouter.constructor) != (fn (*JSC.JSGlobalObject, *JSC.CallFrame) callconv(.C) ?*FileSystemRouter)) { + @compileLog("FileSystemRouter.constructor is not a constructor"); + } + + if (@TypeOf(FileSystemRouter.finalize) != (fn (*FileSystemRouter) callconv(.C) void)) { + @compileLog("FileSystemRouter.finalize is not a finalizer"); + } + + if (@TypeOf(FileSystemRouter.match) != CallbackType) + @compileLog("Expected FileSystemRouter.match to be a callback"); + if (@TypeOf(FileSystemRouter.getOrigin) != GetterType) + @compileLog("Expected FileSystemRouter.getOrigin to be a getter"); + + if (@TypeOf(FileSystemRouter.reload) != CallbackType) + @compileLog("Expected FileSystemRouter.reload to be a callback"); + if (@TypeOf(FileSystemRouter.getRoutes) != GetterType) + @compileLog("Expected FileSystemRouter.getRoutes to be a getter"); + + if (@TypeOf(FileSystemRouter.getStyle) != GetterType) + @compileLog("Expected FileSystemRouter.getStyle to be a getter"); + + if (!JSC.is_bindgen) { + @export(FileSystemRouter.constructor, .{ .name = "FileSystemRouterClass__construct" }); + @export(FileSystemRouter.finalize, .{ .name = "FileSystemRouterClass__finalize" }); + @export(FileSystemRouter.getOrigin, .{ .name = "FileSystemRouterPrototype__getOrigin" }); + @export(FileSystemRouter.getRoutes, .{ .name = "FileSystemRouterPrototype__getRoutes" }); + @export(FileSystemRouter.getStyle, .{ .name = "FileSystemRouterPrototype__getStyle" }); + @export(FileSystemRouter.match, .{ .name = "FileSystemRouterPrototype__match" }); + @export(FileSystemRouter.reload, .{ .name = "FileSystemRouterPrototype__reload" }); + } + } +}; +pub const JSMatchedRoute = struct { + const MatchedRoute = Classes.MatchedRoute; + const GetterType = fn (*MatchedRoute, *JSC.JSGlobalObject) callconv(.C) JSC.JSValue; + const GetterTypeWithThisValue = fn (*MatchedRoute, JSC.JSValue, *JSC.JSGlobalObject) callconv(.C) JSC.JSValue; + const SetterType = fn (*MatchedRoute, *JSC.JSGlobalObject, JSC.JSValue) callconv(.C) bool; + const SetterTypeWithThisValue = fn (*MatchedRoute, JSC.JSValue, *JSC.JSGlobalObject, JSC.JSValue) callconv(.C) bool; + const CallbackType = fn (*MatchedRoute, *JSC.JSGlobalObject, *JSC.CallFrame) callconv(.C) JSC.JSValue; + + /// Return the pointer to the wrapped object. + /// If the object does not match the type, return null. + pub fn fromJS(value: JSC.JSValue) ?*MatchedRoute { + JSC.markBinding(@src()); + return MatchedRoute__fromJS(value); + } + + extern fn MatchedRoutePrototype__filePathSetCachedValue(JSC.JSValue, *JSC.JSGlobalObject, JSC.JSValue) void; + + extern fn MatchedRoutePrototype__filePathGetCachedValue(JSC.JSValue) JSC.JSValue; + + /// `MatchedRoute.filePath` setter + /// This value will be visited by the garbage collector. + pub fn filePathSetCached(thisValue: JSC.JSValue, globalObject: *JSC.JSGlobalObject, value: JSC.JSValue) void { + JSC.markBinding(@src()); + MatchedRoutePrototype__filePathSetCachedValue(thisValue, globalObject, value); + } + + /// `MatchedRoute.filePath` getter + /// This value will be visited by the garbage collector. + pub fn filePathGetCached(thisValue: JSC.JSValue) ?JSC.JSValue { + JSC.markBinding(@src()); + const result = MatchedRoutePrototype__filePathGetCachedValue(thisValue); + if (result == .zero) + return null; + + return result; + } + + extern fn MatchedRoutePrototype__kindSetCachedValue(JSC.JSValue, *JSC.JSGlobalObject, JSC.JSValue) void; + + extern fn MatchedRoutePrototype__kindGetCachedValue(JSC.JSValue) JSC.JSValue; + + /// `MatchedRoute.kind` setter + /// This value will be visited by the garbage collector. + pub fn kindSetCached(thisValue: JSC.JSValue, globalObject: *JSC.JSGlobalObject, value: JSC.JSValue) void { + JSC.markBinding(@src()); + MatchedRoutePrototype__kindSetCachedValue(thisValue, globalObject, value); + } + + /// `MatchedRoute.kind` getter + /// This value will be visited by the garbage collector. + pub fn kindGetCached(thisValue: JSC.JSValue) ?JSC.JSValue { + JSC.markBinding(@src()); + const result = MatchedRoutePrototype__kindGetCachedValue(thisValue); + if (result == .zero) + return null; + + return result; + } + + extern fn MatchedRoutePrototype__nameSetCachedValue(JSC.JSValue, *JSC.JSGlobalObject, JSC.JSValue) void; + + extern fn MatchedRoutePrototype__nameGetCachedValue(JSC.JSValue) JSC.JSValue; + + /// `MatchedRoute.name` setter + /// This value will be visited by the garbage collector. + pub fn nameSetCached(thisValue: JSC.JSValue, globalObject: *JSC.JSGlobalObject, value: JSC.JSValue) void { + JSC.markBinding(@src()); + MatchedRoutePrototype__nameSetCachedValue(thisValue, globalObject, value); + } + + /// `MatchedRoute.name` getter + /// This value will be visited by the garbage collector. + pub fn nameGetCached(thisValue: JSC.JSValue) ?JSC.JSValue { + JSC.markBinding(@src()); + const result = MatchedRoutePrototype__nameGetCachedValue(thisValue); + if (result == .zero) + return null; + + return result; + } + + extern fn MatchedRoutePrototype__paramsSetCachedValue(JSC.JSValue, *JSC.JSGlobalObject, JSC.JSValue) void; + + extern fn MatchedRoutePrototype__paramsGetCachedValue(JSC.JSValue) JSC.JSValue; + + /// `MatchedRoute.params` setter + /// This value will be visited by the garbage collector. + pub fn paramsSetCached(thisValue: JSC.JSValue, globalObject: *JSC.JSGlobalObject, value: JSC.JSValue) void { + JSC.markBinding(@src()); + MatchedRoutePrototype__paramsSetCachedValue(thisValue, globalObject, value); + } + + /// `MatchedRoute.params` getter + /// This value will be visited by the garbage collector. + pub fn paramsGetCached(thisValue: JSC.JSValue) ?JSC.JSValue { + JSC.markBinding(@src()); + const result = MatchedRoutePrototype__paramsGetCachedValue(thisValue); + if (result == .zero) + return null; + + return result; + } + + extern fn MatchedRoutePrototype__pathnameSetCachedValue(JSC.JSValue, *JSC.JSGlobalObject, JSC.JSValue) void; + + extern fn MatchedRoutePrototype__pathnameGetCachedValue(JSC.JSValue) JSC.JSValue; + + /// `MatchedRoute.pathname` setter + /// This value will be visited by the garbage collector. + pub fn pathnameSetCached(thisValue: JSC.JSValue, globalObject: *JSC.JSGlobalObject, value: JSC.JSValue) void { + JSC.markBinding(@src()); + MatchedRoutePrototype__pathnameSetCachedValue(thisValue, globalObject, value); + } + + /// `MatchedRoute.pathname` getter + /// This value will be visited by the garbage collector. + pub fn pathnameGetCached(thisValue: JSC.JSValue) ?JSC.JSValue { + JSC.markBinding(@src()); + const result = MatchedRoutePrototype__pathnameGetCachedValue(thisValue); + if (result == .zero) + return null; + + return result; + } + + extern fn MatchedRoutePrototype__querySetCachedValue(JSC.JSValue, *JSC.JSGlobalObject, JSC.JSValue) void; + + extern fn MatchedRoutePrototype__queryGetCachedValue(JSC.JSValue) JSC.JSValue; + + /// `MatchedRoute.query` setter + /// This value will be visited by the garbage collector. + pub fn querySetCached(thisValue: JSC.JSValue, globalObject: *JSC.JSGlobalObject, value: JSC.JSValue) void { + JSC.markBinding(@src()); + MatchedRoutePrototype__querySetCachedValue(thisValue, globalObject, value); + } + + /// `MatchedRoute.query` getter + /// This value will be visited by the garbage collector. + pub fn queryGetCached(thisValue: JSC.JSValue) ?JSC.JSValue { + JSC.markBinding(@src()); + const result = MatchedRoutePrototype__queryGetCachedValue(thisValue); + if (result == .zero) + return null; + + return result; + } + + extern fn MatchedRoutePrototype__scriptSrcSetCachedValue(JSC.JSValue, *JSC.JSGlobalObject, JSC.JSValue) void; + + extern fn MatchedRoutePrototype__scriptSrcGetCachedValue(JSC.JSValue) JSC.JSValue; + + /// `MatchedRoute.scriptSrc` setter + /// This value will be visited by the garbage collector. + pub fn scriptSrcSetCached(thisValue: JSC.JSValue, globalObject: *JSC.JSGlobalObject, value: JSC.JSValue) void { + JSC.markBinding(@src()); + MatchedRoutePrototype__scriptSrcSetCachedValue(thisValue, globalObject, value); + } + + /// `MatchedRoute.scriptSrc` getter + /// This value will be visited by the garbage collector. + pub fn scriptSrcGetCached(thisValue: JSC.JSValue) ?JSC.JSValue { + JSC.markBinding(@src()); + const result = MatchedRoutePrototype__scriptSrcGetCachedValue(thisValue); + if (result == .zero) + return null; + + return result; + } + + /// Create a new instance of MatchedRoute + pub fn toJS(this: *MatchedRoute, globalObject: *JSC.JSGlobalObject) JSC.JSValue { + JSC.markBinding(@src()); + if (comptime Environment.allow_assert) { + const value__ = MatchedRoute__create(globalObject, this); + std.debug.assert(value__.as(MatchedRoute).? == this); // If this fails, likely a C ABI issue. + return value__; + } else { + return MatchedRoute__create(globalObject, this); + } + } + + /// Modify the internal ptr to point to a new instance of MatchedRoute. + pub fn dangerouslySetPtr(value: JSC.JSValue, ptr: ?*MatchedRoute) bool { + JSC.markBinding(@src()); + return MatchedRoute__dangerouslySetPtr(value, ptr); + } + + /// Detach the ptr from the thisValue + pub fn detachPtr(_: *MatchedRoute, value: JSC.JSValue) void { + JSC.markBinding(@src()); + std.debug.assert(MatchedRoute__dangerouslySetPtr(value, null)); + } + + extern fn MatchedRoute__fromJS(JSC.JSValue) ?*MatchedRoute; + extern fn MatchedRoute__getConstructor(*JSC.JSGlobalObject) JSC.JSValue; + + extern fn MatchedRoute__create(globalObject: *JSC.JSGlobalObject, ptr: ?*MatchedRoute) JSC.JSValue; + + extern fn MatchedRoute__dangerouslySetPtr(JSC.JSValue, ?*MatchedRoute) bool; + + comptime { + if (@TypeOf(MatchedRoute.finalize) != (fn (*MatchedRoute) callconv(.C) void)) { + @compileLog("MatchedRoute.finalize is not a finalizer"); + } + + if (@TypeOf(MatchedRoute.getFilePath) != GetterType) + @compileLog("Expected MatchedRoute.getFilePath to be a getter"); + + if (@TypeOf(MatchedRoute.getKind) != GetterType) + @compileLog("Expected MatchedRoute.getKind to be a getter"); + + if (@TypeOf(MatchedRoute.getName) != GetterType) + @compileLog("Expected MatchedRoute.getName to be a getter"); + + if (@TypeOf(MatchedRoute.getParams) != GetterType) + @compileLog("Expected MatchedRoute.getParams to be a getter"); + + if (@TypeOf(MatchedRoute.getPathname) != GetterType) + @compileLog("Expected MatchedRoute.getPathname to be a getter"); + + if (@TypeOf(MatchedRoute.getQuery) != GetterType) + @compileLog("Expected MatchedRoute.getQuery to be a getter"); + + if (@TypeOf(MatchedRoute.getScriptSrc) != GetterType) + @compileLog("Expected MatchedRoute.getScriptSrc to be a getter"); + + if (@TypeOf(MatchedRoute.getScriptSrc) != GetterType) + @compileLog("Expected MatchedRoute.getScriptSrc to be a getter"); + + if (!JSC.is_bindgen) { + @export(MatchedRoute.finalize, .{ .name = "MatchedRouteClass__finalize" }); + @export(MatchedRoute.getFilePath, .{ .name = "MatchedRoutePrototype__getFilePath" }); + @export(MatchedRoute.getKind, .{ .name = "MatchedRoutePrototype__getKind" }); + @export(MatchedRoute.getName, .{ .name = "MatchedRoutePrototype__getName" }); + @export(MatchedRoute.getParams, .{ .name = "MatchedRoutePrototype__getParams" }); + @export(MatchedRoute.getPathname, .{ .name = "MatchedRoutePrototype__getPathname" }); + @export(MatchedRoute.getQuery, .{ .name = "MatchedRoutePrototype__getQuery" }); + @export(MatchedRoute.getScriptSrc, .{ .name = "MatchedRoutePrototype__getScriptSrc" }); + } + } +}; pub const JSExpect = struct { const Expect = Classes.Expect; const GetterType = fn (*Expect, *JSC.JSGlobalObject) callconv(.C) JSC.JSValue; @@ -1624,6 +1971,10 @@ pub const JSExpect = struct { @compileLog("Expected Expect.toBe to be a callback"); if (@TypeOf(Expect.toBeCloseTo) != CallbackType) @compileLog("Expected Expect.toBeCloseTo to be a callback"); + if (@TypeOf(Expect.toBeDefined) != CallbackType) + @compileLog("Expected Expect.toBeDefined to be a callback"); + if (@TypeOf(Expect.toBeFalsy) != CallbackType) + @compileLog("Expected Expect.toBeFalsy to be a callback"); if (@TypeOf(Expect.toBeGreaterThan) != CallbackType) @compileLog("Expected Expect.toBeGreaterThan to be a callback"); if (@TypeOf(Expect.toBeGreaterThanOrEqual) != CallbackType) @@ -1634,6 +1985,14 @@ pub const JSExpect = struct { @compileLog("Expected Expect.toBeLessThan to be a callback"); if (@TypeOf(Expect.toBeLessThanOrEqual) != CallbackType) @compileLog("Expected Expect.toBeLessThanOrEqual to be a callback"); + if (@TypeOf(Expect.toBeNaN) != CallbackType) + @compileLog("Expected Expect.toBeNaN to be a callback"); + if (@TypeOf(Expect.toBeNull) != CallbackType) + @compileLog("Expected Expect.toBeNull to be a callback"); + if (@TypeOf(Expect.toBeTruthy) != CallbackType) + @compileLog("Expected Expect.toBeTruthy to be a callback"); + if (@TypeOf(Expect.toBeUndefined) != CallbackType) + @compileLog("Expected Expect.toBeUndefined to be a callback"); if (@TypeOf(Expect.toContain) != CallbackType) @compileLog("Expected Expect.toContain to be a callback"); if (@TypeOf(Expect.toContainEqual) != CallbackType) @@ -1729,11 +2088,17 @@ pub const JSExpect = struct { @export(Expect.stringMatching, .{ .name = "ExpectClass__stringMatching" }); @export(Expect.toBe, .{ .name = "ExpectPrototype__toBe" }); @export(Expect.toBeCloseTo, .{ .name = "ExpectPrototype__toBeCloseTo" }); + @export(Expect.toBeDefined, .{ .name = "ExpectPrototype__toBeDefined" }); + @export(Expect.toBeFalsy, .{ .name = "ExpectPrototype__toBeFalsy" }); @export(Expect.toBeGreaterThan, .{ .name = "ExpectPrototype__toBeGreaterThan" }); @export(Expect.toBeGreaterThanOrEqual, .{ .name = "ExpectPrototype__toBeGreaterThanOrEqual" }); @export(Expect.toBeInstanceOf, .{ .name = "ExpectPrototype__toBeInstanceOf" }); @export(Expect.toBeLessThan, .{ .name = "ExpectPrototype__toBeLessThan" }); @export(Expect.toBeLessThanOrEqual, .{ .name = "ExpectPrototype__toBeLessThanOrEqual" }); + @export(Expect.toBeNaN, .{ .name = "ExpectPrototype__toBeNaN" }); + @export(Expect.toBeNull, .{ .name = "ExpectPrototype__toBeNull" }); + @export(Expect.toBeTruthy, .{ .name = "ExpectPrototype__toBeTruthy" }); + @export(Expect.toBeUndefined, .{ .name = "ExpectPrototype__toBeUndefined" }); @export(Expect.toContain, .{ .name = "ExpectPrototype__toContain" }); @export(Expect.toContainEqual, .{ .name = "ExpectPrototype__toContainEqual" }); @export(Expect.toEqual, .{ .name = "ExpectPrototype__toEqual" }); @@ -2401,6 +2766,8 @@ comptime { _ = JSSHA256; _ = JSSHA512_256; _ = JSServerWebSocket; + _ = JSFileSystemRouter; + _ = JSMatchedRoute; _ = JSExpect; _ = JSTextDecoder; _ = JSRequest; diff --git a/src/bun.js/bindings/generated_classes_list.zig b/src/bun.js/bindings/generated_classes_list.zig index 25365940b..1dae06a3b 100644 --- a/src/bun.js/bindings/generated_classes_list.zig +++ b/src/bun.js/bindings/generated_classes_list.zig @@ -19,4 +19,6 @@ pub const Classes = struct { pub const TLSSocket = JSC.API.TLSSocket; pub const Listener = JSC.API.Listener; pub const Expect = JSC.Jest.Expect; + pub const FileSystemRouter = JSC.API.FileSystemRouter; + pub const MatchedRoute = JSC.API.MatchedRoute; }; diff --git a/src/bun.js/bindings/headers-cpp.h b/src/bun.js/bindings/headers-cpp.h index 60276f76f..05368907e 100644 --- a/src/bun.js/bindings/headers-cpp.h +++ b/src/bun.js/bindings/headers-cpp.h @@ -1,4 +1,4 @@ -//-- AUTOGENERATED FILE -- 1667784809 +//-- AUTOGENERATED FILE -- 1668983536 // clang-format off #pragma once diff --git a/src/bun.js/bindings/headers.h b/src/bun.js/bindings/headers.h index a3f71adb3..99b046b59 100644 --- a/src/bun.js/bindings/headers.h +++ b/src/bun.js/bindings/headers.h @@ -1,5 +1,5 @@ // clang-format off -//-- AUTOGENERATED FILE -- 1667784809 +//-- AUTOGENERATED FILE -- 1668983536 #pragma once #include <stddef.h> @@ -349,7 +349,7 @@ CPP_DECL void JSC__JSPromise__rejectWithCaughtException(JSC__JSPromise* arg0, JS CPP_DECL void JSC__JSPromise__resolve(JSC__JSPromise* arg0, JSC__JSGlobalObject* arg1, JSC__JSValue JSValue2); CPP_DECL JSC__JSPromise* JSC__JSPromise__resolvedPromise(JSC__JSGlobalObject* arg0, JSC__JSValue JSValue1); CPP_DECL JSC__JSValue JSC__JSPromise__resolvedPromiseValue(JSC__JSGlobalObject* arg0, JSC__JSValue JSValue1); -CPP_DECL JSC__JSValue JSC__JSPromise__result(const JSC__JSPromise* arg0, JSC__VM* arg1); +CPP_DECL JSC__JSValue JSC__JSPromise__result(JSC__JSPromise* arg0, JSC__VM* arg1); CPP_DECL uint32_t JSC__JSPromise__status(const JSC__JSPromise* arg0, JSC__VM* arg1); #pragma mark - JSC::JSInternalPromise @@ -496,7 +496,7 @@ CPP_DECL JSC__JSValue JSC__JSValue__fromUInt64NoTruncate(JSC__JSGlobalObject* ar CPP_DECL void JSC__JSValue__getClassName(JSC__JSValue JSValue0, JSC__JSGlobalObject* arg1, ZigString* arg2); CPP_DECL JSC__JSValue JSC__JSValue__getErrorsProperty(JSC__JSValue JSValue0, JSC__JSGlobalObject* arg1); CPP_DECL JSC__JSValue JSC__JSValue__getIfPropertyExistsImpl(JSC__JSValue JSValue0, JSC__JSGlobalObject* arg1, const unsigned char* arg2, uint32_t arg3); -CPP_DECL uint32_t JSC__JSValue__getLengthOfArray(JSC__JSValue JSValue0, JSC__JSGlobalObject* arg1); +CPP_DECL uint64_t JSC__JSValue__getLengthOfArray(JSC__JSValue JSValue0, JSC__JSGlobalObject* arg1); CPP_DECL void JSC__JSValue__getNameProperty(JSC__JSValue JSValue0, JSC__JSGlobalObject* arg1, ZigString* arg2); CPP_DECL JSC__JSValue JSC__JSValue__getPrototype(JSC__JSValue JSValue0, JSC__JSGlobalObject* arg1); CPP_DECL void JSC__JSValue__getSymbolDescription(JSC__JSValue JSValue0, JSC__JSGlobalObject* arg1, ZigString* arg2); @@ -542,6 +542,7 @@ CPP_DECL void JSC__JSValue__putRecord(JSC__JSValue JSValue0, JSC__JSGlobalObject CPP_DECL JSC__JSValue JSC__JSValue__symbolFor(JSC__JSGlobalObject* arg0, ZigString* arg1); CPP_DECL bool JSC__JSValue__symbolKeyFor(JSC__JSValue JSValue0, JSC__JSGlobalObject* arg1, ZigString* arg2); CPP_DECL bool JSC__JSValue__toBoolean(JSC__JSValue JSValue0); +CPP_DECL bool JSC__JSValue__toBooleanSlow(JSC__JSValue JSValue0, JSC__JSGlobalObject* arg1); CPP_DECL JSC__JSValue JSC__JSValue__toError(JSC__JSValue JSValue0, JSC__JSGlobalObject* arg1); CPP_DECL int32_t JSC__JSValue__toInt32(JSC__JSValue JSValue0); CPP_DECL int64_t JSC__JSValue__toInt64(JSC__JSValue JSValue0); diff --git a/src/bun.js/bindings/headers.zig b/src/bun.js/bindings/headers.zig index e0909ba8c..41f5f7178 100644 --- a/src/bun.js/bindings/headers.zig +++ b/src/bun.js/bindings/headers.zig @@ -167,7 +167,7 @@ pub extern fn JSC__JSPromise__rejectWithCaughtException(arg0: [*c]JSC__JSPromise pub extern fn JSC__JSPromise__resolve(arg0: [*c]JSC__JSPromise, arg1: ?*JSC__JSGlobalObject, JSValue2: JSC__JSValue) void; pub extern fn JSC__JSPromise__resolvedPromise(arg0: ?*JSC__JSGlobalObject, JSValue1: JSC__JSValue) [*c]JSC__JSPromise; pub extern fn JSC__JSPromise__resolvedPromiseValue(arg0: ?*JSC__JSGlobalObject, JSValue1: JSC__JSValue) JSC__JSValue; -pub extern fn JSC__JSPromise__result(arg0: [*c]const JSC__JSPromise, arg1: [*c]JSC__VM) JSC__JSValue; +pub extern fn JSC__JSPromise__result(arg0: [*c]JSC__JSPromise, arg1: [*c]JSC__VM) JSC__JSValue; pub extern fn JSC__JSPromise__status(arg0: [*c]const JSC__JSPromise, arg1: [*c]JSC__VM) u32; pub extern fn JSC__JSInternalPromise__create(arg0: ?*JSC__JSGlobalObject) [*c]JSC__JSInternalPromise; pub extern fn JSC__JSInternalPromise__isHandled(arg0: [*c]const JSC__JSInternalPromise, arg1: [*c]JSC__VM) bool; @@ -289,7 +289,7 @@ pub extern fn JSC__JSValue__fromUInt64NoTruncate(arg0: ?*JSC__JSGlobalObject, ar pub extern fn JSC__JSValue__getClassName(JSValue0: JSC__JSValue, arg1: ?*JSC__JSGlobalObject, arg2: [*c]ZigString) void; pub extern fn JSC__JSValue__getErrorsProperty(JSValue0: JSC__JSValue, arg1: ?*JSC__JSGlobalObject) JSC__JSValue; pub extern fn JSC__JSValue__getIfPropertyExistsImpl(JSValue0: JSC__JSValue, arg1: ?*JSC__JSGlobalObject, arg2: [*c]const u8, arg3: u32) JSC__JSValue; -pub extern fn JSC__JSValue__getLengthOfArray(JSValue0: JSC__JSValue, arg1: ?*JSC__JSGlobalObject) u32; +pub extern fn JSC__JSValue__getLengthOfArray(JSValue0: JSC__JSValue, arg1: ?*JSC__JSGlobalObject) u64; pub extern fn JSC__JSValue__getNameProperty(JSValue0: JSC__JSValue, arg1: ?*JSC__JSGlobalObject, arg2: [*c]ZigString) void; pub extern fn JSC__JSValue__getPrototype(JSValue0: JSC__JSValue, arg1: ?*JSC__JSGlobalObject) JSC__JSValue; pub extern fn JSC__JSValue__getSymbolDescription(JSValue0: JSC__JSValue, arg1: ?*JSC__JSGlobalObject, arg2: [*c]ZigString) void; @@ -335,6 +335,7 @@ pub extern fn JSC__JSValue__putRecord(JSValue0: JSC__JSValue, arg1: ?*JSC__JSGlo pub extern fn JSC__JSValue__symbolFor(arg0: ?*JSC__JSGlobalObject, arg1: [*c]ZigString) JSC__JSValue; pub extern fn JSC__JSValue__symbolKeyFor(JSValue0: JSC__JSValue, arg1: ?*JSC__JSGlobalObject, arg2: [*c]ZigString) bool; pub extern fn JSC__JSValue__toBoolean(JSValue0: JSC__JSValue) bool; +pub extern fn JSC__JSValue__toBooleanSlow(JSValue0: JSC__JSValue, arg1: ?*JSC__JSGlobalObject) bool; pub extern fn JSC__JSValue__toError(JSValue0: JSC__JSValue, arg1: ?*JSC__JSGlobalObject) JSC__JSValue; pub extern fn JSC__JSValue__toInt32(JSValue0: JSC__JSValue) i32; pub extern fn JSC__JSValue__toInt64(JSValue0: JSC__JSValue) i64; diff --git a/src/bun.js/bindings/napi.cpp b/src/bun.js/bindings/napi.cpp index 649b8bf50..943f37688 100644 --- a/src/bun.js/bindings/napi.cpp +++ b/src/bun.js/bindings/napi.cpp @@ -1480,3 +1480,31 @@ extern "C" napi_status napi_get_value_external(napi_env env, napi_value value, *result = jsCast<Bun::NapiExternal*>(object)->value(); return napi_ok; } + +// TODO: make this per addon instead of globally shared for ALL addons +extern "C" napi_status napi_get_instance_data(napi_env env, + void** data) +{ + Zig::GlobalObject* globalObject = toJS(env); + if (data == nullptr) { + return napi_invalid_arg; + } + + *data = globalObject->napiInstanceData; + return napi_ok; +} + +extern "C" napi_status napi_set_instance_data(napi_env env, + void* data, + napi_finalize finalize_cb, + void* finalize_hint) +{ + Zig::GlobalObject* globalObject = toJS(env); + if (data) + globalObject->napiInstanceData = data; + + globalObject->napiInstanceDataFinalizer = reinterpret_cast<void*>(finalize_cb); + globalObject->napiInstanceDataFinalizerHint = finalize_hint; + + return napi_ok; +}
\ No newline at end of file diff --git a/src/bun.js/bindings/sqlite/JSSQLStatement.cpp b/src/bun.js/bindings/sqlite/JSSQLStatement.cpp index 8fc6ac77a..524c131af 100644 --- a/src/bun.js/bindings/sqlite/JSSQLStatement.cpp +++ b/src/bun.js/bindings/sqlite/JSSQLStatement.cpp @@ -992,14 +992,19 @@ static inline JSC::JSValue constructResultObject(JSC::JSGlobalObject* lexicalGlo switch (sqlite3_column_type(stmt, i)) { case SQLITE_INTEGER: { - result->putDirect(vm, name, jsNumber(sqlite3_column_int(stmt, i)), 0); + // https://github.com/oven-sh/bun/issues/1536 + result->putDirect(vm, name, jsNumber(sqlite3_column_int64(stmt, i)), 0); break; } case SQLITE_FLOAT: { result->putDirect(vm, name, jsNumber(sqlite3_column_double(stmt, i)), 0); break; } - case SQLITE_TEXT: { + // > Note that the SQLITE_TEXT constant was also used in SQLite version + // > 2 for a completely different meaning. Software that links against + // > both SQLite version 2 and SQLite version 3 should use SQLITE3_TEXT, + // > not SQLITE_TEXT. + case SQLITE3_TEXT: { size_t len = sqlite3_column_bytes(stmt, i); const unsigned char* text = len > 0 ? sqlite3_column_text(stmt, i) : nullptr; @@ -1042,13 +1047,18 @@ static inline JSC::JSArray* constructResultRow(JSC::JSGlobalObject* lexicalGloba switch (sqlite3_column_type(stmt, i)) { case SQLITE_INTEGER: { - result->initializeIndex(scope, i, jsNumber(sqlite3_column_int(stmt, i))); + // https://github.com/oven-sh/bun/issues/1536 + result->initializeIndex(scope, i, jsNumber(sqlite3_column_int64(stmt, i))); break; } case SQLITE_FLOAT: { result->initializeIndex(scope, i, jsNumber(sqlite3_column_double(stmt, i))); break; } + // > Note that the SQLITE_TEXT constant was also used in SQLite version + // > 2 for a completely different meaning. Software that links against + // > both SQLite version 2 and SQLite version 3 should use SQLITE3_TEXT, + // > not SQLITE_TEXT. case SQLITE_TEXT: { size_t len = sqlite3_column_bytes(stmt, i); const unsigned char* text = len > 0 ? sqlite3_column_text(stmt, i) : nullptr; diff --git a/src/bun.js/bindings/sqlite/lazy_sqlite3.h b/src/bun.js/bindings/sqlite/lazy_sqlite3.h index d692a0312..8b23a7e03 100644 --- a/src/bun.js/bindings/sqlite/lazy_sqlite3.h +++ b/src/bun.js/bindings/sqlite/lazy_sqlite3.h @@ -151,6 +151,7 @@ static lazy_sqlite3_stmt_readonly_type lazy_sqlite3_stmt_readonly; #define sqlite3_serialize lazy_sqlite3_serialize #define sqlite3_deserialize lazy_sqlite3_deserialize #define sqlite3_stmt_readonly lazy_sqlite3_stmt_readonly +#define sqlite3_column_int64 lazy_sqlite3_column_int64 static void* sqlite3_handle = nullptr; static const char* sqlite3_lib_path = "libsqlite3.dylib"; @@ -182,6 +183,7 @@ static int lazyLoadSQLite() lazy_sqlite3_column_decltype = (lazy_sqlite3_column_decltype_type)dlsym(sqlite3_handle, "sqlite3_column_decltype"); lazy_sqlite3_column_double = (lazy_sqlite3_column_double_type)dlsym(sqlite3_handle, "sqlite3_column_double"); lazy_sqlite3_column_int = (lazy_sqlite3_column_int_type)dlsym(sqlite3_handle, "sqlite3_column_int"); + lazy_sqlite3_column_int64 = (lazy_sqlite3_column_int64_type)dlsym(sqlite3_handle, "sqlite3_column_int64"); lazy_sqlite3_column_name = (lazy_sqlite3_column_name_type)dlsym(sqlite3_handle, "sqlite3_column_name"); lazy_sqlite3_column_text = (lazy_sqlite3_column_text_type)dlsym(sqlite3_handle, "sqlite3_column_text"); lazy_sqlite3_column_type = (lazy_sqlite3_column_type_type)dlsym(sqlite3_handle, "sqlite3_column_type"); diff --git a/src/bun.js/bindings/webcore/WebSocket.cpp b/src/bun.js/bindings/webcore/WebSocket.cpp index 820f0e804..2b685ef95 100644 --- a/src/bun.js/bindings/webcore/WebSocket.cpp +++ b/src/bun.js/bindings/webcore/WebSocket.cpp @@ -157,11 +157,12 @@ WebSocket::WebSocket(ScriptExecutionContext& context) , m_subprotocol(emptyString()) , m_extensions(emptyString()) { + m_state = CONNECTING; + m_hasPendingActivity.store(true); } WebSocket::~WebSocket() { - if (m_upgradeClient != nullptr) { void* upgradeClient = m_upgradeClient; if (m_isSecure) { @@ -275,6 +276,7 @@ ExceptionOr<void> WebSocket::connect(const String& url, const Vector<String>& pr if (!m_url.isValid()) { // context.addConsoleMessage(MessageSource::JS, MessageLevel::Error, ); m_state = CLOSED; + updateHasPendingActivity(); return Exception { SyntaxError, makeString("Invalid url for WebSocket "_s, m_url.stringCenterEllipsizedToLength()) }; } @@ -283,11 +285,13 @@ ExceptionOr<void> WebSocket::connect(const String& url, const Vector<String>& pr if (!m_url.protocolIs("ws"_s) && !is_secure) { // context.addConsoleMessage(MessageSource::JS, MessageLevel::Error, ); m_state = CLOSED; + updateHasPendingActivity(); return Exception { SyntaxError, makeString("Wrong url scheme for WebSocket "_s, m_url.stringCenterEllipsizedToLength()) }; } if (m_url.hasFragmentIdentifier()) { // context.addConsoleMessage(MessageSource::JS, MessageLevel::Error, ); m_state = CLOSED; + updateHasPendingActivity(); return Exception { SyntaxError, makeString("URL has fragment component "_s, m_url.stringCenterEllipsizedToLength()) }; } @@ -326,6 +330,7 @@ ExceptionOr<void> WebSocket::connect(const String& url, const Vector<String>& pr if (!isValidProtocolString(protocol)) { // context.addConsoleMessage(MessageSource::JS, MessageLevel::Error, ); m_state = CLOSED; + updateHasPendingActivity(); return Exception { SyntaxError, makeString("Wrong protocol for WebSocket '"_s, encodeProtocolString(protocol), "'"_s) }; } } @@ -334,6 +339,7 @@ ExceptionOr<void> WebSocket::connect(const String& url, const Vector<String>& pr if (!visited.add(protocol).isNewEntry) { // context.addConsoleMessage(MessageSource::JS, MessageLevel::Error, ); m_state = CLOSED; + updateHasPendingActivity(); return Exception { SyntaxError, makeString("WebSocket protocols contain duplicates:"_s, encodeProtocolString(protocol), "'"_s) }; } } @@ -366,22 +372,22 @@ ExceptionOr<void> WebSocket::connect(const String& url, const Vector<String>& pr } m_isSecure = is_secure; + this->incPendingActivityCount(); + if (is_secure) { us_socket_context_t* ctx = scriptExecutionContext()->webSocketContext<true>(); RELEASE_ASSERT(ctx); - this->m_pendingActivityCount++; this->m_upgradeClient = Bun__WebSocketHTTPSClient__connect(scriptExecutionContext()->jsGlobalObject(), ctx, this, &host, port, &path, &clientProtocolString); } else { us_socket_context_t* ctx = scriptExecutionContext()->webSocketContext<false>(); RELEASE_ASSERT(ctx); - this->m_pendingActivityCount++; this->m_upgradeClient = Bun__WebSocketHTTPClient__connect(scriptExecutionContext()->jsGlobalObject(), ctx, this, &host, port, &path, &clientProtocolString); } if (this->m_upgradeClient == nullptr) { // context.addConsoleMessage(MessageSource::JS, MessageLevel::Error, ); m_state = CLOSED; - this->m_pendingActivityCount--; + this->decPendingActivityCount(); return Exception { SyntaxError, "WebSocket connection failed"_s }; } @@ -399,7 +405,7 @@ ExceptionOr<void> WebSocket::connect(const String& url, const Vector<String>& pr // #endif // m_pendingActivity = makePendingActivity(*this); - + updateHasPendingActivity(); return {}; } @@ -482,7 +488,6 @@ ExceptionOr<void> WebSocket::send(ArrayBufferView& arrayBufferView) void WebSocket::sendWebSocketData(const char* baseAddress, size_t length) { - switch (m_connectedWebSocketKind) { case ConnectedWebSocketKind::Client: { Bun__WebSocketClient__writeBinaryData(this->m_connectedWebSocket.client, reinterpret_cast<const unsigned char*>(baseAddress), length); @@ -512,7 +517,6 @@ void WebSocket::sendWebSocketData(const char* baseAddress, size_t length) void WebSocket::sendWebSocketString(const String& message) { - switch (m_connectedWebSocketKind) { case ConnectedWebSocketKind::Client: { auto zigStr = Zig::toZigString(message); @@ -542,11 +546,11 @@ void WebSocket::sendWebSocketString(const String& message) RELEASE_ASSERT_NOT_REACHED(); } } + updateHasPendingActivity(); } ExceptionOr<void> WebSocket::close(std::optional<unsigned short> optionalCode, const String& reason) { - int code = optionalCode ? optionalCode.value() : static_cast<int>(0); if (code == 0) LOG(Network, "WebSocket %p close() without code and reason", this); @@ -573,6 +577,7 @@ ExceptionOr<void> WebSocket::close(std::optional<unsigned short> optionalCode, c Bun__WebSocketHTTPClient__cancel(upgradeClient); } } + updateHasPendingActivity(); return {}; } m_state = CLOSING; @@ -580,12 +585,14 @@ ExceptionOr<void> WebSocket::close(std::optional<unsigned short> optionalCode, c case ConnectedWebSocketKind::Client: { ZigString reasonZigStr = Zig::toZigString(reason); Bun__WebSocketClient__close(this->m_connectedWebSocket.client, code, &reasonZigStr); + updateHasPendingActivity(); // this->m_bufferedAmount = this->m_connectedWebSocket.client->getBufferedAmount(); break; } case ConnectedWebSocketKind::ClientSSL: { ZigString reasonZigStr = Zig::toZigString(reason); Bun__WebSocketClientTLS__close(this->m_connectedWebSocket.clientSSL, code, &reasonZigStr); + updateHasPendingActivity(); // this->m_bufferedAmount = this->m_connectedWebSocket.clientSSL->getBufferedAmount(); break; } @@ -604,7 +611,7 @@ ExceptionOr<void> WebSocket::close(std::optional<unsigned short> optionalCode, c } } this->m_connectedWebSocketKind = ConnectedWebSocketKind::None; - + updateHasPendingActivity(); return {}; } @@ -715,7 +722,6 @@ ScriptExecutionContext* WebSocket::scriptExecutionContext() const void WebSocket::didConnect() { // from new WebSocket() -> connect() - this->m_pendingActivityCount--; LOG(Network, "WebSocket %p didConnect()", this); // queueTaskKeepingObjectAlive(*this, TaskSource::WebSocket, [this] { @@ -730,10 +736,12 @@ void WebSocket::didConnect() if (auto* context = scriptExecutionContext()) { if (this->hasEventListeners("open"_s)) { + this->incPendingActivityCount(); // the main reason for dispatching on a separate tick is to handle when you haven't yet attached an event listener dispatchEvent(Event::create(eventNames().openEvent, Event::CanBubble::No, Event::IsCancelable::No)); + this->decPendingActivityCount(); } else { - this->m_pendingActivityCount++; + this->incPendingActivityCount(); context->postTask([this, protectedThis = Ref { *this }](ScriptExecutionContext& context) { ASSERT(scriptExecutionContext()); @@ -741,7 +749,7 @@ void WebSocket::didConnect() // m_extensions = m_channel->extensions(); protectedThis->dispatchEvent(Event::create(eventNames().openEvent, Event::CanBubble::No, Event::IsCancelable::No)); // }); - protectedThis->m_pendingActivityCount--; + protectedThis->decPendingActivityCount(); }); } } @@ -768,11 +776,11 @@ void WebSocket::didReceiveMessage(String&& message) } if (auto* context = scriptExecutionContext()) { - this->m_pendingActivityCount++; + this->incPendingActivityCount(); context->postTask([this, message_ = WTFMove(message), protectedThis = Ref { *this }](ScriptExecutionContext& context) { ASSERT(scriptExecutionContext()); protectedThis->dispatchEvent(MessageEvent::create(message_, protectedThis->m_url.string())); - protectedThis->m_pendingActivityCount--; + protectedThis->decPendingActivityCount(); }); } @@ -805,11 +813,11 @@ void WebSocket::didReceiveBinaryData(Vector<uint8_t>&& binaryData) if (auto* context = scriptExecutionContext()) { auto arrayBuffer = JSC::ArrayBuffer::create(binaryData.data(), binaryData.size()); - this->m_pendingActivityCount++; + this->incPendingActivityCount(); context->postTask([this, buffer = WTFMove(arrayBuffer), protectedThis = Ref { *this }](ScriptExecutionContext& context) { ASSERT(scriptExecutionContext()); protectedThis->dispatchEvent(MessageEvent::create(buffer, m_url.string())); - protectedThis->m_pendingActivityCount--; + protectedThis->decPendingActivityCount(); }); } @@ -827,10 +835,10 @@ void WebSocket::didReceiveMessageError(unsigned short code, WTF::StringImpl::Sta return; m_state = CLOSED; if (auto* context = scriptExecutionContext()) { - this->m_pendingActivityCount++; + this->incPendingActivityCount(); // https://html.spec.whatwg.org/multipage/web-sockets.html#feedback-from-the-protocol:concept-websocket-closed, we should synchronously fire a close event. dispatchEvent(CloseEvent::create(code < 1002, code, WTF::String(reason))); - this->m_pendingActivityCount--; + this->decPendingActivityCount(); } } @@ -849,6 +857,7 @@ void WebSocket::didStartClosingHandshake() if (m_state == CLOSED) return; m_state = CLOSING; + updateHasPendingActivity(); // }); } @@ -878,16 +887,19 @@ void WebSocket::didClose(unsigned unhandledBufferedAmount, unsigned short code, this->m_upgradeClient = nullptr; if (this->hasEventListeners("close"_s)) { + this->incPendingActivityCount(); this->dispatchEvent(CloseEvent::create(wasClean, code, reason)); + this->decPendingActivityCount(); + return; } if (auto* context = scriptExecutionContext()) { - this->m_pendingActivityCount++; + this->incPendingActivityCount(); context->postTask([this, code, wasClean, reason, protectedThis = Ref { *this }](ScriptExecutionContext& context) { ASSERT(scriptExecutionContext()); protectedThis->dispatchEvent(CloseEvent::create(wasClean, code, reason)); - protectedThis->m_pendingActivityCount--; + protectedThis->decPendingActivityCount(); }); } @@ -909,11 +921,11 @@ void WebSocket::dispatchErrorEventIfNeeded() m_dispatchedErrorEvent = true; if (auto* context = scriptExecutionContext()) { - this->m_pendingActivityCount++; + this->incPendingActivityCount(); context->postTask([this, protectedThis = Ref { *this }](ScriptExecutionContext& context) { ASSERT(scriptExecutionContext()); protectedThis->dispatchEvent(Event::create(eventNames().errorEvent, Event::CanBubble::No, Event::IsCancelable::No)); - protectedThis->m_pendingActivityCount--; + protectedThis->decPendingActivityCount(); }); } } @@ -936,10 +948,10 @@ void WebSocket::didConnect(us_socket_t* socket, char* bufferedData, size_t buffe void WebSocket::didFailWithErrorCode(int32_t code) { // from new WebSocket() -> connect() + if (m_state == CLOSED) return; - this->m_pendingActivityCount = this->m_pendingActivityCount > 0 ? this->m_pendingActivityCount - 1 : 0; this->m_upgradeClient = nullptr; this->m_connectedWebSocketKind = ConnectedWebSocketKind::None; this->m_connectedWebSocket.client = nullptr; @@ -1109,7 +1121,17 @@ void WebSocket::didFailWithErrorCode(int32_t code) } m_state = CLOSED; + scriptExecutionContext()->postTask([this, protectedThis = Ref { *this }](ScriptExecutionContext& context) { + protectedThis->decPendingActivityCount(); + }); } +void WebSocket::updateHasPendingActivity() +{ + std::atomic_thread_fence(std::memory_order_acquire); + m_hasPendingActivity.store( + !(m_state == CLOSED && m_pendingActivityCount == 0)); +} + } // namespace WebCore extern "C" void WebSocket__didConnect(WebCore::WebSocket* webSocket, us_socket_t* socket, char* bufferedData, size_t len) diff --git a/src/bun.js/bindings/webcore/WebSocket.h b/src/bun.js/bindings/webcore/WebSocket.h index 796268d7a..82de58333 100644 --- a/src/bun.js/bindings/webcore/WebSocket.h +++ b/src/bun.js/bindings/webcore/WebSocket.h @@ -66,7 +66,6 @@ public: OPEN = 1, CLOSING = 2, CLOSED = 3, - }; ExceptionOr<void> connect(const String& url); @@ -103,9 +102,10 @@ public: void didReceiveData(const char* data, size_t length); void didReceiveBinaryData(Vector<uint8_t>&&); + void updateHasPendingActivity(); bool hasPendingActivity() const { - return m_state == State::OPEN || m_state == State::CLOSING || m_pendingActivityCount > 0; + return m_hasPendingActivity.load(); } private: @@ -119,6 +119,8 @@ private: ClientSSL, }; + std::atomic<bool> m_hasPendingActivity { true }; + explicit WebSocket(ScriptExecutionContext&); explicit WebSocket(ScriptExecutionContext&, const String& url); @@ -142,6 +144,20 @@ private: void sendWebSocketString(const String& message); void sendWebSocketData(const char* data, size_t length); + void incPendingActivityCount() + { + m_pendingActivityCount++; + ref(); + updateHasPendingActivity(); + } + + void decPendingActivityCount() + { + m_pendingActivityCount--; + deref(); + updateHasPendingActivity(); + } + void failAsynchronously(); enum class BinaryType { Blob, diff --git a/src/bun.js/builtins/cpp/ReadableStreamDefaultReaderBuiltins.cpp b/src/bun.js/builtins/cpp/ReadableStreamDefaultReaderBuiltins.cpp index b0691d4d8..9504549e0 100644 --- a/src/bun.js/builtins/cpp/ReadableStreamDefaultReaderBuiltins.cpp +++ b/src/bun.js/builtins/cpp/ReadableStreamDefaultReaderBuiltins.cpp @@ -94,7 +94,7 @@ const char* const s_readableStreamDefaultReaderCancelCode = const JSC::ConstructAbility s_readableStreamDefaultReaderReadManyCodeConstructAbility = JSC::ConstructAbility::CannotConstruct; const JSC::ConstructorKind s_readableStreamDefaultReaderReadManyCodeConstructorKind = JSC::ConstructorKind::None; const JSC::ImplementationVisibility s_readableStreamDefaultReaderReadManyCodeImplementationVisibility = JSC::ImplementationVisibility::Public; -const int s_readableStreamDefaultReaderReadManyCodeLength = 4297; +const int s_readableStreamDefaultReaderReadManyCodeLength = 4743; static const JSC::Intrinsic s_readableStreamDefaultReaderReadManyCodeIntrinsic = JSC::NoIntrinsic; const char* const s_readableStreamDefaultReaderReadManyCode = "(function ()\n" \ @@ -126,11 +126,14 @@ const char* const s_readableStreamDefaultReaderReadManyCode = " return controller.@pull(\n" \ " controller\n" \ " ).@then(\n" \ - " ({done, value}) => (\n" \ - " done ? \n" \ - " { done: true, value: [], size: 0 } : \n" \ - " { value: [value], size: 1, done: false }\n" \ - " ));\n" \ + " function({done, value}) {\n" \ + " return (\n" \ + " done ? \n" \ + " { done: true, value: [], size: 0 } : \n" \ + " { value: [value], size: 1, done: false }\n" \ + " );\n" \ + " }\n" \ + " );\n" \ " }\n" \ "\n" \ " const content = queue.content;\n" \ @@ -142,7 +145,17 @@ const char* const s_readableStreamDefaultReaderReadManyCode = " if (length > 0) {\n" \ " var outValues = @newArrayWithSize(length);\n" \ " if (@isReadableByteStreamController(controller)) {\n" \ - " for (var i = 0; i < length; i++) {\n" \ + "\n" \ + " {\n" \ + " const buf = values[0];\n" \ + " if (!(@ArrayBuffer.@isView(buf) || buf instanceof @ArrayBuffer)) {\n" \ + " @putByValDirect(outValues, 0, new @Uint8Array(buf.buffer, buf.byteOffset, buf.byteLength));\n" \ + " } else {\n" \ + " @putByValDirect(outValues, 0, buf);\n" \ + " }\n" \ + " }\n" \ + "\n" \ + " for (var i = 1; i < length; i++) {\n" \ " const buf = values[i];\n" \ " if (!(@ArrayBuffer.@isView(buf) || buf instanceof @ArrayBuffer)) {\n" \ " @putByValDirect(outValues, i, new @Uint8Array(buf.buffer, buf.byteOffset, buf.byteLength));\n" \ @@ -150,6 +163,7 @@ const char* const s_readableStreamDefaultReaderReadManyCode = " @putByValDirect(outValues, i, buf);\n" \ " }\n" \ " }\n" \ + "\n" \ " } else {\n" \ " @putByValDirect(outValues, 0, values[0].value);\n" \ " for (var i = 1; i < length; i++) {\n" \ diff --git a/src/bun.js/builtins/cpp/ReadableStreamInternalsBuiltins.cpp b/src/bun.js/builtins/cpp/ReadableStreamInternalsBuiltins.cpp index c5e41ee2c..f2a3d5a55 100644 --- a/src/bun.js/builtins/cpp/ReadableStreamInternalsBuiltins.cpp +++ b/src/bun.js/builtins/cpp/ReadableStreamInternalsBuiltins.cpp @@ -986,7 +986,7 @@ const char* const s_readableStreamInternalsIsReadableStreamDefaultControllerCode const JSC::ConstructAbility s_readableStreamInternalsReadDirectStreamCodeConstructAbility = JSC::ConstructAbility::CannotConstruct; const JSC::ConstructorKind s_readableStreamInternalsReadDirectStreamCodeConstructorKind = JSC::ConstructorKind::None; const JSC::ImplementationVisibility s_readableStreamInternalsReadDirectStreamCodeImplementationVisibility = JSC::ImplementationVisibility::Public; -const int s_readableStreamInternalsReadDirectStreamCodeLength = 1623; +const int s_readableStreamInternalsReadDirectStreamCodeLength = 1557; static const JSC::Intrinsic s_readableStreamInternalsReadDirectStreamCodeIntrinsic = JSC::NoIntrinsic; const char* const s_readableStreamInternalsReadDirectStreamCode = "(function (stream, sink, underlyingSource) {\n" \ @@ -995,10 +995,6 @@ const char* const s_readableStreamInternalsReadDirectStreamCode = " @putByIdDirectPrivate(stream, \"underlyingSource\", @undefined);\n" \ " @putByIdDirectPrivate(stream, \"start\", @undefined);\n" \ "\n" \ - "\n" \ - " var capturedStream = stream;\n" \ - " var reader;\n" \ - "\n" \ " function close(stream, reason) {\n" \ " if (reason && underlyingSource?.cancel) {\n" \ " try {\n" \ @@ -1019,7 +1015,7 @@ const char* const s_readableStreamInternalsReadDirectStreamCode = " } else {\n" \ " @putByIdDirectPrivate(stream, \"state\", @streamClosed);\n" \ " }\n" \ - " \n" \ + " stream = @undefined;\n" \ " }\n" \ " }\n" \ "\n" \ @@ -1056,6 +1052,7 @@ const char* const s_readableStreamInternalsReadDirectStreamCode = " return maybePromise.@then(() => {});\n" \ " }\n" \ "\n" \ + "\n" \ "})\n" \ ; diff --git a/src/bun.js/builtins/cpp/StreamInternalsBuiltins.cpp b/src/bun.js/builtins/cpp/StreamInternalsBuiltins.cpp index 7886b5678..a957a7c2b 100644 --- a/src/bun.js/builtins/cpp/StreamInternalsBuiltins.cpp +++ b/src/bun.js/builtins/cpp/StreamInternalsBuiltins.cpp @@ -362,16 +362,13 @@ const char* const s_streamInternalsEnqueueValueWithSizeCode = const JSC::ConstructAbility s_streamInternalsPeekQueueValueCodeConstructAbility = JSC::ConstructAbility::CannotConstruct; const JSC::ConstructorKind s_streamInternalsPeekQueueValueCodeConstructorKind = JSC::ConstructorKind::None; const JSC::ImplementationVisibility s_streamInternalsPeekQueueValueCodeImplementationVisibility = JSC::ImplementationVisibility::Public; -const int s_streamInternalsPeekQueueValueCodeLength = 116; +const int s_streamInternalsPeekQueueValueCodeLength = 81; static const JSC::Intrinsic s_streamInternalsPeekQueueValueCodeIntrinsic = JSC::NoIntrinsic; const char* const s_streamInternalsPeekQueueValueCode = "(function (queue)\n" \ "{\n" \ " \"use strict\";\n" \ - "\n" \ - " @assert(queue.content.isNotEmpty());\n" \ - "\n" \ - " return queue.peek()?.value;\n" \ + " return queue.content.peek()?.value;\n" \ "})\n" \ ; diff --git a/src/bun.js/builtins/js/ReadableStreamDefaultReader.js b/src/bun.js/builtins/js/ReadableStreamDefaultReader.js index e93e89e22..77da965ed 100644 --- a/src/bun.js/builtins/js/ReadableStreamDefaultReader.js +++ b/src/bun.js/builtins/js/ReadableStreamDefaultReader.js @@ -80,11 +80,14 @@ function readMany() return controller.@pull( controller ).@then( - ({done, value}) => ( - done ? - { done: true, value: [], size: 0 } : - { value: [value], size: 1, done: false } - )); + function({done, value}) { + return ( + done ? + { done: true, value: [], size: 0 } : + { value: [value], size: 1, done: false } + ); + } + ); } const content = queue.content; @@ -96,7 +99,17 @@ function readMany() if (length > 0) { var outValues = @newArrayWithSize(length); if (@isReadableByteStreamController(controller)) { - for (var i = 0; i < length; i++) { + + { + const buf = values[0]; + if (!(@ArrayBuffer.@isView(buf) || buf instanceof @ArrayBuffer)) { + @putByValDirect(outValues, 0, new @Uint8Array(buf.buffer, buf.byteOffset, buf.byteLength)); + } else { + @putByValDirect(outValues, 0, buf); + } + } + + for (var i = 1; i < length; i++) { const buf = values[i]; if (!(@ArrayBuffer.@isView(buf) || buf instanceof @ArrayBuffer)) { @putByValDirect(outValues, i, new @Uint8Array(buf.buffer, buf.byteOffset, buf.byteLength)); @@ -104,6 +117,7 @@ function readMany() @putByValDirect(outValues, i, buf); } } + } else { @putByValDirect(outValues, 0, values[0].value); for (var i = 1; i < length; i++) { diff --git a/src/bun.js/builtins/js/ReadableStreamInternals.js b/src/bun.js/builtins/js/ReadableStreamInternals.js index 257bb1855..def4d51a3 100644 --- a/src/bun.js/builtins/js/ReadableStreamInternals.js +++ b/src/bun.js/builtins/js/ReadableStreamInternals.js @@ -795,10 +795,6 @@ function readDirectStream(stream, sink, underlyingSource) { @putByIdDirectPrivate(stream, "underlyingSource", @undefined); @putByIdDirectPrivate(stream, "start", @undefined); - - var capturedStream = stream; - var reader; - function close(stream, reason) { if (reason && underlyingSource?.cancel) { try { @@ -819,7 +815,7 @@ function readDirectStream(stream, sink, underlyingSource) { } else { @putByIdDirectPrivate(stream, "state", @streamClosed); } - + stream = @undefined; } } @@ -856,6 +852,7 @@ function readDirectStream(stream, sink, underlyingSource) { return maybePromise.@then(() => {}); } + } @linkTimeConstant; diff --git a/src/bun.js/builtins/js/StreamInternals.js b/src/bun.js/builtins/js/StreamInternals.js index 5e447c29c..78bcdcfb3 100644 --- a/src/bun.js/builtins/js/StreamInternals.js +++ b/src/bun.js/builtins/js/StreamInternals.js @@ -256,10 +256,7 @@ function enqueueValueWithSize(queue, value, size) function peekQueueValue(queue) { "use strict"; - - @assert(queue.content.isNotEmpty()); - - return queue.peek()?.value; + return queue.content.peek()?.value; } function resetQueue(queue) diff --git a/src/bun.js/event_loop.zig b/src/bun.js/event_loop.zig index 90c63af2b..22a016862 100644 --- a/src/bun.js/event_loop.zig +++ b/src/bun.js/event_loop.zig @@ -31,7 +31,7 @@ pub fn ConcurrentPromiseTask(comptime Context: type) type { task: WorkPoolTask = .{ .callback = runFromThreadPool }, event_loop: *JSC.EventLoop, allocator: std.mem.Allocator, - promise: JSValue, + promise: JSC.JSPromise.Strong = .{}, globalThis: *JSGlobalObject, concurrent_task: JSC.ConcurrentTask = .{}, @@ -44,10 +44,10 @@ pub fn ConcurrentPromiseTask(comptime Context: type) type { .event_loop = VirtualMachine.vm.event_loop, .ctx = value, .allocator = allocator, - .promise = JSValue.createInternalPromise(globalThis), .globalThis = globalThis, }; - this.promise.protect(); + var promise = JSC.JSPromise.create(globalThis); + this.promise.strong.set(globalThis, promise.asValue(globalThis)); this.ref.ref(this.event_loop.virtual_machine); return this; @@ -60,19 +60,9 @@ pub fn ConcurrentPromiseTask(comptime Context: type) type { } pub fn runFromJS(this: *This) void { - var promise_value = this.promise; + var promise = this.promise.swap(); this.ref.unref(this.event_loop.virtual_machine); - promise_value.ensureStillAlive(); - promise_value.unprotect(); - - var promise = promise_value.asInternalPromise() orelse { - if (comptime @hasDecl(Context, "deinit")) { - @call(.{}, Context.deinit, .{this.ctx}); - } - return; - }; - var ctx = this.ctx; ctx.then(promise); @@ -340,8 +330,9 @@ pub const EventLoop = struct { } pub fn autoTick(this: *EventLoop) void { - if (this.virtual_machine.uws_event_loop.?.num_polls > 0 or this.virtual_machine.uws_event_loop.?.active > 0) { - this.virtual_machine.uws_event_loop.?.tick(); + var loop = this.virtual_machine.uws_event_loop.?; + if (loop.num_polls > 0 or loop.active > 0) { + loop.tick(); // this.afterUSocketsTick(); } } @@ -392,6 +383,7 @@ pub const EventLoop = struct { this.start_server_on_next_tick = false; ctx.enterUWSLoop(); ctx.is_us_loop_entered = false; + ctx.autoGarbageCollect(); } } diff --git a/src/bun.js/javascript.zig b/src/bun.js/javascript.zig index fe559fac8..7e4ae9ed5 100644 --- a/src/bun.js/javascript.zig +++ b/src/bun.js/javascript.zig @@ -40,7 +40,7 @@ const ImportKind = ast.ImportKind; const Analytics = @import("../analytics/analytics_thread.zig"); const ZigString = @import("../jsc.zig").ZigString; const Runtime = @import("../runtime.zig"); -const Router = @import("./api/router.zig"); +const Router = @import("./api/filesystem_router.zig"); const ImportRecord = ast.ImportRecord; const DotEnv = @import("../env_loader.zig"); const PackageJSON = @import("../resolver/package_json.zig").PackageJSON; @@ -313,7 +313,13 @@ pub export fn Bun__queueTaskConcurrently(global: *JSGlobalObject, task: *JSC.Cpp pub export fn Bun__handleRejectedPromise(global: *JSGlobalObject, promise: *JSC.JSPromise) void { const result = promise.result(global.vm()); var jsc_vm = global.bunVM(); + + // this seems to happen in some cases when GC is running + if (result == .zero) + return; + jsc_vm.onUnhandledError(global, result); + jsc_vm.autoGarbageCollect(); } pub export fn Bun__onDidAppendPlugin(jsc_vm: *VirtualMachine, globalObject: *JSGlobalObject) void { @@ -428,6 +434,13 @@ pub const VirtualMachine = struct { unhandled_error_counter: usize = 0, modules: ModuleLoader.AsyncModule.Queue = .{}, + aggressive_garbage_collection: GCLevel = GCLevel.none, + + pub const GCLevel = enum(u3) { + none = 0, + mild = 1, + aggressive = 2, + }; pub threadlocal var is_main_thread_vm: bool = false; @@ -435,6 +448,27 @@ pub const VirtualMachine = struct { this.onUnhandledRejection = defaultOnUnhandledRejection; } + pub fn loadExtraEnv(this: *VirtualMachine) void { + var map = this.bundler.env.map; + + if (map.get("BUN_SHOW_BUN_STACKFRAMES") != null) + this.hide_bun_stackframes = false; + + if (map.get("BUN_OVERRIDE_MODULE_PATH")) |override_path| { + if (override_path.len > 0) { + this.load_builtins_from_path = override_path; + } + } + + if (map.get("BUN_GARBAGE_COLLECTOR_LEVEL")) |gc_level| { + if (strings.eqlComptime(gc_level, "1")) { + this.aggressive_garbage_collection = .mild; + } else if (strings.eqlComptime(gc_level, "2")) { + this.aggressive_garbage_collection = .aggressive; + } + } + } + pub fn onUnhandledError(this: *JSC.VirtualMachine, globalObject: *JSC.JSGlobalObject, value: JSC.JSValue) void { this.unhandled_error_counter += 1; this.onUnhandledRejection(this, globalObject, value); @@ -448,6 +482,22 @@ pub const VirtualMachine = struct { return this.bundler.getPackageManager(); } + pub fn garbageCollect(this: *const VirtualMachine, sync: bool) JSValue { + @setCold(true); + Global.mimalloc_cleanup(false); + if (sync) + return this.global.vm().runGC(true); + + this.global.vm().collectAsync(); + return JSValue.jsNumber(this.global.vm().heapSize()); + } + + pub inline fn autoGarbageCollect(this: *const VirtualMachine) void { + if (this.aggressive_garbage_collection != .none) { + _ = this.garbageCollect(this.aggressive_garbage_collection == .aggressive); + } + } + pub fn reload(this: *VirtualMachine) void { Output.debug("Reloading...", .{}); this.global.reload(); @@ -677,9 +727,6 @@ pub const VirtualMachine = struct { VirtualMachine.vm.bundler.configureLinker(); try VirtualMachine.vm.bundler.configureFramework(false); - if (VirtualMachine.vm.bundler.env.get("BUN_SHOW_BUN_STACKFRAMES") != null) - VirtualMachine.vm.hide_bun_stackframes = false; - vm.bundler.macro_context = js_ast.Macro.MacroContext.init(&vm.bundler); if (_args.serve orelse false) { diff --git a/src/bun.js/module_loader.zig b/src/bun.js/module_loader.zig index 59a4288fb..f991a9e30 100644 --- a/src/bun.js/module_loader.zig +++ b/src/bun.js/module_loader.zig @@ -40,7 +40,7 @@ const ImportKind = ast.ImportKind; const Analytics = @import("../analytics/analytics_thread.zig"); const ZigString = @import("../jsc.zig").ZigString; const Runtime = @import("../runtime.zig"); -const Router = @import("./api/router.zig"); +const Router = @import("./api/filesystem_router.zig"); const ImportRecord = ast.ImportRecord; const DotEnv = @import("../env_loader.zig"); const PackageJSON = @import("../resolver/package_json.zig").PackageJSON; @@ -547,6 +547,7 @@ pub const ModuleLoader = struct { } pub fn onDone(this: *AsyncModule) void { + JSC.markBinding(@src()); var jsc_vm = this.globalThis.bunVM(); jsc_vm.modules.scheduled -= 1; if (jsc_vm.modules.scheduled == 0) { diff --git a/src/bun.js/scripts/generate-classes.ts b/src/bun.js/scripts/generate-classes.ts index 879d844a6..05b092656 100644 --- a/src/bun.js/scripts/generate-classes.ts +++ b/src/bun.js/scripts/generate-classes.ts @@ -352,9 +352,8 @@ void ${proto}::finishCreation(JSC::VM& vm, JSC::JSGlobalObject* globalObject) `; } -function generateConstructorHeader(typeName) { - const name = constructorName(typeName); - const proto = prototypeName(typeName); +function generatePrototypeHeader(typename) { + const proto = prototypeName(typename); return ` class ${proto} final : public JSC::JSNonFinalObject { @@ -386,8 +385,13 @@ function generateConstructorHeader(typeName) { } void finishCreation(JSC::VM&, JSC::JSGlobalObject*); - }; - + };`; +} + +function generateConstructorHeader(typeName) { + const name = constructorName(typeName); + + return ` class ${name} final : public JSC::InternalFunction { public: using Base = JSC::InternalFunction; @@ -488,6 +492,7 @@ ${name}* ${name}::create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::St return ptr; } + JSC::EncodedJSValue JSC_HOST_CALL_ATTRIBUTES ${name}::construct(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame) { Zig::GlobalObject *globalObject = reinterpret_cast<Zig::GlobalObject*>(lexicalGlobalObject); @@ -534,23 +539,6 @@ JSC::EncodedJSValue JSC_HOST_CALL_ATTRIBUTES ${name}::construct(JSC::JSGlobalObj return JSValue::encode(instance); } -extern "C" EncodedJSValue ${typeName}__create(Zig::GlobalObject* globalObject, void* ptr) { - auto &vm = globalObject->vm(); - JSC::Structure* structure = globalObject->${className(typeName)}Structure(); - ${className(typeName)}* instance = ${className( - typeName, - )}::create(vm, globalObject, structure, ptr); - ${ - obj.estimatedSize - ? `vm.heap.reportExtraMemoryAllocated(${symbolName( - obj.name, - "estimatedSize", - )}(ptr));` - : "" - } - return JSValue::encode(instance); -} - void ${name}::initializeProperties(VM& vm, JSC::JSGlobalObject* globalObject, ${prototypeName( typeName, )}* prototype) @@ -823,7 +811,7 @@ JSC_DEFINE_CUSTOM_GETTER(${symbolName( typeName, proto[name].getter, )}(thisObject->wrapped(),${ - proto[name].this!! ? " thisValue, " : "" + !!proto[name].this ? " thisValue, " : "" } globalObject); RETURN_IF_EXCEPTION(throwScope, {}); RELEASE_AND_RETURN(throwScope, result); @@ -852,7 +840,7 @@ JSC_DEFINE_CUSTOM_SETTER(${symbolName( typeName, proto[name].setter || proto[name].accessor.setter, )}(thisObject->wrapped(),${ - proto[name].this!! ? " thisValue, " : "" + !!proto[name].this ? " thisValue, " : "" } lexicalGlobalObject, encodedValue); RELEASE_AND_RETURN(throwScope, result); @@ -908,47 +896,48 @@ function generateClassHeader(typeName, obj: ClassDefinition) { const DECLARE_VISIT_CHILDREN = values.length || obj.estimatedSize || + obj.hasPendingActivity || [...Object.values(klass), ...Object.values(proto)].find((a) => !!a.cache) - ? "DECLARE_VISIT_CHILDREN;" + ? "DECLARE_VISIT_CHILDREN;\ntemplate<typename Visitor> void visitAdditionalChildren(Visitor&);\nDECLARE_VISIT_OUTPUT_CONSTRAINTS;\n" : ""; const sizeEstimator = obj.estimatedSize ? "static size_t estimatedSize(JSCell* cell, VM& vm);" : ""; var weakOwner = ""; - var weakInit = ""; - + var weakInit = ``; if (obj.hasPendingActivity) { + weakInit = `m_weakThis = JSC::Weak<${name}>(this, getOwner());`; weakOwner = ` - JSC::Weak<${name}> m_weakThis; - bool internalHasPendingActivity(); - bool hasPendingActivity() { - if (!m_ctx) - return false; - - return this->internalHasPendingActivity(); + JSC::Weak<${name}> m_weakThis; + + + static bool hasPendingActivity(void* ctx); + + class Owner final : public JSC::WeakHandleOwner { + public: + bool isReachableFromOpaqueRoots(JSC::Handle<JSC::Unknown> handle, void* context, JSC::AbstractSlotVisitor& visitor, const char** reason) final + { + auto* controller = JSC::jsCast<${name}*>(handle.slot()->asCell()); + if (${name}::hasPendingActivity(controller->wrapped())) { + if (UNLIKELY(reason)) + *reason = "has pending activity"; + return true; + } + + return visitor.containsOpaqueRoot(context); + } + void finalize(JSC::Handle<JSC::Unknown>, void* context) final {} + }; + + static JSC::WeakHandleOwner* getOwner() + { + static NeverDestroyed<Owner> m_owner; + return &m_owner.get(); } - - class Owner final : public JSC::WeakHandleOwner { - public: - bool isReachableFromOpaqueRoots(JSC::Handle<JSC::Unknown> handle, void* context, JSC::AbstractSlotVisitor&, const char**) final - { - auto* controller = JSC::jsCast<${name}*>(handle.slot()->asCell()); - return controller->hasPendingActivity(); - } - void finalize(JSC::Handle<JSC::Unknown>, void* context) final {} - }; - - static JSC::WeakHandleOwner* getOwner() - { - static NeverDestroyed<Owner> m_owner; - return &m_owner.get(); - } `; - weakInit = ` - m_weakThis = JSC::Weak<${name}>(this, getOwner()); -`; } + return ` class ${name} final : public JSC::JSDestructibleObject { public: @@ -983,7 +972,11 @@ function generateClassHeader(typeName, obj: ClassDefinition) { } static JSObject* createPrototype(VM& vm, JSDOMGlobalObject* globalObject); - static JSObject* createConstructor(VM& vm, JSGlobalObject* globalObject, JSValue prototype); + ${ + obj.noConstructor + ? "" + : `static JSObject* createConstructor(VM& vm, JSGlobalObject* globalObject, JSValue prototype)` + }; ~${name}(); @@ -1046,7 +1039,12 @@ function generateClassImpl(typeName, obj: ClassDefinition) { }) .join("\n"); var DEFINE_VISIT_CHILDREN = ""; - if (DEFINE_VISIT_CHILDREN_LIST.length || estimatedSize || values.length) { + if ( + DEFINE_VISIT_CHILDREN_LIST.length || + estimatedSize || + values.length || + hasPendingActivity + ) { DEFINE_VISIT_CHILDREN = ` template<typename Visitor> void ${name}::visitChildrenImpl(JSCell* cell, Visitor& visitor) @@ -1063,9 +1061,33 @@ visitor.reportExtraMemoryVisited(${symbolName(obj.name, "estimatedSize")}(ptr)); : "" } ${DEFINE_VISIT_CHILDREN_LIST} +${hasPendingActivity ? `visitor.addOpaqueRoot(thisObject->wrapped());` : ""} } DEFINE_VISIT_CHILDREN(${name}); + +template<typename Visitor> +void ${name}::visitAdditionalChildren(Visitor& visitor) +{ + ${name}* thisObject = this; + ASSERT_GC_OBJECT_INHERITS(thisObject, info()); + ${values} + ${DEFINE_VISIT_CHILDREN_LIST} + ${hasPendingActivity ? "visitor.addOpaqueRoot(this->wrapped())" : ""}; +} + +DEFINE_VISIT_ADDITIONAL_CHILDREN(${name}); + +template<typename Visitor> +void ${name}::visitOutputConstraintsImpl(JSCell *cell, Visitor& visitor) +{ + ${name}* thisObject = jsCast<${name}*>(cell); + ASSERT_GC_OBJECT_INHERITS(thisObject, info()); + thisObject->visitAdditionalChildren<Visitor>(visitor); +} + +DEFINE_VISIT_OUTPUT_CONSTRAINTS(${name}); + `.trim(); } @@ -1074,8 +1096,8 @@ DEFINE_VISIT_CHILDREN(${name}); if (hasPendingActivity) { output += ` extern "C" bool ${symbolName(typeName, "hasPendingActivity")}(void* ptr); - bool ${name}::internalHasPendingActivity() { - return ${symbolName(typeName, "hasPendingActivity")}(m_ctx); + bool ${name}::hasPendingActivity(void* ctx) { + return ${symbolName(typeName, "hasPendingActivity")}(ctx); } `; } @@ -1162,15 +1184,19 @@ void ${name}::analyzeHeap(JSCell* cell, HeapAnalyzer& analyzer) Base::analyzeHeap(cell, analyzer); } -JSObject* ${name}::createConstructor(VM& vm, JSGlobalObject* globalObject, JSValue prototype) +${ + !obj.noConstructor + ? `JSObject* ${name}::createConstructor(VM& vm, JSGlobalObject* globalObject, JSValue prototype) { return WebCore::${constructorName( typeName, )}::create(vm, globalObject, WebCore::${constructorName( - typeName, - )}::createStructure(vm, globalObject, globalObject->functionPrototype()), jsCast<WebCore::${prototypeName( - typeName, - )}*>(prototype)); + typeName, + )}::createStructure(vm, globalObject, globalObject->functionPrototype()), jsCast<WebCore::${prototypeName( + typeName, + )}*>(prototype)); +}` + : "" } JSObject* ${name}::createPrototype(VM& vm, JSDOMGlobalObject* globalObject) @@ -1179,8 +1205,27 @@ JSObject* ${name}::createPrototype(VM& vm, JSDOMGlobalObject* globalObject) typeName, )}::createStructure(vm, globalObject, globalObject->objectPrototype())); } - + +extern "C" EncodedJSValue ${typeName}__create(Zig::GlobalObject* globalObject, void* ptr) { + auto &vm = globalObject->vm(); + JSC::Structure* structure = globalObject->${className(typeName)}Structure(); + ${className(typeName)}* instance = ${className( + typeName, + )}::create(vm, globalObject, structure, ptr); + ${ + obj.estimatedSize + ? `vm.heap.reportExtraMemoryAllocated(${symbolName( + obj.name, + "estimatedSize", + )}(ptr));` + : "" + } + return JSValue::encode(instance); +} + ${DEFINE_VISIT_CHILDREN} + + `.trim(); @@ -1188,13 +1233,16 @@ ${DEFINE_VISIT_CHILDREN} } function generateHeader(typeName, obj) { - return generateClassHeader(typeName, obj).trim(); + return generateClassHeader(typeName, obj).trim() + "\n\n"; } function generateImpl(typeName, obj) { const proto = obj.proto; return [ - generateConstructorHeader(typeName).trim() + "\n", + generatePrototypeHeader(typeName), + !obj.noConstructor + ? generateConstructorHeader(typeName).trim() + "\n" + : null, Object.keys(proto).length > 0 && generatePrototype(typeName, obj).trim(), !obj.noConstructor ? generateConstructorImpl(typeName, obj).trim() : null, Object.keys(proto).length > 0 && generateClassImpl(typeName, obj).trim(), @@ -1210,7 +1258,7 @@ function generateZig( proto = {}, construct, finalize, - noConstructor, + noConstructor = false, estimatedSize, call = false, values = [], @@ -1219,7 +1267,7 @@ function generateZig( ) { const exports = new Map<string, string>(); - if (construct) { + if (construct && !noConstructor) { exports.set(`constructor`, classSymbolName(typeName, "construct")); } @@ -1307,7 +1355,7 @@ function generateZig( `; } - if (construct) { + if (construct && !noConstructor) { output += ` if (@TypeOf(${typeName}.constructor) != (fn(*JSC.JSGlobalObject, *JSC.CallFrame) callconv(.C) ?*${typeName})) { @compileLog("${typeName}.constructor is not a constructor"); @@ -1573,7 +1621,10 @@ function generateLazyStructureImpl(typeName, { klass = {}, proto = {} }) { `.trim(); } -function generateLazyClassStructureImpl(typeName, { klass = {}, proto = {} }) { +function generateLazyClassStructureImpl( + typeName, + { klass = {}, proto = {}, noConstructor = false }, +) { return ` m_${className(typeName)}.initLater( [](LazyClassStructure::Initializer& init) { @@ -1583,9 +1634,13 @@ function generateLazyClassStructureImpl(typeName, { klass = {}, proto = {} }) { init.setStructure(WebCore::${className( typeName, )}::createStructure(init.vm, init.global, init.prototype)); - init.setConstructor(WebCore::${className( - typeName, - )}::createConstructor(init.vm, init.global, init.prototype)); + ${ + noConstructor + ? "" + : `init.setConstructor(WebCore::${className( + typeName, + )}::createConstructor(init.vm, init.global, init.prototype));` + } }); @@ -1620,15 +1675,16 @@ const GENERATED_CLASSES_IMPL_HEADER = ` // GENERATED CODE - DO NOT MODIFY BY HAND // Generated by make codegen #include "root.h" - + +#include "BunClientData.h" +#include "ZigGlobalObject.h" + #include <JavaScriptCore/JSFunction.h> #include <JavaScriptCore/InternalFunction.h> #include <JavaScriptCore/LazyClassStructure.h> #include <JavaScriptCore/LazyClassStructureInlines.h> #include <JavaScriptCore/FunctionPrototype.h> -#include "ZigGlobalObject.h" - #include <JavaScriptCore/DOMJITAbstractHeap.h> #include "DOMJITIDLConvert.h" #include "DOMJITIDLType.h" @@ -1706,6 +1762,7 @@ function findClasses() { readdirSync(directory).forEach((file) => { if (file.endsWith(".classes.ts")) { const result = require(`${directory}/${file}`); + if (!(result?.default?.length ?? 0)) return; console.log("Generated", result.default.length, "classes from", file); for (let { name } of result.default) { console.log(` - ${name}`); @@ -1751,13 +1808,7 @@ await writeAndUnlink(`${import.meta.dir}/../bindings/ZigGeneratedClasses.cpp`, [ ]); await writeAndUnlink( `${import.meta.dir}/../bindings/ZigGeneratedClasses+lazyStructureHeader.h`, - classes - .map((a) => - !a.noConstructor - ? generateLazyClassStructureHeader(a.name, a) - : generateLazyStructureHeader(a.name, a), - ) - .join("\n"), + classes.map((a) => generateLazyClassStructureHeader(a.name, a)).join("\n"), ); await writeAndUnlink( @@ -1789,11 +1840,7 @@ await writeAndUnlink( await writeAndUnlink( `${import.meta.dir}/../bindings/ZigGeneratedClasses+lazyStructureImpl.h`, initLazyClasses( - classes.map((a) => - !a.noConstructor - ? generateLazyClassStructureImpl(a.name, a) - : generateLazyStructureImpl(a.name, a), - ), + classes.map((a) => generateLazyClassStructureImpl(a.name, a)), ) + "\n" + visitLazyClasses(classes), diff --git a/src/bun.js/scripts/generate-jssink.js b/src/bun.js/scripts/generate-jssink.js index 0e9d3bb50..174efcb06 100644 --- a/src/bun.js/scripts/generate-jssink.js +++ b/src/bun.js/scripts/generate-jssink.js @@ -96,7 +96,8 @@ function header() { ~${className}(); - void* wrapped() const { return m_sinkPtr; } + void* wrapped() const { return m_sinkPtr; } + DECLARE_VISIT_CHILDREN; void detach() { m_sinkPtr = nullptr; @@ -154,41 +155,19 @@ function header() { DECLARE_VISIT_CHILDREN; static void analyzeHeap(JSCell*, JSC::HeapAnalyzer&); - - bool hasPendingActivity() { return m_hasPendingActivity; } void* m_sinkPtr; - bool m_hasPendingActivity; mutable WriteBarrier<JSC::JSFunction> m_onPull; mutable WriteBarrier<JSC::JSFunction> m_onClose; mutable JSC::Weak<JSObject> m_weakReadableStream; - JSC::Weak<${controller}> m_weakThis; ${controller}(JSC::VM& vm, JSC::Structure* structure, void* sinkPtr) : Base(vm, structure) { m_sinkPtr = sinkPtr; - m_hasPendingActivity = true; - m_weakThis = JSC::Weak<${controller}>(this, getOwner()); } void finishCreation(JSC::VM&); - - class Owner final : public JSC::WeakHandleOwner { - public: - bool isReachableFromOpaqueRoots(JSC::Handle<JSC::Unknown> handle, void* context, JSC::AbstractSlotVisitor&, const char**) final - { - auto* controller = JSC::jsCast<${controller}*>(handle.slot()->asCell()); - return controller->hasPendingActivity(); - } - void finalize(JSC::Handle<JSC::Unknown>, void* context) final {} - }; - - static JSC::WeakHandleOwner* getOwner() - { - static NeverDestroyed<Owner> m_owner; - return &m_owner.get(); - } }; JSC_DECLARE_CUSTOM_GETTER(function${name}__getter); @@ -405,8 +384,6 @@ JSC_DEFINE_HOST_FUNCTION(${controller}__close, (JSC::JSGlobalObject * lexicalGlo controller->detach(); ${name}__close(lexicalGlobalObject, ptr); - // Release the controller right before close. - controller->m_hasPendingActivity = false; return JSC::JSValue::encode(JSC::jsUndefined()); } @@ -643,7 +620,7 @@ void JS${controllerName}::detach() { auto readableStream = m_weakReadableStream.get(); auto onClose = m_onClose.get(); m_onClose.clear(); - + if (readableStream && onClose) { JSC::JSGlobalObject *globalObject = this->globalObject(); auto callData = JSC::getCallData(onClose); @@ -760,11 +737,26 @@ void ${controller}::visitChildrenImpl(JSCell* cell, Visitor& visitor) Base::visitChildren(thisObject, visitor); visitor.append(thisObject->m_onPull); visitor.append(thisObject->m_onClose); - visitor.append(thisObject->m_weakReadableStream); + void* ptr = thisObject->m_sinkPtr; + if (ptr) + visitor.addOpaqueRoot(ptr); } DEFINE_VISIT_CHILDREN(${controller}); +template<typename Visitor> +void ${className}::visitChildrenImpl(JSCell* cell, Visitor& visitor) +{ + ${className}* thisObject = jsCast<${className}*>(cell); + ASSERT_GC_OBJECT_INHERITS(thisObject, info()); + Base::visitChildren(thisObject, visitor); + void* ptr = thisObject->m_sinkPtr; + if (ptr) + visitor.addOpaqueRoot(ptr); +} + +DEFINE_VISIT_CHILDREN(${className}); + void ${controller}::start(JSC::JSGlobalObject *globalObject, JSC::JSValue readableStream, JSC::JSFunction *onPull, JSC::JSFunction *onClose) { this->m_weakReadableStream = JSC::Weak<JSC::JSObject>(readableStream.getObject()); diff --git a/src/bun.js/test/jest.classes.ts b/src/bun.js/test/jest.classes.ts index d1d225f64..ad2a5d6e8 100644 --- a/src/bun.js/test/jest.classes.ts +++ b/src/bun.js/test/jest.classes.ts @@ -128,6 +128,30 @@ export default [ fn: "toBeInstanceOf", length: 1, }, + toBeTruthy: { + fn: "toBeTruthy", + length: 0, + }, + toBeUndefined: { + fn: "toBeUndefined", + length: 0, + }, + toBeNaN: { + fn: "toBeNaN", + length: 0, + }, + toBeNull: { + fn: "toBeNull", + length: 0, + }, + toBeFalsy: { + fn: "toBeFalsy", + length: 0, + }, + toBeDefined: { + fn: "toBeDefined", + length: 0, + }, toContain: { fn: "toContain", length: 1, diff --git a/src/bun.js/test/jest.zig b/src/bun.js/test/jest.zig index 4d67ea97f..c7372b573 100644 --- a/src/bun.js/test/jest.zig +++ b/src/bun.js/test/jest.zig @@ -37,6 +37,7 @@ const JSPromise = JSC.JSPromise; const JSValue = JSC.JSValue; const JSError = JSC.JSError; const JSGlobalObject = JSC.JSGlobalObject; +const JSObject = JSC.JSObject; const VirtualMachine = @import("../javascript.zig").VirtualMachine; const Task = @import("../javascript.zig").Task; @@ -274,7 +275,10 @@ pub const Expect = struct { .test_id = Jest.runner.?.pending_test.?.test_id, }; const expect_js_value = expect.toJS(globalObject); + expect_js_value.ensureStillAlive(); JSC.Jest.Expect.capturedValueSetCached(expect_js_value, globalObject, value); + expect_js_value.ensureStillAlive(); + expect.postMatch(globalObject); return expect_js_value; } @@ -293,6 +297,7 @@ pub const Expect = struct { globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFrame, ) callconv(.C) JSC.JSValue { + defer this.postMatch(globalObject); const thisValue = callframe.this(); const arguments_ = callframe.arguments(1); const arguments = arguments_.ptr[0..arguments_.len]; @@ -315,31 +320,29 @@ pub const Expect = struct { return .zero; }; right.ensureStillAlive(); - const eql = left.isSameValue(right, globalObject); + + const not = this.op.contains(.not); + var pass = left.isSameValue(right, globalObject); if (comptime Environment.allow_assert) { - std.debug.assert(eql == JSC.C.JSValueIsStrictEqual(globalObject, left.asObjectRef(), right.asObjectRef())); + std.debug.assert(pass == JSC.C.JSValueIsStrictEqual(globalObject, left.asObjectRef(), right.asObjectRef())); } - if (!eql) { - var lhs_formatter: JSC.ZigConsoleClient.Formatter = JSC.ZigConsoleClient.Formatter{ .globalThis = globalObject }; - var rhs_formatter: JSC.ZigConsoleClient.Formatter = JSC.ZigConsoleClient.Formatter{ .globalThis = globalObject }; - - if (comptime Environment.allow_assert) { - Output.prettyErrorln("\nJSType: {s}\nJSType: {s}\n\n", .{ @tagName(left.jsType()), @tagName(right.jsType()) }); - } + if (not) pass = !pass; + if (pass) return thisValue; - globalObject.throw( - "Expected: {any}\n\tReceived: {any}", - .{ - left.toFmt(globalObject, &lhs_formatter), - right.toFmt(globalObject, &rhs_formatter), - }, - ); - - return .zero; + // handle failure + var lhs_fmt = JSC.ZigConsoleClient.Formatter{ .globalThis = globalObject }; + var rhs_fmt = JSC.ZigConsoleClient.Formatter{ .globalThis = globalObject }; + if (comptime Environment.allow_assert) { + Output.prettyErrorln("\nJSType: {s}\nJSType: {s}\n\n", .{ @tagName(left.jsType()), @tagName(right.jsType()) }); } - return thisValue; + if (not) { + globalObject.throw("\n\tExpected: not {any}\n\tReceived: {any}", .{ left.toFmt(globalObject, &lhs_fmt), right.toFmt(globalObject, &rhs_fmt) }); + } else { + globalObject.throw("\n\tExpected: {any}\n\tReceived: {any}", .{ left.toFmt(globalObject, &lhs_fmt), right.toFmt(globalObject, &rhs_fmt) }); + } + return .zero; } pub fn toHaveLength( @@ -347,6 +350,7 @@ pub const Expect = struct { globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFrame, ) callconv(.C) JSC.JSValue { + defer this.postMatch(globalObject); const thisValue = callframe.this(); const arguments_ = callframe.arguments(1); const arguments = arguments_.ptr[0..arguments_.len]; @@ -363,25 +367,315 @@ pub const Expect = struct { active_test_expectation_counter.actual += 1; - const expected = arguments[0].coerce(i32, globalObject); - const value = JSC.Jest.Expect.capturedValueGetCached(thisValue) orelse { + const expected: JSValue = arguments[0]; + const value: JSValue = JSC.Jest.Expect.capturedValueGetCached(thisValue) orelse { globalObject.throw("Internal consistency error: the expect(value) was garbage collected but it should not have been!", .{}); return .zero; }; - const actual = value.getLengthOfArray(globalObject); - if (expected != actual) { - globalObject.throw("Expected length to equal {d} but received {d}\n Expected: {d}\n Actual: {d}\n", .{ - expected, - actual, - expected, - actual, - }); + value.ensureStillAlive(); + + if (!value.isObject() and !value.isString()) { + var fmt = JSC.ZigConsoleClient.Formatter{ .globalThis = globalObject }; + globalObject.throw("Received value does not have a length property: {any}", .{value.toFmt(globalObject, &fmt)}); return .zero; } - return thisValue; + if (!expected.isNumber()) { + var fmt = JSC.ZigConsoleClient.Formatter{ .globalThis = globalObject }; + globalObject.throw("Expected value must be a non-negative integer: {any}", .{expected.toFmt(globalObject, &fmt)}); + return .zero; + } + + const expected_length: f64 = expected.asNumber(); + if (@round(expected_length) != expected_length or std.math.isInf(expected_length) or std.math.isNan(expected_length) or expected_length < 0) { + var fmt = JSC.ZigConsoleClient.Formatter{ .globalThis = globalObject }; + globalObject.throw("Expected value must be a non-negative integer: {any}", .{expected.toFmt(globalObject, &fmt)}); + return .zero; + } + + const not = this.op.contains(.not); + var pass = false; + + var actual_length: f64 = undefined; + if (value.isString()) { + actual_length = @intToFloat(f64, value.asString().length()); + if (actual_length == expected_length) pass = true; + } else { + const length_value: JSValue = value.getIfPropertyExistsImpl(globalObject, "length", "length".len); + + if (length_value.isEmpty()) { + var fmt = JSC.ZigConsoleClient.Formatter{ .globalThis = globalObject }; + globalObject.throw("Received value does not have a length property: {any}", .{value.toFmt(globalObject, &fmt)}); + return .zero; + } else if (!length_value.isNumber()) { + var fmt = JSC.ZigConsoleClient.Formatter{ .globalThis = globalObject }; + globalObject.throw("Received value has non-number length property: {any}", .{length_value.toFmt(globalObject, &fmt)}); + return .zero; + } + + actual_length = length_value.asNumber(); + if (@round(actual_length) == actual_length) { + if (actual_length == expected_length) pass = true; + } + } + + if (not) pass = !pass; + if (pass) return thisValue; + + // handle failure + if (not) { + globalObject.throw("\n\tExpected: not {d}\n\tReceived: {d}", .{ expected_length, actual_length }); + } else { + globalObject.throw("\n\tExpected: {d}\n\tReceived: {d}", .{ expected_length, actual_length }); + } + return .zero; + } + + pub fn toContain( + this: *Expect, + globalObject: *JSC.JSGlobalObject, + callFrame: *JSC.CallFrame, + ) callconv(.C) JSC.JSValue { + defer this.postMatch(globalObject); + const thisValue = callFrame.this(); + const arguments_ = callFrame.arguments(1); + const arguments = arguments_.ptr[0..arguments_.len]; + + if (arguments.len < 1) { + globalObject.throwInvalidArguments("toContain() takes 1 argument", .{}); + return .zero; + } + + if (this.scope.tests.items.len <= this.test_id) { + globalObject.throw("toContain() must be called in a test", .{}); + return .zero; + } + + active_test_expectation_counter.actual += 1; + + const expected = arguments[0]; + expected.ensureStillAlive(); + const value: JSValue = JSC.Jest.Expect.capturedValueGetCached(thisValue) orelse { + globalObject.throw("Internal consistency error: the expect(value) was garbage collected but it should not have been!", .{}); + return .zero; + }; + value.ensureStillAlive(); + + const not = this.op.contains(.not); + var pass = false; + + if (value.isIterable(globalObject)) { + var itr = value.arrayIterator(globalObject); + while (itr.next()) |item| { + if (item.isSameValue(expected, globalObject)) { + pass = true; + break; + } + } + } else if (value.isString() and expected.isString()) { + const value_string = value.toString(globalObject).toSlice(globalObject, default_allocator).slice(); + const expected_string = expected.toString(globalObject).toSlice(globalObject, default_allocator).slice(); + if (strings.contains(value_string, expected_string)) { + pass = true; + } + } else { + globalObject.throw("Received value must be an array type, or both received and expected values must be strings.", .{}); + return .zero; + } + + if (not) pass = !pass; + if (pass) return thisValue; + + // handle failure + var fmt = JSC.ZigConsoleClient.Formatter{ .globalThis = globalObject }; + if (not) { + globalObject.throw("Expected to not contain \"{any}\"", .{expected.toFmt(globalObject, &fmt)}); + } else { + globalObject.throw("Expected to contain \"{any}\"", .{expected.toFmt(globalObject, &fmt)}); + } + return .zero; + } + + pub fn toBeTruthy(this: *Expect, globalObject: *JSC.JSGlobalObject, callFrame: *JSC.CallFrame) callconv(.C) JSC.JSValue { + defer this.postMatch(globalObject); + const thisValue = callFrame.this(); + const value: JSValue = Expect.capturedValueGetCached(thisValue) orelse { + globalObject.throw("Internal consistency error: the expect(value) was garbage collected but it should not have been!", .{}); + return .zero; + }; + value.ensureStillAlive(); + + if (this.scope.tests.items.len <= this.test_id) { + globalObject.throw("toBeTruthy() must be called in a test", .{}); + return .zero; + } + + active_test_expectation_counter.actual += 1; + + const not = this.op.contains(.not); + var pass = false; + + const truthy = value.toBooleanSlow(globalObject); + if (truthy) pass = true; + + if (not) pass = !pass; + if (pass) return thisValue; + + // handle failure + var fmt = JSC.ZigConsoleClient.Formatter{ .globalThis = globalObject }; + if (not) { + globalObject.throw("Expected \"{any}\" to be not truthy.", .{value.toFmt(globalObject, &fmt)}); + } else { + globalObject.throw("Expected \"{any}\" to be truthy.", .{value.toFmt(globalObject, &fmt)}); + } + return .zero; + } + + pub fn toBeUndefined(this: *Expect, globalObject: *JSC.JSGlobalObject, callFrame: *JSC.CallFrame) callconv(.C) JSC.JSValue { + defer this.postMatch(globalObject); + const thisValue = callFrame.this(); + const value: JSValue = Expect.capturedValueGetCached(thisValue) orelse { + globalObject.throw("Interal consistency error: the expect(value) was garbage collected but it should not have been!", .{}); + return .zero; + }; + value.ensureStillAlive(); + + active_test_expectation_counter.actual += 1; + + const not = this.op.contains(.not); + var pass = false; + if (value.isUndefined()) pass = true; + + if (not) pass = !pass; + if (pass) return thisValue; + + // handle failure + var fmt = JSC.ZigConsoleClient.Formatter{ .globalThis = globalObject }; + if (not) { + globalObject.throw("Expected \"{any}\" to be not undefined.", .{value.toFmt(globalObject, &fmt)}); + } else { + globalObject.throw("Expected \"{any}\" to be undefined.", .{value.toFmt(globalObject, &fmt)}); + } + return .zero; + } + + pub fn toBeNaN(this: *Expect, globalObject: *JSC.JSGlobalObject, callFrame: *JSC.CallFrame) callconv(.C) JSC.JSValue { + defer this.postMatch(globalObject); + + const thisValue = callFrame.this(); + const value: JSValue = Expect.capturedValueGetCached(thisValue) orelse { + globalObject.throw("Interal consistency error: the expect(value) was garbage collected but it should not have been!", .{}); + return .zero; + }; + value.ensureStillAlive(); + + active_test_expectation_counter.actual += 1; + + const not = this.op.contains(.not); + var pass = false; + if (value.isNumber()) { + const number = value.asNumber(); + if (number != number) pass = true; + } + + if (not) pass = !pass; + if (pass) return thisValue; + + // handle failure + var fmt = JSC.ZigConsoleClient.Formatter{ .globalThis = globalObject }; + if (not) { + globalObject.throw("Expected \"{any}\" to be not NaN.", .{value.toFmt(globalObject, &fmt)}); + } else { + globalObject.throw("Expected \"{any}\" to be NaN.", .{value.toFmt(globalObject, &fmt)}); + } + return .zero; + } + + pub fn toBeNull(this: *Expect, globalObject: *JSC.JSGlobalObject, callFrame: *JSC.CallFrame) callconv(.C) JSC.JSValue { + defer this.postMatch(globalObject); + + const thisValue = callFrame.this(); + const value: JSValue = Expect.capturedValueGetCached(thisValue) orelse { + globalObject.throw("Interal consistency error: the expect(value) was garbage collected but it should not have been!", .{}); + return .zero; + }; + value.ensureStillAlive(); + + active_test_expectation_counter.actual += 1; + + const not = this.op.contains(.not); + var pass = value.isNull(); + if (not) pass = !pass; + if (pass) return thisValue; + + // handle failure + var fmt = JSC.ZigConsoleClient.Formatter{ .globalThis = globalObject }; + if (not) { + globalObject.throw("Expected \"{any}\" to be not null.", .{value.toFmt(globalObject, &fmt)}); + } else { + globalObject.throw("Expected \"{any}\" to be null.", .{value.toFmt(globalObject, &fmt)}); + } + return .zero; } + pub fn toBeDefined(this: *Expect, globalObject: *JSC.JSGlobalObject, callFrame: *JSC.CallFrame) callconv(.C) JSC.JSValue { + defer this.postMatch(globalObject); + + const thisValue = callFrame.this(); + const value: JSValue = Expect.capturedValueGetCached(thisValue) orelse { + globalObject.throw("Interal consistency error: the expect(value) was garbage collected but it should not have been!", .{}); + return .zero; + }; + value.ensureStillAlive(); + + active_test_expectation_counter.actual += 1; + + const not = this.op.contains(.not); + var pass = !value.isUndefined(); + if (not) pass = !pass; + if (pass) return thisValue; + + // handle failure + var fmt = JSC.ZigConsoleClient.Formatter{ .globalThis = globalObject }; + if (not) { + globalObject.throw("Expected \"{any}\" to be not defined.", .{value.toFmt(globalObject, &fmt)}); + } else { + globalObject.throw("Expected \"{any}\" to be defined.", .{value.toFmt(globalObject, &fmt)}); + } + return .zero; + } + + pub fn toBeFalsy(this: *Expect, globalObject: *JSC.JSGlobalObject, callFrame: *JSC.CallFrame) callconv(.C) JSC.JSValue { + defer this.postMatch(globalObject); + + const thisValue = callFrame.this(); + + const value: JSValue = Expect.capturedValueGetCached(thisValue) orelse { + globalObject.throw("internal consistency error: the expect(value) was garbage collected but it should not have been!", .{}); + return .zero; + }; + value.ensureStillAlive(); + + const not = this.op.contains(.not); + var pass = false; + + const truthy = value.toBooleanSlow(globalObject); + if (!truthy) pass = true; + + if (not) pass = !pass; + if (pass) return thisValue; + + // handle failure + var fmt = JSC.ZigConsoleClient.Formatter{ .globalThis = globalObject }; + if (not) { + globalObject.throw("Expected \"{any}\" to be not falsy.", .{value.toFmt(globalObject, &fmt)}); + } else { + globalObject.throw("Expected \"{any}\" to be falsy.", .{value.toFmt(globalObject, &fmt)}); + } + return .zero; + } + + pub const toHaveProperty = notImplementedJSCFn; pub const toHaveBeenCalledTimes = notImplementedJSCFn; pub const toHaveBeenCalledWith = notImplementedJSCFn; pub const toHaveBeenLastCalledWith = notImplementedJSCFn; @@ -390,14 +684,12 @@ pub const Expect = struct { pub const toHaveReturnedWith = notImplementedJSCFn; pub const toHaveLastReturnedWith = notImplementedJSCFn; pub const toHaveNthReturnedWith = notImplementedJSCFn; - pub const toHaveProperty = notImplementedJSCFn; pub const toBeCloseTo = notImplementedJSCFn; pub const toBeGreaterThan = notImplementedJSCFn; pub const toBeGreaterThanOrEqual = notImplementedJSCFn; pub const toBeLessThan = notImplementedJSCFn; pub const toBeLessThanOrEqual = notImplementedJSCFn; pub const toBeInstanceOf = notImplementedJSCFn; - pub const toContain = notImplementedJSCFn; pub const toContainEqual = notImplementedJSCFn; pub const toEqual = notImplementedJSCFn; pub const toMatch = notImplementedJSCFn; @@ -409,6 +701,35 @@ pub const Expect = struct { pub const toThrowErrorMatchingSnapshot = notImplementedJSCFn; pub const toThrowErrorMatchingInlineSnapshot = notImplementedJSCFn; + pub const getStaticNot = notImplementedStaticProp; + pub const getStaticResolves = notImplementedStaticProp; + pub const getStaticRejects = notImplementedStaticProp; + + pub fn getNot(this: *Expect, thisValue: JSValue, globalObject: *JSGlobalObject) callconv(.C) JSValue { + _ = Expect.capturedValueGetCached(thisValue) orelse { + globalObject.throw("Internal consistency error: the expect(value) was garbage collected but it should not have been!", .{}); + return .zero; + }; + + this.op.toggle(.not); + + return thisValue; + } + + pub const getResolves = notImplementedJSCProp; + pub const getRejects = notImplementedJSCProp; + + pub const extend = notImplementedStaticFn; + pub const anything = notImplementedStaticFn; + pub const any = notImplementedStaticFn; + pub const arrayContaining = notImplementedStaticFn; + pub const assertions = notImplementedStaticFn; + pub const hasAssertions = notImplementedStaticFn; + pub const objectContaining = notImplementedStaticFn; + pub const stringContaining = notImplementedStaticFn; + pub const stringMatching = notImplementedStaticFn; + pub const addSnapshotSerializer = notImplementedStaticFn; + pub fn notImplementedJSCFn(_: *Expect, globalObject: *JSC.JSGlobalObject, _: *JSC.CallFrame) callconv(.C) JSC.JSValue { globalObject.throw("Not implemented", .{}); return .zero; @@ -429,23 +750,10 @@ pub const Expect = struct { return .zero; } - pub const getStaticNot = notImplementedStaticProp; - pub const getStaticResolves = notImplementedStaticProp; - pub const getStaticRejects = notImplementedStaticProp; - pub const getNot = notImplementedJSCProp; - pub const getResolves = notImplementedJSCProp; - pub const getRejects = notImplementedJSCProp; - - pub const extend = notImplementedStaticFn; - pub const anything = notImplementedStaticFn; - pub const any = notImplementedStaticFn; - pub const arrayContaining = notImplementedStaticFn; - pub const assertions = notImplementedStaticFn; - pub const hasAssertions = notImplementedStaticFn; - pub const objectContaining = notImplementedStaticFn; - pub const stringContaining = notImplementedStaticFn; - pub const stringMatching = notImplementedStaticFn; - pub const addSnapshotSerializer = notImplementedStaticFn; + pub fn postMatch(_: *Expect, globalObject: *JSC.JSGlobalObject) void { + var vm = globalObject.bunVM(); + vm.autoGarbageCollect(); + } }; pub const TestScope = struct { @@ -537,13 +845,15 @@ pub const TestScope = struct { globalThis.bunVM().runErrorHandler(err, null); var task: *TestRunnerTask = arguments.ptr[1].asPromisePtr(TestRunnerTask); task.handleResult(.{ .fail = active_test_expectation_counter.actual }, .promise); + globalThis.bunVM().autoGarbageCollect(); return JSValue.jsUndefined(); } - pub fn onResolve(_: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) JSValue { + pub fn onResolve(globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) JSValue { const arguments = callframe.arguments(2); var task: *TestRunnerTask = arguments.ptr[1].asPromisePtr(TestRunnerTask); task.handleResult(.{ .pass = active_test_expectation_counter.actual }, .promise); + globalThis.bunVM().autoGarbageCollect(); return JSValue.jsUndefined(); } @@ -553,6 +863,7 @@ pub const TestScope = struct { ) callconv(.C) JSValue { const function = callframe.callee(); const args = callframe.arguments(1); + defer globalThis.bunVM().autoGarbageCollect(); if (JSC.getFunctionData(function)) |data| { var task = bun.cast(*TestRunnerTask, data); @@ -579,6 +890,7 @@ pub const TestScope = struct { defer { js.JSValueUnprotect(vm.global, callback); this.callback = null; + vm.autoGarbageCollect(); } JSC.markBinding(@src()); @@ -600,33 +912,35 @@ pub const TestScope = struct { initial_value = js.JSObjectCallAsFunctionReturnValue(vm.global, callback, null, 0, null); } - if (initial_value.isException(vm.global.vm()) or initial_value.isError() or initial_value.isAggregateError(vm.global)) { - vm.runErrorHandler(initial_value, null); - return .{ .fail = active_test_expectation_counter.actual }; - } - - if (!initial_value.isEmptyOrUndefinedOrNull() and (initial_value.asPromise() != null or initial_value.asInternalPromise() != null)) { - if (this.promise != null) { - return .{ .pending = .{} }; + if (!initial_value.isEmptyOrUndefinedOrNull()) { + if (initial_value.isAnyError(vm.global)) { + vm.runErrorHandler(initial_value, null); + return .{ .fail = active_test_expectation_counter.actual }; } - var promise = initial_value.asPromise().?; - this.task = task; - - switch (promise.status(vm.global.vm())) { - .Rejected => { - vm.runErrorHandler(promise.result(vm.global.vm()), null); - return .{ .fail = active_test_expectation_counter.actual }; - }, - .Pending => { - task.promise_state = .pending; - _ = promise.asValue(vm.global).then(vm.global, task, onResolve, onReject); - return .{ .pending = {} }; - }, - - else => { - _ = promise.result(vm.global.vm()); - }, + if (initial_value.jsType() == .JSPromise) { + if (this.promise != null) { + return .{ .pending = .{} }; + } + + var promise: *JSC.JSPromise = initial_value.asPromise().?; + this.task = task; + + switch (promise.status(vm.global.vm())) { + .Rejected => { + vm.runErrorHandler(promise.result(vm.global.vm()), null); + return .{ .fail = active_test_expectation_counter.actual }; + }, + .Pending => { + task.promise_state = .pending; + _ = promise.asValue(vm.global).then(vm.global, task, onResolve, onReject); + return .{ .pending = {} }; + }, + + else => { + _ = promise.result(vm.global.vm()); + }, + } } } diff --git a/src/bun.js/webcore/response.zig b/src/bun.js/webcore/response.zig index 3a5a3f3c7..5c996da45 100644 --- a/src/bun.js/webcore/response.zig +++ b/src/bun.js/webcore/response.zig @@ -31,7 +31,6 @@ const GetJSPrivateData = @import("../base.zig").GetJSPrivateData; const Environment = @import("../../env.zig"); const ZigString = JSC.ZigString; const IdentityContext = @import("../../identity_context.zig").IdentityContext; -const JSInternalPromise = JSC.JSInternalPromise; const JSPromise = JSC.JSPromise; const JSValue = JSC.JSValue; const JSError = JSC.JSError; @@ -1212,11 +1211,13 @@ pub const Blob = struct { if (destination_type == .file and source_type == .bytes) { var write_file_promise = bun.default_allocator.create(WriteFilePromise) catch unreachable; + var promise = JSC.JSPromise.create(ctx.ptr()); + const promise_value = promise.asValue(ctx); write_file_promise.* = .{ - .promise = JSC.JSPromise.create(ctx.ptr()), .globalThis = ctx.ptr(), }; - JSC.C.JSValueProtect(ctx, write_file_promise.promise.asValue(ctx.ptr()).asObjectRef()); + write_file_promise.promise.strong.set(ctx, promise_value); + promise_value.ensureStillAlive(); var file_copier = Store.WriteFile.create( bun.default_allocator, @@ -1228,7 +1229,7 @@ pub const Blob = struct { ) catch unreachable; var task = Store.WriteFile.WriteFileTask.createOnJSThread(bun.default_allocator, ctx.ptr(), file_copier) catch unreachable; task.schedule(); - return write_file_promise.promise.asValue(ctx.ptr()).asObjectRef(); + return promise_value.asObjectRef(); } // If this is file <> file, we can just copy the file else if (destination_type == .file and source_type == .file) { @@ -1242,7 +1243,7 @@ pub const Blob = struct { ctx.ptr(), ) catch unreachable; file_copier.schedule(); - return file_copier.promise.asObjectRef(); + return file_copier.promise.value().asObjectRef(); } else if (destination_type == .bytes and source_type == .bytes) { // If this is bytes <> bytes, we can just duplicate it // this is an edgecase @@ -2508,7 +2509,7 @@ pub const Blob = struct { bun.default_allocator.destroy(this); } - pub fn reject(this: *CopyFile, promise: *JSC.JSInternalPromise) void { + pub fn reject(this: *CopyFile, promise: *JSC.JSPromise) void { var globalThis = this.globalThis; var system_error: SystemError = this.system_error orelse SystemError{}; if (this.source_file_store.pathlike == .path and system_error.path.len == 0) { @@ -2527,7 +2528,7 @@ pub const Blob = struct { promise.reject(globalThis, instance); } - pub fn then(this: *CopyFile, promise: *JSC.JSInternalPromise) void { + pub fn then(this: *CopyFile, promise: *JSC.JSPromise) void { this.source_store.?.deref(); if (this.system_error != null) { @@ -3439,10 +3440,10 @@ pub const Blob = struct { pub fn NewReadFileHandler(comptime Function: anytype) type { return struct { context: Blob, - promise: *JSPromise, + promise: JSPromise.Strong = .{}, globalThis: *JSGlobalObject, pub fn run(handler: *@This(), bytes_: Blob.Store.ReadFile.ResultType) void { - var promise = handler.promise; + var promise = handler.promise.swap(); var blob = handler.context; blob.allocator = null; var globalThis = handler.globalThis; @@ -3463,21 +3464,19 @@ pub const Blob = struct { } pub const WriteFilePromise = struct { - promise: *JSPromise, + promise: JSPromise.Strong = .{}, globalThis: *JSGlobalObject, pub fn run(handler: *@This(), count: Blob.Store.WriteFile.ResultType) void { - var promise = handler.promise; + var promise = handler.promise.swap(); var globalThis = handler.globalThis; bun.default_allocator.destroy(handler); const value = promise.asValue(globalThis); value.ensureStillAlive(); switch (count) { .err => |err| { - value.unprotect(); promise.reject(globalThis, err.toErrorInstance(globalThis)); }, .result => |wrote| { - value.unprotect(); promise.resolve(globalThis, JSC.JSValue.jsNumberFromUint64(wrote)); }, } @@ -3511,9 +3510,11 @@ pub const Blob = struct { var handler = Handler{ .context = this.*, - .promise = promise, .globalThis = global, }; + const promise_value = promise.asValue(global); + promise_value.ensureStillAlive(); + handler.promise.strong.set(global, promise_value); var ptr = bun.default_allocator.create(Handler) catch unreachable; ptr.* = handler; @@ -3528,7 +3529,7 @@ pub const Blob = struct { ) catch unreachable; var read_file_task = Store.ReadFile.ReadFileTask.createOnJSThread(bun.default_allocator, global, file_read) catch unreachable; read_file_task.schedule(); - return promise.asValue(global); + return promise_value; } pub fn needsToReadFile(this: *const Blob) bool { diff --git a/src/bun.js/webcore/streams.classes.ts b/src/bun.js/webcore/streams.classes.ts new file mode 100644 index 000000000..0b070b857 --- /dev/null +++ b/src/bun.js/webcore/streams.classes.ts @@ -0,0 +1,5 @@ +// import { define } from "../scripts/class-definitions"; + +// export default [ +// define({}) +// ] diff --git a/src/bun_js.zig b/src/bun_js.zig index 2510183aa..07d7e4adf 100644 --- a/src/bun_js.zig +++ b/src/bun_js.zig @@ -120,12 +120,7 @@ pub const Run = struct { } } - if (run.vm.bundler.env.map.get("BUN_OVERRIDE_MODULE_PATH")) |override_path| { - if (override_path.len > 0) { - run.vm.load_builtins_from_path = override_path; - } - } - + run.vm.loadExtraEnv(); run.vm.is_main_thread = true; JSC.VirtualMachine.is_main_thread_vm = true; diff --git a/src/cli/test_command.zig b/src/cli/test_command.zig index 3f0082940..11b764893 100644 --- a/src/cli/test_command.zig +++ b/src/cli/test_command.zig @@ -173,6 +173,7 @@ const Scanner = struct { scan_dir_buf: [bun.MAX_PATH_BYTES]u8 = undefined, options: *options.BundleOptions, has_iterated: bool = false, + search_count: usize = 0, const ScanEntry = struct { relative_dir: bun.StoredFileDescriptorType, @@ -267,6 +268,8 @@ const Scanner = struct { if (strings.eql(exclude_name, name)) return; } + this.search_count += 1; + this.dirs_to_scan.writeItem(.{ .relative_dir = fd, .name = entry.base_, @@ -277,6 +280,7 @@ const Scanner = struct { // already seen it! if (!entry.abs_path.isEmpty()) return; + this.search_count += 1; if (!this.couldBeTestFile(name)) return; var parts = &[_]string{ entry.dir, entry.base() }; @@ -295,6 +299,10 @@ pub const TestCommand = struct { pub const name = "wiptest"; pub fn exec(ctx: Command.Context) !void { if (comptime is_bindgen) unreachable; + // print the version so you know its doing stuff if it takes a sec + Output.prettyErrorln("<r><b>bun wiptest <r><d>v" ++ Global.package_json_version_with_sha ++ "<r>\n\n", .{}); + Output.flush(); + var env_loader = brk: { var map = try ctx.allocator.create(DotEnv.Map); map.* = DotEnv.Map.init(ctx.allocator); @@ -306,6 +314,7 @@ pub const TestCommand = struct { JSC.C.JSCInitialize(); NetworkThread.init() catch {}; HTTPThread.init() catch {}; + var reporter = try ctx.allocator.create(CommandLineReporter); reporter.* = CommandLineReporter{ .jest = TestRunner{ @@ -332,12 +341,7 @@ pub const TestCommand = struct { try vm.bundler.configureDefines(); vm.bundler.options.rewrite_jest_for_tests = true; - if (vm.bundler.env.map.get("BUN_OVERRIDE_MODULE_PATH")) |override_path| { - if (override_path.len > 0) { - vm.load_builtins_from_path = override_path; - } - } - + vm.loadExtraEnv(); vm.is_main_thread = true; JSC.VirtualMachine.is_main_thread_vm = true; @@ -348,7 +352,6 @@ pub const TestCommand = struct { .filter_names = ctx.positionals[1..], .results = std.ArrayList(PathString).init(ctx.allocator), }; - scanner.scan(scanner.fs.top_level_dir); scanner.dirs_to_scan.deinit(); @@ -369,31 +372,49 @@ pub const TestCommand = struct { Output.flush(); - Output.prettyError("\n", .{}); + if (scanner.filter_names.len == 0 and test_files.len == 0) { + Output.prettyErrorln( + \\<b><yellow>No tests found<r>! Tests need ".test", "_test_", ".spec" or "_spec_" in the filename <d>(ex: "MyApp.test.ts")<r> + \\ + , + .{}, + ); + + Output.printStartEnd(ctx.start_time, std.time.nanoTimestamp()); + if (scanner.search_count > 0) + Output.prettyError( + \\ {d} files searched + , .{ + scanner.search_count, + }); + } else { + Output.prettyError("\n", .{}); - if (reporter.summary.pass > 0) { - Output.prettyError("<r><green>", .{}); - } + if (reporter.summary.pass > 0) { + Output.prettyError("<r><green>", .{}); + } - Output.prettyError(" {d:5>} pass<r>\n", .{reporter.summary.pass}); + Output.prettyError(" {d:5>} pass<r>\n", .{reporter.summary.pass}); - if (reporter.summary.fail > 0) { - Output.prettyError("<r><red>", .{}); - } else { - Output.prettyError("<r><d>", .{}); - } + if (reporter.summary.fail > 0) { + Output.prettyError("<r><red>", .{}); + } else { + Output.prettyError("<r><d>", .{}); + } - Output.prettyError(" {d:5>} fail<r>\n", .{reporter.summary.fail}); + Output.prettyError(" {d:5>} fail<r>\n", .{reporter.summary.fail}); - if (reporter.summary.expectations > 0) Output.prettyError(" {d:5>} expect() calls\n", .{reporter.summary.expectations}); + if (reporter.summary.expectations > 0) Output.prettyError(" {d:5>} expect() calls\n", .{reporter.summary.expectations}); + + Output.prettyError( + \\ Ran {d} tests across {d} files + , .{ + reporter.summary.fail + reporter.summary.pass, + test_files.len, + }); + Output.printStartEnd(ctx.start_time, std.time.nanoTimestamp()); + } - Output.prettyError( - \\ Ran {d} tests across {d} files - , .{ - reporter.summary.fail + reporter.summary.pass, - test_files.len, - }); - Output.printStartEnd(ctx.start_time, std.time.nanoTimestamp()); Output.prettyError("\n", .{}); Output.flush(); diff --git a/src/deps/uws.zig b/src/deps/uws.zig index 1551efba7..e69b096b4 100644 --- a/src/deps/uws.zig +++ b/src/deps/uws.zig @@ -432,6 +432,10 @@ pub const Loop = extern struct { low_prio_head: ?*Socket, low_prio_budget: i32, iteration_nr: c_longlong, + + pub fn recvSlice(this: *InternalLoopData) []u8 { + return this.recv_buf[0..LIBUS_RECV_BUFFER_LENGTH]; + } }; pub fn get() ?*Loop { @@ -1662,7 +1666,7 @@ extern fn uws_res_upgrade( ) void; extern fn uws_res_cork(i32, res: *uws_res, ctx: *anyopaque, corker: fn (?*anyopaque) callconv(.C) void) void; extern fn uws_res_write_headers(i32, res: *uws_res, names: [*]const Api.StringPointer, values: [*]const Api.StringPointer, count: usize, buf: [*]const u8) void; -pub const LIBUS_RECV_BUFFER_LENGTH = @import("std").zig.c_translation.promoteIntLiteral(i32, 524288, .decimal); +pub const LIBUS_RECV_BUFFER_LENGTH = 524288; pub const LIBUS_TIMEOUT_GRANULARITY = @as(i32, 4); pub const LIBUS_RECV_BUFFER_PADDING = @as(i32, 32); pub const LIBUS_EXT_ALIGNMENT = @as(i32, 16); diff --git a/src/feature_flags.zig b/src/feature_flags.zig index 3d016efb6..ef38ea447 100644 --- a/src/feature_flags.zig +++ b/src/feature_flags.zig @@ -105,3 +105,9 @@ pub const disable_lolhtml = false; /// other ipv4 hosts. This is a workaround for that. /// "localhost" fails to connect. pub const hardcode_localhost_to_127_0_0_1 = true; + +/// React doesn't do anything with jsxs +/// If the "jsxs" import is development, "jsxs" isn't supported +/// But it's very easy to end up importing it accidentally, causing an error at runtime +/// so we just disable it +pub const support_jsxs_in_jsx_transform = false; diff --git a/src/global.zig b/src/global.zig index c7359e367..32ef4214f 100644 --- a/src/global.zig +++ b/src/global.zig @@ -410,5 +410,17 @@ pub fn isHeapMemory(memory: anytype) bool { pub const Mimalloc = @import("./allocators/mimalloc.zig"); -pub const FileDescriptor = std.os.fd_t; -pub const invalid_fd = std.math.maxInt(i32); +pub fn isSliceInBuffer(slice: []const u8, buffer: []const u8) bool { + return slice.len > 0 and @ptrToInt(buffer.ptr) <= @ptrToInt(slice.ptr) and ((@ptrToInt(slice.ptr) + slice.len) <= (@ptrToInt(buffer.ptr) + buffer.len)); +} + +pub fn rangeOfSliceInBuffer(slice: []const u8, buffer: []const u8) ?[2]u32 { + if (!isSliceInBuffer(slice, buffer)) return null; + const r = [_]u32{ + @truncate(u32, @ptrToInt(slice.ptr) -| @ptrToInt(buffer.ptr)), + @truncate(u32, slice.len), + }; + if (comptime Environment.allow_assert) + std.debug.assert(strings.eqlLong(slice, buffer[r[0]..][0..r[1]], false)); + return r; +} diff --git a/src/http/zlib.zig b/src/http/zlib.zig index 4a2e88bec..0e48be608 100644 --- a/src/http/zlib.zig +++ b/src/http/zlib.zig @@ -22,8 +22,16 @@ pub fn put(mutable: *MutableString) void { node.release(); } -pub fn decompress(compressed_data: []const u8, output: *MutableString) Zlib.ZlibError!void { - var reader = try Zlib.ZlibReaderArrayList.init(compressed_data, &output.list, output.allocator); +pub fn decompress(compressed_data: []const u8, output: *MutableString, allocator: std.mem.Allocator) Zlib.ZlibError!void { + var reader = try Zlib.ZlibReaderArrayList.initWithOptionsAndListAllocator( + compressed_data, + &output.list, + output.allocator, + allocator, + .{ + .windowBits = 15 + 32, + }, + ); try reader.readAll(); reader.deinit(); } diff --git a/src/http_client_async.zig b/src/http_client_async.zig index 384c9fa2f..3c18b9552 100644 --- a/src/http_client_async.zig +++ b/src/http_client_async.zig @@ -31,7 +31,7 @@ pub const MimeType = @import("./http/mime_type.zig"); pub const URLPath = @import("./http/url_path.zig"); // This becomes Arena.allocator pub var default_allocator: std.mem.Allocator = undefined; -pub var default_arena: Arena = undefined; +var default_arena: Arena = undefined; pub var http_thread: HTTPThread = undefined; const HiveArray = @import("./hive_array.zig").HiveArray; const Batch = NetworkThread.Batch; @@ -49,6 +49,8 @@ var shared_request_headers_buf: [256]picohttp.Header = undefined; // this doesn't need to be stack memory because it is immediately cloned after use var shared_response_headers_buf: [256]picohttp.Header = undefined; +const end_of_chunked_http1_1_encoding_response_body = "0\r\n\r\n"; + fn NewHTTPContext(comptime ssl: bool) type { return struct { const pool_size = 64; @@ -191,7 +193,7 @@ fn NewHTTPContext(comptime ssl: bool) type { ); } else { // trailing zero is fine to ignore - if (strings.eqlComptime(buf, "0\r\n")) { + if (strings.eqlComptime(buf, end_of_chunked_http1_1_encoding_response_body)) { return; } @@ -527,11 +529,10 @@ pub fn onClose( // a missing 0\r\n chunk if (in_progress and client.state.transfer_encoding == .chunked) { if (picohttp.phr_decode_chunked_is_in_data(&client.state.chunked_decoder) == 0) { - if (client.state.compressed_body orelse client.state.body_out_str) |body| { - if (body.list.items.len > 0) { - client.done(comptime is_ssl, if (is_ssl) &http_thread.https_context else &http_thread.http_context, socket); - return; - } + var buf = client.state.getBodyBuffer(); + if (buf.list.items.len > 0) { + client.done(comptime is_ssl, if (is_ssl) &http_thread.https_context else &http_thread.http_context, socket); + return; } } } @@ -542,8 +543,9 @@ pub fn onClose( return; } - if (in_progress) + if (in_progress) { client.fail(error.ConnectionClosed); + } } pub fn onTimeout( client: *HTTPClient, @@ -628,7 +630,7 @@ pub const HTTPStage = enum { }; pub const InternalState = struct { - request_message: ?*BodyPreamblePool.Node = null, + response_message_buffer: MutableString = undefined, pending_response: picohttp.Response = undefined, allow_keepalive: bool = true, transfer_encoding: Encoding = Encoding.identity, @@ -637,7 +639,7 @@ pub const InternalState = struct { chunked_decoder: picohttp.phr_chunked_decoder = .{}, stage: Stage = Stage.pending, body_out_str: ?*MutableString = null, - compressed_body: ?*MutableString = null, + compressed_body: MutableString = undefined, body_size: usize = 0, request_body: []const u8 = "", request_sent_len: usize = 0, @@ -645,31 +647,36 @@ pub const InternalState = struct { request_stage: HTTPStage = .pending, response_stage: HTTPStage = .pending, - pub fn reset(this: *InternalState) void { - if (this.request_message) |msg| { - msg.release(); - this.request_message = null; - } + pub fn init(body: []const u8, body_out_str: *MutableString) InternalState { + return .{ + .request_body = body, + .compressed_body = MutableString{ .allocator = default_allocator, .list = .{} }, + .response_message_buffer = MutableString{ .allocator = default_allocator, .list = .{} }, + .body_out_str = body_out_str, + .stage = Stage.pending, + .pending_response = picohttp.Response{}, + }; + } - if (this.compressed_body) |body| { - ZlibPool.put(body); - this.compressed_body = null; - } + pub fn reset(this: *InternalState) void { + this.compressed_body.deinit(); + this.response_message_buffer.deinit(); var body_msg = this.body_out_str; + if (body_msg) |body| body.reset(); + this.* = .{ .body_out_str = body_msg, + .compressed_body = MutableString{ .allocator = default_allocator, .list = .{} }, + .response_message_buffer = MutableString{ .allocator = default_allocator, .list = .{} }, + .request_body = "", }; } pub fn getBodyBuffer(this: *InternalState) *MutableString { switch (this.encoding) { Encoding.gzip, Encoding.deflate => { - if (this.compressed_body == null) { - this.compressed_body = ZlibPool.get(default_allocator); - } - - return this.compressed_body.?; + return &this.compressed_body; }, else => { return this.body_out_str.?; @@ -677,32 +684,48 @@ pub const InternalState = struct { } } + fn decompress(this: *InternalState, buffer: MutableString, body_out_str: *MutableString) !void { + defer this.compressed_body.deinit(); + + var gzip_timer: std.time.Timer = undefined; + + if (extremely_verbose) + gzip_timer = std.time.Timer.start() catch @panic("Timer failure"); + + body_out_str.list.expandToCapacity(); + + ZlibPool.decompress(buffer.list.items, body_out_str, default_allocator) catch |err| { + Output.prettyErrorln("<r><red>Zlib error: {s}<r>", .{std.mem.span(@errorName(err))}); + Output.flush(); + return err; + }; + + if (extremely_verbose) + this.gzip_elapsed = gzip_timer.read(); + } + pub fn processBodyBuffer(this: *InternalState, buffer: MutableString) !void { var body_out_str = this.body_out_str.?; - var buffer_ = this.getBodyBuffer(); - buffer_.* = buffer; switch (this.encoding) { Encoding.gzip, Encoding.deflate => { - var gzip_timer: std.time.Timer = undefined; - - if (extremely_verbose) - gzip_timer = std.time.Timer.start() catch @panic("Timer failure"); - - body_out_str.list.expandToCapacity(); - defer ZlibPool.put(buffer_); - ZlibPool.decompress(buffer_.list.items, body_out_str) catch |err| { - Output.prettyErrorln("<r><red>Zlib error<r>", .{}); - Output.flush(); - return err; - }; - - if (extremely_verbose) - this.gzip_elapsed = gzip_timer.read(); + try this.decompress(buffer, body_out_str); + }, + else => { + if (!body_out_str.owns(buffer.list.items)) { + body_out_str.append(buffer.list.items) catch |err| { + Output.prettyErrorln("<r><red>Failed to append to body buffer: {s}<r>", .{std.mem.span(@errorName(err))}); + Output.flush(); + return err; + }; + } }, - else => {}, } + this.postProcessBody(body_out_str); + } + + pub fn postProcessBody(this: *InternalState, body_out_str: *MutableString) void { var response = &this.pending_response; // if it compressed with this header, it is no longer if (this.content_encoding_i < response.headers.len) { @@ -768,6 +791,9 @@ pub fn deinit(this: *HTTPClient) void { redirect.release(); this.redirect = null; } + + this.state.compressed_body.deinit(); + this.state.response_message_buffer.deinit(); } const Stage = enum(u8) { @@ -812,6 +838,14 @@ pub const Encoding = enum { deflate, brotli, chunked, + + pub fn isCompressed(this: Encoding) bool { + return switch (this) { + // we don't support brotli yet + .gzip, .deflate => true, + else => false, + }; + } }; const content_encoding_hash = hashHeaderName("Content-Encoding"); @@ -1067,9 +1101,6 @@ pub const AsyncHTTP = struct { } }; -const BodyPreambleArray = std.BoundedArray(u8, 1024 * 16); -const BodyPreamblePool = ObjectPool(BodyPreambleArray, null, false, 16); - pub fn buildRequest(this: *HTTPClient, body_len: usize) picohttp.Request { var header_count: usize = 0; var header_entries = this.header_entries.slice(); @@ -1189,15 +1220,8 @@ pub fn doRedirect(this: *HTTPClient) void { pub fn start(this: *HTTPClient, body: []const u8, body_out_str: *MutableString) void { body_out_str.reset(); - std.debug.assert(this.state.request_message == null); - this.state = InternalState{ - .request_body = body, - .body_out_str = body_out_str, - .stage = Stage.pending, - .request_message = null, - .pending_response = picohttp.Response{}, - .compressed_body = null, - }; + std.debug.assert(this.state.response_message_buffer.list.capacity == 0); + this.state = InternalState.init(body, body_out_str); if (this.url.isHTTPS()) { this.start_(true); @@ -1352,23 +1376,13 @@ pub fn onData(this: *HTTPClient, comptime is_ssl: bool, incoming_data: []const u switch (this.state.response_stage) { .pending, .headers => { var to_read = incoming_data; - var pending_buffers: [2]string = .{ "", "" }; var amount_read: usize = 0; var needs_move = true; - if (this.state.request_message) |req_msg| { - var available = req_msg.data.unusedCapacitySlice(); - if (available.len == 0) { - this.state.request_message.?.release(); - this.state.request_message = null; - this.closeAndFail(error.ResponseHeaderTooLarge, is_ssl, socket); - return; - } - - const to_read_len = @minimum(available.len, to_read.len); - req_msg.data.appendSliceAssumeCapacity(to_read[0..to_read_len]); - to_read = req_msg.data.slice(); - pending_buffers[1] = incoming_data[to_read_len..]; - needs_move = pending_buffers[1].len > 0; + if (this.state.response_message_buffer.list.items.len > 0) { + // this one probably won't be another chunk, so we use appendSliceExact() to avoid over-allocating + this.state.response_message_buffer.appendSliceExact(incoming_data) catch @panic("Out of memory"); + to_read = this.state.response_message_buffer.list.items; + needs_move = false; } this.state.pending_response = picohttp.Response{}; @@ -1384,15 +1398,8 @@ pub fn onData(this: *HTTPClient, comptime is_ssl: bool, incoming_data: []const u const to_copy = incoming_data; if (to_copy.len > 0) { - this.state.request_message = this.state.request_message orelse brk: { - var preamble = BodyPreamblePool.get(getAllocator()); - preamble.data = .{}; - break :brk preamble; - }; - this.state.request_message.?.data.appendSlice(to_copy) catch { - this.closeAndFail(error.ResponseHeadersTooLarge, is_ssl, socket); - return; - }; + // this one will probably be another chunk, so we leave a little extra room + this.state.response_message_buffer.append(to_copy) catch @panic("Out of memory"); } } @@ -1407,11 +1414,7 @@ pub fn onData(this: *HTTPClient, comptime is_ssl: bool, incoming_data: []const u this.state.pending_response = response; - pending_buffers[0] = to_read[@minimum(@intCast(usize, response.bytes_read), to_read.len)..]; - if (pending_buffers[0].len == 0 and pending_buffers[1].len > 0) { - pending_buffers[0] = pending_buffers[1]; - pending_buffers[1] = ""; - } + var body_buf = to_read[@minimum(@intCast(usize, response.bytes_read), to_read.len)..]; var deferred_redirect: ?*URLBufferPool.Node = null; const can_continue = this.handleResponseMetadata( @@ -1424,10 +1427,7 @@ pub fn onData(this: *HTTPClient, comptime is_ssl: bool, incoming_data: []const u &deferred_redirect, ) catch |err| { if (err == error.Redirect) { - if (this.state.request_message) |msg| { - msg.release(); - this.state.request_message = null; - } + this.state.response_message_buffer.deinit(); if (this.state.allow_keepalive and FeatureFlags.enable_keepalive) { std.debug.assert(this.connected_url.hostname.len > 0); @@ -1461,25 +1461,13 @@ pub fn onData(this: *HTTPClient, comptime is_ssl: bool, incoming_data: []const u return; } - if (pending_buffers[0].len == 0) { + if (body_buf.len == 0) { return; } if (this.state.response_stage == .body) { { - const is_done = this.handleResponseBody(pending_buffers[0]) catch |err| { - this.closeAndFail(err, is_ssl, socket); - return; - }; - - if (is_done) { - this.done(is_ssl, ctx, socket); - return; - } - } - - if (pending_buffers[1].len > 0) { - const is_done = this.handleResponseBody(pending_buffers[1]) catch |err| { + const is_done = this.handleResponseBody(body_buf, true) catch |err| { this.closeAndFail(err, is_ssl, socket); return; }; @@ -1492,7 +1480,7 @@ pub fn onData(this: *HTTPClient, comptime is_ssl: bool, incoming_data: []const u } else if (this.state.response_stage == .body_chunk) { this.setTimeout(socket, 500); { - const is_done = this.handleResponseBodyChunk(pending_buffers[0]) catch |err| { + const is_done = this.handleResponseBodyChunkedEncoding(body_buf) catch |err| { this.closeAndFail(err, is_ssl, socket); return; }; @@ -1502,27 +1490,13 @@ pub fn onData(this: *HTTPClient, comptime is_ssl: bool, incoming_data: []const u return; } } - - if (pending_buffers[1].len > 0) { - const is_done = this.handleResponseBodyChunk(pending_buffers[1]) catch |err| { - this.closeAndFail(err, is_ssl, socket); - return; - }; - - if (is_done) { - this.done(is_ssl, ctx, socket); - return; - } - } - - this.setTimeout(socket, 60); } }, .body => { this.setTimeout(socket, 60); - const is_done = this.handleResponseBody(incoming_data) catch |err| { + const is_done = this.handleResponseBody(incoming_data, false) catch |err| { this.closeAndFail(err, is_ssl, socket); return; }; @@ -1536,7 +1510,7 @@ pub fn onData(this: *HTTPClient, comptime is_ssl: bool, incoming_data: []const u .body_chunk => { this.setTimeout(socket, 500); - const is_done = this.handleResponseBodyChunk(incoming_data) catch |err| { + const is_done = this.handleResponseBodyChunkedEncoding(incoming_data) catch |err| { this.closeAndFail(err, is_ssl, socket); return; }; @@ -1709,7 +1683,51 @@ pub fn toResult(this: *HTTPClient, metadata: HTTPResponseMetadata) HTTPClientRes // never finishing sending the body const preallocate_max = 1024 * 1024 * 256; -pub fn handleResponseBody(this: *HTTPClient, incoming_data: []const u8) !bool { +pub fn handleResponseBody(this: *HTTPClient, incoming_data: []const u8, is_only_buffer: bool) !bool { + std.debug.assert(this.state.transfer_encoding == .identity); + + // is it exactly as much as we need? + if (is_only_buffer and incoming_data.len >= this.state.body_size) { + try handleResponseBodyFromSinglePacket(this, incoming_data[0..this.state.body_size]); + return true; + } else { + return handleResponseBodyFromMultiplePackets(this, incoming_data); + } +} + +fn handleResponseBodyFromSinglePacket(this: *HTTPClient, incoming_data: []const u8) !void { + if (this.state.encoding.isCompressed()) { + var body_buffer = this.state.body_out_str.?; + if (body_buffer.list.capacity == 0) { + const min = @minimum(@ceil(@intToFloat(f64, incoming_data.len) * 1.5), @as(f64, 1024 * 1024 * 2)); + try body_buffer.growBy(@maximum(@floatToInt(usize, min), 32)); + } + + try ZlibPool.decompress(incoming_data, body_buffer, default_allocator); + } else { + try this.state.getBodyBuffer().appendSliceExact(incoming_data); + } + + if (this.state.response_message_buffer.owns(incoming_data)) { + if (comptime Environment.allow_assert) { + // i'm not sure why this would happen and i haven't seen it happen + // but we should check + std.debug.assert(this.state.getBodyBuffer().list.items.ptr != this.state.response_message_buffer.list.items.ptr); + } + + this.state.response_message_buffer.deinit(); + } + + if (this.progress_node) |progress| { + progress.activate(); + progress.setCompletedItems(incoming_data.len); + progress.context.maybeRefresh(); + } + + this.state.postProcessBody(this.state.getBodyBuffer()); +} + +fn handleResponseBodyFromMultiplePackets(this: *HTTPClient, incoming_data: []const u8) !bool { var buffer = this.state.getBodyBuffer(); if (buffer.list.items.len == 0 and @@ -1745,7 +1763,18 @@ pub fn handleResponseBody(this: *HTTPClient, incoming_data: []const u8) !bool { return false; } -pub fn handleResponseBodyChunk( +pub fn handleResponseBodyChunkedEncoding( + this: *HTTPClient, + incoming_data: []const u8, +) !bool { + if (incoming_data.len <= single_packet_small_buffer.len and this.state.getBodyBuffer().list.items.len == 0) { + return try this.handleResponseBodyChunkedEncodingFromSinglePacket(incoming_data); + } else { + return try this.handleResponseBodyChunkedEncodingFromMultiplePackets(incoming_data); + } +} + +fn handleResponseBodyChunkedEncodingFromMultiplePackets( this: *HTTPClient, incoming_data: []const u8, ) !bool { @@ -1762,10 +1791,11 @@ pub fn handleResponseBodyChunk( // phr_decode_chunked mutates in-place const pret = picohttp.phr_decode_chunked( decoder, - buffer.list.items.ptr + (buffer.list.items.len - incoming_data.len), + buffer.list.items.ptr + (buffer.list.items.len -| incoming_data.len), &bytes_decoded, ); buffer.list.items.len -|= incoming_data.len - bytes_decoded; + buffer_.* = buffer; switch (pret) { // Invalid HTTP response body @@ -1780,11 +1810,6 @@ pub fn handleResponseBodyChunk( progress.context.maybeRefresh(); } - if (this.state.compressed_body) |compressed| { - compressed.* = buffer; - } else { - this.state.body_out_str.?.* = buffer; - } return false; }, // Done @@ -1806,6 +1831,74 @@ pub fn handleResponseBodyChunk( unreachable; } +// the first packet for Transfer-Encoding: chunked +// is usually pretty small or sometimes even just a length +// so we can avoid allocating a temporary buffer to copy the data in +var single_packet_small_buffer: [16 * 1024]u8 = undefined; +fn handleResponseBodyChunkedEncodingFromSinglePacket( + this: *HTTPClient, + incoming_data: []const u8, +) !bool { + var decoder = &this.state.chunked_decoder; + std.debug.assert(incoming_data.len <= single_packet_small_buffer.len); + + // set consume_trailer to 1 to discard the trailing header + // using content-encoding per chunk is not supported + decoder.consume_trailer = 1; + + var buffer: []u8 = undefined; + + if ( + // if we've already copied the buffer once, we can avoid copying it again. + this.state.response_message_buffer.owns(incoming_data)) { + buffer = bun.constStrToU8(incoming_data); + } else { + buffer = single_packet_small_buffer[0..incoming_data.len]; + @memcpy(buffer.ptr, incoming_data.ptr, incoming_data.len); + } + + var bytes_decoded = incoming_data.len; + // phr_decode_chunked mutates in-place + const pret = picohttp.phr_decode_chunked( + decoder, + buffer.ptr + (buffer.len -| incoming_data.len), + &bytes_decoded, + ); + buffer.len -|= incoming_data.len - bytes_decoded; + + switch (pret) { + // Invalid HTTP response body + -1 => { + return error.InvalidHTTPResponse; + }, + // Needs more data + -2 => { + if (this.progress_node) |progress| { + progress.activate(); + progress.setCompletedItems(buffer.len); + progress.context.maybeRefresh(); + } + try this.state.getBodyBuffer().appendSliceExact(buffer); + + return false; + }, + // Done + else => { + try this.handleResponseBodyFromSinglePacket(buffer); + std.debug.assert(this.state.body_out_str.?.list.items.ptr != buffer.ptr); + if (this.progress_node) |progress| { + progress.activate(); + progress.setCompletedItems(buffer.len); + progress.context.maybeRefresh(); + } + + return true; + }, + } + + unreachable; +} + pub fn handleResponseMetadata( this: *HTTPClient, response: picohttp.Response, @@ -1876,34 +1969,82 @@ pub fn handleResponseMetadata( if (strings.indexOf(location, "://")) |i| { var url_buf = URLBufferPool.get(default_allocator); - const protocol_name = location[0..i]; - if (strings.eqlComptime(protocol_name, "http") or strings.eqlComptime(protocol_name, "https")) {} else { + const is_protocol_relative = i == 0; + const protocol_name = if (is_protocol_relative) this.url.displayProtocol() else location[0..i]; + const is_http = strings.eqlComptime(protocol_name, "http"); + if (is_http or strings.eqlComptime(protocol_name, "https")) {} else { return error.UnsupportedRedirectProtocol; } - if (location.len > url_buf.data.len) { + if ((protocol_name.len * @as(usize, @boolToInt(is_protocol_relative))) + location.len > url_buf.data.len) { + return error.RedirectURLTooLong; + } + + deferred_redirect.* = this.redirect; + var url_buf_len = location.len; + if (is_protocol_relative) { + if (is_http) { + url_buf.data[0.."http".len].* = "http".*; + std.mem.copy(u8, url_buf.data["http".len..], location); + url_buf_len += "http".len; + } else { + url_buf.data[0.."https".len].* = "https".*; + std.mem.copy(u8, url_buf.data["https".len..], location); + url_buf_len += "https".len; + } + } else { + std.mem.copy(u8, &url_buf.data, location); + } + + this.url = URL.parse(url_buf.data[0..url_buf_len]); + this.redirect = url_buf; + } else if (strings.hasPrefixComptime(location, "//")) { + var url_buf = URLBufferPool.get(default_allocator); + + const protocol_name = this.url.displayProtocol(); + + if (protocol_name.len + 1 + location.len > url_buf.data.len) { return error.RedirectURLTooLong; } deferred_redirect.* = this.redirect; - std.mem.copy(u8, &url_buf.data, location); - this.url = URL.parse(url_buf.data[0..location.len]); + var url_buf_len = location.len; + + if (strings.eqlComptime(protocol_name, "http")) { + url_buf.data[0.."http:".len].* = "http:".*; + std.mem.copy(u8, url_buf.data["http:".len..], location); + url_buf_len += "http:".len; + } else { + url_buf.data[0.."https:".len].* = "https:".*; + std.mem.copy(u8, url_buf.data["https:".len..], location); + url_buf_len += "https:".len; + } + + this.url = URL.parse(url_buf.data[0..url_buf_len]); this.redirect = url_buf; } else { var url_buf = URLBufferPool.get(default_allocator); const original_url = this.url; - this.url = URL.parse(std.fmt.bufPrint( - &url_buf.data, - "{s}://{s}{s}", - .{ original_url.displayProtocol(), original_url.displayHostname(), location }, - ) catch return error.RedirectURLTooLong); + const port = original_url.getPortAuto(); + + if (port == original_url.getDefaultPort()) { + this.url = URL.parse(std.fmt.bufPrint( + &url_buf.data, + "{s}://{s}{s}", + .{ original_url.displayProtocol(), original_url.displayHostname(), location }, + ) catch return error.RedirectURLTooLong); + } else { + this.url = URL.parse(std.fmt.bufPrint( + &url_buf.data, + "{s}://{s}:{d}{s}", + .{ original_url.displayProtocol(), original_url.displayHostname(), port, location }, + ) catch return error.RedirectURLTooLong); + } deferred_redirect.* = this.redirect; this.redirect = url_buf; } - // Ensure we don't up ove - // https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/303 if (response.status_code == 303) { this.method = .GET; diff --git a/src/install/install.zig b/src/install/install.zig index bac5835cf..edfb4da42 100644 --- a/src/install/install.zig +++ b/src/install/install.zig @@ -4493,7 +4493,7 @@ pub const PackageManager = struct { }; if (manager.options.log_level != .silent) { - Output.prettyErrorln("<r><b>bun link <r><d>v" ++ Global.package_json_version ++ "<r>\n", .{}); + Output.prettyErrorln("<r><b>bun link <r><d>v" ++ Global.package_json_version_with_sha ++ "<r>\n", .{}); Output.flush(); } @@ -4643,7 +4643,7 @@ pub const PackageManager = struct { }; if (manager.options.log_level != .silent) { - Output.prettyErrorln("<r><b>bun unlink <r><d>v" ++ Global.package_json_version ++ "<r>\n", .{}); + Output.prettyErrorln("<r><b>bun unlink <r><d>v" ++ Global.package_json_version_with_sha ++ "<r>\n", .{}); Output.flush(); } @@ -5105,7 +5105,7 @@ pub const PackageManager = struct { }; if (manager.options.log_level != .silent) { - Output.prettyErrorln("<r><b>bun " ++ @tagName(op) ++ " <r><d>v" ++ Global.package_json_version ++ "<r>\n", .{}); + Output.prettyErrorln("<r><b>bun " ++ @tagName(op) ++ " <r><d>v" ++ Global.package_json_version_with_sha ++ "<r>\n", .{}); Output.flush(); } @@ -5513,7 +5513,7 @@ pub const PackageManager = struct { }; if (manager.options.log_level != .silent) { - Output.prettyErrorln("<r><b>bun install <r><d>v" ++ Global.package_json_version ++ "<r>\n", .{}); + Output.prettyErrorln("<r><b>bun install <r><d>v" ++ Global.package_json_version_with_sha ++ "<r>\n", .{}); Output.flush(); } diff --git a/src/install/semver.zig b/src/install/semver.zig index 813ee1a8e..37af5c7e2 100644 --- a/src/install/semver.zig +++ b/src/install/semver.zig @@ -211,7 +211,7 @@ pub const String = extern struct { buf: string, in: string, ) Pointer { - std.debug.assert(@ptrToInt(buf.ptr) <= @ptrToInt(in.ptr) and ((@ptrToInt(in.ptr) + in.len) <= (@ptrToInt(buf.ptr) + buf.len))); + std.debug.assert(bun.isSliceInBuffer(in, buf)); return Pointer{ .off = @truncate(u32, @ptrToInt(in.ptr) - @ptrToInt(buf.ptr)), diff --git a/src/js_ast.zig b/src/js_ast.zig index 0bd73c93f..0ca11272a 100644 --- a/src/js_ast.zig +++ b/src/js_ast.zig @@ -7128,7 +7128,7 @@ pub const Macro = struct { while (i < count) { var nextArg = writer.eatArg() orelse return false; if (js.JSValueIsArray(writer.ctx, nextArg.asRef())) { - const extras = nextArg.getLengthOfArray(writer.ctx.ptr()); + const extras = @truncate(u32, nextArg.getLengthOfArray(writer.ctx.ptr())); count += std.math.max(@truncate(@TypeOf(count), extras), 1) - 1; items.ensureUnusedCapacity(extras) catch unreachable; items.expandToCapacity(); @@ -7511,7 +7511,7 @@ pub const Macro = struct { .allocator = JSCBase.getAllocator(ctx), .exception = exception, .args_value = args_value, - .args_len = args_value.getLengthOfArray(ctx.ptr()), + .args_len = @truncate(u32, args_value.getLengthOfArray(ctx.ptr())), .args_i = 0, .errored = false, }; diff --git a/src/js_lexer.zig b/src/js_lexer.zig index 134497421..c41159612 100644 --- a/src/js_lexer.zig +++ b/src/js_lexer.zig @@ -1900,7 +1900,7 @@ fn NewLexer_( const flag = max_flag - @intCast(u8, lexer.code_point); if (flags.isSet(flag)) { lexer.addError( - lexer.regex_flags_start.?, + lexer.current, "Duplicate flag \"{u}\" in regular expression", .{@intCast(u21, lexer.code_point)}, false, @@ -1911,7 +1911,14 @@ fn NewLexer_( lexer.step(); }, else => { - try lexer.syntaxError(); + lexer.addError( + lexer.current, + "Invalid flag \"{u}\" in regular expression", + .{@intCast(u21, lexer.code_point)}, + false, + ); + + lexer.step(); }, } } diff --git a/src/js_parser.zig b/src/js_parser.zig index d88a9cc1a..3a7707d67 100644 --- a/src/js_parser.zig +++ b/src/js_parser.zig @@ -2531,7 +2531,7 @@ pub const Parser = struct { { const jsx_symbol = p.symbols.items[p.jsx_runtime.ref.innerIndex()]; - const jsx_static_symbol = p.symbols.items[p.jsxs_runtime.ref.innerIndex()]; + const jsx_fragment_symbol = p.symbols.items[p.jsx_fragment.ref.innerIndex()]; const jsx_factory_symbol = p.symbols.items[p.jsx_factory.ref.innerIndex()]; @@ -2542,10 +2542,18 @@ pub const Parser = struct { // So a jsx_symbol usage means a jsx_factory_symbol usage // This is kind of a broken way of doing it because it wouldn't work if it was more than one level deep if (FeatureFlags.jsx_runtime_is_cjs) { - if (jsx_symbol.use_count_estimate > 0 or jsx_static_symbol.use_count_estimate > 0) { + if (jsx_symbol.use_count_estimate > 0) { p.recordUsage(p.jsx_automatic.ref); } + if (FeatureFlags.support_jsxs_in_jsx_transform) { + const jsx_static_symbol = p.symbols.items[p.jsxs_runtime.ref.innerIndex()]; + + if (jsx_static_symbol.use_count_estimate > 0) { + p.recordUsage(p.jsx_automatic.ref); + } + } + if (jsx_fragment_symbol.use_count_estimate > 0) { p.recordUsage(p.jsx_classic.ref); } @@ -2576,7 +2584,11 @@ pub const Parser = struct { // p.symbols may grow during this scope // if it grows, the previous pointers are invalidated const jsx_symbol = p.symbols.items[p.jsx_runtime.ref.innerIndex()]; - const jsx_static_symbol = p.symbols.items[p.jsxs_runtime.ref.innerIndex()]; + const jsx_static_symbol: Symbol = if (!FeatureFlags.support_jsxs_in_jsx_transform) + undefined + else + p.symbols.items[p.jsxs_runtime.ref.innerIndex()]; + const jsx_fragment_symbol = p.symbols.items[p.jsx_fragment.ref.innerIndex()]; const jsx_factory_symbol = p.symbols.items[p.jsx_factory.ref.innerIndex()]; @@ -2590,7 +2602,7 @@ pub const Parser = struct { // "JSX" @intCast(u32, @boolToInt(jsx_symbol.use_count_estimate > 0)) * 2 + - @intCast(u32, @boolToInt(jsx_static_symbol.use_count_estimate > 0)) * 2 + + @intCast(u32, @boolToInt(FeatureFlags.support_jsxs_in_jsx_transform and jsx_static_symbol.use_count_estimate > 0)) * 2 + @intCast(u32, @boolToInt(jsx_factory_symbol.use_count_estimate > 0)) + @intCast(u32, @boolToInt(jsx_fragment_symbol.use_count_estimate > 0)) + @intCast(u32, @boolToInt(jsx_filename_symbol.use_count_estimate > 0)); @@ -2600,7 +2612,7 @@ pub const Parser = struct { @intCast(u32, @boolToInt(jsx_classic_symbol.use_count_estimate > 0)) + @intCast(u32, @boolToInt(jsx_fragment_symbol.use_count_estimate > 0)) + @intCast(u32, @boolToInt(p.options.features.react_fast_refresh)) + - @intCast(u32, @boolToInt(jsx_static_symbol.use_count_estimate > 0)); + @intCast(u32, @boolToInt(FeatureFlags.support_jsxs_in_jsx_transform and jsx_static_symbol.use_count_estimate > 0)); const stmts_count = imports_count + 1; const symbols_count: u32 = imports_count + decls_count; const loc = logger.Loc{ .start = 0 }; @@ -2663,7 +2675,7 @@ pub const Parser = struct { decl_i += 1; } - if (jsx_symbol.use_count_estimate > 0 or jsx_static_symbol.use_count_estimate > 0) { + if (jsx_symbol.use_count_estimate > 0 or (FeatureFlags.support_jsxs_in_jsx_transform and jsx_static_symbol.use_count_estimate > 0)) { declared_symbols[declared_symbols_i] = .{ .ref = automatic_namespace_ref, .is_top_level = true }; declared_symbols_i += 1; @@ -2711,31 +2723,32 @@ pub const Parser = struct { decl_i += 1; } - if (jsx_static_symbol.use_count_estimate > 0) { - declared_symbols[declared_symbols_i] = .{ .ref = p.jsxs_runtime.ref, .is_top_level = true }; - declared_symbols_i += 1; + if (FeatureFlags.support_jsxs_in_jsx_transform) { + if (jsx_static_symbol.use_count_estimate > 0) { + declared_symbols[declared_symbols_i] = .{ .ref = p.jsxs_runtime.ref, .is_top_level = true }; + declared_symbols_i += 1; - decls[decl_i] = G.Decl{ - .binding = p.b( - B.Identifier{ - .ref = p.jsxs_runtime.ref, - }, - loc, - ), - .value = p.e( - E.Dot{ - .target = dot_call_target, - .name = p.options.jsx.jsx_static, - .name_loc = loc, - .can_be_removed_if_unused = true, - }, - loc, - ), - }; + decls[decl_i] = G.Decl{ + .binding = p.b( + B.Identifier{ + .ref = p.jsxs_runtime.ref, + }, + loc, + ), + .value = p.e( + E.Dot{ + .target = dot_call_target, + .name = p.options.jsx.jsx_static, + .name_loc = loc, + .can_be_removed_if_unused = true, + }, + loc, + ), + }; - decl_i += 1; + decl_i += 1; + } } - if (jsx_filename_symbol.use_count_estimate > 0) { declared_symbols[declared_symbols_i] = .{ .ref = p.jsx_filename.ref, .is_top_level = true }; declared_symbols_i += 1; @@ -5008,7 +5021,8 @@ fn NewParser_( } p.jsx_fragment = p.declareGeneratedSymbol(.other, "Fragment") catch unreachable; p.jsx_runtime = p.declareGeneratedSymbol(.other, "jsx") catch unreachable; - p.jsxs_runtime = p.declareGeneratedSymbol(.other, "jsxs") catch unreachable; + if (comptime FeatureFlags.support_jsxs_in_jsx_transform) + p.jsxs_runtime = p.declareGeneratedSymbol(.other, "jsxs") catch unreachable; p.jsx_factory = p.declareGeneratedSymbol(.other, "Factory") catch unreachable; if (p.options.jsx.factory.len > 1 or FeatureFlags.jsx_runtime_is_cjs) { @@ -5105,7 +5119,8 @@ fn NewParser_( } } p.resolveGeneratedSymbol(&p.jsx_runtime); - p.resolveGeneratedSymbol(&p.jsxs_runtime); + if (FeatureFlags.support_jsxs_in_jsx_transform) + p.resolveGeneratedSymbol(&p.jsxs_runtime); p.resolveGeneratedSymbol(&p.jsx_factory); p.resolveGeneratedSymbol(&p.jsx_fragment); p.resolveGeneratedSymbol(&p.jsx_classic); @@ -15825,7 +15840,7 @@ fn NewParser_( } fn jsxRefToMemberExpressionAutomatic(p: *P, loc: logger.Loc, is_static: bool) Expr { - return p.jsxRefToMemberExpression(loc, if (is_static and !p.options.jsx.development) + return p.jsxRefToMemberExpression(loc, if (is_static and !p.options.jsx.development and FeatureFlags.support_jsxs_in_jsx_transform) p.jsxs_runtime.ref else p.jsx_runtime.ref); diff --git a/src/js_printer.zig b/src/js_printer.zig index 79faa989b..d7e8dacb8 100644 --- a/src/js_printer.zig +++ b/src/js_printer.zig @@ -1399,7 +1399,7 @@ pub fn NewPrinter( defer if (wrap) p.print(")"); assert(p.import_records.len > import_record_index); - const record = p.import_records[import_record_index]; + const record = &p.import_records[import_record_index]; if (comptime is_bun_platform) { // "bun" is not a real module. It's just globalThis.Bun. @@ -1444,7 +1444,7 @@ pub fn NewPrinter( } p.print("("); - p.printImportRecordPath(&record); + p.printImportRecordPath(record); p.print(")"); return; } @@ -1462,7 +1462,7 @@ pub fn NewPrinter( // Allow it to fail at runtime, if it should p.print("import("); - p.printImportRecordPath(&record); + p.printImportRecordPath(record); p.print(")"); if (leading_interior_comments.len > 0) { @@ -3713,9 +3713,11 @@ pub fn NewPrinter( p.needs_semicolon = false; }, .s_import => |s| { + std.debug.assert(s.import_record_index < p.import_records.len); + + const record: *const ImportRecord = &p.import_records[s.import_record_index]; - // TODO: check loader instead - switch (p.import_records[s.import_record_index].print_mode) { + switch (record.print_mode) { .css => { switch (p.options.css_import_behavior) { .facade => { @@ -3724,7 +3726,7 @@ pub fn NewPrinter( // To parse this, you just look for a line that starts with //@import url(" p.print("//@import url(\""); // We do not URL escape here. - p.print(p.import_records[s.import_record_index].path.text); + p.print(record.path.text); // If they actually use the code, then we emit a facade that just echos whatever they write if (s.default_name) |name| { @@ -3740,7 +3742,7 @@ pub fn NewPrinter( .auto_onimportcss, .facade_onimportcss => { p.print("globalThis.document?.dispatchEvent(new CustomEvent(\"onimportcss\", {detail: \""); - p.print(p.import_records[s.import_record_index].path.text); + p.print(record.path.text); p.print("\"}));\n"); // If they actually use the code, then we emit a facade that just echos whatever they write @@ -3759,14 +3761,14 @@ pub fn NewPrinter( p.print("var "); p.printSymbol(name.ref.?); p.print(" = "); - p.printImportRecordPath(&p.import_records[s.import_record_index]); + p.printImportRecordPath(record); p.printSemicolonAfterStatement(); - } else if (p.import_records[s.import_record_index].contains_import_star) { + } else if (record.contains_import_star) { // this case is particularly important for running files without an extension in bun's runtime p.print("var "); p.printSymbol(s.namespace_ref); p.print(" = {default:"); - p.printImportRecordPath(&p.import_records[s.import_record_index]); + p.printImportRecordPath(record); p.print("}"); p.printSemicolonAfterStatement(); } @@ -3774,24 +3776,19 @@ pub fn NewPrinter( }, .napi_module => { if (comptime is_bun_platform) { - const import_record = &p.import_records[s.import_record_index]; - - if (import_record.print_mode == .napi_module) { - p.printIndent(); - p.print("var "); - p.printSymbol(s.namespace_ref); - p.print(" = import.meta.require("); - p.printImportRecordPath(import_record); - p.print(")"); - p.printSemicolonAfterStatement(); - } + p.printIndent(); + p.print("var "); + p.printSymbol(s.namespace_ref); + p.print(" = import.meta.require("); + p.printImportRecordPath(record); + p.print(")"); + p.printSemicolonAfterStatement(); } return; }, else => {}, } - const record = p.import_records[s.import_record_index]; var item_count: usize = 0; p.printIndent(); @@ -3816,7 +3813,7 @@ pub fn NewPrinter( } if (is_inside_bundle) { - return p.printBundledImport(record, s); + return p.printBundledImport(record.*, s); } if (record.do_commonjs_transform_in_printer or record.path.is_disabled) { @@ -3937,7 +3934,7 @@ pub fn NewPrinter( p.print(" = () => ({default: {}});\n"); } - p.printBundledImport(record, s); + p.printBundledImport(record.*, s); return; } @@ -4009,7 +4006,7 @@ pub fn NewPrinter( p.printSpace(); } - p.printImportRecordPath(&p.import_records[s.import_record_index]); + p.printImportRecordPath(record); p.printSemicolonAfterStatement(); }, .s_block => |s| { diff --git a/src/jsc.zig b/src/jsc.zig index 07f5d4d26..99080603f 100644 --- a/src/jsc.zig +++ b/src/jsc.zig @@ -33,7 +33,8 @@ pub const API = struct { pub const DebugServer = @import("./bun.js/api/server.zig").DebugServer; pub const DebugSSLServer = @import("./bun.js/api/server.zig").DebugSSLServer; pub const Bun = @import("./bun.js/api/bun.zig"); - pub const Router = @import("./bun.js/api/router.zig"); + pub const FileSystemRouter = @import("./bun.js/api/filesystem_router.zig").FileSystemRouter; + pub const MatchedRoute = @import("./bun.js/api/filesystem_router.zig").MatchedRoute; pub const TCPSocket = @import("./bun.js/api/bun/socket.zig").TCPSocket; pub const TLSSocket = @import("./bun.js/api/bun/socket.zig").TLSSocket; pub const Listener = @import("./bun.js/api/bun/socket.zig").Listener; diff --git a/src/linker.lds b/src/linker.lds index f6d9c1e8c..1e1b834b9 100644 --- a/src/linker.lds +++ b/src/linker.lds @@ -1,4 +1,4 @@ -BUN_0.2 { +BUN_0.3 { global: napi*; __cxa_atexit; diff --git a/src/linker.zig b/src/linker.zig index 9855dc82c..be86ee061 100644 --- a/src/linker.zig +++ b/src/linker.zig @@ -611,15 +611,27 @@ pub const Linker = struct { var subpath_buf: [512]u8 = undefined; if (ESModule.Package.parse(import_record.path.text, &subpath_buf)) |pkg| { package_name = pkg.name; - linker.log.addResolveError( - &result.source, - import_record.range, - linker.allocator, - "Version \"{s}\" not found for package \"{s}\" (while resolving \"{s}\")", - .{ pkg.version, package_name, import_record.path.text }, - import_record.kind, - err, - ) catch {}; + if (pkg.version.len > 0) { + linker.log.addResolveError( + &result.source, + import_record.range, + linker.allocator, + "Version \"{s}\" not found for package \"{s}\" (while resolving \"{s}\")", + .{ pkg.version, package_name, import_record.path.text }, + import_record.kind, + err, + ) catch {}; + } else { + linker.log.addResolveError( + &result.source, + import_record.range, + linker.allocator, + "No matching version found for package \"{s}\" (while resolving \"{s}\")", + .{ package_name, import_record.path.text }, + import_record.kind, + err, + ) catch {}; + } } else { linker.log.addResolveError( &result.source, diff --git a/src/mimalloc_arena.zig b/src/mimalloc_arena.zig index 012d1e089..5b2fa14e8 100644 --- a/src/mimalloc_arena.zig +++ b/src/mimalloc_arena.zig @@ -7,9 +7,88 @@ const Environment = @import("./env.zig"); const FeatureFlags = @import("./feature_flags.zig"); const Allocator = mem.Allocator; const assert = std.debug.assert; +const bun = @import("./global.zig"); + +pub const GlobalArena = struct { + arena: Arena, + fallback_allocator: std.mem.Allocator, + + pub fn initWithCapacity(capacity: usize, fallback: std.mem.Allocator) error{OutOfMemory}!GlobalArena { + const arena = try Arena.initWithCapacity(capacity); + + return GlobalArena{ + .arena = arena, + .fallback_allocator = fallback, + }; + } + + pub fn allocator(this: *GlobalArena) Allocator { + return std.mem.Allocator.init(this, alloc, resize, free); + } + + fn alloc( + self: *GlobalArena, + len: usize, + ptr_align: u29, + len_align: u29, + return_address: usize, + ) error{OutOfMemory}![]u8 { + return self.arena.alloc(len, ptr_align, len_align, return_address) catch + return self.fallback_allocator.rawAlloc(len, ptr_align, len_align, return_address); + } + + fn resize( + self: *GlobalArena, + buf: []u8, + buf_align: u29, + new_len: usize, + len_align: u29, + return_address: usize, + ) ?usize { + if (self.arena.ownsPtr(buf.ptr)) { + return self.arena.resize(buf, buf_align, new_len, len_align, return_address); + } else { + return self.fallback_allocator.rawResize(buf, buf_align, new_len, len_align, return_address); + } + } + + fn free( + self: *GlobalArena, + buf: []u8, + buf_align: u29, + return_address: usize, + ) void { + if (self.arena.ownsPtr(buf.ptr)) { + return self.arena.free(buf, buf_align, return_address); + } else { + return self.fallback_allocator.rawFree(buf, buf_align, return_address); + } + } +}; pub const Arena = struct { - heap: ?*mimalloc.mi_heap_t = null, + heap: ?*mimalloc.Heap = null, + arena_id: mimalloc.ArenaID = -1, + + pub fn initWithCapacity(capacity: usize) error{OutOfMemory}!Arena { + var arena_id: mimalloc.ArenaID = -1; + + std.debug.assert(capacity >= 8 * 1024 * 1024); // mimalloc requires a minimum of 8MB + // which makes this not very useful for us! + + if (!mimalloc.mi_manage_os_memory_ex(null, capacity, true, true, false, -1, true, &arena_id)) { + if (!mimalloc.mi_manage_os_memory_ex(null, capacity, false, false, false, -1, true, &arena_id)) { + return error.OutOfMemory; + } + } + std.debug.assert(arena_id != -1); + + var heap = mimalloc.mi_heap_new_in_arena(arena_id) orelse return error.OutOfMemory; + return Arena{ + .heap = heap, + .arena_id = arena_id, + }; + } /// Internally, mimalloc calls mi_heap_get_default() /// to get the default heap. @@ -30,13 +109,31 @@ pub const Arena = struct { } pub fn deinit(this: *Arena) void { - mimalloc.mi_heap_destroy(this.heap); + mimalloc.mi_heap_destroy(this.heap.?); this.heap = null; } pub fn dumpThreadStats(_: *Arena) void { - mimalloc.mi_thread_stats_print_out(null, null); + const dump_fn = struct { + pub fn dump(textZ: [*:0]const u8, _: ?*anyopaque) callconv(.C) void { + const text = bun.span(textZ); + bun.Output.errorWriter().writeAll(text) catch {}; + } + }.dump; + mimalloc.mi_thread_stats_print_out(dump_fn, null); + bun.Output.flush(); + } + + pub fn dumpStats(_: *Arena) void { + const dump_fn = struct { + pub fn dump(textZ: [*:0]const u8, _: ?*anyopaque) callconv(.C) void { + const text = bun.span(textZ); + bun.Output.errorWriter().writeAll(text) catch {}; + } + }.dump; + mimalloc.mi_stats_print_out(dump_fn, null); + bun.Output.flush(); } pub fn reset(this: *Arena) void { @@ -49,7 +146,11 @@ pub const Arena = struct { } pub fn gc(this: Arena, force: bool) void { - mimalloc.mi_heap_collect(this.heap, force); + mimalloc.mi_heap_collect(this.heap orelse return, force); + } + + pub fn ownsPtr(this: Arena, ptr: *const anyopaque) bool { + return mimalloc.mi_heap_check_owned(this.heap.?, ptr); } // Copied from rust @@ -59,19 +160,16 @@ pub const Arena = struct { (alignment == MI_MAX_ALIGN_SIZE and size > (MI_MAX_ALIGN_SIZE / 2))); } - fn alignedAlloc(heap: *mimalloc.mi_heap_t, len: usize, alignment: usize) ?[*]u8 { + fn alignedAlloc(heap: *mimalloc.Heap, len: usize, alignment: usize) ?[*]u8 { if (comptime FeatureFlags.log_allocations) std.debug.print("Malloc: {d}\n", .{len}); // this is the logic that posix_memalign does - var ptr = if (mi_malloc_satisfies_alignment(alignment, len)) - mimalloc.mi_heap_malloc(heap, len) - else - mimalloc.mi_heap_malloc_aligned(heap, len, alignment); + var ptr = mimalloc.mi_heap_malloc_aligned(heap, len, alignment); return @ptrCast([*]u8, ptr orelse null); } - fn alloc( + pub fn alloc( arena: *anyopaque, len: usize, alignment: u29, @@ -82,7 +180,7 @@ pub const Arena = struct { assert(len > 0); assert(std.math.isPowerOfTwo(alignment)); - var ptr = alignedAlloc(@ptrCast(*mimalloc.mi_heap_t, arena), len, alignment) orelse return error.OutOfMemory; + var ptr = alignedAlloc(@ptrCast(*mimalloc.Heap, arena), len, alignment) orelse return error.OutOfMemory; if (len_align == 0) { return ptr[0..len]; } @@ -98,7 +196,7 @@ pub const Arena = struct { } } - fn resize( + pub fn resize( _: *anyopaque, buf: []u8, buf_align: u29, @@ -121,7 +219,7 @@ pub const Arena = struct { return null; } - fn free( + pub fn free( _: *anyopaque, buf: []u8, buf_align: u29, @@ -130,7 +228,8 @@ pub const Arena = struct { _ = buf_align; _ = return_address; if (comptime Environment.allow_assert) - assert(mimalloc.mi_is_in_heap_region(buf.ptr)); // memory must be allocated by mimalloc + assert(mimalloc.mi_is_in_heap_region(buf.ptr)); + mimalloc.mi_free(buf.ptr); } }; diff --git a/src/napi/napi.zig b/src/napi/napi.zig index c30f1d565..d7c7562b9 100644 --- a/src/napi/napi.zig +++ b/src/napi/napi.zig @@ -604,7 +604,7 @@ pub export fn napi_get_array_length(env: napi_env, value: napi_value, result: [* return .array_expected; } - result.* = value.getLengthOfArray(env); + result.* = @truncate(u32, value.getLengthOfArray(env)); return .ok; } pub export fn napi_strict_equals(env: napi_env, lhs: napi_value, rhs: napi_value, result: *bool) napi_status { @@ -1508,6 +1508,8 @@ pub fn fixDeadCodeElimination() void { std.mem.doNotOptimizeAway(&napi_add_finalizer); std.mem.doNotOptimizeAway(&napi_create_external); std.mem.doNotOptimizeAway(&napi_get_value_external); + std.mem.doNotOptimizeAway(&napi_get_instance_data); + std.mem.doNotOptimizeAway(&napi_set_instance_data); std.mem.doNotOptimizeAway(&@import("../bun.js/node/buffer.zig").BufferVectorized.fill); } diff --git a/src/options.zig b/src/options.zig index 24c0cdc2a..9973a7c04 100644 --- a/src/options.zig +++ b/src/options.zig @@ -840,7 +840,7 @@ pub const JSX = struct { use_embedded_refresh_runtime: bool = false, jsx: string = Defaults.JSXFunctionDev, - jsx_static: string = Defaults.JSXStaticFunction, + // jsx_static: string = Defaults.JSXStaticFunction, development: bool = true, parse: bool = true, diff --git a/src/resolver/package_json.zig b/src/resolver/package_json.zig index 5377df556..49b3ad227 100644 --- a/src/resolver/package_json.zig +++ b/src/resolver/package_json.zig @@ -732,13 +732,13 @@ pub const PackageJSON = struct { } if (json.asProperty("exports")) |exports_prop| { - if (ExportsMap.parse(r.allocator, &json_source, r.log, exports_prop.expr)) |exports_map| { + if (ExportsMap.parse(r.allocator, &json_source, r.log, exports_prop.expr, exports_prop.loc)) |exports_map| { package_json.exports = exports_map; } } if (json.asProperty("imports")) |imports_prop| { - if (ExportsMap.parse(r.allocator, &json_source, r.log, imports_prop.expr)) |imports_map| { + if (ExportsMap.parse(r.allocator, &json_source, r.log, imports_prop.expr, imports_prop.loc)) |imports_map| { package_json.imports = imports_map; } } @@ -955,8 +955,9 @@ pub const PackageJSON = struct { pub const ExportsMap = struct { root: Entry, exports_range: logger.Range = logger.Range.None, + property_key_loc: logger.Loc, - pub fn parse(allocator: std.mem.Allocator, source: *const logger.Source, log: *logger.Log, json: js_ast.Expr) ?ExportsMap { + pub fn parse(allocator: std.mem.Allocator, source: *const logger.Source, log: *logger.Log, json: js_ast.Expr, property_key_loc: logger.Loc) ?ExportsMap { var visitor = Visitor{ .allocator = allocator, .source = source, .log = log }; const root = visitor.visit(json); @@ -968,6 +969,7 @@ pub const ExportsMap = struct { return ExportsMap{ .root = root, .exports_range = source.rangeOfString(json.loc), + .property_key_loc = property_key_loc, }; } @@ -1050,7 +1052,7 @@ pub const ExportsMap = struct { map_data_ranges[i] = key_range; map_data_entries[i] = this.visit(prop.value.?); - if (strings.endsWithAnyComptime(key, "/*")) { + if (strings.endsWithComptime(key, "/") or strings.containsChar(key, '*')) { expansion_keys[expansion_key_i] = Entry.Data.Map.MapEntry{ .value = map_data_entries[i], .key = key, @@ -1063,11 +1065,12 @@ pub const ExportsMap = struct { // this leaks a lil, but it's fine. expansion_keys = expansion_keys[0..expansion_key_i]; - // Let expansion_keys be the list of keys of matchObj ending in "/" or "*", - // sorted by length descending. - const LengthSorter: type = strings.NewLengthSorter(Entry.Data.Map.MapEntry, "key"); - var sorter = LengthSorter{}; - std.sort.sort(Entry.Data.Map.MapEntry, expansion_keys, sorter, LengthSorter.lessThan); + // Let expansionKeys be the list of keys of matchObj either ending in "/" + // or containing only a single "*", sorted by the sorting function + // PATTERN_KEY_COMPARE which orders in descending order of specificity. + const GlobLengthSorter: type = strings.NewGlobLengthSorter(Entry.Data.Map.MapEntry, "key"); + var sorter = GlobLengthSorter{}; + std.sort.sort(Entry.Data.Map.MapEntry, expansion_keys, sorter, GlobLengthSorter.lessThan); return Entry{ .data = .{ @@ -1186,6 +1189,7 @@ pub const ESModule = struct { UndefinedNoConditionsMatch, // A more friendly error message for when no conditions are matched Null, Exact, + ExactEndsWithStar, Inexact, // This means we may need to try CommonJS-style extension suffixes /// Module specifier is an invalid URL, package name or package subpath specifier. @@ -1203,9 +1207,15 @@ pub const ESModule = struct { /// The package or module requested does not exist. ModuleNotFound, + /// The user just needs to add the missing extension + ModuleNotFoundMissingExtension, + /// The resolved path corresponds to a directory, which is not a supported target for module imports. UnsupportedDirectoryImport, + /// The user just needs to add the missing "/index.js" suffix + UnsupportedDirectoryImportMissingIndex, + /// When a package path is explicitly set to null, that means it's not exported. PackagePathDisabled, @@ -1383,7 +1393,7 @@ pub const ESModule = struct { pub fn finalize(result_: Resolution) Resolution { var result = result_; - if (result.status != .Exact and result.status != .Inexact) { + if (result.status != .Exact and result.status != .ExactEndsWithStar and result.status != .Inexact) { return result; } @@ -1489,7 +1499,8 @@ pub const ESModule = struct { logs.addNoteFmt("Checking object path map for \"{s}\"", .{match_key}); } - if (!strings.endsWithChar(match_key, '.')) { + // If matchKey is a key of matchObj and does not end in "/" or contain "*", then + if (!strings.endsWithChar(match_key, '/') and !strings.containsChar(match_key, '*')) { if (match_obj.valueForKey(match_key)) |target| { if (r.debug_logs) |log| { log.addNoteFmt("Found \"{s}\"", .{match_key}); @@ -1502,36 +1513,46 @@ pub const ESModule = struct { if (match_obj.data == .map) { const expansion_keys = match_obj.data.map.expansion_keys; for (expansion_keys) |expansion| { - // If expansionKey ends in "*" and matchKey starts with but is not equal to - // the substring of expansionKey excluding the last "*" character - if (strings.endsWithChar(expansion.key, '*')) { - const substr = expansion.key[0 .. expansion.key.len - 1]; - if (strings.startsWith(match_key, substr) and !strings.eql(match_key, substr)) { + + // If expansionKey contains "*", set patternBase to the substring of + // expansionKey up to but excluding the first "*" character + if (strings.indexOfChar(expansion.key, '*')) |star| { + const pattern_base = expansion.key[0..star]; + // If patternBase is not null and matchKey starts with but is not equal + // to patternBase, then + if (strings.startsWith(match_key, pattern_base)) { + // Let patternTrailer be the substring of expansionKey from the index + // after the first "*" character. + const pattern_trailer = expansion.key[star + 1 ..]; + + // If patternTrailer has zero length, or if matchKey ends with + // patternTrailer and the length of matchKey is greater than or + // equal to the length of expansionKey, then + if (pattern_trailer.len == 0 or (strings.endsWith(match_key, pattern_trailer) and match_key.len >= expansion.key.len)) { + const target = expansion.value; + const subpath = match_key[pattern_base.len .. match_key.len - pattern_trailer.len]; + if (r.debug_logs) |log| { + log.addNoteFmt("The key \"{s}\" matched with \"{s}\" left over", .{ expansion.key, subpath }); + } + return r.resolveTarget(package_url, target, subpath, is_imports, true); + } + } + } else { + // Otherwise if patternBase is null and matchKey starts with + // expansionKey, then + if (strings.startsWith(match_key, expansion.key)) { const target = expansion.value; - const subpath = match_key[expansion.key.len - 1 ..]; + const subpath = match_key[expansion.key.len..]; if (r.debug_logs) |log| { log.addNoteFmt("The key \"{s}\" matched with \"{s}\" left over", .{ expansion.key, subpath }); } - - return r.resolveTarget(package_url, target, subpath, is_imports, true); - } - } - - if (strings.startsWith(match_key, expansion.key)) { - const target = expansion.value; - const subpath = match_key[expansion.key.len..]; - if (r.debug_logs) |log| { - log.addNoteFmt("The key \"{s}\" matched with \"{s}\" left over", .{ expansion.key, subpath }); + var result = r.resolveTarget(package_url, target, subpath, is_imports, false); + if (result.status == .Exact or result.status == .ExactEndsWithStar) { + // Return the object { resolved, exact: false }. + result.status = .Inexact; + } + return result; } - - var result = r.resolveTarget(package_url, target, subpath, is_imports, false); - result.status = if (result.status == .Exact) - // Return the object { resolved, exact: false }. - .Inexact - else - result.status; - - return result; } if (r.debug_logs) |log| { @@ -1645,10 +1666,14 @@ pub const ESModule = struct { _ = std.mem.replace(u8, resolved_target, "*", subpath, &resolve_target_buf2); const result = resolve_target_buf2[0..len]; if (r.debug_logs) |log| { - log.addNoteFmt("Subsituted \"{s}\" for \"*\" in \".{s}\" to get \".{s}\" ", .{ subpath, resolved_target, result }); + log.addNoteFmt("Substituted \"{s}\" for \"*\" in \".{s}\" to get \".{s}\" ", .{ subpath, resolved_target, result }); } - return Resolution{ .path = result, .status = .Exact, .debug = .{ .token = target.first_token } }; + const status: Status = if (strings.endsWithChar(result, '*') and strings.indexOfChar(result, '*').? == result.len - 1) + .ExactEndsWithStar + else + .Exact; + return Resolution{ .path = result, .status = status, .debug = .{ .token = target.first_token } }; } else { var parts2 = [_]string{ package_url, str, subpath }; const result = resolve_path.joinStringBuf(&resolve_target_buf2, parts2, .auto); diff --git a/src/resolver/resolver.zig b/src/resolver/resolver.zig index 9fad998cb..87928dd5f 100644 --- a/src/resolver/resolver.zig +++ b/src/resolver/resolver.zig @@ -192,6 +192,9 @@ pub const Result = struct { notes: std.ArrayList(logger.Data), suggestion_text: string = "", suggestion_message: string = "", + suggestion_range: SuggestionRange, + + pub const SuggestionRange = enum { full, end }; pub fn init(allocator: std.mem.Allocator) DebugMeta { return DebugMeta{ .notes = std.ArrayList(logger.Data).init(allocator) }; @@ -199,7 +202,11 @@ pub const Result = struct { pub fn logErrorMsg(m: *DebugMeta, log: *logger.Log, _source: ?*const logger.Source, r: logger.Range, comptime fmt: string, args: anytype) !void { if (_source != null and m.suggestion_message.len > 0) { - const data = logger.rangeData(_source.?, r, m.suggestion_message); + const suggestion_range = if (m.suggestion_range == .end) + logger.Range{ .loc = logger.Loc{ .start = r.endI() - 1 } } + else + r; + const data = logger.rangeData(_source.?, suggestion_range, m.suggestion_message); data.location.?.suggestion = m.suggestion_text; try m.notes.append(data); } @@ -1402,51 +1409,17 @@ pub const Resolver = struct { } } - const esm_ = ESModule.Package.parse(import_path, &esm_subpath_buf); - - if (import_path[0] == '#' and !forbid_imports) { - if (esm_ != null) { - if (dir_info.enclosing_package_json) |package_json| { - load_from_imports_map: { - const imports_map = package_json.imports orelse break :load_from_imports_map; - - if (import_path.len == 1 or strings.hasPrefix(import_path, "#/")) { - if (r.debug_logs) |*debug| { - debug.addNoteFmt("The path \"{s}\" must not equal \"#\" and must not start with \"#/\"", .{import_path}); - } - return .{ .not_found = {} }; - } - - const esmodule = ESModule{ - .conditions = switch (kind) { - ast.ImportKind.require, ast.ImportKind.require_resolve => r.opts.conditions.require, - else => r.opts.conditions.import, - }, - .allocator = r.allocator, - .debug_logs = if (r.debug_logs) |*debug| debug else null, - }; - - const esm_resolution = esmodule.resolveImports(import_path, imports_map.root); - - if (esm_resolution.status == .PackageResolve) - return r.loadNodeModules( - esm_resolution.path, - kind, - dir_info, - global_cache, - true, - ); - - if (r.handleESMResolution(esm_resolution, package_json.source.path.name.dir, kind, package_json)) |result| { - return .{ .success = result }; - } + // Find the parent directory with the "package.json" file + var dir_info_package_json: ?*DirInfo = dir_info; + while (dir_info_package_json != null and dir_info_package_json.?.package_json == null) : (dir_info_package_json = dir_info_package_json.?.getParent()) {} - return .{ .not_found = {} }; - } - } - } + // Check for subpath imports: https://nodejs.org/api/packages.html#subpath-imports + if (dir_info_package_json != null and strings.hasPrefix(import_path, "#") and !forbid_imports and dir_info_package_json.?.package_json.?.imports != null) { + return r.loadPackageImports(import_path, dir_info_package_json.?, kind, global_cache); } + const esm_ = ESModule.Package.parse(import_path, &esm_subpath_buf); + var source_dir_info = dir_info; var any_node_modules_folder = false; const use_node_module_resolver = global_cache != .force; @@ -1492,7 +1465,7 @@ pub const Resolver = struct { // directory path accidentally being interpreted as URL escapes. const esm_resolution = esmodule.resolve("/", esm.subpath, exports_map.root); - if (r.handleESMResolution(esm_resolution, abs_package_path, kind, package_json)) |result| { + if (r.handleESMResolution(esm_resolution, abs_package_path, kind, package_json, esm.subpath)) |result| { return .{ .success = result }; } @@ -1709,7 +1682,7 @@ pub const Resolver = struct { // directory path accidentally being interpreted as URL escapes. const esm_resolution = esmodule.resolve("/", esm.subpath, exports_map.root); - if (r.handleESMResolution(esm_resolution, abs_package_path, kind, package_json)) |*result| { + if (r.handleESMResolution(esm_resolution, abs_package_path, kind, package_json, esm.subpath)) |*result| { result.is_node_module = true; return .{ .success = result.* }; } @@ -1928,22 +1901,24 @@ pub const Resolver = struct { bun.unreachablePanic("TODO: implement enqueueDependencyToResolve for non-root packages", .{}); } - fn handleESMResolution(r: *ThisResolver, esm_resolution_: ESModule.Resolution, abs_package_path: string, kind: ast.ImportKind, package_json: *PackageJSON) ?MatchResult { + fn handleESMResolution(r: *ThisResolver, esm_resolution_: ESModule.Resolution, abs_package_path: string, kind: ast.ImportKind, package_json: *PackageJSON, package_subpath: string) ?MatchResult { var esm_resolution = esm_resolution_; - if (!((esm_resolution.status == .Inexact or esm_resolution.status == .Exact) and + if (!((esm_resolution.status == .Inexact or esm_resolution.status == .Exact or esm_resolution.status == .ExactEndsWithStar) and esm_resolution.path.len > 0 and esm_resolution.path[0] == '/')) return null; const abs_esm_path: string = brk: { var parts = [_]string{ abs_package_path, - esm_resolution.path[1..], + strings.withoutLeadingSlash(esm_resolution.path), }; break :brk r.fs.absBuf(&parts, &esm_absolute_package_path_joined); }; + var missing_suffix: string = undefined; + switch (esm_resolution.status) { - .Exact => { + .Exact, .ExactEndsWithStar => { const resolved_dir_info = (r.dirInfoCached(std.fs.path.dirname(abs_esm_path).?) catch null) orelse { esm_resolution.status = .ModuleNotFound; return null; @@ -1952,13 +1927,63 @@ pub const Resolver = struct { esm_resolution.status = .ModuleNotFound; return null; }; - const entry_query = entries.get(std.fs.path.basename(abs_esm_path)) orelse { + const base = std.fs.path.basename(abs_esm_path); + const extension_order = if (kind == .at or kind == .at_conditional) + r.extension_order + else + r.opts.extension_order; + const entry_query = entries.get(base) orelse { + const ends_with_star = esm_resolution.status == .ExactEndsWithStar; esm_resolution.status = .ModuleNotFound; + + // Try to have a friendly error message if people forget the extension + if (ends_with_star) { + std.mem.copy(u8, &load_as_file_buf, base); + for (extension_order) |ext| { + var file_name = load_as_file_buf[0 .. base.len + ext.len]; + std.mem.copy(u8, file_name[base.len..], ext); + if (entries.get(file_name) != null) { + if (r.debug_logs) |*debug| { + const parts = [_]string{ package_json.name, package_subpath }; + debug.addNoteFmt("The import {s} is missing the extension {s}", .{ ResolvePath.join(parts, .auto), ext }); + } + esm_resolution.status = .ModuleNotFoundMissingExtension; + missing_suffix = ext; + break; + } + } + } return null; }; if (entry_query.entry.kind(&r.fs.fs) == .dir) { + const ends_with_star = esm_resolution.status == .ExactEndsWithStar; esm_resolution.status = .UnsupportedDirectoryImport; + + // Try to have a friendly error message if people forget the "/index.js" suffix + if (ends_with_star) { + if (r.dirInfoCached(abs_esm_path) catch null) |dir_info| { + if (dir_info.getEntries()) |dir_entries| { + const index = "index"; + std.mem.copy(u8, &load_as_file_buf, index); + for (extension_order) |ext| { + var file_name = load_as_file_buf[0 .. index.len + ext.len]; + std.mem.copy(u8, file_name[index.len..], ext); + const index_query = dir_entries.get(file_name); + if (index_query != null and index_query.?.entry.kind(&r.fs.fs) == .file) { + missing_suffix = std.fmt.allocPrint(r.allocator, "/{s}", .{file_name}) catch unreachable; + // defer r.allocator.free(missing_suffix); + if (r.debug_logs) |*debug| { + const parts = [_]string{ package_json.name, package_subpath }; + debug.addNoteFmt("The import {s} is missing the suffix {s}", .{ ResolvePath.join(parts, .auto), missing_suffix }); + } + break; + } + } + } + } + } + return null; } @@ -2109,6 +2134,7 @@ pub const Resolver = struct { return try r.dirInfoCachedMaybeLog(path, true, true); } + /// The path must have a trailing slash and a sentinel 0 pub fn readDirInfo( r: *ThisResolver, path: string, @@ -2509,6 +2535,49 @@ pub const Resolver = struct { return null; } + pub fn loadPackageImports(r: *ThisResolver, import_path: string, dir_info: *DirInfo, kind: ast.ImportKind, global_cache: GlobalCache) MatchResult.Union { + const package_json = dir_info.package_json.?; + if (r.debug_logs) |*debug| { + debug.addNoteFmt("Looking for {s} in \"imports\" map in {s}", .{ import_path, package_json.source.key_path.text }); + debug.increaseIndent(); + defer debug.decreaseIndent(); + } + const imports_map = package_json.imports.?; + + if (import_path.len == 1 or strings.hasPrefix(import_path, "#/")) { + if (r.debug_logs) |*debug| { + debug.addNoteFmt("The path \"{s}\" must not equal \"#\" and must not start with \"#/\"", .{import_path}); + } + return .{ .not_found = {} }; + } + + const esmodule = ESModule{ + .conditions = switch (kind) { + ast.ImportKind.require, ast.ImportKind.require_resolve => r.opts.conditions.require, + else => r.opts.conditions.import, + }, + .allocator = r.allocator, + .debug_logs = if (r.debug_logs) |*debug| debug else null, + }; + + const esm_resolution = esmodule.resolveImports(import_path, imports_map.root); + + if (esm_resolution.status == .PackageResolve) + return r.loadNodeModules( + esm_resolution.path, + kind, + dir_info, + global_cache, + true, + ); + + if (r.handleESMResolution(esm_resolution, package_json.source.path.name.dir, kind, package_json, "")) |result| { + return .{ .success = result }; + } + + return .{ .not_found = {} }; + } + const BrowserMapPath = struct { remapped: string = "", cleaned: string = "", @@ -2741,7 +2810,7 @@ pub const Resolver = struct { }; } - pub fn loadAsIndex(r: *ThisResolver, dir_info: *DirInfo, path: string, extension_order: []const string) ?MatchResult { + pub fn loadAsIndex(r: *ThisResolver, dir_info: *DirInfo, extension_order: []const string) ?MatchResult { var rfs = &r.fs.fs; // Try the "index" file with extensions for (extension_order) |ext| { @@ -2754,7 +2823,7 @@ pub const Resolver = struct { if (lookup.entry.kind(rfs) == .file) { const out_buf = brk: { if (lookup.entry.abs_path.isEmpty()) { - const parts = [_]string{ path, base }; + const parts = [_]string{ dir_info.abs_path, base }; const out_buf_ = r.fs.absBuf(&parts, &index_buf); lookup.entry.abs_path = PathString.init(r.fs.dirname_store.append(@TypeOf(out_buf_), out_buf_) catch unreachable); @@ -2786,7 +2855,7 @@ pub const Resolver = struct { } if (r.debug_logs) |*debug| { - debug.addNoteFmt("Failed to find file: \"{s}/{s}\"", .{ path, base }); + debug.addNoteFmt("Failed to find file: \"{s}/{s}\"", .{ dir_info.abs_path, base }); } } @@ -2837,7 +2906,7 @@ pub const Resolver = struct { // Is it a directory with an index? if (r.dirInfoCached(remapped_abs) catch null) |new_dir| { - if (r.loadAsIndex(new_dir, remapped_abs, extension_order)) |absolute| { + if (r.loadAsIndex(new_dir, extension_order)) |absolute| { return absolute; } } @@ -2847,7 +2916,7 @@ pub const Resolver = struct { } } - return r.loadAsIndex(dir_info, path_, extension_order); + return r.loadAsIndex(dir_info, extension_order); } pub fn loadAsFileOrDirectory(r: *ThisResolver, path: string, kind: ast.ImportKind) ?MatchResult { diff --git a/src/router.zig b/src/router.zig index 2fbb53373..ee9d21d09 100644 --- a/src/router.zig +++ b/src/router.zig @@ -121,7 +121,7 @@ pub const Routes = struct { // We put this here to avoid loading the FrameworkConfig for the client, on the server. client_framework_enabled: bool = false, - pub fn matchPage(this: *Routes, _: string, url_path: URLPath, params: *Param.List) ?Match { + pub fn matchPageWithAllocator(this: *Routes, _: string, url_path: URLPath, params: *Param.List, allocator: std.mem.Allocator) ?Match { // Trim trailing slash var path = url_path.path; var redirect = false; @@ -181,7 +181,7 @@ pub const Routes = struct { var matcher = MatchContextType{ .params = params.* }; defer params.* = matcher.params; - if (this.match(this.allocator, path, *MatchContextType, &matcher)) |route| { + if (this.match(allocator, path, *MatchContextType, &matcher)) |route| { return Match{ .params = params, .name = route.name, @@ -198,6 +198,10 @@ pub const Routes = struct { return null; } + pub fn matchPage(this: *Routes, _: string, url_path: URLPath, params: *Param.List) ?Match { + return this.matchPageWithAllocator("", url_path, params, this.allocator); + } + fn matchDynamic(this: *Routes, allocator: std.mem.Allocator, path: string, comptime MatchContext: type, ctx: MatchContext) ?*Route { // its cleaned, so now we search the big list of strings var i: usize = 0; @@ -319,6 +323,13 @@ const RouteLoader = struct { } pub fn loadAll(allocator: std.mem.Allocator, config: Options.RouteConfig, log: *Logger.Log, comptime ResolverType: type, resolver: *ResolverType, root_dir_info: *const DirInfo) Routes { + var route_dirname_len: u16 = 0; + + const relative_dir = FileSystem.instance.relative(resolver.fs.top_level_dir, config.dir); + if (!strings.hasPrefixComptime(relative_dir, "..")) { + route_dirname_len = @truncate(u16, relative_dir.len + @as(usize, @boolToInt(config.dir[config.dir.len - 1] != std.fs.path.sep))); + } + var this = RouteLoader{ .allocator = allocator, .log = log, @@ -327,7 +338,7 @@ const RouteLoader = struct { .static_list = std.StringHashMap(*Route).init(allocator), .dedupe_dynamic = std.AutoArrayHashMap(u32, string).init(allocator), .all_routes = .{}, - .route_dirname_len = @truncate(u16, FileSystem.instance.relative(resolver.fs.top_level_dir, config.dir).len + @as(usize, @boolToInt(config.dir[config.dir.len - 1] != std.fs.path.sep))), + .route_dirname_len = route_dirname_len, }; defer this.dedupe_dynamic.deinit(); this.load(ResolverType, resolver, root_dir_info); @@ -436,10 +447,10 @@ const RouteLoader = struct { // length is extended by one // entry.dir is a string with a trailing slash if (comptime Environment.isDebug) { - std.debug.assert(entry.dir.ptr[fs.top_level_dir.len - 1] == '/'); + std.debug.assert(entry.dir.ptr[this.config.dir.len - 1] == '/'); } - const public_dir = entry.dir.ptr[fs.top_level_dir.len - 1 .. entry.dir.len]; + const public_dir = entry.dir.ptr[this.config.dir.len - 1 .. entry.dir.len]; if (Route.parse( entry.base(), @@ -636,15 +647,17 @@ pub const Route = struct { // the name we actually store will often be this one var public_path: string = brk: { if (base.len == 0) break :brk public_dir; - route_file_buf[0] = '/'; - - var buf: []u8 = route_file_buf[1..]; - - std.mem.copy( - u8, - buf, - public_dir, - ); + var buf: []u8 = &route_file_buf; + + if (public_dir.len > 0) { + route_file_buf[0] = '/'; + buf = buf[1..]; + std.mem.copy( + u8, + buf, + public_dir, + ); + } buf[public_dir.len] = '/'; buf = buf[public_dir.len + 1 ..]; std.mem.copy(u8, buf, base); @@ -755,6 +768,7 @@ pub const Route = struct { }; threadlocal var params_list: Param.List = undefined; + pub fn match(app: *Router, comptime Server: type, server: Server, comptime RequestContextType: type, ctx: *RequestContextType) !void { ctx.matched_route = null; diff --git a/src/string_immutable.zig b/src/string_immutable.zig index de4cf7199..30e4948cb 100644 --- a/src/string_immutable.zig +++ b/src/string_immutable.zig @@ -652,6 +652,10 @@ pub fn hasPrefixComptime(self: string, comptime alt: anytype) bool { return self.len >= alt.len and eqlComptimeCheckLenWithType(u8, self[0..alt.len], alt, false); } +/// Check if two strings are equal with one of the strings being a comptime-known value +/// +/// strings.eqlComptime(input, "hello world"); +/// strings.eqlComptime(input, "hai"); pub inline fn eqlComptimeCheckLenWithType(comptime Type: type, a: []const Type, comptime b: anytype, comptime check_len: bool) bool { @setEvalBranchQuota(9999); if (comptime check_len) { @@ -3580,6 +3584,48 @@ pub fn NewLengthSorter(comptime Type: type, comptime field: string) type { }; } +pub fn NewGlobLengthSorter(comptime Type: type, comptime field: string) type { + return struct { + const GlobLengthSorter = @This(); + pub fn lessThan(_: GlobLengthSorter, lhs: Type, rhs: Type) bool { + // Assert: keyA ends with "/" or contains only a single "*". + // Assert: keyB ends with "/" or contains only a single "*". + const key_a = @field(lhs, field); + const key_b = @field(rhs, field); + + // Let baseLengthA be the index of "*" in keyA plus one, if keyA contains "*", or the length of keyA otherwise. + // Let baseLengthB be the index of "*" in keyB plus one, if keyB contains "*", or the length of keyB otherwise. + const star_a = indexOfChar(key_a, '*'); + const star_b = indexOfChar(key_b, '*'); + const base_length_a = star_a orelse key_a.len; + const base_length_b = star_b orelse key_b.len; + + // If baseLengthA is greater than baseLengthB, return -1. + // If baseLengthB is greater than baseLengthA, return 1. + if (base_length_a > base_length_b) + return true; + if (base_length_b > base_length_a) + return false; + + // If keyA does not contain "*", return 1. + // If keyB does not contain "*", return -1. + if (star_a == null) + return false; + if (star_b == null) + return true; + + // If the length of keyA is greater than the length of keyB, return -1. + // If the length of keyB is greater than the length of keyA, return 1. + if (key_a.len > key_b.len) + return true; + if (key_b.len > key_a.len) + return false; + + return false; + } + }; +} + /// Update all strings in a struct pointing to "from" to point to "to". pub fn moveAllSlices(comptime Type: type, container: *Type, from: string, to: string) void { const fields_we_care_about = comptime brk: { @@ -3718,3 +3764,32 @@ pub fn isIPAddress(input: []const u8) bool { return false; } } + +pub fn cloneNormalizingSeparators( + allocator: std.mem.Allocator, + input: []const u8, +) ![]u8 { + // remove duplicate slashes in the file path + var base = withoutTrailingSlash(input); + var tokenized = std.mem.tokenize(u8, base, std.fs.path.sep_str); + var buf = try allocator.alloc(u8, base.len + 2); + std.debug.assert(base.len > 0); + if (base[0] == std.fs.path.sep) { + buf[0] = std.fs.path.sep; + } + var remain = buf[@as(usize, @boolToInt(base[0] == std.fs.path.sep))..]; + + while (tokenized.next()) |token| { + if (token.len == 0) continue; + std.mem.copy(u8, remain, token); + remain[token.len..][0] = std.fs.path.sep; + remain = remain[token.len + 1 ..]; + } + if ((remain.ptr - 1) != buf.ptr and (remain.ptr - 1)[0] != std.fs.path.sep) { + remain[0] = std.fs.path.sep; + remain = remain[1..]; + } + remain[0] = 0; + + return buf[0 .. @ptrToInt(remain.ptr) - @ptrToInt(buf.ptr)]; +} diff --git a/src/string_mutable.zig b/src/string_mutable.zig index 2849a4695..a9f528cc0 100644 --- a/src/string_mutable.zig +++ b/src/string_mutable.zig @@ -30,6 +30,10 @@ pub const MutableString = struct { } } + pub fn owns(this: *const MutableString, slice: []const u8) bool { + return @import("./global.zig").isSliceInBuffer(slice, this.list.items.ptr[0..this.list.capacity]); + } + pub fn growIfNeeded(self: *MutableString, amount: usize) !void { try self.list.ensureUnusedCapacity(self.allocator, amount); } @@ -156,6 +160,15 @@ pub const MutableString = struct { try self.list.appendSlice(self.allocator, slice); } + pub inline fn appendSliceExact(self: *MutableString, slice: []const u8) !void { + if (slice.len == 0) return; + + try self.list.ensureTotalCapacityPrecise(self.allocator, self.list.items.len + slice.len); + var end = self.list.items.ptr + self.list.items.len; + self.list.items.len += slice.len; + @memcpy(end, slice.ptr, slice.len); + } + pub inline fn reset( self: *MutableString, ) void { diff --git a/src/url.zig b/src/url.zig index c212c3fe2..26c606a4d 100644 --- a/src/url.zig +++ b/src/url.zig @@ -120,7 +120,11 @@ pub const URL = struct { } pub fn getPortAuto(this: *const URL) u16 { - return this.getPort() orelse (if (this.isHTTPS()) @as(u16, 443) else @as(u16, 80)); + return this.getPort() orelse this.getDefaultPort(); + } + + pub fn getDefaultPort(this: *const URL) u16 { + return if (this.isHTTPS()) @as(u16, 443) else @as(u16, 80); } pub fn hasValidPort(this: *const URL) bool { @@ -216,22 +220,32 @@ pub const URL = struct { offset += url.parsePassword(base[offset..]) orelse 0; offset += url.parseHost(base[offset..]) orelse 0; }, - 'a'...'z', 'A'...'Z', '0'...'9', '-', '_', ':' => { - offset += url.parseProtocol(base[offset..]) orelse 0; - - // if there's no protocol or @, it's ambiguous whether the colon is a port or a username. - if (offset > 0) { - // see https://github.com/oven-sh/bun/issues/1390 - const first_at = strings.indexOfChar(base[offset..], '@') orelse 0; - const first_colon = strings.indexOfChar(base[offset..], ':') orelse 0; - - if (first_at > first_colon and first_at < (strings.indexOfChar(base[offset..], '/') orelse std.math.maxInt(u32))) { - offset += url.parseUsername(base[offset..]) orelse 0; - offset += url.parsePassword(base[offset..]) orelse 0; - } + '/', 'a'...'z', 'A'...'Z', '0'...'9', '-', '_', ':' => { + const is_protocol_relative = base.len > 1 and base[1] == '/'; + if (is_protocol_relative) { + offset += 1; + } else { + offset += url.parseProtocol(base[offset..]) orelse 0; } - offset += url.parseHost(base[offset..]) orelse 0; + const is_relative_path = !is_protocol_relative and base[0] == '/'; + + if (!is_relative_path) { + + // if there's no protocol or @, it's ambiguous whether the colon is a port or a username. + if (offset > 0) { + // see https://github.com/oven-sh/bun/issues/1390 + const first_at = strings.indexOfChar(base[offset..], '@') orelse 0; + const first_colon = strings.indexOfChar(base[offset..], ':') orelse 0; + + if (first_at > first_colon and first_at < (strings.indexOfChar(base[offset..], '/') orelse std.math.maxInt(u32))) { + offset += url.parseUsername(base[offset..]) orelse 0; + offset += url.parsePassword(base[offset..]) orelse 0; + } + } + + offset += url.parseHost(base[offset..]) orelse 0; + } }, else => {}, } @@ -431,15 +445,16 @@ pub const QueryStringMap = struct { threadlocal var _name_count: [8]string = undefined; pub fn getNameCount(this: *QueryStringMap) usize { - if (this.name_count == null) { - var count: usize = 0; - var iterate = this.iter(); - while (iterate.next(&_name_count) != null) { - count += 1; - } - this.name_count = count; - } - return this.name_count.?; + return this.list.len; + // if (this.name_count == null) { + // var count: usize = 0; + // var iterate = this.iter(); + // while (iterate.next(&_name_count) != null) { + // count += 1; + // } + // this.name_count = count; + // } + // return this.name_count.?; } pub fn iter(this: *const QueryStringMap) Iterator { @@ -470,7 +485,9 @@ pub const QueryStringMap = struct { var slice = this.map.list.slice(); const hash = slice.items(.name_hash)[this.i]; - var result = Result{ .name = this.map.str(slice.items(.name)[this.i]), .values = target[0..1] }; + const name_slice = slice.items(.name)[this.i]; + std.debug.assert(name_slice.length > 0); + var result = Result{ .name = this.map.str(name_slice), .values = target[0..1] }; target[0] = this.map.str(slice.items(.value)[this.i]); this.visited.set(this.i); @@ -842,14 +859,22 @@ pub const CombinedScanner = struct { fn stringPointerFromStrings(parent: string, in: string) Api.StringPointer { if (in.len == 0 or parent.len == 0) return Api.StringPointer{}; - const end = @ptrToInt(parent.ptr) + parent.len; - const in_end = @ptrToInt(in.ptr) + in.len; - if (in_end < end) return Api.StringPointer{}; + if (bun.rangeOfSliceInBuffer(in, parent)) |range| { + return Api.StringPointer{ .offset = range[0], .length = range[1] }; + } else { + if (strings.indexOf(parent, in)) |i| { + if (comptime Environment.allow_assert) { + std.debug.assert(strings.eqlLong(parent[i..][0..in.len], in, false)); + } + + return Api.StringPointer{ + .offset = @truncate(u32, i), + .length = @truncate(u32, in.len), + }; + } + } - return Api.StringPointer{ - .offset = @truncate(u32, @maximum(@ptrToInt(in.ptr), @ptrToInt(parent.ptr)) - @ptrToInt(parent.ptr)), - .length = @truncate(u32, in.len), - }; + return Api.StringPointer{}; } pub const PathnameScanner = struct { @@ -888,7 +913,7 @@ pub const PathnameScanner = struct { .name_needs_decoding = false, // TODO: fix this technical debt .value = stringPointerFromStrings(this.pathname, param.value), - .value_needs_decoding = std.mem.indexOfScalar(u8, param.value, '%') != null, + .value_needs_decoding = strings.containsChar(param.value, '%'), }; } }; diff --git a/src/zlib.zig b/src/zlib.zig index 2ff037c52..4be96760f 100644 --- a/src/zlib.zig +++ b/src/zlib.zig @@ -417,6 +417,7 @@ pub const ZlibReaderArrayList = struct { input: []const u8, list: std.ArrayListUnmanaged(u8), + list_allocator: std.mem.Allocator, list_ptr: *std.ArrayListUnmanaged(u8), zlib: zStream_struct, allocator: std.mem.Allocator, @@ -459,10 +460,15 @@ pub const ZlibReaderArrayList = struct { } pub fn initWithOptions(input: []const u8, list: *std.ArrayListUnmanaged(u8), allocator: std.mem.Allocator, options: Options) ZlibError!*ZlibReader { + return initWithOptionsAndListAllocator(input, list, allocator, allocator, options); + } + + pub fn initWithOptionsAndListAllocator(input: []const u8, list: *std.ArrayListUnmanaged(u8), list_allocator: std.mem.Allocator, allocator: std.mem.Allocator, options: Options) ZlibError!*ZlibReader { var zlib_reader = try allocator.create(ZlibReader); zlib_reader.* = ZlibReader{ .input = input, .list = list.*, + .list_allocator = list_allocator, .list_ptr = list, .allocator = allocator, .zlib = undefined, @@ -552,7 +558,7 @@ pub const ZlibReaderArrayList = struct { if (this.zlib.avail_out == 0) { const initial = this.list.items.len; - try this.list.ensureUnusedCapacity(this.allocator, 4096); + try this.list.ensureUnusedCapacity(this.list_allocator, 4096); this.list.expandToCapacity(); this.zlib.next_out = &this.list.items[initial]; this.zlib.avail_out = @intCast(u32, this.list.items.len - initial); @@ -818,6 +824,7 @@ pub const ZlibCompressorArrayList = struct { input: []const u8, list: std.ArrayListUnmanaged(u8), + list_allocator: std.mem.Allocator, list_ptr: *std.ArrayListUnmanaged(u8), zlib: zStream_struct, allocator: std.mem.Allocator, @@ -848,11 +855,16 @@ pub const ZlibCompressorArrayList = struct { } pub fn init(input: []const u8, list: *std.ArrayListUnmanaged(u8), allocator: std.mem.Allocator, options: Options) ZlibError!*ZlibCompressor { + return initWithListAllocator(input, list, allocator, allocator, options); + } + + pub fn initWithListAllocator(input: []const u8, list: *std.ArrayListUnmanaged(u8), allocator: std.mem.Allocator, list_allocator: std.mem.Allocator, options: Options) ZlibError!*ZlibCompressor { var zlib_reader = try allocator.create(ZlibCompressor); zlib_reader.* = ZlibCompressor{ .input = input, .list = list.*, .list_ptr = list, + .list_allocator = list_allocator, .allocator = allocator, .zlib = undefined, .arena = std.heap.ArenaAllocator.init(allocator), @@ -957,7 +969,7 @@ pub const ZlibCompressorArrayList = struct { if (this.zlib.avail_out == 0) { const initial = this.list.items.len; - try this.list.ensureUnusedCapacity(this.allocator, 4096); + try this.list.ensureUnusedCapacity(this.list_allocator, 4096); this.list.expandToCapacity(); this.zlib.next_out = &this.list.items[initial]; this.zlib.avail_out = @intCast(u32, this.list.items.len - initial); diff --git a/test/README.md b/test/README.md index 292d23cf2..274b19fbf 100644 --- a/test/README.md +++ b/test/README.md @@ -2,13 +2,46 @@ Bun currently has four different kinds of tests -To run the tests: +To run all the tests: ```bash make test-all +bun --cwd=test/bun.js wiptest +``` + +### Runtime tests + +To run the runtime tests: + +```bash +cd test/bun.js bun wiptest ``` +These tests are in [./bun.js](./bun.js) and are files with `.test.js` or `.test.ts` in the filename. + +These test that the runtime behaves as expected. These also test the transpiler, both because test files are transpiled and directly by running the transpiler via `Bun.Transpiler`. + +#### Adding a new test + +1. Create a new file in [./bun.js](./bun.js/) with `.test` in the name. + +These test use `bun:test` as the import (though you can also import from `vitest` or jest and it will work). + +This will eventually be a public test runner for bun, but the reporter isn't very good yet and it doesn't run in parallel. + +The syntax intends for Jest compatibility. + +```ts +import { describe, expect, it } from "bun:test"; + +describe("Example", () => { + it("should work", () => { + expect(1).toBe(1); + }); +}); +``` + ### Browser tests Browser tests run end-to-end inside of Puppeteer and execute code transpiled by `bun dev`. These tests are in [./snippets](./snippets). @@ -68,32 +101,6 @@ make integration-test-dev These were the first tests bun started with -### Runtime tests - -These tests are in [./bun.js](./bun.js) and are files which are either `.test.js` or `.test.ts` files. - -These test that the runtime behaves as expected. These also test the transpiler, both because test files are transpiled and directly by running the transpiler via `Bun.Transpiler`. - -#### Adding a new test - -1. Create a new file in [./bun.js](./bun.js/) with `.test` in the name. - -These test use `bun:test` as the import (though you can also import from `vitest` or jest and it will work). - -This will eventually be a public test runner for bun, but the reporter isn't very good yet and it doesn't run in parallel. - -The syntax intends for Jest compatibility. - -```ts -import { describe, expect, it } from "bun:test"; - -describe("Example", () => { - it("should work", () => { - expect(1).toBe(1); - }); -}); -``` - #### Running the tests Run `bun wiptest ${part-of-file-name}` diff --git a/test/bun.js/fetch-gzip.test.ts b/test/bun.js/fetch-gzip.test.ts index 274333522..fdde76ae8 100644 --- a/test/bun.js/fetch-gzip.test.ts +++ b/test/bun.js/fetch-gzip.test.ts @@ -42,9 +42,85 @@ it("fetch() with a buffered gzip response works (one chunk)", async () => { server.stop(); }); -// it("fetch() with a gzip response works (one chunk)", async () => { -// var server = Bun.serve({ -// port: 6023, +it("fetch() with a redirect that returns a buffered gzip response works (one chunk)", async () => { + var server = Bun.serve({ + port: 6020, + + async fetch(req) { + if (req.url.endsWith("/redirect")) + return new Response( + await Bun.file(import.meta.dir + "/fixture.html.gz").arrayBuffer(), + { + headers: { + "Content-Encoding": "gzip", + "Content-Type": "text/html; charset=utf-8", + }, + }, + ); + + return Response.redirect("/redirect"); + }, + }); + + const res = await fetch( + `http://${server.hostname}:${server.port}/hey`, + {}, + { verbose: true }, + ); + const arrayBuffer = await res.arrayBuffer(); + expect( + new Buffer(arrayBuffer).equals( + new Buffer( + await Bun.file(import.meta.dir + "/fixture.html").arrayBuffer(), + ), + ), + ).toBe(true); + server.stop(); +}); + +it("fetch() with a protocol-relative redirect that returns a buffered gzip response works (one chunk)", async () => { + const server = Bun.serve({ + port: 5018, + + async fetch(req, server) { + if (req.url.endsWith("/redirect")) + return new Response( + await Bun.file(import.meta.dir + "/fixture.html.gz").arrayBuffer(), + { + headers: { + "Content-Encoding": "gzip", + "Content-Type": "text/html; charset=utf-8", + }, + }, + ); + + return Response.redirect(`://${server.hostname}:${server.port}/redirect`); + }, + }); + + const res = await fetch( + `http://${server.hostname}:${server.port}/hey`, + {}, + { verbose: true }, + ); + expect(res.url).toBe(`http://${server.hostname}:${server.port}/redirect`); + expect(res.redirected).toBe(true); + expect(res.status).toBe(200); + const arrayBuffer = await res.arrayBuffer(); + expect( + new Buffer(arrayBuffer).equals( + new Buffer( + await Bun.file(import.meta.dir + "/fixture.html").arrayBuffer(), + ), + ), + ).toBe(true); + + server.stop(); +}); + +it("fetch() with a gzip response works (one chunk)", async () => { + var server = Bun.serve({ + port: 6023, // fetch(req) { // return new Response(Bun.file(import.meta.dir + "/fixture.html.gz"), { @@ -73,25 +149,50 @@ it("fetch() with a buffered gzip response works (one chunk)", async () => { // var server = Bun.serve({ // port: 6024, -// fetch(req) { -// return new Response( -// new ReadableStream({ -// type: "direct", -// async pull(controller) { -// var chunks: ArrayBuffer[] = []; -// const buffer = await Bun.file( -// import.meta.dir + "/fixture.html.gz", -// ).arrayBuffer(); -// gcTick(); -// var remaining = buffer; -// for (var i = 100; i < buffer.byteLength; i += 100) { -// var chunk = remaining.slice(0, i); -// remaining = remaining.slice(i); -// controller.write(chunk); -// chunks.push(chunk); -// await controller.flush(); -// } -// gcTick(); +it("fetch() with a gzip response works (one chunk, streamed, with a delay)", async () => { + var server = Bun.serve({ + port: 6081, + + fetch(req) { + return new Response( + new ReadableStream({ + type: "direct", + async pull(controller) { + await 2; + + const buffer = await Bun.file( + import.meta.dir + "/fixture.html.gz", + ).arrayBuffer(); + controller.write(buffer); + controller.close(); + }, + }), + { + headers: { + "Content-Encoding": "gzip", + "Content-Type": "text/html; charset=utf-8", + "Content-Length": "1", + }, + }, + ); + }, + }); + + const res = await fetch(`http://${server.hostname}:${server.port}`, {}); + const arrayBuffer = await res.arrayBuffer(); + expect( + new Buffer(arrayBuffer).equals( + new Buffer( + await Bun.file(import.meta.dir + "/fixture.html").arrayBuffer(), + ), + ), + ).toBe(true); + server.stop(); +}); + +it("fetch() with a gzip response works (multiple chunks)", async () => { + var server = Bun.serve({ + port: 6024, // await controller.flush(); // // sanity check @@ -149,44 +250,66 @@ it("fetch() with a buffered gzip response works (one chunk)", async () => { // corked.length = 0; // } -// if (!cork) { -// socket.write(chunk); -// } +it("fetch() with a gzip response works (multiple chunks, TCP server)", async (done) => { + const compressed = await Bun.file( + import.meta.dir + "/fixture.html.gz", + ).arrayBuffer(); + var socketToClose; + const server = Bun.listen({ + port: 4024, + hostname: "0.0.0.0", + socket: { + async open(socket) { + socketToClose = socket; -// resolve(); -// }); -// } -// await write("HTTP/1.1 200 OK\r\n"); -// await write("Content-Encoding: gzip\r\n"); -// await write("Content-Type: text/html; charset=utf-8\r\n"); -// await write("Content-Length: " + compressed.byteLength + "\r\n"); -// await write("X-WTF: " + "lol".repeat(1000) + "\r\n"); -// await write("\r\n"); -// for (var i = 100; i < compressed.byteLength; i += 100) { -// cork = false; -// await write(compressed.slice(i - 100, i)); -// } -// await write(compressed.slice(i - 100)); -// await socket.end(); -// gcTick(); -// }, -// drain(socket) {}, -// }, -// }); -// await 1; -// gcTick(); -// const res = await fetch(`http://${server.hostname}:${server.port}`, {}); -// const arrayBuffer = await res.arrayBuffer(); -// gcTick(); -// expect( -// new Buffer(arrayBuffer).equals( -// new Buffer( -// await Bun.file(import.meta.dir + "/fixture.html").arrayBuffer(), -// ), -// ), -// ).toBe(true); -// gcTick(); -// server.stop(); -// gcTick(); -// done(); -// }); + var corked: any[] = []; + var cork = true; + async function write(chunk) { + await new Promise<void>((resolve, reject) => { + if (cork) { + corked.push(chunk); + } + + if (!cork && corked.length) { + socket.write(corked.join("")); + corked.length = 0; + } + + if (!cork) { + socket.write(chunk); + } + + resolve(); + }); + } + await write("HTTP/1.1 200 OK\r\n"); + await write("Content-Encoding: gzip\r\n"); + await write("Content-Type: text/html; charset=utf-8\r\n"); + await write("Content-Length: " + compressed.byteLength + "\r\n"); + await write("X-WTF: " + "lol".repeat(1000) + "\r\n"); + await write("\r\n"); + for (var i = 100; i < compressed.byteLength; i += 100) { + cork = false; + await write(compressed.slice(i - 100, i)); + } + await write(compressed.slice(i - 100)); + socket.flush(); + }, + drain(socket) {}, + }, + }); + await 1; + + const res = await fetch(`http://${server.hostname}:${server.port}`, {}); + const arrayBuffer = await res.arrayBuffer(); + expect( + new Buffer(arrayBuffer).equals( + new Buffer( + await Bun.file(import.meta.dir + "/fixture.html").arrayBuffer(), + ), + ), + ).toBe(true); + socketToClose.end(); + server.stop(); + done(); +}); diff --git a/test/bun.js/filesystem_router.test.ts b/test/bun.js/filesystem_router.test.ts new file mode 100644 index 000000000..a73e98c2d --- /dev/null +++ b/test/bun.js/filesystem_router.test.ts @@ -0,0 +1,405 @@ +import { FileSystemRouter } from "bun"; +import { it, expect } from "bun:test"; +import path, { dirname, resolve } from "path"; +import fs, { mkdirSync, realpathSync, rmSync } from "fs"; +import { tmpdir } from "os"; +const tempdir = realpathSync(tmpdir()) + "/"; + +function createTree(basedir, paths) { + for (const end of paths) { + const abs = path.join(basedir, end); + try { + const dir = dirname(abs); + if (dir.length > 0 && dir !== "/") fs.mkdirSync(dir, { recursive: true }); + } catch (e) {} + fs.writeFileSync(abs, "export default " + JSON.stringify(end) + ";\n"); + } +} +var count = 0; +function make(files) { + const dir = tempdir + `fs-router-test-${count++}`; + rmSync(dir, { + recursive: true, + force: true, + }); + + createTree(dir, files); + if (files.length === 0) mkdirSync(dir, { recursive: true }); + return { + dir, + }; +} + +it("should find files", () => { + const { dir } = make([ + `index.tsx`, + `[id].tsx`, + `a.tsx`, + `abc/index.tsx`, + `abc/[id].tsx`, + `abc/def/[id].tsx`, + `abc/def/ghi/index.tsx`, + `abc/def/ghi/[id].tsx`, + `abc/def/ghi/jkl/index.tsx`, + `abc/def/ghi/jkl/[id].tsx`, + `abc/def/index.tsx`, + `b.tsx`, + `foo/[id].tsx`, + `catch-all/[[...id]].tsx`, + ]); + + const router = new FileSystemRouter({ + dir, + fileExtensions: [".tsx"], + style: "nextjs", + }); + + const routes = router.routes; + const fixture = { + "/": `${dir}/index.tsx`, + "/[id]": `${dir}/[id].tsx`, + "/a": `${dir}/a.tsx`, + "/abc": `${dir}/abc/index.tsx`, + "/abc/[id]": `${dir}/abc/[id].tsx`, + "/abc/def/[id]": `${dir}/abc/def/[id].tsx`, + "/abc/def/ghi": `${dir}/abc/def/ghi/index.tsx`, + "/abc/def/ghi/[id]": `${dir}/abc/def/ghi/[id].tsx`, + "/abc/def/ghi/jkl": `${dir}/abc/def/ghi/jkl/index.tsx`, + "/abc/def/ghi/jkl/[id]": `${dir}/abc/def/ghi/jkl/[id].tsx`, + "/abc/def": `${dir}/abc/def/index.tsx`, + "/b": `${dir}/b.tsx`, + "/foo/[id]": `${dir}/foo/[id].tsx`, + "/catch-all/[[...id]]": `${dir}/catch-all/[[...id]].tsx`, + }; + + for (const route in fixture) { + if (!(route in routes)) { + throw new Error(`Route ${route} not found`); + } + + expect(routes[route]).toBe(fixture[route]); + } + + expect(Object.keys(routes).length).toBe(Object.keys(fixture).length); + expect(Object.values(routes).length).toBe(Object.values(fixture).length); +}); + +it("should handle empty dirs", () => { + const { dir } = make([]); + + const router = new FileSystemRouter({ + dir, + fileExtensions: [".tsx"], + style: "nextjs", + }); + + // assert this doesn't crash + expect(router.bar).toBeUndefined(); + + const routes = router.routes; + expect(Object.keys(routes).length).toBe(0); + expect(Object.values(routes).length).toBe(0); +}); + +it("should match dynamic routes", () => { + // set up the test + const { dir } = make(["index.tsx", "posts/[id].tsx", "posts.tsx"]); + + const router = new Bun.FileSystemRouter({ + dir, + style: "nextjs", + }); + + const { name, filePath } = router.match("/posts/hello-world"); + + expect(name).toBe("/posts/[id]"); + expect(filePath).toBe(`${dir}/posts/[id].tsx`); +}); + +it(".params works on dynamic routes", () => { + // set up the test + const { dir } = make(["index.tsx", "posts/[id].tsx", "posts.tsx"]); + + const router = new Bun.FileSystemRouter({ + dir, + style: "nextjs", + }); + + const { + params: { id }, + } = router.match("/posts/hello-world"); + + expect(id).toBe("hello-world"); +}); + +it("should support static routes", () => { + // set up the test + const { dir } = make([ + "index.tsx", + "posts/[id].tsx", + "posts.tsx", + "posts/hey.tsx", + ]); + + const router = new Bun.FileSystemRouter({ + dir, + style: "nextjs", + }); + + const { name, params, filePath } = router.match("/posts/hey"); + + expect(name).toBe("/posts/hey"); + expect(filePath).toBe(`${dir}/posts/hey.tsx`); +}); + +it("should support optional catch-all routes", () => { + // set up the test + const { dir } = make([ + "index.tsx", + "posts/[id].tsx", + "posts.tsx", + "posts/hey.tsx", + "posts/[[...id]].tsx", + ]); + + const router = new Bun.FileSystemRouter({ + dir, + style: "nextjs", + }); + + for (let fixture of [ + "/posts/123", + "/posts/hey", + "/posts/zorp", + "/posts", + "/index", + "/posts/", + ]) { + expect(router.match(fixture)?.name).not.toBe("/posts/[[...id]]"); + } + + for (let fixture of [ + "/posts/hey/there", + "/posts/hey/there/you", + "/posts/zorp/123", + ]) { + const { name, params, filePath } = router.match(fixture); + + expect(name).toBe("/posts/[[...id]]"); + expect(filePath).toBe(`${dir}/posts/[[...id]].tsx`); + expect(params.id).toBe(fixture.split("/").slice(2).join("/")); + } +}); + +it("should support catch-all routes", () => { + // set up the test + const { dir } = make([ + "index.tsx", + "posts/[id].tsx", + "posts.tsx", + "posts/hey.tsx", + "posts/[...id].tsx", + "posts/wow/[[...id]].tsx", + ]); + + const router = new Bun.FileSystemRouter({ + dir, + style: "nextjs", + }); + + for (let fixture of [ + "/posts/123", + "/posts/hey", + "/posts/zorp", + "/posts", + "/index", + "/posts/", + ]) { + expect(router.match(fixture)?.name).not.toBe("/posts/[...id]"); + } + + for (let fixture of [ + "/posts/hey/there", + "/posts/hey/there/you", + "/posts/zorp/123", + "/posts/wow/hey/there", + ]) { + const { name, params, filePath } = router.match(fixture); + + expect(name).toBe("/posts/[...id]"); + expect(filePath).toBe(`${dir}/posts/[...id].tsx`); + expect(params.id).toBe(fixture.split("/").slice(2).join("/")); + } +}); + +it("should support index routes", () => { + // set up the test + const { dir } = make([ + "index.tsx", + "posts/[id].tsx", + "posts.tsx", + "posts/hey.tsx", + ]); + + const router = new Bun.FileSystemRouter({ + dir, + style: "nextjs", + }); + + for (let route of ["/", "/index"]) { + const { name, params, filePath } = router.match(route); + + expect(name).toBe("/"); + expect(filePath).toBe(`${dir}/index.tsx`); + expect(Object.keys(params).length).toBe(0); + } + + for (let route of ["/posts", "/posts/index", "/posts/"]) { + const { name, params, filePath } = router.match(route); + + expect(name).toBe("/posts"); + expect(filePath).toBe(`${dir}/posts.tsx`); + expect(Object.keys(params).length).toBe(0); + } +}); + +it("should support Request", async () => { + // set up the test + const { dir } = make(["index.tsx", "posts/[id].tsx", "posts.tsx"]); + + const router = new Bun.FileSystemRouter({ + dir, + style: "nextjs", + }); + + for (let current of [ + new Request({ url: "/posts/hello-world" }), + new Request({ url: "http://example.com/posts/hello-world" }), + ]) { + const { + name, + params: { id }, + filePath, + } = router.match(current); + expect(name).toBe("/posts/[id]"); + expect(filePath).toBe(`${dir}/posts/[id].tsx`); + expect(id).toBe("hello-world"); + } +}); + +it("assetPrefix, src, and origin", async () => { + // set up the test + const { dir } = make(["index.tsx", "posts/[id].tsx", "posts.tsx"]); + + const router = new Bun.FileSystemRouter({ + dir, + style: "nextjs", + assetPrefix: "/_next/static/", + origin: "https://nextjs.org", + }); + + for (let current of [ + // Reuqest + new Request({ url: "/posts/hello-world" }), + new Request({ url: "https://nextjs.org/posts/hello-world" }), + ]) { + const { name, src, filePath, checkThisDoesntCrash } = router.match(current); + expect(name).toBe("/posts/[id]"); + + // check nothing is weird on the MatchedRoute object + expect(checkThisDoesntCrash).toBeUndefined(); + + expect(src).toBe("https://nextjs.org/_next/static/posts/[id].tsx"); + expect(filePath).toBe(`${dir}/posts/[id].tsx`); + } +}); + +it(".query works", () => { + // set up the test + const { dir } = make(["posts.tsx"]); + + const router = new Bun.FileSystemRouter({ + dir, + style: "nextjs", + assetPrefix: "/_next/static/", + origin: "https://nextjs.org", + }); + + for (let [current, object] of [ + [new URL("https://example.com/posts?hello=world").href, { hello: "world" }], + [ + new URL("https://example.com/posts?hello=world&second=2").href, + { hello: "world", second: "2" }, + ], + [ + new URL("https://example.com/posts?hello=world&second=2&third=3").href, + { hello: "world", second: "2", third: "3" }, + ], + [new URL("https://example.com/posts").href, {}], + ]) { + const { name, src, filePath, checkThisDoesntCrash, query } = + router.match(current); + expect(name).toBe("/posts"); + + // check nothing is weird on the MatchedRoute object + expect(checkThisDoesntCrash).toBeUndefined(); + + expect(JSON.stringify(query)).toBe(JSON.stringify(object)); + expect(filePath).toBe(`${dir}/posts.tsx`); + } +}); + +it("reload() works", () => { + // set up the test + const { dir } = make(["posts.tsx"]); + + const router = new Bun.FileSystemRouter({ + dir, + style: "nextjs", + assetPrefix: "/_next/static/", + origin: "https://nextjs.org", + }); + + expect(router.match("/posts").name).toBe("/posts"); + router.reload(); + expect(router.match("/posts").name).toBe("/posts"); +}); + +it(".query works with dynamic routes, including params", () => { + // set up the test + const { dir } = make(["posts/[id].tsx"]); + + const router = new Bun.FileSystemRouter({ + dir, + style: "nextjs", + assetPrefix: "/_next/static/", + origin: "https://nextjs.org", + }); + + for (let [current, object] of [ + [ + new URL("https://example.com/posts/123?hello=world").href, + { id: "123", hello: "world" }, + ], + [ + new URL("https://example.com/posts/123?hello=world&second=2").href, + { id: "123", hello: "world", second: "2" }, + ], + [ + new URL("https://example.com/posts/123?hello=world&second=2&third=3") + .href, + { id: "123", hello: "world", second: "2", third: "3" }, + ], + [new URL("https://example.com/posts/123").href, { id: "123" }], + ]) { + const { name, src, filePath, checkThisDoesntCrash, query } = + router.match(current); + expect(name).toBe("/posts/[id]"); + + // check nothing is weird on the MatchedRoute object + expect(checkThisDoesntCrash).toBeUndefined(); + + expect(JSON.stringify(query)).toBe(JSON.stringify(object)); + expect(filePath).toBe(`${dir}/posts/[id].tsx`); + } +}); diff --git a/test/bun.js/gc.js b/test/bun.js/gc.js index 350f279a1..6c444126f 100644 --- a/test/bun.js/gc.js +++ b/test/bun.js/gc.js @@ -12,3 +12,13 @@ export function gcTick(trace = false) { setTimeout(resolve, 0); }); } + +export function withoutAggressiveGC(block) { + const origGC = Bun.unsafe.gcAggressionLevel(); + Bun.unsafe.gcAggressionLevel(0); + try { + return block(); + } finally { + Bun.unsafe.gcAggressionLevel(origGC); + } +} diff --git a/test/bun.js/oniguruma-regexp.test.ts b/test/bun.js/oniguruma-regexp.test.ts index 9fe3d7be8..30dd6e7d2 100644 --- a/test/bun.js/oniguruma-regexp.test.ts +++ b/test/bun.js/oniguruma-regexp.test.ts @@ -3,6 +3,52 @@ import { OnigurumaRegExp } from "bun"; import { expect, it, test } from "bun:test"; import { gc as gcTrace } from "./gc"; +it("character property scripts", () => { + // oniguruma does not support \p{Script=<script value>} + // they are converted to \p{<script value>} internally + const sentence = "A ticket to 大阪 costs ¥2000 👌."; + + const g0 = OnigurumaRegExp("\\p{Emoji_Presentation}", "gu"); + const s0 = sentence.match(g0); + const g1 = RegExp("\\p{Emoji_Presentation}", "gu"); + const s1 = sentence.match(g1); + for (const [i, s] of s0.entries()) { + expect(s === s1[i]).toBe(true); + } + + const g2 = OnigurumaRegExp("\\P{Script_Extensions=Latin}+", "gu"); + const s2 = sentence.match(g2); + const g3 = RegExp("\\P{Script_Extensions=Latin}+", "gu"); + const s3 = sentence.match(g3); + for (const [i, s] of s2.entries()) { + expect(s === s3[i]).toBe(true); + } + + const g4 = OnigurumaRegExp("\\p{Sc}|\\p{P}", "gu"); + const s4 = sentence.match(g4); + const g5 = RegExp("\\p{Sc}|\\p{P}", "gu"); + const s5 = sentence.match(g5); + for (const [i, s] of s4.entries()) { + expect(s === s5[i]).toBe(true); + } + + expect("٢".match(new RegExp("\\p{Script=Thaana}", "u"))).toBe(null); + expect("٢".match(new RegExp("\\p{Script_Extensions=Thaana}", "u"))![0]).toBe( + "٢", + ); + + expect("٢".match(new OnigurumaRegExp("\\p{Thaana}", "u"))).toBe(null); + expect( + "٢".match(new OnigurumaRegExp("\\p{Script_Extensions=Thaana}", "u")), + ).toBe(null); + + let r1 = new OnigurumaRegExp( + "<\\/(?<fullName>(?<name>[-_\\p{Letter}\\p{Number}\\p{script=Deva}\\p{sc=Thai}]{1,32})(?: (?<subcommandOrGroup>[-_\\p{Letter}\\p{Number}\\p{sc=Deva}\\p{sc=Thai}]{1,32}))?(?: (?<subcommand>[-_\\p{Letter}\\p{Number}\\p{sc=Deva}\\p{sc=Thai}]{1,32}))?):(?<id>\\d{17,20})>", + "", + ); + expect(r1 !== null).toBe(true); +}); + it("repeated match and exec calls", () => { for (let i = 0; i < 20000; i++) { let r1 = new OnigurumaRegExp("//.+?/[^?]+", "sg"); diff --git a/test/bun.js/os.test.js b/test/bun.js/os.test.js index 792d2cf40..f48354216 100644 --- a/test/bun.js/os.test.js +++ b/test/bun.js/os.test.js @@ -127,7 +127,7 @@ it("networkInterfaces", () => { it("EOL", () => { if (process.platform === "win32") expect(os.EOL).toBe("\\r\\n"); - else expect(os.EOL).toBe("\\n"); + else expect(os.EOL).toBe("\n"); }); it("devNull", () => { diff --git a/test/bun.js/react-dom.test.tsx b/test/bun.js/react-dom.test.tsx index a05ed16a1..04074acb8 100644 --- a/test/bun.js/react-dom.test.tsx +++ b/test/bun.js/react-dom.test.tsx @@ -218,73 +218,88 @@ describe("ReactDOM", () => { }); } } - // for (let renderToReadableStream of [ - // renderToReadableStreamBun, - // // renderToReadableStreamBrowser, - // ]) { - // // there is an event loop bug that causes deadlocks - // // the bug is with `fetch`, not with the HTTP server - // for (let [inputString, reactElement] of fixtures) { - // describe(`${renderToReadableStream.name}(${inputString})`, () => { - // it("http server, 1 request", async () => { - // var server; - // try { - // server = serve({ - // port: port++, - // async fetch(req) { - // return new Response(await renderToReadableStream(reactElement)); - // }, - // }); - // const resp = await fetch("http://localhost:" + server.port + "/"); - // expect((await resp.text()).replaceAll("<!-- -->", "")).toBe( - // inputString - // ); - // gc(); - // } catch (e) { - // throw e; - // } finally { - // server?.stop(); - // gc(); - // } - // // expect( - // // heapStats().objectTypeCounts.ReadableHTTPResponseSinkController ?? 0 - // // ).toBe(0); - // }); - // // const count = 4; - // // it(`http server, ${count} requests`, async () => { - // // var server; - // // try { - // // server = serve({ - // // port: port++, - // // async fetch(req) { - // // return new Response(await renderToReadableStream(reactElement)); - // // }, - // // }); - // // var total = 0; - // // gc(); - // // while (total++ < count) { - // // var attempt = total; - // // const response = await fetch( - // // "http://localhost:" + server.port + "/" - // // ); - // // gc(); - // // const result = await response.text(); - // // try { - // // expect(result.replaceAll("<!-- -->", "")).toBe(inputString); - // // } catch (e) { - // // e.message += "\nAttempt: " + attempt; - // // throw e; - // // } + for (let renderToReadableStream of [ + renderToReadableStreamBun, + renderToReadableStreamBrowser, + ]) { + // there is an event loop bug that causes deadlocks + // the bug is with `fetch`, not with the HTTP server + for (let [inputString, reactElement] of fixtures) { + describe(`${renderToReadableStream.name}(${inputString})`, () => { + it("http server, 1 request", async () => { + await (async function () { + var server; + try { + server = serve({ + port: port++, + async fetch(req) { + return new Response( + await renderToReadableStream(reactElement), + ); + }, + }); + const resp = await fetch("http://localhost:" + server.port + "/"); + expect((await resp.text()).replaceAll("<!-- -->", "")).toBe( + inputString, + ); + gc(); + } catch (e) { + throw e; + } finally { + server?.stop(); + gc(); + } + })(); + gc(); + expect( + heapStats().objectTypeCounts.ReadableHTTPResponseSinkController ?? + 0, + ).toBe(1); + }); + const count = 4; + it(`http server, ${count} requests`, async () => { + var remain = count; + await (async function () { + var server; + try { + server = serve({ + port: port++, + async fetch(req) { + return new Response( + await renderToReadableStream(reactElement), + ); + }, + }); + gc(); + while (remain--) { + var attempt = remain + 1; + const response = await fetch( + "http://localhost:" + server.port + "/", + ); + gc(); + const result = await response.text(); + try { + expect(result.replaceAll("<!-- -->", "")).toBe(inputString); + } catch (e: any) { + e.message += "\nAttempt: " + attempt; + throw e; + } + + gc(); + } + } catch (e) { + throw e; + } finally { + server.stop(); + } + })(); - // // gc(); - // // } - // // } catch (e) { - // // throw e; - // // } finally { - // // server.stop(); - // // } - // // }); - // }); - // } - // } + const { ReadableHTTPResponseSinkController = 0 } = + heapStats().objectTypeCounts; + expect(ReadableHTTPResponseSinkController).toBe(1); + expect(remain + 1).toBe(0); + }); + }); + } + } }); diff --git a/test/bun.js/resolve.test.js b/test/bun.js/resolve.test.js index 1ae00306e..80e2bb7ba 100644 --- a/test/bun.js/resolve.test.js +++ b/test/bun.js/resolve.test.js @@ -1,6 +1,10 @@ import { it, expect } from "bun:test"; import { mkdirSync, writeFileSync } from "fs"; -import { join } from "path"; +import { join, resolve } from "path"; + +function resolveFrom(from) { + return (specifier) => import.meta.resolveSync(specifier, from); +} it("#imports", async () => { await writePackageJSONImportsFixture(); @@ -44,16 +48,19 @@ it("#imports", async () => { } }); -// this is known to be failing it("#imports with wildcard", async () => { await writePackageJSONImportsFixture(); + const run = resolveFrom( + resolve( + import.meta.dir + "/node_modules/package-json-imports/package.json", + ), + ); - // Chcek that package-json-imports/#foo/wildcard works - expect( - ( - await import.meta.resolve("package-json-imports/#foo/wildcard.js") - ).endsWith("/wildcard.js"), - ).toBe(true); + const wildcard = resolve( + import.meta.dir + "/node_modules/package-json-imports/foo/wildcard.js", + ); + expect(run("#foo/wildcard.js")).toBe(wildcard); + expect(run("#foo/extensionless/wildcard")).toBe(wildcard); }); it("import.meta.resolve", async () => { @@ -241,9 +248,11 @@ function writePackageJSONImportsFixture() { "./baz": "./foo/bar.js", }, imports: { - "#foo": "./foo/private-foo.js", "#foo/bar": "./foo/private-foo.js", - "#foo/": "./foo/", + "#foo/*.js": "./foo/*.js", + "#foo/extensionless/*": "./foo/*.js", + "#foo": "./foo/private-foo.js", + "#internal-react": "react", }, }, diff --git a/test/bun.js/sqlite.test.js b/test/bun.js/sqlite.test.js index 4ca236819..2bf7fc72d 100644 --- a/test/bun.js/sqlite.test.js +++ b/test/bun.js/sqlite.test.js @@ -134,6 +134,15 @@ it("creates", () => { stmt2.finalize(); }); +it("int52", () => { + const db = Database.open(":memory:"); + db.exec("CREATE TABLE test (id INTEGER PRIMARY KEY, int64 INTEGER)"); + db.run("INSERT INTO test (int64) VALUES (?)", Number.MAX_SAFE_INTEGER); + expect(db.query("SELECT * FROM test").get().int64).toBe( + Number.MAX_SAFE_INTEGER, + ); +}); + it("typechecks", () => { const db = Database.open(":memory:"); db.exec("CREATE TABLE test (id INTEGER PRIMARY KEY, name TEXT)"); diff --git a/test/bun.js/streams.test.js b/test/bun.js/streams.test.js index 349a42dc8..4f2aaa9c9 100644 --- a/test/bun.js/streams.test.js +++ b/test/bun.js/streams.test.js @@ -13,40 +13,42 @@ import { gc } from "./gc"; beforeEach(() => gc()); afterEach(() => gc()); -// This test hangs, TODO: fix it -// describe("WritableStream", () => { -// it("works", async () => { -// try { -// var chunks = []; -// var writable = new WritableStream({ -// write(chunk, controller) { -// chunks.push(chunk); -// }, -// close(er) { -// console.log("closed"); -// console.log(er); -// }, -// abort(reason) { -// console.log("aborted!"); -// console.log(reason); -// }, -// }); -// var writer = writable.getWriter(); - -// writer.write(new Uint8Array([1, 2, 3])); -// writer.write(new Uint8Array([4, 5, 6])); -// await writer.close(); - -// expect(JSON.stringify(Array.from(Buffer.concat(chunks)))).toBe( -// JSON.stringify([1, 2, 3, 4, 5, 6]) -// ); -// } catch (e) { -// console.log(e); -// console.log(e.stack); -// throw e; -// } -// }); -// }); +describe("WritableStream", () => { + it("works", async () => { + try { + var chunks = []; + var writable = new WritableStream({ + write(chunk, controller) { + chunks.push(chunk); + }, + close(er) { + console.log("closed"); + console.log(er); + }, + abort(reason) { + console.log("aborted!"); + console.log(reason); + }, + }); + + var writer = writable.getWriter(); + + writer.write(new Uint8Array([1, 2, 3])); + + writer.write(new Uint8Array([4, 5, 6])); + + await writer.close(); + + expect(JSON.stringify(Array.from(Buffer.concat(chunks)))).toBe( + JSON.stringify([1, 2, 3, 4, 5, 6]), + ); + } catch (e) { + console.log(e); + console.log(e.stack); + throw e; + } + }); +}); // describe("ReadableStream.prototype.tee", () => { // it("class", () => { diff --git a/test/bun.js/test-test.test.ts b/test/bun.js/test-test.test.ts new file mode 100644 index 000000000..8ada29ed0 --- /dev/null +++ b/test/bun.js/test-test.test.ts @@ -0,0 +1,144 @@ +import { expect, test } from "@jest/globals"; + +test("toBe()", () => { + const a = 1; + const b = 1; + expect(a).toBe(a); + expect(a).toBe(b); + expect(a).toBe(1); + expect(1).toBe(a); + expect(b).toBe(a); + + const c = { a: 1 }; + const d = { a: 1 }; + expect(c).toBe(c); + expect(c).not.toBe(d); + expect(c).not.toBe({ a: 1 }); + expect({ a: 1 }).not.toBe(c); + expect(d).not.toBe(c); + + expect(1).toBe(1); + // expect(1).not.toBe(1); + + expect(1).not.toBe(2); + expect(1).not.toBe("1"); + expect("hello test").toBe("hello test"); + expect("hello test").not.toBe("hello test2"); +}); + +test("toHaveLength()", () => { + expect({ length: Number.MAX_SAFE_INTEGER }).toHaveLength( + Number.MAX_SAFE_INTEGER, + ); + expect("123").toHaveLength(3); + expect([1, 2, 3]).toHaveLength(3); + expect([1, 2, 3]).not.toHaveLength(2); + expect("123").not.toHaveLength(2); + expect({ length: 3 }).toHaveLength(3); + expect({ length: 3 }).not.toHaveLength(2); + expect({ length: 3 }).not.toHaveLength(Number.MAX_SAFE_INTEGER); + expect({ length: Number.MAX_SAFE_INTEGER }).not.toHaveLength( + Number.MAX_SAFE_INTEGER - 1, + ); + expect({ length: 3.3 }).not.toHaveLength(3); + expect("123").not.toHaveLength(-0); +}); + +test("toContain()", () => { + const s1 = new String("123"); + expect(s1).not.toContain("12"); + const s2 = "123"; + expect(s2).toContain("12"); + + expect("test").toContain("es"); + expect("test").toContain("est"); + expect("test").toContain("test"); + expect(["test", "es"]).toContain("es"); + expect("").toContain(""); + expect([""]).toContain(""); + + expect(["lemon", "lime"]).not.toContain("orange"); + expect("citrus fruits").toContain("fruit"); + + const a = new Uint16Array([1, 2, 3]); + expect(a).toContain(2); + expect(a).not.toContain(4); + // expect([4, 5, 6]).not.toContain(5); + + expect([]).not.toContain([]); +}); + +test("toBeTruthy()", () => { + expect("test").toBeTruthy(); + expect(true).toBeTruthy(); + expect(1).toBeTruthy(); + expect({}).toBeTruthy(); + expect([]).toBeTruthy(); + expect(() => {}).toBeTruthy(); + // expect(() => {}).not.toBeTruthy(); + + expect("").not.toBeTruthy(); + expect(0).not.toBeTruthy(); + expect(-0).not.toBeTruthy(); + expect(NaN).not.toBeTruthy(); + expect(0n).not.toBeTruthy(); + expect(false).not.toBeTruthy(); + expect(null).not.toBeTruthy(); + expect(undefined).not.toBeTruthy(); +}); + +test("toBeUndefined()", () => { + expect(undefined).toBeUndefined(); + // expect(undefined).not.toBeUndefined(); + + expect(null).not.toBeUndefined(); + expect(null).not.not.not.toBeUndefined(); + expect(0).not.toBeUndefined(); + expect("hello defined").not.toBeUndefined(); +}); + +test("toBeNaN()", () => { + expect(NaN).toBeNaN(); + // expect(NaN).not.toBeNaN(); + + expect(0).not.toBeNaN(); + expect("hello not NaN").not.toBeNaN(); +}); + +test("toBeNull()", () => { + expect(null).toBeNull(); + // expect(null).not.toBeNull(); + + expect(undefined).not.toBeNull(); + expect(0).not.toBeNull(); + expect("hello not null").not.toBeNull(); +}); + +test("toBeDefined()", () => { + expect(0).toBeDefined(); + expect("hello defined").toBeDefined(); + expect(null).toBeDefined(); + // expect(null).not.toBeDefined(); + + expect(undefined).not.toBeDefined(); +}); + +test("toBeFalsy()", () => { + expect("").toBeFalsy(); + expect(0).toBeFalsy(); + expect(-0).toBeFalsy(); + expect(NaN).toBeFalsy(); + expect(0n).toBeFalsy(); + expect(false).toBeFalsy(); + expect(null).toBeFalsy(); + expect(undefined).toBeFalsy(); + // expect(undefined).not.toBeFalsy(); + + expect("hello not falsy").not.toBeFalsy(); + expect("hello not falsy").not.not.not.toBeFalsy(); + expect(1).not.toBeFalsy(); + expect(true).not.toBeFalsy(); + expect({}).not.toBeFalsy(); + expect([]).not.toBeFalsy(); + expect(() => {}).not.toBeFalsy(); +}); diff --git a/test/bun.js/web-globals.test.js b/test/bun.js/web-globals.test.js index 2f966aa03..06bb1cb67 100644 --- a/test/bun.js/web-globals.test.js +++ b/test/bun.js/web-globals.test.js @@ -1,4 +1,6 @@ +import { unsafe } from "bun"; import { expect, it, test } from "bun:test"; +import { withoutAggressiveGC } from "gc"; test("exists", () => { expect(typeof URL !== "undefined").toBe(true); @@ -58,11 +60,14 @@ it("crypto.getRandomValues", () => { ); } - // run it again to check that the fast path works - for (var i = 0; i < 9000; i++) { - var array = crypto.getRandomValues(foo); - expect(array).toBe(foo); - } + // disable it for this block because it tends to get stuck here running the GC forever + withoutAggressiveGC(() => { + // run it again to check that the fast path works + for (var i = 0; i < 9000; i++) { + var array = crypto.getRandomValues(foo); + expect(array).toBe(foo); + } + }); // run it on a large input expect( @@ -87,15 +92,17 @@ it("crypto.randomUUID", () => { expect(uuid[18]).toBe("-"); expect(uuid[23]).toBe("-"); - // check that the fast path works - for (let i = 0; i < 9000; i++) { - var uuid2 = crypto.randomUUID(); - expect(uuid2.length).toBe(36); - expect(uuid2[8]).toBe("-"); - expect(uuid2[13]).toBe("-"); - expect(uuid2[18]).toBe("-"); - expect(uuid2[23]).toBe("-"); - } + withoutAggressiveGC(() => { + // check that the fast path works + for (let i = 0; i < 9000; i++) { + var uuid2 = crypto.randomUUID(); + expect(uuid2.length).toBe(36); + expect(uuid2[8]).toBe("-"); + expect(uuid2[13]).toBe("-"); + expect(uuid2[18]).toBe("-"); + expect(uuid2[23]).toBe("-"); + } + }); }); it("URL.prototype.origin", () => { |