1818
1919const std = @import ("std" );
2020
21- const ArenaAllocator = std .heap . ArenaAllocator ;
21+ const Allocator = std .mem . Allocator ;
2222
2323const Env = @import ("env.zig" ).Env ;
2424const Page = @import ("page.zig" ).Page ;
@@ -37,7 +37,17 @@ pub const Session = struct {
3737 browser : * Browser ,
3838
3939 // Used to create our Inspector and in the BrowserContext.
40- arena : ArenaAllocator ,
40+ arena : Allocator ,
41+
42+ // The page's arena is unsuitable for data that has to existing while
43+ // navigating from one page to another. For example, if we're clicking
44+ // on an HREF, the URL exists in the original page (where the click
45+ // originated) but also has to exist in the new page.
46+ // While we could use the Session's arena, this could accumulate a lot of
47+ // memory if we do many navigation events. The `transfer_arena` is meant to
48+ // bridge the gap: existing long enough to store any data needed to end one
49+ // page and start another.
50+ transfer_arena : Allocator ,
4151
4252 executor : Env.Executor ,
4353 storage_shed : storage.Shed ,
@@ -53,17 +63,17 @@ pub const Session = struct {
5363 self .* = .{
5464 .browser = browser ,
5565 .executor = executor ,
56- .arena = ArenaAllocator . init ( allocator ),
66+ .arena = browser . session_arena . allocator ( ),
5767 .storage_shed = storage .Shed .init (allocator ),
5868 .cookie_jar = storage .CookieJar .init (allocator ),
69+ .transfer_arena = browser .transfer_arena .allocator (),
5970 };
6071 }
6172
6273 pub fn deinit (self : * Session ) void {
6374 if (self .page != null ) {
6475 self .removePage ();
6576 }
66- self .arena .deinit ();
6777 self .cookie_jar .deinit ();
6878 self .storage_shed .deinit ();
6979 self .executor .deinit ();
@@ -116,12 +126,12 @@ pub const Session = struct {
116126 // it isn't null!
117127 std .debug .assert (self .page != null );
118128
119- // can't use the page arena, because we're about to reset it
120- // and don't want to use the session's arena, because that'll start to
121- // look like a leak if we navigate from page to page a lot.
122- var buf : [ 2048 ] u8 = undefined ;
123- var fba = std . heap . FixedBufferAllocator . init ( & buf );
124- const url = try self .page .? .url .resolve (fba . allocator () , url_string );
129+ defer _ = self . browser . transfer_arena . reset (.{ . retain_with_limit = 1 * 1024 * 1024 });
130+
131+ // it's safe to use the transfer arena here, because the page will
132+ // eventually clone the URL using its own page_arena (after it gets
133+ // the final URL, possibly following redirects)
134+ const url = try self .page .? .url .resolve (self . transfer_arena , url_string );
125135
126136 self .removePage ();
127137 var page = try self .createPage ();
0 commit comments