@@ -27,19 +27,6 @@ if (typeof EventEmitter !== 'function') {
2727
2828function  noop  ( )  { } 
2929
30- function  handle_detect_buffers_reply  ( reply ,  command ,  buffer_args )  { 
31-     if  ( buffer_args  ===  false  ||  this . message_buffers )  { 
32-         // If detect_buffers option was specified, then the reply from the parser will be a buffer. 
33-         // If this command did not use Buffer arguments, then convert the reply to Strings here. 
34-         reply  =  utils . reply_to_strings ( reply ) ; 
35-     } 
36- 
37-     if  ( command  ===  'hgetall' )  { 
38-         reply  =  utils . reply_to_object ( reply ) ; 
39-     } 
40-     return  reply ; 
41- } 
42- 
4330exports . debug_mode  =  / \b r e d i s \b / i. test ( process . env . NODE_DEBUG ) ; 
4431
4532// Attention: The second parameter might be removed at will and is not officially supported. 
@@ -112,10 +99,6 @@ function RedisClient (options, stream) {
11299        self . warn ( 'WARNING: You activated return_buffers and detect_buffers at the same time. The return value is always going to be a buffer.' ) ; 
113100        options . detect_buffers  =  false ; 
114101    } 
115-     if  ( options . detect_buffers )  { 
116-         // We only need to look at the arguments if we do not know what we have to return 
117-         this . handle_reply  =  handle_detect_buffers_reply ; 
118-     } 
119102    this . should_buffer  =  false ; 
120103    this . max_attempts  =  options . max_attempts  |  0 ; 
121104    if  ( 'max_attempts'  in  options )  { 
@@ -144,18 +127,19 @@ function RedisClient (options, stream) {
144127    this . pub_sub_mode  =  0 ; 
145128    this . subscription_set  =  { } ; 
146129    this . monitoring  =  false ; 
147-     this . message_buffers  =  false ; 
130+     this . message_buffers  =  false ;   // Do we have subscribes on message_buffer event 
148131    this . closing  =  false ; 
149132    this . server_info  =  { } ; 
150133    this . auth_pass  =  options . auth_pass  ||  options . password ; 
151134    this . selected_db  =  options . db ;  // Save the selected db here, used when reconnecting 
152135    this . old_state  =  null ; 
153136    this . fire_strings  =  true ;  // Determine if strings or buffers should be written to the stream 
137+     this . cur_command_ret_buf  =  0 ; 
154138    this . pipeline  =  false ; 
155139    this . sub_commands_left  =  0 ; 
156140    this . times_connected  =  0 ; 
157141    this . options  =  options ; 
158-     this . buffers  =  options . return_buffers  ||  options . detect_buffers ; 
142+     this . using_buffer_parser  =  options . return_buffers  ||  options . detect_buffers ; 
159143    this . reply  =  'ON' ;  // Returning replies is the default 
160144    // Init parser 
161145    this . reply_parser  =  create_parser ( this ,  options ) ; 
@@ -172,17 +156,23 @@ function RedisClient (options, stream) {
172156                'The drain event listener is deprecated and will be removed in v.3.0.0.\n'  + 
173157                'If you want to keep on listening to this event please listen to the stream drain event directly.' 
174158            ) ; 
175-         }  else  if  ( event  ===  'message_buffer'  ||  event  ===  'pmessage_buffer'  ||  event  ===  'messageBuffer'  ||  event  ===  'pmessageBuffer'   &&   ! this . buffers )  { 
159+         }  else  if  ( event  ===  'message_buffer'  ||  event  ===  'pmessage_buffer'  ||  event  ===  'messageBuffer'  ||  event  ===  'pmessageBuffer' )  { 
176160            this . message_buffers  =  true ; 
177-             this . handle_reply  =  handle_detect_buffers_reply ; 
178-             this . reply_parser  =  create_parser ( this ) ; 
161+             if  ( ! this . using_buffer_parser )  { 
162+                 this . switchToBufferParser ( ) ; 
163+             } 
179164        } 
180165    } ) ; 
181166} 
182167util . inherits ( RedisClient ,  EventEmitter ) ; 
183168
184169RedisClient . connection_id  =  0 ; 
185170
171+ RedisClient . prototype . switchToBufferParser  =  function ( )  { 
172+     this . using_buffer_parser  =  true ; 
173+     this . reply_parser  =  create_parser ( this ) ; 
174+ } 
175+ 
186176function  create_parser  ( self )  { 
187177    return  Parser ( { 
188178        returnReply : function  ( data )  { 
@@ -208,7 +198,7 @@ function create_parser (self) {
208198            self . emit ( 'error' ,  err ) ; 
209199            self . create_stream ( ) ; 
210200        } , 
211-         returnBuffers : self . buffers   ||   self . message_buffers , 
201+         returnBuffers : self . using_buffer_parser , 
212202        name : self . options . parser , 
213203        stringNumbers : self . options . string_numbers 
214204    } ) ; 
@@ -304,7 +294,15 @@ RedisClient.prototype.create_stream = function () {
304294    } 
305295} ; 
306296
307- RedisClient . prototype . handle_reply  =  function  ( reply ,  command )  { 
297+ RedisClient . prototype . handle_reply  =  function  ( reply ,  command ,  buffer_reply )  { 
298+     if  ( ! buffer_reply  &&  this . using_buffer_parser )  { 
299+         // Reply from parser will be Buffer if: 
300+         // 1) return_buffers option set to true 
301+         // 2) or detect_buffers option set to true and command used Buffer arguments 
302+         // 3) or buffer_reply argument was set to true when calling internal_send_command 
303+         reply  =  utils . reply_to_strings ( reply ) ; 
304+     } 
305+ 
308306    if  ( command  ===  'hgetall' )  { 
309307        reply  =  utils . reply_to_object ( reply ) ; 
310308    } 
@@ -531,7 +529,7 @@ RedisClient.prototype.ready_check = function () {
531529RedisClient . prototype . send_offline_queue  =  function  ( )  { 
532530    for  ( var  command_obj  =  this . offline_queue . shift ( ) ;  command_obj ;  command_obj  =  this . offline_queue . shift ( ) )  { 
533531        debug ( 'Sending offline command: '  +  command_obj . command ) ; 
534-         this . internal_send_command ( command_obj . command ,  command_obj . args ,  command_obj . callback ,  command_obj . call_on_write ) ; 
532+         this . internal_send_command ( command_obj . command ,  command_obj . args ,  command_obj . callback ,  command_obj . call_on_write ,   command_obj . buffer_reply ) ; 
535533    } 
536534    this . drain ( ) ; 
537535} ; 
@@ -716,7 +714,7 @@ function normal_reply (self, reply) {
716714    var  command_obj  =  self . command_queue . shift ( ) ; 
717715    if  ( typeof  command_obj . callback  ===  'function' )  { 
718716        if  ( command_obj . command  !==  'exec' )  { 
719-             reply  =  self . handle_reply ( reply ,  command_obj . command ,  command_obj . buffer_args ) ; 
717+             reply  =  self . handle_reply ( reply ,  command_obj . command ,  command_obj . buffer_reply ) ; 
720718        } 
721719        command_obj . callback ( null ,  reply ) ; 
722720    }  else  { 
@@ -728,7 +726,7 @@ function subscribe_unsubscribe (self, reply, type) {
728726    // Subscribe commands take an optional callback and also emit an event, but only the _last_ response is included in the callback 
729727    // The pub sub commands return each argument in a separate return value and have to be handled that way 
730728    var  command_obj  =  self . command_queue . get ( 0 ) ; 
731-     var  buffer  =  self . options . return_buffers   ||   self . options . detect_buffers   &&   command_obj . buffer_args ; 
729+     var  buffer  =  command_obj . buffer_reply ; 
732730    var  channel  =  ( buffer  ||  reply [ 1 ]  ===  null )  ? reply [ 1 ]  : reply [ 1 ] . toString ( ) ; 
733731    var  count  =  + reply [ 2 ] ;  // Return the channel counter as number no matter if `string_numbers` is activated or not 
734732    debug ( type ,  channel ) ; 
@@ -803,7 +801,7 @@ RedisClient.prototype.return_reply = function (reply) {
803801    // the average performance of all other commands in case of no monitor mode 
804802    if  ( this . monitoring )  { 
805803        var  replyStr ; 
806-         if  ( this . buffers  &&  Buffer . isBuffer ( reply ) )  { 
804+         if  ( this . using_buffer_parser  &&  Buffer . isBuffer ( reply ) )  { 
807805            replyStr  =  reply . toString ( ) ; 
808806        }  else  { 
809807            replyStr  =  reply ; 
@@ -864,9 +862,17 @@ function handle_offline_command (self, command_obj) {
864862    self . should_buffer  =  true ; 
865863} 
866864
865+ RedisClient . prototype . internal_send_command_buf  =  function  ( command ,  args ,  callback ,  call_on_write )  { 
866+     return  this . internal_send_command ( command ,  args ,  callback ,  call_on_write ,  true ) ; 
867+ } ; 
868+ 
867869// Do not call internal_send_command directly, if you are not absolutly certain it handles everything properly 
868870// e.g. monitor / info does not work with internal_send_command only 
869- RedisClient . prototype . internal_send_command  =  function  ( command ,  args ,  callback ,  call_on_write )  { 
871+ RedisClient . prototype . internal_send_command  =  function  ( command ,  args ,  callback ,  call_on_write ,  buffer_reply )  { 
872+     if  ( this . cur_command_ret_buf )  { 
873+         buffer_reply  =  true ;  //needed for send_command_buf and individual commands 
874+     } 
875+ 
870876    var  arg ,  prefix_keys ,  command_obj ; 
871877    var  i  =  0 ; 
872878    var  command_str  =  '' ; 
@@ -881,10 +887,14 @@ RedisClient.prototype.internal_send_command = function (command, args, callback,
881887
882888    if  ( this . ready  ===  false  ||  this . stream . writable  ===  false )  { 
883889        // Handle offline commands right away 
884-         handle_offline_command ( this ,  new  OfflineCommand ( command ,  args ,  callback ,  call_on_write ) ) ; 
890+         handle_offline_command ( this ,  new  OfflineCommand ( command ,  args ,  callback ,  call_on_write ,   buffer_reply ) ) ; 
885891        return  false ;  // Indicate buffering 
886892    } 
887893
894+     if  ( buffer_reply  &&  ! this . using_buffer_parser )  { 
895+         this . switchToBufferParser ( ) ; 
896+     } 
897+ 
888898    for  ( i  =  0 ;  i  <  len ;  i  +=  1 )  { 
889899        if  ( typeof  args [ i ]  ===  'string' )  { 
890900            // 30000 seemed to be a good value to switch to buffers after testing and checking the pros and cons 
@@ -929,7 +939,7 @@ RedisClient.prototype.internal_send_command = function (command, args, callback,
929939        } 
930940    } 
931941    // Pass the original args to make sure in error cases the original arguments are returned 
932-     command_obj  =  new  Command ( command ,  args ,  buffer_args ,  callback ) ; 
942+     command_obj  =  new  Command ( command ,  args ,  this . options . return_buffers   ||   buffer_args   &&   this . options . detect_buffers   ||   buffer_reply ,  callback ) ; 
933943
934944    if  ( this . options . prefix )  { 
935945        prefix_keys  =  commands . getKeyIndexes ( command ,  args_copy ) ; 
0 commit comments