@@ -25,7 +25,7 @@ const {
2525 ERR_INVALID_THIS ,
2626 ERR_NO_ICU ,
2727} = require ( 'internal/errors' ) . codes ;
28- const kMethod = Symbol ( 'method' ) ;
28+ const kSingleByte = Symbol ( 'method' ) ;
2929const kHandle = Symbol ( 'handle' ) ;
3030const kFlags = Symbol ( 'flags' ) ;
3131const kEncoding = Symbol ( 'encoding' ) ;
@@ -447,137 +447,99 @@ function parseInput(input) {
447447 }
448448}
449449
450- const TextDecoder =
451- internalBinding ( 'config' ) . hasIntl ?
452- makeTextDecoderICU ( ) :
453- makeTextDecoderJS ( ) ;
450+ const { hasIntl } = internalBinding ( 'config' ) ;
454451
455- function makeTextDecoderICU ( ) {
456- const {
452+ let _decode , getConverter
453+ if ( hasIntl ) {
454+ ; ( {
457455 decode : _decode ,
458456 getConverter,
459- } = internalBinding ( 'icu' ) ;
457+ } = internalBinding ( 'icu' ) ) ;
458+ }
460459
461- class TextDecoder {
462- constructor ( encoding = 'utf-8' , options = kEmptyObject ) {
463- encoding = `${ encoding } ` ;
464- validateObject ( options , 'options' , kValidateObjectAllowObjectsAndNull ) ;
460+ const kBOMSeen = Symbol ( 'BOM seen' ) ;
465461
466- const enc = getEncodingFromLabel ( encoding ) ;
467- if ( enc === undefined )
468- throw new ERR_ENCODING_NOT_SUPPORTED ( encoding ) ;
462+ let StringDecoder ;
463+ function lazyStringDecoder ( ) {
464+ if ( StringDecoder === undefined )
465+ ( { StringDecoder } = require ( 'string_decoder' ) ) ;
466+ return StringDecoder ;
467+ }
469468
470- let flags = 0 ;
471- if ( options !== null ) {
472- flags |= options . fatal ? CONVERTER_FLAGS_FATAL : 0 ;
473- flags |= options . ignoreBOM ? CONVERTER_FLAGS_IGNORE_BOM : 0 ;
474- }
469+ class TextDecoder {
470+ constructor ( encoding = 'utf-8' , options = kEmptyObject ) {
471+ encoding = `${ encoding } ` ;
472+ validateObject ( options , 'options' , kValidateObjectAllowObjectsAndNull ) ;
475473
476- this [ kDecoder ] = true ;
477- this [ kFlags ] = flags ;
478- this [ kEncoding ] = enc ;
479- this [ kIgnoreBOM ] = Boolean ( options ?. ignoreBOM ) ;
480- this [ kFatal ] = Boolean ( options ?. fatal ) ;
481- // Only support fast path for UTF-8.
482- this [ kUTF8FastPath ] = enc === 'utf-8' ;
483- this [ kHandle ] = undefined ;
484- this [ kMethod ] = undefined ;
485-
486- if ( isSinglebyteEncoding ( this . encoding ) ) {
487- this [ kMethod ] = createSinglebyteDecoder ( this . encoding , this [ kFatal ] ) ;
488- } else if ( ! this [ kUTF8FastPath ] ) {
489- this . #prepareConverter( ) ;
490- }
474+ const enc = getEncodingFromLabel ( encoding ) ;
475+ if ( enc === undefined )
476+ throw new ERR_ENCODING_NOT_SUPPORTED ( encoding ) ;
477+
478+ let flags = 0 ;
479+ if ( options !== null ) {
480+ flags |= options . fatal ? CONVERTER_FLAGS_FATAL : 0 ;
481+ flags |= options . ignoreBOM ? CONVERTER_FLAGS_IGNORE_BOM : 0 ;
491482 }
492483
493- #prepareConverter( ) {
494- if ( this [ kHandle ] !== undefined ) return ;
484+ this [ kDecoder ] = true ;
485+ this [ kFlags ] = flags ;
486+ this [ kEncoding ] = enc ;
487+ this [ kIgnoreBOM ] = Boolean ( options ?. ignoreBOM ) ;
488+ this [ kFatal ] = Boolean ( options ?. fatal ) ;
489+ // Only support fast path for UTF-8.
490+ this [ kUTF8FastPath ] = enc === 'utf-8' ;
491+ this [ kHandle ] = undefined ;
492+ this [ kSingleByte ] = undefined ; // Does not care about streaming or BOM
493+
494+ if ( isSinglebyteEncoding ( enc ) ) {
495+ this [ kSingleByte ] = createSinglebyteDecoder ( enc , this [ kFatal ] ) ;
496+ } else if ( ! this [ kUTF8FastPath ] ) {
497+ this . #prepareConverter( ) ;
498+ }
499+ }
500+
501+ #prepareConverter( ) {
502+ if ( this [ kHandle ] !== undefined ) return ;
503+ if ( hasIntl ) {
495504 let icuEncoding = this [ kEncoding ] ;
496505 if ( icuEncoding === 'gbk' ) icuEncoding = 'gb18030' ; // 10.1.1. GBK's decoder is gb18030's decoder
497506 const handle = getConverter ( icuEncoding , this [ kFlags ] ) ;
498507 if ( handle === undefined )
499508 throw new ERR_ENCODING_NOT_SUPPORTED ( this [ kEncoding ] ) ;
500509 this [ kHandle ] = handle ;
501- }
502-
503- decode ( input = empty , options = kEmptyObject ) {
504- validateDecoder ( this ) ;
505- validateObject ( options , 'options' , kValidateObjectAllowObjectsAndNull ) ;
506-
507- if ( this [ kMethod ] ) return this [ kMethod ] ( input ) ;
508-
509- this [ kUTF8FastPath ] &&= ! ( options ?. stream ) ;
510-
511- if ( this [ kUTF8FastPath ] ) {
512- return decodeUTF8 ( input , this [ kIgnoreBOM ] , this [ kFatal ] ) ;
510+ } else {
511+ if ( enc !== 'utf-8' && enc !== 'utf-16le' ) {
512+ throw new ERR_ENCODING_NOT_SUPPORTED ( `${ encoding } ` ) ;
513513 }
514514
515- this . #prepareConverter( ) ;
516-
517- let flags = 0 ;
518- if ( options !== null )
519- flags |= options . stream ? 0 : CONVERTER_FLAGS_FLUSH ;
520-
521- return _decode ( this [ kHandle ] , input , flags , this . encoding ) ;
515+ if ( this [ kFatal ] ) throw new ERR_NO_ICU ( '"fatal" option' ) ;
516+ // StringDecoder will normalize WHATWG encoding to Node.js encoding.
517+ this [ kHandle ] = new ( lazyStringDecoder ( ) ) ( enc ) ;
518+ this [ kBOMSeen ] = false ;
522519 }
523520 }
524521
525- return TextDecoder ;
526- }
527-
528- function makeTextDecoderJS ( ) {
529- let StringDecoder ;
530- function lazyStringDecoder ( ) {
531- if ( StringDecoder === undefined )
532- ( { StringDecoder } = require ( 'string_decoder' ) ) ;
533- return StringDecoder ;
534- }
535-
536- const kBOMSeen = Symbol ( 'BOM seen' ) ;
537-
538- function hasConverter ( encoding ) {
539- return encoding === 'utf-8' || encoding === 'utf-16le' ;
540- }
522+ decode ( input = empty , options = kEmptyObject ) {
523+ validateDecoder ( this ) ;
524+ validateObject ( options , 'options' , kValidateObjectAllowObjectsAndNull ) ;
541525
542- class TextDecoder {
543- constructor ( encoding = 'utf-8' , options = kEmptyObject ) {
544- encoding = `${ encoding } ` ;
545- validateObject ( options , 'options' , kValidateObjectAllowObjectsAndNull ) ;
526+ if ( this [ kSingleByte ] ) return this [ kSingleByte ] ( input ) ;
546527
547- const enc = getEncodingFromLabel ( encoding ) ;
548- if ( enc === undefined )
549- throw new ERR_ENCODING_NOT_SUPPORTED ( encoding ) ;
528+ this [ kUTF8FastPath ] &&= ! ( options ?. stream ) ;
550529
551- let flags = 0 ;
552- if ( options !== null ) {
553- flags |= options . fatal ? CONVERTER_FLAGS_FATAL : 0 ;
554- flags |= options . ignoreBOM ? CONVERTER_FLAGS_IGNORE_BOM : 0 ;
555- }
556-
557- this [ kDecoder ] = true ;
558- this [ kFlags ] = flags ;
559- this [ kEncoding ] = enc ;
560- this [ kIgnoreBOM ] = Boolean ( options ?. ignoreBOM ) ;
561- this [ kFatal ] = Boolean ( options ?. fatal ) ;
562- this [ kBOMSeen ] = false ;
563- this [ kMethod ] = undefined ;
564-
565- if ( isSinglebyteEncoding ( enc ) ) {
566- this [ kMethod ] = createSinglebyteDecoder ( enc , this [ kFatal ] ) ;
567- } else {
568- if ( ! hasConverter ( enc ) ) throw new ERR_ENCODING_NOT_SUPPORTED ( encoding ) ;
569- if ( this [ kFatal ] ) throw new ERR_NO_ICU ( '"fatal" option' ) ;
570- // StringDecoder will normalize WHATWG encoding to Node.js encoding.
571- this [ kHandle ] = new ( lazyStringDecoder ( ) ) ( enc ) ;
572- }
530+ if ( this [ kUTF8FastPath ] ) {
531+ return decodeUTF8 ( input , this [ kIgnoreBOM ] , this [ kFatal ] ) ;
573532 }
574533
575- decode ( input = empty , options = kEmptyObject ) {
576- validateDecoder ( this ) ;
577- validateObject ( options , 'options' , kValidateObjectAllowObjectsAndNull ) ;
534+ this . #prepareConverter( ) ;
578535
579- if ( this [ kMethod ] ) return this [ kMethod ] ( input ) ;
536+ if ( hasIntl ) {
537+ let flags = 0 ;
538+ if ( options !== null )
539+ flags |= options . stream ? 0 : CONVERTER_FLAGS_FLUSH ;
580540
541+ return _decode ( this [ kHandle ] , input , flags , this . encoding ) ;
542+ } else {
581543 if ( this [ kFlags ] & CONVERTER_FLAGS_FLUSH ) {
582544 this [ kBOMSeen ] = false ;
583545 }
@@ -605,8 +567,6 @@ function makeTextDecoderJS() {
605567 return result ;
606568 }
607569 }
608-
609- return TextDecoder ;
610570}
611571
612572// Mix in some shared properties.
0 commit comments