2
2
3
3
const {
4
4
ObjectDefineProperties,
5
+ String,
6
+ StringPrototypeCharCodeAt,
5
7
Symbol,
8
+ Uint8Array,
6
9
} = primordials ;
7
10
8
11
const {
@@ -31,6 +34,7 @@ const {
31
34
const kHandle = Symbol ( 'kHandle' ) ;
32
35
const kTransform = Symbol ( 'kTransform' ) ;
33
36
const kType = Symbol ( 'kType' ) ;
37
+ const kPendingHighSurrogate = Symbol ( 'kPendingHighSurrogate' ) ;
34
38
35
39
/**
36
40
* @typedef {import('./readablestream').ReadableStream } ReadableStream
@@ -49,19 +53,46 @@ function isTextDecoderStream(value) {
49
53
50
54
class TextEncoderStream {
51
55
constructor ( ) {
56
+ this [ kPendingHighSurrogate ] = null ;
52
57
this [ kType ] = 'TextEncoderStream' ;
53
58
this [ kHandle ] = new TextEncoder ( ) ;
54
59
this [ kTransform ] = new TransformStream ( {
55
60
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 ) ;
58
88
controller . enqueue ( value ) ;
89
+ }
59
90
} ,
60
91
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
+ }
65
96
} ,
66
97
} ) ;
67
98
}
0 commit comments