@@ -570,42 +570,91 @@ void Copy(const FunctionCallbackInfo<Value> &args) {
570
570
571
571
572
572
void Fill (const FunctionCallbackInfo<Value>& args) {
573
- THROW_AND_RETURN_UNLESS_BUFFER (Environment::GetCurrent (args), args[0 ]);
573
+ Environment* env = Environment::GetCurrent (args);
574
+
575
+ THROW_AND_RETURN_UNLESS_BUFFER (env, args[0 ]);
574
576
SPREAD_ARG (args[0 ], ts_obj);
575
577
576
578
size_t start = args[2 ]->Uint32Value ();
577
579
size_t end = args[3 ]->Uint32Value ();
578
- size_t length = end - start;
579
- CHECK (length + start <= ts_obj_length);
580
+ size_t fill_length = end - start;
581
+ Local<String> str_obj;
582
+ size_t str_length;
583
+ enum encoding enc;
584
+ CHECK (fill_length + start <= ts_obj_length);
585
+
586
+ // First check if Buffer has been passed.
587
+ if (Buffer::HasInstance (args[1 ])) {
588
+ SPREAD_ARG (args[1 ], fill_obj);
589
+ str_length = fill_obj_length;
590
+ memcpy (ts_obj_data + start, fill_obj_data, MIN (str_length, fill_length));
591
+ goto start_fill;
592
+ }
580
593
581
- if (args[1 ]->IsNumber ()) {
594
+ // Then coerce everything that's not a string.
595
+ if (!args[1 ]->IsString ()) {
582
596
int value = args[1 ]->Uint32Value () & 255 ;
583
- memset (ts_obj_data + start, value, length );
597
+ memset (ts_obj_data + start, value, fill_length );
584
598
return ;
585
599
}
586
600
587
- node::Utf8Value str (args.GetIsolate (), args[1 ]);
588
- size_t str_length = str.length ();
589
- size_t in_there = str_length;
590
- char * ptr = ts_obj_data + start + str_length;
601
+ str_obj = args[1 ]->ToString (env->isolate ());
602
+ enc = ParseEncoding (env->isolate (), args[4 ], UTF8);
603
+ str_length =
604
+ enc == UTF8 ? str_obj->Utf8Length () :
605
+ enc == UCS2 ? str_obj->Length () * sizeof (uint16_t ) : str_obj->Length ();
606
+
607
+ if (enc == HEX && str_length % 2 != 0 )
608
+ return env->ThrowTypeError (" Invalid hex string" );
591
609
592
610
if (str_length == 0 )
593
611
return ;
594
612
595
- memcpy (ts_obj_data + start, *str, MIN (str_length, length));
613
+ // Can't use StringBytes::Write() in all cases. For example if attempting
614
+ // to write a two byte character into a one byte Buffer.
615
+ if (enc == UTF8) {
616
+ node::Utf8Value str (env->isolate (), args[1 ]);
617
+ memcpy (ts_obj_data + start, *str, MIN (str_length, fill_length));
596
618
597
- if (str_length >= length)
619
+ } else if (enc == UCS2) {
620
+ node::TwoByteValue str (env->isolate (), args[1 ]);
621
+ memcpy (ts_obj_data + start, *str, MIN (str_length, fill_length));
622
+
623
+ } else {
624
+ // Write initial String to Buffer, then use that memory to copy remainder
625
+ // of string. Correct the string length for cases like HEX where less than
626
+ // the total string length is written.
627
+ str_length = StringBytes::Write (env->isolate (),
628
+ ts_obj_data + start,
629
+ fill_length,
630
+ str_obj,
631
+ enc,
632
+ nullptr );
633
+ // This check is also needed in case Write() returns that no bytes could
634
+ // be written.
635
+ // TODO(trevnorris): Should this throw? Because of the string length was
636
+ // greater than 0 but couldn't be written then the string was invalid.
637
+ if (str_length == 0 )
638
+ return ;
639
+ }
640
+
641
+ start_fill:
642
+
643
+ if (str_length >= fill_length)
598
644
return ;
599
645
600
- while (in_there < length - in_there) {
646
+
647
+ size_t in_there = str_length;
648
+ char * ptr = ts_obj_data + start + str_length;
649
+
650
+ while (in_there < fill_length - in_there) {
601
651
memcpy (ptr, ts_obj_data + start, in_there);
602
652
ptr += in_there;
603
653
in_there *= 2 ;
604
654
}
605
655
606
- if (in_there < length) {
607
- memcpy (ptr, ts_obj_data + start, length - in_there);
608
- in_there = length;
656
+ if (in_there < fill_length) {
657
+ memcpy (ptr, ts_obj_data + start, fill_length - in_there);
609
658
}
610
659
}
611
660
0 commit comments