Repository: nodejs/node
File: lib/internal/encoding.js (JavaScript)

Code before:

  class TextDecoder {
    constructor(encoding = 'utf-8', options = kEmptyObject) {
      encoding = `${encoding}`;
      validateObject(options, 'options', kValidateObjectAllowObjectsAndNull);

      const enc = getEncodingFromLabel(encoding);
      if (enc === undefined)
        throw new ERR_ENCODING_NOT_SUPPORTED(encoding);

      let flags = 0;
      if (options !== null) {
        flags |= options.fatal ? CONVERTER_FLAGS_FATAL : 0;
        flags |= options.ignoreBOM ? CONVERTER_FLAGS_IGNORE_BOM : 0;
      }

      this[kDecoder] = true;
      this[kFlags] = flags;
      this[kEncoding] = enc;
      this[kIgnoreBOM] = Boolean(options?.ignoreBOM);
      this[kFatal] = Boolean(options?.fatal);
      // Only support fast path for UTF-8.
      this[kUTF8FastPath] = enc === 'utf-8';
      this[kHandle] = undefined;

      if (!this[kUTF8FastPath]) {
        this.#prepareConverter();
      }
    }

    #prepareConverter() {
      if (this[kHandle] !== undefined) return;
      const handle = getConverter(this[kEncoding], this[kFlags]);
      if (handle === undefined)
        throw new ERR_ENCODING_NOT_SUPPORTED(this[kEncoding]);
      this[kHandle] = handle;
    }

    decode(input = empty, options = kEmptyObject) {
      validateDecoder(this);

      this[kUTF8FastPath] &&= !(options?.stream);

      if (this[kUTF8FastPath]) {
        return decodeUTF8(input, this[kIgnoreBOM], this[kFatal]);
      }

      this.#prepareConverter();

      validateObject(options, 'options', kValidateObjectAllowObjectsAndNull);


Review comment (bug):
This line specifically uses the wrong assumption that `Latin1` and `windows-1252` are the same encoding

They aren't

Code after:
    getConverter,
  } = internalBinding('icu');

  class TextDecoder {
    constructor(encoding = 'utf-8', options = kEmptyObject) {
      encoding = `${encoding}`;
      validateObject(options, 'options', kValidateObjectAllowObjectsAndNull);

      const enc = getEncodingFromLabel(encoding);
      if (enc === undefined)
        throw new ERR_ENCODING_NOT_SUPPORTED(encoding);

      let flags = 0;
      if (options !== null) {
        flags |= options.fatal ? CONVERTER_FLAGS_FATAL : 0;
        flags |= options.ignoreBOM ? CONVERTER_FLAGS_IGNORE_BOM : 0;
      }

      this[kDecoder] = true;
      this[kFlags] = flags;
      this[kEncoding] = enc;
      this[kIgnoreBOM] = Boolean(options?.ignoreBOM);
      this[kFatal] = Boolean(options?.fatal);
      // Only support fast path for UTF-8.
      this[kUTF8FastPath] = enc === 'utf-8';
      this[kLatin1FastPath] = enc === 'windows-1252';
      this[kHandle] = undefined;

      if (!this[kUTF8FastPath] && !this[kLatin1FastPath]) {
        this.#prepareConverter();
      }
    }

    #prepareConverter() {
      if (this[kHandle] !== undefined) return;
      const handle = getConverter(this[kEncoding], this[kFlags]);
      if (handle === undefined)
        throw new ERR_ENCODING_NOT_SUPPORTED(this[kEncoding]);
      this[kHandle] = handle;
    }

    decode(input = empty, options = kEmptyObject) {
      validateDecoder(this);

      this[kUTF8FastPath] &&= !(options?.stream);
      this[kLatin1FastPath] &&= !(options?.stream);

      if (this[kUTF8FastPath]) {
        return decodeUTF8(input, this[kIgnoreBOM], this[kFatal]);
      }