visaljs 0.0.9 → 0.0.11

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 (232) hide show
  1. package/README.md +12 -4
  2. package/THIRD_PARTY_LICENSES +31 -1
  3. package/cli.js +3745 -890
  4. package/node/include/js_node.h +12 -1
  5. package/node/prelude/_http_common.js +29 -0
  6. package/node/prelude/async_hooks.js +50 -11
  7. package/node/prelude/child_process.js +31 -4
  8. package/node/prelude/console.js +311 -143
  9. package/node/prelude/crypto.js +6 -4
  10. package/node/prelude/dgram.js +1169 -0
  11. package/node/prelude/diagnostics_channel.js +3 -1
  12. package/node/prelude/dns.js +250 -45
  13. package/node/prelude/dns_promises.js +8 -2
  14. package/node/prelude/fs_promises.js +9 -1
  15. package/node/prelude/http.js +405 -94
  16. package/node/prelude/https.js +13 -4
  17. package/node/prelude/internal/console_class.js +7 -0
  18. package/node/prelude/internal/console_global.js +25 -0
  19. package/node/prelude/internal/crypto/key_encryption.js +217 -0
  20. package/node/prelude/internal/crypto/keys.js +161 -26
  21. package/node/prelude/internal/crypto/random.js +24 -0
  22. package/node/prelude/internal/crypto/util.js +2 -1
  23. package/node/prelude/internal/crypto_x509.js +161 -0
  24. package/node/prelude/internal/dns_classes.js +6 -0
  25. package/node/prelude/internal/dns_resolver.js +371 -0
  26. package/node/prelude/internal/errors.js +9 -0
  27. package/node/prelude/internal/events_on.js +82 -37
  28. package/node/prelude/internal/features.js +8 -4
  29. package/node/prelude/internal/fs_filehandle.js +10 -4
  30. package/node/prelude/internal/http_chars.ts +22 -0
  31. package/node/prelude/internal/perf_histogram.js +1 -1
  32. package/node/prelude/internal/process_more.js +32 -17
  33. package/node/prelude/internal/process_signals.js +8 -2
  34. package/node/prelude/internal/punycode.ts +163 -0
  35. package/node/prelude/internal/readline.js +648 -274
  36. package/node/prelude/internal/readline_editor.js +1240 -0
  37. package/node/prelude/internal/string_width.js +43 -0
  38. package/node/prelude/internal/tls/common.js +145 -33
  39. package/node/prelude/internal/tls/wrap.js +182 -49
  40. package/node/prelude/internal/tls/x509.js +4 -1
  41. package/node/prelude/internal/udp.js +177 -0
  42. package/node/prelude/net.js +30 -14
  43. package/node/prelude/os.js +24 -6
  44. package/node/prelude/perf_hooks.js +37 -2
  45. package/node/prelude/punycode.js +2 -130
  46. package/node/prelude/readline.js +113 -4
  47. package/node/prelude/readline_promises.js +56 -32
  48. package/node/prelude/tls.js +21 -4
  49. package/node/prelude/util.js +3 -16
  50. package/node/src/host_dns.c +623 -0
  51. package/node/src/host_http.c +12 -0
  52. package/node/src/host_net.c +46 -0
  53. package/node/src/host_os.c +1 -6
  54. package/node/src/host_sys.c +79 -0
  55. package/node/src/host_udp.c +418 -0
  56. package/node/third_party/c-ares/LICENSE.md +24 -0
  57. package/node/third_party/c-ares/config/darwin/ares_config.h +573 -0
  58. package/node/third_party/c-ares/config/freebsd/ares_config.h +573 -0
  59. package/node/third_party/c-ares/config/linux/ares_config.h +573 -0
  60. package/node/third_party/c-ares/config/openbsd/ares_config.h +583 -0
  61. package/node/third_party/c-ares/include/ares.h +1237 -0
  62. package/node/third_party/c-ares/include/ares_build.h +202 -0
  63. package/node/third_party/c-ares/include/ares_dns.h +127 -0
  64. package/node/third_party/c-ares/include/ares_dns_record.h +1119 -0
  65. package/node/third_party/c-ares/include/ares_nameser.h +510 -0
  66. package/node/third_party/c-ares/include/ares_version.h +47 -0
  67. package/node/third_party/c-ares/src/lib/ares_addrinfo2hostent.c +305 -0
  68. package/node/third_party/c-ares/src/lib/ares_addrinfo_localhost.c +245 -0
  69. package/node/third_party/c-ares/src/lib/ares_android.c +496 -0
  70. package/node/third_party/c-ares/src/lib/ares_android.h +38 -0
  71. package/node/third_party/c-ares/src/lib/ares_cancel.c +87 -0
  72. package/node/third_party/c-ares/src/lib/ares_close_sockets.c +137 -0
  73. package/node/third_party/c-ares/src/lib/ares_conn.c +511 -0
  74. package/node/third_party/c-ares/src/lib/ares_conn.h +202 -0
  75. package/node/third_party/c-ares/src/lib/ares_cookie.c +461 -0
  76. package/node/third_party/c-ares/src/lib/ares_data.c +168 -0
  77. package/node/third_party/c-ares/src/lib/ares_data.h +92 -0
  78. package/node/third_party/c-ares/src/lib/ares_destroy.c +159 -0
  79. package/node/third_party/c-ares/src/lib/ares_free_hostent.c +54 -0
  80. package/node/third_party/c-ares/src/lib/ares_free_string.c +33 -0
  81. package/node/third_party/c-ares/src/lib/ares_freeaddrinfo.c +67 -0
  82. package/node/third_party/c-ares/src/lib/ares_getaddrinfo.c +806 -0
  83. package/node/third_party/c-ares/src/lib/ares_getenv.c +38 -0
  84. package/node/third_party/c-ares/src/lib/ares_getenv.h +34 -0
  85. package/node/third_party/c-ares/src/lib/ares_gethostbyaddr.c +229 -0
  86. package/node/third_party/c-ares/src/lib/ares_gethostbyname.c +341 -0
  87. package/node/third_party/c-ares/src/lib/ares_getnameinfo.c +437 -0
  88. package/node/third_party/c-ares/src/lib/ares_hosts_file.c +960 -0
  89. package/node/third_party/c-ares/src/lib/ares_inet_net_pton.h +31 -0
  90. package/node/third_party/c-ares/src/lib/ares_init.c +631 -0
  91. package/node/third_party/c-ares/src/lib/ares_ipv6.h +115 -0
  92. package/node/third_party/c-ares/src/lib/ares_library_init.c +190 -0
  93. package/node/third_party/c-ares/src/lib/ares_metrics.c +261 -0
  94. package/node/third_party/c-ares/src/lib/ares_options.c +492 -0
  95. package/node/third_party/c-ares/src/lib/ares_parse_into_addrinfo.c +179 -0
  96. package/node/third_party/c-ares/src/lib/ares_private.h +648 -0
  97. package/node/third_party/c-ares/src/lib/ares_process.c +1649 -0
  98. package/node/third_party/c-ares/src/lib/ares_qcache.c +442 -0
  99. package/node/third_party/c-ares/src/lib/ares_query.c +151 -0
  100. package/node/third_party/c-ares/src/lib/ares_search.c +623 -0
  101. package/node/third_party/c-ares/src/lib/ares_send.c +300 -0
  102. package/node/third_party/c-ares/src/lib/ares_set_socket_functions.c +590 -0
  103. package/node/third_party/c-ares/src/lib/ares_setup.h +224 -0
  104. package/node/third_party/c-ares/src/lib/ares_socket.c +427 -0
  105. package/node/third_party/c-ares/src/lib/ares_socket.h +163 -0
  106. package/node/third_party/c-ares/src/lib/ares_sortaddrinfo.c +447 -0
  107. package/node/third_party/c-ares/src/lib/ares_strerror.c +91 -0
  108. package/node/third_party/c-ares/src/lib/ares_sysconfig.c +642 -0
  109. package/node/third_party/c-ares/src/lib/ares_sysconfig_files.c +851 -0
  110. package/node/third_party/c-ares/src/lib/ares_sysconfig_mac.c +373 -0
  111. package/node/third_party/c-ares/src/lib/ares_sysconfig_win.c +673 -0
  112. package/node/third_party/c-ares/src/lib/ares_timeout.c +162 -0
  113. package/node/third_party/c-ares/src/lib/ares_update_servers.c +1376 -0
  114. package/node/third_party/c-ares/src/lib/ares_version.c +36 -0
  115. package/node/third_party/c-ares/src/lib/config-dos.h +114 -0
  116. package/node/third_party/c-ares/src/lib/config-win32.h +396 -0
  117. package/node/third_party/c-ares/src/lib/dsa/ares_array.c +409 -0
  118. package/node/third_party/c-ares/src/lib/dsa/ares_htable.c +451 -0
  119. package/node/third_party/c-ares/src/lib/dsa/ares_htable.h +174 -0
  120. package/node/third_party/c-ares/src/lib/dsa/ares_htable_asvp.c +224 -0
  121. package/node/third_party/c-ares/src/lib/dsa/ares_htable_dict.c +230 -0
  122. package/node/third_party/c-ares/src/lib/dsa/ares_htable_strvp.c +210 -0
  123. package/node/third_party/c-ares/src/lib/dsa/ares_htable_szvp.c +188 -0
  124. package/node/third_party/c-ares/src/lib/dsa/ares_htable_vpstr.c +186 -0
  125. package/node/third_party/c-ares/src/lib/dsa/ares_htable_vpvp.c +194 -0
  126. package/node/third_party/c-ares/src/lib/dsa/ares_llist.c +385 -0
  127. package/node/third_party/c-ares/src/lib/dsa/ares_slist.c +479 -0
  128. package/node/third_party/c-ares/src/lib/dsa/ares_slist.h +207 -0
  129. package/node/third_party/c-ares/src/lib/event/ares_event.h +191 -0
  130. package/node/third_party/c-ares/src/lib/event/ares_event_configchg.c +746 -0
  131. package/node/third_party/c-ares/src/lib/event/ares_event_epoll.c +192 -0
  132. package/node/third_party/c-ares/src/lib/event/ares_event_kqueue.c +248 -0
  133. package/node/third_party/c-ares/src/lib/event/ares_event_poll.c +140 -0
  134. package/node/third_party/c-ares/src/lib/event/ares_event_select.c +159 -0
  135. package/node/third_party/c-ares/src/lib/event/ares_event_thread.c +575 -0
  136. package/node/third_party/c-ares/src/lib/event/ares_event_wake_pipe.c +172 -0
  137. package/node/third_party/c-ares/src/lib/event/ares_event_win32.c +981 -0
  138. package/node/third_party/c-ares/src/lib/event/ares_event_win32.h +161 -0
  139. package/node/third_party/c-ares/src/lib/include/ares_array.h +276 -0
  140. package/node/third_party/c-ares/src/lib/include/ares_buf.h +732 -0
  141. package/node/third_party/c-ares/src/lib/include/ares_htable_asvp.h +130 -0
  142. package/node/third_party/c-ares/src/lib/include/ares_htable_dict.h +123 -0
  143. package/node/third_party/c-ares/src/lib/include/ares_htable_strvp.h +130 -0
  144. package/node/third_party/c-ares/src/lib/include/ares_htable_szvp.h +118 -0
  145. package/node/third_party/c-ares/src/lib/include/ares_htable_vpstr.h +111 -0
  146. package/node/third_party/c-ares/src/lib/include/ares_htable_vpvp.h +128 -0
  147. package/node/third_party/c-ares/src/lib/include/ares_llist.h +239 -0
  148. package/node/third_party/c-ares/src/lib/include/ares_mem.h +41 -0
  149. package/node/third_party/c-ares/src/lib/include/ares_str.h +261 -0
  150. package/node/third_party/c-ares/src/lib/inet_net_pton.c +451 -0
  151. package/node/third_party/c-ares/src/lib/inet_ntop.c +219 -0
  152. package/node/third_party/c-ares/src/lib/legacy/ares_create_query.c +78 -0
  153. package/node/third_party/c-ares/src/lib/legacy/ares_expand_name.c +99 -0
  154. package/node/third_party/c-ares/src/lib/legacy/ares_expand_string.c +107 -0
  155. package/node/third_party/c-ares/src/lib/legacy/ares_fds.c +80 -0
  156. package/node/third_party/c-ares/src/lib/legacy/ares_getsock.c +85 -0
  157. package/node/third_party/c-ares/src/lib/legacy/ares_parse_a_reply.c +107 -0
  158. package/node/third_party/c-ares/src/lib/legacy/ares_parse_aaaa_reply.c +109 -0
  159. package/node/third_party/c-ares/src/lib/legacy/ares_parse_caa_reply.c +137 -0
  160. package/node/third_party/c-ares/src/lib/legacy/ares_parse_mx_reply.c +110 -0
  161. package/node/third_party/c-ares/src/lib/legacy/ares_parse_naptr_reply.c +132 -0
  162. package/node/third_party/c-ares/src/lib/legacy/ares_parse_ns_reply.c +154 -0
  163. package/node/third_party/c-ares/src/lib/legacy/ares_parse_ptr_reply.c +213 -0
  164. package/node/third_party/c-ares/src/lib/legacy/ares_parse_soa_reply.c +115 -0
  165. package/node/third_party/c-ares/src/lib/legacy/ares_parse_srv_reply.c +114 -0
  166. package/node/third_party/c-ares/src/lib/legacy/ares_parse_txt_reply.c +144 -0
  167. package/node/third_party/c-ares/src/lib/legacy/ares_parse_uri_reply.c +113 -0
  168. package/node/third_party/c-ares/src/lib/record/ares_dns_mapping.c +982 -0
  169. package/node/third_party/c-ares/src/lib/record/ares_dns_multistring.c +309 -0
  170. package/node/third_party/c-ares/src/lib/record/ares_dns_multistring.h +72 -0
  171. package/node/third_party/c-ares/src/lib/record/ares_dns_name.c +736 -0
  172. package/node/third_party/c-ares/src/lib/record/ares_dns_parse.c +1360 -0
  173. package/node/third_party/c-ares/src/lib/record/ares_dns_private.h +273 -0
  174. package/node/third_party/c-ares/src/lib/record/ares_dns_record.c +1701 -0
  175. package/node/third_party/c-ares/src/lib/record/ares_dns_write.c +1229 -0
  176. package/node/third_party/c-ares/src/lib/str/ares_buf.c +1510 -0
  177. package/node/third_party/c-ares/src/lib/str/ares_str.c +562 -0
  178. package/node/third_party/c-ares/src/lib/str/ares_strsplit.c +90 -0
  179. package/node/third_party/c-ares/src/lib/str/ares_strsplit.h +51 -0
  180. package/node/third_party/c-ares/src/lib/thirdparty/apple/dnsinfo.h +122 -0
  181. package/node/third_party/c-ares/src/lib/util/ares_iface_ips.c +640 -0
  182. package/node/third_party/c-ares/src/lib/util/ares_iface_ips.h +140 -0
  183. package/node/third_party/c-ares/src/lib/util/ares_math.c +167 -0
  184. package/node/third_party/c-ares/src/lib/util/ares_math.h +58 -0
  185. package/node/third_party/c-ares/src/lib/util/ares_rand.c +389 -0
  186. package/node/third_party/c-ares/src/lib/util/ares_rand.h +36 -0
  187. package/node/third_party/c-ares/src/lib/util/ares_threads.c +613 -0
  188. package/node/third_party/c-ares/src/lib/util/ares_threads.h +60 -0
  189. package/node/third_party/c-ares/src/lib/util/ares_time.h +49 -0
  190. package/node/third_party/c-ares/src/lib/util/ares_timeval.c +95 -0
  191. package/node/third_party/c-ares/src/lib/util/ares_uri.c +1627 -0
  192. package/node/third_party/c-ares/src/lib/util/ares_uri.h +252 -0
  193. package/node/third_party/c-ares/src/lib/windows_port.c +29 -0
  194. package/package.json +1 -1
  195. package/prebuilt/darwin-arm64/cares-a6286c65ca9374a3.a +0 -0
  196. package/prebuilt/darwin-x64/cares-a6286c65ca9374a3.a +0 -0
  197. package/prebuilt/linux-arm64/cares-4ba05ac8e948af8e.a +0 -0
  198. package/prebuilt/linux-arm64-musl/cares-4ba05ac8e948af8e.a +0 -0
  199. package/prebuilt/linux-x64/cares-4ba05ac8e948af8e.a +0 -0
  200. package/prebuilt/linux-x64-musl/cares-4ba05ac8e948af8e.a +0 -0
  201. package/prebuilt/win32-x64/boringssl-ce573858472b7fc9.a +0 -0
  202. package/prebuilt/win32-x64/brotli-20d86a61f30baeb3.a +0 -0
  203. package/prebuilt/win32-x64/cares-49c9ec95162b912d.a +0 -0
  204. package/prebuilt/win32-x64/uv-b11bae65d7fced82.a +0 -0
  205. package/prebuilt/win32-x64/zlib-4ce2317a4c3f5fb5.a +0 -0
  206. package/prebuilt/win32-x64/zstd-015315ac7c784c73.a +0 -0
  207. package/runtime/include/js_buffer.h +185 -0
  208. package/runtime/include/js_builtins.h +58 -0
  209. package/runtime/include/js_crypto.h +11 -0
  210. package/runtime/include/js_exception.h +3 -0
  211. package/runtime/include/js_function.h +1 -1
  212. package/runtime/include/js_gc.h +13 -10
  213. package/runtime/include/js_jobs.h +2 -0
  214. package/runtime/include/js_object.h +79 -3
  215. package/runtime/include/js_ops.h +27 -0
  216. package/runtime/include/js_runtime.h +1 -0
  217. package/runtime/include/js_web.h +0 -3
  218. package/runtime/include/jscontext.h +8 -0
  219. package/runtime/src/builtins.c +17 -4
  220. package/runtime/src/crypto_internal.h +1 -0
  221. package/runtime/src/crypto_subtle.c +66 -7
  222. package/runtime/src/crypto_tls.c +265 -19
  223. package/runtime/src/function.c +37 -10
  224. package/runtime/src/gc.c +76 -93
  225. package/runtime/src/inspect.c +18 -1
  226. package/runtime/src/iterator.c +5 -1
  227. package/runtime/src/jobs.c +37 -22
  228. package/runtime/src/object.c +91 -8
  229. package/runtime/src/os.c +16 -6
  230. package/runtime/src/os.h +2 -0
  231. package/runtime/src/process.c +97 -10
  232. package/runtime/src/typedarray.c +23 -0
@@ -50,24 +50,27 @@ typedef struct JSBlock {
50
50
  size_t map_size; /* JS_BLOCK_SIZE, or the large object's mapping */
51
51
  uint32_t cell_size;
52
52
  uint32_t cell_count;
53
- uint8_t size_class;
53
+ uint8_t size_class; /* a small block's */
54
54
  uint8_t is_large;
55
- union {
56
- uint8_t queued; /* in its class's sweep queue */
57
- uint8_t remembered; /* a large object: in the remembered set, with cards marked */
58
- };
55
+ uint8_t queued; /* in its class's sweep queue */
59
56
  uint8_t has_finalizable;
60
57
  uint32_t index_magic; /* ceil(2^32 / cell_size): a cell's index is (offset * magic) >> 32 */
61
58
  uint8_t young; /* the allocator took it since the last collection */
59
+ uint8_t remembered; /* a large object: in the remembered set, with cards marked */
60
+ uint8_t card_shift; /* a large object: a card is 2^card_shift bytes of it */
62
61
  uint64_t mark_bits[JS_BITMAP_WORDS];
63
- uint64_t alloc_bits[JS_BITMAP_WORDS]; /* exact only while the world is stopped */
62
+ union {
63
+ uint64_t alloc_bits[JS_BITMAP_WORDS]; /* exact only while the world is stopped */
64
+ /* A large object's: its one cell's allocation bit, then its cards, a bit per card that a
65
+ * store gave a young cell since the last collection. */
66
+ struct {
67
+ uint64_t large_alloc;
68
+ uint64_t cards[JS_BITMAP_WORDS - 1];
69
+ };
70
+ };
64
71
  } JSBlock;
65
72
 
66
- /* A large object's cards: a bit per 2^card_shift bytes of the object
67
- * that a store gave a young cell since the last collection. They live in the allocation bitmap,
68
- * whose only other bit is bit 0 of word 0. A large object's size_class is its card_shift. */
69
73
  #define JS_LARGE_CARDS ((JS_BITMAP_WORDS - 1) * 64)
70
- static inline uint64_t *js_large_cards(JSBlock *b) { return &b->alloc_bits[1]; }
71
74
 
72
75
  #define JS_BLOCK_FIRST_CELL \
73
76
  ((sizeof(JSBlock) + JS_CELL_ALIGN - 1) & ~(size_t)(JS_CELL_ALIGN - 1))
@@ -65,6 +65,8 @@ typedef enum JSRejectionMode {
65
65
  } JSRejectionMode;
66
66
 
67
67
  void js_enqueue_microtask(JSContext *ctx, const JSJob *job);
68
+ /* process.nextTick's queue, which a checkpoint runs before the microtasks (Node's order) */
69
+ void js_enqueue_tick(JSContext *ctx, const JSJob *job);
68
70
  /* The checkpoint: runs every queued job (and the ones they queue), then processes
69
71
  * unhandled rejections. A nested call does nothing. 0, or -1 after an uncaught error
70
72
  * or a strict unhandled rejection (already reported). */
@@ -296,10 +296,10 @@ JS_WARN_UNUSED JSValue js_own_keys(JSContext *ctx, JSObject *o);
296
296
  #define JS_IC_EMPTY 0
297
297
  #define JS_IC_OWN 1 /* get: an own data property; set: an own writable data property */
298
298
  #define JS_IC_PROTO 2 /* get: a data property of `holder`, `depth` prototypes up */
299
- #define JS_IC_ADD 3 /* set: adding the key takes the receiver from `shape` to `next` */
299
+ #define JS_IC_ADD 3 /* set: adding the key takes the receiver from `shape` to `next`; `depth` prototypes up to null, or to one whose writable data property it shadows */
300
300
  #define JS_IC_GETTER 4 /* get: an accessor of `holder` (NULL: the receiver), `depth` prototypes up */
301
301
  #define JS_IC_ABSENT 5 /* get: no such property on the receiver or its `depth` prototypes (the last's proto is null) */
302
- #define JS_IC_MAX_DEPTH 4
302
+ #define JS_IC_MAX_DEPTH 8 /* prototypes a cache can check: Node's sockets are 6 deep (Socket, Duplex, Readable, Stream, EventEmitter, Object) */
303
303
 
304
304
  /* One per property access site with a constant named key; a site is either a get or a
305
305
  * set. Monomorphic: a miss refills it. Never caches dictionary shapes (their layout
@@ -314,7 +314,7 @@ typedef struct JSPropCache {
314
314
  JSShape *fast; /* OWN, inline slot: the receiver shape; else NULL */
315
315
  uint16_t fast_off; /* with `fast`: the slot's byte offset in the object */
316
316
  uint8_t kind; /* JS_IC_* */
317
- uint8_t depth; /* PROTO: hops to the holder; ADD: prototypes up to null */
317
+ uint8_t depth; /* PROTO: hops to the holder; ADD: prototypes checked (JS_IC_ADD) */
318
318
  uint32_t slot; /* OWN, PROTO: the slot */
319
319
  JSShape *shape; /* receiver shape; NULL = empty */
320
320
  JSObject *holder; /* PROTO */
@@ -326,6 +326,8 @@ typedef struct JSPropCache {
326
326
  /* A module's caches, once at startup (the GC resets them weakly). */
327
327
  void js_register_prop_caches(JSRuntime *rt, JSPropCache *ics, size_t n);
328
328
 
329
+ /* The slow paths of a named access: `ic` is the site's cache, or NULL for a computed key's access
330
+ * (the runtime's shared caches only). */
329
331
  JS_WARN_UNUSED JSValue js_get_prop_slow(JSContext *ctx, JSValue obj, JSValue key, JSPropCache *ic);
330
332
  JS_WARN_UNUSED int js_set_prop_slow(JSContext *ctx, JSValue obj, JSValue key, JSValue v, bool strict, JSPropCache *ic);
331
333
 
@@ -373,6 +375,22 @@ static inline int js_set_prop(JSContext *ctx, JSValue obj, JSValue key, JSValue
373
375
  return js_set_prop_slow(ctx, obj, key, v, strict, ic);
374
376
  }
375
377
 
378
+ /* obj[key] and obj[key] = v at a site whose key is most likely always the same symbol or string
379
+ * (the optimizer's guess: a module binding stored once, as Node's kState). `site` holds the key
380
+ * the site's cache is for (EMPTY: none yet): while the key is that one, the access is a named
381
+ * access's, inline cache and all. Another key the slow path makes the site's, or, when it isn't
382
+ * a property key already (an index, a string not interned), accesses generically. */
383
+ JS_WARN_UNUSED JSValue js_get_keyed_slow(JSContext *ctx, JSValue obj, JSValue key, JSValue *site, JSPropCache *ic);
384
+ JS_WARN_UNUSED int js_set_keyed_slow(JSContext *ctx, JSValue obj, JSValue key, JSValue v, bool strict, JSValue *site, JSPropCache *ic);
385
+ static inline JSValue js_get_keyed(JSContext *ctx, JSValue obj, JSValue key, JSValue *site, JSPropCache *ic) {
386
+ if (JS_LIKELY(js_same_bits(key, *site))) return js_get_prop(ctx, obj, key, ic);
387
+ return js_get_keyed_slow(ctx, obj, key, site, ic);
388
+ }
389
+ static inline int js_set_keyed(JSContext *ctx, JSValue obj, JSValue key, JSValue v, bool strict, JSValue *site, JSPropCache *ic) {
390
+ if (JS_LIKELY(js_same_bits(key, *site))) return js_set_prop(ctx, obj, key, v, strict, ic);
391
+ return js_set_keyed_slow(ctx, obj, key, v, strict, site, ic);
392
+ }
393
+
376
394
  /* An object's new shape. When the object is a prototype, caches that checked the chain it's on
377
395
  * may be stale: the runtime's proto_epoch moves on. */
378
396
  static JS_FAST_PATH void js_object_set_shape(JSContext *ctx, JSObject *o, JSShape *s) {
@@ -475,6 +493,64 @@ static inline JSValue js_get_length(JSContext *ctx, JSValue obj, JSValue key, JS
475
493
  if (js_is_string(obj)) return js_int32((int32_t)js_string_length(obj)); /* below 2^30 */
476
494
  return js_get_prop(ctx, obj, key, ic);
477
495
  }
496
+ /* ---- Static code's arrays ("use static": number[], string[], boolean[]) ------------------ */
497
+
498
+ /* An element's kind (an i32[] is a number[] whose reads the code converts). tsc's element types
499
+ * aren't sound (a cast, an i32[] alias of a number[]), so every read checks it: a read's value is
500
+ * of the kind or the read throws. An index past the end is a RangeError, never undefined or a hole. */
501
+ enum { JS_SARRAY_NUMBER, JS_SARRAY_STRING, JS_SARRAY_BOOLEAN };
502
+
503
+ static inline bool js_sarray_is(JSValue v, int kind) {
504
+ switch (kind) {
505
+ case JS_SARRAY_NUMBER: return js_is_number(v);
506
+ case JS_SARRAY_STRING: return !js_is_empty(v) && js_is_string(v);
507
+ default: return js_is_bool(v);
508
+ }
509
+ }
510
+ /* A Number key as an index: -1 (past every end) when it isn't one. */
511
+ static inline int64_t js_sarray_index_f64(double key) {
512
+ return key >= 0 && key < 4294967295.0 && (double)(int64_t)key == key ? (int64_t)key : -1;
513
+ }
514
+ static inline int64_t js_sarray_index(JSValue key) {
515
+ return js_is_int32(key) ? js_as_int32(key) : js_sarray_index_f64(js_as_number(key));
516
+ }
517
+ JS_WARN_UNUSED JSValue js_sarray_get_slow(JSContext *ctx, JSValue arr, int64_t i, int kind);
518
+ JS_WARN_UNUSED int js_sarray_set_slow(JSContext *ctx, JSValue arr, int64_t i, JSValue v, int kind);
519
+ JS_WARN_UNUSED JSValue js_sarray_length_slow(JSContext *ctx, JSValue arr);
520
+ JS_WARN_UNUSED JSValue js_sarray_push_slow(JSContext *ctx, JSValue arr, JSValue v, int kind);
521
+
522
+ static JS_FAST_PATH JSValue js_sarray_get(JSContext *ctx, JSValue arr, int64_t i, int kind) {
523
+ if (JS_LIKELY(js_is_array(arr))) {
524
+ JSElements *d = js_as_object(arr)->elements;
525
+ if (JS_LIKELY(d->kind == JS_ELEMENTS_DENSE && (uint64_t)i < d->length && js_sarray_is(d->data[i], kind))) return d->data[i];
526
+ }
527
+ return js_sarray_get_slow(ctx, arr, i, kind);
528
+ }
529
+ /* a[i] = v: at the length, a push; past it, a RangeError. */
530
+ static JS_FAST_PATH int js_sarray_set(JSContext *ctx, JSValue arr, int64_t i, JSValue v, int kind) {
531
+ if (JS_LIKELY(js_is_array(arr) && js_sarray_is(v, kind))) {
532
+ JSElements *d = js_as_object(arr)->elements;
533
+ if (JS_LIKELY(d->kind == JS_ELEMENTS_DENSE && (uint64_t)i < d->length && !js_is_empty(d->data[i]))) {
534
+ js_store(ctx, &d->cell, &d->data[i], v);
535
+ return 1;
536
+ }
537
+ }
538
+ return js_sarray_set_slow(ctx, arr, i, v, kind);
539
+ }
540
+ /* a.length, an int32 (a longer array is a RangeError). */
541
+ static JS_FAST_PATH JSValue js_sarray_length(JSContext *ctx, JSValue arr) {
542
+ if (JS_LIKELY(js_is_array(arr) && js_array_length(js_as_object(arr)) <= INT32_MAX)) return js_int32((int32_t)js_array_length(js_as_object(arr)));
543
+ return js_sarray_length_slow(ctx, arr);
544
+ }
545
+ /* a.push(v): the new length, an int32. */
546
+ static JS_FAST_PATH JSValue js_sarray_push(JSContext *ctx, JSValue arr, JSValue v, int kind) {
547
+ if (JS_LIKELY(js_is_array(arr) && js_sarray_is(v, kind) && js_array_length(js_as_object(arr)) < INT32_MAX)) {
548
+ if (JS_UNLIKELY(js_array_push(ctx, js_as_object(arr), v) < 0)) return JS_EXCEPTION;
549
+ return js_int32((int32_t)js_array_length(js_as_object(arr)));
550
+ }
551
+ return js_sarray_push_slow(ctx, arr, v, kind);
552
+ }
553
+
478
554
  /* delete obj[key]: true or false (sloppy), a TypeError when strict and not deletable.
479
555
  * `key` is a property key; js_delete_elem converts it first. */
480
556
  JS_WARN_UNUSED JSValue js_delete_value(JSContext *ctx, JSValue obj, JSValue key, bool strict);
@@ -46,6 +46,33 @@ JS_WARN_UNUSED JSValue js_ge(JSContext *ctx, JSValue a, JSValue b);
46
46
  /* ===, !==: never throw (strings compare by content). */
47
47
  bool js_strict_equals(JSContext *ctx, JSValue a, JSValue b);
48
48
  static inline JSValue js_strict_eq(JSContext *ctx, JSValue a, JSValue b) { return js_bool(js_strict_equals(ctx, a, b)); }
49
+ /* A Number as a typed file's ("use static") int, an int64_t: truncated toward zero and wrapped
50
+ * modulo 2^64, as ToInt32 is for 32 bits; NaN and the infinities 0 (a plain C conversion of those
51
+ * would be undefined behaviour). */
52
+ static inline int64_t js_f64_to_i64(double d) {
53
+ if (d >= -9223372036854775808.0 && d < 9223372036854775808.0) return (int64_t)d;
54
+ if (d != d || d == INFINITY || d == -INFINITY) return 0;
55
+ double m = fmod(trunc(d), 18446744073709551616.0); /* exact: d is an integer this large */
56
+ if (m < 0) m += 18446744073709551616.0;
57
+ return (int64_t)(uint64_t)m;
58
+ }
59
+ /* A Number value as an int; anything else (typed code's caller passed it unchecked) 0. */
60
+ static inline int64_t js_value_to_i64(JSValue v) {
61
+ if (js_is_int32(v)) return js_as_int32(v);
62
+ return js_is_number(v) ? js_f64_to_i64(js_as_number(v)) : 0;
63
+ }
64
+
65
+ /* v === d, d a number literal (not NaN): v is a Number of that value (0 and -0 alike). */
66
+ static inline bool js_strict_eq_num(JSValue v, double d) {
67
+ if (js_is_int32(v)) return (double)js_as_int32(v) == d;
68
+ return js_is_number(v) && js_as_number(v) == d;
69
+ }
70
+
71
+ /* a === s, s a string literal: an atom, so a string with its units is s itself unless it isn't
72
+ * interned */
73
+ static inline bool js_strict_eq_atom(JSContext *ctx, JSValue a, JSValue s) {
74
+ return js_same_bits(a, s) || (js_is_string(a) && !js_is_atom(a) && js_string_equals(ctx, a, s));
75
+ }
49
76
  static inline JSValue js_strict_ne(JSContext *ctx, JSValue a, JSValue b) { return js_bool(!js_strict_equals(ctx, a, b)); }
50
77
 
51
78
  /* A switch whose cases are all string literals: the index of the first case `v` is === to, or
@@ -17,6 +17,7 @@
17
17
  #include "js_console.h"
18
18
  #include "js_ops.h"
19
19
  #include "js_object.h"
20
+ #include "js_buffer.h"
20
21
  #include "js_function.h"
21
22
  #include "js_error.h"
22
23
  #include "js_generator.h"
@@ -13,9 +13,6 @@
13
13
  JS_WARN_UNUSED JSValue js_throw_node_error(JSContext *ctx, JSErrorKind kind, const char *code, const char *fmt, ...);
14
14
  /* ERR_INVALID_THIS: `Value of "this" must be of type TextDecoder`. */
15
15
  JS_WARN_UNUSED JSValue js_throw_invalid_this(JSContext *ctx, const char *type);
16
- /* ERR_INVALID_ARG_TYPE: `The "dest" argument must be <expected>. Received …` (Node's wording
17
- * of the value). */
18
- JS_WARN_UNUSED JSValue js_throw_invalid_arg_type(JSContext *ctx, const char *name, const char *expected, JSValue value);
19
16
  /* Node's "Received …" tail for a value: " Received type number (1)", " Received an instance of
20
17
  * Array", " Received undefined". */
21
18
  void js_node_received(JSContext *ctx, JSValue v, char *buf, size_t cap);
@@ -189,6 +189,7 @@ struct JSRuntime {
189
189
  JSValue symbol_registry; /* Symbol.for's GlobalSymbolRegistry: key -> symbol (a root) */
190
190
  uintptr_t stack_limit; /* lowest usable stack address, margin included */
191
191
  JSJobQueue jobs; /* microtasks */
192
+ JSJobQueue ticks; /* process.nextTick's: each checkpoint runs them all before the microtasks (Node's) */
192
193
  JSTimers timers; /* setTimeout / setInterval */
193
194
  /* The async context: an opaque value the host keeps per chain of async work
194
195
  * (node:async_hooks' AsyncLocalStorage keeps its stores in it). Every job, timer and promise
@@ -226,6 +227,12 @@ struct JSRuntime {
226
227
  const JSBigIntOps *bigint; /* set by the bigint component */
227
228
  /* A typed array's length now: -1 when out of bounds (detached), -2 for anything else. */
228
229
  double (*typed_array_length)(JSValue v);
230
+ /* Set by typed arrays: obj[i] and obj[i] = d (a Number) of a typed array, inline, for an index
231
+ * in bounds and an element that is a Number (not a BigInt): true when done; false for
232
+ * anything else, which takes the generic path. */
233
+ bool (*typed_array_get)(JSValue v, int32_t i, JSValue *out);
234
+ bool (*typed_array_set)(JSValue v, int32_t i, double d);
235
+ const struct JSClass *typed_array_class; /* set by typed arrays: js_buffer.h's inline element access tests it */
229
236
  /* Set by typed arrays: a typed array's or DataView's bytes (its current window), true; false
230
237
  * for anything else (an ArrayBuffer too: process.stdout.write takes views only). */
231
238
  bool (*view_bytes)(JSValue v, uint8_t **data, size_t *length);
@@ -240,6 +247,7 @@ struct JSContext {
240
247
  uint8_t barrier_threshold; /* js_store's slow path runs for an owner whose GC byte is this or more */
241
248
  JSValue intrinsics[JS_INTRINSIC_COUNT];
242
249
  JSContext *next_realm;
250
+ struct JSShape *array_shape; /* the root shape of its arrays with Array.prototype (js_new_array), made at the first */
243
251
  };
244
252
 
245
253
  JSRuntime *js_runtime_new(void);
@@ -793,7 +793,7 @@ CORE(object_proto_lookup_setter) {
793
793
 
794
794
  /* ---- Function.prototype (§20.2.3) --------------------------------------------------------------- */
795
795
 
796
- BUILTIN(function_proto_call) {
796
+ JSValue js_function_proto_call(JSContext *ctx, JSValue callee, JSValue this_val, uint32_t argc, const JSValue *argv, JSValue new_target) {
797
797
  UNUSED_ARGS;
798
798
  if (!js_is_callable(this_val)) return js_throw_type_error(ctx, "Function.prototype.call called on a non-function");
799
799
  return js_call(ctx, this_val, ARG(0), argc > 1 ? argc - 1 : 0, argv + (argc > 1 ? 1 : argc));
@@ -822,10 +822,23 @@ static JSValueArray *list_from_array_like(JSContext *ctx, JSValue v) {
822
822
 
823
823
  JSValueArray *js_list_from_array_like(JSContext *ctx, JSValue v) { return list_from_array_like(ctx, v); }
824
824
 
825
- BUILTIN(function_proto_apply) {
825
+ JSValue js_function_proto_apply(JSContext *ctx, JSValue callee, JSValue this_val, uint32_t argc, const JSValue *argv, JSValue new_target) {
826
826
  UNUSED_ARGS;
827
827
  if (!js_is_callable(this_val)) return js_throw_type_error(ctx, "Function.prototype.apply was called on a non-function");
828
828
  if (js_is_nullish(ARG(1))) return js_call(ctx, this_val, ARG(0), 0, NULL);
829
+ /* a short dense array without holes (emit's arguments): its elements are its own data
830
+ * properties, so reading them can't run code. Copied, as the callee may change the array. */
831
+ if (js_is_array(ARG(1))) {
832
+ JSObject *a = js_as_object(ARG(1));
833
+ JSElements *e = a->elements;
834
+ uint32_t n = js_array_length(a);
835
+ JSValue args[8];
836
+ if (e->kind == JS_ELEMENTS_DENSE && e->length == n && n <= 8) {
837
+ uint32_t i = 0;
838
+ while (i < n && !js_is_empty(e->data[i])) args[i] = e->data[i], i++;
839
+ if (i == n) return js_call(ctx, this_val, ARG(0), n, args);
840
+ }
841
+ }
829
842
  JSValueArray *list = list_from_array_like(ctx, ARG(1));
830
843
  if (!list) return JS_EXCEPTION;
831
844
  JSValue r = js_call(ctx, this_val, ARG(0), list->cell.aux, list->values);
@@ -959,8 +972,8 @@ void js_builtins_realm_init(JSContext *ctx, JSObject *global) {
959
972
 
960
973
  JSValue object = define_constructor(ctx, global, "Object", object_ctor, 1, in[JS_INTRINSIC_OBJECT_PROTOTYPE]);
961
974
  static const JSBuiltin function_proto[] = {
962
- JS_BUILTIN_FN("call", function_proto_call, 1),
963
- JS_BUILTIN_FN("apply", function_proto_apply, 2),
975
+ JS_BUILTIN_FN("call", js_function_proto_call, 1),
976
+ JS_BUILTIN_FN("apply", js_function_proto_apply, 2),
964
977
  JS_BUILTIN_FN("bind", function_proto_bind, 1),
965
978
  JS_BUILTIN_FN("toString", function_proto_to_string, 0),
966
979
  };
@@ -267,6 +267,7 @@ const char *js_ec_curve_jwk(int curve);
267
267
  typedef enum JSWebAlg {
268
268
  JS_WEB_HMAC = 1, JS_WEB_PBKDF2, JS_WEB_HKDF, JS_WEB_AES_CTR, JS_WEB_AES_CBC, JS_WEB_AES_GCM, JS_WEB_AES_KW,
269
269
  JS_WEB_RSASSA, JS_WEB_RSA_PSS, JS_WEB_RSA_OAEP, JS_WEB_ECDSA, JS_WEB_ECDH, JS_WEB_X25519, JS_WEB_ED25519,
270
+ JS_WEB_CHACHA20_POLY1305,
270
271
  } JSWebAlg;
271
272
 
272
273
  /* KeyUsage, as bits in this order */
@@ -226,14 +226,15 @@ static int arg_enum(Call *c, JSValue v, const char *const *values, int count, co
226
226
  c->op, where, shown, type));
227
227
  }
228
228
 
229
- enum { FORMAT_RAW, FORMAT_SPKI, FORMAT_PKCS8, FORMAT_JWK };
230
- static const char *const FORMATS[] = { "raw", "spki", "pkcs8", "jwk" };
229
+ /* the raw-* formats (Node 24's, from WebCrypto's Modern Algorithms draft) say which key raw is */
230
+ enum { FORMAT_RAW, FORMAT_SPKI, FORMAT_PKCS8, FORMAT_JWK, FORMAT_RAW_PUBLIC, FORMAT_RAW_PRIVATE, FORMAT_RAW_SEED, FORMAT_RAW_SECRET };
231
+ static const char *const FORMATS[] = { "raw", "spki", "pkcs8", "jwk", "raw-public", "raw-private", "raw-seed", "raw-secret" };
231
232
  static const char *const USAGES[] = { "encrypt", "decrypt", "sign", "verify", "deriveKey", "deriveBits", "wrapKey", "unwrapKey" };
232
233
 
233
234
  static int arg_format(Call *c, JSValue v, int i) {
234
235
  char where[32];
235
236
  snprintf(where, sizeof where, "%s argument", ORDINALS[i]);
236
- return arg_enum(c, v, FORMATS, 4, "KeyFormat", where);
237
+ return arg_enum(c, v, FORMATS, 8, "KeyFormat", where);
237
238
  }
238
239
 
239
240
  /* sequence<KeyUsage>: a new array of the strings, in order (duplicates kept, as Node keeps them),
@@ -373,7 +374,7 @@ typedef enum Op {
373
374
 
374
375
  /* Parameter dictionaries, and their members (alphabetical, as WebIDL converts them) */
375
376
  typedef enum Dict {
376
- DICT_NONE, DICT_HMAC_IMPORT, DICT_HMAC_KEYGEN, DICT_PBKDF2, DICT_HKDF, DICT_AES_CBC, DICT_AES_CTR, DICT_AES_GCM, DICT_AES_KEYGEN,
377
+ DICT_NONE, DICT_HMAC_IMPORT, DICT_HMAC_KEYGEN, DICT_PBKDF2, DICT_HKDF, DICT_AES_CBC, DICT_AES_CTR, DICT_AES_GCM, DICT_AEAD, DICT_AES_KEYGEN,
377
378
  DICT_AES_DERIVED, DICT_RSA_HASHED_IMPORT, DICT_RSA_HASHED_KEYGEN, DICT_RSA_PSS, DICT_RSA_OAEP, DICT_EC_IMPORT, DICT_EC_KEYGEN,
378
379
  DICT_ECDSA, DICT_ECDH_DERIVE,
379
380
  } Dict;
@@ -402,6 +403,7 @@ static const struct {
402
403
  [DICT_AES_CBC] = { "AesCbcParams", { M_IV, M_END }, 1, 0 },
403
404
  [DICT_AES_CTR] = { "AesCtrParams", { M_COUNTER, M_LENGTH, M_END }, 3, 255 },
404
405
  [DICT_AES_GCM] = { "AesGcmParams", { M_ADDITIONAL_DATA, M_IV, M_TAG_LENGTH, M_END }, 2, 0 },
406
+ [DICT_AEAD] = { "AeadParams", { M_ADDITIONAL_DATA, M_IV, M_TAG_LENGTH, M_END }, 2, 0 },
405
407
  [DICT_AES_KEYGEN] = { "AesKeyGenParams", { M_LENGTH, M_END }, 1, 65535 },
406
408
  [DICT_AES_DERIVED] = { "AesDerivedKeyParams", { M_LENGTH, M_END }, 1, 65535 },
407
409
  [DICT_RSA_HASHED_IMPORT] = { "RsaHashedImportParams", { M_HASH, M_END }, 1, 0 },
@@ -446,6 +448,8 @@ static const struct {
446
448
  { [OP_IMPORT_KEY] = DICT_EC_IMPORT, [OP_GENERATE_KEY] = DICT_EC_KEYGEN, [OP_DERIVE_BITS] = DICT_ECDH_DERIVE } },
447
449
  { "X25519", JS_WEB_X25519, KEY_OPS | BIT(OP_DERIVE_BITS), { [OP_DERIVE_BITS] = DICT_ECDH_DERIVE } },
448
450
  { "Ed25519", JS_WEB_ED25519, KEY_OPS | BIT(OP_SIGN) | BIT(OP_VERIFY), { 0 } },
451
+ { "ChaCha20-Poly1305", JS_WEB_CHACHA20_POLY1305, BIT(OP_IMPORT_KEY) | BIT(OP_GENERATE_KEY) | BIT(OP_ENCRYPT) | BIT(OP_DECRYPT),
452
+ { [OP_ENCRYPT] = DICT_AEAD, [OP_DECRYPT] = DICT_AEAD } },
449
453
  };
450
454
 
451
455
  /* A normalized algorithm: its registry entry and the members its dictionary has. */
@@ -714,6 +718,7 @@ static bool is_aes(uint8_t alg) { return alg >= JS_WEB_AES_CTR && alg <= JS_WEB_
714
718
  /* A JWK's `alg` for a secret key: HS256, A128GCM, … */
715
719
  static void jwk_alg(uint8_t alg, const JSHashAlg *hash, uint32_t length, char *out, size_t cap) {
716
720
  if (alg == JS_WEB_HMAC) snprintf(out, cap, "HS%s", hash->web + 4);
721
+ else if (alg == JS_WEB_CHACHA20_POLY1305) snprintf(out, cap, "C20P");
717
722
  else snprintf(out, cap, "A%u%s", length, web_alg_name(alg) + 4);
718
723
  }
719
724
 
@@ -728,6 +733,14 @@ static JSValue aes_algorithm(JSContext *ctx, const char *name, uint32_t length)
728
733
  return o;
729
734
  }
730
735
 
736
+ /* a secret key's algorithm object: { name, length } for AES; ChaCha20-Poly1305's, { name } */
737
+ static JSValue secret_algorithm(JSContext *ctx, uint8_t alg, const char *name, uint32_t length) {
738
+ if (alg != JS_WEB_CHACHA20_POLY1305) return aes_algorithm(ctx, name, length);
739
+ JSValue a = js_new_object(ctx);
740
+ put(ctx, a, "name", str(ctx, name));
741
+ return a;
742
+ }
743
+
731
744
  static JSValue import_aes(JSContext *ctx, int format, JSValue key_data, const JWK *jwk, Params *p, bool extractable, JSValue usages,
732
745
  uint16_t mask) {
733
746
  uint8_t alg = params_alg(p);
@@ -750,7 +763,7 @@ static JSValue import_aes(JSContext *ctx, int format, JSValue key_data, const JW
750
763
  return dom_error(ctx, "NotSupportedError", m);
751
764
  }
752
765
  uint32_t length = (uint32_t)raw.n * 8;
753
- if (length != 128 && length != 192 && length != 256) {
766
+ if (alg == JS_WEB_CHACHA20_POLY1305 ? length != 256 : length != 128 && length != 192 && length != 256) {
754
767
  bytes_free(&raw);
755
768
  return dom_error(ctx, "DataError", "Invalid key length");
756
769
  }
@@ -764,7 +777,7 @@ static JSValue import_aes(JSContext *ctx, int format, JSValue key_data, const JW
764
777
  }
765
778
  JSValue data = js_new_secret_key(ctx, raw.p, raw.n);
766
779
  bytes_free(&raw);
767
- return js_new_crypto_key(ctx, data, alg, NULL, length, aes_algorithm(ctx, p->name, length), usages, mask, extractable);
780
+ return js_new_crypto_key(ctx, data, alg, NULL, length, secret_algorithm(ctx, alg, p->name, length), usages, mask, extractable);
768
781
  }
769
782
 
770
783
  /* ---- Asymmetric keys: RSA, EC, X25519 and Ed25519 ------------------------------------------------- */
@@ -1048,6 +1061,18 @@ static JSValue generate_asym(JSContext *ctx, Params *p, bool extractable, uint16
1048
1061
  return pair;
1049
1062
  }
1050
1063
 
1064
+ /* A raw-* format as raw for the algorithm it fits (raw-secret: a secret key's; raw-public: an EC,
1065
+ * X25519 or Ed25519 public key's), other formats as they are; -1 where it doesn't fit (raw-private
1066
+ * and raw-seed are ML-DSA's and ML-KEM's). */
1067
+ static int raw_alias(int alg, int format) {
1068
+ if (format == FORMAT_RAW && alg == JS_WEB_CHACHA20_POLY1305) return -1; /* Node: raw-secret only */
1069
+ if (format < FORMAT_RAW_PUBLIC) return format;
1070
+ bool secret = !is_asym_alg(alg);
1071
+ if (format == FORMAT_RAW_SECRET && secret) return FORMAT_RAW;
1072
+ if (format == FORMAT_RAW_PUBLIC && !secret && alg != JS_WEB_RSASSA && alg != JS_WEB_RSA_PSS && alg != JS_WEB_RSA_OAEP) return FORMAT_RAW;
1073
+ return -1;
1074
+ }
1075
+
1051
1076
  /* importKey's steps after the `this` check, for subtle.importKey and deriveKey. */
1052
1077
  static JSValue import_key(JSContext *ctx, uint32_t argc, const JSValue *argv) {
1053
1078
  Call c = { ctx, "importKey" };
@@ -1066,6 +1091,14 @@ static JSValue import_key(JSContext *ctx, uint32_t argc, const JSValue *argv) {
1066
1091
  params_free(&p);
1067
1092
  return JS_EXCEPTION;
1068
1093
  }
1094
+ int raw = raw_alias(REGISTRY[p.entry].alg, format);
1095
+ if (raw < 0) {
1096
+ char m[96];
1097
+ snprintf(m, sizeof m, "Unable to import %s using %s format", p.name, FORMATS[format]);
1098
+ params_free(&p);
1099
+ return dom_error(ctx, "NotSupportedError", m);
1100
+ }
1101
+ format = raw;
1069
1102
  JSValue key;
1070
1103
  switch (REGISTRY[p.entry].alg) {
1071
1104
  case JS_WEB_HMAC:
@@ -1075,6 +1108,7 @@ static JSValue import_key(JSContext *ctx, uint32_t argc, const JSValue *argv) {
1075
1108
  case JS_WEB_AES_CBC:
1076
1109
  case JS_WEB_AES_GCM:
1077
1110
  case JS_WEB_AES_KW:
1111
+ case JS_WEB_CHACHA20_POLY1305:
1078
1112
  key = import_aes(ctx, format, argv[1], &jwk, &p, extractable, usages, mask);
1079
1113
  break;
1080
1114
  case JS_WEB_RSASSA:
@@ -1121,6 +1155,14 @@ static JSValue export_key(JSContext *ctx, uint32_t argc, const JSValue *argv) {
1121
1155
  return dom_error(ctx, "NotSupportedError", m);
1122
1156
  }
1123
1157
  if (!k->extractable) return dom_error(ctx, "InvalidAccessError", "key is not extractable");
1158
+ int raw = raw_alias(k->alg, format);
1159
+ if (raw < 0 || (format == FORMAT_RAW_PUBLIC && js_key_data(k->data)->type != JS_KEY_PUBLIC)) {
1160
+ uint8_t type = js_key_data(k->data)->type;
1161
+ snprintf(m, sizeof m, "Unable to export %s %s key using %s format", web_alg_name(k->alg),
1162
+ type == JS_KEY_SECRET ? "secret" : type == JS_KEY_PUBLIC ? "public" : "private", FORMATS[format]);
1163
+ return dom_error(ctx, "NotSupportedError", m);
1164
+ }
1165
+ format = raw;
1124
1166
  if (is_asym_alg(k->alg)) return export_asym(ctx, format, k);
1125
1167
  JSKeyData *d = js_key_data(k->data);
1126
1168
  if (format == FORMAT_RAW) return array_buffer_of(ctx, d->bytes, d->len);
@@ -1229,6 +1271,9 @@ static JSValue generate_key(JSContext *ctx, uint32_t argc, const JSValue *argv)
1229
1271
  if (p.has_length && p.length == 0) return dom_error(ctx, "OperationError", "HmacKeyGenParams.length cannot be 0");
1230
1272
  length = p.has_length ? p.length : (uint32_t)p.hash->block_len * 8;
1231
1273
  if (has_any_not_in(mask, JS_USAGE_SIGN | JS_USAGE_VERIFY)) return dom_error(ctx, "SyntaxError", "Unsupported key usage for HMAC key");
1274
+ } else if (alg == JS_WEB_CHACHA20_POLY1305) {
1275
+ length = 256;
1276
+ if (has_any_not_in(mask, aes_usages(alg))) return usage_error(ctx, p.name);
1232
1277
  } else {
1233
1278
  length = p.length;
1234
1279
  if (length != 128 && length != 192 && length != 256)
@@ -1245,7 +1290,7 @@ static JSValue generate_key(JSContext *ctx, uint32_t argc, const JSValue *argv)
1245
1290
  JSValue data = js_new_secret_key(ctx, bytes, n);
1246
1291
  free(bytes);
1247
1292
  if (js_array_length(js_as_object(usages)) == 0) return dom_error(ctx, "SyntaxError", "Usages cannot be empty when creating a key.");
1248
- JSValue algorithm = alg == JS_WEB_HMAC ? hmac_algorithm(ctx, p.hash, length) : aes_algorithm(ctx, p.name, length);
1293
+ JSValue algorithm = alg == JS_WEB_HMAC ? hmac_algorithm(ctx, p.hash, length) : secret_algorithm(ctx, alg, p.name, length);
1249
1294
  return js_new_crypto_key(ctx, data, alg, p.hash, length, algorithm, usages, mask, extractable);
1250
1295
  }
1251
1296
 
@@ -1564,6 +1609,20 @@ static JSValue aes_cipher(JSContext *ctx, bool encrypt, JSCryptoKey *k, Params *
1564
1609
  data->p, data->n - tag_n, &out);
1565
1610
  break;
1566
1611
  }
1612
+ case JS_WEB_CHACHA20_POLY1305: {
1613
+ uint32_t tag_bits = p->has_tag_length ? p->tag_length : 128;
1614
+ if (tag_bits != 128) {
1615
+ char m[64];
1616
+ snprintf(m, sizeof m, "%u is not a valid ChaCha20-Poly1305 tag length", tag_bits);
1617
+ return dom_error(ctx, "OperationError", m);
1618
+ }
1619
+ if (p->iv.n != 12) return dom_error(ctx, "OperationError", "algorithm.iv must contain exactly 12 bytes");
1620
+ if (!encrypt && data->n < 16) return op_failed(ctx);
1621
+ const JSCipherAlg *alg = js_cipher_by_name("chacha20-poly1305");
1622
+ ok = encrypt ? run_cipher(alg, true, d, p->iv.p, 12, 16, &p->additional_data, NULL, 0, data->p, data->n, &out)
1623
+ : run_cipher(alg, false, d, p->iv.p, 12, 16, &p->additional_data, data->p + data->n - 16, 16, data->p, data->n - 16, &out);
1624
+ break;
1625
+ }
1567
1626
  default: { /* AES-KW, with RFC 3394's default IV */
1568
1627
  static const uint8_t KW_IV[8] = { 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6 };
1569
1628
  ok = run_cipher(js_cipher_aes(JS_CIPHER_WRAP, d->len), encrypt, d, KW_IV, 8, -1, NULL, NULL, 0, data->p, data->n, &out);