Skip to content

Commit

Permalink
util: improve text-decoder performance
Browse files Browse the repository at this point in the history
  • Loading branch information
anonrig committed Nov 7, 2022
1 parent 79e26b5 commit 31d97d1
Show file tree
Hide file tree
Showing 4 changed files with 26 additions and 17 deletions.
10 changes: 1 addition & 9 deletions lib/internal/encoding.js
Expand Up @@ -411,15 +411,7 @@ function makeTextDecoderICU() {

decode(input = empty, options = kEmptyObject) {
validateDecoder(this);
if (isAnyArrayBuffer(input)) {
try {
input = lazyBuffer().from(input);
} catch {
// If the buffer is detached,
// use an empty Uint8Array to avoid TypeError
input = empty;
}
} else if (!isArrayBufferView(input)) {
if (!isAnyArrayBuffer(input) && !isArrayBufferView(input)) {
throw new ERR_INVALID_ARG_TYPE('input',
['ArrayBuffer', 'ArrayBufferView'],
input);
Expand Down
10 changes: 4 additions & 6 deletions src/node_i18n.cc
Expand Up @@ -453,12 +453,10 @@ void ConverterObject::Decode(const FunctionCallbackInfo<Value>& args) {
// characters times the min char size, multiplied by 2 as unicode may
// take up to 2 UChars to encode a character
size_t limit = 2 * converter->min_char_size() *
(!flush ?
input.length() :
std::max(
input.length(),
static_cast<size_t>(
ucnv_toUCountPending(converter->conv(), &status))));
(!flush ? input.length()
: std::max(input.length(),
static_cast<size_t>(ucnv_toUCountPending(
converter->conv(), &status))));
status = U_ZERO_ERROR;

if (limit > 0)
Expand Down
22 changes: 20 additions & 2 deletions src/util-inl.h
Expand Up @@ -513,8 +513,9 @@ SlicedArguments::SlicedArguments(
template <typename T, size_t S>
ArrayBufferViewContents<T, S>::ArrayBufferViewContents(
v8::Local<v8::Value> value) {
CHECK(value->IsArrayBufferView());
Read(value.As<v8::ArrayBufferView>());
CHECK(value->IsArrayBufferView() || value->IsSharedArrayBuffer() ||
value->IsArrayBuffer());
ReadValue(value);
}

template <typename T, size_t S>
Expand Down Expand Up @@ -542,6 +543,23 @@ void ArrayBufferViewContents<T, S>::Read(v8::Local<v8::ArrayBufferView> abv) {
}
}

template <typename T, size_t S>
void ArrayBufferViewContents<T, S>::ReadValue(v8::Local<v8::Value> buf) {
static_assert(sizeof(T) == 1, "Only supports one-byte data at the moment");

if (buf->IsArrayBufferView()) {
Read(buf.As<v8::ArrayBufferView>());
} else if (buf->IsArrayBuffer()) {
auto ab = buf.As<v8::ArrayBuffer>();
length_ = ab->ByteLength();
data_ = reinterpret_cast<T*>(ab->Data());
} else {
auto sab = buf.As<v8::SharedArrayBuffer>();
length_ = sab->ByteLength();
data_ = reinterpret_cast<T*>(sab->Data());
}
}

// ECMA262 20.1.2.5
inline bool IsSafeJsInt(v8::Local<v8::Value> v) {
if (!v->IsNumber()) return false;
Expand Down
1 change: 1 addition & 0 deletions src/util.h
Expand Up @@ -506,6 +506,7 @@ class ArrayBufferViewContents {
explicit inline ArrayBufferViewContents(v8::Local<v8::Object> value);
explicit inline ArrayBufferViewContents(v8::Local<v8::ArrayBufferView> abv);
inline void Read(v8::Local<v8::ArrayBufferView> abv);
inline void ReadValue(v8::Local<v8::Value> buf);

inline const T* data() const { return data_; }
inline size_t length() const { return length_; }
Expand Down

0 comments on commit 31d97d1

Please sign in to comment.