@@ -7,6 +7,11 @@ import { Duplex } from 'stream';
77 * used when running compass-web in a local sandbox, mms has their own
88 * implementation
99 */
10+ enum MESSAGE_TYPE {
11+ JSON = 0x01 ,
12+ BINARY = 0x02 ,
13+ }
14+
1015class Socket extends Duplex {
1116 private _ws : WebSocket | null = null ;
1217 constructor ( ) {
@@ -36,7 +41,7 @@ class Socket extends Duplex {
3641 ok : 1 ,
3742 } ) ;
3843 setTimeout ( ( ) => {
39- this . _ws ?. send ( connectMsg ) ;
44+ this . _ws ?. send ( this . encodeStringMessageWithTypeByte ( connectMsg ) ) ;
4045 } ) ;
4146 } ,
4247 { once : true }
@@ -49,10 +54,11 @@ class Socket extends Duplex {
4954 } ) ;
5055 this . _ws . addEventListener (
5156 'message' ,
52- ( { data } : MessageEvent < string | ArrayBuffer > ) => {
53- if ( typeof data === 'string' ) {
57+ ( { data } : MessageEvent < ArrayBuffer > ) => {
58+ const dataView = new Uint8Array ( data ) ;
59+ if ( dataView [ 0 ] === 0x01 ) {
5460 try {
55- const res = JSON . parse ( data ) as { preMessageOk : 1 } ;
61+ const res = this . decodeMessageWithTypeByte ( dataView ) ;
5662 if ( res . preMessageOk ) {
5763 setTimeout ( ( ) => {
5864 this . emit ( options . tls ? 'secureConnect' : 'connect' ) ;
@@ -64,7 +70,7 @@ class Socket extends Duplex {
6470 }
6571 } else {
6672 setTimeout ( ( ) => {
67- this . emit ( 'data' , Buffer . from ( data ) ) ;
73+ this . emit ( 'data' , this . decodeMessageWithTypeByte ( dataView ) ) ;
6874 } ) ;
6975 }
7076 }
@@ -75,7 +81,7 @@ class Socket extends Duplex {
7581 // noop
7682 }
7783 _write ( chunk : ArrayBufferLike , _encoding : BufferEncoding , cb : ( ) => void ) {
78- this . _ws ?. send ( chunk ) ;
84+ this . _ws ?. send ( this . encodeBinaryMessageWithTypeByte ( new Uint8Array ( chunk ) ) ) ;
7985 setTimeout ( ( ) => {
8086 cb ( ) ;
8187 } ) ;
@@ -110,6 +116,38 @@ class Socket extends Duplex {
110116 setNoDelay ( ) {
111117 return this ;
112118 }
119+
120+ encodeStringMessageWithTypeByte ( message : string ) {
121+ const utf8Encoder = new TextEncoder ( ) ;
122+ const utf8Array = utf8Encoder . encode ( message ) ;
123+ return this . encodeMessageWithTypeByte ( utf8Array , MESSAGE_TYPE . JSON ) ;
124+ }
125+
126+ encodeBinaryMessageWithTypeByte ( message : Uint8Array ) {
127+ return this . encodeMessageWithTypeByte ( message , MESSAGE_TYPE . BINARY ) ;
128+ }
129+
130+ encodeMessageWithTypeByte ( message : Uint8Array , type : MESSAGE_TYPE ) {
131+ const encoded = new Uint8Array ( message . length + 1 ) ;
132+ encoded [ 0 ] = type ;
133+ encoded . set ( message , 1 ) ;
134+ return encoded ;
135+ }
136+
137+ decodeMessageWithTypeByte ( message : Uint8Array ) {
138+ const typeByte = message [ 0 ] ;
139+ if ( typeByte === MESSAGE_TYPE . JSON ) {
140+ const jsonBytes = message . subarray ( 1 ) ;
141+ const textDecoder = new TextDecoder ( 'utf-8' ) ;
142+ const jsonStr = textDecoder . decode ( jsonBytes ) ;
143+ return JSON . parse ( jsonStr ) ;
144+ } else if ( typeByte === MESSAGE_TYPE . BINARY ) {
145+ return message . subarray ( 1 ) ;
146+ } else {
147+ // eslint-disable-next-line no-console
148+ console . error ( 'message does not have valid type byte "%s"' , message ) ;
149+ }
150+ }
113151}
114152
115153export { isIPv4 , isIPv6 } from 'is-ip' ;
0 commit comments