feat(node/net): add SocketAddress (in C++)

This commit is contained in:
Don Isaac
2025-02-17 17:59:34 -08:00
parent b4f34b03d6
commit b4eb9ed3ff
13 changed files with 577 additions and 43 deletions

View File

@@ -1,63 +1,255 @@
#include "JSSocketAddress.h"
#include "ZigGlobalObject.h"
#include "BunClientData.h"
#include "JavaScriptCore/JSCast.h"
#include "JavaScriptCore/JSObjectInlines.h"
#include "JavaScriptCore/ObjectConstructor.h"
#include "JavaScriptCore/JSCast.h"
#include "ZigGlobalObject.h"
#include "JavaScriptCore/JSCell.h"
#include "ErrorCode.h"
#include "JSSocketAddress.h"
#include "JSSocketAddressConstructor.h"
#include "JSSocketAddressPrototype.h"
using namespace JSC;
namespace Bun {
namespace JSSocketAddress {
// Using a structure with inlined offsets should be more lightweight than a class.
Structure* createStructure(VM& vm, JSGlobalObject* globalObject)
static constexpr PropertyOffset addressOffset = 0;
static constexpr PropertyOffset addressFamilyOffset = 1;
static constexpr PropertyOffset portOffset = 2;
static constexpr PropertyOffset flowLabelOffset = 3;
inline JSC::JSString* JSSocketAddress::address() const
{
JSC::Structure* structure = globalObject->structureCache().emptyObjectStructureForPrototype(
auto value = this->getDirect(addressOffset);
JSC::JSString* str = jsCast<JSC::JSString*>(value);
return str;
// return value.getString(globalObject());
}
inline uint8_t JSSocketAddress::addressFamily() const
{
uint32_t af = this->getDirect(addressFamilyOffset).asUInt32();
ASSERT(af == AF_INET6 || af == AF_INET);
return af;
}
inline in_port_t JSSocketAddress::port() const
{
auto port = this->getDirect(portOffset).asUInt32();
ASSERT(port <= 0xFFFF);
return port;
}
inline uint32_t JSSocketAddress::flowLabel() const
{
return this->getDirect(flowLabelOffset).asUInt32();
}
// =============================================================================
JSSocketAddress* JSSocketAddress::create(JSC::VM& vm,
JSC::JSGlobalObject* globalObject,
JSC::Structure* structure,
JSC::JSString* address,
in_port_t port,
bool isIPv6)
{
return create(vm, globalObject, structure, address, port, isIPv6 ? AF_INET6 : AF_INET, 0);
}
JSSocketAddress* JSSocketAddress::create(JSC::VM& vm,
JSC::JSGlobalObject* globalObject,
JSC::Structure* structure,
JSC::JSString* address,
in_port_t port,
uint8_t addressFamily, // AF_INET | AF_INET6
uint32_t flowLabel)
{
static const NeverDestroyed<String> IPv4 = MAKE_STATIC_STRING_IMPL("IPv4");
static const NeverDestroyed<String> IPv6 = MAKE_STATIC_STRING_IMPL("IPv6");
auto scope = DECLARE_THROW_SCOPE(vm);
address_t addr;
const char* address_bytes = address->value(globalObject)->ascii().data();
switch (inet_pton(addressFamily, address_bytes, &addr)) {
case 1: // ok
break;
case 0: // invalid address
// node throws ERR_INVALID_ADDRESS
Bun::throwError(globalObject, scope, ErrorCode::ERR_INVALID_IP_ADDRESS, "Invalid address"_s);
return nullptr;
case -1: // syserr
// TODO: how to handle system errors?
Bun::throwError(globalObject, scope, ErrorCode::ERR_INVALID_IP_ADDRESS, "Invalid address"_s);
return nullptr;
default:
__builtin_unreachable();
}
auto* af_str = jsString(vm, addressFamily == AF_INET6 ? IPv6 : IPv4);
JSSocketAddress* ptr = new (NotNull, JSC::allocateCell<JSSocketAddress>(vm)) JSSocketAddress(vm, structure);
ptr->m_address = addr;
ptr->finishCreation(vm);
ptr->putDirectOffset(vm, flowLabelOffset, jsNumber(flowLabel));
ptr->putDirectOffset(vm, addressOffset, address);
ptr->putDirectOffset(vm, addressFamilyOffset, af_str);
ptr->putDirectOffset(vm, portOffset, jsNumber(port));
return ptr;
}
void JSSocketAddress::destroy(JSC::JSCell* cell)
{
auto* thisObject = jsCast<JSSocketAddress*>(cell);
thisObject->~JSSocketAddress();
}
JSC::GCClient::IsoSubspace* JSSocketAddress::subspaceForImpl(JSC::VM& vm)
{
// return WebCore::subspaceForImpl<JSSocketAddress, WebCore::UseCustomHeapCellType::No>(
// vm,
// [](auto& spaces) { return spaces.m_clientSubspaceForJSSocketAddress.get(); },
// [](auto& spaces, auto&& space) { spaces.m_clientSubspaceForJSSocketAddress = std::forward<decltype(space)>(space); },
// [](auto& spaces) { return spaces.m_subspaceForJSSocketAddress.get(); },
// [](auto& spaces, auto&& space) { spaces.m_subspaceForJSSocketAddress
// = std::forward<decltype(space)>(space); });
return &vm.plainObjectSpace();
}
JSC::JSObject* JSSocketAddress::createPrototype(JSC::VM& vm, JSC::JSGlobalObject* globalObject)
{
auto* structure = JSSocketAddressPrototype::createStructure(vm, globalObject, globalObject->objectPrototype());
structure->setMayBePrototype(true);
return JSSocketAddressPrototype::create(vm, globalObject, structure);
}
JSC::Structure* JSSocketAddress::createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype)
{
auto* structure = JSC::Structure::create(vm,
globalObject,
globalObject->objectPrototype(),
3);
prototype,
JSC::TypeInfo(JSC::ObjectType, StructureFlags),
info(),
NonArray,
4);
JSC::PropertyOffset offset;
// TODO: add identifiers to CommonIdentifiers?
structure = structure->addPropertyTransition(
vm,
structure,
JSC::Identifier::fromString(vm, "address"_s),
0,
static_cast<unsigned>(PropertyAttribute::ReadOnly | PropertyAttribute::DontDelete),
offset);
ASSERT(offset == addressOffset);
structure = structure->addPropertyTransition(
vm,
structure,
JSC::Identifier::fromString(vm, "family"_s),
0,
static_cast<unsigned>(PropertyAttribute::ReadOnly | PropertyAttribute::DontDelete),
offset);
ASSERT(offset == addressFamilyOffset);
structure = structure->addPropertyTransition(
vm,
structure,
JSC::Identifier::fromString(vm, "port"_s),
0,
static_cast<unsigned>(PropertyAttribute::ReadOnly | PropertyAttribute::DontDelete),
offset);
ASSERT(offset == portOffset);
structure->addPropertyTransition(
vm,
structure,
JSC::Identifier::fromString(vm, "flowLabel"_s),
static_cast<unsigned>(PropertyAttribute::ReadOnly | PropertyAttribute::DontDelete),
offset);
ASSERT(offset == flowLabelOffset);
return structure;
}
} // namespace JSSocketAddress
JSSocketAddress::~JSSocketAddress()
{
}
void JSSocketAddress::finishCreation(JSC::VM& vm)
{
Base::finishCreation(vm);
ASSERT(inherits(info()));
// initializeProperties(vm, globalObject, prototype);
// TODO: idk how to get a globalobject here
// this->m_address.initLater([](const LazyProperty<JSSocketAddress, address_t>::Initializer& init) {
// auto af = init->owner->addressFamily();
// auto address = init->owner->address();
// address.value()
// address.value(init->vm.)
// });
// ASSERT(inherits(info()));
// reifyStaticProperties(vm, JSSocketAddress::info(),
// JSSocketAddressPrototypeTableValues, *this);
// JSC_TO_STRING_TAG_WITHOUT_TRANSITION();
}
// void JSSocketAddress::initializeProperties(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSObject* prototype)
const ClassInfo JSSocketAddress::s_info
= {
"SocketAddress"_s,
&Base::s_info,
nullptr,
nullptr,
CREATE_METHOD_TABLE(JSSocketAddress)
};
template<typename Visitor>
void JSSocketAddress::visitChildrenImpl(JSCell* cell, Visitor& visitor)
{
JSSocketAddress* thisObject = jsCast<JSSocketAddress*>(cell);
ASSERT_GC_OBJECT_INHERITS(thisObject, info());
Base::visitChildren(thisObject, visitor);
thisObject->visitAdditionalChildren<Visitor>(visitor);
}
DEFINE_VISIT_CHILDREN(JSSocketAddress);
template<typename Visitor>
void JSSocketAddress::visitAdditionalChildren(Visitor& visitor)
{
JSSocketAddress* thisObject = this;
ASSERT_GC_OBJECT_INHERITS(thisObject, info());
// TODO: do properties added via putDirectOffset need visiting?
// visitor.append(thisObject->m_address);
}
DEFINE_VISIT_ADDITIONAL_CHILDREN(JSSocketAddress);
template<typename Visitor>
void JSSocketAddress::visitOutputConstraintsImpl(JSCell* cell, Visitor& visitor)
{
auto* thisObject = jsCast<JSSocketAddress*>(cell);
ASSERT_GC_OBJECT_INHERITS(thisObject, info());
Base::visitOutputConstraints(thisObject, visitor);
thisObject->visitAdditionalChildren(visitor);
}
DEFINE_VISIT_OUTPUT_CONSTRAINTS(JSSocketAddress);
} // namespace Bun
extern "C" JSObject* JSSocketAddress__create(JSGlobalObject* globalObject, JSString* value, int32_t port, bool isIPv6)
{
static const NeverDestroyed<String> IPv4 = MAKE_STATIC_STRING_IMPL("IPv4");
static const NeverDestroyed<String> IPv6 = MAKE_STATIC_STRING_IMPL("IPv6");
VM& vm = globalObject->vm();
auto* global = jsCast<Zig::GlobalObject*>(globalObject);
auto scope = DECLARE_THROW_SCOPE(globalObject->vm());
JSObject* thisObject = constructEmptyObject(vm, global->JSSocketAddressStructure());
thisObject->putDirectOffset(vm, 0, value);
thisObject->putDirectOffset(vm, 1, isIPv6 ? jsString(vm, IPv6) : jsString(vm, IPv4));
thisObject->putDirectOffset(vm, 2, jsNumber(port));
if (UNLIKELY(port < 0 || port > std::numeric_limits<in_port_t>::max())) {
throwRangeError(global, scope, "Port out of range"_s);
return nullptr;
}
return thisObject;
return Bun::JSSocketAddress::create(globalObject->vm(), globalObject, global->JSSocketAddressStructure(), value, port, isIPv6 ? AF_INET6 : AF_INET, 0);
}

View File

@@ -3,14 +3,127 @@
#include "root.h"
#include "JavaScriptCore/JSObjectInlines.h"
extern "C" {
#if OS(WINDOWS)
#include <WinSock2.h> // in_addr - https://learn.microsoft.com/en-us/windows/win32/api/winsock2/
#include <in6addr.h> // in6_addr - https://learn.microsoft.com/en-us/windows/win32/api/ws2def/
#include <ws2tcpip.h> // inet_ntop, inet_pton - https://learn.microsoft.com/en-us/windows/win32/api/ws2tcpip/
#include <Ws2def.h> // AF_INET, AF_INET6
typedef union address {
struct in_addr ipv4;
struct in6_addr ipv6;
} address_t;
#define in_port_t USHORT
#else
#include <netinet/in.h> // in_addr, in6_addr
#include <arpa/inet.h> // inet_pton, inet_ntop
typedef union address {
struct in_addr ipv4;
struct in6_addr ipv6;
} address_t;
#endif
}
using namespace JSC;
namespace Bun {
namespace JSSocketAddress {
Structure* createStructure(VM& vm, JSGlobalObject* globalObject);
/// `SocketAddress` is written in Zig
// struct SocketAddress;
// class JSSocketAddress : public JSC::JSDestructibleObject {
// public:
// using Base = JSC::JSDestructibleObject;
// using DOMWrapped = SocketAddress;
// static J Structure* createStructure(VM& vm, JSGlobalObject* globalObject);
// }; // class JSSocketAddress
class JSSocketAddress final : public JSC::JSObject {
public:
using Base = JSC::JSObject;
static constexpr unsigned StructureFlags = Base::StructureFlags;
// static constexpr JSC::DestructionMode needsDestruction = NeedsDestruction;
/// Native SocketAddress used in/by Zig code.
// SocketAddress* m_sockaddr { nullptr };
// SocketAddress* m_address
// uint8_t m_address[16];
// LazyProperty<JSSocketAddress, address_t> m_address;
address_t m_address;
JSC::JSString* address() const;
uint8_t addressFamily() const;
in_port_t port() const;
uint32_t flowLabel() const;
/// Returns `nullptr` if the address is invalid. A js exception will be thrown.
static JSSocketAddress* create(JSC::VM& vm,
JSC::JSGlobalObject* globalObject,
JSC::Structure* structure,
JSC::JSString* address,
in_port_t port,
bool isIPv6);
/// Returns `nullptr` if the address is invalid. A js exception will be thrown.
static JSSocketAddress* create(JSC::VM& vm,
JSC::JSGlobalObject* globalObject,
JSC::Structure* structure,
JSC::JSString* address,
in_port_t port,
uint8_t addressFamily, // AF_INET | AF_INET6
uint32_t flowLabel);
static void destroy(JSC::JSCell*);
template<typename, JSC::SubspaceAccess mode> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm)
{
if constexpr (mode == JSC::SubspaceAccess::Concurrently)
return nullptr;
return subspaceForImpl(vm);
}
static JSC::GCClient::IsoSubspace* subspaceForImpl(JSC::VM& vm);
static JSObject* createPrototype(JSC::VM& vm, JSC::JSGlobalObject* globalObject);
// static JSObject* createConstructor(JSC::VM& vm, JSC::JSGlobalObject* globalObject);
static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype);
// {
// return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), info());
// }
// void detach()
// {
// this->sockaddr
// }
// static void analyzeHeap(JSCell*, JSC::HeapAnalyzer&);
// static ptrdiff_t offsetOfWrapped() { return OBJECT_OFFSETOF(JSSocketAddress, m_ctx); }
// /**
// * Estimated size of the object from Zig including the JS wrapper.
// */
// static size_t estimatedSize(JSC::JSCell* cell, JSC::VM& vm);
// /**
// * Memory cost of the object from Zig, without necessarily having a JS wrapper alive.
// */
// static size_t memoryCost(void* ptr);
JSSocketAddress(JSC::VM& vm, JSC::Structure* structure)
: Base(vm, structure)
{
}
~JSSocketAddress();
void finishCreation(JSC::VM&);
DECLARE_EXPORT_INFO;
DECLARE_VISIT_CHILDREN;
template<typename Visitor> void visitAdditionalChildren(Visitor&);
DECLARE_VISIT_OUTPUT_CONSTRAINTS;
}; // class JSSocketAddress
} // namespace JSSocketAddress
} // namespace Bun
extern "C" JSObject* JSSocketAddress__create(JSGlobalObject* globalObject, JSString* value, int port, bool isIPv6);

View File

@@ -0,0 +1,105 @@
#include "JSSocketAddressConstructor.h"
#include "JSSocketAddress.h"
#include "JavaScriptCore/Lookup.h"
#include "NodeValidator.h"
#include "ZigGlobalObject.h"
using namespace JSC;
namespace Bun {
const ClassInfo JSSocketAddressConstructor::s_info = {
"SocketAddressConstructor"_s,
&Base::s_info,
nullptr,
nullptr,
CREATE_METHOD_TABLE(JSSocketAddressConstructor)
};
// todo
// static const JSSocketAddressConstructorTableValues[] = {
// { "isSocketAddress"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), JSC::NoIntrinsic, { JSC::HashTableValue::NativeFunctionType, jsScketAddressConstructorFunction_isSocketAddress, 1 },
// { "parse"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), JSC::NoIntrinsic, { JSC::HashTableValue::NativeFunctionType, jsScketAddressConstructorFunction_parse, 1 } },
// };
// void initializeProperties(JSC::VM& vm, JSC::JSGlobalObject* global, JSSocketAddressPrototype* prototype)
// {
// }
JSSocketAddressConstructor* JSSocketAddressConstructor::create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure)
{
JSSocketAddressConstructor* ptr = new (NotNull, JSC::allocateCell<JSSocketAddressConstructor>(vm)) JSSocketAddressConstructor(vm, structure);
ptr->finishCreation(vm);
return ptr;
}
// new SocketAddress(AF, address, port?, flowLabel?)
JSC::EncodedJSValue JSSocketAddressConstructor::construct(JSC::JSGlobalObject* globalObject, JSC::CallFrame* callFrame)
{
Zig::GlobalObject* global = reinterpret_cast<Zig::GlobalObject*>(globalObject);
static const NeverDestroyed<String> port_name = MAKE_STATIC_STRING_IMPL("port");
auto& vm = global->vm();
auto scope = DECLARE_THROW_SCOPE(vm);
JSValue af_arg = callFrame->argument(0);
JSValue address_arg = callFrame->argument(1);
JSValue port_arg = callFrame->argument(2);
JSValue flowLabel_arg = callFrame->argument(3);
// addressFamily
V::validateUint32(scope, global, af_arg, "addressFamily"_s, jsBoolean(false));
RETURN_IF_EXCEPTION(scope, {});
uint32_t af = af_arg.toUInt32(global);
if (UNLIKELY(af != AF_INET && af != AF_INET6)) {
throwTypeError(global, scope, "Invalid address family"_s);
return encodedJSUndefined();
}
// address
V::validateString(scope, global, address_arg, "address"_s);
RETURN_IF_EXCEPTION(scope, encodedJSUndefined());
JSC::JSString* address = jsCast<JSC::JSString*>(address_arg);
// port
in_port_t port = 0;
if (LIKELY(!port_arg.isUndefined())) {
V::validatePort(scope, global, port_arg, jsString(vm, port_name), true);
RETURN_IF_EXCEPTION(scope, encodedJSUndefined());
uint32_t port32 = port_arg.toUInt32(global);
ASSERT(port32 <= std::numeric_limits<in_port_t>().max());
port = static_cast<in_port_t>(port32);
}
// flowLabel
uint32_t flowLabel = 0;
if (UNLIKELY(!flowLabel_arg.isUndefined())) {
V::validateUint32(scope, global, flowLabel_arg, "flowlabel"_s, jsBoolean(false));
RETURN_IF_EXCEPTION(scope, encodedJSUndefined());
flowLabel = flowLabel_arg.toUInt32(global);
}
auto* structure = global->JSSocketAddressStructure();
auto* sockaddr = JSSocketAddress::create(vm, global, structure, address, port, af, flowLabel);
// throws if inet_pton fails
RETURN_IF_EXCEPTION(scope, encodedJSUndefined());
return JSValue::encode(sockaddr);
}
JSC::EncodedJSValue JSSocketAddressConstructor::call(JSC::JSGlobalObject* global, JSC::CallFrame* callFrame)
{
auto scope = DECLARE_THROW_SCOPE(global->vm());
throwTypeError(global, scope, "Cannot construct SocketAddress"_s);
return encodedJSUndefined();
}
JSSocketAddressConstructor::JSSocketAddressConstructor(JSC::VM& vm, JSC::Structure* structure)
: Base(vm, structure, call, construct)
{
}
// TODO: reifyStaticProperties
// void JSSocketAddressConstructor::finishCreation(JSC::VM& vm, JSC::JSGlobalObject* global, JSSocketAddressPrototype* prototype)
// {
// Base::finishCreation(vm);
// reifyStaticProperties(vm, JSSocketAddress::info(), JSSocketAddressConstructorTableValues, *this);
// }
} // namespace Bun

View File

@@ -0,0 +1,49 @@
#pragma once
#include "root.h"
#include "JSSocketAddressPrototype.h"
namespace Bun {
class JSSocketAddressConstructor final : public JSC::InternalFunction {
public:
using Base = JSC::InternalFunction;
static JSSocketAddressConstructor* create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure);
static constexpr unsigned StructureFlags = Base::StructureFlags;
static constexpr JSC::DestructionMode needsDestruction = JSC::DoesNotNeedDestruction;
static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSObject* prototype)
{
return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::InternalFunctionType, StructureFlags), info());
}
template<typename, JSC::SubspaceAccess mode> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm)
{
if constexpr (mode == JSC::SubspaceAccess::Concurrently)
return nullptr;
return &vm.internalFunctionSpace();
// TODO: use separate subspace??
// return WebCore::subspaceForImpl<JSSocketAddressConstructor, WebCore::UseCustomHeapCellType::No>(
// vm,
// [](auto& spaces) { return spaces.m_clientSubspaceForBunClassConstructor.get(); },
// [](auto& spaces, auto&& space) { spaces.m_clientSubspaceForBunClassConstructor = std::forward<decltype(space)>(space); },
// [](auto& spaces) { return spaces.m_subspaceForBunClassConstructor.get(); },
// [](auto& spaces, auto&& space) { spaces.m_subspaceForBunClassConstructor = std::forward<decltype(space)>(space); });
}
// void initializeProperties(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSSocketAddressPrototype* prototype);
// Must be defined for each specialization class.
static JSC::EncodedJSValue JSC_HOST_CALL_ATTRIBUTES construct(JSC::JSGlobalObject*, JSC::CallFrame*);
static JSC::EncodedJSValue JSC_HOST_CALL_ATTRIBUTES call(JSC::JSGlobalObject*, JSC::CallFrame*);
DECLARE_EXPORT_INFO;
protected:
JSSocketAddressConstructor(JSC::VM& vm, JSC::Structure* structure);
DECLARE_DEFAULT_FINISH_CREATION;
};
} // namespace Bun

View File

@@ -0,0 +1,13 @@
#include "JSSocketAddressPrototype.h"
// const ClassInfo JSX509CertificatePrototype::s_info = { "X509Certificate"_s,
// &Base::s_info, nullptr, nullptr,
// CREATE_METHOD_TABLE(JSX509CertificatePrototype) };
using namespace JSC;
namespace Bun {
const ClassInfo JSSocketAddressPrototype::s_info = { "SocketAddress"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSSocketAddressPrototype) };
} // namespace Bun

View File

@@ -0,0 +1,42 @@
#pragma once
#include "root.h"
namespace Bun {
class JSSocketAddressPrototype final : public JSC::JSNonFinalObject {
public:
using Base = JSC::JSNonFinalObject;
static JSSocketAddressPrototype* create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure)
{
JSSocketAddressPrototype* ptr = new (NotNull, JSC::allocateCell<JSSocketAddressPrototype>(vm)) JSSocketAddressPrototype(vm, globalObject, structure);
ptr->finishCreation(vm);
return ptr;
}
DECLARE_INFO;
template<typename CellType, JSC::SubspaceAccess>
static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm)
{
STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(JSSocketAddressPrototype, Base);
return &vm.plainObjectSpace();
}
static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype)
{
return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), info());
}
protected:
JSSocketAddressPrototype(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure)
: Base(vm, structure)
{
}
// void finishCreation(JSC::VM& vm, JSC::JSGlobalObject* globalObject)
// void finishCreation(JSC::VM& vm) { Base::finishCreation(vm); }
DECLARE_DEFAULT_FINISH_CREATION;
};
} // namespace Bun

View File

@@ -254,7 +254,13 @@ JSC_DEFINE_HOST_FUNCTION(jsFunction_validatePort, (JSC::JSGlobalObject * globalO
if (allowZero.isUndefined()) allowZero = jsBoolean(true);
auto allowZero_b = allowZero.toBoolean(globalObject);
if (!port.isNumber() && !port.isString()) return Bun::ERR::SOCKET_BAD_PORT(scope, globalObject, name, port, allowZero_b);
return V::validatePort(scope, globalObject, port, name, allowZero_b);
}
JSC::EncodedJSValue V::validatePort(JSC::ThrowScope& scope, JSC::JSGlobalObject* globalObject, JSValue port, JSValue name, bool allowZero)
{
if (!port.isNumber() && !port.isString()) return Bun::ERR::SOCKET_BAD_PORT(scope, globalObject, name, port, allowZero);
if (port.isString()) {
auto port_str = port.getString(globalObject);
@@ -290,19 +296,19 @@ JSC_DEFINE_HOST_FUNCTION(jsFunction_validatePort, (JSC::JSGlobalObject * globalO
return false;
});
if (trimmed.length() == 0) {
return Bun::ERR::SOCKET_BAD_PORT(scope, globalObject, name, port, allowZero_b);
return Bun::ERR::SOCKET_BAD_PORT(scope, globalObject, name, port, allowZero);
}
}
auto port_num = port.toNumber(globalObject);
RETURN_IF_EXCEPTION(scope, {});
if (std::isnan(port_num)) return Bun::ERR::SOCKET_BAD_PORT(scope, globalObject, name, port, allowZero_b);
if (std::isinf(port_num)) return Bun::ERR::SOCKET_BAD_PORT(scope, globalObject, name, port, allowZero_b);
if (std::fmod(port_num, 1.0) != 0) return Bun::ERR::SOCKET_BAD_PORT(scope, globalObject, name, port, allowZero_b);
if (port_num < 0) return Bun::ERR::SOCKET_BAD_PORT(scope, globalObject, name, port, allowZero_b);
if (port_num > 0xffff) return Bun::ERR::SOCKET_BAD_PORT(scope, globalObject, name, port, allowZero_b);
if (port_num == 0 && !allowZero_b) return Bun::ERR::SOCKET_BAD_PORT(scope, globalObject, name, port, allowZero_b);
if (std::isnan(port_num)) return Bun::ERR::SOCKET_BAD_PORT(scope, globalObject, name, port, allowZero);
if (std::isinf(port_num)) return Bun::ERR::SOCKET_BAD_PORT(scope, globalObject, name, port, allowZero);
if (std::fmod(port_num, 1.0) != 0) return Bun::ERR::SOCKET_BAD_PORT(scope, globalObject, name, port, allowZero);
if (port_num < 0) return Bun::ERR::SOCKET_BAD_PORT(scope, globalObject, name, port, allowZero);
if (port_num > 0xffff) return Bun::ERR::SOCKET_BAD_PORT(scope, globalObject, name, port, allowZero);
if (port_num == 0 && !allowZero) return Bun::ERR::SOCKET_BAD_PORT(scope, globalObject, name, port, allowZero);
return JSValue::encode(port);
}

View File

@@ -38,6 +38,7 @@ JSC::EncodedJSValue validateArray(JSC::ThrowScope& scope, JSC::JSGlobalObject* g
JSC::EncodedJSValue validateArray(JSC::ThrowScope& scope, JSC::JSGlobalObject* globalObject, JSValue value, ASCIILiteral name, JSValue minLength);
JSC::EncodedJSValue validateUint32(JSC::ThrowScope& scope, JSC::JSGlobalObject* globalObject, JSValue value, JSValue name, JSValue positive);
JSC::EncodedJSValue validateUint32(JSC::ThrowScope& scope, JSC::JSGlobalObject* globalObject, JSValue value, ASCIILiteral name, JSValue positive);
JSC::EncodedJSValue validatePort(JSC::ThrowScope& scope, JSC::JSGlobalObject* globalObject, JSValue port, JSC::JSValue name, bool allowZero);
}

View File

@@ -115,6 +115,8 @@
#include "JSReadableStreamDefaultReader.h"
#include "JSSink.h"
#include "JSSocketAddress.h"
#include "JSSocketAddressConstructor.h"
#include "JSSocketAddressPrototype.h"
#include "JSSQLStatement.h"
#include "JSStringDecoder.h"
#include "JSTextEncoder.h"
@@ -2914,11 +2916,6 @@ void GlobalObject::finishCreation(VM& vm)
init.vm, reinterpret_cast<Zig::GlobalObject*>(init.owner)));
});
m_JSSocketAddressStructure.initLater(
[](const Initializer<Structure>& init) {
init.set(JSSocketAddress::createStructure(init.vm, init.owner));
});
m_errorConstructorPrepareStackTraceInternalValue.initLater(
[](const Initializer<JSFunction>& init) {
init.set(JSFunction::create(init.vm, init.owner, 2, "ErrorPrepareStackTrace"_s, jsFunctionDefaultErrorPrepareStackTrace, ImplementationVisibility::Public));
@@ -3286,6 +3283,17 @@ void GlobalObject::finishCreation(VM& vm)
init.setConstructor(constructor);
});
m_JSSocketAddressClassStructure.initLater(
[](LazyClassStructure::Initializer& init) {
auto* prototype = JSSocketAddressPrototype::create(init.vm, init.global, JSSocketAddressPrototype::createStructure(init.vm, init.global, init.global->objectPrototype()));
auto* structure = JSSocketAddress::createStructure(init.vm, init.global, prototype);
auto* constructor = JSSocketAddressConstructor::create(
init.vm, init.global, JSSocketAddressConstructor::createStructure(init.vm, init.global, init.global->functionPrototype()));
init.setPrototype(prototype);
init.setStructure(structure);
init.setConstructor(constructor);
});
m_JSBufferClassStructure.initLater(
[](LazyClassStructure::Initializer& init) {
auto prototype = WebCore::createBufferPrototype(init.vm, init.global);
@@ -3890,8 +3898,8 @@ void GlobalObject::visitChildrenImpl(JSCell* cell, Visitor& visitor)
thisObject->m_JSHTTPSResponseControllerPrototype.visit(visitor);
thisObject->m_JSHTTPSResponseSinkClassStructure.visit(visitor);
thisObject->m_JSNetworkSinkClassStructure.visit(visitor);
thisObject->m_JSSocketAddressClassStructure.visit(visitor);
thisObject->m_JSFetchTaskletChunkedRequestControllerPrototype.visit(visitor);
thisObject->m_JSSocketAddressStructure.visit(visitor);
thisObject->m_JSSQLStatementStructure.visit(visitor);
thisObject->m_V8GlobalInternals.visit(visitor);
thisObject->m_JSStringDecoderClassStructure.visit(visitor);

View File

@@ -216,6 +216,10 @@ public:
JSC::JSValue NetworkSinkPrototype() const { return m_JSNetworkSinkClassStructure.prototypeInitializedOnMainThread(this); }
JSC::JSValue JSReadableNetworkSinkControllerPrototype() const { return m_JSFetchTaskletChunkedRequestControllerPrototype.getInitializedOnMainThread(this); }
JSC::Structure* JSSocketAddressStructure() const { return m_JSSocketAddressClassStructure.getInitializedOnMainThread(this); }
JSC::JSObject* JSSocketAdddress() { return m_JSSocketAddressClassStructure.constructorInitializedOnMainThread(this); }
JSC::JSValue JSSocketAddressPrototype() const { return m_JSSocketAddressClassStructure.prototypeInitializedOnMainThread(this); }
JSC::Structure* JSBufferListStructure() const { return m_JSBufferListClassStructure.getInitializedOnMainThread(this); }
JSC::JSObject* JSBufferList() { return m_JSBufferListClassStructure.constructorInitializedOnMainThread(this); }
JSC::JSValue JSBufferListPrototype() const { return m_JSBufferListClassStructure.prototypeInitializedOnMainThread(this); }
@@ -261,8 +265,6 @@ public:
Structure* ImportMetaObjectStructure() const { return m_importMetaObjectStructure.getInitializedOnMainThread(this); }
Structure* AsyncContextFrameStructure() const { return m_asyncBoundFunctionStructure.getInitializedOnMainThread(this); }
Structure* JSSocketAddressStructure() const { return m_JSSocketAddressStructure.getInitializedOnMainThread(this); }
JSWeakMap* vmModuleContextMap() const { return m_vmModuleContextMap.getInitializedOnMainThread(this); }
Structure* NapiExternalStructure() const { return m_NapiExternalStructure.getInitializedOnMainThread(this); }
@@ -531,6 +533,7 @@ public:
LazyClassStructure m_JSHTTPResponseSinkClassStructure;
LazyClassStructure m_JSHTTPSResponseSinkClassStructure;
LazyClassStructure m_JSNetworkSinkClassStructure;
LazyClassStructure m_JSSocketAddressClassStructure;
LazyClassStructure m_JSStringDecoderClassStructure;
LazyClassStructure m_NapiClassStructure;
@@ -575,7 +578,6 @@ public:
LazyProperty<JSGlobalObject, Structure> m_cachedNodeVMGlobalObjectStructure;
LazyProperty<JSGlobalObject, Structure> m_cachedGlobalProxyStructure;
LazyProperty<JSGlobalObject, Structure> m_commonJSModuleObjectStructure;
LazyProperty<JSGlobalObject, Structure> m_JSSocketAddressStructure;
LazyProperty<JSGlobalObject, Structure> m_memoryFootprintStructure;
LazyProperty<JSGlobalObject, JSObject> m_requireFunctionUnbound;
LazyProperty<JSGlobalObject, JSObject> m_requireResolveFunctionUnbound;

View File

@@ -61,6 +61,7 @@ public:
std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForJSS3Bucket;
std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForJSS3File;
std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForJSX509Certificate;
std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForJSSocketAddress;
#include "ZigGeneratedClasses+DOMClientIsoSubspaces.h"
/* --- bun --- */

View File

@@ -61,6 +61,7 @@ public:
std::unique_ptr<IsoSubspace> m_subspaceForJSS3Bucket;
std::unique_ptr<IsoSubspace> m_subspaceForJSS3File;
std::unique_ptr<IsoSubspace> m_subspaceForJSX509Certificate;
std::unique_ptr<IsoSubspace> m_subspaceForJSSocketAddress;
#include "ZigGeneratedClasses+DOMIsoSubspaces.h"
/*-- BUN --*/

View File

@@ -27,6 +27,7 @@ using namespace JSC;
macro(abortSteps) \
macro(addAbortAlgorithmToSignal) \
macro(addEventListener) \
macro(address) \
macro(appendFromJS) \
macro(argv) \
macro(assignToStream) \