@mikrojs/firmware 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 (88) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +30 -0
  3. package/bin/idf.py +7 -0
  4. package/chips.json +3 -0
  5. package/cmake.js +9 -0
  6. package/components/mikrojs/CMakeLists.txt +187 -0
  7. package/components/mikrojs/Kconfig +55 -0
  8. package/components/mikrojs/idf_component.yml +6 -0
  9. package/components/mikrojs/include/mem.h +3 -0
  10. package/components/mikrojs/include/mik_color.h +3 -0
  11. package/components/mikrojs/include/mik_http_internal.h +77 -0
  12. package/components/mikrojs/include/mikrojs.h +5 -0
  13. package/components/mikrojs/include/mikrojs_esp32.h +65 -0
  14. package/components/mikrojs/include/private.h +10 -0
  15. package/components/mikrojs/include/utils.h +3 -0
  16. package/components/mikrojs/mik_ble.cpp +1588 -0
  17. package/components/mikrojs/mik_ble_c_shim.c +61 -0
  18. package/components/mikrojs/mik_ble_c_shim.h +37 -0
  19. package/components/mikrojs/mik_config.cpp +167 -0
  20. package/components/mikrojs/mik_deploy.cpp +584 -0
  21. package/components/mikrojs/mik_http.cpp +916 -0
  22. package/components/mikrojs/mik_i2c.cpp +364 -0
  23. package/components/mikrojs/mik_main.cpp +542 -0
  24. package/components/mikrojs/mik_neopixel.cpp +437 -0
  25. package/components/mikrojs/mik_nvs_kv.cpp +219 -0
  26. package/components/mikrojs/mik_pin.cpp +195 -0
  27. package/components/mikrojs/mik_pwm.cpp +525 -0
  28. package/components/mikrojs/mik_recovery.cpp +86 -0
  29. package/components/mikrojs/mik_rtc.cpp +305 -0
  30. package/components/mikrojs/mik_serial_io.cpp +362 -0
  31. package/components/mikrojs/mik_sleep.cpp +226 -0
  32. package/components/mikrojs/mik_sntp.cpp +275 -0
  33. package/components/mikrojs/mik_spi.cpp +330 -0
  34. package/components/mikrojs/mik_uart.cpp +497 -0
  35. package/components/mikrojs/mik_wifi.cpp +1434 -0
  36. package/components/mikrojs/platform_esp32.cpp +192 -0
  37. package/components/mikrojs/test/CMakeLists.txt +32 -0
  38. package/components/mikrojs/test/abort_test.cpp +254 -0
  39. package/components/mikrojs/test/ble_test.cpp +714 -0
  40. package/components/mikrojs/test/fs_js_test.cpp +458 -0
  41. package/components/mikrojs/test/fs_pub_test.cpp +312 -0
  42. package/components/mikrojs/test/http_test.cpp +475 -0
  43. package/components/mikrojs/test/i2c_test.cpp +138 -0
  44. package/components/mikrojs/test/modules_extended_test.cpp +137 -0
  45. package/components/mikrojs/test/modules_test.cpp +131 -0
  46. package/components/mikrojs/test/pins_test.cpp +47 -0
  47. package/components/mikrojs/test/pwm_test.cpp +166 -0
  48. package/components/mikrojs/test/repl_protocol_test.cpp +405 -0
  49. package/components/mikrojs/test/rtc_test.cpp +331 -0
  50. package/components/mikrojs/test/runtime_test.cpp +89 -0
  51. package/components/mikrojs/test/sleep_test.cpp +222 -0
  52. package/components/mikrojs/test/sntp_test.cpp +249 -0
  53. package/components/mikrojs/test/stdio_test.cpp +449 -0
  54. package/components/mikrojs/test/sys_test.cpp +165 -0
  55. package/components/mikrojs/test/text_encoding_test.cpp +224 -0
  56. package/components/mikrojs/test/timers_js_test.cpp +244 -0
  57. package/components/mikrojs/test/timers_test.cpp +79 -0
  58. package/components/mikrojs/test/wifi_test.cpp +599 -0
  59. package/default-app/main/CMakeLists.txt +3 -0
  60. package/default-app/main/main.cpp +5 -0
  61. package/discover.js +77 -0
  62. package/index.d.ts +7 -0
  63. package/index.js +20 -0
  64. package/package.json +61 -0
  65. package/partitions.csv +5 -0
  66. package/prebuilds/esp32/bootloader/bootloader.bin +0 -0
  67. package/prebuilds/esp32/flasher_args.json +24 -0
  68. package/prebuilds/esp32/mikrojs.bin +0 -0
  69. package/prebuilds/esp32/partition_table/partition-table.bin +0 -0
  70. package/prebuilds/esp32c3/bootloader/bootloader.bin +0 -0
  71. package/prebuilds/esp32c3/flasher_args.json +24 -0
  72. package/prebuilds/esp32c3/mikrojs.bin +0 -0
  73. package/prebuilds/esp32c3/partition_table/partition-table.bin +0 -0
  74. package/prebuilds/esp32c6/bootloader/bootloader.bin +0 -0
  75. package/prebuilds/esp32c6/flasher_args.json +24 -0
  76. package/prebuilds/esp32c6/mikrojs.bin +0 -0
  77. package/prebuilds/esp32c6/partition_table/partition-table.bin +0 -0
  78. package/prebuilds/esp32s3/bootloader/bootloader.bin +0 -0
  79. package/prebuilds/esp32s3/flasher_args.json +24 -0
  80. package/prebuilds/esp32s3/mikrojs.bin +0 -0
  81. package/prebuilds/esp32s3/partition_table/partition-table.bin +0 -0
  82. package/project.cmake +101 -0
  83. package/resolve.js +54 -0
  84. package/sdkconfig.defaults +127 -0
  85. package/sdkconfig.defaults.esp32 +8 -0
  86. package/sdkconfig.defaults.esp32c3 +15 -0
  87. package/sdkconfig.defaults.esp32c6 +26 -0
  88. package/sdkconfig.defaults.esp32s3 +22 -0
@@ -0,0 +1,192 @@
1
+ #include "mikrojs/platform.h"
2
+ #include "mikrojs_esp32.h"
3
+
4
+ #include <esp_log.h>
5
+ #include <esp_heap_caps.h>
6
+ #include <esp_mac.h>
7
+ #include <esp_random.h>
8
+ #include <esp_system.h>
9
+ #include <esp_rtc_time.h>
10
+ #include <esp_timer.h>
11
+ #include <freertos/FreeRTOS.h>
12
+ #include <freertos/task.h>
13
+ #include <soc/soc_caps.h>
14
+
15
+ #include <stdarg.h>
16
+ #include <stdio.h>
17
+ #include <unistd.h>
18
+
19
+ /* Check for LittleFS availability (optional — only used for .df directive) */
20
+ #ifdef CONFIG_LITTLEFS_MAX_PARTITIONS
21
+ #include <esp_littlefs.h>
22
+ #define HAS_LITTLEFS 1
23
+ #else
24
+ #define HAS_LITTLEFS 0
25
+ #endif
26
+
27
+ static int64_t esp32_get_boot_us(void) {
28
+ return esp_timer_get_time();
29
+ }
30
+
31
+ static int64_t esp32_get_rtc_us(void) {
32
+ return (int64_t)esp_rtc_get_time_us();
33
+ }
34
+
35
+ static uint32_t esp32_random(void) {
36
+ return esp_random();
37
+ }
38
+
39
+ static void esp32_restart(void) {
40
+ esp_restart();
41
+ }
42
+
43
+ static void esp32_yield(void) {
44
+ vTaskDelay(1);
45
+ }
46
+
47
+ static size_t esp32_get_free_system_mem(void) {
48
+ return esp_get_free_heap_size();
49
+ }
50
+
51
+ static size_t esp32_get_min_free_system_mem(void) {
52
+ return esp_get_minimum_free_heap_size();
53
+ }
54
+
55
+ static size_t esp32_get_total_system_mem(void) {
56
+ multi_heap_info_t info;
57
+ heap_caps_get_info(&info, MALLOC_CAP_8BIT);
58
+ return info.total_free_bytes + info.total_allocated_bytes;
59
+ }
60
+
61
+ static size_t esp32_get_largest_free_system_mem(void) {
62
+ return heap_caps_get_largest_free_block(MALLOC_CAP_8BIT);
63
+ }
64
+
65
+ static bool esp32_get_fs_info(const char* label, size_t* total, size_t* used) {
66
+ #if HAS_LITTLEFS
67
+ return esp_littlefs_info(label, total, used) == ESP_OK;
68
+ #else
69
+ (void)label;
70
+ (void)total;
71
+ (void)used;
72
+ return false;
73
+ #endif
74
+ }
75
+
76
+ /* JS stdio (console.log / console.error / REPL input) goes through
77
+ * the same auto-detecting USB-Serial/JTAG + UART0 console that
78
+ * mik_serial_io.cpp manages. Bypasses newlib stdio / VFS so early
79
+ * boot doesn't pull in the USB-JTAG VFS on battery-boot-fragile
80
+ * boards. mik__console_write already handles the "no host attached"
81
+ * case for USB-JTAG by dropping the payload silently. */
82
+
83
+ static int esp32_stdout_write(const void* buf, size_t len) {
84
+ return mik__console_write(buf, len);
85
+ }
86
+
87
+ static int esp32_stderr_write(const void* buf, size_t len) {
88
+ return mik__console_write(buf, len);
89
+ }
90
+
91
+ static int esp32_stdin_read(void* buf, size_t len) {
92
+ return mik__console_read(buf, len);
93
+ }
94
+
95
+ /* Base MAC (6 bytes) encoded as Crockford's Base32 (10 lowercase chars).
96
+ * Lossless: decode the 10 chars to recover the original 6 MAC bytes.
97
+ * Crockford's Base32 excludes I, L, O, U to avoid visual ambiguity. */
98
+ static const char* esp32_get_device_id(void) {
99
+ static const char cb32[] = "0123456789abcdefghjkmnpqrstvwxyz";
100
+ static char id[11] = {0}; /* 6 bytes (48 bits) -> 10 x 5-bit chars + NUL */
101
+ if (id[0] == '\0') {
102
+ uint8_t m[6];
103
+ esp_efuse_mac_get_default(m);
104
+ /* Pack 6 bytes into a 48-bit value, then extract 5 bits at a time
105
+ * from the most significant end. */
106
+ uint64_t v = ((uint64_t)m[0] << 40) | ((uint64_t)m[1] << 32) |
107
+ ((uint64_t)m[2] << 24) | ((uint64_t)m[3] << 16) |
108
+ ((uint64_t)m[4] << 8) | (uint64_t)m[5];
109
+ for (int i = 9; i >= 0; i--) {
110
+ id[i] = cb32[v & 0x1f];
111
+ v >>= 5;
112
+ }
113
+ }
114
+ return id;
115
+ }
116
+
117
+ static void esp32_log(int level, const char* tag, const char* fmt, ...) {
118
+ /* Map MIK_LOG_xxx to ESP_LOG_xxx for the runtime filter check. */
119
+ esp_log_level_t esp_level;
120
+ switch (level) {
121
+ case MIK_LOG_ERROR:
122
+ esp_level = ESP_LOG_ERROR;
123
+ break;
124
+ case MIK_LOG_WARN:
125
+ esp_level = ESP_LOG_WARN;
126
+ break;
127
+ case MIK_LOG_INFO:
128
+ esp_level = ESP_LOG_INFO;
129
+ break;
130
+ case MIK_LOG_DEBUG:
131
+ esp_level = ESP_LOG_DEBUG;
132
+ break;
133
+ case MIK_LOG_VERBOSE:
134
+ esp_level = ESP_LOG_VERBOSE;
135
+ break;
136
+ default:
137
+ return;
138
+ }
139
+
140
+ /* Apply the same runtime tag filter esp_log_writev would. We can't
141
+ * delegate to esp_log_writev directly because it passes fmt straight
142
+ * to vprintf without a prefix or newline, and we want a cross-platform
143
+ * `[LEVEL] tag: ...` shape that's visually distinct from ESP-IDF's
144
+ * own `D (12345) tag: ...` subsystem logs. */
145
+ esp_log_level_t tag_level = esp_log_level_get(tag);
146
+ if (tag_level == ESP_LOG_NONE || esp_level > tag_level) return;
147
+
148
+ printf("[%s] %s: ", mik_log_level_name(level), tag);
149
+ va_list args;
150
+ va_start(args, fmt);
151
+ vprintf(fmt, args);
152
+ va_end(args);
153
+ putchar('\n');
154
+ }
155
+
156
+ static const MIKPlatform esp32_platform = {
157
+ .get_boot_us = esp32_get_boot_us,
158
+ .get_rtc_us = esp32_get_rtc_us,
159
+ .random = esp32_random,
160
+ .restart = esp32_restart,
161
+ .yield = esp32_yield,
162
+ .get_free_system_mem = esp32_get_free_system_mem,
163
+ .get_min_free_system_mem = esp32_get_min_free_system_mem,
164
+ .get_total_system_mem = esp32_get_total_system_mem,
165
+ .get_largest_free_system_mem = esp32_get_largest_free_system_mem,
166
+ .get_fs_info = esp32_get_fs_info,
167
+ .log = esp32_log,
168
+ .stdout_write = esp32_stdout_write,
169
+ .stderr_write = esp32_stderr_write,
170
+ .stdin_read = esp32_stdin_read,
171
+ .get_device_id = esp32_get_device_id,
172
+ };
173
+
174
+ /*
175
+ * Global platform pointer + API (replaces platform_posix.cpp for ESP32 builds).
176
+ * The ESP32 platform is the default, so MIK_SetPlatform() doesn't need to be
177
+ * called explicitly unless overriding.
178
+ */
179
+ static const MIKPlatform* current_platform = &esp32_platform;
180
+
181
+ void MIK_SetPlatform(const MIKPlatform* platform) {
182
+ current_platform = platform;
183
+ }
184
+
185
+ const MIKPlatform* MIK_GetPlatform(void) {
186
+ return current_platform;
187
+ }
188
+
189
+ const MIKPlatform* MIK_DefaultPOSIXPlatform(void) {
190
+ /* Not available on ESP32 — return the ESP32 platform instead */
191
+ return &esp32_platform;
192
+ }
@@ -0,0 +1,32 @@
1
+ # ble_test.cpp references mik__ble_consume which is only defined when
2
+ # NimBLE (CONFIG_BT_ENABLED) is available. Exclude it for BT-less builds.
3
+ set(_MIK_TEST_SRCS
4
+ abort_test.cpp
5
+ fs_js_test.cpp
6
+ fs_pub_test.cpp
7
+ http_test.cpp
8
+ i2c_test.cpp
9
+ modules_extended_test.cpp
10
+ modules_test.cpp
11
+ pins_test.cpp
12
+ pwm_test.cpp
13
+ repl_protocol_test.cpp
14
+ rtc_test.cpp
15
+ runtime_test.cpp
16
+ sleep_test.cpp
17
+ sntp_test.cpp
18
+ stdio_test.cpp
19
+ sys_test.cpp
20
+ text_encoding_test.cpp
21
+ timers_js_test.cpp
22
+ timers_test.cpp
23
+ wifi_test.cpp
24
+ )
25
+ if(CONFIG_BT_ENABLED)
26
+ list(APPEND _MIK_TEST_SRCS ble_test.cpp)
27
+ endif()
28
+
29
+ idf_component_register(SRCS ${_MIK_TEST_SRCS}
30
+ INCLUDE_DIRS "."
31
+ REQUIRES unity mikrojs spi_flash
32
+ )
@@ -0,0 +1,254 @@
1
+ #include "mikrojs.h"
2
+ #include "quickjs.h"
3
+ #include "unity.h"
4
+
5
+ static MIKRuntime* rt;
6
+ static JSContext* ctx;
7
+
8
+ static void setup() {
9
+ rt = MIK_NewRuntime();
10
+ ctx = MIK_GetJSContext(rt);
11
+ }
12
+
13
+ static void teardown() { MIK_FreeRuntime(rt); }
14
+
15
+ static JSValue eval(const char* code) {
16
+ return JS_Eval(ctx, code, strlen(code), "test.js", JS_EVAL_TYPE_GLOBAL);
17
+ }
18
+
19
+ static const char* eval_str(const char* code) {
20
+ JSValue val = eval(code);
21
+ const char* s = JS_ToCString(ctx, val);
22
+ JS_FreeValue(ctx, val);
23
+ return s;
24
+ }
25
+
26
+ /* ── AbortController/AbortSignal API tests ───────────────────────── */
27
+
28
+ TEST_CASE("AbortController is defined as a function", "[abort]") {
29
+ setup();
30
+ const char* s = eval_str("typeof AbortController");
31
+ TEST_ASSERT_EQUAL_STRING("function", s);
32
+ JS_FreeCString(ctx, s);
33
+ teardown();
34
+ }
35
+
36
+ TEST_CASE("AbortSignal is defined as a function", "[abort]") {
37
+ setup();
38
+ const char* s = eval_str("typeof AbortSignal");
39
+ TEST_ASSERT_EQUAL_STRING("function", s);
40
+ JS_FreeCString(ctx, s);
41
+ teardown();
42
+ }
43
+
44
+ TEST_CASE("AbortError is defined as a function", "[abort]") {
45
+ setup();
46
+ const char* s = eval_str("typeof AbortError");
47
+ TEST_ASSERT_EQUAL_STRING("function", s);
48
+ JS_FreeCString(ctx, s);
49
+ teardown();
50
+ }
51
+
52
+ TEST_CASE("TimeoutError is defined as a function", "[abort]") {
53
+ setup();
54
+ const char* s = eval_str("typeof TimeoutError");
55
+ TEST_ASSERT_EQUAL_STRING("function", s);
56
+ JS_FreeCString(ctx, s);
57
+ teardown();
58
+ }
59
+
60
+ TEST_CASE("AbortController.signal starts not aborted", "[abort]") {
61
+ setup();
62
+ const char* s = eval_str("new AbortController().signal.aborted ? 'yes' : 'no'");
63
+ TEST_ASSERT_EQUAL_STRING("no", s);
64
+ JS_FreeCString(ctx, s);
65
+ teardown();
66
+ }
67
+
68
+ TEST_CASE("AbortController.abort() sets aborted to true", "[abort]") {
69
+ setup();
70
+ const char* s = eval_str(R"(
71
+ const ac = new AbortController();
72
+ ac.abort();
73
+ ac.signal.aborted ? 'yes' : 'no';
74
+ )");
75
+ TEST_ASSERT_EQUAL_STRING("yes", s);
76
+ JS_FreeCString(ctx, s);
77
+ teardown();
78
+ }
79
+
80
+ TEST_CASE("AbortController.abort() sets custom reason", "[abort]") {
81
+ setup();
82
+ const char* s = eval_str(R"(
83
+ const ac = new AbortController();
84
+ ac.abort("custom reason");
85
+ ac.signal.reason;
86
+ )");
87
+ TEST_ASSERT_EQUAL_STRING("custom reason", s);
88
+ JS_FreeCString(ctx, s);
89
+ teardown();
90
+ }
91
+
92
+ TEST_CASE("AbortController.abort() default reason is AbortError", "[abort]") {
93
+ setup();
94
+ const char* s = eval_str(R"(
95
+ const ac = new AbortController();
96
+ ac.abort();
97
+ const r = ac.signal.reason;
98
+ (r instanceof AbortError && r.name === "AbortError") ? "ok" : "fail";
99
+ )");
100
+ TEST_ASSERT_EQUAL_STRING("ok", s);
101
+ JS_FreeCString(ctx, s);
102
+ teardown();
103
+ }
104
+
105
+ TEST_CASE("AbortSignal.abort() returns pre-aborted signal", "[abort]") {
106
+ setup();
107
+ const char* s = eval_str("AbortSignal.abort().aborted ? 'yes' : 'no'");
108
+ TEST_ASSERT_EQUAL_STRING("yes", s);
109
+ JS_FreeCString(ctx, s);
110
+ teardown();
111
+ }
112
+
113
+ TEST_CASE("AbortSignal.throwIfAborted() throws when aborted", "[abort]") {
114
+ setup();
115
+ const char* s = eval_str(R"(
116
+ try {
117
+ AbortSignal.abort("boom").throwIfAborted();
118
+ "no throw";
119
+ } catch (e) { String(e); }
120
+ )");
121
+ TEST_ASSERT_EQUAL_STRING("boom", s);
122
+ JS_FreeCString(ctx, s);
123
+ teardown();
124
+ }
125
+
126
+ TEST_CASE("AbortSignal.throwIfAborted() is no-op when not aborted", "[abort]") {
127
+ setup();
128
+ const char* s = eval_str(R"(
129
+ try {
130
+ new AbortController().signal.throwIfAborted();
131
+ "ok";
132
+ } catch (e) { "threw"; }
133
+ )");
134
+ TEST_ASSERT_EQUAL_STRING("ok", s);
135
+ JS_FreeCString(ctx, s);
136
+ teardown();
137
+ }
138
+
139
+ TEST_CASE("abort fires onabort and addEventListener listeners", "[abort]") {
140
+ setup();
141
+ const char* s = eval_str(R"(
142
+ const ac = new AbortController();
143
+ const called = [];
144
+ ac.signal.onabort = () => called.push("onabort");
145
+ ac.signal.addEventListener("abort", () => called.push("listener"));
146
+ ac.abort();
147
+ called.join(",");
148
+ )");
149
+ TEST_ASSERT_EQUAL_STRING("onabort,listener", s);
150
+ JS_FreeCString(ctx, s);
151
+ teardown();
152
+ }
153
+
154
+ TEST_CASE("abort is idempotent - listeners fire only once", "[abort]") {
155
+ setup();
156
+ const char* s = eval_str(R"(
157
+ const ac = new AbortController();
158
+ let count = 0;
159
+ ac.signal.addEventListener("abort", () => count++);
160
+ ac.abort();
161
+ ac.abort();
162
+ String(count);
163
+ )");
164
+ TEST_ASSERT_EQUAL_STRING("1", s);
165
+ JS_FreeCString(ctx, s);
166
+ teardown();
167
+ }
168
+
169
+ TEST_CASE("removeEventListener removes listener", "[abort]") {
170
+ setup();
171
+ const char* s = eval_str(R"(
172
+ const ac = new AbortController();
173
+ let called = false;
174
+ const fn = () => { called = true; };
175
+ ac.signal.addEventListener("abort", fn);
176
+ ac.signal.removeEventListener("abort", fn);
177
+ ac.abort();
178
+ called ? "called" : "not called";
179
+ )");
180
+ TEST_ASSERT_EQUAL_STRING("not called", s);
181
+ JS_FreeCString(ctx, s);
182
+ teardown();
183
+ }
184
+
185
+ TEST_CASE("AbortSignal.any() aborts when any input aborts", "[abort]") {
186
+ setup();
187
+ const char* s = eval_str(R"(
188
+ const ac1 = new AbortController();
189
+ const ac2 = new AbortController();
190
+ const combined = AbortSignal.any([ac1.signal, ac2.signal]);
191
+ ac2.abort("second");
192
+ combined.aborted && combined.reason === "second" ? "ok" : "fail";
193
+ )");
194
+ TEST_ASSERT_EQUAL_STRING("ok", s);
195
+ JS_FreeCString(ctx, s);
196
+ teardown();
197
+ }
198
+
199
+ TEST_CASE("AbortSignal.any() picks up already-aborted signal", "[abort]") {
200
+ setup();
201
+ const char* s = eval_str(R"(
202
+ const aborted = AbortSignal.abort("already");
203
+ const combined = AbortSignal.any([aborted, new AbortController().signal]);
204
+ combined.aborted && combined.reason === "already" ? "ok" : "fail";
205
+ )");
206
+ TEST_ASSERT_EQUAL_STRING("ok", s);
207
+ JS_FreeCString(ctx, s);
208
+ teardown();
209
+ }
210
+
211
+ TEST_CASE("AbortSignal.timeout() creates a signal with TimeoutError name", "[abort]") {
212
+ setup();
213
+ // We can't easily test the actual timeout firing (needs event loop),
214
+ // but we can verify the signal is created and starts non-aborted.
215
+ const char* s = eval_str(R"(
216
+ const sig = AbortSignal.timeout(60000);
217
+ sig instanceof AbortSignal && !sig.aborted ? "ok" : "fail";
218
+ )");
219
+ TEST_ASSERT_EQUAL_STRING("ok", s);
220
+ JS_FreeCString(ctx, s);
221
+ teardown();
222
+ }
223
+
224
+ TEST_CASE("AbortError has correct name and message", "[abort]") {
225
+ setup();
226
+ const char* s = eval_str(R"(
227
+ const e = new AbortError("test msg");
228
+ e.name + ":" + e.message;
229
+ )");
230
+ TEST_ASSERT_EQUAL_STRING("AbortError:test msg", s);
231
+ JS_FreeCString(ctx, s);
232
+ teardown();
233
+ }
234
+
235
+ TEST_CASE("AbortError is an instance of Error", "[abort]") {
236
+ setup();
237
+ const char* s = eval_str(R"(
238
+ new AbortError() instanceof Error ? "yes" : "no";
239
+ )");
240
+ TEST_ASSERT_EQUAL_STRING("yes", s);
241
+ JS_FreeCString(ctx, s);
242
+ teardown();
243
+ }
244
+
245
+ TEST_CASE("TimeoutError has correct name and message", "[abort]") {
246
+ setup();
247
+ const char* s = eval_str(R"(
248
+ const e = new TimeoutError("test msg");
249
+ e.name + ":" + e.message;
250
+ )");
251
+ TEST_ASSERT_EQUAL_STRING("TimeoutError:test msg", s);
252
+ JS_FreeCString(ctx, s);
253
+ teardown();
254
+ }