MIRROR: javascript for ๐Ÿœ's, a tiny runtime with big ambitions
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

add libuv for async fetching

+266 -195
+5 -5
README.txt
··· 11 11 ./build/ant script.js 12 12 13 13 EXAMPLE: 14 - See tests/server/server.cjs for a good server example using Ant.serve() 14 + See examples/server/server.js for a good server example using Ant.serve() 15 15 with Radix3 routing, parameter handling, and various response types. 16 16 17 17 MODULES: 18 - - Ant.serve() - HTTP server (mongoose) 19 - - Ant.require() - CommonJS module loading 18 + - Ant.serve() - HTTP server 19 + - import() - ESM module loading 20 20 - Timers - setTimeout, setInterval, queueMicrotask 21 - - fetch() - HTTP client (curl) 22 - - crypto.* - Cryptography (libsodium) 21 + - fetch() - HTTP client 22 + - crypto.* - Cryptography 23 23 - JSON.* - JSON parsing 24 24 - console.* - Logging 25 25
+2 -23
examples/server/server.js
··· 47 47 }); 48 48 49 49 router.insert('/api/v2/demo', async c => { 50 - return c.res.json({ 51 - slideshow: { 52 - author: 'Yours Truly', 53 - date: 'date of publication', 54 - slides: [ 55 - { 56 - title: 'Wake up to WonderWidgets!', 57 - type: 'all' 58 - }, 59 - { 60 - items: ['Why <em>WonderWidgets</em> are great', 'Who <em>buys</em> WonderWidgets'], 61 - title: 'Overview', 62 - type: 'all' 63 - } 64 - ], 65 - metadata: { 66 - title: 'Sample Slide Show', 67 - isFavorite: true, 68 - viewCount: 105407, 69 - createdAt: '2024-12-01T22:51:49.000Z' 70 - } 71 - } 72 - }); 50 + const data = (await fetch('https://themackabu.dev/test.json')).json(); 51 + return c.res.json(data); 73 52 }); 74 53 75 54 router.insert('/files/*path', async c => {
+2
include/modules/fetch.h
··· 2 2 #define FETCH_H 3 3 4 4 void init_fetch_module(void); 5 + void fetch_poll_events(void); 6 + int has_pending_fetches(void); 5 7 6 8 #endif
+40 -37
meson.build
··· 4 4 'default_library=static' 5 5 ]) 6 6 7 + cmake = import('cmake') 7 8 include = include_directories('include') 8 9 9 10 module_files = run_command('sh', '-c', ··· 19 20 'src/snapshot.c', 20 21 ) + files(module_files) 21 22 22 - # system dependencies 23 + zlib_dep = dependency('zlib', required: true) 24 + llhttp = dependency('llhttp', required: true) 25 + openssl_dep = dependency('openssl', required: true) 23 26 libsodium_dep = dependency('libsodium', required: true) 24 27 25 - # dependencies 26 - libuv_dep = subproject('libuv').get_variable('libuv_dep') 28 + if host_machine.system() == 'darwin' 29 + security_dep = dependency('appleframeworks', modules: ['Security', 'CoreFoundation'], required: true) 30 + endif 31 + 32 + tlsuv_opts = cmake.subproject_options() 33 + tlsuv_opts.append_compile_args('c', [ 34 + '-Wno-unused-function', 35 + '-Wno-unused-variable', 36 + '-Wno-bitwise-op-parentheses', 37 + '-Wno-sometimes-uninitialized' 38 + ]) 39 + 40 + tlsuv_opts.add_cmake_defines({'BUILD_TESTING': 'OFF'}) 41 + tlsuv_dep = cmake.subproject('tlsuv', options: tlsuv_opts).dependency('tlsuv') 42 + 27 43 yyjson_dep = subproject('yyjson').get_variable('yyjson_dep') 28 44 uuidv7_dep = subproject('uuidv7').get_variable('uuidv7_dep') 29 45 mongoose_dep = subproject('mongoose').get_variable('mongoose_dep') 30 46 argtable3_dep = subproject('argtable3').get_variable('argtable3_dep') 31 47 minicoro_dep = subproject('minicoro').get_variable('minicoro_dep') 32 48 33 - curl_dep = subproject('curl', default_options: [ 34 - 'tests=disabled', 35 - 'tool=disabled', 36 - 'unittests=disabled'] 37 - ).get_variable('curl_dep') 49 + libuv_dep = subproject('libuv', default_options: [ 50 + 'build_tests=false', 51 + 'build_benchmarks=false' 52 + ]).get_variable('libuv_dep') 38 53 39 54 git = find_program('git', required: false) 40 55 if git.found() ··· 51 66 build_date = run_command('date', '+%Y-%m-%d', check: true).stdout().strip() 52 67 53 68 version_conf = configuration_data() 54 - version_conf.set('ANT_VERSION', '0.0.6.21') 69 + version_conf.set('ANT_VERSION', '0.0.6.22') 55 70 version_conf.set('ANT_GIT_HASH', git_hash) 56 71 version_conf.set('ANT_BUILD_DATE', build_date) 57 72 ··· 62 77 ) 63 78 64 79 build_include = include_directories('.') 65 - add_project_arguments('-D JS_DUMP', language: 'c') 66 - 67 - gen_snapshot_sources = files( 68 - 'src/ant.c', 69 - 'src/runtime.c', 70 - 'src/tools/gen_snapshot.c', 71 - ) + files(module_files) 80 + add_project_arguments('-D JS_DUMP', '-Wno-unused-function', language: 'c') 72 81 73 82 gen_snapshot = executable( 74 83 'gen_snapshot', 75 - gen_snapshot_sources, 84 + files('src/tools/gen_snapshot.c'), 76 85 include_directories: [include, build_include], 77 - dependencies: [ 78 - libuv_dep, 79 - curl_dep, 80 - yyjson_dep, 81 - uuidv7_dep, 82 - mongoose_dep, 83 - argtable3_dep, 84 - libsodium_dep, 85 - minicoro_dep 86 - ], 87 86 c_args: ['-DANT_SNAPSHOT_GENERATOR'], 88 87 native: true 89 88 ) ··· 103 102 build_by_default: true 104 103 ) 105 104 105 + ant_deps = [ 106 + llhttp, mongoose_dep, 107 + libuv_dep, argtable3_dep, 108 + tlsuv_dep, libsodium_dep, 109 + yyjson_dep, minicoro_dep, 110 + uuidv7_dep, openssl_dep, 111 + zlib_dep 112 + ] 113 + 114 + if host_machine.system() == 'darwin' 115 + ant_deps += [security_dep] 116 + endif 117 + 106 118 executable( 107 119 'ant', 108 120 sources + [snapshot_h], 109 121 include_directories: [include, build_include], 110 - dependencies: [ 111 - libuv_dep, 112 - curl_dep, 113 - yyjson_dep, 114 - uuidv7_dep, 115 - mongoose_dep, 116 - argtable3_dep, 117 - libsodium_dep, 118 - minicoro_dep 119 - ] 122 + dependencies: ant_deps 120 123 )
+5 -2
src/ant.c
··· 18 18 #include "ant.h" 19 19 #include "config.h" 20 20 #include "modules/timer.h" 21 + #include "modules/fetch.h" 21 22 22 23 #define MINICORO_IMPL 23 24 #include "minicoro.h" ··· 418 419 } 419 420 420 421 void js_poll_events(struct js *js) { 422 + fetch_poll_events(); 423 + 421 424 if (has_pending_timers()) { 422 425 int64_t next_timeout_ms = get_next_timer_timeout(); 423 426 if (next_timeout_ms <= 0) process_timers(js); ··· 468 471 } 469 472 470 473 void js_run_event_loop(struct js *js) { 471 - while (has_pending_microtasks() || has_pending_timers() || has_pending_coroutines()) { 474 + while (has_pending_microtasks() || has_pending_timers() || has_pending_coroutines() || has_pending_fetches()) { 472 475 js_poll_events(js); 473 476 474 477 if (!has_pending_microtasks() && has_pending_timers() && !has_ready_coroutines()) { ··· 476 479 if (next_timeout_ms > 0) usleep(next_timeout_ms > 1000000 ? 1000000 : next_timeout_ms * 1000); 477 480 } 478 481 479 - if (!has_pending_microtasks() && !has_pending_timers() && !has_pending_coroutines()) break; 482 + if (!has_pending_microtasks() && !has_pending_timers() && !has_pending_coroutines() && !has_pending_fetches()) break; 480 483 } 481 484 } 482 485
+195 -92
src/modules/fetch.c
··· 1 + #include <uv.h> 1 2 #include <stdio.h> 2 3 #include <stdlib.h> 3 4 #include <string.h> 4 - #include <curl/curl.h> 5 + #include <tlsuv/tlsuv.h> 6 + #include <tlsuv/http.h> 5 7 6 8 #include "runtime.h" 7 9 #include "modules/fetch.h" ··· 10 12 typedef struct { 11 13 char *data; 12 14 size_t size; 15 + size_t capacity; 13 16 } fetch_buffer_t; 14 17 15 - static CURL *global_curl = NULL; 16 - static void cleanup_fetch_module(void); 18 + typedef struct fetch_request_s { 19 + struct js *js; 20 + jsval_t promise; 21 + tlsuv_http_t http_client; 22 + tlsuv_http_req_t *http_req; 23 + fetch_buffer_t response_buffer; 24 + int status_code; 25 + int completed; 26 + int failed; 27 + char *error_msg; 28 + jsval_t headers_obj; 29 + struct fetch_request_s *next; 30 + } fetch_request_t; 17 31 18 - static size_t write_callback(void *contents, size_t size, size_t nmemb, void *userp) { 19 - size_t realsize = size * nmemb; 20 - fetch_buffer_t *buf = (fetch_buffer_t *)userp; 21 - 22 - char *ptr = realloc(buf->data, buf->size + realsize + 1); 23 - if (!ptr) return 0; 32 + static uv_loop_t *fetch_loop = NULL; 33 + static fetch_request_t *pending_requests = NULL; 34 + 35 + static void free_fetch_request(fetch_request_t *req) { 36 + if (!req) return; 24 37 25 - buf->data = ptr; 26 - memcpy(&(buf->data[buf->size]), contents, realsize); 27 - buf->size += realsize; 28 - buf->data[buf->size] = 0; 38 + if (req->response_buffer.data) free(req->response_buffer.data); 39 + if (req->error_msg) free(req->error_msg); 29 40 30 - return realsize; 41 + free(req); 42 + } 43 + 44 + static void remove_pending_request(fetch_request_t *req) { 45 + fetch_request_t **curr = &pending_requests; 46 + while (*curr) { 47 + if (*curr == req) *curr = req->next; break; 48 + curr = &(*curr)->next; 49 + } 31 50 } 32 51 33 52 static jsval_t create_response(struct js *js, int status, const char *body, size_t body_len) { ··· 58 77 return response_obj; 59 78 } 60 79 80 + static void complete_request(fetch_request_t *req) { 81 + if (req->failed) { 82 + jsval_t err = js_mkstr(req->js, req->error_msg ? req->error_msg : "Unknown error", req->error_msg ? strlen(req->error_msg) : 13); 83 + js_reject_promise(req->js, req->promise, err); 84 + } else { 85 + jsval_t response = create_response(req->js, req->status_code, req->response_buffer.data, req->response_buffer.size); 86 + js_resolve_promise(req->js, req->promise, response); 87 + } 88 + 89 + remove_pending_request(req); 90 + free_fetch_request(req); 91 + } 92 + 93 + static void on_http_close(tlsuv_http_t *client) { 94 + fetch_request_t *req = (fetch_request_t *)client->data; 95 + if (req && req->completed) complete_request(req); 96 + } 97 + 98 + static void body_cb(tlsuv_http_req_t *http_req, char *body, ssize_t len) { 99 + fetch_request_t *req = (fetch_request_t *)http_req->data; 100 + 101 + if (len == UV_EOF) { 102 + req->completed = 1; 103 + tlsuv_http_close(&req->http_client, on_http_close); 104 + return; 105 + } 106 + 107 + if (len < 0) { 108 + req->failed = 1; 109 + req->error_msg = strdup(uv_strerror(len)); 110 + req->completed = 1; 111 + tlsuv_http_close(&req->http_client, on_http_close); 112 + return; 113 + } 114 + 115 + if (req->response_buffer.size + len > req->response_buffer.capacity) { 116 + size_t new_capacity = req->response_buffer.capacity * 2; 117 + while (new_capacity < req->response_buffer.size + len) new_capacity *= 2; 118 + char *new_data = realloc(req->response_buffer.data, new_capacity); 119 + 120 + if (!new_data) { 121 + req->failed = 1; 122 + req->error_msg = strdup("Out of memory"); 123 + req->completed = 1; 124 + tlsuv_http_close(&req->http_client, on_http_close); 125 + return; 126 + } 127 + 128 + req->response_buffer.data = new_data; 129 + req->response_buffer.capacity = new_capacity; 130 + } 131 + 132 + memcpy(req->response_buffer.data + req->response_buffer.size, body, len); 133 + req->response_buffer.size += len; 134 + } 135 + 136 + static void resp_cb(tlsuv_http_resp_t *resp, void *data) { 137 + (void)data; 138 + fetch_request_t *req = (fetch_request_t *)resp->req->data; 139 + 140 + if (resp->code < 0) { 141 + req->failed = 1; 142 + req->error_msg = strdup(uv_strerror(resp->code)); 143 + req->completed = 1; 144 + tlsuv_http_close(&req->http_client, on_http_close); 145 + return; 146 + } 147 + 148 + req->status_code = resp->code; 149 + resp->body_cb = body_cb; 150 + } 151 + 61 152 static jsval_t do_fetch_microtask(struct js *js, jsval_t *args, int nargs) { 62 153 (void)args; 63 154 (void)nargs; ··· 74 165 return js_mkundef(); 75 166 } 76 167 77 - const char *method = "GET"; 168 + fetch_request_t *req = calloc(1, sizeof(fetch_request_t)); 169 + if (!req) { 170 + jsval_t err = js_mkstr(js, "Out of memory", 13); 171 + js_reject_promise(js, promise, err); 172 + return js_mkundef(); 173 + } 174 + 175 + req->js = js; 176 + req->promise = promise; 177 + req->headers_obj = options_val; 178 + 179 + req->response_buffer.capacity = 16384; 180 + req->response_buffer.data = malloc(req->response_buffer.capacity); 181 + req->response_buffer.size = 0; 182 + 183 + if (!req->response_buffer.data) { 184 + jsval_t err = js_mkstr(js, "Out of memory", 13); 185 + js_reject_promise(js, promise, err); 186 + free(req); 187 + return js_mkundef(); 188 + } 189 + 190 + req->next = pending_requests; 191 + pending_requests = req; 192 + 193 + struct tlsuv_url_s parsed_url; 194 + if (tlsuv_parse_url(&parsed_url, url_str) != 0) { 195 + jsval_t err = js_mkstr(js, "Failed to parse URL", 19); 196 + js_reject_promise(js, promise, err); 197 + remove_pending_request(req); 198 + free_fetch_request(req); 199 + return js_mkundef(); 200 + } 201 + 202 + size_t host_len = (parsed_url.path - parsed_url.hostname) + parsed_url.hostname_len; 203 + char *host_url = calloc(1, host_len + parsed_url.scheme_len + 4); 204 + 205 + snprintf( 206 + host_url, host_len + parsed_url.scheme_len + 4, "%.*s://%.*s", 207 + (int)parsed_url.scheme_len, parsed_url.scheme, (int)parsed_url.hostname_len, parsed_url.hostname) 208 + ; 209 + 210 + if (parsed_url.port > 0 && !((parsed_url.port == 80 && strncmp(parsed_url.scheme, "http", 4) == 0) || (parsed_url.port == 443 && strncmp(parsed_url.scheme, "https", 5) == 0))) { 211 + char port_str[16]; 212 + snprintf(port_str, sizeof(port_str), ":%d", parsed_url.port); 213 + strcat(host_url, port_str); 214 + } 215 + 216 + int rc = tlsuv_http_init(fetch_loop, &req->http_client, host_url); 217 + free(host_url); 218 + 219 + if (rc != 0) { 220 + jsval_t err = js_mkstr(js, "Failed to initialize HTTP client", 33); 221 + js_reject_promise(js, promise, err); 222 + remove_pending_request(req); 223 + free_fetch_request(req); 224 + return js_mkundef(); 225 + } 226 + 227 + req->http_client.data = req; 228 + 229 + char *method = "GET"; 78 230 char *body = NULL; 231 + size_t body_len = 0; 79 232 80 233 if (js_type(options_val) != JS_UNDEF && js_type(options_val) != JS_NULL) { 81 234 jsval_t method_val = js_get(js, options_val, "method"); 82 235 if (js_type(method_val) == JS_STR) { 83 - method = js_getstr(js, method_val, NULL); 236 + char *method_str = js_getstr(js, method_val, NULL); 237 + if (method_str) method = method_str; 84 238 } 85 239 86 240 jsval_t body_val = js_get(js, options_val, "body"); 87 241 if (js_type(body_val) == JS_STR) { 88 242 body = js_getstr(js, body_val, NULL); 243 + if (body) body_len = strlen(body); 89 244 } 90 245 } 91 246 92 - CURL *curl = global_curl; 93 - if (!curl) { 94 - jsval_t err = js_mkstr(js, "CURL not initialized", 20); 95 - js_reject_promise(js, promise, err); 96 - return js_mkundef(); 97 - } 247 + char *path = parsed_url.path_len > 0 ? strndup(parsed_url.path, parsed_url.path_len) : strdup("/"); 248 + req->http_req = tlsuv_http_req(&req->http_client, method, path, resp_cb, req); 249 + free(path); 98 250 99 - fetch_buffer_t response_buf = { .data = malloc(1), .size = 0 }; 100 - if (!response_buf.data) { 101 - jsval_t err = js_mkstr(js, "Memory allocation failed", 24); 251 + if (!req->http_req) { 252 + jsval_t err = js_mkstr(js, "Failed to create HTTP request", 30); 102 253 js_reject_promise(js, promise, err); 254 + tlsuv_http_close(&req->http_client, NULL); 255 + remove_pending_request(req); 256 + free_fetch_request(req); 103 257 return js_mkundef(); 104 258 } 105 259 106 - curl_easy_reset(curl); 107 - 108 - curl_easy_setopt(curl, CURLOPT_URL, url_str); 109 - curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback); 110 - curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response_buf); 111 - curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L); 260 + req->http_req->data = req; 112 261 113 - if (strcmp(method, "GET") != 0) { 114 - curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, method); 115 - } 116 - 117 - struct curl_slist *headers = NULL; 118 262 if (js_type(options_val) != JS_UNDEF && js_type(options_val) != JS_NULL) { 119 263 jsval_t headers_val = js_get(js, options_val, "headers"); 120 264 if (js_type(headers_val) != JS_UNDEF && js_type(headers_val) != JS_NULL) { ··· 126 270 while (js_prop_iter_next(&iter, &key, &key_len, &value)) { 127 271 char *value_str = js_getstr(js, value, NULL); 128 272 if (value_str) { 129 - char header_line[1024]; 130 - snprintf(header_line, sizeof(header_line), "%.*s: %s", (int)key_len, key, value_str); 131 - headers = curl_slist_append(headers, header_line); 273 + char *key_str = strndup(key, key_len); 274 + tlsuv_http_req_header(req->http_req, key_str, value_str); 275 + free(key_str); 132 276 } 133 277 } 134 278 js_prop_iter_end(&iter); 135 - 136 - if (headers) { 137 - curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); 138 - } 139 279 } 140 280 } 141 281 142 - if (body) { 143 - curl_easy_setopt(curl, CURLOPT_POSTFIELDS, body); 144 - curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, (long)strlen(body)); 145 - } 146 - 147 - CURLcode res = curl_easy_perform(curl); 148 - if (headers) curl_slist_free_all(headers); 149 - 150 - if (res != CURLE_OK) { 151 - free(response_buf.data); 152 - const char *err_msg = curl_easy_strerror(res); 153 - jsval_t err = js_mkstr(js, err_msg, strlen(err_msg)); 154 - js_reject_promise(js, promise, err); 155 - return js_mkundef(); 282 + if (body && body_len > 0) { 283 + tlsuv_http_req_data(req->http_req, body, body_len, body_cb); 156 284 } 157 285 158 - long status_code = 0; 159 - curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &status_code); 160 - 161 - jsval_t response = create_response(js, (int)status_code, response_buf.data, response_buf.size); 162 - 163 - free(response_buf.data); 164 - js_resolve_promise(js, promise, response); 165 - 166 286 return js_mkundef(); 167 287 } 168 288 169 289 static jsval_t js_fetch(struct js *js, jsval_t *args, int nargs) { 170 - if (nargs < 1) { 171 - return js_mkerr(js, "fetch requires at least 1 argument"); 172 - } 173 - 174 - if (js_type(args[0]) != JS_STR) { 175 - return js_mkerr(js, "fetch URL must be a string"); 176 - } 290 + if (nargs < 1) return js_mkerr(js, "fetch requires at least 1 argument"); 291 + if (js_type(args[0]) != JS_STR) return js_mkerr(js, "fetch URL must be a string"); 177 292 178 293 jsval_t url_val = args[0]; 179 294 jsval_t options_val = nargs > 1 ? args[1] : js_mkundef(); 180 295 181 296 jsval_t promise = js_mkpromise(js); 182 - 183 297 jsval_t wrapper_obj = js_mkobj(js); 298 + 184 299 js_set(js, wrapper_obj, "__native_func", js_mkfun(do_fetch_microtask)); 185 300 js_set(js, wrapper_obj, "url", url_val); 186 301 js_set(js, wrapper_obj, "options", options_val); ··· 195 310 } 196 311 197 312 void init_fetch_module() { 198 - static int curl_initialized = 0; 199 - if (!curl_initialized) { 200 - curl_global_init(CURL_GLOBAL_DEFAULT); 201 - curl_initialized = 1; 202 - 203 - global_curl = curl_easy_init(); 204 - if (!global_curl) { 205 - fprintf(stderr, "Warning: Failed to initialize CURL handle\n"); 206 - } 207 - 208 - atexit(cleanup_fetch_module); 209 - } 210 - 313 + if (!fetch_loop) fetch_loop = uv_default_loop(); 211 314 struct js *js = rt->js; 212 315 js_set(js, js_glob(js), "fetch", js_mkfun(js_fetch)); 213 316 } 214 317 215 - static void cleanup_fetch_module() { 216 - if (global_curl) { 217 - curl_easy_cleanup(global_curl); 218 - global_curl = NULL; 219 - } 220 - curl_global_cleanup(); 318 + int has_pending_fetches(void) { 319 + return pending_requests != NULL || (fetch_loop && uv_loop_alive(fetch_loop)); 320 + } 321 + 322 + void fetch_poll_events(void) { 323 + if (fetch_loop && uv_loop_alive(fetch_loop)) uv_run(fetch_loop, UV_RUN_ONCE); 221 324 }
+3 -31
src/tools/gen_snapshot.c
··· 4 4 #include <libgen.h> 5 5 #include <limits.h> 6 6 7 - #include "ant.h" 8 - #include "runtime.h" 9 - 10 7 typedef struct { 11 8 char *placeholder; 12 9 char *value; ··· 497 494 } 498 495 free(cache.paths); 499 496 500 - struct js *js = js_create_dynamic(1024 * 1024, 10 * 1024 * 1024); 501 - if (!js) { 502 - fprintf(stderr, "Error: Failed to create JS runtime\n"); 503 - free(js_code); 504 - return 1; 505 - } 506 - 507 - ant_runtime_init(js); 508 - 509 - jsval_t result = js_eval(js, js_code, processed_len); 510 - if (js_type(result) == JS_ERR) { 511 - fprintf(stderr, "Error: Failed to evaluate JS code:\n%s\n", js_str(js, result)); 512 - js_destroy(js); 513 - free(js_code); 514 - return 1; 515 - } 516 - 517 - size_t total_mem, min_free, cstack; 518 - js_stats(js, &total_mem, &min_free, &cstack); 519 - size_t used_mem = js_getbrk(js); 520 - 521 497 FILE *out = fopen(output_file, "w"); 522 498 if (!out) { 523 499 fprintf(stderr, "Error: Cannot open output file: %s\n", output_file); 524 - js_destroy(js); 525 500 free(js_code); 526 501 return 1; 527 502 } ··· 547 522 548 523 fprintf(out, "\n};\n\n"); 549 524 fprintf(out, "static const size_t ant_snapshot_source_len = %zu;\n\n", processed_len); 550 - fprintf(out, "/* memory usage after evaluation: %zu bytes */\n", used_mem); 551 - fprintf(out, "/* total memory: %zu bytes */\n", total_mem); 552 - fprintf(out, "static const size_t ant_snapshot_mem_size = %zu;\n\n", used_mem); 525 + fprintf(out, "/* bundled source size: %zu bytes */\n", processed_len); 526 + fprintf(out, "static const size_t ant_snapshot_mem_size = %zu;\n\n", processed_len); 553 527 554 528 fprintf(out, "#endif /* ANT_SNAPSHOT_DATA_H */\n"); 555 529 556 530 fclose(out); 557 - js_destroy(js); 558 531 free(js_code); 559 532 560 533 for (int i = 0; i < num_replacements; i++) { ··· 565 538 566 539 printf("snapshot generated successfully: %s\n", output_file); 567 540 printf(" original size: %ld bytes\n", file_size); 568 - printf(" processed size: %zu bytes\n", processed_len); 569 - printf(" memory used: %zu bytes\n", used_mem); 541 + printf(" bundled size: %zu bytes\n", processed_len); 570 542 printf(" replacements: %d\n", num_replacements); 571 543 572 544 return 0;
+5
subprojects/tlsuv.wrap
··· 1 + [wrap-git] 2 + url = https://github.com/openziti/tlsuv 3 + revision = v0.40.0 4 + depth = 1 5 + clone-recursive = true
+9 -5
tests/fetch.cjs
··· 1 1 async function test_get() { 2 - const { origin } = (await fetch('https://httpbin.org/get')).json(); 3 - console.log(origin); 2 + const { ip } = (await fetch('https://ifconfig.co/json')).json(); 3 + console.log(ip); 4 + } 5 + 6 + async function test_json() { 7 + const test = (await fetch('https://themackabu.dev/test.json')).json(); 8 + console.log(test); 4 9 } 5 10 6 11 async function test_post() { 7 - const response = await fetch('https://httpbin.org/post', { 12 + const response = await fetch('https://httpbingo.org/post', { 8 13 method: 'POST', 9 14 body: JSON.stringify({ runtime: 'ant' }), 10 15 headers: { ··· 17 22 console.log(`${json}\n${headers}`); 18 23 } 19 24 20 - void test_get(); 21 - void test_post(); 25 + void Promise.all([test_get(), test_post(), test_json()]);