text-decoder-stream.ts 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354
  1. // Copyright 2016 Google Inc.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. // Polyfill for TextEncoderStream and TextDecoderStream
  15. // Modified by Sukka (https://skk.moe) to increase compatibility and performance with Bun.
  16. export class PolyfillTextDecoderStream extends TransformStream<Uint8Array, string> {
  17. readonly fatal: boolean;
  18. readonly ignoreBOM: boolean;
  19. constructor(
  20. public readonly encoding: BufferEncoding = 'utf-8',
  21. {
  22. fatal = false,
  23. ignoreBOM = false
  24. }: ConstructorParameters<typeof TextDecoder>[1] = {}
  25. ) {
  26. const decoder = new TextDecoder(encoding, { fatal, ignoreBOM });
  27. const nonLastChunkDecoderOpt = { stream: true };
  28. super({
  29. transform(chunk: Uint8Array, controller: TransformStreamDefaultController<string>) {
  30. const decoded = decoder.decode(chunk, nonLastChunkDecoderOpt);
  31. controller.enqueue(decoded);
  32. },
  33. flush(controller: TransformStreamDefaultController<string>) {
  34. // If {fatal: false} is in options (the default), then the final call to
  35. // decode() can produce extra output (usually the unicode replacement
  36. // character 0xFFFD). When fatal is true, this call is just used for its
  37. // side-effect of throwing a TypeError exception if the input is
  38. // incomplete.
  39. const output = decoder.decode();
  40. if (output.length > 0) {
  41. controller.enqueue(output);
  42. }
  43. }
  44. });
  45. this.fatal = fatal;
  46. this.ignoreBOM = ignoreBOM;
  47. }
  48. }