aboutsummaryrefslogtreecommitdiff
path: root/src/bun.js
diff options
context:
space:
mode:
authorGravatar Jarred Sumner <jarred@jarredsumner.com> 2023-07-02 18:06:21 -0700
committerGravatar GitHub <noreply@github.com> 2023-07-02 18:06:21 -0700
commitc3f8593f8cb1571b41b8233e5ded98e3d3f99fb0 (patch)
treec6d45c32b1d63b8bf6f347146b67255b0bccdb6b /src/bun.js
parent4cbda049e97b2e1049cd2c4c93a617a54931b220 (diff)
downloadbun-c3f8593f8cb1571b41b8233e5ded98e3d3f99fb0.tar.gz
bun-c3f8593f8cb1571b41b8233e5ded98e3d3f99fb0.tar.zst
bun-c3f8593f8cb1571b41b8233e5ded98e3d3f99fb0.zip
[node:buffer] Implement `isUtf8` and `isAscii` (#3498)
Co-authored-by: Jarred Sumner <709451+Jarred-Sumner@users.noreply.github.com>
Diffstat (limited to 'src/bun.js')
-rw-r--r--src/bun.js/modules/BufferModule.h130
1 files changed, 130 insertions, 0 deletions
diff --git a/src/bun.js/modules/BufferModule.h b/src/bun.js/modules/BufferModule.h
index a96fb18c8..6e6e39e9c 100644
--- a/src/bun.js/modules/BufferModule.h
+++ b/src/bun.js/modules/BufferModule.h
@@ -2,11 +2,127 @@
#include "../bindings/ZigGlobalObject.h"
#include "JavaScriptCore/JSGlobalObject.h"
#include "JavaScriptCore/ObjectConstructor.h"
+#include "simdutf.h"
namespace Zig {
using namespace WebCore;
using namespace JSC;
+// TODO: Add DOMJIT fast path
+JSC_DEFINE_HOST_FUNCTION(jsBufferConstructorFunction_isUtf8,
+ (JSC::JSGlobalObject * lexicalGlobalObject,
+ JSC::CallFrame *callframe)) {
+ auto throwScope = DECLARE_THROW_SCOPE(lexicalGlobalObject->vm());
+
+ auto buffer = callframe->argument(0);
+ auto *bufferView = JSC::jsDynamicCast<JSC::JSArrayBufferView *>(buffer);
+ const char *ptr = nullptr;
+ size_t byteLength = 0;
+ if (bufferView) {
+ if (UNLIKELY(bufferView->isDetached())) {
+ throwTypeError(lexicalGlobalObject, throwScope,
+ "ArrayBufferView is detached"_s);
+ return JSValue::encode({});
+ }
+
+ byteLength = bufferView->byteLength();
+
+ if (byteLength == 0) {
+ return JSValue::encode(jsBoolean(true));
+ }
+
+ ptr = reinterpret_cast<const char *>(bufferView->vector());
+ } else if (auto *arrayBuffer =
+ JSC::jsDynamicCast<JSC::JSArrayBuffer *>(buffer)) {
+ auto *impl = arrayBuffer->impl();
+
+ if (!impl) {
+ return JSValue::encode(jsBoolean(true));
+ }
+
+ if (UNLIKELY(impl->isDetached())) {
+ throwTypeError(lexicalGlobalObject, throwScope,
+ "ArrayBuffer is detached"_s);
+ return JSValue::encode({});
+ }
+
+ byteLength = impl->byteLength();
+
+ if (byteLength == 0) {
+ return JSValue::encode(jsBoolean(true));
+ }
+
+ ptr = reinterpret_cast<const char *>(impl->data());
+ } else {
+ throwVMError(
+ lexicalGlobalObject, throwScope,
+ createTypeError(lexicalGlobalObject,
+ "First argument must be an ArrayBufferView"_s));
+ return JSValue::encode({});
+ }
+
+ RELEASE_AND_RETURN(throwScope, JSValue::encode(jsBoolean(
+ simdutf::validate_utf8(ptr, byteLength))));
+}
+
+// TODO: Add DOMJIT fast path
+JSC_DEFINE_HOST_FUNCTION(jsBufferConstructorFunction_isAscii,
+ (JSC::JSGlobalObject * lexicalGlobalObject,
+ JSC::CallFrame *callframe)) {
+ auto throwScope = DECLARE_THROW_SCOPE(lexicalGlobalObject->vm());
+
+ auto buffer = callframe->argument(0);
+ auto *bufferView = JSC::jsDynamicCast<JSC::JSArrayBufferView *>(buffer);
+ const char *ptr = nullptr;
+ size_t byteLength = 0;
+ if (bufferView) {
+
+ if (UNLIKELY(bufferView->isDetached())) {
+ throwTypeError(lexicalGlobalObject, throwScope,
+ "ArrayBufferView is detached"_s);
+ return JSValue::encode({});
+ }
+
+ byteLength = bufferView->byteLength();
+
+ if (byteLength == 0) {
+ return JSValue::encode(jsBoolean(true));
+ }
+
+ ptr = reinterpret_cast<const char *>(bufferView->vector());
+ } else if (auto *arrayBuffer =
+ JSC::jsDynamicCast<JSC::JSArrayBuffer *>(buffer)) {
+ auto *impl = arrayBuffer->impl();
+ if (UNLIKELY(impl->isDetached())) {
+ throwTypeError(lexicalGlobalObject, throwScope,
+ "ArrayBuffer is detached"_s);
+ return JSValue::encode({});
+ }
+
+ if (!impl) {
+ return JSValue::encode(jsBoolean(true));
+ }
+
+ byteLength = impl->byteLength();
+
+ if (byteLength == 0) {
+ return JSValue::encode(jsBoolean(true));
+ }
+
+ ptr = reinterpret_cast<const char *>(impl->data());
+ } else {
+ throwVMError(
+ lexicalGlobalObject, throwScope,
+ createTypeError(lexicalGlobalObject,
+ "First argument must be an ArrayBufferView"_s));
+ return JSValue::encode({});
+ }
+
+ RELEASE_AND_RETURN(
+ throwScope,
+ JSValue::encode(jsBoolean(simdutf::validate_ascii(ptr, byteLength))));
+}
+
JSC_DEFINE_HOST_FUNCTION(jsFunctionNotImplemented,
(JSGlobalObject * globalObject,
CallFrame *callFrame)) {
@@ -106,6 +222,20 @@ inline void generateBufferSourceCode(JSC::JSGlobalObject *lexicalGlobalObject,
exportProperty(JSC::Identifier::fromString(vm, "resolveObjectURL"_s),
resolveObjectURL);
+ exportProperty(JSC::Identifier::fromString(vm, "isAscii"_s),
+ JSC::JSFunction::create(vm, globalObject, 1, "isAscii"_s,
+ jsBufferConstructorFunction_isAscii,
+ ImplementationVisibility::Public,
+ NoIntrinsic,
+ jsBufferConstructorFunction_isUtf8));
+
+ exportProperty(JSC::Identifier::fromString(vm, "isUtf8"_s),
+ JSC::JSFunction::create(vm, globalObject, 1, "isUtf8"_s,
+ jsBufferConstructorFunction_isUtf8,
+ ImplementationVisibility::Public,
+ NoIntrinsic,
+ jsBufferConstructorFunction_isUtf8));
+
exportNames.append(vm.propertyNames->defaultKeyword);
exportValues.append(defaultObject);
}