22
33const {
44 ObjectDefineProperties,
5+ String,
6+ StringPrototypeCharCodeAt,
57 Symbol,
8+ Uint8Array,
69} = primordials ;
710
811const {
@@ -31,6 +34,7 @@ const {
3134const kHandle = Symbol ( 'kHandle' ) ;
3235const kTransform = Symbol ( 'kTransform' ) ;
3336const kType = Symbol ( 'kType' ) ;
37+ const kPendingHighSurrogate = Symbol ( 'kPendingHighSurrogate' ) ;
3438
3539/**
3640 * @typedef {import('./readablestream').ReadableStream } ReadableStream
@@ -49,19 +53,46 @@ function isTextDecoderStream(value) {
4953
5054class TextEncoderStream {
5155 constructor ( ) {
56+ this [ kPendingHighSurrogate ] = null ;
5257 this [ kType ] = 'TextEncoderStream' ;
5358 this [ kHandle ] = new TextEncoder ( ) ;
5459 this [ kTransform ] = new TransformStream ( {
5560 transform : ( chunk , controller ) => {
56- const value = this [ kHandle ] . encode ( chunk ) ;
57- if ( value )
61+ // https://encoding.spec.whatwg.org/#encode-and-enqueue-a-chunk
62+ chunk = String ( chunk ) ;
63+ let finalChunk = '' ;
64+ for ( let i = 0 ; i < chunk . length ; i ++ ) {
65+ const item = chunk [ i ] ;
66+ const codeUnit = StringPrototypeCharCodeAt ( item , 0 ) ;
67+ if ( this [ kPendingHighSurrogate ] !== null ) {
68+ const highSurrogate = this [ kPendingHighSurrogate ] ;
69+ this [ kPendingHighSurrogate ] = null ;
70+ if ( 0xDC00 <= codeUnit && codeUnit <= 0xDFFF ) {
71+ finalChunk += highSurrogate + item ;
72+ continue ;
73+ }
74+ finalChunk += '\uFFFD' ;
75+ }
76+ if ( 0xD800 <= codeUnit && codeUnit <= 0xDBFF ) {
77+ this [ kPendingHighSurrogate ] = item ;
78+ continue ;
79+ }
80+ if ( 0xDC00 <= codeUnit && codeUnit <= 0xDFFF ) {
81+ finalChunk += '\uFFFD' ;
82+ continue ;
83+ }
84+ finalChunk += item ;
85+ }
86+ if ( finalChunk ) {
87+ const value = this [ kHandle ] . encode ( finalChunk ) ;
5888 controller . enqueue ( value ) ;
89+ }
5990 } ,
6091 flush : ( controller ) => {
61- const value = this [ kHandle ] . encode ( ) ;
62- if ( value . byteLength > 0 )
63- controller . enqueue ( value ) ;
64- controller . terminate ( ) ;
92+ // https://encoding.spec.whatwg.org/# encode-and-flush
93+ if ( this [ kPendingHighSurrogate ] !== null ) {
94+ controller . enqueue ( new Uint8Array ( [ 0xEF , 0xBF , 0xBD ] ) ) ;
95+ }
6596 } ,
6697 } ) ;
6798 }
0 commit comments