1
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2024-12-24 08:09:08 -05:00

fix(ext/web): Prevent TextDecoderStream resource leak on stream cancellation (#21074)

This PR uses the new `cancel` method of `TransformStream` to properly
clean up the internal `TextDecoder` used in `TextDecoderStream` if the
stream is cancelled.

Fixes #13142

Co-authored-by: Bartek Iwańczuk <biwanczuk@gmail.com>
This commit is contained in:
Florian Schwalm 2023-11-12 20:47:03 +01:00 committed by GitHub
parent 9f4a45561f
commit 3a7abe6906
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 29 additions and 0 deletions

View file

@ -319,3 +319,20 @@ Deno.test(function binaryEncode() {
assertEquals(Array.from(bytes), decodeBinary(binaryString)); assertEquals(Array.from(bytes), decodeBinary(binaryString));
} }
}); });
Deno.test(
{ permissions: { read: true } },
async function textDecoderStreamCleansUpOnCancel() {
const filename = "cli/tests/testdata/assets/hello.txt";
const file = await Deno.open(filename);
const readable = file.readable.pipeThrough(new TextDecoderStream());
const chunks = [];
for await (const chunk of readable) {
chunks.push(chunk);
// breaking out of the loop prevents normal shutdown at end of async iterator values and triggers the cancel method of the stream instead
break;
}
assertEquals(chunks.length, 1);
assertEquals(chunks[0].length, 12);
},
);

View file

@ -6680,6 +6680,10 @@ webidl.converters.Transformer = webidl
key: "flush", key: "flush",
converter: webidl.converters.Function, converter: webidl.converters.Function,
}, },
{
key: "cancel",
converter: webidl.converters.Function,
},
{ {
key: "readableType", key: "readableType",
converter: webidl.converters.any, converter: webidl.converters.any,

View file

@ -301,6 +301,14 @@ class TextDecoderStream {
return PromiseReject(err); return PromiseReject(err);
} }
}, },
cancel: (_reason) => {
try {
const _ = this.#decoder.decode();
return PromiseResolve();
} catch (err) {
return PromiseReject(err);
}
},
}); });
this[webidl.brand] = webidl.brand; this[webidl.brand] = webidl.brand;
} }