Skip to content

Commit 4fa0db3

Browse files
committed
fix: Do not close JS stream reader if closed
1 parent 3207821 commit 4fa0db3

File tree

2 files changed

+34
-2
lines changed

2 files changed

+34
-2
lines changed

src/Uno.UI/WasmScripts/Uno.UI.js

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3540,6 +3540,7 @@ var Uno;
35403540
}
35413541
static async readAsync(streamId, targetArrayPointer, offset, count, position) {
35423542
var streamReader;
3543+
var readerNeedsRelease = true;
35433544
try {
35443545
const instance = NativeFileReadStream._streamMap.get(streamId);
35453546
var totalRead = 0;
@@ -3553,10 +3554,23 @@ var Uno;
35533554
totalRead += chunk.value.length;
35543555
chunk = await streamReader.read();
35553556
}
3557+
// If this is the end of stream, it closed itself
3558+
readerNeedsRelease = !chunk.done;
35563559
return totalRead.toString();
35573560
}
35583561
finally {
3559-
if (streamReader) {
3562+
// Reader must be released only if the underlying stream has not already closed it.
3563+
// Otherwise the release operation sets a new Promise.reject as reader.closed which
3564+
// raises silent but observable exception in Chromium-based browsers.
3565+
if (streamReader && readerNeedsRelease) {
3566+
// Silently handling TypeError exceptions on closed event as the releaseLock()
3567+
// raises one in case of a successful close.
3568+
streamReader.closed.catch(reason => {
3569+
if (!(reason instanceof TypeError)) {
3570+
throw reason;
3571+
}
3572+
});
3573+
streamReader.cancel();
35603574
streamReader.releaseLock();
35613575
}
35623576
}

src/Uno.UI/ts/Windows/Storage/Streams/NativeFileReadStream.ts

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,14 @@
2020

2121
public static async readAsync(streamId: string, targetArrayPointer: number, offset: number, count: number, position: number): Promise<string> {
2222
var streamReader: ReadableStreamDefaultReader;
23+
var readerNeedsRelease = true;
2324
try {
2425
const instance = NativeFileReadStream._streamMap.get(streamId);
2526

2627
var totalRead = 0;
2728
var stream = await instance._file.slice(position, position + count).stream();
2829
streamReader = stream.getReader();
30+
2931
var chunk = await streamReader.read();
3032
while (!chunk.done && chunk.value) {
3133
for (var i = 0; i < chunk.value.length; i++) {
@@ -36,10 +38,26 @@
3638
chunk = await streamReader.read();
3739
}
3840

41+
// If this is the end of stream, it closed itself
42+
readerNeedsRelease = !chunk.done;
43+
3944
return totalRead.toString();
4045
}
4146
finally {
42-
if (streamReader) {
47+
// Reader must be released only if the underlying stream has not already closed it.
48+
// Otherwise the release operation sets a new Promise.reject as reader.closed which
49+
// raises silent but observable exception in Chromium-based browsers.
50+
if (streamReader && readerNeedsRelease) {
51+
52+
// Silently handling TypeError exceptions on closed event as the releaseLock()
53+
// raises one in case of a successful close.
54+
streamReader.closed.catch(reason => {
55+
if (!(reason instanceof TypeError)) {
56+
throw reason;
57+
}
58+
});
59+
60+
streamReader.cancel();
4361
streamReader.releaseLock();
4462
}
4563
}

0 commit comments

Comments
 (0)