mirror of
https://github.com/lightpanda-io/browser.git
synced 2025-10-29 07:03:29 +00:00
htmlRunner for ReadableStream tests, fix ReadableStream enqueue
This commit is contained in:
@@ -173,166 +173,5 @@ pub fn _getReader(self: *ReadableStream, _options: ?GetReaderOptions) !ReadableS
|
|||||||
|
|
||||||
const testing = @import("../../testing.zig");
|
const testing = @import("../../testing.zig");
|
||||||
test "streams: ReadableStream" {
|
test "streams: ReadableStream" {
|
||||||
var runner = try testing.jsRunner(testing.tracking_allocator, .{ .url = "https://lightpanda.io" });
|
try testing.htmlRunner("streams/readable_stream.html");
|
||||||
defer runner.deinit();
|
|
||||||
|
|
||||||
try runner.testCases(&.{
|
|
||||||
.{ "var readResult;", "undefined" },
|
|
||||||
.{
|
|
||||||
\\ const stream = new ReadableStream({
|
|
||||||
\\ start(controller) {
|
|
||||||
\\ controller.enqueue("hello");
|
|
||||||
\\ controller.enqueue("world");
|
|
||||||
\\ controller.close();
|
|
||||||
\\ }
|
|
||||||
\\ });
|
|
||||||
,
|
|
||||||
undefined,
|
|
||||||
},
|
|
||||||
.{
|
|
||||||
\\ const reader = stream.getReader();
|
|
||||||
\\ (async function () { readResult = await reader.read() }());
|
|
||||||
\\ false;
|
|
||||||
,
|
|
||||||
"false",
|
|
||||||
},
|
|
||||||
.{ "reader", "[object ReadableStreamDefaultReader]" },
|
|
||||||
.{ "readResult.value", "hello" },
|
|
||||||
.{ "readResult.done", "false" },
|
|
||||||
}, .{});
|
|
||||||
}
|
|
||||||
|
|
||||||
test "streams: ReadableStream cancel and close" {
|
|
||||||
var runner = try testing.jsRunner(testing.tracking_allocator, .{ .url = "https://lightpanda.io" });
|
|
||||||
defer runner.deinit();
|
|
||||||
try runner.testCases(&.{
|
|
||||||
.{ "var readResult; var cancelResult; var closeResult;", "undefined" },
|
|
||||||
|
|
||||||
// Test 1: Stream with controller.close()
|
|
||||||
.{
|
|
||||||
\\ const stream1 = new ReadableStream({
|
|
||||||
\\ start(controller) {
|
|
||||||
\\ controller.enqueue("first");
|
|
||||||
\\ controller.enqueue("second");
|
|
||||||
\\ controller.close();
|
|
||||||
\\ }
|
|
||||||
\\ });
|
|
||||||
,
|
|
||||||
undefined,
|
|
||||||
},
|
|
||||||
.{ "const reader1 = stream1.getReader();", undefined },
|
|
||||||
.{
|
|
||||||
\\ (async function () {
|
|
||||||
\\ readResult = await reader1.read();
|
|
||||||
\\ }());
|
|
||||||
\\ false;
|
|
||||||
,
|
|
||||||
"false",
|
|
||||||
},
|
|
||||||
.{ "readResult.value", "first" },
|
|
||||||
.{ "readResult.done", "false" },
|
|
||||||
|
|
||||||
// Read second chunk
|
|
||||||
.{
|
|
||||||
\\ (async function () {
|
|
||||||
\\ readResult = await reader1.read();
|
|
||||||
\\ }());
|
|
||||||
\\ false;
|
|
||||||
,
|
|
||||||
"false",
|
|
||||||
},
|
|
||||||
.{ "readResult.value", "second" },
|
|
||||||
.{ "readResult.done", "false" },
|
|
||||||
|
|
||||||
// Read after close - should get done: true
|
|
||||||
.{
|
|
||||||
\\ (async function () {
|
|
||||||
\\ readResult = await reader1.read();
|
|
||||||
\\ }());
|
|
||||||
\\ false;
|
|
||||||
,
|
|
||||||
"false",
|
|
||||||
},
|
|
||||||
.{ "readResult.value", "undefined" },
|
|
||||||
.{ "readResult.done", "true" },
|
|
||||||
|
|
||||||
// Test 2: Stream with reader.cancel()
|
|
||||||
.{
|
|
||||||
\\ const stream2 = new ReadableStream({
|
|
||||||
\\ start(controller) {
|
|
||||||
\\ controller.enqueue("data1");
|
|
||||||
\\ controller.enqueue("data2");
|
|
||||||
\\ controller.enqueue("data3");
|
|
||||||
\\ },
|
|
||||||
\\ cancel(reason) {
|
|
||||||
\\ closeResult = `Stream cancelled: ${reason}`;
|
|
||||||
\\ }
|
|
||||||
\\ });
|
|
||||||
,
|
|
||||||
undefined,
|
|
||||||
},
|
|
||||||
.{ "const reader2 = stream2.getReader();", undefined },
|
|
||||||
|
|
||||||
// Read one chunk before canceling
|
|
||||||
.{
|
|
||||||
\\ (async function () {
|
|
||||||
\\ readResult = await reader2.read();
|
|
||||||
\\ }());
|
|
||||||
\\ false;
|
|
||||||
,
|
|
||||||
"false",
|
|
||||||
},
|
|
||||||
.{ "readResult.value", "data1" },
|
|
||||||
.{ "readResult.done", "false" },
|
|
||||||
|
|
||||||
// Cancel the stream
|
|
||||||
.{
|
|
||||||
\\ (async function () {
|
|
||||||
\\ cancelResult = await reader2.cancel("user requested");
|
|
||||||
\\ }());
|
|
||||||
\\ false;
|
|
||||||
,
|
|
||||||
"false",
|
|
||||||
},
|
|
||||||
.{ "cancelResult", "undefined" },
|
|
||||||
.{ "closeResult", "Stream cancelled: user requested" },
|
|
||||||
|
|
||||||
// Try to read after cancel - should throw or return done
|
|
||||||
.{
|
|
||||||
\\ try {
|
|
||||||
\\ (async function () {
|
|
||||||
\\ readResult = await reader2.read();
|
|
||||||
\\ }());
|
|
||||||
\\ } catch(e) {
|
|
||||||
\\ readResult = { error: e.name };
|
|
||||||
\\ }
|
|
||||||
\\ false;
|
|
||||||
,
|
|
||||||
"false",
|
|
||||||
},
|
|
||||||
|
|
||||||
// Test 3: Cancel without reason
|
|
||||||
.{
|
|
||||||
\\ const stream3 = new ReadableStream({
|
|
||||||
\\ start(controller) {
|
|
||||||
\\ controller.enqueue("test");
|
|
||||||
\\ },
|
|
||||||
\\ cancel(reason) {
|
|
||||||
\\ closeResult = reason === undefined ? "no reason" : reason;
|
|
||||||
\\ }
|
|
||||||
\\ });
|
|
||||||
,
|
|
||||||
undefined,
|
|
||||||
},
|
|
||||||
.{ "const reader3 = stream3.getReader();", undefined },
|
|
||||||
.{
|
|
||||||
\\ (async function () {
|
|
||||||
\\ await reader3.cancel();
|
|
||||||
\\ }());
|
|
||||||
\\ false;
|
|
||||||
,
|
|
||||||
"false",
|
|
||||||
},
|
|
||||||
.{ "closeResult", "no reason" },
|
|
||||||
}, .{});
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -59,13 +59,15 @@ pub fn _enqueue(self: *ReadableStreamDefaultController, chunk: []const u8, page:
|
|||||||
return error.TypeError;
|
return error.TypeError;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const duped_chunk = try page.arena.dupe(u8, chunk);
|
||||||
|
|
||||||
if (self.stream.reader_resolver) |*rr| {
|
if (self.stream.reader_resolver) |*rr| {
|
||||||
defer rr.deinit();
|
defer rr.deinit();
|
||||||
try rr.resolve(ReadableStreamReadResult{ .value = .{ .data = chunk }, .done = false });
|
try rr.resolve(ReadableStreamReadResult{ .value = .{ .data = duped_chunk }, .done = false });
|
||||||
self.stream.reader_resolver = null;
|
self.stream.reader_resolver = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
try self.stream.queue.append(page.arena, chunk);
|
try self.stream.queue.append(page.arena, duped_chunk);
|
||||||
try self.stream.pullIf();
|
try self.stream.pullIf();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -48,6 +48,7 @@ pub fn _read(self: *const ReadableStreamDefaultReader, page: *Page) !Env.Promise
|
|||||||
if (stream.queue.items.len > 0) {
|
if (stream.queue.items.len > 0) {
|
||||||
const data = self.stream.queue.orderedRemove(0);
|
const data = self.stream.queue.orderedRemove(0);
|
||||||
const resolver = page.main_context.createPromiseResolver();
|
const resolver = page.main_context.createPromiseResolver();
|
||||||
|
|
||||||
try resolver.resolve(ReadableStreamReadResult{ .value = .{ .data = data }, .done = false });
|
try resolver.resolve(ReadableStreamReadResult{ .value = .{ .data = data }, .done = false });
|
||||||
try self.stream.pullIf();
|
try self.stream.pullIf();
|
||||||
return resolver.promise();
|
return resolver.promise();
|
||||||
|
|||||||
117
src/tests/streams/readable_stream.html
Normal file
117
src/tests/streams/readable_stream.html
Normal file
@@ -0,0 +1,117 @@
|
|||||||
|
<script src="../testing.js"></script>
|
||||||
|
|
||||||
|
<script id=readable_stream>
|
||||||
|
const stream = new ReadableStream({
|
||||||
|
start(controller) {
|
||||||
|
controller.enqueue("hello");
|
||||||
|
controller.enqueue("world");
|
||||||
|
controller.close();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const reader = stream.getReader();
|
||||||
|
|
||||||
|
testing.async(reader.read(), (data) => {
|
||||||
|
testing.expectEqual("hello", data.value);
|
||||||
|
testing.expectEqual(false, data.done);
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script id=readable_stream_close>
|
||||||
|
var closeResult;
|
||||||
|
|
||||||
|
const stream1 = new ReadableStream({
|
||||||
|
start(controller) {
|
||||||
|
controller.enqueue("first");
|
||||||
|
controller.enqueue("second");
|
||||||
|
controller.close();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const reader1 = stream1.getReader();
|
||||||
|
|
||||||
|
testing.async(reader1.read(), (data) => {
|
||||||
|
testing.expectEqual("first", data.value);
|
||||||
|
testing.expectEqual(false, data.done);
|
||||||
|
});
|
||||||
|
|
||||||
|
testing.async(reader1.read(), (data) => {
|
||||||
|
testing.expectEqual("second", data.value);
|
||||||
|
testing.expectEqual(false, data.done);
|
||||||
|
});
|
||||||
|
|
||||||
|
testing.async(reader1.read(), (data) => {
|
||||||
|
testing.expectEqual(undefined, data.value);
|
||||||
|
testing.expectEqual(true, data.done);
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script id=readable_stream_cancel>
|
||||||
|
var readResult;
|
||||||
|
var cancelResult;
|
||||||
|
var closeResult;
|
||||||
|
|
||||||
|
const stream2 = new ReadableStream({
|
||||||
|
start(controller) {
|
||||||
|
controller.enqueue("data1");
|
||||||
|
controller.enqueue("data2");
|
||||||
|
controller.enqueue("data3");
|
||||||
|
},
|
||||||
|
cancel(reason) {
|
||||||
|
closeResult = `Stream cancelled: ${reason}`;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const reader2 = stream2.getReader();
|
||||||
|
|
||||||
|
testing.async(reader2.read(), (data) => {
|
||||||
|
testing.expectEqual("data1", data.value);
|
||||||
|
testing.expectEqual(false, data.done);
|
||||||
|
});
|
||||||
|
|
||||||
|
testing.async(reader2.cancel("user requested"), (result) => {
|
||||||
|
testing.expectEqual(undefined, result);
|
||||||
|
testing.expectEqual("Stream cancelled: user requested", closeResult);
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script id=readable_stream_cancel_no_reason>
|
||||||
|
var closeResult2;
|
||||||
|
|
||||||
|
const stream3 = new ReadableStream({
|
||||||
|
start(controller) {
|
||||||
|
controller.enqueue("test");
|
||||||
|
},
|
||||||
|
cancel(reason) {
|
||||||
|
closeResult2 = reason === undefined ? "no reason" : reason;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const reader3 = stream3.getReader();
|
||||||
|
|
||||||
|
testing.async(reader3.cancel(), (result) => {
|
||||||
|
testing.expectEqual(undefined, result);
|
||||||
|
testing.expectEqual("no reason", closeResult2);
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script id=readable_stream_read_after_cancel>
|
||||||
|
var readAfterCancelResult;
|
||||||
|
|
||||||
|
const stream4 = new ReadableStream({
|
||||||
|
start(controller) {
|
||||||
|
controller.enqueue("before_cancel");
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const reader4 = stream4.getReader();
|
||||||
|
|
||||||
|
testing.async(reader4.cancel("test cancel"), (cancelResult) => {
|
||||||
|
testing.expectEqual(undefined, cancelResult);
|
||||||
|
});
|
||||||
|
|
||||||
|
testing.async(reader4.read(), (data) => {
|
||||||
|
testing.expectEqual(undefined, data.value);
|
||||||
|
testing.expectEqual(true, data.done);
|
||||||
|
});
|
||||||
|
</script>
|
||||||
Reference in New Issue
Block a user