From aa9fa589b7dbcc2e31c29fbb16987afaceaf80f8 Mon Sep 17 00:00:00 2001
From: Yagiz Nizipli <yagiz@nizipli.com>
Date: Mon, 7 Nov 2022 09:06:54 -0500
Subject: [PATCH 1/3] benchmark: fix text-decoder benchmark

---
 benchmark/util/text-decoder.js | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/benchmark/util/text-decoder.js b/benchmark/util/text-decoder.js
index ad845f7c92d0c7..9a6fc97eab2695 100644
--- a/benchmark/util/text-decoder.js
+++ b/benchmark/util/text-decoder.js
@@ -14,6 +14,8 @@ function main({ encoding, len, n, ignoreBOM }) {
   const decoder = new TextDecoder(encoding, { ignoreBOM });
 
   bench.start();
-  decoder.decode(buf);
+  for (let i = 0; i < n; i++) {
+    decoder.decode(buf);
+  }
   bench.end(n);
 }

From d621bc7d6f448ffcb6e5a47b4442938d95c85a7d Mon Sep 17 00:00:00 2001
From: Yagiz Nizipli <yagiz@nizipli.com>
Date: Mon, 7 Nov 2022 09:07:09 -0500
Subject: [PATCH 2/3] benchmark: add parameters to text-decoder benchmark

---
 benchmark/util/text-decoder.js | 22 +++++++++++++++++++---
 1 file changed, 19 insertions(+), 3 deletions(-)

diff --git a/benchmark/util/text-decoder.js b/benchmark/util/text-decoder.js
index 9a6fc97eab2695..3d1ccc34bb8995 100644
--- a/benchmark/util/text-decoder.js
+++ b/benchmark/util/text-decoder.js
@@ -6,12 +6,28 @@ const bench = common.createBenchmark(main, {
   encoding: ['utf-8', 'latin1', 'iso-8859-3'],
   ignoreBOM: [0, 1],
   len: [256, 1024 * 16, 1024 * 512],
-  n: [1e6]
+  n: [1e2],
+  type: ['SharedArrayBuffer', 'ArrayBuffer', 'Buffer']
 });
 
-function main({ encoding, len, n, ignoreBOM }) {
-  const buf = Buffer.allocUnsafe(len);
+function main({ encoding, len, n, ignoreBOM, type }) {
   const decoder = new TextDecoder(encoding, { ignoreBOM });
+  let buf;
+
+  switch (type) {
+    case 'SharedArrayBuffer': {
+      buf = new SharedArrayBuffer(len);
+      break;
+    }
+    case 'ArrayBuffer': {
+      buf = new ArrayBuffer(len);
+      break;
+    }
+    case 'Buffer': {
+      buf = Buffer.allocUnsafe(len);
+      break;
+    }
+  }
 
   bench.start();
   for (let i = 0; i < n; i++) {

From 2d97395c30b73568c4791f59ed8838435b848c62 Mon Sep 17 00:00:00 2001
From: Yagiz Nizipli <yagiz@nizipli.com>
Date: Mon, 7 Nov 2022 09:07:34 -0500
Subject: [PATCH 3/3] util: improve text-decoder performance

---
 lib/internal/encoding.js | 10 +---------
 src/util-inl.h           | 25 +++++++++++++++++++++++--
 src/util.h               |  1 +
 3 files changed, 25 insertions(+), 11 deletions(-)

diff --git a/lib/internal/encoding.js b/lib/internal/encoding.js
index 2ab85d9d9acb06..40c87a0a8719ff 100644
--- a/lib/internal/encoding.js
+++ b/lib/internal/encoding.js
@@ -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);
diff --git a/src/util-inl.h b/src/util-inl.h
index bdf9732e853485..18f829d2775f0d 100644
--- a/src/util-inl.h
+++ b/src/util-inl.h
@@ -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>());
+  DCHECK(value->IsArrayBufferView() || value->IsSharedArrayBuffer() ||
+         value->IsArrayBuffer());
+  ReadValue(value);
 }
 
 template <typename T, size_t S>
@@ -542,6 +543,26 @@ 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");
+  DCHECK(buf->IsArrayBufferView() || buf->IsSharedArrayBuffer() ||
+         buf->IsArrayBuffer());
+
+  if (buf->IsArrayBufferView()) {
+    Read(buf.As<v8::ArrayBufferView>());
+  } else if (buf->IsArrayBuffer()) {
+    auto ab = buf.As<v8::ArrayBuffer>();
+    length_ = ab->ByteLength();
+    data_ = static_cast<T*>(ab->Data());
+  } else {
+    CHECK(buf->IsSharedArrayBuffer());
+    auto sab = buf.As<v8::SharedArrayBuffer>();
+    length_ = sab->ByteLength();
+    data_ = static_cast<T*>(sab->Data());
+  }
+}
+
 // ECMA262 20.1.2.5
 inline bool IsSafeJsInt(v8::Local<v8::Value> v) {
   if (!v->IsNumber()) return false;
diff --git a/src/util.h b/src/util.h
index 7a41eae4aa77df..6094f07f201f2f 100644
--- a/src/util.h
+++ b/src/util.h
@@ -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_; }