mirror of
https://github.com/oven-sh/bun
synced 2026-02-12 20:09:04 +00:00
122 lines
4.4 KiB
Zig
122 lines
4.4 KiB
Zig
//! Represents a boundary between client and server code. Every boundary
|
|
//! gets bundled twice, once for the desired target, and once to generate
|
|
//! a module of "references". Specifically, the generated file takes the
|
|
//! canonical Ast as input to derive a wrapper. See `Framework.ServerComponents`
|
|
//! for more details about this generated file.
|
|
//!
|
|
//! This is sometimes abbreviated as SCB
|
|
use_directive: UseDirective,
|
|
|
|
/// The index of the original file.
|
|
source_index: Index.Int,
|
|
|
|
/// Index to the file imported on the opposite platform, which is
|
|
/// generated by the bundler. For client components, this is the
|
|
/// server's code. For server actions, this is the client's code.
|
|
reference_source_index: Index.Int,
|
|
|
|
/// When `bake.Framework.ServerComponents.separate_ssr_graph` is enabled this
|
|
/// points to the separated module. When the SSR graph is not separate, this is
|
|
/// equal to `reference_source_index`
|
|
//
|
|
// TODO: Is this used for server actions.
|
|
ssr_source_index: Index.Int,
|
|
|
|
/// The requirements for this data structure is to have reasonable lookup
|
|
/// speed, but also being able to pull a `[]const Index.Int` of all
|
|
/// boundaries for iteration.
|
|
pub const List = struct {
|
|
list: std.MultiArrayList(ServerComponentBoundary) = .{},
|
|
/// Used to facilitate fast lookups into `items` by `.source_index`
|
|
map: Map = .{},
|
|
|
|
const Map = std.ArrayHashMapUnmanaged(void, void, struct {}, true);
|
|
|
|
/// Can only be called on the bundler thread.
|
|
pub fn put(
|
|
m: *List,
|
|
allocator: std.mem.Allocator,
|
|
source_index: Index.Int,
|
|
use_directive: UseDirective,
|
|
reference_source_index: Index.Int,
|
|
ssr_source_index: Index.Int,
|
|
) !void {
|
|
try m.list.append(allocator, .{
|
|
.source_index = source_index,
|
|
.use_directive = use_directive,
|
|
.reference_source_index = reference_source_index,
|
|
.ssr_source_index = ssr_source_index,
|
|
});
|
|
const gop = try m.map.getOrPutAdapted(
|
|
allocator,
|
|
source_index,
|
|
Adapter{ .list = m.list.slice() },
|
|
);
|
|
bun.assert(!gop.found_existing);
|
|
}
|
|
|
|
/// Can only be called on the bundler thread.
|
|
pub fn getIndex(l: *const List, real_source_index: Index.Int) ?usize {
|
|
return l.map.getIndexAdapted(
|
|
real_source_index,
|
|
Adapter{ .list = l.list.slice() },
|
|
);
|
|
}
|
|
|
|
/// Use this to improve speed of accessing fields at the cost of
|
|
/// storing more pointers. Invalidated when input is mutated.
|
|
pub fn slice(l: List) Slice {
|
|
return .{ .list = l.list.slice(), .map = l.map };
|
|
}
|
|
|
|
pub const Slice = struct {
|
|
list: std.MultiArrayList(ServerComponentBoundary).Slice,
|
|
map: Map,
|
|
|
|
pub fn getIndex(l: *const Slice, real_source_index: Index.Int) ?usize {
|
|
return l.map.getIndexAdapted(
|
|
real_source_index,
|
|
Adapter{ .list = l.list },
|
|
) orelse return null;
|
|
}
|
|
|
|
pub fn getReferenceSourceIndex(l: *const Slice, real_source_index: Index.Int) ?u32 {
|
|
const i = l.map.getIndexAdapted(
|
|
real_source_index,
|
|
Adapter{ .list = l.list },
|
|
) orelse return null;
|
|
bun.unsafeAssert(l.list.capacity > 0); // optimize MultiArrayList.Slice.items
|
|
return l.list.items(.reference_source_index)[i];
|
|
}
|
|
|
|
pub fn bitSet(scbs: Slice, alloc: std.mem.Allocator, input_file_count: usize) !bun.bit_set.DynamicBitSetUnmanaged {
|
|
var scb_bitset = try bun.bit_set.DynamicBitSetUnmanaged.initEmpty(alloc, input_file_count);
|
|
for (scbs.list.items(.source_index)) |source_index| {
|
|
scb_bitset.set(source_index);
|
|
}
|
|
return scb_bitset;
|
|
}
|
|
};
|
|
|
|
pub const Adapter = struct {
|
|
list: std.MultiArrayList(ServerComponentBoundary).Slice,
|
|
|
|
pub fn hash(_: Adapter, key: Index.Int) u32 {
|
|
return std.hash.uint32(key);
|
|
}
|
|
|
|
pub fn eql(adapt: Adapter, a: Index.Int, _: void, b_index: usize) bool {
|
|
bun.unsafeAssert(adapt.list.capacity > 0); // optimize MultiArrayList.Slice.items
|
|
return a == adapt.list.items(.source_index)[b_index];
|
|
}
|
|
};
|
|
};
|
|
|
|
const bun = @import("bun");
|
|
const std = @import("std");
|
|
|
|
const js_ast = bun.ast;
|
|
const Index = js_ast.Index;
|
|
const ServerComponentBoundary = js_ast.ServerComponentBoundary;
|
|
const UseDirective = js_ast.UseDirective;
|