summaryrefslogtreecommitdiff
path: root/test/addons-napi/test_async/test_async.cc
blob: bc0af66d26ec615f7eb9d0322cd64a7c142769ec (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
#include <node_api.h>
#include "../common.h"

#if defined _WIN32
#include <windows.h>
#else
#include <unistd.h>
#endif

typedef struct {
  int32_t _input;
  int32_t _output;
  napi_ref _callback;
  napi_async_work _request;
} carrier;

carrier the_carrier;

struct AutoHandleScope {
  explicit AutoHandleScope(napi_env env)
  : _env(env),
  _scope(nullptr) {
    napi_open_handle_scope(_env, &_scope);
  }
  ~AutoHandleScope() {
    napi_close_handle_scope(_env, _scope);
  }
 private:
  AutoHandleScope() { }

  napi_env _env;
  napi_handle_scope _scope;
};

void Execute(napi_env env, void* data) {
#if defined _WIN32
  Sleep(1000);
#else
  sleep(1);
#endif
  carrier* c = static_cast<carrier*>(data);

  if (c != &the_carrier) {
    napi_throw_type_error(env, "Wrong data parameter to Execute.");
    return;
  }

  c->_output = c->_input * 2;
}

void Complete(napi_env env, napi_status status, void* data) {
  AutoHandleScope scope(env);
  carrier* c = static_cast<carrier*>(data);

  if (c != &the_carrier) {
    napi_throw_type_error(env, "Wrong data parameter to Complete.");
    return;
  }

  if (status != napi_ok) {
    napi_throw_type_error(env, "Execute callback failed.");
    return;
  }

  napi_value argv[2];

  NAPI_CALL_RETURN_VOID(env, napi_get_null(env, &argv[0]));
  NAPI_CALL_RETURN_VOID(env, napi_create_number(env, c->_output, &argv[1]));
  napi_value callback;
  NAPI_CALL_RETURN_VOID(env,
    napi_get_reference_value(env, c->_callback, &callback));
  napi_value global;
  NAPI_CALL_RETURN_VOID(env, napi_get_global(env, &global));

  napi_value result;
  NAPI_CALL_RETURN_VOID(env,
    napi_call_function(env, global, callback, 2, argv, &result));

  NAPI_CALL_RETURN_VOID(env, napi_delete_reference(env, c->_callback));
  NAPI_CALL_RETURN_VOID(env, napi_delete_async_work(env, c->_request));
}

napi_value Test(napi_env env, napi_callback_info info) {
  size_t argc = 2;
  napi_value argv[2];
  napi_value _this;
  void* data;
  NAPI_CALL(env,
    napi_get_cb_info(env, info, &argc, argv, &_this, &data));
  NAPI_ASSERT(env, argc >= 2, "Not enough arguments, expected 2.");

  napi_valuetype t;
  NAPI_CALL(env, napi_typeof(env, argv[0], &t));
  NAPI_ASSERT(env, t == napi_number,
    "Wrong first argument, integer expected.");
  NAPI_CALL(env, napi_typeof(env, argv[1], &t));
  NAPI_ASSERT(env, t == napi_function,
    "Wrong second argument, function expected.");

  the_carrier._output = 0;

  NAPI_CALL(env,
    napi_get_value_int32(env, argv[0], &the_carrier._input));
  NAPI_CALL(env,
    napi_create_reference(env, argv[1], 1, &the_carrier._callback));
  NAPI_CALL(env, napi_create_async_work(
    env, Execute, Complete, &the_carrier, &the_carrier._request));
  NAPI_CALL(env,
    napi_queue_async_work(env, the_carrier._request));

  return nullptr;
}

void Init(napi_env env, napi_value exports, napi_value module, void* priv) {
  napi_value test;
  NAPI_CALL_RETURN_VOID(env,
    napi_create_function(env, "Test", Test, nullptr, &test));
  NAPI_CALL_RETURN_VOID(env,
    napi_set_named_property(env, module, "exports", test));
}

NAPI_MODULE(addon, Init)