Compare commits

...

5 Commits

Author SHA1 Message Date
Jarred Sumner
a9c818df68 Make signal.abort() fast 2024-08-03 19:10:55 -07:00
Jarred Sumner
42fb8405c3 Merge remote-tracking branch 'origin' into jarred/nonnull 2024-08-03 01:43:28 -07:00
Jarred Sumner
d9b199406e Update Worker.cpp 2024-08-03 01:30:09 -07:00
Jarred Sumner
fcebe72044 Update Worker.cpp 2024-08-03 01:23:21 -07:00
Jarred Sumner
efce576072 Add nullability annotations 2024-08-03 01:15:22 -07:00
24 changed files with 664 additions and 571 deletions

View File

@@ -1106,8 +1106,11 @@ if(CMAKE_BUILD_TYPE STREQUAL "Debug")
-Werror=sometimes-uninitialized
-Werror=unused
-Wno-unused-function
-Wno-nullability-completeness
-Werror
-fsanitize=null
)
target_link_libraries(${bun} PRIVATE -fsanitize=null)
else()
target_compile_options(${bun} PUBLIC /Od /Z7)
endif()
@@ -1133,6 +1136,7 @@ elseif(CMAKE_BUILD_TYPE STREQUAL "Release")
-Werror=nonnull
-Werror=move
-Werror=sometimes-uninitialized
-Wno-nullability-completeness
-Werror
)
else()

View File

@@ -101,6 +101,9 @@ struct addrinfo_result {
int error;
};
#define us_internal_ssl_socket_context_r struct us_internal_ssl_socket_context_t *nonnull_arg
#define us_internal_ssl_socket_r struct us_internal_ssl_socket_t *nonnull_arg
extern int Bun__addrinfo_get(struct us_loop_t* loop, const char* host, struct addrinfo_request** ptr);
extern int Bun__addrinfo_set(struct addrinfo_request* ptr, struct us_connecting_socket_t* socket);
extern void Bun__addrinfo_freeRequest(struct addrinfo_request* addrinfo_req, int error);
@@ -110,19 +113,19 @@ extern struct addrinfo_result *Bun__addrinfo_getRequestResult(struct addrinfo_re
/* Loop related */
void us_internal_dispatch_ready_poll(struct us_poll_t *p, int error,
int events);
void us_internal_timer_sweep(struct us_loop_t *loop);
void us_internal_free_closed_sockets(struct us_loop_t *loop);
void us_internal_timer_sweep(us_loop_r loop);
void us_internal_free_closed_sockets(us_loop_r loop);
void us_internal_loop_link(struct us_loop_t *loop,
struct us_socket_context_t *context);
void us_internal_loop_unlink(struct us_loop_t *loop,
struct us_socket_context_t *context);
void us_internal_loop_data_init(struct us_loop_t *loop,
void (*wakeup_cb)(struct us_loop_t *loop),
void (*pre_cb)(struct us_loop_t *loop),
void (*post_cb)(struct us_loop_t *loop));
void us_internal_loop_data_free(struct us_loop_t *loop);
void us_internal_loop_pre(struct us_loop_t *loop);
void us_internal_loop_post(struct us_loop_t *loop);
void (*wakeup_cb)(us_loop_r loop),
void (*pre_cb)(us_loop_r loop),
void (*post_cb)(us_loop_r loop));
void us_internal_loop_data_free(us_loop_r loop);
void us_internal_loop_pre(us_loop_r loop);
void us_internal_loop_post(us_loop_r loop);
/* Asyncs (old) */
struct us_internal_async *us_internal_create_async(struct us_loop_t *loop,
@@ -139,22 +142,22 @@ int us_internal_poll_type(struct us_poll_t *p);
void us_internal_poll_set_type(struct us_poll_t *p, int poll_type);
/* SSL loop data */
void us_internal_init_loop_ssl_data(struct us_loop_t *loop);
void us_internal_free_loop_ssl_data(struct us_loop_t *loop);
void us_internal_init_loop_ssl_data(us_loop_r loop);
void us_internal_free_loop_ssl_data(us_loop_r loop);
/* Socket context related */
void us_internal_socket_context_link_socket(struct us_socket_context_t *context,
struct us_socket_t *s);
void us_internal_socket_context_link_socket(us_socket_context_r context,
us_socket_r s);
void us_internal_socket_context_unlink_socket(int ssl,
struct us_socket_context_t *context, struct us_socket_t *s);
us_socket_context_r context, us_socket_r s);
void us_internal_socket_after_resolve(struct us_connecting_socket_t *s);
void us_internal_socket_after_open(struct us_socket_t *s, int error);
void us_internal_socket_after_open(us_socket_r s, int error);
struct us_internal_ssl_socket_t *
us_internal_ssl_socket_close(struct us_internal_ssl_socket_t *s, int code,
us_internal_ssl_socket_close(us_internal_ssl_socket_r s, int code,
void *reason);
int us_internal_handle_dns_results(struct us_loop_t *loop);
int us_internal_handle_dns_results(us_loop_r loop);
/* Sockets are polls */
struct us_socket_t {
@@ -248,9 +251,9 @@ struct us_listen_socket_t {
/* Listen sockets are keps in their own list */
void us_internal_socket_context_link_listen_socket(
struct us_socket_context_t *context, struct us_listen_socket_t *s);
us_socket_context_r context, struct us_listen_socket_t *s);
void us_internal_socket_context_unlink_listen_socket(int ssl,
struct us_socket_context_t *context, struct us_listen_socket_t *s);
us_socket_context_r context, struct us_listen_socket_t *s);
struct us_socket_context_t {
alignas(LIBUS_EXT_ALIGNMENT) struct us_loop_t *loop;
@@ -290,31 +293,31 @@ typedef void (*us_internal_on_handshake_t)(
void us_internal_socket_context_free(int ssl, struct us_socket_context_t *context);
/* SNI functions */
void us_internal_ssl_socket_context_add_server_name(
struct us_internal_ssl_socket_context_t *context,
us_internal_ssl_socket_context_r context,
const char *hostname_pattern, struct us_socket_context_options_t options,
void *user);
void us_bun_internal_ssl_socket_context_add_server_name(
struct us_internal_ssl_socket_context_t *context,
us_internal_ssl_socket_context_r context,
const char *hostname_pattern,
struct us_bun_socket_context_options_t options, void *user);
void us_internal_ssl_socket_context_remove_server_name(
struct us_internal_ssl_socket_context_t *context,
us_internal_ssl_socket_context_r context,
const char *hostname_pattern);
void us_internal_ssl_socket_context_on_server_name(
struct us_internal_ssl_socket_context_t *context,
us_internal_ssl_socket_context_r context,
void (*cb)(struct us_internal_ssl_socket_context_t *, const char *));
void *
us_internal_ssl_socket_get_sni_userdata(struct us_internal_ssl_socket_t *s);
us_internal_ssl_socket_get_sni_userdata(us_internal_ssl_socket_r s);
void *us_internal_ssl_socket_context_find_server_name_userdata(
struct us_internal_ssl_socket_context_t *context,
us_internal_ssl_socket_context_r context,
const char *hostname_pattern);
void *
us_internal_ssl_socket_get_native_handle(struct us_internal_ssl_socket_t *s);
us_internal_ssl_socket_get_native_handle(us_internal_ssl_socket_r s);
void *us_internal_ssl_socket_context_get_native_handle(
struct us_internal_ssl_socket_context_t *context);
us_internal_ssl_socket_context_r context);
struct us_bun_verify_error_t
us_internal_verify_error(struct us_internal_ssl_socket_t *s);
us_internal_verify_error(us_internal_ssl_socket_r s);
struct us_internal_ssl_socket_context_t *us_internal_create_ssl_socket_context(
struct us_loop_t *loop, int context_ext_size,
struct us_socket_context_options_t options);
@@ -324,109 +327,109 @@ us_internal_bun_create_ssl_socket_context(
struct us_bun_socket_context_options_t options);
void us_internal_ssl_socket_context_free(
struct us_internal_ssl_socket_context_t *context);
us_internal_ssl_socket_context_r context);
void us_internal_ssl_socket_context_on_open(
struct us_internal_ssl_socket_context_t *context,
us_internal_ssl_socket_context_r context,
struct us_internal_ssl_socket_t *(*on_open)(
struct us_internal_ssl_socket_t *s, int is_client, char *ip,
us_internal_ssl_socket_r s, int is_client, char *ip,
int ip_length));
void us_internal_ssl_socket_context_on_close(
struct us_internal_ssl_socket_context_t *context,
us_internal_ssl_socket_context_r context,
struct us_internal_ssl_socket_t *(*on_close)(
struct us_internal_ssl_socket_t *s, int code, void *reason));
us_internal_ssl_socket_r s, int code, void *reason));
void us_internal_ssl_socket_context_on_data(
struct us_internal_ssl_socket_context_t *context,
us_internal_ssl_socket_context_r context,
struct us_internal_ssl_socket_t *(*on_data)(
struct us_internal_ssl_socket_t *s, char *data, int length));
us_internal_ssl_socket_r s, char *data, int length));
void us_internal_update_handshake(struct us_internal_ssl_socket_t *s);
int us_internal_renegotiate(struct us_internal_ssl_socket_t *s);
void us_internal_trigger_handshake_callback(struct us_internal_ssl_socket_t *s,
void us_internal_update_handshake(us_internal_ssl_socket_r s);
int us_internal_renegotiate(us_internal_ssl_socket_r s);
void us_internal_trigger_handshake_callback(us_internal_ssl_socket_r s,
int success);
void us_internal_on_ssl_handshake(
struct us_internal_ssl_socket_context_t *context,
us_internal_ssl_socket_context_r context,
us_internal_on_handshake_t onhandshake, void *custom_data);
void us_internal_ssl_socket_context_on_writable(
struct us_internal_ssl_socket_context_t *context,
us_internal_ssl_socket_context_r context,
struct us_internal_ssl_socket_t *(*on_writable)(
struct us_internal_ssl_socket_t *s));
us_internal_ssl_socket_r s));
void us_internal_ssl_socket_context_on_timeout(
struct us_internal_ssl_socket_context_t *context,
us_internal_ssl_socket_context_r context,
struct us_internal_ssl_socket_t *(*on_timeout)(
struct us_internal_ssl_socket_t *s));
us_internal_ssl_socket_r s));
void us_internal_ssl_socket_context_on_long_timeout(
struct us_internal_ssl_socket_context_t *context,
us_internal_ssl_socket_context_r context,
struct us_internal_ssl_socket_t *(*on_timeout)(
struct us_internal_ssl_socket_t *s));
us_internal_ssl_socket_r s));
void us_internal_ssl_socket_context_on_end(
struct us_internal_ssl_socket_context_t *context,
us_internal_ssl_socket_context_r context,
struct us_internal_ssl_socket_t *(*on_end)(
struct us_internal_ssl_socket_t *s));
us_internal_ssl_socket_r s));
void us_internal_ssl_socket_context_on_connect_error(
struct us_internal_ssl_socket_context_t *context,
us_internal_ssl_socket_context_r context,
struct us_internal_ssl_socket_t *(*on_connect_error)(
struct us_internal_ssl_socket_t *s, int code));
us_internal_ssl_socket_r s, int code));
void us_internal_ssl_socket_context_on_socket_connect_error(
struct us_internal_ssl_socket_context_t *context,
us_internal_ssl_socket_context_r context,
struct us_internal_ssl_socket_t *(*on_socket_connect_error)(
struct us_internal_ssl_socket_t *s, int code));
us_internal_ssl_socket_r s, int code));
struct us_listen_socket_t *us_internal_ssl_socket_context_listen(
struct us_internal_ssl_socket_context_t *context, const char *host,
us_internal_ssl_socket_context_r context, const char *host,
int port, int options, int socket_ext_size);
struct us_listen_socket_t *us_internal_ssl_socket_context_listen_unix(
struct us_internal_ssl_socket_context_t *context, const char *path,
us_internal_ssl_socket_context_r context, const char *path,
size_t pathlen, int options, int socket_ext_size);
struct us_connecting_socket_t *us_internal_ssl_socket_context_connect(
struct us_internal_ssl_socket_context_t *context, const char *host,
us_internal_ssl_socket_context_r context, const char *host,
int port, int options, int socket_ext_size, int* is_resolved);
struct us_internal_ssl_socket_t *us_internal_ssl_socket_context_connect_unix(
struct us_internal_ssl_socket_context_t *context, const char *server_path,
us_internal_ssl_socket_context_r context, const char *server_path,
size_t pathlen, int options, int socket_ext_size);
int us_internal_ssl_socket_write(struct us_internal_ssl_socket_t *s,
int us_internal_ssl_socket_write(us_internal_ssl_socket_r s,
const char *data, int length, int msg_more);
int us_internal_ssl_socket_raw_write(struct us_internal_ssl_socket_t *s,
int us_internal_ssl_socket_raw_write(us_internal_ssl_socket_r s,
const char *data, int length,
int msg_more);
void us_internal_ssl_socket_timeout(struct us_internal_ssl_socket_t *s,
void us_internal_ssl_socket_timeout(us_internal_ssl_socket_r s,
unsigned int seconds);
void *
us_internal_ssl_socket_context_ext(struct us_internal_ssl_socket_context_t *s);
struct us_internal_ssl_socket_context_t *
us_internal_ssl_socket_get_context(struct us_internal_ssl_socket_t *s);
void *us_internal_ssl_socket_ext(struct us_internal_ssl_socket_t *s);
us_internal_ssl_socket_get_context(us_internal_ssl_socket_r s);
void *us_internal_ssl_socket_ext(us_internal_ssl_socket_r s);
void *us_internal_connecting_ssl_socket_ext(struct us_connecting_socket_t *c);
int us_internal_ssl_socket_is_shut_down(struct us_internal_ssl_socket_t *s);
int us_internal_ssl_socket_is_closed(struct us_internal_ssl_socket_t *s);
void us_internal_ssl_socket_shutdown(struct us_internal_ssl_socket_t *s);
int us_internal_ssl_socket_is_shut_down(us_internal_ssl_socket_r s);
int us_internal_ssl_socket_is_closed(us_internal_ssl_socket_r s);
void us_internal_ssl_socket_shutdown(us_internal_ssl_socket_r s);
struct us_internal_ssl_socket_t *us_internal_ssl_socket_context_adopt_socket(
struct us_internal_ssl_socket_context_t *context,
struct us_internal_ssl_socket_t *s, int ext_size);
us_internal_ssl_socket_context_r context,
us_internal_ssl_socket_r s, int ext_size);
struct us_internal_ssl_socket_t *us_internal_ssl_socket_wrap_with_tls(
struct us_socket_t *s, struct us_bun_socket_context_options_t options,
us_socket_r s, struct us_bun_socket_context_options_t options,
struct us_socket_events_t events, int socket_ext_size);
struct us_internal_ssl_socket_context_t *
us_internal_create_child_ssl_socket_context(
struct us_internal_ssl_socket_context_t *context, int context_ext_size);
us_internal_ssl_socket_context_r context, int context_ext_size);
struct us_loop_t *us_internal_ssl_socket_context_loop(
struct us_internal_ssl_socket_context_t *context);
us_internal_ssl_socket_context_r context);
struct us_internal_ssl_socket_t *
us_internal_ssl_socket_open(struct us_internal_ssl_socket_t *s, int is_client,
us_internal_ssl_socket_open(us_internal_ssl_socket_r s, int is_client,
char *ip, int ip_length);
int us_raw_root_certs(struct us_cert_string_t **out);

View File

@@ -35,6 +35,25 @@
#ifndef LIBUSOCKETS_H
#define LIBUSOCKETS_H
#ifdef BUN_DEBUG
#define nonnull_arg _Nonnull
#else
#define nonnull_arg
#endif
#ifdef BUN_DEBUG
#define nonnull_fn_decl
#else
#ifndef nonnull_fn_decl
#define nonnull_fn_decl __attribute__((nonnull))
#endif
#endif
#define us_loop_r struct us_loop_t *nonnull_arg
#define us_socket_r struct us_socket_t *nonnull_arg
#define us_poll_r struct us_poll_t *nonnull_arg
#define us_socket_context_r struct us_socket_context_t *nonnull_arg
/* 512kb shared receive buffer */
#define LIBUS_RECV_BUFFER_LENGTH 524288
@@ -124,11 +143,11 @@ struct us_udp_packet_buffer_t *us_create_udp_packet_buffer();
/* Creates a (heavy-weight) UDP socket with a user space ring buffer. Again, this one is heavy weight and
* shoud be reused. One entire QUIC server can be implemented using only one single UDP socket so weight
* is not a concern as is the case for TCP sockets which are 1-to-1 with TCP connections. */
//struct us_udp_socket_t *us_create_udp_socket(struct us_loop_t *loop, void (*read_cb)(struct us_udp_socket_t *), unsigned short port);
//struct us_udp_socket_t *us_create_udp_socket(us_loop_r loop, void (*read_cb)(struct us_udp_socket_t *), unsigned short port);
//struct us_udp_socket_t *us_create_udp_socket(struct us_loop_t *loop, void (*data_cb)(struct us_udp_socket_t *, struct us_udp_packet_buffer_t *, int), void (*drain_cb)(struct us_udp_socket_t *), char *host, unsigned short port);
//struct us_udp_socket_t *us_create_udp_socket(us_loop_r loop, void (*data_cb)(struct us_udp_socket_t *, struct us_udp_packet_buffer_t *, int), void (*drain_cb)(struct us_udp_socket_t *), char *host, unsigned short port);
struct us_udp_socket_t *us_create_udp_socket(struct us_loop_t *loop, void (*data_cb)(struct us_udp_socket_t *, void *, int), void (*drain_cb)(struct us_udp_socket_t *), void (*close_cb)(struct us_udp_socket_t *), const char *host, unsigned short port, void *user);
struct us_udp_socket_t *us_create_udp_socket(us_loop_r loop, void (*data_cb)(struct us_udp_socket_t *, void *, int), void (*drain_cb)(struct us_udp_socket_t *), void (*close_cb)(struct us_udp_socket_t *), const char *host, unsigned short port, void *user);
void us_udp_socket_close(struct us_udp_socket_t *s);
@@ -141,7 +160,7 @@ int us_udp_socket_bind(struct us_udp_socket_t *s, const char *hostname, unsigned
/* Public interfaces for timers */
/* Create a new high precision, low performance timer. May fail and return null */
struct us_timer_t *us_create_timer(struct us_loop_t *loop, int fallthrough, unsigned int ext_size);
struct us_timer_t *us_create_timer(us_loop_r loop, int fallthrough, unsigned int ext_size);
/* Returns user data extension for this timer */
void *us_timer_ext(struct us_timer_t *timer);
@@ -175,17 +194,17 @@ struct us_bun_verify_error_t {
};
struct us_socket_events_t {
struct us_socket_t *(*on_open)(struct us_socket_t *, int is_client, char *ip, int ip_length);
struct us_socket_t *(*on_data)(struct us_socket_t *, char *data, int length);
struct us_socket_t *(*on_writable)(struct us_socket_t *);
struct us_socket_t *(*on_close)(struct us_socket_t *, int code, void *reason);
struct us_socket_t *(*on_open)(us_socket_r, int is_client, char *ip, int ip_length);
struct us_socket_t *(*on_data)(us_socket_r, char *data, int length);
struct us_socket_t *(*on_writable)(us_socket_r);
struct us_socket_t *(*on_close)(us_socket_r, int code, void *reason);
//void (*on_timeout)(struct us_socket_context *);
struct us_socket_t *(*on_timeout)(struct us_socket_t *);
struct us_socket_t *(*on_long_timeout)(struct us_socket_t *);
struct us_socket_t *(*on_end)(struct us_socket_t *);
struct us_socket_t *(*on_timeout)(us_socket_r);
struct us_socket_t *(*on_long_timeout)(us_socket_r);
struct us_socket_t *(*on_end)(us_socket_r);
struct us_connecting_socket_t *(*on_connect_error)(struct us_connecting_socket_t *, int code);
struct us_socket_t *(*on_connecting_socket_error)(struct us_socket_t *, int code);
void (*on_handshake)(struct us_socket_t*, int success, struct us_bun_verify_error_t verify_error, void* custom_data);
struct us_socket_t *(*on_connecting_socket_error)(us_socket_r, int code);
void (*on_handshake)(us_socket_r, int success, struct us_bun_verify_error_t verify_error, void* custom_data);
};
@@ -211,70 +230,70 @@ struct us_bun_socket_context_options_t {
};
/* Return 15-bit timestamp for this context */
unsigned short us_socket_context_timestamp(int ssl, struct us_socket_context_t *context);
unsigned short us_socket_context_timestamp(int ssl, us_socket_context_r context) nonnull_fn_decl;
/* Adds SNI domain and cert in asn1 format */
void us_socket_context_add_server_name(int ssl, struct us_socket_context_t *context, const char *hostname_pattern, struct us_socket_context_options_t options, void *user);
void us_bun_socket_context_add_server_name(int ssl, struct us_socket_context_t *context, const char *hostname_pattern, struct us_bun_socket_context_options_t options, void *user);
void us_socket_context_remove_server_name(int ssl, struct us_socket_context_t *context, const char *hostname_pattern);
void us_socket_context_on_server_name(int ssl, struct us_socket_context_t *context, void (*cb)(struct us_socket_context_t *, const char *hostname));
void *us_socket_server_name_userdata(int ssl, struct us_socket_t *s);
void *us_socket_context_find_server_name_userdata(int ssl, struct us_socket_context_t *context, const char *hostname_pattern);
void us_socket_context_add_server_name(int ssl, us_socket_context_r context, const char *hostname_pattern, struct us_socket_context_options_t options, void *user);
void us_bun_socket_context_add_server_name(int ssl, us_socket_context_r context, const char *hostname_pattern, struct us_bun_socket_context_options_t options, void *user);
void us_socket_context_remove_server_name(int ssl, us_socket_context_r context, const char *hostname_pattern);
void us_socket_context_on_server_name(int ssl, us_socket_context_r context, void (*cb)(us_socket_context_r context, const char *hostname));
void *us_socket_server_name_userdata(int ssl, us_socket_r s);
void *us_socket_context_find_server_name_userdata(int ssl, us_socket_context_r context, const char *hostname_pattern);
/* Returns the underlying SSL native handle, such as SSL_CTX or nullptr */
void *us_socket_context_get_native_handle(int ssl, struct us_socket_context_t *context);
void *us_socket_context_get_native_handle(int ssl, us_socket_context_r context);
/* A socket context holds shared callbacks and user data extension for associated sockets */
struct us_socket_context_t *us_create_socket_context(int ssl, struct us_loop_t *loop,
int ext_size, struct us_socket_context_options_t options);
struct us_socket_context_t *us_create_socket_context(int ssl, us_loop_r loop,
int ext_size, struct us_socket_context_options_t options) nonnull_fn_decl;
struct us_socket_context_t *us_create_bun_socket_context(int ssl, struct us_loop_t *loop,
int ext_size, struct us_bun_socket_context_options_t options);
int ext_size, struct us_bun_socket_context_options_t options) nonnull_fn_decl;
/* Delete resources allocated at creation time (will call unref now and only free when ref count == 0). */
void us_socket_context_free(int ssl, struct us_socket_context_t *context);
void us_socket_context_ref(int ssl, struct us_socket_context_t *context);
void us_socket_context_unref(int ssl, struct us_socket_context_t *context);
void us_socket_context_free(int ssl, us_socket_context_r context) nonnull_fn_decl;
void us_socket_context_ref(int ssl, us_socket_context_r context) nonnull_fn_decl;
void us_socket_context_unref(int ssl, us_socket_context_r context) nonnull_fn_decl;
struct us_bun_verify_error_t us_socket_verify_error(int ssl, struct us_socket_t *context);
/* Setters of various async callbacks */
void us_socket_context_on_open(int ssl, struct us_socket_context_t *context,
struct us_socket_t *(*on_open)(struct us_socket_t *s, int is_client, char *ip, int ip_length));
void us_socket_context_on_close(int ssl, struct us_socket_context_t *context,
struct us_socket_t *(*on_close)(struct us_socket_t *s, int code, void *reason));
void us_socket_context_on_data(int ssl, struct us_socket_context_t *context,
struct us_socket_t *(*on_data)(struct us_socket_t *s, char *data, int length));
void us_socket_context_on_writable(int ssl, struct us_socket_context_t *context,
struct us_socket_t *(*on_writable)(struct us_socket_t *s));
void us_socket_context_on_timeout(int ssl, struct us_socket_context_t *context,
struct us_socket_t *(*on_timeout)(struct us_socket_t *s));
void us_socket_context_on_long_timeout(int ssl, struct us_socket_context_t *context,
struct us_socket_t *(*on_timeout)(struct us_socket_t *s));
void us_socket_context_on_open(int ssl, us_socket_context_r context,
struct us_socket_t *(*on_open)(us_socket_r s, int is_client, char *ip, int ip_length));
void us_socket_context_on_close(int ssl, us_socket_context_r context,
struct us_socket_t *(*on_close)(us_socket_r s, int code, void *reason));
void us_socket_context_on_data(int ssl, us_socket_context_r context,
struct us_socket_t *(*on_data)(us_socket_r s, char *data, int length));
void us_socket_context_on_writable(int ssl, us_socket_context_r context,
struct us_socket_t *(*on_writable)(us_socket_r s));
void us_socket_context_on_timeout(int ssl, us_socket_context_r context,
struct us_socket_t *(*on_timeout)(us_socket_r s));
void us_socket_context_on_long_timeout(int ssl, us_socket_context_r context,
struct us_socket_t *(*on_timeout)(us_socket_r s));
/* This one is only used for when a connecting socket fails in a late stage. */
void us_socket_context_on_connect_error(int ssl, struct us_socket_context_t *context,
void us_socket_context_on_connect_error(int ssl, us_socket_context_r context,
struct us_connecting_socket_t *(*on_connect_error)(struct us_connecting_socket_t *s, int code));
void us_socket_context_on_socket_connect_error(int ssl, struct us_socket_context_t *context,
struct us_socket_t *(*on_connect_error)(struct us_socket_t *s, int code));
void us_socket_context_on_socket_connect_error(int ssl, us_socket_context_r context,
struct us_socket_t *(*on_connect_error)(us_socket_r s, int code));
void us_socket_context_on_handshake(int ssl, struct us_socket_context_t *context, void (*on_handshake)(struct us_socket_t *, int success, struct us_bun_verify_error_t verify_error, void* custom_data), void* custom_data);
void us_socket_context_on_handshake(int ssl, us_socket_context_r context, void (*on_handshake)(struct us_socket_t *, int success, struct us_bun_verify_error_t verify_error, void* custom_data), void* custom_data);
/* Emitted when a socket has been half-closed */
void us_socket_context_on_end(int ssl, struct us_socket_context_t *context, struct us_socket_t *(*on_end)(struct us_socket_t *s));
void us_socket_context_on_end(int ssl, us_socket_context_r context, struct us_socket_t *(*on_end)(us_socket_r s));
/* Returns user data extension for this socket context */
void *us_socket_context_ext(int ssl, struct us_socket_context_t *context);
void *us_socket_context_ext(int ssl, us_socket_context_r context);
/* Closes all open sockets, including listen sockets. Does not invalidate the socket context. */
void us_socket_context_close(int ssl, struct us_socket_context_t *context);
void us_socket_context_close(int ssl, us_socket_context_r context);
/* Listen for connections. Acts as the main driving cog in a server. Will call set async callbacks. */
struct us_listen_socket_t *us_socket_context_listen(int ssl, struct us_socket_context_t *context,
struct us_listen_socket_t *us_socket_context_listen(int ssl, us_socket_context_r context,
const char *host, int port, int options, int socket_ext_size);
struct us_listen_socket_t *us_socket_context_listen_unix(int ssl, struct us_socket_context_t *context,
struct us_listen_socket_t *us_socket_context_listen_unix(int ssl, us_socket_context_r context,
const char *path, size_t pathlen, int options, int socket_ext_size);
/* listen_socket.c/.h */
void us_listen_socket_close(int ssl, struct us_listen_socket_t *ls);
void us_listen_socket_close(int ssl, struct us_listen_socket_t *ls) nonnull_fn_decl;
/*
Returns one of
@@ -285,156 +304,156 @@ void us_listen_socket_close(int ssl, struct us_listen_socket_t *ls);
This is the slow path where we must either go through DNS resolution or create multiple sockets
per the happy eyeballs algorithm
*/
void *us_socket_context_connect(int ssl, struct us_socket_context_t *context,
const char *host, int port, int options, int socket_ext_size, int *is_connecting);
void *us_socket_context_connect(int ssl, struct us_socket_context_t * nonnull_arg context,
const char *host, int port, int options, int socket_ext_size, int *is_connecting) __attribute__((nonnull(2)));
struct us_socket_t *us_socket_context_connect_unix(int ssl, struct us_socket_context_t *context,
const char *server_path, size_t pathlen, int options, int socket_ext_size);
struct us_socket_t *us_socket_context_connect_unix(int ssl, us_socket_context_r context,
const char *server_path, size_t pathlen, int options, int socket_ext_size) __attribute__((nonnull(2)));
/* Is this socket established? Can be used to check if a connecting socket has fired the on_open event yet.
* Can also be used to determine if a socket is a listen_socket or not, but you probably know that already. */
int us_socket_is_established(int ssl, struct us_socket_t *s);
int us_socket_is_established(int ssl, us_socket_r s) nonnull_fn_decl;
void us_connecting_socket_free(struct us_connecting_socket_t *c);
void us_connecting_socket_free(struct us_connecting_socket_t *c) nonnull_fn_decl;
/* Cancel a connecting socket. Can be used together with us_socket_timeout to limit connection times.
* Entirely destroys the socket - this function works like us_socket_close but does not trigger on_close event since
* you never got the on_open event first. */
void us_connecting_socket_close(int ssl, struct us_connecting_socket_t *c);
void us_connecting_socket_close(int ssl, struct us_connecting_socket_t *c) nonnull_fn_decl;
/* Returns the loop for this socket context. */
struct us_loop_t *us_socket_context_loop(int ssl, struct us_socket_context_t *context);
struct us_loop_t *us_socket_context_loop(int ssl, us_socket_context_r context) nonnull_fn_decl __attribute((returns_nonnull));
/* Invalidates passed socket, returning a new resized socket which belongs to a different socket context.
* Used mainly for "socket upgrades" such as when transitioning from HTTP to WebSocket. */
struct us_socket_t *us_socket_context_adopt_socket(int ssl, struct us_socket_context_t *context, struct us_socket_t *s, int ext_size);
struct us_socket_t *us_socket_context_adopt_socket(int ssl, us_socket_context_r context, us_socket_r s, int ext_size);
/* Create a child socket context which acts much like its own socket context with its own callbacks yet still relies on the
* parent socket context for some shared resources. Child socket contexts should be used together with socket adoptions and nothing else. */
struct us_socket_context_t *us_create_child_socket_context(int ssl, struct us_socket_context_t *context, int context_ext_size);
struct us_socket_context_t *us_create_child_socket_context(int ssl, us_socket_context_r context, int context_ext_size);
/* Public interfaces for loops */
/* Returns a new event loop with user data extension */
struct us_loop_t *us_create_loop(void *hint, void (*wakeup_cb)(struct us_loop_t *loop),
void (*pre_cb)(struct us_loop_t *loop), void (*post_cb)(struct us_loop_t *loop), unsigned int ext_size);
struct us_loop_t *us_create_loop(void *hint, void (*wakeup_cb)(us_loop_r loop),
void (*pre_cb)(us_loop_r loop), void (*post_cb)(us_loop_r loop), unsigned int ext_size);
/* Frees the loop immediately */
void us_loop_free(struct us_loop_t *loop);
void us_loop_free(us_loop_r loop) nonnull_fn_decl;
/* Returns the loop user data extension */
void *us_loop_ext(struct us_loop_t *loop);
void *us_loop_ext(us_loop_r loop) nonnull_fn_decl;
/* Blocks the calling thread and drives the event loop until no more non-fallthrough polls are scheduled */
void us_loop_run(struct us_loop_t *loop);
void us_loop_run(us_loop_r loop) nonnull_fn_decl;
/* Signals the loop from any thread to wake up and execute its wakeup handler from the loop's own running thread.
* This is the only fully thread-safe function and serves as the basis for thread safety */
void us_wakeup_loop(struct us_loop_t *loop);
void us_wakeup_loop(us_loop_r loop) nonnull_fn_decl;
/* Hook up timers in existing loop */
void us_loop_integrate(struct us_loop_t *loop);
void us_loop_integrate(us_loop_r loop) nonnull_fn_decl;
/* Returns the loop iteration number */
long long us_loop_iteration_number(struct us_loop_t *loop);
long long us_loop_iteration_number(us_loop_r loop) nonnull_fn_decl;
/* Public interfaces for polls */
/* A fallthrough poll does not keep the loop running, it falls through */
struct us_poll_t *us_create_poll(struct us_loop_t *loop, int fallthrough, unsigned int ext_size);
struct us_poll_t *us_create_poll(us_loop_r loop, int fallthrough, unsigned int ext_size);
/* After stopping a poll you must manually free the memory */
void us_poll_free(struct us_poll_t *p, struct us_loop_t *loop);
void us_poll_free(us_poll_r p, struct us_loop_t *loop);
/* Associate this poll with a socket descriptor and poll type */
void us_poll_init(struct us_poll_t *p, LIBUS_SOCKET_DESCRIPTOR fd, int poll_type);
void us_poll_init(us_poll_r p, LIBUS_SOCKET_DESCRIPTOR fd, int poll_type);
/* Start, change and stop polling for events */
void us_poll_start(struct us_poll_t *p, struct us_loop_t *loop, int events);
void us_poll_change(struct us_poll_t *p, struct us_loop_t *loop, int events);
void us_poll_stop(struct us_poll_t *p, struct us_loop_t *loop);
void us_poll_start(us_poll_r p, us_loop_r loop, int events) nonnull_fn_decl;
void us_poll_change(us_poll_r p, us_loop_r loop, int events) nonnull_fn_decl;
void us_poll_stop(us_poll_r p, struct us_loop_t *loop) nonnull_fn_decl;
/* Return what events we are polling for */
int us_poll_events(struct us_poll_t *p);
int us_poll_events(us_poll_r p) nonnull_fn_decl;
/* Returns the user data extension of this poll */
void *us_poll_ext(struct us_poll_t *p);
void *us_poll_ext(us_poll_r p) nonnull_fn_decl;
/* Get associated socket descriptor from a poll */
LIBUS_SOCKET_DESCRIPTOR us_poll_fd(struct us_poll_t *p);
LIBUS_SOCKET_DESCRIPTOR us_poll_fd(us_poll_r p) nonnull_fn_decl;
/* Resize an active poll */
struct us_poll_t *us_poll_resize(struct us_poll_t *p, struct us_loop_t *loop, unsigned int ext_size);
struct us_poll_t *us_poll_resize(us_poll_r p, us_loop_r loop, unsigned int ext_size) nonnull_fn_decl;
/* Public interfaces for sockets */
/* Returns the underlying native handle for a socket, such as SSL or file descriptor.
* In the case of file descriptor, the value of pointer is fd. */
void *us_socket_get_native_handle(int ssl, struct us_socket_t *s);
void *us_socket_get_native_handle(int ssl, us_socket_r s) nonnull_fn_decl;
/* Write up to length bytes of data. Returns actual bytes written.
* Will call the on_writable callback of active socket context on failure to write everything off in one go.
* Set hint msg_more if you have more immediate data to write. */
int us_socket_write(int ssl, struct us_socket_t *s, const char *data, int length, int msg_more);
int us_socket_write(int ssl, us_socket_r s, const char * nonnull_arg data, int length, int msg_more) nonnull_fn_decl;
/* Special path for non-SSL sockets. Used to send header and payload in one go. Works like us_socket_write. */
int us_socket_write2(int ssl, struct us_socket_t *s, const char *header, int header_length, const char *payload, int payload_length);
int us_socket_write2(int ssl, us_socket_r s, const char *header, int header_length, const char *payload, int payload_length) nonnull_fn_decl;
/* Set a low precision, high performance timer on a socket. A socket can only have one single active timer
* at any given point in time. Will remove any such pre set timer */
void us_socket_timeout(int ssl, struct us_socket_t *s, unsigned int seconds);
void us_socket_timeout(int ssl, us_socket_r s, unsigned int seconds) nonnull_fn_decl;
/* Set a low precision, high performance timer on a socket. Suitable for per-minute precision. */
void us_socket_long_timeout(int ssl, struct us_socket_t *s, unsigned int minutes);
void us_socket_long_timeout(int ssl, us_socket_r s, unsigned int minutes) nonnull_fn_decl;
/* Return the user data extension of this socket */
void *us_socket_ext(int ssl, struct us_socket_t *s);
void *us_connecting_socket_ext(int ssl, struct us_connecting_socket_t *c);
void *us_socket_ext(int ssl, us_socket_r s) nonnull_fn_decl;
void *us_connecting_socket_ext(int ssl, struct us_connecting_socket_t *c) nonnull_fn_decl;
/* Return the socket context of this socket */
struct us_socket_context_t *us_socket_context(int ssl, struct us_socket_t *s);
struct us_socket_context_t *us_socket_context(int ssl, us_socket_r s) nonnull_fn_decl __attribute__((returns_nonnull));
/* Withdraw any msg_more status and flush any pending data */
void us_socket_flush(int ssl, struct us_socket_t *s);
void us_socket_flush(int ssl, us_socket_r s) nonnull_fn_decl;
/* Shuts down the connection by sending FIN and/or close_notify */
void us_socket_shutdown(int ssl, struct us_socket_t *s);
void us_socket_shutdown(int ssl, us_socket_r s) nonnull_fn_decl;
/* Shuts down the connection in terms of read, meaning next event loop
* iteration will catch the socket being closed. Can be used to defer closing
* to next event loop iteration. */
void us_socket_shutdown_read(int ssl, struct us_socket_t *s);
void us_socket_shutdown_read(int ssl, us_socket_r s) nonnull_fn_decl;
/* Returns whether the socket has been shut down or not */
int us_socket_is_shut_down(int ssl, struct us_socket_t *s);
int us_socket_is_shut_down(int ssl, us_socket_r s) nonnull_fn_decl;
/* Returns whether this socket has been closed. Only valid if memory has not yet been released. */
int us_socket_is_closed(int ssl, struct us_socket_t *s);
int us_socket_is_closed(int ssl, us_socket_r s) nonnull_fn_decl;
/* Immediately closes the socket */
struct us_socket_t *us_socket_close(int ssl, struct us_socket_t *s, int code, void *reason);
struct us_socket_t *us_socket_close(int ssl, us_socket_r s, int code, void *reason) __attribute__((nonnull(2)));
/* Returns local port or -1 on failure. */
int us_socket_local_port(int ssl, struct us_socket_t *s);
int us_socket_local_port(int ssl, us_socket_r s) nonnull_fn_decl;
/* Copy remote (IP) address of socket, or fail with zero length. */
void us_socket_remote_address(int ssl, struct us_socket_t *s, char *buf, int *length);
void us_socket_local_address(int ssl, struct us_socket_t *s, char *buf, int *length);
void us_socket_remote_address(int ssl, us_socket_r s, char *nonnull_arg buf, int *nonnull_arg length) nonnull_fn_decl;
void us_socket_local_address(int ssl, us_socket_r s, char *nonnull_arg buf, int *nonnull_arg length) nonnull_fn_decl;
/* Bun extras */
struct us_socket_t *us_socket_pair(struct us_socket_context_t *ctx, int socket_ext_size, LIBUS_SOCKET_DESCRIPTOR* fds);
struct us_socket_t *us_socket_from_fd(struct us_socket_context_t *ctx, int socket_ext_size, LIBUS_SOCKET_DESCRIPTOR fd);
struct us_socket_t *us_socket_attach(int ssl, LIBUS_SOCKET_DESCRIPTOR client_fd, struct us_socket_context_t *ctx, int flags, int socket_ext_size);
struct us_socket_t *us_socket_wrap_with_tls(int ssl, struct us_socket_t *s, struct us_bun_socket_context_options_t options, struct us_socket_events_t events, int socket_ext_size);
int us_socket_raw_write(int ssl, struct us_socket_t *s, const char *data, int length, int msg_more);
struct us_socket_t *us_socket_wrap_with_tls(int ssl, us_socket_r s, struct us_bun_socket_context_options_t options, struct us_socket_events_t events, int socket_ext_size);
int us_socket_raw_write(int ssl, us_socket_r s, const char *data, int length, int msg_more);
struct us_socket_t* us_socket_open(int ssl, struct us_socket_t * s, int is_client, char* ip, int ip_length);
int us_raw_root_certs(struct us_cert_string_t**out);
unsigned int us_get_remote_address_info(char *buf, struct us_socket_t *s, const char **dest, int *port, int *is_ipv6);
int us_socket_get_error(int ssl, struct us_socket_t *s);
unsigned int us_get_remote_address_info(char *buf, us_socket_r s, const char **dest, int *port, int *is_ipv6);
int us_socket_get_error(int ssl, us_socket_r s);
void us_socket_ref(struct us_socket_t *s);
void us_socket_unref(struct us_socket_t *s);
void us_socket_ref(us_socket_r s);
void us_socket_unref(us_socket_r s);
#ifdef __cplusplus
}

View File

@@ -1455,7 +1455,7 @@ fn NewRequestContext(comptime ssl_enabled: bool, comptime debug_mode: bool, comp
fn drainMicrotasks(this: *const RequestContext) void {
if (this.isAsync()) return;
if(this.server) |server| server.vm.drainMicrotasks();
if (this.server) |server| server.vm.drainMicrotasks();
}
pub fn setAbortHandler(this: *RequestContext) void {
@@ -1484,7 +1484,7 @@ fn NewRequestContext(comptime ssl_enabled: bool, comptime debug_mode: bool, comp
var class_name = value.getClassInfoName() orelse bun.String.empty;
defer class_name.deref();
if(ctx.server) |server| {
if (ctx.server) |server| {
const globalThis: *JSC.JSGlobalObject = server.globalThis;
Output.enableBuffering();
@@ -1516,7 +1516,7 @@ fn NewRequestContext(comptime ssl_enabled: bool, comptime debug_mode: bool, comp
return;
}
if(ctx.server == null) {
if (ctx.server == null) {
ctx.renderMissingInvalidResponse(value);
return;
}
@@ -1588,7 +1588,7 @@ fn NewRequestContext(comptime ssl_enabled: bool, comptime debug_mode: bool, comp
this.request_body = null;
}
if(this.server) |server| {
if (this.server) |server| {
this.server = null;
server.request_pool_allocator.put(this);
server.onRequestComplete();
@@ -1784,7 +1784,7 @@ fn NewRequestContext(comptime ssl_enabled: bool, comptime debug_mode: bool, comp
}
this.detachResponse();
this.endRequestStreamingAndDrain();
this.deref();
this.deref();
}
/// Drain a partial response buffer
@@ -1911,9 +1911,7 @@ fn NewRequestContext(comptime ssl_enabled: bool, comptime debug_mode: bool, comp
this.signal = null;
defer signal.unref();
if (!signal.aborted()) {
const reason = JSC.WebCore.AbortSignal.createAbortError(JSC.ZigString.static("The user aborted a request"), &JSC.ZigString.Empty, globalThis);
reason.ensureStillAlive();
_ = signal.signal(reason);
signal.signal(globalThis, .ConnectionClosed);
any_js_calls = true;
}
}
@@ -1928,7 +1926,7 @@ fn NewRequestContext(comptime ssl_enabled: bool, comptime debug_mode: bool, comp
if (this.isDeadRequest()) {
this.finalizeWithoutDeinit();
} else {
if(this.endRequestStreaming()) {
if (this.endRequestStreaming()) {
any_js_calls = true;
}
@@ -1973,13 +1971,10 @@ fn NewRequestContext(comptime ssl_enabled: bool, comptime debug_mode: bool, comp
this.signal = null;
defer signal.unref();
if (this.flags.aborted and !signal.aborted()) {
const reason = JSC.WebCore.AbortSignal.createAbortError(JSC.ZigString.static("The user aborted a request"), &JSC.ZigString.Empty, globalThis);
reason.ensureStillAlive();
_ = signal.signal(reason);
signal.signal(globalThis, .ConnectionClosed);
}
}
// Case 1:
// User called .blob(), .json(), text(), or .arrayBuffer() on the Request object
// but we received nothing or the connection was aborted
@@ -1989,7 +1984,7 @@ fn NewRequestContext(comptime ssl_enabled: bool, comptime debug_mode: bool, comp
// Case 3:
// Stream was not consumed and the connection was aborted or ended
_ = this.endRequestStreaming();
if (this.byte_stream) |stream| {
ctxLog("finalizeWithoutDeinit: stream != null", .{});
@@ -2306,9 +2301,9 @@ fn NewRequestContext(comptime ssl_enabled: bool, comptime debug_mode: bool, comp
if (comptime can_sendfile) {
return this.renderSendFile(blob);
}
if(this.server) |server| {
this.ref();
this.blob.Blob.doReadFileInternal(*RequestContext, this, onReadFile, server.globalThis);
if (this.server) |server| {
this.ref();
this.blob.Blob.doReadFileInternal(*RequestContext, this, onReadFile, server.globalThis);
}
}
@@ -2320,7 +2315,7 @@ fn NewRequestContext(comptime ssl_enabled: bool, comptime debug_mode: bool, comp
}
if (result == .err) {
if(this.server) |server| {
if (this.server) |server| {
this.runErrorHandler(result.err.toErrorInstance(server.globalThis));
}
return;
@@ -2475,7 +2470,6 @@ fn NewRequestContext(comptime ssl_enabled: bool, comptime debug_mode: bool, comp
streamLog("returned a promise", .{});
this.drainMicrotasks();
switch (promise.status(globalThis.vm())) {
.Pending => {
streamLog("promise still Pending", .{});
@@ -2577,7 +2571,6 @@ fn NewRequestContext(comptime ssl_enabled: bool, comptime debug_mode: bool, comp
request_object.request_context.setRequest(req);
assert(ctx.server != null);
request_object.ensureURL() catch {
request_object.url = bun.String.empty;
};
@@ -2608,15 +2601,15 @@ fn NewRequestContext(comptime ssl_enabled: bool, comptime debug_mode: bool, comp
fn endRequestStreamingAndDrain(this: *RequestContext) void {
assert(this.server != null);
if(this.endRequestStreaming()) {
if (this.endRequestStreaming()) {
this.server.?.vm.drainMicrotasks();
}
}
fn endRequestStreaming(this: *RequestContext) bool {
assert(this.server != null);
// if we cannot, we have to reject pending promises
// first, we reject the request body promise
if (this.request_body) |body| {
// if we cannot, we have to reject pending promises
// first, we reject the request body promise
if (this.request_body) |body| {
// User called .blob(), .json(), text(), or .arrayBuffer() on the Request object
// but we received nothing or the connection was aborted
if (body.value == .Locked) {
@@ -2629,7 +2622,7 @@ fn NewRequestContext(comptime ssl_enabled: bool, comptime debug_mode: bool, comp
fn detachResponse(this: *RequestContext) void {
if (this.resp) |resp| {
this.resp = null;
if (this.flags.is_waiting_for_request_body) {
this.flags.is_waiting_for_request_body = false;
resp.clearOnData();
@@ -2807,8 +2800,8 @@ fn NewRequestContext(comptime ssl_enabled: bool, comptime debug_mode: bool, comp
resp.body.value = .{ .Used = {} };
}
}
if(req.isAbortedOrEnded()) {
if (req.isAbortedOrEnded()) {
return;
}
@@ -2883,7 +2876,7 @@ fn NewRequestContext(comptime ssl_enabled: bool, comptime debug_mode: bool, comp
req.endStream(true);
if (comptime debug_mode) {
if(req.server) |server| {
if (req.server) |server| {
if (!err.isEmptyOrUndefinedOrNull()) {
var exception_list: std.ArrayList(Api.JsException) = std.ArrayList(Api.JsException).init(req.allocator);
defer exception_list.deinit();
@@ -3148,7 +3141,7 @@ fn NewRequestContext(comptime ssl_enabled: bool, comptime debug_mode: bool, comp
}
fn finishRunningErrorHandler(this: *RequestContext, value: JSC.JSValue, status: u16) void {
if(this.server == null) return this.renderProductionError(status);
if (this.server == null) return this.renderProductionError(status);
var vm: *JSC.VirtualMachine = this.server.?.vm;
const globalThis = this.server.?.globalThis;
if (comptime debug_mode) {
@@ -3182,7 +3175,7 @@ fn NewRequestContext(comptime ssl_enabled: bool, comptime debug_mode: bool, comp
status: u16,
) void {
JSC.markBinding(@src());
if(this.server) |server| {
if (this.server) |server| {
if (!server.config.onError.isEmpty() and !this.flags.has_called_error_handler) {
this.flags.has_called_error_handler = true;
const result = server.config.onError.call(
@@ -3565,7 +3558,7 @@ fn NewRequestContext(comptime ssl_enabled: bool, comptime debug_mode: bool, comp
}
const max_request_body_preallocate_length = 1024 * 256;
pub fn onStartBuffering(this: *RequestContext) void {
if(this.server) |server| {
if (this.server) |server| {
ctxLog("onStartBuffering", .{});
// TODO: check if is someone calling onStartBuffering other than onStartBufferingCallback
// if is not, this should be removed and only keep protect + setAbortHandler
@@ -5511,7 +5504,7 @@ pub fn NewServer(comptime NamespaceType: type, comptime ssl_enabled_: bool, comp
// obviously invalid pointer marks it as used
upgrader.upgrade_context = @as(*uws.uws_socket_context_s, @ptrFromInt(std.math.maxInt(usize)));
// set the abort handler so we can receive onAbort to deref the context
upgrader.setAbortHandler();
upgrader.setAbortHandler();
// after upgrading we should not use the response anymore
upgrader.resp = null;
request.upgrader = null;

View File

@@ -1,3 +1,9 @@
#include "ExceptionCode.h"
#include "JSDOMException.h"
#include "JavaScriptCore/Error.h"
#include "JavaScriptCore/ErrorType.h"
#include "JavaScriptCore/ObjectConstructor.h"
#include "JavaScriptCore/WriteBarrier.h"
#include "root.h"
#include "headers-handwritten.h"
#include "BunClientData.h"
@@ -12,6 +18,42 @@
#include "wtf/text/MakeString.h"
#include "wtf/text/WTFString.h"
#include <cstdio>
#include "AbortSignal.h"
#include "NodeError.h"
#include "JavaScriptCore/ErrorInstanceInlines.h"
#include "JSDOMException.h"
static JSC::JSObject* createErrorPrototype(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::ErrorType type, WTF::ASCIILiteral name, WTF::ASCIILiteral code)
{
JSC::JSObject* prototype;
switch (type) {
case JSC::ErrorType::TypeError:
prototype = JSC::constructEmptyObject(globalObject, globalObject->m_typeErrorStructure.prototype(globalObject));
break;
case JSC::ErrorType::RangeError:
prototype = JSC::constructEmptyObject(globalObject, globalObject->m_rangeErrorStructure.prototype(globalObject));
break;
case JSC::ErrorType::Error:
prototype = JSC::constructEmptyObject(globalObject, globalObject->errorPrototype());
break;
default: {
RELEASE_ASSERT_NOT_REACHED_WITH_MESSAGE("TODO: Add support for more error types");
break;
}
}
prototype->putDirect(vm, vm.propertyNames->name, jsString(vm, String(name)), 0);
prototype->putDirect(vm, WebCore::builtinNames(vm).codePublicName(), jsString(vm, String(code)), 0);
return prototype;
}
static JSC::Structure* createErrorStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::ErrorType type, WTF::ASCIILiteral name, WTF::ASCIILiteral code)
{
JSC::JSObject* prototype = createErrorPrototype(vm, globalObject, type, name, code);
return JSC::ErrorInstance::createStructure(vm, globalObject, prototype);
}
JSC::EncodedJSValue JSC__JSValue__createTypeError(const ZigString* message, const ZigString* arg1, JSC::JSGlobalObject* globalObject);
JSC::EncodedJSValue JSC__JSValue__createRangeError(const ZigString* message, const ZigString* arg1, JSC::JSGlobalObject* globalObject);
@@ -20,10 +62,118 @@ extern "C" JSC::EncodedJSValue Bun__ERR_INVALID_ARG_TYPE(JSC::JSGlobalObject* gl
extern "C" JSC::EncodedJSValue Bun__ERR_MISSING_ARGS(JSC::JSGlobalObject* globalObject, JSC::EncodedJSValue arg1, JSC::EncodedJSValue arg2, JSC::EncodedJSValue arg3);
extern "C" JSC::EncodedJSValue Bun__ERR_IPC_CHANNEL_CLOSED(JSC::JSGlobalObject* globalObject);
// clang-format on
namespace Bun {
using namespace JSC;
struct NodeErrorData {
JSC::ErrorType type;
WTF::ASCIILiteral name;
WTF::ASCIILiteral code;
};
static constexpr NodeErrorData errors[NODE_ERROR_COUNT] = {
#define DECLARE_ERROR_WITH_CODE_ENUM(E, name, code) { JSC::ErrorType::E, #name ""_s, #code ""_s },
FOR_EACH_NODE_ERROR_WITH_CODE(DECLARE_ERROR_WITH_CODE_ENUM)
#undef DECLARE_ERROR_WITH_CODE_ENUM
};
const ClassInfo NodeErrorCache::s_info = { "NodeErrorCache"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(NodeErrorCache) };
NodeErrorCache::NodeErrorCache(VM& vm, Structure* structure)
: Base(vm, structure)
{
}
template<typename Visitor>
void NodeErrorCache::visitChildrenImpl(JSCell* cell, Visitor& visitor)
{
auto* thisObject = jsCast<NodeErrorCache*>(cell);
ASSERT_GC_OBJECT_INHERITS(thisObject, info());
Base::visitChildren(thisObject, visitor);
}
DEFINE_VISIT_CHILDREN_WITH_MODIFIER(JS_EXPORT_PRIVATE, NodeErrorCache);
Structure* NodeErrorCache::createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject)
{
return Structure::create(vm, globalObject, jsNull(), TypeInfo(InternalFieldTupleType, StructureFlags), info(), 0, 0);
}
NodeErrorCache* NodeErrorCache::create(VM& vm, Structure* structure)
{
NodeErrorCache* object = new (NotNull, allocateCell<NodeErrorCache>(vm)) NodeErrorCache(vm, structure);
object->finishCreation(vm);
return object;
}
void NodeErrorCache::finishCreation(VM& vm)
{
Base::finishCreation(vm);
ASSERT(inherits(info()));
for (unsigned i = 0; i < NODE_ERROR_COUNT; i++) {
this->internalField(i).clear();
}
}
static NodeErrorCache* errorCache(Zig::GlobalObject* globalObject)
{
return static_cast<NodeErrorCache*>(globalObject->nodeErrorCache());
}
// clang-format on
static Structure* createErrorStructure(JSC::VM& vm, JSGlobalObject* globalObject, JSC::ErrorType type, WTF::ASCIILiteral name, WTF::ASCIILiteral code)
{
auto* prototype = createErrorPrototype(vm, globalObject, type, name, code);
return ErrorInstance::createStructure(vm, globalObject, prototype);
}
JSObject* NodeErrorCache::createError(VM& vm, Zig::GlobalObject* globalObject, NodeErrorCode code, JSValue message, JSValue options)
{
auto* cache = errorCache(globalObject);
if (!cache->internalField(static_cast<unsigned>(code))) {
const auto& data = errors[code];
auto* structure = createErrorStructure(vm, globalObject, data.type, data.name, data.code);
cache->internalField(static_cast<unsigned>(code)).set(vm, cache, structure);
}
auto* structure = jsCast<Structure*>(cache->internalField(static_cast<unsigned>(code)).get());
return JSC::ErrorInstance::create(globalObject, structure, message, options, nullptr, JSC::RuntimeType::TypeNothing, errors[code].type, true);
}
JSObject* createError(VM& vm, Zig::GlobalObject* globalObject, NodeErrorCode code, const String& message)
{
return errorCache(globalObject)->createError(vm, globalObject, code, jsString(vm, message), jsUndefined());
}
JSObject* createError(VM& vm, JSC::JSGlobalObject* globalObject, NodeErrorCode code, JSValue message)
{
if (auto* zigGlobalObject = jsDynamicCast<Zig::GlobalObject*>(globalObject))
return createError(vm, zigGlobalObject, code, message, jsUndefined());
auto* structure = createErrorStructure(vm, globalObject, errors[code].type, errors[code].name, errors[code].code);
return JSC::ErrorInstance::create(globalObject, structure, message, jsUndefined(), nullptr, JSC::RuntimeType::TypeNothing, errors[code].type, true);
}
JSC::JSObject* createError(VM& vm, Zig::GlobalObject* globalObject, NodeErrorCode code, JSValue message, JSValue options)
{
return errorCache(globalObject)->createError(vm, globalObject, code, message, options);
}
JSObject* createError(JSC::JSGlobalObject* globalObject, NodeErrorCode code, const String& message)
{
auto& vm = globalObject->vm();
return createError(vm, globalObject, code, jsString(vm, message));
}
JSObject* createError(Zig::JSGlobalObject* globalObject, NodeErrorCode code, JSC::JSValue message)
{
auto& vm = globalObject->vm();
return createError(vm, globalObject, code, message);
}
WTF::String JSValueToStringSafe(JSC::JSGlobalObject* globalObject, JSValue arg)
{
ASSERT(!arg.isEmpty());
@@ -45,48 +195,6 @@ WTF::String JSValueToStringSafe(JSC::JSGlobalObject* globalObject, JSValue arg)
return arg.toString(globalObject)->getString(globalObject);
}
JSC::JSValue createErrorWithCode(JSC::JSGlobalObject* globalObject, String message, ASCIILiteral code)
{
JSC::VM& vm = globalObject->vm();
JSC::JSObject* result = JSC::createError(globalObject, message);
JSC::EnsureStillAliveScope ensureAlive(result);
auto typeError = JSC::JSValue(result).asCell()->getObject();
auto clientData = WebCore::clientData(vm);
typeError->putDirect(vm, clientData->builtinNames().codePublicName(), jsString(vm, String(code)), 0);
return typeError;
}
JSC::JSValue createTypeErrorWithCode(JSC::JSGlobalObject* globalObject, String message, ASCIILiteral code)
{
JSC::VM& vm = globalObject->vm();
JSC::JSObject* result = JSC::createTypeError(globalObject, message);
JSC::EnsureStillAliveScope ensureAlive(result);
auto typeError = JSC::JSValue(result).asCell()->getObject();
auto clientData = WebCore::clientData(vm);
typeError->putDirect(vm, clientData->builtinNames().codePublicName(), jsString(vm, String(code)), 0);
return typeError;
}
JSC::JSValue createRangeErrorWithCode(JSC::JSGlobalObject* globalObject, String message, ASCIILiteral code)
{
JSC::VM& vm = globalObject->vm();
JSC::JSObject* result = JSC::createRangeError(globalObject, message);
JSC::EnsureStillAliveScope ensureAlive(result);
auto typeError = JSC::JSValue(result).asCell()->getObject();
auto clientData = WebCore::clientData(vm);
typeError->putDirect(vm, clientData->builtinNames().codePublicName(), jsString(vm, String(code)), 0);
return typeError;
}
JSC_DEFINE_HOST_FUNCTION(jsFunction_ERR_INVALID_ARG_TYPE, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callFrame))
{
JSC::VM& vm = globalObject->vm();
@@ -117,7 +225,7 @@ extern "C" JSC::EncodedJSValue Bun__ERR_INVALID_ARG_TYPE(JSC::JSGlobalObject* gl
RETURN_IF_EXCEPTION(scope, {});
auto message = makeString("The \""_s, arg_name, "\" argument must be of type "_s, expected_type, ". Received "_s, actual_value);
return JSC::JSValue::encode(createTypeErrorWithCode(globalObject, message, "ERR_INVALID_ARG_TYPE"_s));
return JSValue::encode(createError(globalObject, NodeErrorCode::ERR_INVALID_ARG_TYPE, message));
}
JSC_DEFINE_HOST_FUNCTION(jsFunction_ERR_OUT_OF_RANGE, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callFrame))
@@ -141,17 +249,17 @@ JSC_DEFINE_HOST_FUNCTION(jsFunction_ERR_OUT_OF_RANGE, (JSC::JSGlobalObject * glo
RETURN_IF_EXCEPTION(scope, {});
auto message = makeString("The value of \""_s, arg_name, "\" is out of range. It must be "_s, range, ". Received "_s, input);
return JSC::JSValue::encode(createRangeErrorWithCode(globalObject, message, "ERR_OUT_OF_RANGE"_s));
return JSC::JSValue::encode(createError(globalObject, NodeErrorCode::ERR_OUT_OF_RANGE, message));
}
JSC_DEFINE_HOST_FUNCTION(jsFunction_ERR_IPC_DISCONNECTED, (JSC::JSGlobalObject * globalObject, JSC::CallFrame*))
{
return JSC::JSValue::encode(createErrorWithCode(globalObject, "IPC channel is already disconnected"_s, "ERR_IPC_DISCONNECTED"_s));
return JSC::JSValue::encode(createError(globalObject, NodeErrorCode::ERR_IPC_DISCONNECTED, "IPC channel is already disconnected"_s));
}
JSC_DEFINE_HOST_FUNCTION(jsFunction_ERR_SERVER_NOT_RUNNING, (JSC::JSGlobalObject * globalObject, JSC::CallFrame*))
{
return JSC::JSValue::encode(createErrorWithCode(globalObject, "Server is not running."_s, "ERR_SERVER_NOT_RUNNING"_s));
return JSC::JSValue::encode(createError(globalObject, NodeErrorCode::ERR_SERVER_NOT_RUNNING, "Server is not running."_s));
}
extern "C" JSC::EncodedJSValue Bun__ERR_MISSING_ARGS(JSC::JSGlobalObject* globalObject, JSC::EncodedJSValue arg1, JSC::EncodedJSValue arg2, JSC::EncodedJSValue arg3)
@@ -170,7 +278,7 @@ extern "C" JSC::EncodedJSValue Bun__ERR_MISSING_ARGS(JSC::JSGlobalObject* global
if (arg2 == 0) {
// 1 arg name passed
auto message = makeString("The \""_s, name1, "\" argument must be specified"_s);
return JSC::JSValue::encode(createTypeErrorWithCode(globalObject, message, "ERR_MISSING_ARGS"_s));
return JSC::JSValue::encode(createError(globalObject, NodeErrorCode::ERR_MISSING_ARGS, message));
}
auto name2 = JSValue::decode(arg2).toWTFString(globalObject);
@@ -179,7 +287,7 @@ extern "C" JSC::EncodedJSValue Bun__ERR_MISSING_ARGS(JSC::JSGlobalObject* global
if (arg3 == 0) {
// 2 arg names passed
auto message = makeString("The \""_s, name1, "\" and \""_s, name2, "\" arguments must be specified"_s);
return JSC::JSValue::encode(createTypeErrorWithCode(globalObject, message, "ERR_MISSING_ARGS"_s));
return JSC::JSValue::encode(createError(globalObject, NodeErrorCode::ERR_MISSING_ARGS, message));
}
auto name3 = JSValue::decode(arg3).toWTFString(globalObject);
@@ -187,7 +295,7 @@ extern "C" JSC::EncodedJSValue Bun__ERR_MISSING_ARGS(JSC::JSGlobalObject* global
// 3 arg names passed
auto message = makeString("The \""_s, name1, "\", \""_s, name2, "\", and \""_s, name3, "\" arguments must be specified"_s);
return JSC::JSValue::encode(createTypeErrorWithCode(globalObject, message, "ERR_MISSING_ARGS"_s));
return JSC::JSValue::encode(createError(globalObject, NodeErrorCode::ERR_MISSING_ARGS, message));
}
JSC_DEFINE_HOST_FUNCTION(jsFunction_ERR_IPC_CHANNEL_CLOSED, (JSC::JSGlobalObject * globalObject, JSC::CallFrame*))
@@ -196,12 +304,37 @@ JSC_DEFINE_HOST_FUNCTION(jsFunction_ERR_IPC_CHANNEL_CLOSED, (JSC::JSGlobalObject
}
extern "C" JSC::EncodedJSValue Bun__ERR_IPC_CHANNEL_CLOSED(JSC::JSGlobalObject* globalObject)
{
return JSC::JSValue::encode(createErrorWithCode(globalObject, "Channel closed."_s, "ERR_IPC_CHANNEL_CLOSED"_s));
return JSC::JSValue::encode(createError(globalObject, NodeErrorCode::ERR_IPC_CHANNEL_CLOSED, "Channel closed."_s));
}
JSC_DEFINE_HOST_FUNCTION(jsFunction_ERR_SOCKET_BAD_TYPE, (JSC::JSGlobalObject * globalObject, JSC::CallFrame*))
{
return JSC::JSValue::encode(createTypeErrorWithCode(globalObject, "Bad socket type specified. Valid types are: udp4, udp6"_s, "ERR_SOCKET_BAD_TYPE"_s));
return JSC::JSValue::encode(createError(globalObject, NodeErrorCode::ERR_SOCKET_BAD_TYPE, "Bad socket type specified. Valid types are: udp4, udp6"_s));
}
} // namespace Bun
JSC::JSValue WebCore::toJS(JSC::JSGlobalObject* globalObject, CommonAbortReason abortReason)
{
switch (abortReason) {
case CommonAbortReason::Timeout: {
return createError(globalObject, Bun::NodeErrorCode::ABORT_ERR, "The operation timed out"_s);
}
case CommonAbortReason::UserAbort: {
return createError(globalObject, Bun::NodeErrorCode::ABORT_ERR, "The operation was aborted by the user"_s);
}
case CommonAbortReason::ConnectionClosed: {
return createError(globalObject, Bun::NodeErrorCode::ABORT_ERR, "The connection was closed"_s);
}
default: {
break;
}
}
RELEASE_ASSERT_NOT_REACHED();
}
extern "C" JSC::EncodedJSValue WebCore__CommonAbortReason__toJS(JSC::JSGlobalObject* globalObject, WebCore::CommonAbortReason abortReason)
{
return JSC::JSValue::encode(WebCore::toJS(globalObject, abortReason));
}

View File

@@ -1,7 +1,80 @@
#pragma once
#include "ZigGlobalObject.h"
#include "root.h"
#include <JavaScriptCore/JSInternalFieldObjectImpl.h>
#include <JavaScriptCore/JSInternalFieldObjectImplInlines.h>
#include "BunClientData.h"
namespace Bun {
// clang-format off
#define FOR_EACH_NODE_ERROR_WITH_CODE(macro) \
macro(TypeError, TypeError, ERR_INVALID_ARG_TYPE) \
macro(RangeError, RangeError, ERR_OUT_OF_RANGE) \
macro(Error, Error, ERR_IPC_DISCONNECTED) \
macro(Error, Error, ERR_SERVER_NOT_RUNNING) \
macro(TypeError, TypeError, ERR_MISSING_ARGS) \
macro(Error, Error, ERR_IPC_CHANNEL_CLOSED) \
macro(TypeError, TypeError, ERR_SOCKET_BAD_TYPE) \
macro(Error, AbortError, ABORT_ERR)
#define COUNT_ERROR_WITH_CODE_ENUM(E, name, code) +1
static constexpr size_t NODE_ERROR_COUNT = 0 FOR_EACH_NODE_ERROR_WITH_CODE(COUNT_ERROR_WITH_CODE_ENUM);
#undef COUNT_ERROR_WITH_CODE_ENUM
using namespace JSC;
// clang-format on
enum NodeErrorCode : uint8_t {
#define DECLARE_ERROR_WITH_CODE_ENUM(E, name, code) code,
FOR_EACH_NODE_ERROR_WITH_CODE(DECLARE_ERROR_WITH_CODE_ENUM)
#undef DECLARE_ERROR_WITH_CODE_ENUM
};
class NodeErrorCache : public JSC::JSInternalFieldObjectImpl<NODE_ERROR_COUNT> {
public:
using Base = JSInternalFieldObjectImpl<NODE_ERROR_COUNT>;
using Field = NodeErrorCode;
DECLARE_EXPORT_INFO;
static size_t allocationSize(Checked<size_t> inlineCapacity)
{
ASSERT_UNUSED(inlineCapacity, inlineCapacity == 0U);
return sizeof(NodeErrorCache);
}
template<typename, SubspaceAccess mode>
static GCClient::IsoSubspace* subspaceFor(JSC::VM& vm)
{
if constexpr (mode == JSC::SubspaceAccess::Concurrently)
return nullptr;
return WebCore::subspaceForImpl<NodeErrorCache, WebCore::UseCustomHeapCellType::No>(
vm,
[](auto& spaces) { return spaces.m_clientSubspaceForNodeErrors.get(); },
[](auto& spaces, auto&& space) { spaces.m_clientSubspaceForNodeErrors = std::forward<decltype(space)>(space); },
[](auto& spaces) { return spaces.m_subspaceForNodeErrors.get(); },
[](auto& spaces, auto&& space) { spaces.m_subspaceForNodeErrors = std::forward<decltype(space)>(space); });
}
static NodeErrorCache* create(VM& vm, Structure* structure);
static Structure* createStructure(VM& vm, JSGlobalObject* globalObject);
JSObject* createError(VM& vm, Zig::GlobalObject* globalObject, NodeErrorCode code, JSValue message, JSValue options);
private:
JS_EXPORT_PRIVATE NodeErrorCache(VM&, Structure*);
DECLARE_VISIT_CHILDREN_WITH_MODIFIER(JS_EXPORT_PRIVATE);
void finishCreation(VM&);
};
JSC::JSObject* createError(Zig::GlobalObject* globalObject, NodeErrorCode code, const WTF::String& message);
JSC::JSObject* createError(JSC::JSGlobalObject* globalObject, NodeErrorCode code, const WTF::String& message);
JSC::JSObject* createError(Zig::GlobalObject* globalObject, NodeErrorCode code, JSC::JSValue message);
JSC::JSObject* createError(VM& vm, Zig::GlobalObject* globalObject, NodeErrorCode code, JSValue message, JSValue options = jsUndefined());
JSC::JSValue toJS(JSC::JSGlobalObject*, NodeErrorCode);
JSC_DEFINE_HOST_FUNCTION(jsFunction_ERR_INVALID_ARG_TYPE, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callFrame));
JSC_DEFINE_HOST_FUNCTION(jsFunction_ERR_OUT_OF_RANGE, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callFrame));
JSC_DEFINE_HOST_FUNCTION(jsFunction_ERR_IPC_DISCONNECTED, (JSC::JSGlobalObject * globalObject, JSC::CallFrame*));

View File

@@ -146,6 +146,7 @@
#include "UtilInspect.h"
#include "Base64Helpers.h"
#include "wtf/text/OrdinalNumber.h"
#include "NodeError.h"
#if ENABLE(REMOTE_INSPECTOR)
#include "JavaScriptCore/RemoteInspectorServer.h"
@@ -2695,6 +2696,15 @@ void GlobalObject::finishCreation(VM& vm)
init.set(Bun::createUtilInspectOptionsStructure(init.vm, init.owner));
});
m_nodeErrorCache.initLater(
[](const Initializer<JSObject>& init) {
auto* structure = NodeErrorCache::createStructure(
init.vm,
init.owner);
init.set(NodeErrorCache::create(init.vm, structure));
});
m_utilInspectStylizeColorFunction.initLater(
[](const Initializer<JSFunction>& init) {
JSC::MarkedArgumentBuffer args;
@@ -3553,6 +3563,8 @@ void GlobalObject::visitChildrenImpl(JSCell* cell, Visitor& visitor)
thisObject->mockModule.mockWithImplementationCleanupDataStructure.visit(visitor);
thisObject->mockModule.withImplementationCleanupFunction.visit(visitor);
thisObject->m_nodeErrorCache.visit(visitor);
for (auto& barrier : thisObject->m_thenables) {
visitor.append(barrier);
}

View File

@@ -402,6 +402,9 @@ public:
//
LazyProperty<JSGlobalObject, JSC::JSFunction> m_errorConstructorPrepareStackTraceInternalValue;
LazyProperty<JSGlobalObject, JSObject> m_nodeErrorCache;
JSObject* nodeErrorCache() const { return m_nodeErrorCache.getInitializedOnMainThread(this); }
Structure* memoryFootprintStructure()
{
return m_memoryFootprintStructure.getInitializedOnMainThread(this);

View File

@@ -5547,49 +5547,6 @@ extern "C" WebCore__AbortSignal* WebCore__AbortSignal__fromJS(JSC__JSValue value
return reinterpret_cast<WebCore__AbortSignal*>(&object->wrapped());
}
static auto ABORT_ERROR_NAME = MAKE_STATIC_STRING_IMPL("AbortError");
extern "C" JSC__JSValue WebCore__AbortSignal__createAbortError(const ZigString* message, const ZigString* arg1,
JSC__JSGlobalObject* globalObject)
{
JSC::VM& vm = globalObject->vm();
ZigString code = *arg1;
JSC::JSObject* error = Zig::getErrorInstance(message, globalObject).asCell()->getObject();
error->putDirect(
vm, vm.propertyNames->name,
JSC::JSValue(JSC::jsOwnedString(vm, ABORT_ERROR_NAME)),
0);
if (code.len > 0) {
auto clientData = WebCore::clientData(vm);
JSC::JSValue codeValue = Zig::toJSStringValue(code, globalObject);
error->putDirect(vm, clientData->builtinNames().codePublicName(), codeValue, 0);
}
return JSC::JSValue::encode(error);
}
static auto TIMEOUT_ERROR_NAME = MAKE_STATIC_STRING_IMPL("TimeoutError");
extern "C" JSC__JSValue WebCore__AbortSignal__createTimeoutError(const ZigString* message, const ZigString* arg1,
JSC__JSGlobalObject* globalObject)
{
JSC::VM& vm = globalObject->vm();
ZigString code = *arg1;
JSC::JSObject* error = Zig::getErrorInstance(message, globalObject).asCell()->getObject();
error->putDirect(
vm, vm.propertyNames->name,
JSC::JSValue(JSC::jsOwnedString(vm, TIMEOUT_ERROR_NAME)),
0);
if (code.len > 0) {
auto clientData = WebCore::clientData(vm);
JSC::JSValue codeValue = Zig::toJSStringValue(code, globalObject);
error->putDirect(vm, clientData->builtinNames().codePublicName(), codeValue, 0);
}
return JSC::JSValue::encode(error);
}
CPP_DECL double JSC__JSValue__getUnixTimestamp(JSC__JSValue timeValue)
{

View File

@@ -2003,6 +2003,18 @@ pub fn PromiseCallback(comptime Type: type, comptime CallbackFunction: fn (*Type
}.callback;
}
pub const CommonAbortReason = enum(u8) {
Timeout = 1,
UserAbort = 2,
ConnectionClosed = 3,
pub fn toJS(this: CommonAbortReason, global: *JSGlobalObject) JSValue {
return WebCore__CommonAbortReason__toJS(global, this);
}
extern fn WebCore__CommonAbortReason__toJS(*JSGlobalObject, CommonAbortReason) JSValue;
};
pub const AbortSignal = extern opaque {
pub const shim = Shimmer("WebCore", "AbortSignal", @This());
const cppFn = shim.cppFn;
@@ -2042,12 +2054,15 @@ pub const AbortSignal = extern opaque {
return cppFn("cleanNativeBindings", .{ this, ctx });
}
extern fn WebCore__AbortSignal__signal(*AbortSignal, *JSC.JSGlobalObject, CommonAbortReason) void;
pub fn signal(
this: *AbortSignal,
reason: JSValue,
) *AbortSignal {
globalObject: *JSC.JSGlobalObject,
reason: CommonAbortReason,
) void {
bun.Analytics.Features.abort_signal += 1;
return cppFn("signal", .{ this, reason });
return WebCore__AbortSignal__signal(this, globalObject, reason);
}
/// This function is not threadsafe. aborted is a boolean, not an atomic!
@@ -2095,15 +2110,7 @@ pub const AbortSignal = extern opaque {
return WebCore__AbortSignal__new(global);
}
pub fn createAbortError(message: *const ZigString, code: *const ZigString, global: *JSGlobalObject) JSValue {
return cppFn("createAbortError", .{ message, code, global });
}
pub fn createTimeoutError(message: *const ZigString, code: *const ZigString, global: *JSGlobalObject) JSValue {
return cppFn("createTimeoutError", .{ message, code, global });
}
pub const Extern = [_][]const u8{ "createAbortError", "createTimeoutError", "create", "ref", "unref", "signal", "abortReason", "aborted", "addListener", "fromJS", "toJS", "cleanNativeBindings" };
pub const Extern = [_][]const u8{ "create", "ref", "unref", "signal", "abortReason", "aborted", "addListener", "fromJS", "toJS", "cleanNativeBindings" };
};
pub const JSPromise = extern struct {

View File

@@ -231,8 +231,6 @@ CPP_DECL JSC__JSValue WebCore__AbortSignal__abortReason(WebCore__AbortSignal* ar
CPP_DECL WebCore__AbortSignal* WebCore__AbortSignal__addListener(WebCore__AbortSignal* arg0, void* arg1, void(* ArgFn2)(void* arg0, JSC__JSValue JSValue1));
CPP_DECL void WebCore__AbortSignal__cleanNativeBindings(WebCore__AbortSignal* arg0, void* arg1);
CPP_DECL JSC__JSValue WebCore__AbortSignal__create(JSC__JSGlobalObject* arg0);
CPP_DECL JSC__JSValue WebCore__AbortSignal__createAbortError(const ZigString* arg0, const ZigString* arg1, JSC__JSGlobalObject* arg2);
CPP_DECL JSC__JSValue WebCore__AbortSignal__createTimeoutError(const ZigString* arg0, const ZigString* arg1, JSC__JSGlobalObject* arg2);
CPP_DECL WebCore__AbortSignal* WebCore__AbortSignal__fromJS(JSC__JSValue JSValue0);
CPP_DECL WebCore__AbortSignal* WebCore__AbortSignal__ref(WebCore__AbortSignal* arg0);
CPP_DECL WebCore__AbortSignal* WebCore__AbortSignal__signal(WebCore__AbortSignal* arg0, JSC__JSValue JSValue1);

View File

@@ -143,8 +143,6 @@ pub extern fn WebCore__AbortSignal__abortReason(arg0: ?*bindings.AbortSignal) JS
pub extern fn WebCore__AbortSignal__addListener(arg0: ?*bindings.AbortSignal, arg1: ?*anyopaque, ArgFn2: ?*const fn (?*anyopaque, JSC__JSValue) callconv(.C) void) ?*bindings.AbortSignal;
pub extern fn WebCore__AbortSignal__cleanNativeBindings(arg0: ?*bindings.AbortSignal, arg1: ?*anyopaque) void;
pub extern fn WebCore__AbortSignal__create(arg0: *bindings.JSGlobalObject) JSC__JSValue;
pub extern fn WebCore__AbortSignal__createAbortError(arg0: [*c]const ZigString, arg1: [*c]const ZigString, arg2: *bindings.JSGlobalObject) JSC__JSValue;
pub extern fn WebCore__AbortSignal__createTimeoutError(arg0: [*c]const ZigString, arg1: [*c]const ZigString, arg2: *bindings.JSGlobalObject) JSC__JSValue;
pub extern fn WebCore__AbortSignal__fromJS(JSValue0: JSC__JSValue) ?*bindings.AbortSignal;
pub extern fn WebCore__AbortSignal__ref(arg0: ?*bindings.AbortSignal) ?*bindings.AbortSignal;
pub extern fn WebCore__AbortSignal__signal(arg0: ?*bindings.AbortSignal, JSValue1: JSC__JSValue) ?*bindings.AbortSignal;

View File

@@ -32,6 +32,7 @@
#include "Event.h"
#include "EventNames.h"
#include "JSDOMException.h"
#include "JavaScriptCore/JSCJSValue.h"
#include "ScriptExecutionContext.h"
#include "WebCoreOpaqueRoot.h"
#include "wtf/DebugHeap.h"
@@ -112,6 +113,20 @@ AbortSignal::AbortSignal(ScriptExecutionContext* context, Aborted aborted, JSC::
AbortSignal::~AbortSignal() = default;
JSValue AbortSignal::jsReason(JSC::JSGlobalObject& globalObject)
{
JSValue existingValue = m_reason.getValue(jsUndefined());
if (existingValue.isUndefined()) {
if (m_commonReason != CommonAbortReason::None) {
existingValue = toJS(&globalObject, m_commonReason);
m_commonReason = CommonAbortReason::None;
m_reason.setWeakly(existingValue);
}
}
return existingValue;
}
void AbortSignal::addSourceSignal(AbortSignal& signal)
{
if (signal.isDependent()) {
@@ -164,6 +179,16 @@ void AbortSignal::signalAbort(JSC::JSValue reason)
dependentSignal->signalAbort(reason);
}
void AbortSignal::signalAbort(JSC::JSGlobalObject* globalObject, CommonAbortReason reason)
{
// 1. If signal's aborted flag is set, then return.
if (m_aborted)
return;
m_commonReason = reason;
signalAbort(toJS(globalObject, reason));
}
void AbortSignal::cleanNativeBindings(void* ref)
{
auto callbacks = std::exchange(m_native_callbacks, {});
@@ -183,7 +208,7 @@ void AbortSignal::signalFollow(AbortSignal& signal)
return;
if (signal.aborted()) {
signalAbort(signal.reason().getValue());
signalAbort(signal.jsReason(*scriptExecutionContext()->jsGlobalObject()));
return;
}
@@ -203,7 +228,8 @@ void AbortSignal::eventListenersDidChange()
uint32_t AbortSignal::addAbortAlgorithmToSignal(AbortSignal& signal, Ref<AbortAlgorithm>&& algorithm)
{
if (signal.aborted()) {
algorithm->handleEvent(signal.m_reason.getValue());
// TODO: Null check.
algorithm->handleEvent(signal.jsReason(*signal.scriptExecutionContext()->jsGlobalObject()));
return 0;
}
return signal.addAlgorithm([algorithm = WTFMove(algorithm)](JSC::JSValue value) mutable {

View File

@@ -30,6 +30,8 @@
#include "ContextDestructionObserver.h"
#include "EventTarget.h"
#include "JSValueInWrappedObject.h"
#include "JavaScriptCore/JSGlobalObject.h"
#include "ZigGlobalObject.h"
#include "wtf/DebugHeap.h"
#include "wtf/FastMalloc.h"
#include <wtf/Function.h>
@@ -46,6 +48,15 @@ class WebCoreOpaqueRoot;
DECLARE_ALLOCATOR_WITH_HEAP_IDENTIFIER(AbortSignal);
enum class CommonAbortReason : uint8_t {
None,
Timeout,
UserAbort,
ConnectionClosed,
};
JSC::JSValue toJS(JSC::JSGlobalObject*, CommonAbortReason);
class AbortSignal final : public RefCounted<AbortSignal>, public EventTargetWithInlineData, private ContextDestructionObserver {
WTF_MAKE_FAST_ALLOCATED_WITH_HEAP_IDENTIFIER(AbortSignal);
@@ -61,11 +72,13 @@ public:
static uint32_t addAbortAlgorithmToSignal(AbortSignal&, Ref<AbortAlgorithm>&&);
static void removeAbortAlgorithmFromSignal(AbortSignal&, uint32_t algorithmIdentifier);
void signalAbort(JSC::JSGlobalObject* globalObject, CommonAbortReason reason);
void signalAbort(JSC::JSValue reason);
void signalFollow(AbortSignal&);
bool aborted() const { return m_aborted; }
const JSValueInWrappedObject& reason() const { return m_reason; }
JSValue jsReason(JSC::JSGlobalObject& globalObject);
void cleanNativeBindings(void* ref);
void addNativeCallback(NativeCallbackTuple callback) { m_native_callbacks.append(callback); }
@@ -89,8 +102,10 @@ public:
AbortSignalSet& sourceSignals() { return m_sourceSignals; }
private:
enum class Aborted : bool { No,
Yes };
enum class Aborted : bool {
No,
Yes
};
explicit AbortSignal(ScriptExecutionContext*, Aborted = Aborted::No, JSC::JSValue reason = JSC::jsUndefined());
void setHasActiveTimeoutTimer(bool hasActiveTimeoutTimer) { m_hasActiveTimeoutTimer = hasActiveTimeoutTimer; }
@@ -112,6 +127,7 @@ private:
AbortSignalSet m_sourceSignals;
AbortSignalSet m_dependentSignals;
JSValueInWrappedObject m_reason;
CommonAbortReason m_commonReason { CommonAbortReason::None };
Vector<NativeCallbackTuple, 2> m_native_callbacks;
uint32_t m_algorithmIdentifier { 0 };
bool m_aborted { false };

View File

@@ -44,6 +44,7 @@ public:
std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForMockWithImplementationCleanupData;
std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForProcessObject;
std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForInternalModuleRegistry;
std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForNodeErrors;
std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForBunInspectorConnection;
std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForJSNextTickQueue;
std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForNAPIFunction;

View File

@@ -44,6 +44,7 @@ public:
std::unique_ptr<IsoSubspace> m_subspaceForMockWithImplementationCleanupData;
std::unique_ptr<IsoSubspace> m_subspaceForProcessObject;
std::unique_ptr<IsoSubspace> m_subspaceForInternalModuleRegistry;
std::unique_ptr<IsoSubspace> m_subspaceForNodeErrors;
std::unique_ptr<IsoSubspace> m_subspaceForBunInspectorConnection;
std::unique_ptr<IsoSubspace> m_subspaceForJSNextTickQueue;
std::unique_ptr<IsoSubspace> m_subspaceForNAPIFunction;

View File

@@ -225,7 +225,7 @@ static inline JSValue jsAbortSignal_reasonGetter(JSGlobalObject& lexicalGlobalOb
auto& vm = JSC::getVM(&lexicalGlobalObject);
auto throwScope = DECLARE_THROW_SCOPE(vm);
auto& impl = thisObject.wrapped();
RELEASE_AND_RETURN(throwScope, (toJS<IDLAny>(lexicalGlobalObject, throwScope, impl.reason())));
RELEASE_AND_RETURN(throwScope, (toJS<IDLAny>(lexicalGlobalObject, throwScope, impl.jsReason(lexicalGlobalObject))));
}
JSC_DEFINE_CUSTOM_GETTER(jsAbortSignal_reason, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue thisValue, PropertyName attributeName))

View File

@@ -399,10 +399,12 @@ extern "C" void WebWorker__dispatchExit(Zig::GlobalObject* globalObject, Worker*
JSC::VM& vm = globalObject->vm();
vm.setHasTerminationRequest();
while (!vm.hasOneRef())
vm.deref();
// clang-tidy is smart enough to realize that deref() leads to freeing
// but it's not smart enough to realize that `hasOneRef()` ensures its safety
while (!vm.hasOneRef()) // NOLINT
vm.deref(); // NOLINT
vm.deref();
vm.deref(); // NOLINT
}
}
extern "C" void WebWorker__dispatchOnline(Worker* worker, Zig::GlobalObject* globalObject)

View File

@@ -535,7 +535,7 @@ pub const FSWatcher = struct {
listener.ensureStillAlive();
var args = [_]JSC.JSValue{
EventType.@"error".toJS(this.globalThis),
if (err.isEmptyOrUndefinedOrNull()) JSC.WebCore.AbortSignal.createAbortError(JSC.ZigString.static("The user aborted a request"), &JSC.ZigString.Empty, this.globalThis) else err,
JSC.CommonAbortReason.UserAbort.toJS(this.globalThis),
};
_ = listener.callWithGlobalThis(
this.globalThis,

View File

@@ -321,10 +321,24 @@ pub const Body = struct {
Message: bun.String,
JSValue: JSC.Strong,
pub fn toStreamError(this: *@This(), globalObject: *JSC.JSGlobalObject) JSC.WebCore.StreamResult.StreamError {
return switch (this.*) {
.Aborted => .{
.AbortReason = JSC.CommonAbortReason.UserAbort,
},
.Timeout => .{
.AbortReason = JSC.CommonAbortReason.Timeout,
},
else => .{
.JSValue = this.toJS(globalObject),
},
};
}
pub fn toJS(this: *@This(), globalObject: *JSC.JSGlobalObject) JSC.JSValue {
const js_value = switch (this.*) {
.Timeout => JSC.WebCore.AbortSignal.createTimeoutError(JSC.ZigString.static("The operation timed out"), &JSC.ZigString.Empty, globalObject),
.Aborted => JSC.WebCore.AbortSignal.createAbortError(JSC.ZigString.static("The user aborted a request"), &JSC.ZigString.Empty, globalObject),
.Timeout => JSC.CommonAbortReason.Timeout.toJS(globalObject),
.Aborted => JSC.CommonAbortReason.UserAbort.toJS(globalObject),
.SystemError => |system_error| system_error.toErrorInstance(globalObject),
.Message => |message| message.toErrorInstance(globalObject),
// do a early return in this case we don't need to create a new Strong
@@ -927,12 +941,12 @@ pub const Body = struct {
}
}
// The Promise version goes before the ReadableStream version incase the Promise version is used too.
// Avoid creating unnecessary duplicate JSValue.
if (strong_readable.get()) |readable| {
if (readable.ptr == .Bytes) {
readable.ptr.Bytes.onData(
.{
.err = .{ .JSValue = this.Error.toJS(global) },
},
.{ .err = this.Error.toStreamError(global) },
bun.default_allocator,
);
} else {

View File

@@ -1262,7 +1262,7 @@ pub const Fetch = struct {
if (signal.aborted()) {
this.abort_reason = signal.abortReason();
if (this.abort_reason.isEmptyOrUndefinedOrNull()) {
return JSC.WebCore.AbortSignal.createAbortError(JSC.ZigString.static("The user aborted a request"), &JSC.ZigString.Empty, this.global_this);
return JSC.CommonAbortReason.UserAbort.toJS(this.global_this);
}
this.abort_reason.protect();
return this.abort_reason;

View File

@@ -660,7 +660,7 @@ pub const DrainResult = union(enum) {
pub const StreamResult = union(Tag) {
pending: *Pending,
err: union(Err) { Error: Syscall.Error, JSValue: JSC.JSValue },
err: StreamError,
done: void,
owned: bun.ByteList,
owned_and_done: bun.ByteList,
@@ -682,9 +682,28 @@ pub const StreamResult = union(Tag) {
}
}
pub const Err = enum {
Error,
JSValue,
pub const StreamError = union(enum) {
Error: Syscall.Error,
AbortReason: JSC.CommonAbortReason,
JSValue: JSC.JSValue,
pub fn toJS(this: *@This(), globalObject: *JSC.JSGlobalObject) JSC.JSValue {
return switch (this.*) {
.Error => |*err| {
const value = err.toJSC(globalObject);
value.protect();
this.* = .{ .JSValue = value };
return value;
},
.JSValue => this.JSValue,
.AbortReason => |reason| {
const value = reason.toJS(globalObject);
value.protect();
this.* = .{ .JSValue = value };
return value;
},
};
}
};
pub const Tag = enum {
@@ -943,11 +962,9 @@ pub const StreamResult = union(Tag) {
defer loop.exit();
switch (result.*) {
.err => |err| {
.err => |*err| {
const value = brk: {
if (err == .Error) break :brk err.Error.toJSC(globalThis);
const js_err = err.JSValue;
const js_err = err.toJS(globalThis);
js_err.ensureStillAlive();
js_err.unprotect();
@@ -4332,13 +4349,9 @@ pub const ByteStream = struct {
if (to_copy.len == 0) {
if (stream == .err) {
if (stream.err == .Error) {
this.pending.result = .{ .err = .{ .Error = stream.err.Error } };
}
const js_err = stream.err.JSValue;
js_err.ensureStillAlive();
js_err.protect();
this.pending.result = .{ .err = .{ .JSValue = js_err } };
this.pending.result = .{
.err = stream.err,
};
} else {
this.pending.result = .{
.done = {},

View File

@@ -138,204 +138,7 @@ typedef void (*uws_get_headers_server_handler)(const char *header_name,
size_t header_value_size,
void *user_data);
// Basic HTTP
uws_app_t *uws_create_app(int ssl,
struct us_bun_socket_context_options_t options);
void uws_app_destroy(int ssl, uws_app_t *app);
void uws_app_get(int ssl, uws_app_t *app, const char *pattern,
uws_method_handler handler, void *user_data);
void uws_app_post(int ssl, uws_app_t *app, const char *pattern,
uws_method_handler handler, void *user_data);
void uws_app_options(int ssl, uws_app_t *app, const char *pattern,
uws_method_handler handler, void *user_data);
void uws_app_delete(int ssl, uws_app_t *app, const char *pattern,
uws_method_handler handler, void *user_data);
void uws_app_patch(int ssl, uws_app_t *app, const char *pattern,
uws_method_handler handler, void *user_data);
void uws_app_put(int ssl, uws_app_t *app, const char *pattern,
uws_method_handler handler, void *user_data);
void uws_app_head(int ssl, uws_app_t *app, const char *pattern,
uws_method_handler handler, void *user_data);
void uws_app_connect(int ssl, uws_app_t *app, const char *pattern,
uws_method_handler handler, void *user_data);
void uws_app_trace(int ssl, uws_app_t *app, const char *pattern,
uws_method_handler handler, void *user_data);
void uws_app_any(int ssl, uws_app_t *app, const char *pattern,
uws_method_handler handler, void *user_data);
void uws_app_run(int ssl, uws_app_t *);
void uws_app_listen(int ssl, uws_app_t *app, int port,
uws_listen_handler handler, void *user_data);
void uws_app_listen_with_config(int ssl, uws_app_t *app, const char *host,
uint16_t port, int32_t options,
uws_listen_handler handler, void *user_data);
void uws_app_listen_domain(int ssl, uws_app_t *app, const char *domain,
size_t pathlen, uws_listen_domain_handler handler,
void *user_data);
void uws_app_listen_domain_with_options(int ssl, uws_app_t *app,
const char *domain, size_t pathlen,
int options,
uws_listen_domain_handler handler,
void *user_data);
void uws_app_domain(int ssl, uws_app_t *app, const char *server_name);
bool uws_constructor_failed(int ssl, uws_app_t *app);
unsigned int uws_num_subscribers(int ssl, uws_app_t *app, const char *topic,
size_t topic_length);
bool uws_publish(int ssl, uws_app_t *app, const char *topic,
size_t topic_length, const char *message,
size_t message_length, uws_opcode_t opcode, bool compress);
void *uws_get_native_handle(int ssl, uws_app_t *app);
void uws_remove_server_name(int ssl, uws_app_t *app,
const char *hostname_pattern);
void uws_add_server_name(int ssl, uws_app_t *app, const char *hostname_pattern);
void uws_add_server_name_with_options(
int ssl, uws_app_t *app, const char *hostname_pattern,
struct us_bun_socket_context_options_t options);
void uws_missing_server_name(int ssl, uws_app_t *app,
uws_missing_server_handler handler,
void *user_data);
void uws_filter(int ssl, uws_app_t *app, uws_filter_handler handler,
void *user_data);
// WebSocket
void uws_ws(int ssl, uws_app_t *app, void *upgradeCtx, const char *pattern,
size_t pattern_length, size_t id,
const uws_socket_behavior_t *behavior);
void *uws_ws_get_user_data(int ssl, uws_websocket_t *ws);
void uws_ws_close(int ssl, uws_websocket_t *ws);
uws_sendstatus_t uws_ws_send(int ssl, uws_websocket_t *ws, const char *message,
size_t length, uws_opcode_t opcode);
uws_sendstatus_t uws_ws_send_with_options(int ssl, uws_websocket_t *ws,
const char *message, size_t length,
uws_opcode_t opcode, bool compress,
bool fin);
uws_sendstatus_t uws_ws_send_fragment(int ssl, uws_websocket_t *ws,
const char *message, size_t length,
bool compress);
uws_sendstatus_t uws_ws_send_first_fragment(int ssl, uws_websocket_t *ws,
const char *message, size_t length,
bool compress);
uws_sendstatus_t
uws_ws_send_first_fragment_with_opcode(int ssl, uws_websocket_t *ws,
const char *message, size_t length,
uws_opcode_t opcode, bool compress);
uws_sendstatus_t uws_ws_send_last_fragment(int ssl, uws_websocket_t *ws,
const char *message, size_t length,
bool compress);
void uws_ws_end(int ssl, uws_websocket_t *ws, int code, const char *message,
size_t length);
void uws_ws_cork(int ssl, uws_websocket_t *ws, void (*handler)(void *user_data),
void *user_data);
bool uws_ws_subscribe(int ssl, uws_websocket_t *ws, const char *topic,
size_t length);
bool uws_ws_unsubscribe(int ssl, uws_websocket_t *ws, const char *topic,
size_t length);
bool uws_ws_is_subscribed(int ssl, uws_websocket_t *ws, const char *topic,
size_t length);
void uws_ws_iterate_topics(int ssl, uws_websocket_t *ws,
void (*callback)(const char *topic, size_t length,
void *user_data),
void *user_data);
bool uws_ws_publish(int ssl, uws_websocket_t *ws, const char *topic,
size_t topic_length, const char *message,
size_t message_length);
bool uws_ws_publish_with_options(int ssl, uws_websocket_t *ws,
const char *topic, size_t topic_length,
const char *message, size_t message_length,
uws_opcode_t opcode, bool compress);
unsigned int uws_ws_get_buffered_amount(int ssl, uws_websocket_t *ws);
size_t uws_ws_get_remote_address(int ssl, uws_websocket_t *ws,
const char **dest);
size_t uws_ws_get_remote_address_as_text(int ssl, uws_websocket_t *ws,
const char **dest);
// Response
void uws_res_end(int ssl, uws_res_t *res, const char *data, size_t length,
bool close_connection);
void uws_res_pause(int ssl, uws_res_t *res);
void uws_res_resume(int ssl, uws_res_t *res);
void uws_res_write_continwue(int ssl, uws_res_t *res);
void uws_res_write_status(int ssl, uws_res_t *res, const char *status,
size_t length);
void uws_res_write_header(int ssl, uws_res_t *res, const char *key,
size_t key_length, const char *value,
size_t value_length);
void uws_res_write_header_int(int ssl, uws_res_t *res, const char *key,
size_t key_length, uint64_t value);
void uws_res_end_without_body(int ssl, uws_res_t *res, bool close_connection);
void uws_res_end_stream(int ssl, uws_res_t *res, bool close_connection);
bool uws_res_write(int ssl, uws_res_t *res, const char *data, size_t length);
uint64_t uws_res_get_write_offset(int ssl, uws_res_t *res);
bool uws_res_has_responded(int ssl, uws_res_t *res);
void uws_res_on_writable(int ssl, uws_res_t *res,
bool (*handler)(uws_res_t *res, uint64_t,
void *opcional_data),
void *user_data);
void uws_res_on_aborted(int ssl, uws_res_t *res,
void (*handler)(uws_res_t *res, void *opcional_data),
void *opcional_data);
void uws_res_on_data(int ssl, uws_res_t *res,
void (*handler)(uws_res_t *res, const char *chunk,
size_t chunk_length, bool is_end,
void *opcional_data),
void *opcional_data);
void uws_res_upgrade(int ssl, uws_res_t *res, void *data,
const char *sec_web_socket_key,
size_t sec_web_socket_key_length,
const char *sec_web_socket_protocol,
size_t sec_web_socket_protocol_length,
const char *sec_web_socket_extensions,
size_t sec_web_socket_extensions_length,
uws_socket_context_t *ws);
// Request
bool uws_req_is_ancient(uws_req_t *res);
bool uws_req_get_yield(uws_req_t *res);
void uws_req_set_yield(uws_req_t *res, bool yield);
size_t uws_req_get_url(uws_req_t *res, const char **dest);
size_t uws_req_get_method(uws_req_t *res, const char **dest);
size_t uws_req_get_header(uws_req_t *res, const char *lower_case_header,
size_t lower_case_header_length, const char **dest);
size_t uws_req_get_query(uws_req_t *res, const char *key, size_t key_length,
const char **dest);
size_t uws_req_get_parameter(uws_req_t *res, unsigned short index,
const char **dest);
void uws_req_for_each_header(uws_req_t *res,
uws_get_headers_server_handler handler,
void *user_data);
struct us_loop_t *uws_get_loop();
struct us_loop_t *uws_get_loop_with_native(void *existing_native_loop);
void uws_loop_addPostHandler(us_loop_t *loop, void *ctx_,
void (*cb)(void *ctx, us_loop_t *loop));
void uws_loop_removePostHandler(us_loop_t *loop, void *key);
void uws_loop_addPreHandler(us_loop_t *loop, void *key,
void (*cb)(void *ctx, us_loop_t *loop));
void uws_loop_removePreHandler(us_loop_t *loop, void *ctx_);
void uws_loop_defer(us_loop_t *loop, void *ctx, void (*cb)(void *ctx));
void uws_res_write_headers(int ssl, uws_res_t *res, const StringPointer *names,
const StringPointer *values, size_t count,
const char *buf);
void *uws_res_get_native_handle(int ssl, uws_res_t *res);
void uws_res_uncork(int ssl, uws_res_t *res);
void us_socket_mark_needs_more_not_ssl(uws_res_t *res);
int uws_res_state(int ssl, uws_res_t *res);
bool uws_res_try_end(int ssl, uws_res_t *res, const char *bytes, size_t len,
size_t total_len, bool close);
void uws_res_prepare_for_sendfile(int ssl, uws_res_t *res);
void uws_res_override_write_offset(int ssl, uws_res_t *res, uint64_t offset);
void uws_app_close(int ssl, uws_app_t *app);
#ifdef __cplusplus
}

View File

@@ -1,5 +1,6 @@
// clang-format off
#include "_libusockets.h"
#include "libusockets.h"
#include <bun-uws/src/App.h>
#include <bun-uws/src/AsyncSocket.h>
#include <bun-usockets/src/internal/internal.h>
@@ -7,6 +8,8 @@
extern "C" const char* ares_inet_ntop(int af, const char *src, char *dst, size_t size);
#define uws_res_r uws_res_t* nonnull_arg
extern "C"
{
@@ -1015,7 +1018,7 @@ extern "C"
return value.length();
}
void uws_res_end(int ssl, uws_res_t *res, const char *data, size_t length,
void uws_res_end(int ssl, uws_res_r res, const char *data, size_t length,
bool close_connection)
{
if (ssl)
@@ -1032,7 +1035,7 @@ extern "C"
}
}
void uws_res_end_stream(int ssl, uws_res_t *res, bool close_connection)
void uws_res_end_stream(int ssl, uws_res_r res, bool close_connection)
{
if (ssl)
{
@@ -1048,7 +1051,7 @@ extern "C"
}
}
void uws_res_pause(int ssl, uws_res_t *res)
void uws_res_pause(int ssl, uws_res_r res)
{
if (ssl)
{
@@ -1062,7 +1065,7 @@ extern "C"
}
}
void uws_res_resume(int ssl, uws_res_t *res)
void uws_res_resume(int ssl, uws_res_r res)
{
if (ssl)
{
@@ -1076,7 +1079,7 @@ extern "C"
}
}
void uws_res_write_continue(int ssl, uws_res_t *res)
void uws_res_write_continue(int ssl, uws_res_r res)
{
if (ssl)
{
@@ -1090,7 +1093,7 @@ extern "C"
}
}
void uws_res_write_status(int ssl, uws_res_t *res, const char *status,
void uws_res_write_status(int ssl, uws_res_r res, const char *status,
size_t length)
{
if (ssl)
@@ -1105,7 +1108,7 @@ extern "C"
}
}
void uws_res_write_header(int ssl, uws_res_t *res, const char *key,
void uws_res_write_header(int ssl, uws_res_r res, const char *key,
size_t key_length, const char *value,
size_t value_length)
{
@@ -1122,7 +1125,7 @@ extern "C"
std::string_view(value, value_length));
}
}
void uws_res_write_header_int(int ssl, uws_res_t *res, const char *key,
void uws_res_write_header_int(int ssl, uws_res_r res, const char *key,
size_t key_length, uint64_t value)
{
if (ssl)
@@ -1137,7 +1140,7 @@ extern "C"
uwsRes->writeHeader(std::string_view(key, key_length), value);
}
}
void uws_res_end_sendfile(int ssl, uws_res_t *res, uint64_t offset, bool close_connection)
void uws_res_end_sendfile(int ssl, uws_res_r res, uint64_t offset, bool close_connection)
{
if (ssl)
{
@@ -1158,7 +1161,7 @@ extern "C"
us_socket_timeout(0, (us_socket_t *)uwsRes, uWS::HTTP_TIMEOUT_S);
}
}
void uws_res_end_without_body(int ssl, uws_res_t *res, bool close_connection)
void uws_res_end_without_body(int ssl, uws_res_r res, bool close_connection)
{
if (ssl)
{
@@ -1204,7 +1207,9 @@ extern "C"
}
}
bool uws_res_write(int ssl, uws_res_t *res, const char *data, size_t length)
bool uws_res_write(int ssl, uws_res_r res, const char *data, size_t length) nonnull_fn_decl;
bool uws_res_write(int ssl, uws_res_r res, const char *data, size_t length)
{
if (ssl)
{
@@ -1214,7 +1219,8 @@ extern "C"
uWS::HttpResponse<false> *uwsRes = (uWS::HttpResponse<false> *)res;
return uwsRes->write(std::string_view(data, length));
}
uint64_t uws_res_get_write_offset(int ssl, uws_res_t *res)
uint64_t uws_res_get_write_offset(int ssl, uws_res_r res) nonnull_fn_decl;
uint64_t uws_res_get_write_offset(int ssl, uws_res_r res)
{
if (ssl)
{
@@ -1225,7 +1231,8 @@ extern "C"
return uwsRes->getWriteOffset();
}
bool uws_res_has_responded(int ssl, uws_res_t *res)
bool uws_res_has_responded(int ssl, uws_res_r res) nonnull_fn_decl;
bool uws_res_has_responded(int ssl, uws_res_r res)
{
if (ssl)
{
@@ -1236,8 +1243,8 @@ extern "C"
return uwsRes->hasResponded();
}
void uws_res_on_writable(int ssl, uws_res_t *res,
bool (*handler)(uws_res_t *res, uint64_t,
void uws_res_on_writable(int ssl, uws_res_r res,
bool (*handler)(uws_res_r res, uint64_t,
void *opcional_data),
void *opcional_data)
{
@@ -1255,7 +1262,7 @@ extern "C"
}
}
void uws_res_clear_on_writable(int ssl, uws_res_t *res) {
void uws_res_clear_on_writable(int ssl, uws_res_r res) {
if (ssl) {
uWS::HttpResponse<true> *uwsRes = (uWS::HttpResponse<true> *)res;
uwsRes->clearOnWritable();
@@ -1265,8 +1272,8 @@ extern "C"
}
}
void uws_res_on_aborted(int ssl, uws_res_t *res,
void (*handler)(uws_res_t *res, void *opcional_data),
void uws_res_on_aborted(int ssl, uws_res_r res,
void (*handler)(uws_res_r res, void *opcional_data),
void *opcional_data)
{
if (ssl)
@@ -1297,8 +1304,8 @@ extern "C"
}
}
void uws_res_on_data(int ssl, uws_res_t *res,
void (*handler)(uws_res_t *res, const char *chunk,
void uws_res_on_data(int ssl, uws_res_r res,
void (*handler)(uws_res_r res, const char *chunk,
size_t chunk_length, bool is_end,
void *opcional_data),
void *opcional_data)
@@ -1359,6 +1366,9 @@ extern "C"
return value.length();
}
size_t uws_req_get_header(uws_req_t *res, const char *lower_case_header,
size_t lower_case_header_length, const char **dest) nonnull_fn_decl;
size_t uws_req_get_header(uws_req_t *res, const char *lower_case_header,
size_t lower_case_header_length, const char **dest)
{
@@ -1398,7 +1408,7 @@ extern "C"
return value.length();
}
void uws_res_upgrade(int ssl, uws_res_t *res, void *data,
void uws_res_upgrade(int ssl, uws_res_r res, void *data,
const char *sec_web_socket_key,
size_t sec_web_socket_key_length,
const char *sec_web_socket_protocol,
@@ -1470,9 +1480,12 @@ extern "C"
{ cb(ctx); });
}
void uws_res_write_headers(int ssl, uws_res_t *res, const StringPointer *names,
void uws_res_write_headers(int ssl, uws_res_r res, const StringPointer *names,
const StringPointer *values, size_t count,
const char *buf)
const char *buf) nonnull_fn_decl;
void uws_res_write_headers(int ssl, uws_res_r res, const StringPointer *names,
const StringPointer *values, size_t count,
const char *buf)
{
if (ssl)
{
@@ -1494,7 +1507,7 @@ extern "C"
}
}
void uws_res_uncork(int ssl, uws_res_t *res)
void uws_res_uncork(int ssl, uws_res_r res)
{
if (ssl)
{
@@ -1508,15 +1521,15 @@ extern "C"
}
}
void us_socket_mark_needs_more_not_ssl(uws_res_t *res)
void us_socket_mark_needs_more_not_ssl(uws_res_r res)
{
us_socket_t *s = (us_socket_t *)res;
us_socket_r s = (us_socket_t *)res;
s->context->loop->data.last_write_failed = 1;
us_poll_change(&s->p, s->context->loop,
LIBUS_SOCKET_READABLE | LIBUS_SOCKET_WRITABLE);
}
void uws_res_override_write_offset(int ssl, uws_res_t *res, uint64_t offset)
void uws_res_override_write_offset(int ssl, uws_res_r res, uint64_t offset)
{
if (ssl)
{
@@ -1528,7 +1541,11 @@ extern "C"
}
}
void uws_res_cork(int ssl, uws_res_t *res, void *ctx,
__attribute__((callback (corker, ctx)))
void uws_res_cork(int ssl, uws_res_r res, void *ctx,
void (*corker)(void *ctx)) nonnull_fn_decl;
void uws_res_cork(int ssl, uws_res_r res, void *ctx,
void (*corker)(void *ctx))
{
if (ssl)
@@ -1545,7 +1562,7 @@ extern "C"
}
}
void uws_res_prepare_for_sendfile(int ssl, uws_res_t *res)
void uws_res_prepare_for_sendfile(int ssl, uws_res_r res)
{
if (ssl)
{
@@ -1569,7 +1586,7 @@ extern "C"
}
}
bool uws_res_try_end(int ssl, uws_res_t *res, const char *bytes, size_t len,
bool uws_res_try_end(int ssl, uws_res_r res, const char *bytes, size_t len,
size_t total_len, bool close)
{
if (ssl)
@@ -1594,7 +1611,7 @@ extern "C"
}
}
int uws_res_state(int ssl, uws_res_t *res)
int uws_res_state(int ssl, uws_res_r res)
{
if (ssl)
{
@@ -1608,7 +1625,7 @@ extern "C"
}
}
void *uws_res_get_native_handle(int ssl, uws_res_t *res)
void *uws_res_get_native_handle(int ssl, uws_res_r res)
{
if (ssl)
{
@@ -1622,14 +1639,14 @@ extern "C"
}
}
void us_socket_sendfile_needs_more(us_socket_t *s) {
void us_socket_sendfile_needs_more(us_socket_r s) {
s->context->loop->data.last_write_failed = 1;
us_poll_change(&s->p, s->context->loop, LIBUS_SOCKET_READABLE | LIBUS_SOCKET_WRITABLE);
}
// Gets the remote address and port
// Returns 0 if failure / unix socket
uint64_t uws_res_get_remote_address_info(uws_res_t *res, const char **dest, int *port, bool *is_ipv6)
uint64_t uws_res_get_remote_address_info(uws_res_r res, const char **dest, int *port, bool *is_ipv6)
{
// This function is manual inlining + modification of
// us_socket_remote_address