3
3
const {
4
4
ObjectDefineProperties,
5
5
Symbol,
6
+ String,
7
+ Uint8Array,
6
8
} = primordials ;
7
9
8
10
const {
@@ -31,6 +33,7 @@ const {
31
33
const kHandle = Symbol ( 'kHandle' ) ;
32
34
const kTransform = Symbol ( 'kTransform' ) ;
33
35
const kType = Symbol ( 'kType' ) ;
36
+ const kPendingHighSurrogate = Symbol ( 'kPendingHighSurrogate' ) ;
34
37
35
38
/**
36
39
* @typedef {import('./readablestream').ReadableStream } ReadableStream
@@ -49,19 +52,46 @@ function isTextDecoderStream(value) {
49
52
50
53
class TextEncoderStream {
51
54
constructor ( ) {
55
+ this [ kPendingHighSurrogate ] = null ;
52
56
this [ kType ] = 'TextEncoderStream' ;
53
57
this [ kHandle ] = new TextEncoder ( ) ;
54
58
this [ kTransform ] = new TransformStream ( {
55
59
transform : ( chunk , controller ) => {
56
- const value = this [ kHandle ] . encode ( chunk ) ;
57
- if ( value )
60
+ // https://encoding.spec.whatwg.org/#encode-and-enqueue-a-chunk
61
+ chunk = String ( chunk ) ;
62
+ let finalChunk = '' ;
63
+ for ( let i = 0 ; i < chunk . length ; i ++ ) {
64
+ const item = chunk [ i ] ;
65
+ const codeUnit = item . charCodeAt ( 0 ) ;
66
+ if ( this [ kPendingHighSurrogate ] !== null ) {
67
+ const highSurrogate = this [ kPendingHighSurrogate ] ;
68
+ this [ kPendingHighSurrogate ] = null ;
69
+ if ( 0xDC00 <= codeUnit && codeUnit <= 0xDFFF ) {
70
+ finalChunk += highSurrogate + item ;
71
+ continue ;
72
+ }
73
+ finalChunk += '\uFFFD' ;
74
+ }
75
+ if ( 0xD800 <= codeUnit && codeUnit <= 0xDBFF ) {
76
+ this [ kPendingHighSurrogate ] = item ;
77
+ continue ;
78
+ }
79
+ if ( 0xDC00 <= codeUnit && codeUnit <= 0xDFFF ) {
80
+ finalChunk += '\uFFFD' ;
81
+ continue ;
82
+ }
83
+ finalChunk += item ;
84
+ }
85
+ if ( finalChunk ) {
86
+ const value = this [ kHandle ] . encode ( finalChunk ) ;
58
87
controller . enqueue ( value ) ;
88
+ }
59
89
} ,
60
90
flush : ( controller ) => {
61
- const value = this [ kHandle ] . encode ( ) ;
62
- if ( value . byteLength > 0 )
63
- controller . enqueue ( value ) ;
64
- controller . terminate ( ) ;
91
+ // https://encoding.spec.whatwg.org/# encode-and-flush
92
+ if ( this [ kPendingHighSurrogate ] !== null ) {
93
+ controller . enqueue ( new Uint8Array ( [ 0xEF , 0xBF , 0xBD ] ) ) ;
94
+ }
65
95
} ,
66
96
} ) ;
67
97
}
0 commit comments