diff options
Diffstat (limited to 'src/bun.js/modules/NodeBufferModule.h')
-rw-r--r-- | src/bun.js/modules/NodeBufferModule.h | 213 |
1 files changed, 213 insertions, 0 deletions
diff --git a/src/bun.js/modules/NodeBufferModule.h b/src/bun.js/modules/NodeBufferModule.h new file mode 100644 index 000000000..5c6acd48e --- /dev/null +++ b/src/bun.js/modules/NodeBufferModule.h @@ -0,0 +1,213 @@ +#include "../bindings/JSBuffer.h" +#include "_NativeModule.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)) { + VM &vm = globalObject->vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + + throwException(globalObject, scope, + createError(globalObject, "Not implemented"_s)); + return JSValue::encode(jsUndefined()); +} + +DEFINE_NATIVE_MODULE(NodeBuffer) { + INIT_NATIVE_MODULE(12); + + put(JSC::Identifier::fromString(vm, "Buffer"_s), + globalObject->JSBufferConstructor()); + + auto *slowBuffer = JSC::JSFunction::create( + vm, globalObject, 0, "SlowBuffer"_s, WebCore::constructSlowBuffer, + ImplementationVisibility::Public, NoIntrinsic, + WebCore::constructSlowBuffer); + slowBuffer->putDirect( + vm, vm.propertyNames->prototype, globalObject->JSBufferPrototype(), + JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::DontEnum | + JSC::PropertyAttribute::DontDelete); + put(JSC::Identifier::fromString(vm, "SlowBuffer"_s), slowBuffer); + auto blobIdent = JSC::Identifier::fromString(vm, "Blob"_s); + + JSValue blobValue = + lexicalGlobalObject->get(globalObject, PropertyName(blobIdent)); + put(blobIdent, blobValue); + + // TODO: implement File + put(JSC::Identifier::fromString(vm, "File"_s), blobValue); + + put(JSC::Identifier::fromString(vm, "INSPECT_MAX_BYTES"_s), + JSC::jsNumber(50)); + + put(JSC::Identifier::fromString(vm, "kMaxLength"_s), + JSC::jsNumber(4294967296LL)); + + put(JSC::Identifier::fromString(vm, "kStringMaxLength"_s), + JSC::jsNumber(536870888)); + + JSC::JSObject *constants = JSC::constructEmptyObject( + lexicalGlobalObject, globalObject->objectPrototype(), 2); + constants->putDirect(vm, JSC::Identifier::fromString(vm, "MAX_LENGTH"_s), + JSC::jsNumber(4294967296LL)); + constants->putDirect(vm, + JSC::Identifier::fromString(vm, "MAX_STRING_LENGTH"_s), + JSC::jsNumber(536870888)); + + put(JSC::Identifier::fromString(vm, "constants"_s), constants); + + JSC::Identifier atobI = JSC::Identifier::fromString(vm, "atob"_s); + JSC::JSValue atobV = + lexicalGlobalObject->get(globalObject, PropertyName(atobI)); + + JSC::Identifier btoaI = JSC::Identifier::fromString(vm, "btoa"_s); + JSC::JSValue btoaV = + lexicalGlobalObject->get(globalObject, PropertyName(btoaI)); + + put(atobI, atobV); + put(btoaI, btoaV); + + auto *transcode = InternalFunction::createFunctionThatMasqueradesAsUndefined( + vm, globalObject, 1, "transcode"_s, jsFunctionNotImplemented); + + put(JSC::Identifier::fromString(vm, "transcode"_s), transcode); + + auto *resolveObjectURL = + InternalFunction::createFunctionThatMasqueradesAsUndefined( + vm, globalObject, 1, "resolveObjectURL"_s, jsFunctionNotImplemented); + + put(JSC::Identifier::fromString(vm, "resolveObjectURL"_s), resolveObjectURL); + + put(JSC::Identifier::fromString(vm, "isAscii"_s), + JSC::JSFunction::create(vm, globalObject, 1, "isAscii"_s, + jsBufferConstructorFunction_isAscii, + ImplementationVisibility::Public, NoIntrinsic, + jsBufferConstructorFunction_isUtf8)); + + put(JSC::Identifier::fromString(vm, "isUtf8"_s), + JSC::JSFunction::create(vm, globalObject, 1, "isUtf8"_s, + jsBufferConstructorFunction_isUtf8, + ImplementationVisibility::Public, NoIntrinsic, + jsBufferConstructorFunction_isUtf8)); +} + +} // namespace Zig |