Merge branch 'fix_compile_warnings'
This commit is contained in:
@@ -113,31 +113,34 @@ static JSValue js_miniz_compress(JSContext *js, JSValue this_val,
|
||||
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);
|
||||
void *out_buf = js_malloc_rt(out_len_est);
|
||||
if (!out_buf) {
|
||||
void *out_ptr;
|
||||
JSValue abuf = js_new_blob_alloc(js, (size_t)out_len_est, &out_ptr);
|
||||
if (JS_IsException(abuf)) {
|
||||
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) */
|
||||
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);
|
||||
|
||||
/* clean-up for string input */
|
||||
if (cstring) JS_FreeCString(js, cstring);
|
||||
|
||||
if (st != MZ_OK) {
|
||||
js_free_rt(out_buf);
|
||||
if (st != MZ_OK)
|
||||
return JS_RaiseDisrupt(js,
|
||||
"miniz: compression failed (%d)", st);
|
||||
}
|
||||
|
||||
/* ─── 4. Hand JavaScript a copy of the compressed data ────── */
|
||||
JSValue abuf = js_new_blob_stoned_copy(js, out_buf, out_len);
|
||||
js_free_rt(out_buf);
|
||||
/* ─── 4. Stone with actual compressed size ────────────────── */
|
||||
js_blob_stone(abuf, (size_t)out_len);
|
||||
return abuf;
|
||||
}
|
||||
|
||||
|
||||
@@ -98,19 +98,17 @@ JSC_CCALL(fd_read,
|
||||
if (argc > 1)
|
||||
size = js2number(js, argv[1]);
|
||||
|
||||
void *buf = malloc(size);
|
||||
if (!buf)
|
||||
return JS_RaiseDisrupt(js, "malloc failed");
|
||||
|
||||
int bytes_read = pd_file->read(fd, buf, (unsigned int)size);
|
||||
void *out;
|
||||
ret = js_new_blob_alloc(js, size, &out);
|
||||
if (JS_IsException(ret)) return ret;
|
||||
|
||||
int bytes_read = pd_file->read(fd, out, (unsigned int)size);
|
||||
if (bytes_read < 0) {
|
||||
free(buf);
|
||||
const char* err = pd_file->geterr();
|
||||
return JS_RaiseDisrupt(js, "read failed: %s", err ? err : "unknown error");
|
||||
}
|
||||
|
||||
ret = js_new_blob_stoned_copy(js, buf, bytes_read);
|
||||
free(buf);
|
||||
|
||||
js_blob_stone(ret, bytes_read);
|
||||
return ret;
|
||||
)
|
||||
|
||||
@@ -134,22 +132,17 @@ JSC_SCALL(fd_slurp,
|
||||
return JS_RaiseDisrupt(js, "open failed: %s", err ? err : "unknown error");
|
||||
}
|
||||
|
||||
void *data = malloc(size);
|
||||
if (!data) {
|
||||
pd_file->close(fd);
|
||||
return JS_RaiseDisrupt(js, "malloc failed");
|
||||
}
|
||||
void *out;
|
||||
ret = js_new_blob_alloc(js, size, &out);
|
||||
if (JS_IsException(ret)) { pd_file->close(fd); return ret; }
|
||||
|
||||
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);
|
||||
|
||||
if (bytes_read < 0) {
|
||||
free(data);
|
||||
if (bytes_read < 0)
|
||||
return JS_RaiseDisrupt(js, "read failed");
|
||||
}
|
||||
|
||||
ret = js_new_blob_stoned_copy(js, data, bytes_read);
|
||||
free(data);
|
||||
js_blob_stone(ret, bytes_read);
|
||||
)
|
||||
|
||||
JSC_CCALL(fd_lseek,
|
||||
|
||||
@@ -102,18 +102,15 @@ JSC_CCALL(fd_read,
|
||||
if (argc > 1)
|
||||
size = js2number(js, argv[1]);
|
||||
|
||||
void *buf = malloc(size);
|
||||
if (!buf)
|
||||
return JS_RaiseDisrupt(js, "malloc failed");
|
||||
|
||||
ssize_t bytes_read = read(fd, buf, size);
|
||||
if (bytes_read < 0) {
|
||||
free(buf);
|
||||
void *out;
|
||||
ret = js_new_blob_alloc(js, size, &out);
|
||||
if (JS_IsException(ret)) return ret;
|
||||
|
||||
ssize_t bytes_read = read(fd, out, size);
|
||||
if (bytes_read < 0)
|
||||
return JS_RaiseDisrupt(js, "read failed: %s", strerror(errno));
|
||||
}
|
||||
|
||||
ret = js_new_blob_stoned_copy(js, buf, bytes_read);
|
||||
free(buf);
|
||||
|
||||
js_blob_stone(ret, bytes_read);
|
||||
return ret;
|
||||
)
|
||||
|
||||
@@ -128,39 +125,48 @@ JSC_SCALL(fd_slurp,
|
||||
size_t size = st.st_size;
|
||||
if (size == 0)
|
||||
return js_new_blob_stoned_copy(js, NULL, 0);
|
||||
|
||||
|
||||
#ifndef _WIN32
|
||||
int fd = open(str, O_RDONLY);
|
||||
if (fd < 0)
|
||||
return JS_RaiseDisrupt(js, "open failed: %s", strerror(errno));
|
||||
|
||||
void *data = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0);
|
||||
if (data == MAP_FAILED) {
|
||||
close(fd);
|
||||
return JS_RaiseDisrupt(js, "mmap failed: %s", strerror(errno));
|
||||
|
||||
void *out;
|
||||
ret = js_new_blob_alloc(js, size, &out);
|
||||
if (JS_IsException(ret)) { close(fd); return ret; }
|
||||
|
||||
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);
|
||||
js_blob_stone(ret, total);
|
||||
#else
|
||||
// Windows: use memory mapping for optimal performance
|
||||
HANDLE hFile = CreateFileA(str, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
if (hFile == INVALID_HANDLE_VALUE)
|
||||
return JS_RaiseDisrupt(js, "CreateFile failed: %lu", GetLastError());
|
||||
|
||||
|
||||
HANDLE hMapping = CreateFileMappingA(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
|
||||
if (hMapping == NULL) {
|
||||
CloseHandle(hFile);
|
||||
return JS_RaiseDisrupt(js, "CreateFileMapping failed: %lu", GetLastError());
|
||||
}
|
||||
|
||||
|
||||
void *data = MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0);
|
||||
if (data == NULL) {
|
||||
CloseHandle(hMapping);
|
||||
CloseHandle(hFile);
|
||||
return JS_RaiseDisrupt(js, "MapViewOfFile failed: %lu", GetLastError());
|
||||
}
|
||||
|
||||
|
||||
ret = js_new_blob_stoned_copy(js, data, size);
|
||||
UnmapViewOfFile(data);
|
||||
CloseHandle(hMapping);
|
||||
|
||||
@@ -8,26 +8,25 @@
|
||||
JSC_CCALL(kim_encode,
|
||||
const char *utf8_str = JS_ToCString(js, argv[0]);
|
||||
if (!utf8_str) return JS_EXCEPTION;
|
||||
|
||||
|
||||
// Count runes to estimate kim buffer size
|
||||
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;
|
||||
char *kim_buffer = malloc(kim_size);
|
||||
char *kim_ptr = kim_buffer;
|
||||
|
||||
// Encode utf8 to kim
|
||||
void *out;
|
||||
ret = js_new_blob_alloc(js, kim_size, &out);
|
||||
if (JS_IsException(ret)) { JS_FreeCString(js, utf8_str); return ret; }
|
||||
|
||||
// Encode utf8 to kim directly into blob
|
||||
char *kim_ptr = (char *)out;
|
||||
long long runes_encoded;
|
||||
utf8_to_kim(&utf8_str, &kim_ptr, &runes_encoded);
|
||||
|
||||
// Calculate actual size used
|
||||
size_t actual_size = kim_ptr - kim_buffer;
|
||||
|
||||
// Create blob with the encoded data
|
||||
ret = js_new_blob_stoned_copy(js, kim_buffer, actual_size);
|
||||
|
||||
free(kim_buffer);
|
||||
|
||||
// Stone with actual size used
|
||||
size_t actual_size = kim_ptr - (char *)out;
|
||||
js_blob_stone(ret, actual_size);
|
||||
|
||||
JS_FreeCString(js, utf8_str);
|
||||
)
|
||||
|
||||
|
||||
59
net/socket.c
59
net/socket.c
@@ -333,19 +333,15 @@ JSC_CCALL(socket_recv,
|
||||
flags = js2number(js, argv[2]);
|
||||
}
|
||||
|
||||
void *buf = malloc(len);
|
||||
if (!buf) {
|
||||
return JS_RaiseDisrupt(js, "malloc failed");
|
||||
}
|
||||
|
||||
ssize_t received = recv(sockfd, buf, len, flags);
|
||||
if (received < 0) {
|
||||
free(buf);
|
||||
void *out;
|
||||
ret = js_new_blob_alloc(js, len, &out);
|
||||
if (JS_IsException(ret)) return ret;
|
||||
|
||||
ssize_t received = recv(sockfd, out, len, flags);
|
||||
if (received < 0)
|
||||
return JS_RaiseDisrupt(js, "recv failed: %s", strerror(errno));
|
||||
}
|
||||
|
||||
ret = js_new_blob_stoned_copy(js, buf, received);
|
||||
free(buf);
|
||||
|
||||
js_blob_stone(ret, received);
|
||||
return ret;
|
||||
)
|
||||
|
||||
@@ -421,25 +417,20 @@ JSC_CCALL(socket_recvfrom,
|
||||
flags = js2number(js, argv[2]);
|
||||
}
|
||||
|
||||
void *buf = malloc(len);
|
||||
if (!buf) {
|
||||
return JS_RaiseDisrupt(js, "malloc failed");
|
||||
}
|
||||
|
||||
void *out;
|
||||
JSValue blob = js_new_blob_alloc(js, len, &out);
|
||||
if (JS_IsException(blob)) return blob;
|
||||
|
||||
struct sockaddr_storage 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);
|
||||
if (received < 0) {
|
||||
free(buf);
|
||||
if (received < 0)
|
||||
return JS_RaiseDisrupt(js, "recvfrom failed: %s", strerror(errno));
|
||||
}
|
||||
|
||||
ret = JS_NewObject(js);
|
||||
JS_SetPropertyStr(js, ret, "data", js_new_blob_stoned_copy(js, buf, received));
|
||||
free(buf);
|
||||
|
||||
|
||||
js_blob_stone(blob, received);
|
||||
|
||||
// Get source address info
|
||||
char ipstr[INET6_ADDRSTRLEN];
|
||||
int port;
|
||||
@@ -452,11 +443,15 @@ JSC_CCALL(socket_recvfrom,
|
||||
inet_ntop(AF_INET6, &s->sin6_addr, ipstr, sizeof ipstr);
|
||||
port = ntohs(s->sin6_port);
|
||||
}
|
||||
|
||||
JSValue addr_info = JS_NewObject(js);
|
||||
JS_SetPropertyStr(js, addr_info, "address", JS_NewString(js, ipstr));
|
||||
JS_SetPropertyStr(js, addr_info, "port", JS_NewInt32(js, port));
|
||||
JS_SetPropertyStr(js, ret, "address", addr_info);
|
||||
|
||||
JS_FRAME(js);
|
||||
JS_ROOT(ret_r, JS_NewObject(js));
|
||||
JS_SetPropertyStr(js, ret_r.val, "data", blob);
|
||||
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,
|
||||
|
||||
@@ -78,15 +78,13 @@ JSC_CCALL(file_read,
|
||||
if (!pd_file) return JS_RaiseDisrupt(js, "file not initialized");
|
||||
SDFile *f = js2sdfile(js, argv[0]);
|
||||
unsigned int len = (unsigned int)js2number(js, argv[1]);
|
||||
void *buf = malloc(len);
|
||||
if (!buf) return JS_RaiseDisrupt(js, "malloc failed");
|
||||
int read = pd_file->read(f, buf, len);
|
||||
if (read < 0) {
|
||||
free(buf);
|
||||
void *out;
|
||||
JSValue blob = js_new_blob_alloc(js, len, &out);
|
||||
if (JS_IsException(blob)) return blob;
|
||||
int bytes_read = pd_file->read(f, out, len);
|
||||
if (bytes_read < 0)
|
||||
return JS_NULL;
|
||||
}
|
||||
JSValue blob = js_new_blob_stoned_copy(js, buf, read);
|
||||
free(buf);
|
||||
js_blob_stone(blob, bytes_read);
|
||||
return blob;
|
||||
)
|
||||
|
||||
|
||||
@@ -139,15 +139,13 @@ JSC_CCALL(http_read,
|
||||
if (!pd_network || !pd_network->http) return JS_RaiseDisrupt(js, "network not initialized");
|
||||
HTTPConnection *conn = js2http(js, argv[0]);
|
||||
unsigned int buflen = (unsigned int)js2number(js, argv[1]);
|
||||
void *buf = malloc(buflen);
|
||||
if (!buf) return JS_RaiseDisrupt(js, "malloc failed");
|
||||
int read = pd_network->http->read(conn, buf, buflen);
|
||||
if (read < 0) {
|
||||
free(buf);
|
||||
void *out;
|
||||
JSValue blob = js_new_blob_alloc(js, buflen, &out);
|
||||
if (JS_IsException(blob)) return blob;
|
||||
int bytes_read = pd_network->http->read(conn, out, buflen);
|
||||
if (bytes_read < 0)
|
||||
return JS_NULL;
|
||||
}
|
||||
JSValue blob = js_new_blob_stoned_copy(js, buf, read);
|
||||
free(buf);
|
||||
js_blob_stone(blob, bytes_read);
|
||||
return blob;
|
||||
)
|
||||
|
||||
@@ -218,15 +216,13 @@ JSC_CCALL(tcp_read,
|
||||
if (!pd_network || !pd_network->tcp) return JS_RaiseDisrupt(js, "network not initialized");
|
||||
TCPConnection *conn = js2tcp(js, argv[0]);
|
||||
size_t len = (size_t)js2number(js, argv[1]);
|
||||
void *buf = malloc(len);
|
||||
if (!buf) return JS_RaiseDisrupt(js, "malloc failed");
|
||||
int read = pd_network->tcp->read(conn, buf, len);
|
||||
if (read < 0) {
|
||||
free(buf);
|
||||
return JS_NewInt32(js, read); // Return error code
|
||||
}
|
||||
JSValue blob = js_new_blob_stoned_copy(js, buf, read);
|
||||
free(buf);
|
||||
void *out;
|
||||
JSValue blob = js_new_blob_alloc(js, len, &out);
|
||||
if (JS_IsException(blob)) return blob;
|
||||
int bytes_read = pd_network->tcp->read(conn, out, len);
|
||||
if (bytes_read < 0)
|
||||
return JS_NewInt32(js, bytes_read); // Return error code
|
||||
js_blob_stone(blob, bytes_read);
|
||||
return blob;
|
||||
)
|
||||
|
||||
|
||||
30
qop.c
30
qop.c
@@ -183,18 +183,15 @@ static JSValue js_qop_read(JSContext *js, JSValue self, int argc, JSValue *argv)
|
||||
return JS_NULL;
|
||||
}
|
||||
|
||||
unsigned char *dest = js_malloc_rt(file->size);
|
||||
if (!dest)
|
||||
return JS_RaiseOOM(js);
|
||||
void *out;
|
||||
JSValue blob = js_new_blob_alloc(js, file->size, &out);
|
||||
if (JS_IsException(blob)) return blob;
|
||||
|
||||
int bytes = qop_read(qop, file, dest);
|
||||
if (bytes == 0) {
|
||||
js_free_rt(dest);
|
||||
int bytes = qop_read(qop, file, out);
|
||||
if (bytes == 0)
|
||||
return JS_RaiseDisrupt(js, "Failed to read file");
|
||||
}
|
||||
|
||||
JSValue blob = js_new_blob_stoned_copy(js, dest, bytes);
|
||||
js_free_rt(dest);
|
||||
js_blob_stone(blob, bytes);
|
||||
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)
|
||||
return JS_RaiseDisrupt(js, "Invalid start or len");
|
||||
|
||||
unsigned char *dest = js_malloc_rt(len);
|
||||
if (!dest)
|
||||
return JS_RaiseOOM(js);
|
||||
void *out;
|
||||
JSValue blob = js_new_blob_alloc(js, len, &out);
|
||||
if (JS_IsException(blob)) return blob;
|
||||
|
||||
int bytes = qop_read_ex(qop, file, dest, start, len);
|
||||
if (bytes == 0) {
|
||||
js_free_rt(dest);
|
||||
int bytes = qop_read_ex(qop, file, out, start, len);
|
||||
if (bytes == 0)
|
||||
return JS_RaiseDisrupt(js, "Failed to read file part");
|
||||
}
|
||||
|
||||
JSValue blob = js_new_blob_stoned_copy(js, dest, bytes);
|
||||
js_free_rt(dest);
|
||||
js_blob_stone(blob, bytes);
|
||||
return blob;
|
||||
}
|
||||
|
||||
|
||||
@@ -10,6 +10,8 @@ extern "C" {
|
||||
|
||||
// blob fns
|
||||
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);
|
||||
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
|
||||
|
||||
@@ -10048,16 +10048,38 @@ JSValue js_core_blob_use (JSContext *js) {
|
||||
return JS_GetPropertyStr (js, js->global_obj, "blob");
|
||||
}
|
||||
|
||||
/* 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) {
|
||||
/* Allocate a mutable blob. *out receives writable pointer to data area.
|
||||
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;
|
||||
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);
|
||||
if (bytes > 0)
|
||||
memcpy (bd->bits, data, bytes);
|
||||
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);
|
||||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
var fd = use("fd")
|
||||
var miniz = use("miniz")
|
||||
var utf8 = use("utf8")
|
||||
|
||||
return {
|
||||
create_and_read_zip: function() {
|
||||
@@ -35,7 +34,7 @@ return {
|
||||
disrupt
|
||||
|
||||
extracted_blob = reader.slurp(ENTRY_PATH)
|
||||
extracted_text = utf8.decode(extracted_blob)
|
||||
extracted_text = text(extracted_blob)
|
||||
|
||||
if (extracted_text != PAYLOAD)
|
||||
disrupt
|
||||
@@ -59,8 +58,8 @@ return {
|
||||
|
||||
var _run = function() {
|
||||
writer = miniz.write(ZIP_PATH)
|
||||
writer.add_file(ENTRY1, utf8.encode("content1"))
|
||||
writer.add_file(ENTRY2, utf8.encode("content2"))
|
||||
writer.add_file(ENTRY1, blob("content1"))
|
||||
writer.add_file(ENTRY2, blob("content2"))
|
||||
writer = null
|
||||
|
||||
zip_blob = fd.slurp(ZIP_PATH)
|
||||
@@ -87,7 +86,7 @@ return {
|
||||
|
||||
var _run = function() {
|
||||
writer = miniz.write(ZIP_PATH)
|
||||
writer.add_file(ENTRY_PATH, utf8.encode("data"))
|
||||
writer.add_file(ENTRY_PATH, blob("data"))
|
||||
writer = null
|
||||
|
||||
zip_blob = fd.slurp(ZIP_PATH)
|
||||
|
||||
Reference in New Issue
Block a user