Merge branch 'fix_compile_warnings'

This commit is contained in:
2026-02-20 14:21:10 -06:00
11 changed files with 160 additions and 153 deletions

View File

@@ -113,31 +113,34 @@ static JSValue js_miniz_compress(JSContext *js, JSValue this_val,
return JS_EXCEPTION; return JS_EXCEPTION;
} }
/* ─── 2. Allocate an output buffer big enough ────────────── */ /* ─── 2. Allocate output blob (before getting blob input ptr) ── */
mz_ulong out_len_est = mz_compressBound(in_len); mz_ulong out_len_est = mz_compressBound(in_len);
void *out_buf = js_malloc_rt(out_len_est); void *out_ptr;
if (!out_buf) { JSValue abuf = js_new_blob_alloc(js, (size_t)out_len_est, &out_ptr);
if (JS_IsException(abuf)) {
if (cstring) JS_FreeCString(js, cstring); if (cstring) JS_FreeCString(js, cstring);
return JS_EXCEPTION; return abuf;
}
/* Re-derive blob input pointer after alloc (GC may have moved it) */
if (!cstring) {
in_ptr = js_get_blob_data(js, &in_len, argv[0]);
} }
/* ─── 3. Do the compression (MZ_DEFAULT_COMPRESSION = level 6) */ /* ─── 3. Do the compression (MZ_DEFAULT_COMPRESSION = level 6) */
mz_ulong out_len = out_len_est; mz_ulong out_len = out_len_est;
int st = mz_compress2(out_buf, &out_len, int st = mz_compress2(out_ptr, &out_len,
in_ptr, in_len, MZ_DEFAULT_COMPRESSION); in_ptr, in_len, MZ_DEFAULT_COMPRESSION);
/* clean-up for string input */ /* clean-up for string input */
if (cstring) JS_FreeCString(js, cstring); if (cstring) JS_FreeCString(js, cstring);
if (st != MZ_OK) { if (st != MZ_OK)
js_free_rt(out_buf);
return JS_RaiseDisrupt(js, return JS_RaiseDisrupt(js,
"miniz: compression failed (%d)", st); "miniz: compression failed (%d)", st);
}
/* ─── 4. Hand JavaScript a copy of the compressed data ────── */ /* ─── 4. Stone with actual compressed size ────────────────── */
JSValue abuf = js_new_blob_stoned_copy(js, out_buf, out_len); js_blob_stone(abuf, (size_t)out_len);
js_free_rt(out_buf);
return abuf; return abuf;
} }

View File

@@ -98,19 +98,17 @@ JSC_CCALL(fd_read,
if (argc > 1) if (argc > 1)
size = js2number(js, argv[1]); size = js2number(js, argv[1]);
void *buf = malloc(size); void *out;
if (!buf) ret = js_new_blob_alloc(js, size, &out);
return JS_RaiseDisrupt(js, "malloc failed"); if (JS_IsException(ret)) return ret;
int bytes_read = pd_file->read(fd, buf, (unsigned int)size); int bytes_read = pd_file->read(fd, out, (unsigned int)size);
if (bytes_read < 0) { if (bytes_read < 0) {
free(buf);
const char* err = pd_file->geterr(); const char* err = pd_file->geterr();
return JS_RaiseDisrupt(js, "read failed: %s", err ? err : "unknown error"); return JS_RaiseDisrupt(js, "read failed: %s", err ? err : "unknown error");
} }
ret = js_new_blob_stoned_copy(js, buf, bytes_read); js_blob_stone(ret, bytes_read);
free(buf);
return ret; return ret;
) )
@@ -134,22 +132,17 @@ JSC_SCALL(fd_slurp,
return JS_RaiseDisrupt(js, "open failed: %s", err ? err : "unknown error"); return JS_RaiseDisrupt(js, "open failed: %s", err ? err : "unknown error");
} }
void *data = malloc(size); void *out;
if (!data) { ret = js_new_blob_alloc(js, size, &out);
pd_file->close(fd); if (JS_IsException(ret)) { pd_file->close(fd); return ret; }
return JS_RaiseDisrupt(js, "malloc failed");
}
int bytes_read = pd_file->read(fd, data, (unsigned int)size); int bytes_read = pd_file->read(fd, out, (unsigned int)size);
pd_file->close(fd); pd_file->close(fd);
if (bytes_read < 0) { if (bytes_read < 0)
free(data);
return JS_RaiseDisrupt(js, "read failed"); return JS_RaiseDisrupt(js, "read failed");
}
ret = js_new_blob_stoned_copy(js, data, bytes_read); js_blob_stone(ret, bytes_read);
free(data);
) )
JSC_CCALL(fd_lseek, JSC_CCALL(fd_lseek,

View File

@@ -102,18 +102,15 @@ JSC_CCALL(fd_read,
if (argc > 1) if (argc > 1)
size = js2number(js, argv[1]); size = js2number(js, argv[1]);
void *buf = malloc(size); void *out;
if (!buf) ret = js_new_blob_alloc(js, size, &out);
return JS_RaiseDisrupt(js, "malloc failed"); if (JS_IsException(ret)) return ret;
ssize_t bytes_read = read(fd, buf, size); ssize_t bytes_read = read(fd, out, size);
if (bytes_read < 0) { if (bytes_read < 0)
free(buf);
return JS_RaiseDisrupt(js, "read failed: %s", strerror(errno)); return JS_RaiseDisrupt(js, "read failed: %s", strerror(errno));
}
js_blob_stone(ret, bytes_read);
ret = js_new_blob_stoned_copy(js, buf, bytes_read);
free(buf);
return ret; return ret;
) )
@@ -128,39 +125,48 @@ JSC_SCALL(fd_slurp,
size_t size = st.st_size; size_t size = st.st_size;
if (size == 0) if (size == 0)
return js_new_blob_stoned_copy(js, NULL, 0); return js_new_blob_stoned_copy(js, NULL, 0);
#ifndef _WIN32 #ifndef _WIN32
int fd = open(str, O_RDONLY); int fd = open(str, O_RDONLY);
if (fd < 0) if (fd < 0)
return JS_RaiseDisrupt(js, "open failed: %s", strerror(errno)); return JS_RaiseDisrupt(js, "open failed: %s", strerror(errno));
void *data = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0); void *out;
if (data == MAP_FAILED) { ret = js_new_blob_alloc(js, size, &out);
close(fd); if (JS_IsException(ret)) { close(fd); return ret; }
return JS_RaiseDisrupt(js, "mmap failed: %s", strerror(errno));
size_t total = 0;
while (total < size) {
ssize_t n = read(fd, (uint8_t *)out + total, size - total);
if (n < 0) {
if (errno == EINTR) continue;
close(fd);
return JS_RaiseDisrupt(js, "read failed: %s", strerror(errno));
}
if (n == 0) break;
total += n;
} }
ret = js_new_blob_stoned_copy(js, data, size);
munmap(data, size);
close(fd); close(fd);
js_blob_stone(ret, total);
#else #else
// Windows: use memory mapping for optimal performance // Windows: use memory mapping for optimal performance
HANDLE hFile = CreateFileA(str, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); HANDLE hFile = CreateFileA(str, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE) if (hFile == INVALID_HANDLE_VALUE)
return JS_RaiseDisrupt(js, "CreateFile failed: %lu", GetLastError()); return JS_RaiseDisrupt(js, "CreateFile failed: %lu", GetLastError());
HANDLE hMapping = CreateFileMappingA(hFile, NULL, PAGE_READONLY, 0, 0, NULL); HANDLE hMapping = CreateFileMappingA(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
if (hMapping == NULL) { if (hMapping == NULL) {
CloseHandle(hFile); CloseHandle(hFile);
return JS_RaiseDisrupt(js, "CreateFileMapping failed: %lu", GetLastError()); return JS_RaiseDisrupt(js, "CreateFileMapping failed: %lu", GetLastError());
} }
void *data = MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0); void *data = MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0);
if (data == NULL) { if (data == NULL) {
CloseHandle(hMapping); CloseHandle(hMapping);
CloseHandle(hFile); CloseHandle(hFile);
return JS_RaiseDisrupt(js, "MapViewOfFile failed: %lu", GetLastError()); return JS_RaiseDisrupt(js, "MapViewOfFile failed: %lu", GetLastError());
} }
ret = js_new_blob_stoned_copy(js, data, size); ret = js_new_blob_stoned_copy(js, data, size);
UnmapViewOfFile(data); UnmapViewOfFile(data);
CloseHandle(hMapping); CloseHandle(hMapping);

View File

@@ -8,26 +8,25 @@
JSC_CCALL(kim_encode, JSC_CCALL(kim_encode,
const char *utf8_str = JS_ToCString(js, argv[0]); const char *utf8_str = JS_ToCString(js, argv[0]);
if (!utf8_str) return JS_EXCEPTION; if (!utf8_str) return JS_EXCEPTION;
// Count runes to estimate kim buffer size // Count runes to estimate kim buffer size
int rune_count = utf8_count(utf8_str); int rune_count = utf8_count(utf8_str);
// Allocate kim buffer (worst case: 5 bytes per rune) // Allocate blob (worst case: 5 bytes per rune)
size_t kim_size = rune_count * 5; size_t kim_size = rune_count * 5;
char *kim_buffer = malloc(kim_size); void *out;
char *kim_ptr = kim_buffer; ret = js_new_blob_alloc(js, kim_size, &out);
if (JS_IsException(ret)) { JS_FreeCString(js, utf8_str); return ret; }
// Encode utf8 to kim
// Encode utf8 to kim directly into blob
char *kim_ptr = (char *)out;
long long runes_encoded; long long runes_encoded;
utf8_to_kim(&utf8_str, &kim_ptr, &runes_encoded); utf8_to_kim(&utf8_str, &kim_ptr, &runes_encoded);
// Calculate actual size used // Stone with actual size used
size_t actual_size = kim_ptr - kim_buffer; size_t actual_size = kim_ptr - (char *)out;
js_blob_stone(ret, actual_size);
// Create blob with the encoded data
ret = js_new_blob_stoned_copy(js, kim_buffer, actual_size);
free(kim_buffer);
JS_FreeCString(js, utf8_str); JS_FreeCString(js, utf8_str);
) )

View File

@@ -333,19 +333,15 @@ JSC_CCALL(socket_recv,
flags = js2number(js, argv[2]); flags = js2number(js, argv[2]);
} }
void *buf = malloc(len); void *out;
if (!buf) { ret = js_new_blob_alloc(js, len, &out);
return JS_RaiseDisrupt(js, "malloc failed"); if (JS_IsException(ret)) return ret;
}
ssize_t received = recv(sockfd, out, len, flags);
ssize_t received = recv(sockfd, buf, len, flags); if (received < 0)
if (received < 0) {
free(buf);
return JS_RaiseDisrupt(js, "recv failed: %s", strerror(errno)); return JS_RaiseDisrupt(js, "recv failed: %s", strerror(errno));
}
js_blob_stone(ret, received);
ret = js_new_blob_stoned_copy(js, buf, received);
free(buf);
return ret; return ret;
) )
@@ -421,25 +417,20 @@ JSC_CCALL(socket_recvfrom,
flags = js2number(js, argv[2]); flags = js2number(js, argv[2]);
} }
void *buf = malloc(len); void *out;
if (!buf) { JSValue blob = js_new_blob_alloc(js, len, &out);
return JS_RaiseDisrupt(js, "malloc failed"); if (JS_IsException(blob)) return blob;
}
struct sockaddr_storage from_addr; struct sockaddr_storage from_addr;
socklen_t from_len = sizeof from_addr; socklen_t from_len = sizeof from_addr;
ssize_t received = recvfrom(sockfd, buf, len, flags, ssize_t received = recvfrom(sockfd, out, len, flags,
(struct sockaddr *)&from_addr, &from_len); (struct sockaddr *)&from_addr, &from_len);
if (received < 0) { if (received < 0)
free(buf);
return JS_RaiseDisrupt(js, "recvfrom failed: %s", strerror(errno)); return JS_RaiseDisrupt(js, "recvfrom failed: %s", strerror(errno));
}
js_blob_stone(blob, received);
ret = JS_NewObject(js);
JS_SetPropertyStr(js, ret, "data", js_new_blob_stoned_copy(js, buf, received));
free(buf);
// Get source address info // Get source address info
char ipstr[INET6_ADDRSTRLEN]; char ipstr[INET6_ADDRSTRLEN];
int port; int port;
@@ -452,11 +443,15 @@ JSC_CCALL(socket_recvfrom,
inet_ntop(AF_INET6, &s->sin6_addr, ipstr, sizeof ipstr); inet_ntop(AF_INET6, &s->sin6_addr, ipstr, sizeof ipstr);
port = ntohs(s->sin6_port); port = ntohs(s->sin6_port);
} }
JSValue addr_info = JS_NewObject(js); JS_FRAME(js);
JS_SetPropertyStr(js, addr_info, "address", JS_NewString(js, ipstr)); JS_ROOT(ret_r, JS_NewObject(js));
JS_SetPropertyStr(js, addr_info, "port", JS_NewInt32(js, port)); JS_SetPropertyStr(js, ret_r.val, "data", blob);
JS_SetPropertyStr(js, ret, "address", addr_info); JS_ROOT(addr_info, JS_NewObject(js));
JS_SetPropertyStr(js, addr_info.val, "address", JS_NewString(js, ipstr));
JS_SetPropertyStr(js, addr_info.val, "port", JS_NewInt32(js, port));
JS_SetPropertyStr(js, ret_r.val, "address", addr_info.val);
JS_RETURN(ret_r.val);
) )
JSC_CCALL(socket_shutdown, JSC_CCALL(socket_shutdown,

View File

@@ -78,15 +78,13 @@ JSC_CCALL(file_read,
if (!pd_file) return JS_RaiseDisrupt(js, "file not initialized"); if (!pd_file) return JS_RaiseDisrupt(js, "file not initialized");
SDFile *f = js2sdfile(js, argv[0]); SDFile *f = js2sdfile(js, argv[0]);
unsigned int len = (unsigned int)js2number(js, argv[1]); unsigned int len = (unsigned int)js2number(js, argv[1]);
void *buf = malloc(len); void *out;
if (!buf) return JS_RaiseDisrupt(js, "malloc failed"); JSValue blob = js_new_blob_alloc(js, len, &out);
int read = pd_file->read(f, buf, len); if (JS_IsException(blob)) return blob;
if (read < 0) { int bytes_read = pd_file->read(f, out, len);
free(buf); if (bytes_read < 0)
return JS_NULL; return JS_NULL;
} js_blob_stone(blob, bytes_read);
JSValue blob = js_new_blob_stoned_copy(js, buf, read);
free(buf);
return blob; return blob;
) )

View File

@@ -139,15 +139,13 @@ JSC_CCALL(http_read,
if (!pd_network || !pd_network->http) return JS_RaiseDisrupt(js, "network not initialized"); if (!pd_network || !pd_network->http) return JS_RaiseDisrupt(js, "network not initialized");
HTTPConnection *conn = js2http(js, argv[0]); HTTPConnection *conn = js2http(js, argv[0]);
unsigned int buflen = (unsigned int)js2number(js, argv[1]); unsigned int buflen = (unsigned int)js2number(js, argv[1]);
void *buf = malloc(buflen); void *out;
if (!buf) return JS_RaiseDisrupt(js, "malloc failed"); JSValue blob = js_new_blob_alloc(js, buflen, &out);
int read = pd_network->http->read(conn, buf, buflen); if (JS_IsException(blob)) return blob;
if (read < 0) { int bytes_read = pd_network->http->read(conn, out, buflen);
free(buf); if (bytes_read < 0)
return JS_NULL; return JS_NULL;
} js_blob_stone(blob, bytes_read);
JSValue blob = js_new_blob_stoned_copy(js, buf, read);
free(buf);
return blob; return blob;
) )
@@ -218,15 +216,13 @@ JSC_CCALL(tcp_read,
if (!pd_network || !pd_network->tcp) return JS_RaiseDisrupt(js, "network not initialized"); if (!pd_network || !pd_network->tcp) return JS_RaiseDisrupt(js, "network not initialized");
TCPConnection *conn = js2tcp(js, argv[0]); TCPConnection *conn = js2tcp(js, argv[0]);
size_t len = (size_t)js2number(js, argv[1]); size_t len = (size_t)js2number(js, argv[1]);
void *buf = malloc(len); void *out;
if (!buf) return JS_RaiseDisrupt(js, "malloc failed"); JSValue blob = js_new_blob_alloc(js, len, &out);
int read = pd_network->tcp->read(conn, buf, len); if (JS_IsException(blob)) return blob;
if (read < 0) { int bytes_read = pd_network->tcp->read(conn, out, len);
free(buf); if (bytes_read < 0)
return JS_NewInt32(js, read); // Return error code return JS_NewInt32(js, bytes_read); // Return error code
} js_blob_stone(blob, bytes_read);
JSValue blob = js_new_blob_stoned_copy(js, buf, read);
free(buf);
return blob; return blob;
) )

30
qop.c
View File

@@ -183,18 +183,15 @@ static JSValue js_qop_read(JSContext *js, JSValue self, int argc, JSValue *argv)
return JS_NULL; return JS_NULL;
} }
unsigned char *dest = js_malloc_rt(file->size); void *out;
if (!dest) JSValue blob = js_new_blob_alloc(js, file->size, &out);
return JS_RaiseOOM(js); if (JS_IsException(blob)) return blob;
int bytes = qop_read(qop, file, dest); int bytes = qop_read(qop, file, out);
if (bytes == 0) { if (bytes == 0)
js_free_rt(dest);
return JS_RaiseDisrupt(js, "Failed to read file"); return JS_RaiseDisrupt(js, "Failed to read file");
}
JSValue blob = js_new_blob_stoned_copy(js, dest, bytes); js_blob_stone(blob, bytes);
js_free_rt(dest);
return blob; return blob;
} }
@@ -223,18 +220,15 @@ static JSValue js_qop_read_ex(JSContext *js, JSValue self, int argc, JSValue *ar
if (JS_ToUint32(js, &start, argv[1]) < 0 || JS_ToUint32(js, &len, argv[2]) < 0) if (JS_ToUint32(js, &start, argv[1]) < 0 || JS_ToUint32(js, &len, argv[2]) < 0)
return JS_RaiseDisrupt(js, "Invalid start or len"); return JS_RaiseDisrupt(js, "Invalid start or len");
unsigned char *dest = js_malloc_rt(len); void *out;
if (!dest) JSValue blob = js_new_blob_alloc(js, len, &out);
return JS_RaiseOOM(js); if (JS_IsException(blob)) return blob;
int bytes = qop_read_ex(qop, file, dest, start, len); int bytes = qop_read_ex(qop, file, out, start, len);
if (bytes == 0) { if (bytes == 0)
js_free_rt(dest);
return JS_RaiseDisrupt(js, "Failed to read file part"); return JS_RaiseDisrupt(js, "Failed to read file part");
}
JSValue blob = js_new_blob_stoned_copy(js, dest, bytes); js_blob_stone(blob, bytes);
js_free_rt(dest);
return blob; return blob;
} }

View File

@@ -10,6 +10,8 @@ extern "C" {
// blob fns // blob fns
JSValue js_core_blob_use(JSContext *js); JSValue js_core_blob_use(JSContext *js);
JSValue js_new_blob_alloc(JSContext *js, size_t bytes, void **out);
void js_blob_stone(JSValue blob, size_t actual_bytes);
JSValue js_new_blob_stoned_copy(JSContext *js, void *data, size_t bytes); JSValue js_new_blob_stoned_copy(JSContext *js, void *data, size_t bytes);
void *js_get_blob_data(JSContext *js, size_t *size, JSValue v); // bytes void *js_get_blob_data(JSContext *js, size_t *size, JSValue v); // bytes
void *js_get_blob_data_bits(JSContext *js, size_t *bits, JSValue v); // bits void *js_get_blob_data_bits(JSContext *js, size_t *bits, JSValue v); // bits

View File

@@ -10048,16 +10048,38 @@ JSValue js_core_blob_use (JSContext *js) {
return JS_GetPropertyStr (js, js->global_obj, "blob"); return JS_GetPropertyStr (js, js->global_obj, "blob");
} }
/* Create a new blob from raw data, stone it, and return as JSValue */ /* Allocate a mutable blob. *out receives writable pointer to data area.
JSValue js_new_blob_stoned_copy (JSContext *js, void *data, size_t bytes) { WARNING: *out is invalidated by ANY GC-triggering operation.
Caller fills data, then calls js_blob_stone(). */
JSValue js_new_blob_alloc (JSContext *js, size_t bytes, void **out) {
size_t bits = bytes * 8; size_t bits = bytes * 8;
JSValue bv = js_new_heap_blob (js, bits); JSValue bv = js_new_heap_blob (js, bits);
if (JS_IsException (bv)) return bv; if (JS_IsException (bv)) {
*out = NULL;
return bv;
}
JSBlob *bd = (JSBlob *)chase (bv); JSBlob *bd = (JSBlob *)chase (bv);
if (bytes > 0)
memcpy (bd->bits, data, bytes);
bd->length = bits; bd->length = bits;
*out = bd->bits;
return bv;
}
/* Set actual length and stone the blob. actual_bytes <= allocated bytes.
Does NOT allocate — cannot trigger GC. */
void js_blob_stone (JSValue blob, size_t actual_bytes) {
JSBlob *bd = (JSBlob *)chase (blob);
bd->length = actual_bytes * 8;
bd->mist_hdr = objhdr_set_s (bd->mist_hdr, true); bd->mist_hdr = objhdr_set_s (bd->mist_hdr, true);
}
/* Create a new blob from raw data, stone it, and return as JSValue */
JSValue js_new_blob_stoned_copy (JSContext *js, void *data, size_t bytes) {
void *out;
JSValue bv = js_new_blob_alloc (js, bytes, &out);
if (JS_IsException (bv)) return bv;
if (bytes > 0)
memcpy (out, data, bytes);
js_blob_stone (bv, bytes);
return bv; return bv;
} }

View File

@@ -1,6 +1,5 @@
var fd = use("fd") var fd = use("fd")
var miniz = use("miniz") var miniz = use("miniz")
var utf8 = use("utf8")
return { return {
create_and_read_zip: function() { create_and_read_zip: function() {
@@ -35,7 +34,7 @@ return {
disrupt disrupt
extracted_blob = reader.slurp(ENTRY_PATH) extracted_blob = reader.slurp(ENTRY_PATH)
extracted_text = utf8.decode(extracted_blob) extracted_text = text(extracted_blob)
if (extracted_text != PAYLOAD) if (extracted_text != PAYLOAD)
disrupt disrupt
@@ -59,8 +58,8 @@ return {
var _run = function() { var _run = function() {
writer = miniz.write(ZIP_PATH) writer = miniz.write(ZIP_PATH)
writer.add_file(ENTRY1, utf8.encode("content1")) writer.add_file(ENTRY1, blob("content1"))
writer.add_file(ENTRY2, utf8.encode("content2")) writer.add_file(ENTRY2, blob("content2"))
writer = null writer = null
zip_blob = fd.slurp(ZIP_PATH) zip_blob = fd.slurp(ZIP_PATH)
@@ -87,7 +86,7 @@ return {
var _run = function() { var _run = function() {
writer = miniz.write(ZIP_PATH) writer = miniz.write(ZIP_PATH)
writer.add_file(ENTRY_PATH, utf8.encode("data")) writer.add_file(ENTRY_PATH, blob("data"))
writer = null writer = null
zip_blob = fd.slurp(ZIP_PATH) zip_blob = fd.slurp(ZIP_PATH)