diff --git a/benchmark/util/text-decoder.js b/benchmark/util/text-decoder.js new file mode 100644 index 00000000000000..29997169ebf531 --- /dev/null +++ b/benchmark/util/text-decoder.js @@ -0,0 +1,19 @@ +'use strict'; + +const common = require('../common.js'); + +const bench = common.createBenchmark(main, { + encoding: ['utf-8', 'latin1', 'iso-8859-3'], + ignoreBOM: [0, 1], + len: [1, 64, 1024], + n: [1e6] +}); + +function main({ encoding, len, n, ignoreBOM }) { + const buf = Buffer.allocUnsafe(len); + const decoder = new TextDecoder(encoding, { ignoreBOM }); + + bench.start(); + decoder.decode(buf); + bench.end(n); +} diff --git a/lib/internal/encoding.js b/lib/internal/encoding.js index f9fa43228d5f57..01154958660a0c 100644 --- a/lib/internal/encoding.js +++ b/lib/internal/encoding.js @@ -432,7 +432,7 @@ function makeTextDecoderICU() { if (typeof ret === 'number') { throw new ERR_ENCODING_INVALID_ENCODED_DATA(this.encoding, ret); } - return ret.toString('ucs2'); + return ret; } } diff --git a/src/node_i18n.cc b/src/node_i18n.cc index 581d52a7d05738..1fc2e0c9cbbe40 100644 --- a/src/node_i18n.cc +++ b/src/node_i18n.cc @@ -50,6 +50,7 @@ #include "node_buffer.h" #include "node_errors.h" #include "node_internals.h" +#include "string_bytes.h" #include "util-inl.h" #include "v8.h" @@ -502,18 +503,32 @@ void ConverterObject::Decode(const FunctionCallbackInfo& args) { } } ret = ToBufferEndian(env, &result); - if (omit_initial_bom && !ret.IsEmpty()) { - // Perform `ret = ret.slice(2)`. + + if (!ret.IsEmpty()) { CHECK(ret.ToLocalChecked()->IsUint8Array()); - Local orig_ret = ret.ToLocalChecked().As(); - ret = Buffer::New(env, - orig_ret->Buffer(), - orig_ret->ByteOffset() + 2, - orig_ret->ByteLength() - 2) - .FromMaybe(Local()); + + if (omit_initial_bom) { + // Perform `ret = ret.slice(2)`. + Local orig_ret = ret.ToLocalChecked().As(); + ret = Buffer::New(env, + orig_ret->Buffer(), + orig_ret->ByteOffset() + 2, + orig_ret->ByteLength() - 2) + .FromMaybe(Local()); + } + + Local error; + ArrayBufferViewContents buf(ret.ToLocalChecked()); + MaybeLocal encoded = StringBytes::Encode( + env->isolate(), buf.data(), buf.length(), encoding::UCS2, &error); + + if (!encoded.IsEmpty()) { + args.GetReturnValue().Set(encoded.ToLocalChecked()); + } else { + args.GetReturnValue().Set(error); + } } - if (!ret.IsEmpty()) - args.GetReturnValue().Set(ret.ToLocalChecked()); + return; }