static int es_faprovider_register(duk_context *ctx) { es_context_t *ec = es_get(ctx); const char *name = duk_require_string(ctx, 0); es_fap_t *ef = es_resource_alloc(&es_resource_fap); ef->fap.fap_opaque = ef; if(es_prop_is_true(ctx, 1, "cachable")) ef->fap.fap_flags |= FAP_ALLOW_CACHE, ef->fap.fap_fini = es_fap_fini; ef->fap.fap_open = es_fap_open; ef->fap.fap_seek = es_fap_seek; ef->fap.fap_read = es_fap_read; ef->fap.fap_close = es_fap_close; ef->fap.fap_fsize = es_fap_fsize; ef->fap.fap_stat = es_fap_stat; ef->name = strdup(name); ef->fap.fap_name = ef->name; es_resource_retain(&ef->super); // Refcount owned by FAP fileaccess_register_dynamic(&ef->fap); es_resource_link(&ef->super, ec, 1); es_root_register(ctx, 1, ef); es_resource_push(ctx, &ef->super); return 1; }
static void es_fa_read(void *aux) { es_fa_handle_t *fah = aux; es_fap_t *ef = fah->fah_ef; es_context_t *ec = ef->super.er_ctx; duk_context *ctx = ec->ec_duk; es_context_begin(ec); duk_set_top(ctx, 0); duk_push_external_buffer(ctx); es_root_register(ctx, -1, fah->fah_readbuf); duk_config_buffer(ctx, 0, fah->fah_readbuf, fah->fah_readlen); es_push_root(ctx, ef); duk_get_prop_string(ctx, -1, "read"); es_push_native_obj(ctx, &es_native_fah, fah_retain(fah)); es_push_root(ctx, fah); duk_push_buffer_object(ctx, 0, 0, fah->fah_readlen, DUK_BUFOBJ_UINT8ARRAY); duk_push_int(ctx, fah->fah_readlen); duk_push_number(ctx, fah->fah_fpos); int rc = duk_pcall(ctx, 5); if(rc) { fah_exception(fah, ctx); es_dump_err(ctx); } es_context_end(ec, 0); fah_release(fah); }
static int set_timer(duk_context *duk, int repeat) { es_context_t *ec = es_get(duk); es_timer_t *et = es_resource_create(ec, &es_resource_timer, 1); int val = duk_require_int(duk, 1); es_root_register(duk, 0, et); et->et_interval = val * repeat; int64_t now = arch_get_ts(); et->et_expire = now + val * 1000LL; hts_mutex_lock(&timer_mutex); if(thread_running == 0) { thread_running = 1; hts_thread_create_detached("estimer", timer_thread, NULL, THREAD_PRIO_MODEL); } else { hts_cond_signal(&timer_cond); } LIST_INSERT_SORTED(&timers, et, et_link, estimercmp, es_timer_t); hts_mutex_unlock(&timer_mutex); es_resource_push(duk, &et->super); return 1; }
static int es_faprovider_openRespond(duk_context *ctx) { es_fa_handle_t *fah = es_get_native_obj(ctx, 0, &es_native_fah); if(duk_get_boolean(ctx, 1)) { es_root_register(ctx, 2, fah); fah_ok(fah); } else { fah_fail(fah, ctx); } return 0; }
static int es_route_create(duk_context *ctx) { const char *str = duk_safe_to_string(ctx, 0); if(str[0] != '^') { int l = strlen(str); char *s = alloca(l + 2); s[0] = '^'; memcpy(s+1, str, l+1); str = s; } es_context_t *ec = es_get(ctx); hts_mutex_lock(&route_mutex); es_route_t *er; LIST_FOREACH(er, &routes, er_link) if(!strcmp(er->er_pattern, str)) break; if(er != NULL) { hts_mutex_unlock(&route_mutex); duk_error(ctx, DUK_ERR_ERROR, "Route %s already exist", str); } er = es_resource_alloc(&es_resource_route); if(hts_regcomp(&er->er_regex, str)) { hts_mutex_unlock(&route_mutex); free(er); duk_error(ctx, DUK_ERR_ERROR, "Invalid regular expression for route %s", str); } er->er_pattern = strdup(str); er->er_prio = strcspn(str, "()[].*?+$") ?: INT32_MAX; LIST_INSERT_SORTED(&routes, er, er_link, er_cmp, es_route_t); es_resource_link(&er->super, ec, 1); hts_mutex_unlock(&route_mutex); es_root_register(ctx, 1, er); es_resource_push(ctx, &er->super); return 1; }