@@ -95,6 +95,7 @@ using v8::NewStringType;
9595using v8::Object;
9696using v8::ObjectTemplate;
9797using v8::String;
98+ using v8::Uint8Array;
9899using v8::Value;
99100
100101namespace i18n {
@@ -227,25 +228,41 @@ class ConverterObject : public BaseObject, Converter {
227228 const char * source = input.data ();
228229 size_t source_length = input.length ();
229230
230- if (converter->unicode_ && !converter->ignoreBOM_ && !converter->bomSeen_ ) {
231- int32_t bomOffset = 0 ;
232- ucnv_detectUnicodeSignature (source, source_length, &bomOffset, &status);
233- source += bomOffset;
234- source_length -= bomOffset;
235- converter->bomSeen_ = true ;
236- }
237-
238231 UChar* target = *result;
239232 ucnv_toUnicode (converter->conv ,
240233 &target, target + (limit * sizeof (UChar)),
241234 &source, source + source_length,
242235 nullptr , flush, &status);
243236
244237 if (U_SUCCESS (status)) {
245- if (limit > 0 )
238+ bool omit_initial_bom = false ;
239+ if (limit > 0 ) {
246240 result.SetLength (target - &result[0 ]);
241+ if (result.length () > 0 &&
242+ converter->unicode_ &&
243+ !converter->ignoreBOM_ &&
244+ !converter->bomSeen_ ) {
245+ // If the very first result in the stream is a BOM, and we are not
246+ // explicitly told to ignore it, then we mark it for discarding.
247+ if (result[0 ] == 0xFEFF ) {
248+ omit_initial_bom = true ;
249+ }
250+ converter->bomSeen_ = true ;
251+ }
252+ }
247253 ret = ToBufferEndian (env, &result);
248- args.GetReturnValue ().Set (ret.ToLocalChecked ());
254+ if (omit_initial_bom && !ret.IsEmpty ()) {
255+ // Peform `ret = ret.slice(2)`.
256+ CHECK (ret.ToLocalChecked ()->IsUint8Array ());
257+ Local<Uint8Array> orig_ret = ret.ToLocalChecked ().As <Uint8Array>();
258+ ret = Buffer::New (env,
259+ orig_ret->Buffer (),
260+ orig_ret->ByteOffset () + 2 ,
261+ orig_ret->ByteLength () - 2 )
262+ .FromMaybe (Local<Uint8Array>());
263+ }
264+ if (!ret.IsEmpty ())
265+ args.GetReturnValue ().Set (ret.ToLocalChecked ());
249266 return ;
250267 }
251268
0 commit comments