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.

use SLOT_DATA for response context instead of __store

Replace js_getthis() with js_getcurrentfunc() and SLOT_DATA for accessing
context in response methods. This allows methods like c.res.body to work
when passed directly to .then() without requiring .bind().

- Add js_heavy_mkfun() to create functions with attached data
- Add ANT_PTR() macro for pointer-to-jsval conversion
- Update res_body, res_header, res_status, res_html, res_json,
res_notFound, res_redirect to use js_getcurrentfunc() + SLOT_DATA
- Update req_header, js_set_prop, js_get_prop similarly
- Remove __response_ctx and __headers properties from objects

+252 -127
+25
examples/demo/fetch.js
··· 1 + const fetchJson = (url, options) => fetch(url, options).then(r => r.json()); 2 + 3 + const test_get = async () => { 4 + const { ip } = await fetchJson('https://ifconfig.co/json'); 5 + console.log(ip); 6 + }; 7 + 8 + const test_json = async () => { 9 + const test = await fetchJson('https://themackabu.dev/test.json'); 10 + console.log(JSON.stringify(test)); 11 + }; 12 + 13 + const test_post = async () => { 14 + const { json, headers } = await fetchJson('https://httpbingo.org/post', { 15 + method: 'POST', 16 + body: JSON.stringify({ runtime: 'ant' }), 17 + headers: { 18 + 'Content-Type': 'application/json', 19 + 'User-Agent': 'ant/alpha (ant)' 20 + } 21 + }); 22 + console.log(`${JSON.stringify(json)}\n${JSON.stringify(headers)}`); 23 + }; 24 + 25 + Promise.all([test_get(), test_post(), test_json()]);
+13 -15
examples/server/server.js
··· 11 11 addRoute(router, 'GET', '/meow', async c => { 12 12 const userAgent = c.req.header('User-Agent'); 13 13 c.res.header('X-Ant', 'meow'); 14 - 15 14 return c.res.body(`${meow}\n\n${userAgent}`); 16 15 }); 17 16 18 - addRoute(router, 'GET', '/echo', c => 19 - fetch('http://localhost:8000/meow').then(res => { 20 - c.res.header('X-Ant', 'meow'); 21 - c.res.body(res.body); 22 - }) 23 - ); 17 + addRoute(router, 'GET', '/echo', c => { 18 + c.res.header('X-Ant', 'meow'); 19 + fetch('http://localhost:8000/meow') 20 + .then(res => res.text()) 21 + .then(c.res.body); 22 + }); 24 23 25 - addRoute(router, 'GET', '/get', c => { 26 - console.log(c.get('meow')); 27 - c.res.body(decodeURIComponent(c.get('meow'))); 24 + addRoute(router, 'GET', '/get/:id', c => { 25 + c.res.body(decodeURIComponent(c.get(c.params.id))); 28 26 }); 29 27 30 - addRoute(router, 'GET', '/set/**:val', c => { 31 - c.set('meow', c.params.val); 32 - c.res.body(`meow = ${c.params.val}`); 28 + addRoute(router, 'GET', '/set/:id/**:val', c => { 29 + c.set(c.params.id, c.params.val); 30 + c.res.body(`${c.params.id} = ${c.params.val}`); 33 31 }); 34 32 35 33 addRoute(router, 'GET', '/fs/meow', async c => { ··· 61 59 62 60 addRoute(router, 'GET', '/zen', async c => { 63 61 const response = await fetch('https://api.github.com/zen'); 64 - return c.res.body(response.body); 62 + return c.res.body(await response.text()); 65 63 }); 66 64 67 65 addRoute(router, 'GET', '/api/v2/demo', async c => { 68 66 const data = await fetch('https://themackabu.dev/test.json'); 69 - return c.res.json(data.json()); 67 + return c.res.json(await data.json()); 70 68 }); 71 69 72 70 addRoute(router, 'GET', '/files/**:path', async c => {
+3
include/ant.h
··· 15 15 16 16 #define ANT_LIMIT_SIZE_CACHE 16384 17 17 #define ANT_STRING(s) js_mkstr(js, s, sizeof(s) - 1) 18 + #define ANT_PTR(ptr) js_mknum((unsigned long)(ptr)) 18 19 19 20 struct js; 20 21 ··· 88 89 jsval_t js_mkerr(struct js *js, const char *fmt, ...); 89 90 jsval_t js_mkerr_typed(struct js *js, js_err_type_t err_type, const char *fmt, ...); 90 91 jsval_t js_mkfun(jsval_t (*fn)(struct js *, jsval_t *, int)); 92 + jsval_t js_heavy_mkfun(struct js *js, jsval_t (*fn)(struct js *, jsval_t *, int), jsval_t data); 93 + 91 94 jsval_t js_call(struct js *js, jsval_t func, jsval_t *args, int nargs); 92 95 jsval_t js_call_with_this(struct js *js, jsval_t func, jsval_t this_val, jsval_t *args, int nargs); 93 96
+1
include/config.h
··· 52 52 SLOT_PRIMITIVE, 53 53 SLOT_PROXY_REF, 54 54 SLOT_BUILTIN, 55 + SLOT_DATA, 55 56 SLOT_MAX = 255 56 57 } internal_slot_t; 57 58
+1
include/config.h.in
··· 41 41 SLOT_PRIMITIVE, 42 42 SLOT_PROXY_REF, 43 43 SLOT_BUILTIN, 44 + SLOT_DATA, 44 45 SLOT_MAX = 255 45 46 } internal_slot_t; 46 47
+142 -37
src/ant.c
··· 4587 4587 return lkp_interned(js, obj, search_intern, len); 4588 4588 } 4589 4589 4590 + static jsval_t *resolve_bound_args(struct js *js, jsval_t func_obj, jsval_t *args, int nargs, int *out_nargs) { 4591 + *out_nargs = nargs; 4592 + 4593 + jsval_t bound_arr = get_slot(js, func_obj, SLOT_BOUND_ARGS); 4594 + int bound_argc = 0; 4595 + 4596 + if (vtype(bound_arr) == T_ARR) { 4597 + jsoff_t len_off = lkp_interned(js, bound_arr, INTERN_LENGTH, 6); 4598 + if (len_off != 0) { 4599 + jsval_t len_val = resolveprop(js, mkval(T_PROP, len_off)); 4600 + if (vtype(len_val) == T_NUM) bound_argc = (int) tod(len_val); 4601 + } 4602 + } 4603 + 4604 + if (bound_argc <= 0) return NULL; 4605 + 4606 + *out_nargs = bound_argc + nargs; 4607 + jsval_t *combined = (jsval_t *)ANT_GC_MALLOC(sizeof(jsval_t) * (*out_nargs)); 4608 + if (!combined) return NULL; 4609 + 4610 + for (int i = 0; i < bound_argc; i++) { 4611 + char idx[16]; 4612 + snprintf(idx, sizeof(idx), "%d", i); 4613 + jsoff_t prop_off = lkp(js, bound_arr, idx, strlen(idx)); 4614 + combined[i] = (prop_off != 0) ? resolveprop(js, mkval(T_PROP, prop_off)) : js_mkundef(); 4615 + } 4616 + for (int i = 0; i < nargs; i++) combined[bound_argc + i] = args[i]; 4617 + 4618 + return combined; 4619 + } 4620 + 4590 4621 static jsoff_t lkp_scope(struct js *js, jsval_t scope, const char *buf, size_t len) { 4591 4622 const char *search_intern = intern_string(buf, len); 4592 4623 if (!search_intern) return 0; ··· 6040 6071 js->this_val = bound_this; 6041 6072 } 6042 6073 6074 + jsval_t saved_func = js->current_func; 6075 + js->current_func = func; 6076 + 6043 6077 jsval_t (*fn)(struct js *, jsval_t *, int) = (jsval_t(*)(struct js *, jsval_t *, int)) vdata(cfunc_slot); 6044 6078 jsval_t result = fn(js, args, nargs); 6045 6079 6080 + js->current_func = saved_func; 6046 6081 if (vtype(bound_this) != JS_UNDEF) { 6047 6082 pop_this(); 6048 6083 js->this_val = saved_this; ··· 6298 6333 jsval_t func_obj = mkval(T_OBJ, vdata(func)); 6299 6334 jsval_t cfunc_slot = get_slot(js, func_obj, SLOT_CFUNC); 6300 6335 if (vtype(cfunc_slot) == T_CFUNC) { 6336 + jsval_t bound_this_slot = get_slot(js, func_obj, SLOT_BOUND_THIS); 6337 + bool has_bound_this = vtype(bound_this_slot) != T_UNDEF; 6338 + 6339 + if (has_bound_this) { 6340 + pop_this(); 6341 + push_this(bound_this_slot); 6342 + } 6343 + 6301 6344 jsval_t saved_func = js->current_func; 6302 6345 js->current_func = func; 6303 - res = call_c(js, (jsval_t(*)(struct js *, jsval_t *, int)) vdata(cfunc_slot)); 6346 + 6347 + int bound_argc; 6348 + jsval_t *bound_args = resolve_bound_args(js, func_obj, NULL, 0, &bound_argc); 6349 + 6350 + if (!bound_args) { 6351 + res = call_c(js, (jsval_t(*)(struct js *, jsval_t *, int)) vdata(cfunc_slot)); 6352 + } else { 6353 + UT_array *args_arr; 6354 + utarray_new(args_arr, &jsval_icd); 6355 + for (int i = 0; i < bound_argc; i++) utarray_push_back(args_arr, &bound_args[i]); 6356 + ANT_GC_FREE(bound_args); 6357 + 6358 + jsval_t err; 6359 + int call_argc = parse_call_args(js, args_arr, &err); 6360 + if (call_argc < 0) { 6361 + utarray_free(args_arr); 6362 + js->current_func = saved_func; 6363 + if (has_bound_this) pop_this(); 6364 + return err; 6365 + } 6366 + 6367 + jsval_t *argv = (jsval_t *)utarray_front(args_arr); 6368 + int total_argc = (int)utarray_len(args_arr); 6369 + jsval_t saved_this = js->this_val; 6370 + js->this_val = peek_this(); 6371 + res = ((jsval_t(*)(struct js *, jsval_t *, int)) vdata(cfunc_slot))(js, argv, total_argc); 6372 + js->this_val = saved_this; 6373 + setlwm(js); 6374 + utarray_free(args_arr); 6375 + } 6376 + 6304 6377 js->current_func = saved_func; 6378 + 6379 + if (has_bound_this) { 6380 + pop_this(); 6381 + push_this(target_this); 6382 + } 6305 6383 } else { 6306 6384 jsval_t builtin_slot = get_slot(js, func_obj, SLOT_BUILTIN); 6307 6385 if (vtype(builtin_slot) == T_NUM && tod(builtin_slot) == BUILTIN_OBJECT) res = call_c(js, builtin_Object); else { ··· 6329 6407 is_bound = true; 6330 6408 } 6331 6409 6332 - jsval_t bound_args_storage[64]; 6333 - jsval_t *bound_args = NULL; 6334 - int bound_argc = 0; 6335 - jsval_t bound_arr = get_slot(js, func_obj, SLOT_BOUND_ARGS); 6336 - if (vtype(bound_arr) == T_ARR) { 6337 - jsoff_t len_off = lkp_interned(js, bound_arr, INTERN_LENGTH, 6); 6338 - if (len_off != 0) { 6339 - jsval_t len_val = resolveprop(js, mkval(T_PROP, len_off)); 6340 - if (vtype(len_val) == T_NUM) { 6341 - bound_argc = (int) tod(len_val); 6342 - if (bound_argc > 64) bound_argc = 64; 6343 - } 6344 - } 6345 - if (bound_argc > 0) { 6346 - bound_args = bound_args_storage; 6347 - for (int i = 0; i < bound_argc; i++) { 6348 - char idx[16]; 6349 - snprintf(idx, sizeof(idx), "%d", i); 6350 - jsoff_t prop_off = lkp(js, bound_arr, idx, strlen(idx)); 6351 - bound_args[i] = (prop_off != 0) ? resolveprop(js, mkval(T_PROP, prop_off)) : js_mkundef(); 6352 - } 6353 - } 6354 - } 6410 + int bound_argc; 6411 + jsval_t *bound_args = resolve_bound_args(js, func_obj, NULL, 0, &bound_argc); 6355 6412 6356 6413 jsval_t nfe_name_val = js_mkundef(); 6357 6414 jsval_t slot_name = get_slot(js, func_obj, SLOT_NAME); ··· 6468 6525 skip_fields: 6469 6526 if (is_async) { 6470 6527 res = start_async_in_coroutine(js, code_str, fnlen, closure_scope, bound_args, bound_argc); 6471 - pop_call_frame(); 6472 6528 } else { 6473 6529 res = call_js_internal(js, code_str, fnlen, closure_scope, bound_args, bound_argc, func); 6474 - pop_call_frame(); 6475 6530 } 6531 + pop_call_frame(); 6532 + if (bound_args) ANT_GC_FREE(bound_args); 6476 6533 js->current_func = saved_func; 6477 6534 } 6478 6535 } ··· 12117 12174 set_slot(js, bound_func, SLOT_CODE, code_val); 12118 12175 } 12119 12176 12177 + jsval_t cfunc_slot = get_slot(js, func_obj, SLOT_CFUNC); 12178 + if (vtype(cfunc_slot) == T_CFUNC) { 12179 + set_slot(js, bound_func, SLOT_CFUNC, cfunc_slot); 12180 + } 12181 + 12120 12182 jsval_t scope_slot = get_slot(js, func_obj, SLOT_SCOPE); 12121 12183 if (vtype(scope_slot) != T_UNDEF) { 12122 12184 set_slot(js, bound_func, SLOT_SCOPE, scope_slot); ··· 12125 12187 jsval_t async_slot = get_slot(js, func_obj, SLOT_ASYNC); 12126 12188 if (vtype(async_slot) == T_BOOL && vdata(async_slot) == 1) { 12127 12189 set_slot(js, bound_func, SLOT_ASYNC, js_mktrue()); 12190 + } 12191 + 12192 + jsval_t data_slot = get_slot(js, func_obj, SLOT_DATA); 12193 + if (vtype(data_slot) != T_UNDEF) { 12194 + set_slot(js, bound_func, SLOT_DATA, data_slot); 12128 12195 } 12129 12196 12130 12197 set_slot(js, bound_func, SLOT_TARGET_FUNC, func); ··· 21185 21252 inline void js_setthis(struct js *js, jsval_t val) { js->this_val = val; } 21186 21253 inline jsval_t js_getcurrentfunc(struct js *js) { return js->current_func; } 21187 21254 21255 + jsval_t js_heavy_mkfun(struct js *js, jsval_t (*fn)(struct js *, jsval_t *, int), jsval_t data) { 21256 + jsval_t cfunc = js_mkfun(fn); 21257 + jsval_t fn_obj = mkobj(js, 0); 21258 + 21259 + set_slot(js, fn_obj, SLOT_CFUNC, cfunc); 21260 + set_slot(js, fn_obj, SLOT_DATA, data); 21261 + 21262 + return mkval(T_FUNC, (unsigned long)vdata(fn_obj)); 21263 + } 21264 + 21188 21265 void js_set(struct js *js, jsval_t obj, const char *key, jsval_t val) { 21189 21266 size_t key_len = strlen(key); 21190 21267 ··· 21550 21627 } else if (vtype(func) == T_FUNC) { 21551 21628 jsval_t func_obj = mkval(T_OBJ, vdata(func)); 21552 21629 jsval_t cfunc_slot = get_slot(js, func_obj, SLOT_CFUNC); 21630 + 21553 21631 if (vtype(cfunc_slot) == T_CFUNC) { 21632 + jsval_t slot_bound_this = get_slot(js, func_obj, SLOT_BOUND_THIS); 21633 + bool has_slot_bound_this = vtype(slot_bound_this) != T_UNDEF; 21634 + 21635 + int final_nargs; 21636 + jsval_t *combined_args = resolve_bound_args(js, func_obj, args, nargs, &final_nargs); 21637 + jsval_t *final_args = combined_args ? combined_args : args; 21638 + 21554 21639 jsval_t saved_func = js->current_func; 21555 21640 jsval_t saved_this = js->this_val; 21556 21641 js->current_func = func; 21557 - if (use_bound_this) js->this_val = bound_this; 21642 + 21643 + if (has_slot_bound_this) { 21644 + js->this_val = slot_bound_this; 21645 + } else if (use_bound_this) js->this_val = bound_this; 21646 + 21558 21647 jsval_t (*fn)(struct js *, jsval_t *, int) = (jsval_t(*)(struct js *, jsval_t *, int)) vdata(cfunc_slot); 21559 - jsval_t res = fn(js, args, nargs); 21648 + jsval_t res = fn(js, final_args, final_nargs); 21560 21649 js->current_func = saved_func; 21561 21650 js->this_val = saved_this; 21651 + 21652 + if (combined_args) ANT_GC_FREE(combined_args); 21562 21653 return res; 21563 21654 } 21655 + 21564 21656 jsval_t code_val = get_slot(js, func_obj, SLOT_CODE); 21565 21657 if (vtype(code_val) != T_STR) return js_mkerr(js, "function has no code"); 21566 21658 jsoff_t fnlen, fnoff = vstr(js, code_val, &fnlen); 21567 21659 const char *fn = (const char *) (&js->mem[fnoff]); 21568 21660 21661 + jsval_t slot_bound_this = get_slot(js, func_obj, SLOT_BOUND_THIS); 21662 + bool has_slot_bound_this = vtype(slot_bound_this) != T_UNDEF; 21663 + 21664 + int final_nargs; 21665 + jsval_t *combined_args = resolve_bound_args(js, func_obj, args, nargs, &final_nargs); 21666 + jsval_t *final_args = combined_args ? combined_args : args; 21667 + 21569 21668 jsval_t async_slot = get_slot(js, func_obj, SLOT_ASYNC); 21570 21669 bool is_async = vtype(async_slot) == T_BOOL && vdata(async_slot) == 1; 21571 21670 21572 21671 if (is_async) { 21573 21672 jsval_t closure_scope = get_slot(js, func_obj, SLOT_SCOPE); 21574 - return start_async_in_coroutine(js, fn, fnlen, closure_scope, args, nargs); 21673 + jsval_t res = start_async_in_coroutine(js, fn, fnlen, closure_scope, final_args, final_nargs); 21674 + if (combined_args) ANT_GC_FREE(combined_args); 21675 + return res; 21575 21676 } 21576 21677 21577 21678 jsval_t saved_scope = js->scope; 21578 21679 jsval_t closure_scope = get_slot(js, func_obj, SLOT_SCOPE); 21579 - if (vtype(closure_scope) == T_OBJ) { 21580 - js->scope = closure_scope; 21581 - } 21680 + if (vtype(closure_scope) == T_OBJ) js->scope = closure_scope; 21582 21681 21583 21682 uint8_t saved_flags = js->flags; 21584 21683 js->flags = 0; ··· 21589 21688 if (!pf) { 21590 21689 delscope(js); 21591 21690 js->scope = saved_scope; 21691 + if (combined_args) ANT_GC_FREE(combined_args); 21592 21692 return js_mkerr(js, "failed to parse function"); 21593 21693 } 21594 21694 ··· 21597 21697 parsed_param_t *pp = (parsed_param_t *)utarray_eltptr(pf->params, i); 21598 21698 21599 21699 if (pp->is_destruct) { 21600 - jsval_t arg_val = (arg_idx < nargs) ? args[arg_idx++] : js_mkundef(); 21700 + jsval_t arg_val = (arg_idx < final_nargs) ? final_args[arg_idx++] : js_mkundef(); 21601 21701 if (vtype(arg_val) == T_UNDEF && pp->default_len > 0) { 21602 21702 arg_val = js_eval_str(js, &fn[pp->default_start], pp->default_len); 21603 21703 } 21604 21704 bind_destruct_pattern(js, &fn[pp->pattern_off], pp->pattern_len, arg_val, js->scope); 21605 21705 } else { 21606 - jsval_t v = arg_idx < nargs ? args[arg_idx++] : js_mkundef(); 21706 + jsval_t v = arg_idx < final_nargs ? final_args[arg_idx++] : js_mkundef(); 21607 21707 if (vtype(v) == T_UNDEF && pp->default_len > 0) { 21608 21708 v = js_eval_str(js, &fn[pp->default_start], pp->default_len); 21609 21709 } ··· 21615 21715 jsval_t rest_array = mkarr(js); 21616 21716 if (!is_err(rest_array)) { 21617 21717 jsoff_t idx = 0; 21618 - while (arg_idx < nargs) { 21718 + while (arg_idx < final_nargs) { 21619 21719 char idxstr[16]; 21620 21720 size_t idxlen = uint_to_str(idxstr, sizeof(idxstr), (unsigned)idx); 21621 21721 jsval_t key = js_mkstr(js, idxstr, idxlen); 21622 - setprop(js, rest_array, key, args[arg_idx]); 21722 + setprop(js, rest_array, key, final_args[arg_idx]); 21623 21723 idx++; 21624 21724 arg_idx++; 21625 21725 } ··· 21631 21731 } 21632 21732 21633 21733 jsval_t saved_this = js->this_val; 21634 - js->this_val = use_bound_this ? bound_this : js_glob(js); 21734 + if (has_slot_bound_this) { 21735 + js->this_val = slot_bound_this; 21736 + } else if (use_bound_this) { 21737 + js->this_val = bound_this; 21738 + } else js->this_val = js_glob(js); 21635 21739 21636 21740 js_parse_state_t saved_state; 21637 21741 JS_SAVE_STATE(js, saved_state); ··· 21647 21751 js->this_val = saved_this; 21648 21752 delscope(js); 21649 21753 js->scope = saved_scope; 21754 + if (combined_args) ANT_GC_FREE(combined_args); 21650 21755 21651 21756 return res; 21652 21757 }
+32 -8
src/modules/fetch.c
··· 11 11 #include "config.h" 12 12 #include "runtime.h" 13 13 #include "modules/fetch.h" 14 + #include "modules/json.h" 14 15 #include "modules/timer.h" 15 16 16 17 typedef struct { ··· 56 57 } 57 58 } 58 59 60 + static jsval_t response_text(struct js *js, jsval_t *args, int nargs) { 61 + (void)args; (void)nargs; 62 + 63 + jsval_t fn = js_getcurrentfunc(js); 64 + jsval_t body = js_get_slot(js, fn, SLOT_DATA); 65 + jsval_t promise = js_mkpromise(js); 66 + js_resolve_promise(js, promise, body); 67 + 68 + return promise; 69 + } 70 + 71 + static jsval_t response_json(struct js *js, jsval_t *args, int nargs) { 72 + (void)args; (void)nargs; 73 + 74 + jsval_t fn = js_getcurrentfunc(js); 75 + jsval_t body = js_get_slot(js, fn, SLOT_DATA); 76 + jsval_t parsed = js_json_parse(js, &body, 1); 77 + jsval_t promise = js_mkpromise(js); 78 + 79 + if (js_type(parsed) == JS_ERR) { 80 + js_reject_promise(js, promise, parsed); 81 + } else js_resolve_promise(js, promise, parsed); 82 + 83 + return promise; 84 + } 85 + 59 86 static jsval_t create_response(struct js *js, int status, const char *body, size_t body_len) { 60 87 jsval_t response_obj = js_mkobj(js); 61 - 88 + jsval_t body_str = js_mkstr(js, body, body_len); 89 + 90 + js_set(js, response_obj, "ok", status >= 200 && status < 300 ? js_mktrue() : js_mkfalse()); 62 91 js_set(js, response_obj, "status", js_mknum(status)); 63 - js_set(js, response_obj, "ok", status >= 200 && status < 300 ? js_mktrue() : js_mkfalse()); 64 - js_set(js, response_obj, "body", js_mkstr(js, body, body_len)); 65 92 66 - const char *json_code = "(){return JSON.parse(this.body)}"; 67 - jsval_t json_str = js_mkstr(js, json_code, strlen(json_code)); 68 - jsval_t json_obj = js_mkobj(js); 69 - js_set_slot(js, json_obj, SLOT_CODE, json_str); 70 - js_set(js, response_obj, "json", js_obj_to_func(json_obj)); 93 + js_set(js, response_obj, "text", js_heavy_mkfun(js, response_text, body_str)); 94 + js_set(js, response_obj, "json", js_heavy_mkfun(js, response_json, body_str)); 71 95 72 96 return response_obj; 73 97 }
+35 -42
src/modules/server.c
··· 341 341 static jsval_t js_set_prop(struct js *js, jsval_t *args, int nargs) { 342 342 if (nargs < 2) return js_mkundef(); 343 343 344 - jsval_t this_val = js_getthis(js); 345 - jsval_t store_obj = js_get(js, this_val, "__store"); 346 - 347 - if (js_type(store_obj) == JS_UNDEF) { 348 - return js_mkundef(); 349 - } 344 + jsval_t fn = js_getcurrentfunc(js); 345 + jsval_t store_obj = js_get_slot(js, fn, SLOT_DATA); 346 + if (js_type(store_obj) == JS_UNDEF) return js_mkundef(); 350 347 351 348 if (js_type(args[0]) == JS_STR) { 352 349 size_t key_len; ··· 360 357 static jsval_t js_get_prop(struct js *js, jsval_t *args, int nargs) { 361 358 if (nargs < 1) return js_mkundef(); 362 359 363 - jsval_t this_val = js_getthis(js); 364 - jsval_t store_obj = js_get(js, this_val, "__store"); 365 - 366 - if (js_type(store_obj) == JS_UNDEF) { 367 - return js_mkundef(); 368 - } 360 + jsval_t fn = js_getcurrentfunc(js); 361 + jsval_t store_obj = js_get_slot(js, fn, SLOT_DATA); 362 + if (js_type(store_obj) == JS_UNDEF) return js_mkundef(); 369 363 370 364 if (js_type(args[0]) == JS_STR) { 371 365 size_t key_len; ··· 379 373 static jsval_t req_header(struct js *js, jsval_t *args, int nargs) { 380 374 if (nargs < 1) return js_mkundef(); 381 375 382 - jsval_t this_val = js_getthis(js); 383 - jsval_t headers_val = js_get(js, this_val, "__headers"); 376 + jsval_t fn = js_getcurrentfunc(js); 377 + jsval_t headers_val = js_get_slot(js, fn, SLOT_DATA); 384 378 if (js_type(headers_val) != JS_NUM) return js_mkundef(); 385 379 386 380 UT_array *headers = (UT_array *)(unsigned long)js_getnum(headers_val); ··· 403 397 static jsval_t res_header(struct js *js, jsval_t *args, int nargs) { 404 398 if (nargs < 2) return js_mkundef(); 405 399 406 - jsval_t this_val = js_getthis(js); 407 - jsval_t ctx_val = js_get(js, this_val, "__response_ctx"); 400 + jsval_t fn = js_getcurrentfunc(js); 401 + jsval_t ctx_val = js_get_slot(js, fn, SLOT_DATA); 408 402 if (js_type(ctx_val) != JS_NUM) return js_mkundef(); 409 403 410 404 response_ctx_t *ctx = (response_ctx_t *)(unsigned long)js_getnum(ctx_val); ··· 423 417 static jsval_t res_status(struct js *js, jsval_t *args, int nargs) { 424 418 if (nargs < 1) return js_mkundef(); 425 419 426 - jsval_t this_val = js_getthis(js); 427 - jsval_t ctx_val = js_get(js, this_val, "__response_ctx"); 420 + jsval_t fn = js_getcurrentfunc(js); 421 + jsval_t ctx_val = js_get_slot(js, fn, SLOT_DATA); 428 422 if (js_type(ctx_val) != JS_NUM) return js_mkundef(); 429 423 430 424 response_ctx_t *ctx = (response_ctx_t *)(unsigned long)js_getnum(ctx_val); ··· 440 434 static jsval_t res_body(struct js *js, jsval_t *args, int nargs) { 441 435 if (nargs < 1) return js_mkundef(); 442 436 443 - jsval_t this_val = js_getthis(js); 444 - jsval_t ctx_val = js_get(js, this_val, "__response_ctx"); 437 + jsval_t fn = js_getcurrentfunc(js); 438 + jsval_t ctx_val = js_get_slot(js, fn, SLOT_DATA); 445 439 if (js_type(ctx_val) != JS_NUM) return js_mkundef(); 446 440 447 441 response_ctx_t *ctx = (response_ctx_t *)(unsigned long)js_getnum(ctx_val); ··· 469 463 static jsval_t res_html(struct js *js, jsval_t *args, int nargs) { 470 464 if (nargs < 1) return js_mkundef(); 471 465 472 - jsval_t this_val = js_getthis(js); 473 - jsval_t ctx_val = js_get(js, this_val, "__response_ctx"); 466 + jsval_t fn = js_getcurrentfunc(js); 467 + jsval_t ctx_val = js_get_slot(js, fn, SLOT_DATA); 474 468 if (js_type(ctx_val) != JS_NUM) return js_mkundef(); 475 469 476 470 response_ctx_t *ctx = (response_ctx_t *)(unsigned long)js_getnum(ctx_val); ··· 493 487 static jsval_t res_json(struct js *js, jsval_t *args, int nargs) { 494 488 if (nargs < 1) return js_mkundef(); 495 489 496 - jsval_t this_val = js_getthis(js); 497 - jsval_t ctx_val = js_get(js, this_val, "__response_ctx"); 490 + jsval_t fn = js_getcurrentfunc(js); 491 + jsval_t ctx_val = js_get_slot(js, fn, SLOT_DATA); 498 492 if (js_type(ctx_val) != JS_NUM) return js_mkundef(); 499 493 500 494 response_ctx_t *ctx = (response_ctx_t *)(unsigned long)js_getnum(ctx_val); ··· 524 518 } 525 519 526 520 static jsval_t res_notFound(struct js *js, jsval_t *args, int nargs) { 527 - jsval_t this_val = js_getthis(js); 528 - jsval_t ctx_val = js_get(js, this_val, "__response_ctx"); 521 + (void)args; (void)nargs; 522 + 523 + jsval_t fn = js_getcurrentfunc(js); 524 + jsval_t ctx_val = js_get_slot(js, fn, SLOT_DATA); 529 525 if (js_type(ctx_val) != JS_NUM) return js_mkundef(); 530 526 531 527 response_ctx_t *ctx = (response_ctx_t *)(unsigned long)js_getnum(ctx_val); ··· 543 539 static jsval_t res_redirect(struct js *js, jsval_t *args, int nargs) { 544 540 if (nargs < 1) return js_mkundef(); 545 541 546 - jsval_t this_val = js_getthis(js); 547 - jsval_t ctx_val = js_get(js, this_val, "__response_ctx"); 542 + jsval_t fn = js_getcurrentfunc(js); 543 + jsval_t ctx_val = js_get_slot(js, fn, SLOT_DATA); 548 544 if (js_type(ctx_val) != JS_NUM) return js_mkundef(); 549 545 550 546 response_ctx_t *ctx = (response_ctx_t *)(unsigned long)js_getnum(ctx_val); ··· 721 717 js_set(server->js, req, "uri", js_mkstr(server->js, http_req->uri, strlen(http_req->uri))); 722 718 js_set(server->js, req, "query", js_mkstr(server->js, http_req->query, strlen(http_req->query))); 723 719 js_set(server->js, req, "body", js_mkstr(server->js, http_req->body ? http_req->body : "", http_req->body ? http_req->body_len : 0)); 724 - js_set(server->js, req, "__headers", js_mknum((unsigned long)http_req->headers)); 725 - js_set(server->js, req, "header", js_mkfun(req_header)); 720 + js_set(server->js, req, "header", js_heavy_mkfun(server->js, req_header, ANT_PTR(http_req->headers))); 726 721 727 722 jsval_t res_obj = js_mkobj(server->js); 728 - js_set(server->js, res_obj, "__response_ctx", js_mknum((unsigned long)res_ctx)); 729 - js_set(server->js, res_obj, "header", js_mkfun(res_header)); 730 - js_set(server->js, res_obj, "status", js_mkfun(res_status)); 731 - js_set(server->js, res_obj, "body", js_mkfun(res_body)); 732 - js_set(server->js, res_obj, "html", js_mkfun(res_html)); 733 - js_set(server->js, res_obj, "json", js_mkfun(res_json)); 734 - js_set(server->js, res_obj, "notFound", js_mkfun(res_notFound)); 735 - js_set(server->js, res_obj, "redirect", js_mkfun(res_redirect)); 723 + js_set(server->js, res_obj, "header", js_heavy_mkfun(server->js, res_header, ANT_PTR(res_ctx))); 724 + js_set(server->js, res_obj, "status", js_heavy_mkfun(server->js, res_status, ANT_PTR(res_ctx))); 725 + js_set(server->js, res_obj, "body", js_heavy_mkfun(server->js, res_body, ANT_PTR(res_ctx))); 726 + js_set(server->js, res_obj, "html", js_heavy_mkfun(server->js, res_html, ANT_PTR(res_ctx))); 727 + js_set(server->js, res_obj, "json", js_heavy_mkfun(server->js, res_json, ANT_PTR(res_ctx))); 728 + js_set(server->js, res_obj, "notFound", js_heavy_mkfun(server->js, res_notFound, ANT_PTR(res_ctx))); 729 + js_set(server->js, res_obj, "redirect", js_heavy_mkfun(server->js, res_redirect, ANT_PTR(res_ctx))); 736 730 737 731 js_set(server->js, ctx, "req", req); 738 732 js_set(server->js, ctx, "res", res_obj); 739 733 740 - js_set(server->js, ctx, "set", js_mkfun(js_set_prop)); 741 - js_set(server->js, ctx, "get", js_mkfun(js_get_prop)); 742 - js_set(server->js, ctx, "__store", server->store_obj); 743 - 734 + js_set(server->js, ctx, "set", js_heavy_mkfun(server->js, js_set_prop, server->store_obj)); 735 + js_set(server->js, ctx, "get", js_heavy_mkfun(server->js, js_get_prop, server->store_obj)); 736 + 744 737 jsval_t args[1] = {ctx}; 745 738 result = js_call(server->js, server->handler, args, 1); 746 739 if (js_type(result) == JS_PROMISE) return;
-25
tests/fetch.cjs
··· 1 - async function test_get() { 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(JSON.stringify(test)); 9 - } 10 - 11 - async function test_post() { 12 - const response = await fetch('https://httpbingo.org/post', { 13 - method: 'POST', 14 - body: JSON.stringify({ runtime: 'ant' }), 15 - headers: { 16 - 'Content-Type': 'application/json', 17 - 'User-Agent': 'ant/alpha (ant)' 18 - } 19 - }); 20 - 21 - const { json, headers } = response.json(); 22 - console.log(`${JSON.stringify(json)}\n${JSON.stringify(headers)}`); 23 - } 24 - 25 - void Promise.all([test_get(), test_post(), test_json()]);