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:
parent
9f4a45561f
commit
3a7abe6906
3 changed files with 29 additions and 0 deletions
|
@ -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);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue