@mikrojs/native 0.0.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (109) hide show
  1. package/CMakeLists.txt +198 -0
  2. package/LICENSE +21 -0
  3. package/README.md +49 -0
  4. package/cmake/mikrojs_bytecode.cmake +146 -0
  5. package/cmake.js +22 -0
  6. package/dist/index.d.ts +52 -0
  7. package/dist/index.d.ts.map +1 -0
  8. package/dist/index.js +132 -0
  9. package/dist/index.js.map +1 -0
  10. package/dist/types.d.ts +43 -0
  11. package/dist/types.d.ts.map +1 -0
  12. package/dist/types.js +2 -0
  13. package/dist/types.js.map +1 -0
  14. package/include/byteorder_apple.h +11 -0
  15. package/include/byteorder_windows.h +12 -0
  16. package/include/mikrojs/cbor_helpers.h +24 -0
  17. package/include/mikrojs/cutils_wrap.h +59 -0
  18. package/include/mikrojs/errors.h +144 -0
  19. package/include/mikrojs/mem.h +11 -0
  20. package/include/mikrojs/mik_color.h +32 -0
  21. package/include/mikrojs/mikrojs.h +331 -0
  22. package/include/mikrojs/platform.h +82 -0
  23. package/include/mikrojs/private.h +281 -0
  24. package/include/mikrojs/utils.h +125 -0
  25. package/package.json +100 -0
  26. package/prebuilds/darwin-arm64/mikrojs.napi.node +0 -0
  27. package/prebuilds/linux-arm64/mikrojs.napi.node +0 -0
  28. package/prebuilds/linux-x64/mikrojs.napi.node +0 -0
  29. package/runtime/ble/ble.ts +231 -0
  30. package/runtime/ble/types.ts +194 -0
  31. package/runtime/ble/uuid.ts +89 -0
  32. package/runtime/ble/validators.ts +61 -0
  33. package/runtime/cbor/cbor.ts +1 -0
  34. package/runtime/cbor/types.ts +8 -0
  35. package/runtime/console/types.ts +50 -0
  36. package/runtime/env/env.ts +17 -0
  37. package/runtime/env/types.ts +12 -0
  38. package/runtime/format/types.ts +4 -0
  39. package/runtime/fs/fs.ts +93 -0
  40. package/runtime/fs/types.ts +92 -0
  41. package/runtime/globals.d.ts +87 -0
  42. package/runtime/http/helpers.ts +222 -0
  43. package/runtime/http/native.ts +151 -0
  44. package/runtime/http/request.ts +25 -0
  45. package/runtime/i2c/i2c.ts +35 -0
  46. package/runtime/i2c/types.ts +55 -0
  47. package/runtime/inspect/types.ts +10 -0
  48. package/runtime/internal.d.ts +456 -0
  49. package/runtime/kv/nvs.ts +17 -0
  50. package/runtime/kv/rtc.ts +17 -0
  51. package/runtime/kv/shared.ts +107 -0
  52. package/runtime/kv/types.ts +150 -0
  53. package/runtime/neopixel/neopixel.ts +38 -0
  54. package/runtime/neopixel/types.ts +27 -0
  55. package/runtime/pin/pin.ts +51 -0
  56. package/runtime/pin/types.ts +49 -0
  57. package/runtime/pwm/pwm.ts +32 -0
  58. package/runtime/pwm/types.ts +29 -0
  59. package/runtime/reader/reader.ts +167 -0
  60. package/runtime/reader/types.ts +34 -0
  61. package/runtime/result/native-result.node-shim.ts +44 -0
  62. package/runtime/result/result.ts +26 -0
  63. package/runtime/result/types.ts +60 -0
  64. package/runtime/schema/schema.ts +321 -0
  65. package/runtime/schema/types.ts +152 -0
  66. package/runtime/sleep/sleep.ts +14 -0
  67. package/runtime/sleep/types.ts +44 -0
  68. package/runtime/sntp/sntp.ts +54 -0
  69. package/runtime/sntp/types.ts +38 -0
  70. package/runtime/spi/spi.ts +31 -0
  71. package/runtime/spi/types.ts +42 -0
  72. package/runtime/stdio/stdio.ts +44 -0
  73. package/runtime/stdio/types.ts +22 -0
  74. package/runtime/stream/stream.ts +150 -0
  75. package/runtime/stream/types.ts +47 -0
  76. package/runtime/sys/sys.ts +90 -0
  77. package/runtime/sys/types.ts +131 -0
  78. package/runtime/test/test.ts +595 -0
  79. package/runtime/test/types.ts +97 -0
  80. package/runtime/uart/types.ts +75 -0
  81. package/runtime/uart/uart.ts +51 -0
  82. package/runtime/wifi/types.ts +156 -0
  83. package/runtime/wifi/wifi.ts +208 -0
  84. package/scripts/bundle-runtime.js +149 -0
  85. package/scripts/compare-minifiers.js +189 -0
  86. package/scripts/compile-bytecode.sh +38 -0
  87. package/scripts/copy-prebuild.js +20 -0
  88. package/scripts/generate-symbol-map.js +146 -0
  89. package/src/builtins.cpp +82 -0
  90. package/src/cutils_compat.c +38 -0
  91. package/src/eval_bytecode.cpp +42 -0
  92. package/src/fs.cpp +878 -0
  93. package/src/mem.cpp +63 -0
  94. package/src/mik_abort.cpp +160 -0
  95. package/src/mik_app_config.cpp +358 -0
  96. package/src/mik_cbor.cpp +334 -0
  97. package/src/mik_color.cpp +46 -0
  98. package/src/mik_console.cpp +422 -0
  99. package/src/mik_inspect.cpp +850 -0
  100. package/src/mik_repl.cpp +1122 -0
  101. package/src/mik_result.cpp +344 -0
  102. package/src/mik_stdio.cpp +147 -0
  103. package/src/mik_sys.cpp +239 -0
  104. package/src/mik_text_encoding.cpp +443 -0
  105. package/src/mikrojs.cpp +942 -0
  106. package/src/modules.cpp +944 -0
  107. package/src/platform_posix.cpp +134 -0
  108. package/src/timers.cpp +208 -0
  109. package/src/utils.cpp +173 -0
@@ -0,0 +1,134 @@
1
+ #include "mikrojs/platform.h"
2
+
3
+ #include <stdarg.h>
4
+ #include <stdio.h>
5
+ #include <stdlib.h>
6
+ #include <time.h>
7
+ #include <unistd.h>
8
+
9
+ static int64_t posix_get_boot_us(void) {
10
+ struct timespec ts;
11
+ clock_gettime(CLOCK_MONOTONIC, &ts);
12
+ return (int64_t)ts.tv_sec * 1000000 + ts.tv_nsec / 1000;
13
+ }
14
+
15
+ static int64_t posix_get_rtc_us(void) {
16
+ /* No deep sleep on desktop — same as boot */
17
+ return posix_get_boot_us();
18
+ }
19
+
20
+ static uint32_t posix_random(void) {
21
+ return arc4random();
22
+ }
23
+
24
+ static void posix_restart(void) {
25
+ exit(1);
26
+ }
27
+
28
+ static void posix_yield(void) {
29
+ usleep(1000);
30
+ }
31
+
32
+ static size_t posix_get_free_system_mem(void) {
33
+ return 0; /* Not available on desktop */
34
+ }
35
+
36
+ static size_t posix_get_min_free_system_mem(void) {
37
+ return 0; /* Not available on desktop */
38
+ }
39
+
40
+ static size_t posix_get_total_system_mem(void) {
41
+ return 0; /* Not available on desktop */
42
+ }
43
+
44
+ static size_t posix_get_largest_free_system_mem(void) {
45
+ return 0; /* Not available on desktop */
46
+ }
47
+
48
+ static bool posix_get_fs_info(const char* label, size_t* total, size_t* used) {
49
+ (void)label;
50
+ (void)total;
51
+ (void)used;
52
+ return false;
53
+ }
54
+
55
+ static int posix_stdout_write(const void* buf, size_t len) {
56
+ return (int)write(fileno(stdout), buf, len);
57
+ }
58
+
59
+ static int posix_stderr_write(const void* buf, size_t len) {
60
+ return (int)write(fileno(stderr), buf, len);
61
+ }
62
+
63
+ static int posix_stdin_read(void* buf, size_t len) {
64
+ return (int)read(fileno(stdin), buf, len);
65
+ }
66
+
67
+ /* Derive a stable device ID from the hostname. FNV-1a hash truncated to
68
+ * 6 bytes, then Crockford's Base32 encoded (10 lowercase chars).
69
+ * Deterministic across restarts on the same machine. */
70
+ static const char* posix_get_device_id(void) {
71
+ static const char cb32[] = "0123456789abcdefghjkmnpqrstvwxyz";
72
+ static char id[11] = {0};
73
+ if (id[0] == '\0') {
74
+ char hostname[256];
75
+ if (gethostname(hostname, sizeof(hostname)) != 0) {
76
+ hostname[0] = '?';
77
+ hostname[1] = '\0';
78
+ }
79
+ /* FNV-1a 64-bit, then take the low 48 bits */
80
+ uint64_t h = 0xcbf29ce484222325ULL;
81
+ for (const char* p = hostname; *p; p++) {
82
+ h ^= (uint8_t)*p;
83
+ h *= 0x100000001b3ULL;
84
+ }
85
+ uint64_t v = h & 0xffffffffffffULL;
86
+ for (int i = 9; i >= 0; i--) {
87
+ id[i] = cb32[v & 0x1f];
88
+ v >>= 5;
89
+ }
90
+ }
91
+ return id;
92
+ }
93
+
94
+ static void posix_log(int level, const char* tag, const char* fmt, ...) {
95
+ if (level < MIK_LOG_ERROR || level > MIK_LOG_VERBOSE) return;
96
+ fprintf(stderr, "[%s] %s: ", mik_log_level_name(level), tag);
97
+ va_list args;
98
+ va_start(args, fmt);
99
+ vfprintf(stderr, fmt, args);
100
+ va_end(args);
101
+ fprintf(stderr, "\n");
102
+ }
103
+
104
+ static const MIKPlatform posix_platform = {
105
+ .get_boot_us = posix_get_boot_us,
106
+ .get_rtc_us = posix_get_rtc_us,
107
+ .random = posix_random,
108
+ .restart = posix_restart,
109
+ .yield = posix_yield,
110
+ .get_free_system_mem = posix_get_free_system_mem,
111
+ .get_min_free_system_mem = posix_get_min_free_system_mem,
112
+ .get_total_system_mem = posix_get_total_system_mem,
113
+ .get_largest_free_system_mem = posix_get_largest_free_system_mem,
114
+ .get_fs_info = posix_get_fs_info,
115
+ .log = posix_log,
116
+ .stdout_write = posix_stdout_write,
117
+ .stderr_write = posix_stderr_write,
118
+ .stdin_read = posix_stdin_read,
119
+ .get_device_id = posix_get_device_id,
120
+ };
121
+
122
+ static const MIKPlatform* current_platform = &posix_platform;
123
+
124
+ void MIK_SetPlatform(const MIKPlatform* platform) {
125
+ current_platform = platform;
126
+ }
127
+
128
+ const MIKPlatform* MIK_GetPlatform(void) {
129
+ return current_platform;
130
+ }
131
+
132
+ const MIKPlatform* MIK_DefaultPOSIXPlatform(void) {
133
+ return &posix_platform;
134
+ }
package/src/timers.cpp ADDED
@@ -0,0 +1,208 @@
1
+ #include <mikrojs/platform.h>
2
+ #include <mikrojs/private.h>
3
+ #include <mikrojs/utils.h>
4
+
5
+ #include <algorithm>
6
+
7
+ #include "quickjs.h"
8
+
9
+ #define MAX_SAFE_INTEGER (((uint32_t)1 << 31) - 1)
10
+
11
+ uint32_t MIK_Timer_Schedule(MIKTimers* timers, JSContext* ctx, const JSValue func, const int argc,
12
+ const JSValue* argv, const int64_t timeout, const bool is_interval,
13
+ const int64_t now = MIK_GetPlatform()->get_boot_us()) {
14
+ auto timer_id = timers->next_timer_id++;
15
+
16
+ if (timer_id > MAX_SAFE_INTEGER)
17
+ timer_id = 1;
18
+
19
+ const int64_t next_deadline = now + timeout;
20
+
21
+ auto entry = MIKTimerEntry{
22
+ timer_id, is_interval, timeout, next_deadline, JS_DupValue(ctx, func), argc, {},
23
+ };
24
+
25
+ for (int i = 0; i < argc; i++) {
26
+ entry.argv[i] = JS_DupValue(ctx, argv[i]);
27
+ }
28
+
29
+ timers->entries.push_back(entry);
30
+ return entry.id;
31
+ }
32
+
33
+ bool MIK_Timer_UnSchedule(MIKTimers* timers, JSContext* ctx, uint32_t id) {
34
+ auto it = std::find_if(timers->entries.begin(), timers->entries.end(),
35
+ [id](const MIKTimerEntry& e) { return e.id == id; });
36
+ if (it != timers->entries.end()) {
37
+ JS_FreeValue(ctx, it->func);
38
+ for (int i = 0; i < it->argc; i++) JS_FreeValue(ctx, it->argv[i]);
39
+ timers->entries.erase(it); // remove the element
40
+ return true;
41
+ }
42
+
43
+ return false;
44
+ }
45
+
46
+ size_t MIK_Timer_CountDue(MIKTimers* timers, int64_t now) {
47
+ size_t count = 0;
48
+ for (const auto& entry : timers->entries) {
49
+ if (entry.next_deadline <= now) {
50
+ count++;
51
+ }
52
+ }
53
+ return count;
54
+ }
55
+
56
+ void MIK_Timer_SetNextDeadline(MIKTimers* timers, uint32_t id, int64_t next_deadline) {
57
+ for (auto& timer : timers->entries) {
58
+ if (timer.id == id) {
59
+ timer.next_deadline = next_deadline;
60
+ return;
61
+ }
62
+ }
63
+ }
64
+
65
+ void MIK_Timer_ClearAll(MIKTimers* timers, JSContext* ctx) {
66
+ while (!timers->entries.empty()) {
67
+ auto& entry = timers->entries.back();
68
+ JS_FreeValue(ctx, entry.func);
69
+ for (int i = 0; i < entry.argc; i++) JS_FreeValue(ctx, entry.argv[i]);
70
+ timers->entries.pop_back();
71
+ }
72
+ }
73
+
74
+ MIKTimerRegistry* MIK_NewTimerRegistry() {
75
+ auto* timers = new MIKTimerRegistry();
76
+ timers->entries.reserve(MIK_MAX_DUE_TIMERS);
77
+ return timers;
78
+ }
79
+
80
+ static JSValue mik__timer_set(JSContext* ctx, JSValue this_val, int argc, JSValue* argv,
81
+ int magic) {
82
+ MIKRuntime* mik_runtime = static_cast<MIKRuntime*>(JS_GetContextOpaque(ctx));
83
+ CHECK_NOT_NULL(mik_runtime);
84
+
85
+ int64_t delay;
86
+ JSValue func;
87
+
88
+ func = argv[0];
89
+ if (!JS_IsFunction(ctx, func)) {
90
+ return JS_ThrowTypeError(ctx, "not a function");
91
+ }
92
+
93
+ if (argc <= 1) {
94
+ delay = 0;
95
+ } else if (JS_ToInt64(ctx, &delay, argv[1])) {
96
+ return JS_EXCEPTION;
97
+ }
98
+
99
+ int nargs = argc - 2;
100
+ if (nargs < 0) {
101
+ nargs = 0;
102
+ }
103
+ if (nargs > MIK_TIMER_MAX_ARGS) {
104
+ return JS_ThrowRangeError(ctx, "too many arguments for setTimeout/setInterval (max %d)",
105
+ MIK_TIMER_MAX_ARGS);
106
+ }
107
+
108
+ uint32_t id = MIK_Timer_Schedule(mik_runtime->timers, mik_runtime->ctx, func, nargs,
109
+ argv + 2, delay * 1000, magic);
110
+
111
+ return JS_NewInt32(ctx, id);
112
+ }
113
+
114
+ static JSValue mik__timer_clear(JSContext* ctx, JSValue this_val, int argc, JSValue* argv) {
115
+ MIKRuntime* mik_runtime = static_cast<MIKRuntime*>(JS_GetContextOpaque(ctx));
116
+ CHECK_NOT_NULL(mik_runtime);
117
+ int64_t timer_id;
118
+
119
+ if (JS_ToInt64(ctx, &timer_id, argv[0])) {
120
+ return JS_EXCEPTION;
121
+ }
122
+
123
+ MIK_Timer_UnSchedule(mik_runtime->timers, mik_runtime->ctx, timer_id);
124
+ return JS_UNDEFINED;
125
+ }
126
+
127
+ static const JSCFunctionListEntry mik_timer_funcs[] = {
128
+ JS_CFUNC_MAGIC_DEF("setTimeout", 2, mik__timer_set, 0),
129
+ MIK_CFUNC_DEF("clearTimeout", 1, mik__timer_clear),
130
+ JS_CFUNC_MAGIC_DEF("setInterval", 2, mik__timer_set, 1),
131
+ MIK_CFUNC_DEF("clearInterval", 1, mik__timer_clear)};
132
+
133
+ void mik__timers_init(JSContext* ctx, JSValue ns) {
134
+ JS_SetPropertyFunctionList(ctx, ns, mik_timer_funcs, countof(mik_timer_funcs));
135
+ }
136
+
137
+ void mik__timers_destroy(JSContext* ctx) {
138
+ const MIKRuntime* mik_rt = static_cast<MIKRuntime*>(JS_GetContextOpaque(ctx));
139
+ MIK_Timer_ClearAll(mik_rt->timers, mik_rt->ctx);
140
+ }
141
+
142
+ void mik__timers_consume(JSContext* ctx) {
143
+ MIKRuntime* mik_rt = static_cast<MIKRuntime*>(JS_GetContextOpaque(ctx));
144
+ auto* timers = mik_rt->timers;
145
+ const MIKPlatform* platform = MIK_GetPlatform();
146
+ int64_t now = platform->get_boot_us();
147
+
148
+ // Collect IDs of due timers into a small stack buffer to avoid heap allocation.
149
+ // This lets us safely iterate even if callbacks add/remove timers.
150
+ uint32_t due_ids[MIK_MAX_DUE_TIMERS];
151
+ size_t due_count = 0;
152
+
153
+ for (auto& entry : timers->entries) {
154
+ if (entry.next_deadline <= now) {
155
+ if (due_count < MIK_MAX_DUE_TIMERS) {
156
+ due_ids[due_count++] = entry.id;
157
+ }
158
+ // Update interval deadlines before executing callbacks
159
+ if (entry.is_interval) {
160
+ entry.next_deadline = entry.timeout + platform->get_boot_us();
161
+ }
162
+ }
163
+ }
164
+
165
+ if (due_count == 0)
166
+ return;
167
+
168
+ for (size_t i = 0; i < due_count; i++) {
169
+ // Re-find the entry — a previous callback may have cleared it
170
+ auto it = std::find_if(timers->entries.begin(), timers->entries.end(),
171
+ [&](const MIKTimerEntry& e) { return e.id == due_ids[i]; });
172
+ if (it == timers->entries.end())
173
+ continue;
174
+
175
+ // Dup the function and args before calling — the callback may call
176
+ // clearInterval which frees the entry (and its JSValues) mid-call.
177
+ JSValue func = JS_DupValue(mik_rt->ctx, it->func);
178
+ int nargs = it->argc;
179
+ JSValue args[MIK_TIMER_MAX_ARGS];
180
+ for (int j = 0; j < nargs; j++) {
181
+ args[j] = JS_DupValue(mik_rt->ctx, it->argv[j]);
182
+ }
183
+
184
+ JSValue ret = JS_Call(mik_rt->ctx, func, JS_UNDEFINED, nargs, args);
185
+ if (JS_IsException(ret)) {
186
+ if (mik_rt->error_handler_fn && JS_HasException(mik_rt->ctx)) {
187
+ JSValue exc = JS_GetException(mik_rt->ctx);
188
+ mik_rt->error_handler_fn(mik_rt->ctx, exc, mik_rt->error_handler_opaque);
189
+ JS_Throw(mik_rt->ctx, exc);
190
+ }
191
+ mik_dump_error(mik_rt->ctx);
192
+ }
193
+ JS_FreeValue(mik_rt->ctx, ret);
194
+ JS_FreeValue(mik_rt->ctx, func);
195
+ for (int j = 0; j < nargs; j++) {
196
+ JS_FreeValue(mik_rt->ctx, args[j]);
197
+ }
198
+ }
199
+
200
+ // Remove one-shot timers that are still alive (not already cleared by a callback)
201
+ for (size_t i = 0; i < due_count; i++) {
202
+ auto it = std::find_if(timers->entries.begin(), timers->entries.end(),
203
+ [&](const MIKTimerEntry& e) { return e.id == due_ids[i]; });
204
+ if (it != timers->entries.end() && !it->is_interval) {
205
+ MIK_Timer_UnSchedule(timers, mik_rt->ctx, due_ids[i]);
206
+ }
207
+ }
208
+ }
package/src/utils.cpp ADDED
@@ -0,0 +1,173 @@
1
+ #include "mikrojs/utils.h"
2
+
3
+ #include <errno.h>
4
+ #include <stdarg.h>
5
+ #include <stdio.h>
6
+ #include <stdlib.h>
7
+ #include <string.h>
8
+
9
+ #include "mikrojs/mikrojs.h"
10
+ #include "mikrojs/private.h"
11
+
12
+ JSValue mik_new_error(JSContext* ctx, int err) {
13
+ JSValue obj = JS_NewError(ctx);
14
+ JS_DefinePropertyValueStr(ctx, obj, "message", JS_NewString(ctx, strerror(err)),
15
+ JS_PROP_C_W_E);
16
+ JS_DefinePropertyValueStr(ctx, obj, "errno", JS_NewInt32(ctx, err), JS_PROP_C_W_E);
17
+ return obj;
18
+ }
19
+
20
+ JSValue mik_throw_errno(JSContext* ctx, int err) {
21
+ return JS_Throw(ctx, mik_new_error(ctx, err));
22
+ }
23
+
24
+ void mik_assert(const struct AssertionInfo info) {
25
+ fprintf(stderr, "%s:%s%s Assertion `%s' failed.\n", info.file_line, info.function,
26
+ *info.function ? ":" : "", info.message);
27
+ fflush(stderr);
28
+ abort();
29
+ }
30
+
31
+ static void mik_dump_obj(JSContext* ctx, FILE* f, JSValue val) {
32
+ const char* str = JS_ToCString(ctx, val);
33
+ if (str) {
34
+ fprintf(f, "%s\n", str);
35
+ JS_FreeCString(ctx, str);
36
+ } else {
37
+ fprintf(f, "[exception]\n");
38
+ }
39
+ }
40
+
41
+ void mik_dump_error(JSContext* ctx) {
42
+ JSValue exception_val = JS_GetException(ctx);
43
+ mik_dump_error1(ctx, exception_val);
44
+ JS_FreeValue(ctx, exception_val);
45
+ }
46
+
47
+ void mik_dump_error1(JSContext* ctx, JSValue exception_val) {
48
+ /* In REPL mode, use the colorized report path */
49
+ if (MIK_IsReplActive()) {
50
+ mik__report_uncaught(ctx, exception_val);
51
+ return;
52
+ }
53
+
54
+ int is_error = JS_IsError(exception_val);
55
+ mik_dump_obj(ctx, stderr, exception_val);
56
+ if (is_error) {
57
+ JSValue val = JS_GetPropertyStr(ctx, exception_val, "stack");
58
+ if (!JS_IsUndefined(val)) {
59
+ mik_dump_obj(ctx, stderr, val);
60
+ }
61
+ JS_FreeValue(ctx, val);
62
+ }
63
+ fflush(stderr);
64
+ }
65
+
66
+ void mik_call_handler(JSContext* ctx, JSValue func, int argc, JSValue* argv) {
67
+ JSValue ret, func1;
68
+ /* 'func' might be destroyed when calling itself (if it frees the
69
+ handler), so must take extra care */
70
+ func1 = JS_DupValue(ctx, func);
71
+ ret = JS_Call(ctx, func1, JS_UNDEFINED, argc, argv);
72
+ JS_FreeValue(ctx, func1);
73
+ if (JS_IsException(ret)) {
74
+ mik_dump_error(ctx);
75
+ }
76
+ JS_FreeValue(ctx, ret);
77
+ }
78
+
79
+ JSValue MIK_InitPromise(JSContext* ctx, MIKPromise* p) {
80
+ JSValue rfuncs[2];
81
+ p->p = JS_NewPromiseCapability(ctx, rfuncs);
82
+ if (JS_IsException(p->p)) {
83
+ return JS_EXCEPTION;
84
+ }
85
+ p->rfuncs[0] = rfuncs[0];
86
+ p->rfuncs[1] = rfuncs[1];
87
+ return JS_DupValue(ctx, p->p);
88
+ }
89
+
90
+ bool MIK_IsPromisePending(JSContext* ctx, MIKPromise* p) { return !JS_IsUndefined(p->p); }
91
+
92
+ void MIK_FreePromise(JSContext* ctx, MIKPromise* p) {
93
+ JS_FreeValue(ctx, p->rfuncs[0]);
94
+ JS_FreeValue(ctx, p->rfuncs[1]);
95
+ JS_FreeValue(ctx, p->p);
96
+ }
97
+
98
+ void MIK_FreePromiseRT(JSRuntime* rt, MIKPromise* p) {
99
+ JS_FreeValueRT(rt, p->rfuncs[0]);
100
+ JS_FreeValueRT(rt, p->rfuncs[1]);
101
+ JS_FreeValueRT(rt, p->p);
102
+ }
103
+
104
+ void MIK_ClearPromise(JSContext* ctx, MIKPromise* p) {
105
+ p->p = JS_UNDEFINED;
106
+ p->rfuncs[0] = JS_UNDEFINED;
107
+ p->rfuncs[1] = JS_UNDEFINED;
108
+ }
109
+
110
+ void MIK_MarkPromise(JSRuntime* rt, MIKPromise* p, JS_MarkFunc* mark_func) {
111
+ JS_MarkValue(rt, p->p, mark_func);
112
+ JS_MarkValue(rt, p->rfuncs[0], mark_func);
113
+ JS_MarkValue(rt, p->rfuncs[1], mark_func);
114
+ }
115
+
116
+ void MIK_SettlePromise(JSContext* ctx, MIKPromise* p, bool is_reject, int argc, JSValue* argv) {
117
+ JSValue ret = JS_Call(ctx, p->rfuncs[is_reject], JS_UNDEFINED, argc, argv);
118
+ for (int i = 0; i < argc; i++) {
119
+ JS_FreeValue(ctx, argv[i]);
120
+ }
121
+ if (JS_IsException(ret)) {
122
+ mik_dump_error(ctx);
123
+ }
124
+ JS_FreeValue(ctx, ret);
125
+ MIK_FreePromise(ctx, p);
126
+ }
127
+
128
+ void MIK_ResolvePromise(JSContext* ctx, MIKPromise* p, int argc, JSValue* argv) {
129
+ MIK_SettlePromise(ctx, p, false, argc, argv);
130
+ }
131
+
132
+ void MIK_RejectPromise(JSContext* ctx, MIKPromise* p, int argc, JSValue* argv) {
133
+ MIK_SettlePromise(ctx, p, true, argc, argv);
134
+ }
135
+
136
+ static inline JSValue mik__settled_promise(JSContext* ctx, bool is_reject, int argc,
137
+ JSValue* argv) {
138
+ JSValue promise, resolving_funcs[2], ret;
139
+
140
+ promise = JS_NewPromiseCapability(ctx, resolving_funcs);
141
+ if (JS_IsException(promise)) {
142
+ return JS_EXCEPTION;
143
+ }
144
+
145
+ ret = JS_Call(ctx, resolving_funcs[is_reject], JS_UNDEFINED, argc, argv);
146
+
147
+ for (int i = 0; i < argc; i++) {
148
+ JS_FreeValue(ctx, argv[i]);
149
+ }
150
+ JS_FreeValue(ctx, ret);
151
+ JS_FreeValue(ctx, resolving_funcs[0]);
152
+ JS_FreeValue(ctx, resolving_funcs[1]);
153
+
154
+ return promise;
155
+ }
156
+
157
+ JSValue MIK_NewResolvedPromise(JSContext* ctx, int argc, JSValue* argv) {
158
+ return mik__settled_promise(ctx, false, argc, argv);
159
+ }
160
+
161
+ JSValue MIK_NewRejectedPromise(JSContext* ctx, int argc, JSValue* argv) {
162
+ return mik__settled_promise(ctx, true, argc, argv);
163
+ }
164
+
165
+ static void mik__buf_free(JSRuntime* rt, void* opaque, void* ptr) { js_free_rt(rt, ptr); }
166
+
167
+ JSValue MIK_NewUint8Array(JSContext* ctx, uint8_t* data, size_t size) {
168
+ return JS_NewUint8Array(ctx, data, size, mik__buf_free, NULL, false);
169
+ }
170
+
171
+ void mik_dbuf_init(JSContext* ctx, DynBuf* s) {
172
+ dbuf_init2(s, JS_GetRuntime(ctx), (DynBufReallocFunc*)js_realloc_rt);
173
+ }