From 3271e1464ea0ec56f4fca2016f9e15c4288c75a3 Mon Sep 17 00:00:00 2001 From: Pierre Tachoire Date: Fri, 6 Mar 2026 10:21:07 +0100 Subject: [PATCH] Revert pool arena usage w/ ReadableStream Revert "update ref counting for new ReadableStream usages" This reverts commit c64500dd85bda8f5b55f80b5070374ec2c01b0f5. Revert "add reference counting for ReadableStream" This reverts commit 812ad3f49e29d1e4ffb6ba8b9cd4d32ddcf38edb. Revert "use a pool arena with ReadableStream" This reverts commit 8e8a1a7541e33e2bd33905fd2fe3b407538f8683. --- .../webapi/encoding/TextDecoderStream.zig | 10 ---- .../webapi/encoding/TextEncoderStream.zig | 10 ---- src/browser/webapi/streams/ReadableStream.zig | 46 +------------------ .../ReadableStreamDefaultController.zig | 24 +++------- .../streams/ReadableStreamDefaultReader.zig | 19 -------- .../webapi/streams/TransformStream.zig | 20 -------- 6 files changed, 9 insertions(+), 120 deletions(-) diff --git a/src/browser/webapi/encoding/TextDecoderStream.zig b/src/browser/webapi/encoding/TextDecoderStream.zig index b0b7e45c..a5b2dc9a 100644 --- a/src/browser/webapi/encoding/TextDecoderStream.zig +++ b/src/browser/webapi/encoding/TextDecoderStream.zig @@ -72,14 +72,6 @@ pub fn init(label_: ?[]const u8, opts_: ?InitOpts, page: *Page) !TextDecoderStre }; } -pub fn acquireRef(self: *TextDecoderStream) void { - self._transform.acquireRef(); -} - -pub fn deinit(self: *TextDecoderStream, shutdown: bool, page: *Page) void { - self._transform.deinit(shutdown, page); -} - fn decodeTransform(controller: *TransformStream.DefaultController, chunk: js.Value, ignoreBOM: bool) !void { // chunk should be a Uint8Array; decode it as UTF-8 string const typed_array = try chunk.toZig(js.TypedArray(u8)); @@ -119,8 +111,6 @@ pub const JsApi = struct { pub const name = "TextDecoderStream"; pub const prototype_chain = bridge.prototypeChain(); pub var class_id: bridge.ClassId = undefined; - pub const weak = true; - pub const finalizer = bridge.finalizer(TextDecoderStream.deinit); }; pub const constructor = bridge.constructor(TextDecoderStream.init, .{}); diff --git a/src/browser/webapi/encoding/TextEncoderStream.zig b/src/browser/webapi/encoding/TextEncoderStream.zig index a7ae5e2e..b2526637 100644 --- a/src/browser/webapi/encoding/TextEncoderStream.zig +++ b/src/browser/webapi/encoding/TextEncoderStream.zig @@ -34,14 +34,6 @@ pub fn init(page: *Page) !TextEncoderStream { }; } -pub fn acquireRef(self: *TextEncoderStream) void { - self._transform.acquireRef(); -} - -pub fn deinit(self: *TextEncoderStream, shutdown: bool, page: *Page) void { - self._transform.deinit(shutdown, page); -} - fn encodeTransform(controller: *TransformStream.DefaultController, chunk: js.Value) !void { // chunk should be a JS string; encode it as UTF-8 bytes (Uint8Array) const str = chunk.isString() orelse return error.InvalidChunk; @@ -64,8 +56,6 @@ pub const JsApi = struct { pub const name = "TextEncoderStream"; pub const prototype_chain = bridge.prototypeChain(); pub var class_id: bridge.ClassId = undefined; - pub const weak = true; - pub const finalizer = bridge.finalizer(TextEncoderStream.deinit); }; pub const constructor = bridge.constructor(TextEncoderStream.init, .{}); diff --git a/src/browser/webapi/streams/ReadableStream.zig b/src/browser/webapi/streams/ReadableStream.zig index 7d99a0c1..e4e5d0f9 100644 --- a/src/browser/webapi/streams/ReadableStream.zig +++ b/src/browser/webapi/streams/ReadableStream.zig @@ -52,8 +52,6 @@ _pull_fn: ?js.Function.Global = null, _pulling: bool = false, _pull_again: bool = false, _cancel: ?Cancel = null, -_arena: std.mem.Allocator, -_rc: usize = 0, const UnderlyingSource = struct { start: ?js.Function = null, @@ -70,18 +68,13 @@ const QueueingStrategy = struct { pub fn init(src_: ?UnderlyingSource, strategy_: ?QueueingStrategy, page: *Page) !*ReadableStream { const strategy: QueueingStrategy = strategy_ orelse .{}; - const arena = try page.getArena(.{ .debug = "ReadableStream" }); - errdefer page.releaseArena(arena); - - const self = try arena.create(ReadableStream); - self.* = .{ + const self = try page._factory.create(ReadableStream{ ._page = page, ._state = .readable, - ._arena = arena, ._reader = null, ._controller = undefined, ._stored_error = null, - }; + }); self._controller = try ReadableStreamDefaultController.init(self, strategy.highWaterMark, page); @@ -115,23 +108,6 @@ pub fn initWithData(data: []const u8, page: *Page) !*ReadableStream { return stream; } -pub fn deinit(self: *ReadableStream, _: bool, page: *Page) void { - const rc = self._rc; - if (comptime IS_DEBUG) { - std.debug.assert(rc != 0); - } - - if (rc == 1) { - page.releaseArena(self._arena); - } else { - self._rc = rc - 1; - } -} - -pub fn acquireRef(self: *ReadableStream) void { - self._rc += 1; -} - pub fn getReader(self: *ReadableStream, page: *Page) !*ReadableStreamDefaultReader { if (self.getLocked()) { return error.ReaderLocked; @@ -144,12 +120,6 @@ pub fn getReader(self: *ReadableStream, page: *Page) !*ReadableStreamDefaultRead pub fn releaseReader(self: *ReadableStream) void { self._reader = null; - - const rc = self._rc; - if (comptime IS_DEBUG) { - std.debug.assert(rc != 0); - } - self._rc = rc - 1; } pub fn getAsyncIterator(self: *ReadableStream, page: *Page) !*AsyncIterator { @@ -397,8 +367,6 @@ pub const JsApi = struct { pub const name = "ReadableStream"; pub const prototype_chain = bridge.prototypeChain(); pub var class_id: bridge.ClassId = undefined; - pub const weak = true; - pub const finalizer = bridge.finalizer(ReadableStream.deinit); }; pub const constructor = bridge.constructor(ReadableStream.init, .{}); @@ -422,14 +390,6 @@ pub const AsyncIterator = struct { }); } - pub fn acquireRef(self: *AsyncIterator) void { - self._stream.acquireRef(); - } - - pub fn deinit(self: *AsyncIterator, shutdown: bool, page: *Page) void { - self._stream.deinit(shutdown, page); - } - pub fn next(self: *AsyncIterator, page: *Page) !js.Promise { return self._reader.read(page); } @@ -446,8 +406,6 @@ pub const AsyncIterator = struct { pub const name = "ReadableStreamAsyncIterator"; pub const prototype_chain = bridge.prototypeChain(); pub var class_id: bridge.ClassId = undefined; - pub const weak = true; - pub const finalizer = bridge.finalizer(AsyncIterator.deinit); }; pub const next = bridge.function(ReadableStream.AsyncIterator.next, .{}); diff --git a/src/browser/webapi/streams/ReadableStreamDefaultController.zig b/src/browser/webapi/streams/ReadableStreamDefaultController.zig index cd6c6352..18228475 100644 --- a/src/browser/webapi/streams/ReadableStreamDefaultController.zig +++ b/src/browser/webapi/streams/ReadableStreamDefaultController.zig @@ -27,8 +27,6 @@ const ReadableStreamDefaultReader = @import("ReadableStreamDefaultReader.zig"); const IS_DEBUG = @import("builtin").mode == .Debug; -/// ReadableStreamDefaultController uses ReadableStream's arena to make -/// allocation. Indeed, the controller is owned by its ReadableStream. const ReadableStreamDefaultController = @This(); pub const Chunk = union(enum) { @@ -48,6 +46,7 @@ pub const Chunk = union(enum) { _page: *Page, _stream: *ReadableStream, +_arena: std.mem.Allocator, _queue: std.ArrayList(Chunk), _pending_reads: std.ArrayList(js.PromiseResolver.Global), _high_water_mark: u32, @@ -57,22 +56,15 @@ pub fn init(stream: *ReadableStream, high_water_mark: u32, page: *Page) !*Readab ._page = page, ._queue = .empty, ._stream = stream, + ._arena = page.arena, ._pending_reads = .empty, ._high_water_mark = high_water_mark, }); } -pub fn acquireRef(self: *ReadableStreamDefaultController) void { - self._stream.acquireRef(); -} - -pub fn deinit(self: *ReadableStreamDefaultController, shutdown: bool, page: *Page) void { - self._stream.deinit(shutdown, page); -} - pub fn addPendingRead(self: *ReadableStreamDefaultController, page: *Page) !js.Promise { const resolver = page.js.local.?.createPromiseResolver(); - try self._pending_reads.append(self._stream._arena, try resolver.persist()); + try self._pending_reads.append(self._arena, try resolver.persist()); return resolver.promise(); } @@ -82,8 +74,8 @@ pub fn enqueue(self: *ReadableStreamDefaultController, chunk: Chunk) !void { } if (self._pending_reads.items.len == 0) { - const chunk_copy = try chunk.dupe(self._stream._arena); - return self._queue.append(self._stream._arena, chunk_copy); + const chunk_copy = try chunk.dupe(self._page.arena); + return self._queue.append(self._arena, chunk_copy); } // I know, this is ouch! But we expect to have very few (if any) @@ -117,7 +109,7 @@ pub fn enqueueValue(self: *ReadableStreamDefaultController, value: js.Value) !vo if (self._pending_reads.items.len == 0) { const persisted = try value.persist(); - try self._queue.append(self._stream._arena, .{ .js_value = persisted }); + try self._queue.append(self._arena, .{ .js_value = persisted }); return; } @@ -178,7 +170,7 @@ pub fn doError(self: *ReadableStreamDefaultController, err: []const u8) !void { } self._stream._state = .errored; - self._stream._stored_error = try self._stream._arena.dupe(u8, err); + self._stream._stored_error = try self._page.arena.dupe(u8, err); // Reject all pending reads for (self._pending_reads.items) |resolver| { @@ -218,8 +210,6 @@ pub const JsApi = struct { pub const name = "ReadableStreamDefaultController"; pub const prototype_chain = bridge.prototypeChain(); pub var class_id: bridge.ClassId = undefined; - pub const weak = true; - pub const finalizer = bridge.finalizer(ReadableStreamDefaultController.deinit); }; pub const enqueue = bridge.function(ReadableStreamDefaultController.enqueueValue, .{}); diff --git a/src/browser/webapi/streams/ReadableStreamDefaultReader.zig b/src/browser/webapi/streams/ReadableStreamDefaultReader.zig index e8c639ce..2d3c5bbe 100644 --- a/src/browser/webapi/streams/ReadableStreamDefaultReader.zig +++ b/src/browser/webapi/streams/ReadableStreamDefaultReader.zig @@ -19,8 +19,6 @@ const std = @import("std"); const js = @import("../../js/js.zig"); -const IS_DEBUG = @import("builtin").mode == .Debug; - const Page = @import("../../Page.zig"); const ReadableStream = @import("ReadableStream.zig"); const ReadableStreamDefaultController = @import("ReadableStreamDefaultController.zig"); @@ -37,21 +35,6 @@ pub fn init(stream: *ReadableStream, page: *Page) !*ReadableStreamDefaultReader }); } -pub fn acquireRef(self: *ReadableStreamDefaultReader) void { - const stream = self._stream orelse { - if (comptime IS_DEBUG) { - std.debug.assert(false); - } - return; - }; - stream.acquireRef(); -} - -pub fn deinit(self: *ReadableStreamDefaultReader, shutdown: bool, page: *Page) void { - const stream = self._stream orelse return; - stream.deinit(shutdown, page); -} - pub const ReadResult = struct { done: bool, value: Chunk, @@ -127,8 +110,6 @@ pub const JsApi = struct { pub const name = "ReadableStreamDefaultReader"; pub const prototype_chain = bridge.prototypeChain(); pub var class_id: bridge.ClassId = undefined; - pub const weak = true; - pub const finalizer = bridge.finalizer(ReadableStreamDefaultReader.deinit); }; pub const read = bridge.function(ReadableStreamDefaultReader.read, .{}); diff --git a/src/browser/webapi/streams/TransformStream.zig b/src/browser/webapi/streams/TransformStream.zig index bfed7330..e1f42029 100644 --- a/src/browser/webapi/streams/TransformStream.zig +++ b/src/browser/webapi/streams/TransformStream.zig @@ -85,14 +85,6 @@ pub fn initWithZigTransform(zig_transform: ZigTransformFn, page: *Page) !*Transf return self; } -pub fn acquireRef(self: *TransformStream) void { - self._readable.acquireRef(); -} - -pub fn deinit(self: *TransformStream, shutdown: bool, page: *Page) void { - self._readable.deinit(shutdown, page); -} - pub fn transformWrite(self: *TransformStream, chunk: js.Value, page: *Page) !void { if (self._controller._zig_transform_fn) |zig_fn| { // Zig-level transform (used by TextEncoderStream etc.) @@ -138,8 +130,6 @@ pub const JsApi = struct { pub const name = "TransformStream"; pub const prototype_chain = bridge.prototypeChain(); pub var class_id: bridge.ClassId = undefined; - pub const weak = true; - pub const finalizer = bridge.finalizer(TransformStream.deinit); }; pub const constructor = bridge.constructor(TransformStream.init, .{}); @@ -175,14 +165,6 @@ pub const TransformStreamDefaultController = struct { }); } - pub fn acquireRef(self: *TransformStreamDefaultController) void { - self._stream.acquireRef(); - } - - pub fn deinit(self: *TransformStreamDefaultController, shutdown: bool, page: *Page) void { - self._stream.deinit(shutdown, page); - } - pub fn enqueue(self: *TransformStreamDefaultController, chunk: ReadableStreamDefaultController.Chunk) !void { try self._stream._readable._controller.enqueue(chunk); } @@ -207,8 +189,6 @@ pub const TransformStreamDefaultController = struct { pub const name = "TransformStreamDefaultController"; pub const prototype_chain = bridge.prototypeChain(); pub var class_id: bridge.ClassId = undefined; - pub const weak = true; - pub const finalizer = bridge.finalizer(TransformStreamDefaultController.deinit); }; pub const enqueue = bridge.function(TransformStreamDefaultController.enqueueValue, .{});