11var exec = require ( 'cordova/exec' ) ;
2+ /**
3+ * Whether to log debug messages
4+ */
5+ let DEBUG = false ;
6+
7+ const logIfDebug = ( ...args ) => {
8+ if ( DEBUG ) {
9+ console . log ( ...args ) ;
10+ }
11+ } ;
212
3- class WebSocketInstance {
13+ class WebSocketInstance extends EventTarget {
414 constructor ( url , instanceId ) {
15+ super ( ) ;
516 this . instanceId = instanceId ;
617 this . extensions = '' ;
718 this . readyState = WebSocketInstance . CONNECTING ;
@@ -10,27 +21,66 @@ class WebSocketInstance {
1021 this . onclose = null ;
1122 this . onerror = null ;
1223 this . url = url ;
24+ this . binaryType = '' ; // empty as Default is string.
1325
1426 exec ( ( event ) => {
27+ logIfDebug ( `[Cordova WebSocket - ID=${ this . instanceId } ] Event from native:` , event ) ;
28+
1529 if ( event . type === 'open' ) {
1630 this . readyState = WebSocketInstance . OPEN ;
1731 this . extensions = event . extensions || '' ;
18- if ( this . onopen ) this . onopen . bind ( this ) ( event ) ;
32+ if ( this . onopen ) this . onopen ( event ) ;
33+ this . dispatchEvent ( new Event ( 'open' ) ) ;
34+ }
35+
36+ if ( event . type === 'message' ) {
37+ let msgData = event . data ;
38+ if ( event . isBinary && this . binaryType === 'arraybuffer' ) {
39+ let binary = atob ( msgData ) ;
40+ let bytes = new Uint8Array ( binary . length ) ;
41+ for ( let i = 0 ; i < binary . length ; i ++ ) {
42+ bytes [ i ] = binary . charCodeAt ( i ) ;
43+ }
44+ msgData = bytes . buffer ;
45+ }
46+ logIfDebug ( `[Cordova WebSocket - ID=${ this . instanceId } ] msg Event:` , event , msgData ) ;
47+ const msgEvent = new MessageEvent ( 'message' , { data : msgData } ) ;
48+ if ( this . onmessage ) this . onmessage ( msgEvent ) ;
49+ this . dispatchEvent ( msgEvent ) ;
1950 }
20- if ( event . type === 'message' && this . onmessage ) this . onmessage . bind ( this ) ( event ) ;
51+
2152 if ( event . type === 'close' ) {
2253 this . readyState = WebSocketInstance . CLOSED ;
23- if ( this . onclose ) this . onclose . bind ( this ) ( { code : event ?. data ?. code , reason : event ?. data ?. reason , type : event . type } ) ;
54+ const closeEvent = new CloseEvent ( 'close' , { code : event . data ?. code , reason : event . data ?. reason } ) ;
55+ if ( this . onclose ) this . onclose ( closeEvent ) ;
56+ this . dispatchEvent ( closeEvent ) ;
57+ }
58+
59+ if ( event . type === 'error' ) {
60+ const errorEvent = new Event ( 'error' , { message : event ?. data } ) ;
61+ if ( this . onerror ) this . onerror ( errorEvent ) ;
62+ this . dispatchEvent ( errorEvent ) ;
2463 }
25- if ( event . type === 'error' && this . onerror ) this . onerror . bind ( this ) ( event ) ;
2664 } , null , "WebSocketPlugin" , "registerListener" , [ this . instanceId ] ) ;
2765 }
2866
2967 send ( message ) {
30- if ( this . readyState === WebSocketInstance . OPEN ) {
31- exec ( null , null , "WebSocketPlugin" , "send" , [ this . instanceId , message ] ) ;
68+ if ( this . readyState !== WebSocketInstance . OPEN ) {
69+ throw new Error ( `WebSocket is not open/connected` ) ;
70+ }
71+
72+ let finalMessage = null ;
73+ if ( message instanceof ArrayBuffer || ArrayBuffer . isView ( message ) ) {
74+ const uint8Array = message instanceof ArrayBuffer ? new Uint8Array ( message ) : message ;
75+ finalMessage = btoa ( String . fromCharCode . apply ( null , uint8Array ) ) ;
76+
77+ exec ( ( ) => logIfDebug ( `[Cordova WebSocket - ID=${ this . instanceId } ] Sent message:` , finalMessage ) , ( err ) => console . error ( `[Cordova WebSocket - ID=${ this . instanceId } ] Send error:` , err ) , "WebSocketPlugin" , "send" , [ this . instanceId , finalMessage ] ) ;
78+ } else if ( typeof message === 'string' ) {
79+ finalMessage = message ;
80+
81+ exec ( ( ) => logIfDebug ( `[Cordova WebSocket - ID=${ this . instanceId } ] Sent message:` , finalMessage ) , ( err ) => console . error ( `[Cordova WebSocket - ID=${ this . instanceId } ] Send error:` , err ) , "WebSocketPlugin" , "send" , [ this . instanceId , finalMessage ] ) ;
3282 } else {
33- throw new Error ( "WebSocket is not open" ) ;
83+ throw new Error ( `Unsupported message type: ${ typeof message } ` ) ;
3484 }
3585 }
3686
@@ -42,7 +92,7 @@ class WebSocketInstance {
4292 */
4393 close ( code , reason ) {
4494 this . readyState = WebSocketInstance . CLOSING ;
45- exec ( null , null , "WebSocketPlugin" , "close" , [ this . instanceId , code , reason ] ) ;
95+ exec ( ( ) => logIfDebug ( `[Cordova WebSocket - ID= ${ this . instanceId } ] Close requested` , code , reason ) , ( err ) => console . error ( `[Cordova WebSocket - ID= ${ this . instanceId } ] Close error` , err ) , "WebSocketPlugin" , "close" , [ this . instanceId , code , reason ] ) ;
4696 }
4797}
4898
@@ -51,9 +101,9 @@ WebSocketInstance.OPEN = 1;
51101WebSocketInstance . CLOSING = 2 ;
52102WebSocketInstance . CLOSED = 3 ;
53103
54- const connect = function ( url , protocols = null , headers = null ) {
104+ const connect = function ( url , protocols = null , headers = null , binaryType ) {
55105 return new Promise ( ( resolve , reject ) => {
56- exec ( instanceId => resolve ( new WebSocketInstance ( url , instanceId ) ) , reject , "WebSocketPlugin" , "connect" , [ url , protocols , headers ] ) ;
106+ exec ( instanceId => resolve ( new WebSocketInstance ( url , instanceId ) ) , reject , "WebSocketPlugin" , "connect" , [ url , protocols , binaryType , headers ] ) ;
57107 } ) ;
58108} ;
59109
@@ -67,7 +117,16 @@ const listClients = function() {
67117
68118const send = function ( instanceId , message ) {
69119 return new Promise ( ( resolve , reject ) => {
70- exec ( resolve , reject , "WebSocketPlugin" , "send" , [ instanceId , message ] ) ;
120+ if ( typeof message === 'string' ) {
121+ exec ( resolve , reject , "WebSocketPlugin" , "send" , [ instanceId , message ] ) ;
122+ } else if ( message instanceof ArrayBuffer || ArrayBuffer . isView ( message ) ) {
123+ const uint8Array = message instanceof ArrayBuffer ? new Uint8Array ( message ) : message ;
124+ const base64Message = btoa ( String . fromCharCode . apply ( null , uint8Array ) ) ;
125+
126+ exec ( resolve , reject , "WebSocketPlugin" , "send" , [ instanceId , base64Message ] ) ;
127+ } else {
128+ reject ( `Unsupported message type: ${ typeof message } ` ) ;
129+ }
71130 } ) ;
72131} ;
73132
@@ -86,4 +145,4 @@ const close = function(instanceId, code, reason) {
86145 } ) ;
87146} ;
88147
89- module . exports = { connect, listClients, send, close } ;
148+ module . exports = { connect, listClients, send, close, DEBUG } ;
0 commit comments