Revert pool arena usage w/ ReadableStream

Revert "update ref counting for new ReadableStream usages"
This reverts commit c64500dd85.

Revert "add reference counting for ReadableStream"
This reverts commit 812ad3f49e.

Revert "use a pool arena with ReadableStream"
This reverts commit 8e8a1a7541.
This commit is contained in:
Pierre Tachoire
2026-03-06 10:21:07 +01:00
parent 58c2355c8b
commit 3271e1464e
6 changed files with 9 additions and 120 deletions

View File

@@ -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 { fn decodeTransform(controller: *TransformStream.DefaultController, chunk: js.Value, ignoreBOM: bool) !void {
// chunk should be a Uint8Array; decode it as UTF-8 string // chunk should be a Uint8Array; decode it as UTF-8 string
const typed_array = try chunk.toZig(js.TypedArray(u8)); const typed_array = try chunk.toZig(js.TypedArray(u8));
@@ -119,8 +111,6 @@ pub const JsApi = struct {
pub const name = "TextDecoderStream"; pub const name = "TextDecoderStream";
pub const prototype_chain = bridge.prototypeChain(); pub const prototype_chain = bridge.prototypeChain();
pub var class_id: bridge.ClassId = undefined; 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, .{}); pub const constructor = bridge.constructor(TextDecoderStream.init, .{});

View File

@@ -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 { fn encodeTransform(controller: *TransformStream.DefaultController, chunk: js.Value) !void {
// chunk should be a JS string; encode it as UTF-8 bytes (Uint8Array) // chunk should be a JS string; encode it as UTF-8 bytes (Uint8Array)
const str = chunk.isString() orelse return error.InvalidChunk; const str = chunk.isString() orelse return error.InvalidChunk;
@@ -64,8 +56,6 @@ pub const JsApi = struct {
pub const name = "TextEncoderStream"; pub const name = "TextEncoderStream";
pub const prototype_chain = bridge.prototypeChain(); pub const prototype_chain = bridge.prototypeChain();
pub var class_id: bridge.ClassId = undefined; 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, .{}); pub const constructor = bridge.constructor(TextEncoderStream.init, .{});

View File

@@ -52,8 +52,6 @@ _pull_fn: ?js.Function.Global = null,
_pulling: bool = false, _pulling: bool = false,
_pull_again: bool = false, _pull_again: bool = false,
_cancel: ?Cancel = null, _cancel: ?Cancel = null,
_arena: std.mem.Allocator,
_rc: usize = 0,
const UnderlyingSource = struct { const UnderlyingSource = struct {
start: ?js.Function = null, start: ?js.Function = null,
@@ -70,18 +68,13 @@ const QueueingStrategy = struct {
pub fn init(src_: ?UnderlyingSource, strategy_: ?QueueingStrategy, page: *Page) !*ReadableStream { pub fn init(src_: ?UnderlyingSource, strategy_: ?QueueingStrategy, page: *Page) !*ReadableStream {
const strategy: QueueingStrategy = strategy_ orelse .{}; const strategy: QueueingStrategy = strategy_ orelse .{};
const arena = try page.getArena(.{ .debug = "ReadableStream" }); const self = try page._factory.create(ReadableStream{
errdefer page.releaseArena(arena);
const self = try arena.create(ReadableStream);
self.* = .{
._page = page, ._page = page,
._state = .readable, ._state = .readable,
._arena = arena,
._reader = null, ._reader = null,
._controller = undefined, ._controller = undefined,
._stored_error = null, ._stored_error = null,
}; });
self._controller = try ReadableStreamDefaultController.init(self, strategy.highWaterMark, page); self._controller = try ReadableStreamDefaultController.init(self, strategy.highWaterMark, page);
@@ -115,23 +108,6 @@ pub fn initWithData(data: []const u8, page: *Page) !*ReadableStream {
return stream; 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 { pub fn getReader(self: *ReadableStream, page: *Page) !*ReadableStreamDefaultReader {
if (self.getLocked()) { if (self.getLocked()) {
return error.ReaderLocked; return error.ReaderLocked;
@@ -144,12 +120,6 @@ pub fn getReader(self: *ReadableStream, page: *Page) !*ReadableStreamDefaultRead
pub fn releaseReader(self: *ReadableStream) void { pub fn releaseReader(self: *ReadableStream) void {
self._reader = null; 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 { pub fn getAsyncIterator(self: *ReadableStream, page: *Page) !*AsyncIterator {
@@ -397,8 +367,6 @@ pub const JsApi = struct {
pub const name = "ReadableStream"; pub const name = "ReadableStream";
pub const prototype_chain = bridge.prototypeChain(); pub const prototype_chain = bridge.prototypeChain();
pub var class_id: bridge.ClassId = undefined; 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, .{}); 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 { pub fn next(self: *AsyncIterator, page: *Page) !js.Promise {
return self._reader.read(page); return self._reader.read(page);
} }
@@ -446,8 +406,6 @@ pub const AsyncIterator = struct {
pub const name = "ReadableStreamAsyncIterator"; pub const name = "ReadableStreamAsyncIterator";
pub const prototype_chain = bridge.prototypeChain(); pub const prototype_chain = bridge.prototypeChain();
pub var class_id: bridge.ClassId = undefined; 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, .{}); pub const next = bridge.function(ReadableStream.AsyncIterator.next, .{});

View File

@@ -27,8 +27,6 @@ const ReadableStreamDefaultReader = @import("ReadableStreamDefaultReader.zig");
const IS_DEBUG = @import("builtin").mode == .Debug; 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(); const ReadableStreamDefaultController = @This();
pub const Chunk = union(enum) { pub const Chunk = union(enum) {
@@ -48,6 +46,7 @@ pub const Chunk = union(enum) {
_page: *Page, _page: *Page,
_stream: *ReadableStream, _stream: *ReadableStream,
_arena: std.mem.Allocator,
_queue: std.ArrayList(Chunk), _queue: std.ArrayList(Chunk),
_pending_reads: std.ArrayList(js.PromiseResolver.Global), _pending_reads: std.ArrayList(js.PromiseResolver.Global),
_high_water_mark: u32, _high_water_mark: u32,
@@ -57,22 +56,15 @@ pub fn init(stream: *ReadableStream, high_water_mark: u32, page: *Page) !*Readab
._page = page, ._page = page,
._queue = .empty, ._queue = .empty,
._stream = stream, ._stream = stream,
._arena = page.arena,
._pending_reads = .empty, ._pending_reads = .empty,
._high_water_mark = high_water_mark, ._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 { pub fn addPendingRead(self: *ReadableStreamDefaultController, page: *Page) !js.Promise {
const resolver = page.js.local.?.createPromiseResolver(); 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(); return resolver.promise();
} }
@@ -82,8 +74,8 @@ pub fn enqueue(self: *ReadableStreamDefaultController, chunk: Chunk) !void {
} }
if (self._pending_reads.items.len == 0) { if (self._pending_reads.items.len == 0) {
const chunk_copy = try chunk.dupe(self._stream._arena); const chunk_copy = try chunk.dupe(self._page.arena);
return self._queue.append(self._stream._arena, chunk_copy); return self._queue.append(self._arena, chunk_copy);
} }
// I know, this is ouch! But we expect to have very few (if any) // 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) { if (self._pending_reads.items.len == 0) {
const persisted = try value.persist(); 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; return;
} }
@@ -178,7 +170,7 @@ pub fn doError(self: *ReadableStreamDefaultController, err: []const u8) !void {
} }
self._stream._state = .errored; 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 // Reject all pending reads
for (self._pending_reads.items) |resolver| { for (self._pending_reads.items) |resolver| {
@@ -218,8 +210,6 @@ pub const JsApi = struct {
pub const name = "ReadableStreamDefaultController"; pub const name = "ReadableStreamDefaultController";
pub const prototype_chain = bridge.prototypeChain(); pub const prototype_chain = bridge.prototypeChain();
pub var class_id: bridge.ClassId = undefined; 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, .{}); pub const enqueue = bridge.function(ReadableStreamDefaultController.enqueueValue, .{});

View File

@@ -19,8 +19,6 @@
const std = @import("std"); const std = @import("std");
const js = @import("../../js/js.zig"); const js = @import("../../js/js.zig");
const IS_DEBUG = @import("builtin").mode == .Debug;
const Page = @import("../../Page.zig"); const Page = @import("../../Page.zig");
const ReadableStream = @import("ReadableStream.zig"); const ReadableStream = @import("ReadableStream.zig");
const ReadableStreamDefaultController = @import("ReadableStreamDefaultController.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 { pub const ReadResult = struct {
done: bool, done: bool,
value: Chunk, value: Chunk,
@@ -127,8 +110,6 @@ pub const JsApi = struct {
pub const name = "ReadableStreamDefaultReader"; pub const name = "ReadableStreamDefaultReader";
pub const prototype_chain = bridge.prototypeChain(); pub const prototype_chain = bridge.prototypeChain();
pub var class_id: bridge.ClassId = undefined; 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, .{}); pub const read = bridge.function(ReadableStreamDefaultReader.read, .{});

View File

@@ -85,14 +85,6 @@ pub fn initWithZigTransform(zig_transform: ZigTransformFn, page: *Page) !*Transf
return self; 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 { pub fn transformWrite(self: *TransformStream, chunk: js.Value, page: *Page) !void {
if (self._controller._zig_transform_fn) |zig_fn| { if (self._controller._zig_transform_fn) |zig_fn| {
// Zig-level transform (used by TextEncoderStream etc.) // Zig-level transform (used by TextEncoderStream etc.)
@@ -138,8 +130,6 @@ pub const JsApi = struct {
pub const name = "TransformStream"; pub const name = "TransformStream";
pub const prototype_chain = bridge.prototypeChain(); pub const prototype_chain = bridge.prototypeChain();
pub var class_id: bridge.ClassId = undefined; 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, .{}); 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 { pub fn enqueue(self: *TransformStreamDefaultController, chunk: ReadableStreamDefaultController.Chunk) !void {
try self._stream._readable._controller.enqueue(chunk); try self._stream._readable._controller.enqueue(chunk);
} }
@@ -207,8 +189,6 @@ pub const TransformStreamDefaultController = struct {
pub const name = "TransformStreamDefaultController"; pub const name = "TransformStreamDefaultController";
pub const prototype_chain = bridge.prototypeChain(); pub const prototype_chain = bridge.prototypeChain();
pub var class_id: bridge.ClassId = undefined; 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, .{}); pub const enqueue = bridge.function(TransformStreamDefaultController.enqueueValue, .{});