@@ -601,56 +601,124 @@ njs_int_t
601601njs_string_prototype_concat (njs_vm_t * vm , njs_value_t * args , njs_uint_t nargs ,
602602 njs_index_t unused , njs_value_t * retval )
603603{
604- u_char * p , * start ;
605- uint64_t size , length , mask ;
604+
605+ #define NUM_TXT_BUF_LEN 512
606+ #define MAX_NUM_TXT_LEN njs_length("-1.7976931348623157e+308")
607+
608+ char * n_p , n_txt [NUM_TXT_BUF_LEN ];
609+ double num ;
610+ u_char * p ;
611+ uint64_t sz , size , length ;
606612 njs_int_t ret ;
607613 njs_uint_t i ;
614+ const char * n_p_max ;
608615 njs_string_prop_t string ;
609616
617+
618+ n_p_max = n_txt + NUM_TXT_BUF_LEN - 2 * (sizeof (uint16_t ) + MAX_NUM_TXT_LEN );
619+ n_p = n_txt ;
620+
610621 if (njs_is_null_or_undefined (& args [0 ])) {
611622 njs_type_error (vm , "\"this\" argument is null or undefined" );
612623 return NJS_ERROR ;
613624 }
614625
615- for (i = 0 ; i < nargs ; i ++ ) {
616- if (!njs_is_string (& args [i ])) {
617- ret = njs_value_to_string (vm , & args [i ], & args [i ]);
618- if (ret != NJS_OK ) {
619- return ret ;
620- }
621- }
622- }
623-
624626 if (nargs == 1 ) {
625- njs_string_copy (retval , & args [0 ]);
627+ njs_value_assign (retval , & args [0 ]);
626628 return NJS_OK ;
627629 }
628630
629631 size = 0 ;
630632 length = 0 ;
631- mask = -1 ;
632633
633634 for (i = 0 ; i < nargs ; i ++ ) {
634- (void ) njs_string_prop (vm , & string , & args [i ]);
635+ if (njs_is_number (& args [i ])) {
636+ num = njs_number (& args [i ]);
635637
636- size += string . size ;
637- length += string . length ;
638- }
638+ if ( isnan ( num )) {
639+ size += njs_length ( "NaN" ) ;
640+ length += njs_length ( "NaN" );
639641
640- length &= mask ;
642+ } else if (isinf (num )) {
643+ if (num < 0 ) {
644+ size += njs_length ("-Infinity" );
645+ length += njs_length ("-Infinity" );
641646
642- start = njs_string_alloc (vm , retval , size , length );
643- if (njs_slow_path (start == NULL )) {
647+ } else {
648+ size += njs_length ("Infinity" );
649+ length += njs_length ("Infinity" );
650+ }
651+
652+ } else {
653+ sz = njs_dtoa (num , (char * ) n_p + sizeof (uint16_t ));
654+
655+ if (njs_fast_path (n_p < n_p_max )) {
656+ * ((uint16_t * )(n_p )) = sz ;
657+ n_p += sizeof (uint16_t ) + sz ;
658+ }
659+
660+ size += sz ;
661+ length += sz ;
662+ }
663+
664+ } else {
665+ if (!njs_is_string (& args [i ])) {
666+ ret = njs_value_to_string (vm , & args [i ], & args [i ]);
667+ if (ret != NJS_OK ) {
668+ return ret ;
669+ }
670+
671+ }
672+
673+ njs_string_prop (vm , & string , & args [i ]);
674+
675+ size += string .size ;
676+ length += string .length ;
677+ }
678+ }
679+
680+ p = njs_string_alloc (vm , retval , size , length );
681+ if (njs_slow_path (p == NULL )) {
644682 return NJS_ERROR ;
645683 }
646684
647- p = start ;
685+ n_p = n_txt ;
648686
649687 for (i = 0 ; i < nargs ; i ++ ) {
650- (void ) njs_string_prop (vm , & string , & args [i ]);
688+ if (njs_is_number (& args [i ])) {
689+ num = njs_number (& args [i ]);
651690
652- p = memcpy (p , string .start , string .size );
653- p += string .size ;
691+ if (isnan (num )) {
692+ p = njs_cpymem (p , "NaN" , njs_length ("NaN" ));
693+
694+ } else if (isinf (num )) {
695+ if (num < 0 ) {
696+ p = njs_cpymem (p , "-Infinity" , njs_length ("-Infinity" ));
697+
698+ } else {
699+ p = njs_cpymem (p , "Infinity" , njs_length ("Infinity" ));
700+ }
701+
702+ } else {
703+ if (njs_fast_path (n_p < n_p_max )) {
704+ length = * ((uint16_t * )(n_p ));
705+
706+ n_p += sizeof (uint16_t );
707+ p = njs_cpymem (p , n_p , length );
708+
709+ n_p += length ;
710+
711+ } else {
712+ sz = njs_dtoa (num , (char * ) p );
713+ p += sz ;
714+ }
715+ }
716+
717+ } else {
718+ njs_string_prop (vm , & string , & args [i ]);
719+
720+ p = njs_cpymem (p , string .start , string .size );
721+ }
654722 }
655723
656724 return NJS_OK ;
0 commit comments