示例#1
0
static enum v7_err Sys_prof(struct v7 *v7, v7_val_t *res) {
  *res = v7_mk_object(v7);

  v7_set(v7, *res, "sysfree", ~0, v7_mk_number(v7, sj_get_free_heap_size()));
  v7_set(v7, *res, "min_sysfree", ~0,
         v7_mk_number(v7, sj_get_min_free_heap_size()));
  v7_set(v7, *res, "used_by_js", ~0,
         v7_mk_number(v7, v7_heap_stat(v7, V7_HEAP_STAT_HEAP_USED)));
  v7_set(v7, *res, "used_by_fs", ~0,
         v7_mk_number(v7, sj_get_fs_memory_usage()));

  return V7_OK;
}
示例#2
0
static v7_val_t OS_prof(struct v7 *v7, v7_val_t this_obj, v7_val_t args) {
  v7_val_t result = v7_create_object(v7);
  v7_own(v7, &result);

  v7_set(v7, result, "sysfree", 7, 0,
         v7_create_number(sj_get_free_heap_size()));
  v7_set(v7, result, "used_by_js", 10, 0,
         v7_create_number(v7_heap_stat(v7, V7_HEAP_STAT_HEAP_USED)));
  v7_set(v7, result, "used_by_fs", 10, 0,
         v7_create_number(sj_get_fs_memory_usage()));

  v7_disown(v7, &result);
  return result;
}
示例#3
0
文件: js_oop.c 项目: QUSIR/v7
int main(void) {
    enum v7_err rcode = V7_OK;
    struct v7 *v7 = v7_create();
    v7_val_t ctor_func, proto, eval_result;

    proto = v7_mk_object(v7);
    ctor_func = v7_mk_function_with_proto(v7, MyThing_ctor, proto);
    v7_def(v7, ctor_func, "MY_CONST", ~0,
           (V7_DESC_WRITABLE(0) | V7_DESC_CONFIGURABLE(0)), v7_mk_number(123));
    v7_set_method(v7, proto, "myMethod", &MyThing_myMethod);
    v7_set(v7, v7_get_global(v7), "MyThing", ~0, ctor_func);

    rcode = v7_exec(v7,
                    "\
      print('MyThing.MY_CONST = ', MyThing.MY_CONST); \
      var t = new MyThing(456); \
      print('t.MY_CONST = ', t.MY_CONST); \
      print('t.myMethod = ', t.myMethod); \
      print('t.myMethod() = ', t.myMethod());",
                    &eval_result);
    if (rcode != V7_OK) {
        fprintf(stderr, "exec error: %d\n", (int) rcode);
    }

    v7_destroy(v7);
    return (int) rcode;
}
示例#4
0
SJ_PRIVATE enum v7_err Http_response_writeHead(struct v7 *v7, v7_val_t *res) {
  enum v7_err rcode = V7_OK;
  DECLARE_CONN();

  unsigned long code = 200;
  v7_val_t arg0 = v7_arg(v7, 0), arg1 = v7_arg(v7, 1);

  if (v7_is_truthy(v7, v7_get(v7, v7_get_this(v7), "_whd", ~0))) {
    rcode = v7_throwf(v7, "Error", "Headers already sent");
    goto clean;
  }

  if (v7_is_number(arg0)) {
    code = v7_to_number(arg0);
  }

  write_http_status(c, code);
  http_write_headers(v7, arg1, c);
  mg_send(c, "\r\n", 2);
  v7_set(v7, v7_get_this(v7), "_whd", ~0, v7_mk_boolean(1));
  *res = v7_get_this(v7);

clean:
  return rcode;
}
示例#5
0
文件: v7.c 项目: di3online/v7
enum v7_err v7_set_str(struct v7 *v7, struct v7_val *obj,
                       const char *key, const char *str, unsigned long len) {
  struct v7_val *k = v7_mkval_str(v7, key, strlen(key));
  struct v7_val *v = v7_mkval_str(v7, str, len);
  CHECK(k != NULL && v != NULL, V7_OUT_OF_MEMORY);
  return v7_set(v7, obj, k, v);
}
示例#6
0
文件: v7_esp.c 项目: fast01/smart.js
/* Currently can only handle one timer */
ICACHE_FLASH_ATTR static v7_val_t set_timeout(struct v7 *v7, v7_val_t this_obj,
                                              v7_val_t args) {
  v7_val_t cb = v7_array_get(v7, args, 0);
  v7_val_t msecsv = v7_array_get(v7, args, 1);
  int msecs;

  if (!v7_is_function(cb)) {
    printf("cb is not a function\n");
    return v7_create_undefined();
  }
  if (!v7_is_double(msecsv)) {
    printf("msecs is not a double\n");
    return v7_create_undefined();
  }
  msecs = v7_to_double(msecsv);

  /*
   * used to convey the callback to the timer handler _and_ to root
   * the function so that the GC doesn't deallocate it.
   */
  v7_set(v7, v7_get_global_object(v7), "_js_timeout_handler", 19, 0, cb);
  os_timer_disarm(&js_timeout_timer);
  os_timer_setfn(&js_timeout_timer, js_timeout, NULL);
  os_timer_arm(&js_timeout_timer, msecs, 0);

  return v7_create_undefined();
}
void sj_init_ws_client(struct v7 *v7) {
  v7_val_t ws_proto = v7_create_object(v7);
  v7_val_t ws = v7_create_constructor(v7, ws_proto, sj_ws_ctor, 1);
  v7_own(v7, &ws);

  v7_set_method(v7, ws_proto, "send", WebSocket_send);
  v7_set_method(v7, ws_proto, "close", WebSocket_close);
  v7_set(v7, ws_proto, "readyState", ~0,
         V7_PROPERTY_DONT_ENUM | V7_PROPERTY_GETTER,
         v7_create_function(v7, WebSocket_readyState, 0));
  v7_set(v7, ws, "OPEN", ~0, 0, WEBSOCKET_OPEN);
  v7_set(v7, ws, "CLOSED", ~0, 0, WEBSOCKET_CLOSED);
  v7_set(v7, v7_get_global_object(v7), "WebSocket", ~0, 0, ws);

  v7_disown(v7, &ws);
}
示例#8
0
void sj_init_uart(struct v7 *v7) {
  v7_val_t uart = V7_UNDEFINED, uart_proto = V7_UNDEFINED,
           uart_ctor = V7_UNDEFINED;
  v7_own(v7, &uart);
  v7_own(v7, &uart_proto);
  v7_own(v7, &uart_ctor);

  uart = v7_mk_object(v7);
  uart_proto = v7_mk_object(v7);
  uart_ctor = v7_mk_function_with_proto(v7, UART_ctor, uart_proto);

  v7_def(v7, uart, "dev", ~0, _V7_DESC_HIDDEN(1), uart_ctor);
  v7_set_method(v7, uart_proto, "read", UART_read);
  v7_set_method(v7, uart_proto, "write", UART_write);
  v7_set_method(v7, uart_proto, "recv", UART_recv);
  v7_set(v7, v7_get_global(v7), "UART", ~0, uart);
  {
    enum v7_err rcode = v7_exec(
        v7, "UART.open = function (d) { return new UART.dev(d); }", NULL);
    assert(rcode == V7_OK);
#if defined(NDEBUG)
    (void) rcode;
#endif
  }

  v7_disown(v7, &uart_ctor);
  v7_disown(v7, &uart_proto);
  v7_disown(v7, &uart);
}
示例#9
0
static v7_val_t Wifi_changed(struct v7 *v7) {
  v7_val_t cb = v7_arg(v7, 0);
  if (!v7_is_function(cb)) return v7_create_boolean(0);
  v7_set(v7, s_wifi, "_ccb", ~0, V7_PROPERTY_DONT_ENUM | V7_PROPERTY_HIDDEN,
         cb);
  return v7_create_boolean(1);
}
示例#10
0
文件: v7.c 项目: di3online/v7
enum v7_err v7_set_func(struct v7 *v7, struct v7_val *obj,
                        const char *key, v7_func_t c_func) {
  struct v7_val *k = v7_mkval_str(v7, key, strlen(key));
  struct v7_val *v = v7_mkval(v7, V7_C_FUNC);
  CHECK(k != NULL && v != NULL, V7_OUT_OF_MEMORY);
  v->v.c_func = c_func;
  return v7_set(v7, obj, k, v);
}
示例#11
0
文件: v7.c 项目: di3online/v7
enum v7_err v7_set_num(struct v7 *v7, struct v7_val *obj,
                       const char *key, double num) {
  struct v7_val *k = v7_mkval_str(v7, key, strlen(key));
  struct v7_val *v = v7_mkval(v7, V7_NUM);
  CHECK(k != NULL && v != NULL, V7_OUT_OF_MEMORY);
  v->v.num = num;
  return v7_set(v7, obj, k, v);
}
示例#12
0
void sj_sys_js_init(struct v7 *v7) {
  v7_val_t sys, fs;

  sys = v7_mk_object(v7);
  v7_set(v7, v7_get_global(v7), "Sys", ~0, sys);
  v7_set_method(v7, sys, "prof", Sys_prof);
  v7_set_method(v7, sys, "reboot", Sys_reboot);
  v7_set_method(v7, sys, "setLogLevel", Sys_setLogLevel);
  v7_set_method(v7, sys, "time", Sys_time);
  v7_set_method(v7, sys, "wdtFeed", Sys_wdtFeed);
  v7_set_method(v7, sys, "wdtSetTimeout", Sys_wdtSetTimeout);
  v7_set_method(v7, sys, "wdtEnable", Sys_wdtEnable);
  v7_set_method(v7, sys, "wdtDisable", Sys_wdtDisable);
  fs = v7_mk_object(v7);
  v7_set(v7, sys, "fs", ~0, fs);
  v7_set_method(v7, fs, "free", Sys_fs_getFreeSpace);
}
示例#13
0
static v7_val_t GPIO_setisr(struct v7 *v7, v7_val_t this_obj, v7_val_t args) {
  v7_val_t pinv = v7_array_get(v7, args, 0);
  v7_val_t typev = v7_array_get(v7, args, 1);
  v7_val_t cb = v7_array_get(v7, args, 2);
  v7_val_t current_cb;

  char prop_name[15];
  int pin, type, len, has_isr, new_isr_provided;

  if (!v7_is_number(pinv) || !v7_is_number(typev)) {
    printf("Invalid arguments\n");
    return v7_create_boolean(0);
  }

  pin = v7_to_number(pinv);
  type = v7_to_number(typev);

  len = snprintf(prop_name, sizeof(prop_name), "_ih_%d", (int) pin);
  current_cb = v7_get(v7, v7_get_global_object(v7), prop_name, len);
  has_isr = v7_is_function(current_cb);
  new_isr_provided = v7_is_function(cb);

  if (!has_isr && !new_isr_provided) {
    printf("Missing callback\n");
    return v7_create_boolean(0);
  };

  if (has_isr && new_isr_provided && current_cb != cb) {
    printf("Only one interruption handler is allowed for pin\n");
    return v7_create_boolean(0);
  }

  if (type == 0 && has_isr) {
    v7_set(v7, v7_get_global_object(v7), prop_name, len, 0,
           v7_create_undefined());
  } else if (!has_isr && new_isr_provided) {
    v7_set(v7, v7_get_global_object(v7), prop_name, len, 0, cb);
  }

  if (type != 0 && !s_gpio_intr_installed) {
    sj_gpio_intr_init(gpio_intr_handler_proxy);
    s_gpio_intr_installed = 1;
  }

  return v7_create_boolean(sj_gpio_intr_set(pin, type) == 0);
}
示例#14
0
void sj_init_simple_http_client(struct v7 *v7) {
  v7_val_t http;

  http = v7_create_object(v7);
  v7_set(v7, v7_get_global_object(v7), "Http", 4, 0, http);
  v7_set_method(v7, http, "get", sj_http_get);
  v7_set_method(v7, http, "post", sj_http_post);
}
示例#15
0
void init_gpiojs(struct v7 *v7) {
  s_v7 = v7;
  v7_val_t gpio = v7_create_object(v7);
  v7_set(v7, v7_get_global(v7), "GPIO", ~0, 0, gpio);
  v7_set_method(v7, gpio, "setmode", GPIO_setmode);
  v7_set_method(v7, gpio, "read", GPIO_read);
  v7_set_method(v7, gpio, "write", GPIO_write);
  v7_set_method(v7, gpio, "setisr", GPIO_setisr);
}
示例#16
0
void miot_console_api_setup(struct v7 *v7) {
  v7_val_t console_v = v7_mk_object(v7);
  v7_own(v7, &console_v);

  v7_set_method(v7, console_v, "log", Console_log);
  v7_set(v7, v7_get_global(v7), "console", ~0, console_v);

  v7_disown(v7, &console_v);
}
示例#17
0
void sj_gpio_api_setup(struct v7 *v7) {
  s_v7 = v7;
  v7_val_t gpio = v7_mk_object(v7);
  v7_set(v7, v7_get_global(v7), "GPIO", ~0, gpio);
  v7_set_method(v7, gpio, "setmode", GPIO_setmode);
  v7_set_method(v7, gpio, "read", GPIO_read);
  v7_set_method(v7, gpio, "write", GPIO_write);
  v7_set_method(v7, gpio, "setisr", GPIO_setisr);
}
static void ws_ev_handler(struct ns_connection *nc, int ev, void *ev_data) {
  struct websocket_message *wm = (struct websocket_message *) ev_data;
  struct user_data *ud = (struct user_data *) nc->user_data;
  struct v7 *v7 = ud->v7;

  switch (ev) {
    case NS_CONNECT:
      if (*(int *) ev_data == 0) {
        char *proto = NULL;
        if (ud->proto != NULL) {
          int tmp = asprintf(&proto, "Sec-WebSocket-Protocol: %s\n", ud->proto);
          (void) tmp; /* Shutup compiler */
        }
        ns_send_websocket_handshake(nc, "/", proto);
        if (proto != NULL) {
          free(proto);
        }
      } else {
        invoke_cb(ud, "onerror", v7_create_null());
      }
      break;
    case NS_WEBSOCKET_HANDSHAKE_DONE:
      v7_set(v7, ud->ws, "_nc", ~0, V7_PROPERTY_HIDDEN, v7_create_foreign(nc));
      invoke_cb(ud, "onopen", v7_create_null());
      break;
    case NS_WEBSOCKET_FRAME: {
      v7_val_t ev, data;
      ev = v7_create_object(v7);
      v7_own(v7, &ev);
      data = v7_create_string(v7, (char *) wm->data, wm->size, 1);
      v7_set(v7, ev, "data", ~0, 0, data);
      invoke_cb(ud, "onmessage", ev);
      v7_disown(v7, &ev);
      break;
    }
    case NS_CLOSE:
      invoke_cb(ud, "onclose", v7_create_null());
      nc->user_data = NULL;
      v7_set(v7, ud->ws, "_nc", ~0, V7_PROPERTY_HIDDEN, v7_create_undefined());
      v7_disown(v7, &ud->ws);
      free(ud);
      break;
  }
}
示例#19
0
文件: v7.c 项目: di3online/v7
// function_defition = "function" "(" func_params ")" "{" func_body "}"
static enum v7_err parse_function_definition(struct v7 *v7, struct v7_val **v,
                                             int num_params) {
  int i = 0, old_no_exec = v7->no_exec, old_sp = v7->sp;
  const char *src = v7->cursor;

  // If 'v' (func to call) is NULL, that means we're just parsing function
  // definition to save it's body.
  v7->no_exec = v == NULL;
  TRY(match(v7, '('));

  // Initialize new scope
  if (!v7->no_exec) {
    v7->current_scope++;
    CHECK(v7->current_scope < (int) ARRAY_SIZE(v7->scopes),
          V7_RECURSION_TOO_DEEP);
    CHECK(v7->scopes[v7->current_scope].v.props == NULL, V7_INTERNAL_ERROR);
    CHECK(v7->scopes[v7->current_scope].type == V7_OBJ, V7_INTERNAL_ERROR);
  }

  while (*v7->cursor != ')') {
    TRY(parse_identifier(v7));
    if (!v7->no_exec) {
      struct v7_val *key = v7_mkval_str(v7, v7->tok, v7->tok_len);
      struct v7_val *val = i < num_params ? v[i + 1] : v7_mkval(v7, V7_UNDEF);
      v7_set(v7, &v7->scopes[v7->current_scope], key, val);
    }
    i++;
    if (!test_and_skip_char(v7, ',')) break;
  }
  TRY(match(v7, ')'));
  TRY(match(v7, '{'));

  while (*v7->cursor != '}') {
    int is_return_statement = 0;
    inc_stack(v7, old_sp - v7->sp);   // Clean up the stack from prev stmt
    TRY(parse_statement(v7, &is_return_statement));
    if (is_return_statement) break;   // Leave statement value on stack
  }

  if (v7->no_exec) {
    TRY(v7_make_and_push(v7, V7_FUNC));
    v7_top(v7)[-1]->v.func = v7_strdup(src, (v7->cursor + 1) - src);
  }
  TRY(match(v7, '}'));

  // Deinitialize scope
  if (!v7->no_exec) {
    v7->scopes[v7->current_scope].ref_count = 1;  // Force free_val() below
    free_val(v7, &v7->scopes[v7->current_scope]);
    v7->current_scope--;
    assert(v7->current_scope >= 0);
  }

  v7->no_exec = old_no_exec;
  return V7_OK;
}
示例#20
0
void sj_init_v7_ext(struct v7 *v7) {
  v7_val_t os, gc;

  v7_set(v7, v7_get_global(v7), "version", 7, 0,
         v7_create_string(v7, sj_version, strlen(sj_version), 1));

  v7_set_method(v7, v7_get_global(v7), "usleep", global_usleep);

  gc = v7_create_object(v7);
  v7_set(v7, v7_get_global(v7), "GC", 2, 0, gc);
  v7_set_method(v7, gc, "stat", GC_stat);
  v7_set_method(v7, gc, "gc", GC_gc);

  os = v7_create_object(v7);
  v7_set(v7, v7_get_global(v7), "OS", 2, 0, os);
  v7_set_method(v7, os, "prof", OS_prof);
  v7_set_method(v7, os, "wdt_feed", OS_wdt_feed);
  v7_set_method(v7, os, "reset", OS_reset);
}
示例#21
0
void sj_init_sys(struct v7 *v7) {
  v7_val_t sys;

  sys = v7_mk_object(v7);
  v7_set(v7, v7_get_global(v7), "Sys", ~0, sys);
  v7_set_method(v7, sys, "prof", Sys_prof);
  v7_set_method(v7, sys, "wdtFeed", Sys_wdtFeed);
  v7_set_method(v7, sys, "reboot", Sys_reboot);
  v7_set_method(v7, sys, "setLogLevel", Sys_setLogLevel);
}
示例#22
0
void sj_v7_ext_api_setup(struct v7 *v7) {
  v7_val_t gc;

  v7_set_method(v7, v7_get_global(v7), "usleep", global_usleep);

  gc = v7_mk_object(v7);
  v7_set(v7, v7_get_global(v7), "GC", ~0, gc);
  v7_set_method(v7, gc, "stat", GC_stat);
  v7_set_method(v7, gc, "gc", GC_gc);
}
示例#23
0
static enum v7_err UART_onTXEmpty(struct v7 *v7, v7_val_t *res) {
  struct esp_sj_uart_state *us;
  enum v7_err ret = esp_sj_uart_get_state(v7, &us);
  if (ret != V7_OK) return ret;
  v7_set(v7, us->obj, "_txcb", 5, v7_arg(v7, 0));
  if (v7_is_callable(v7, v7_arg(v7, 0))) {
    esp_sj_uart_schedule_dispatcher(us->uart_no);
  }
  *res = v7_mk_undefined();
  return V7_OK;
}
示例#24
0
文件: unit_test.c 项目: dev-gitter/v7
static const char *test_native_functions(void) {
  struct v7_val *v;
  struct v7 *v7 = v7_create();

  ASSERT(v7_set(v7, v7_global(v7), "adder", v7_push_func(v7, adder)) == V7_OK);
  ASSERT((v = v7_exec(v7, "adder(1, 2, 3 + 4);")) != NULL);
  ASSERT(check_num(v7, v, 10.0));
  v7_destroy(&v7);

  return NULL;
}
示例#25
0
static v7_val_t gsm_on_incoming_call(struct v7* v7)
{
     v7_val_t cb = v7_arg(v7, 0);
     if (!v7_is_function(cb)) {
        return v7_create_boolean(0);
     };

     v7_set(v7, v7_get_global(v7), INCOMING_CALL_CB, sizeof(INCOMING_CALL_CB) - 1, 0, cb);
     
    return v7_create_boolean(1);
}
示例#26
0
void init_v7(void *stack_base) {
  struct v7_create_opts opts;
  v7_val_t dht11, debug;

  opts.object_arena_size = 164;
  opts.function_arena_size = 26;
  opts.property_arena_size = 400;
  opts.c_stack_base = stack_base;
  v7 = v7_create_opt(opts);

  v7_set_method(v7, v7_get_global(v7), "dsleep", dsleep);
  v7_set_method(v7, v7_get_global(v7), "crash", crash);

#if V7_ESP_ENABLE__DHT11
  dht11 = v7_create_object(v7);
  v7_set(v7, v7_get_global(v7), "DHT11", 5, 0, dht11);
  v7_set_method(v7, dht11, "read", DHT11_read);
#else
  (void) dht11;
#endif /* V7_ESP_ENABLE__DHT11 */

  debug = v7_create_object(v7);
  v7_set(v7, v7_get_global(v7), "Debug", 5, 0, debug);
  v7_set_method(v7, debug, "mode", Debug_mode);
  v7_set_method(v7, debug, "print", Debug_print);

  sj_init_timers(v7);
  sj_init_v7_ext(v7);

  init_gpiojs(v7);
  init_i2cjs(v7);
  init_pwm(v7);
  init_spijs(v7);
  init_wifi(v7);

  mongoose_init();
  sj_init_http(v7);
  sj_init_ws_client(v7);

  v7_gc(v7, 1);
}
示例#27
0
static v7_val_t DHT11_read(struct v7 *v7) {
  int pin, temp, rh;
  v7_val_t pinv = v7_arg(v7, 0), result;

  if (!v7_is_number(pinv)) {
    printf("non-numeric pin\n");
    return v7_create_undefined();
  }
  pin = v7_to_number(pinv);

  if (!dht11_read(pin, &temp, &rh)) {
    return v7_create_null();
  }

  result = v7_create_object(v7);
  v7_own(v7, &result);
  v7_set(v7, result, "temp", 4, 0, v7_create_number(temp));
  v7_set(v7, result, "rh", 2, 0, v7_create_number(rh));
  v7_disown(v7, &result);
  return result;
}
示例#28
0
void sj_mqtt_api_setup(struct v7 *v7) {
  v7_val_t mqtt_proto = v7_mk_object(v7);
  v7_val_t mqtt_connect =
      v7_mk_function_with_proto(v7, sj_mqtt_connect, mqtt_proto);
  v7_val_t mqtt;
  v7_own(v7, &mqtt_connect);

  mqtt = v7_mk_object(v7);
  v7_own(v7, &mqtt);

  v7_set(v7, mqtt, "connect", ~0, mqtt_connect);
  v7_def(v7, mqtt, "proto", ~0, V7_DESC_ENUMERABLE(0), mqtt_proto);

  v7_set_method(v7, mqtt_proto, "publish", MQTT_publish);
  v7_set_method(v7, mqtt_proto, "subscribe", MQTT_subscribe);
  v7_set_method(v7, mqtt_proto, "on", MQTT_on);
  v7_set(v7, v7_get_global(v7), "MQTT", ~0, mqtt);

  v7_disown(v7, &mqtt);
  v7_disown(v7, &mqtt_connect);
}
示例#29
0
int main(void) {
  struct v7 *v7 = v7_create();
  v7_val_t ctor_func, proto, eval_result;

  proto = v7_create_object(v7);
  ctor_func = v7_create_constructor(v7, proto, MyThing_ctor, 1);
  v7_set(v7, ctor_func, "MY_CONST", ~0,
         V7_PROPERTY_READ_ONLY | V7_PROPERTY_DONT_DELETE,
         v7_create_number(123));
  v7_set_method(v7, proto, "myMethod", &MyThing_myMethod);
  v7_set(v7, v7_get_global_object(v7), "MyThing", ~0, 0, ctor_func);

  v7_exec(v7, &eval_result, "\
      print('MyThing.MY_CONST = ', MyThing.MY_CONST); \
      var t = new MyThing(456); \
      print('t.MY_CONST = ', t.MY_CONST); \
      print('t.myMethod = ', t.myMethod); \
      print('t.myMethod() = ', t.myMethod());");
  v7_destroy(v7);
  return 0;
}
示例#30
0
/*
 * Mongoose event handler. If JavaScript callback was provided, call it
 */
static void http_ev_handler(struct mg_connection *c, int ev, void *ev_data) {
  struct user_data *ud = (struct user_data *) c->user_data;

  if (ev == MG_EV_HTTP_REQUEST) {
    /* HTTP request has arrived */

    if (v7_is_callable(ud->v7, ud->handler)) {
      /* call provided JavaScript callback with `request` and `response` */
      v7_val_t request = v7_mk_object(ud->v7);
      v7_own(ud->v7, &request);
      v7_val_t response = v7_mk_object(ud->v7);
      v7_own(ud->v7, &response);
      setup_request_object(ud->v7, request, ev_data);
      setup_response_object(ud->v7, response, c, request);
      sj_invoke_cb2_this(ud->v7, ud->handler, ud->obj, request, response);
      v7_disown(ud->v7, &request);
      v7_disown(ud->v7, &response);
    } else {
      /*
       * no JavaScript callback provided; serve the request with the default
       * options by `mg_serve_http()`
       */
      struct mg_serve_http_opts opts;
      memset(&opts, 0, sizeof(opts));
      mg_serve_http(c, ev_data, opts);
    }
  } else if (ev == MG_EV_HTTP_REPLY) {
    /* HTTP response has arrived */

    /* if JavaScript callback was provided, call it with `response` */
    if (v7_is_callable(ud->v7, ud->handler)) {
      v7_val_t response = v7_mk_object(ud->v7);
      v7_own(ud->v7, &response);
      setup_request_object(ud->v7, response, ev_data);
      sj_invoke_cb1_this(ud->v7, ud->handler, ud->obj, response);
      v7_disown(ud->v7, &response);
    }

    if (c->flags & MG_F_CLOSE_CONNECTION_AFTER_RESPONSE) {
      c->flags |= MG_F_CLOSE_IMMEDIATELY;
    }
  } else if (ev == MG_EV_TIMER) {
    sj_invoke_cb0_this(ud->v7, ud->timeout_callback, ud->obj);
  } else if (ev == MG_EV_CLOSE) {
    if (c->listener == NULL && ud != NULL) {
      v7_set(ud->v7, ud->obj, "_c", ~0, v7_mk_undefined());
      v7_disown(ud->v7, &ud->obj);
      v7_disown(ud->v7, &ud->timeout_callback);
      free(ud);
      c->user_data = NULL;
    }
  }
}