visaljs 0.0.10 โ†’ 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 (221) hide show
  1. package/README.md +12 -4
  2. package/THIRD_PARTY_LICENSES +31 -1
  3. package/cli.js +962 -68
  4. package/node/include/js_node.h +11 -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 +395 -86
  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/perf_histogram.js +1 -1
  31. package/node/prelude/internal/process_more.js +32 -17
  32. package/node/prelude/internal/process_signals.js +8 -2
  33. package/node/prelude/internal/punycode.ts +163 -0
  34. package/node/prelude/internal/readline.js +648 -274
  35. package/node/prelude/internal/readline_editor.js +1240 -0
  36. package/node/prelude/internal/string_width.js +43 -0
  37. package/node/prelude/internal/tls/common.js +145 -33
  38. package/node/prelude/internal/tls/wrap.js +182 -49
  39. package/node/prelude/internal/tls/x509.js +4 -1
  40. package/node/prelude/internal/udp.js +177 -0
  41. package/node/prelude/net.js +13 -1
  42. package/node/prelude/os.js +24 -6
  43. package/node/prelude/perf_hooks.js +37 -2
  44. package/node/prelude/punycode.js +2 -130
  45. package/node/prelude/readline.js +113 -4
  46. package/node/prelude/readline_promises.js +56 -32
  47. package/node/prelude/tls.js +21 -4
  48. package/node/prelude/util.js +3 -16
  49. package/node/src/host_dns.c +623 -0
  50. package/node/src/host_http.c +12 -0
  51. package/node/src/host_net.c +46 -0
  52. package/node/src/host_os.c +1 -6
  53. package/node/src/host_sys.c +70 -0
  54. package/node/src/host_udp.c +418 -0
  55. package/node/third_party/c-ares/LICENSE.md +24 -0
  56. package/node/third_party/c-ares/config/darwin/ares_config.h +573 -0
  57. package/node/third_party/c-ares/config/freebsd/ares_config.h +573 -0
  58. package/node/third_party/c-ares/config/linux/ares_config.h +573 -0
  59. package/node/third_party/c-ares/config/openbsd/ares_config.h +583 -0
  60. package/node/third_party/c-ares/include/ares.h +1237 -0
  61. package/node/third_party/c-ares/include/ares_build.h +202 -0
  62. package/node/third_party/c-ares/include/ares_dns.h +127 -0
  63. package/node/third_party/c-ares/include/ares_dns_record.h +1119 -0
  64. package/node/third_party/c-ares/include/ares_nameser.h +510 -0
  65. package/node/third_party/c-ares/include/ares_version.h +47 -0
  66. package/node/third_party/c-ares/src/lib/ares_addrinfo2hostent.c +305 -0
  67. package/node/third_party/c-ares/src/lib/ares_addrinfo_localhost.c +245 -0
  68. package/node/third_party/c-ares/src/lib/ares_android.c +496 -0
  69. package/node/third_party/c-ares/src/lib/ares_android.h +38 -0
  70. package/node/third_party/c-ares/src/lib/ares_cancel.c +87 -0
  71. package/node/third_party/c-ares/src/lib/ares_close_sockets.c +137 -0
  72. package/node/third_party/c-ares/src/lib/ares_conn.c +511 -0
  73. package/node/third_party/c-ares/src/lib/ares_conn.h +202 -0
  74. package/node/third_party/c-ares/src/lib/ares_cookie.c +461 -0
  75. package/node/third_party/c-ares/src/lib/ares_data.c +168 -0
  76. package/node/third_party/c-ares/src/lib/ares_data.h +92 -0
  77. package/node/third_party/c-ares/src/lib/ares_destroy.c +159 -0
  78. package/node/third_party/c-ares/src/lib/ares_free_hostent.c +54 -0
  79. package/node/third_party/c-ares/src/lib/ares_free_string.c +33 -0
  80. package/node/third_party/c-ares/src/lib/ares_freeaddrinfo.c +67 -0
  81. package/node/third_party/c-ares/src/lib/ares_getaddrinfo.c +806 -0
  82. package/node/third_party/c-ares/src/lib/ares_getenv.c +38 -0
  83. package/node/third_party/c-ares/src/lib/ares_getenv.h +34 -0
  84. package/node/third_party/c-ares/src/lib/ares_gethostbyaddr.c +229 -0
  85. package/node/third_party/c-ares/src/lib/ares_gethostbyname.c +341 -0
  86. package/node/third_party/c-ares/src/lib/ares_getnameinfo.c +437 -0
  87. package/node/third_party/c-ares/src/lib/ares_hosts_file.c +960 -0
  88. package/node/third_party/c-ares/src/lib/ares_inet_net_pton.h +31 -0
  89. package/node/third_party/c-ares/src/lib/ares_init.c +631 -0
  90. package/node/third_party/c-ares/src/lib/ares_ipv6.h +115 -0
  91. package/node/third_party/c-ares/src/lib/ares_library_init.c +190 -0
  92. package/node/third_party/c-ares/src/lib/ares_metrics.c +261 -0
  93. package/node/third_party/c-ares/src/lib/ares_options.c +492 -0
  94. package/node/third_party/c-ares/src/lib/ares_parse_into_addrinfo.c +179 -0
  95. package/node/third_party/c-ares/src/lib/ares_private.h +648 -0
  96. package/node/third_party/c-ares/src/lib/ares_process.c +1649 -0
  97. package/node/third_party/c-ares/src/lib/ares_qcache.c +442 -0
  98. package/node/third_party/c-ares/src/lib/ares_query.c +151 -0
  99. package/node/third_party/c-ares/src/lib/ares_search.c +623 -0
  100. package/node/third_party/c-ares/src/lib/ares_send.c +300 -0
  101. package/node/third_party/c-ares/src/lib/ares_set_socket_functions.c +590 -0
  102. package/node/third_party/c-ares/src/lib/ares_setup.h +224 -0
  103. package/node/third_party/c-ares/src/lib/ares_socket.c +427 -0
  104. package/node/third_party/c-ares/src/lib/ares_socket.h +163 -0
  105. package/node/third_party/c-ares/src/lib/ares_sortaddrinfo.c +447 -0
  106. package/node/third_party/c-ares/src/lib/ares_strerror.c +91 -0
  107. package/node/third_party/c-ares/src/lib/ares_sysconfig.c +642 -0
  108. package/node/third_party/c-ares/src/lib/ares_sysconfig_files.c +851 -0
  109. package/node/third_party/c-ares/src/lib/ares_sysconfig_mac.c +373 -0
  110. package/node/third_party/c-ares/src/lib/ares_sysconfig_win.c +673 -0
  111. package/node/third_party/c-ares/src/lib/ares_timeout.c +162 -0
  112. package/node/third_party/c-ares/src/lib/ares_update_servers.c +1376 -0
  113. package/node/third_party/c-ares/src/lib/ares_version.c +36 -0
  114. package/node/third_party/c-ares/src/lib/config-dos.h +114 -0
  115. package/node/third_party/c-ares/src/lib/config-win32.h +396 -0
  116. package/node/third_party/c-ares/src/lib/dsa/ares_array.c +409 -0
  117. package/node/third_party/c-ares/src/lib/dsa/ares_htable.c +451 -0
  118. package/node/third_party/c-ares/src/lib/dsa/ares_htable.h +174 -0
  119. package/node/third_party/c-ares/src/lib/dsa/ares_htable_asvp.c +224 -0
  120. package/node/third_party/c-ares/src/lib/dsa/ares_htable_dict.c +230 -0
  121. package/node/third_party/c-ares/src/lib/dsa/ares_htable_strvp.c +210 -0
  122. package/node/third_party/c-ares/src/lib/dsa/ares_htable_szvp.c +188 -0
  123. package/node/third_party/c-ares/src/lib/dsa/ares_htable_vpstr.c +186 -0
  124. package/node/third_party/c-ares/src/lib/dsa/ares_htable_vpvp.c +194 -0
  125. package/node/third_party/c-ares/src/lib/dsa/ares_llist.c +385 -0
  126. package/node/third_party/c-ares/src/lib/dsa/ares_slist.c +479 -0
  127. package/node/third_party/c-ares/src/lib/dsa/ares_slist.h +207 -0
  128. package/node/third_party/c-ares/src/lib/event/ares_event.h +191 -0
  129. package/node/third_party/c-ares/src/lib/event/ares_event_configchg.c +746 -0
  130. package/node/third_party/c-ares/src/lib/event/ares_event_epoll.c +192 -0
  131. package/node/third_party/c-ares/src/lib/event/ares_event_kqueue.c +248 -0
  132. package/node/third_party/c-ares/src/lib/event/ares_event_poll.c +140 -0
  133. package/node/third_party/c-ares/src/lib/event/ares_event_select.c +159 -0
  134. package/node/third_party/c-ares/src/lib/event/ares_event_thread.c +575 -0
  135. package/node/third_party/c-ares/src/lib/event/ares_event_wake_pipe.c +172 -0
  136. package/node/third_party/c-ares/src/lib/event/ares_event_win32.c +981 -0
  137. package/node/third_party/c-ares/src/lib/event/ares_event_win32.h +161 -0
  138. package/node/third_party/c-ares/src/lib/include/ares_array.h +276 -0
  139. package/node/third_party/c-ares/src/lib/include/ares_buf.h +732 -0
  140. package/node/third_party/c-ares/src/lib/include/ares_htable_asvp.h +130 -0
  141. package/node/third_party/c-ares/src/lib/include/ares_htable_dict.h +123 -0
  142. package/node/third_party/c-ares/src/lib/include/ares_htable_strvp.h +130 -0
  143. package/node/third_party/c-ares/src/lib/include/ares_htable_szvp.h +118 -0
  144. package/node/third_party/c-ares/src/lib/include/ares_htable_vpstr.h +111 -0
  145. package/node/third_party/c-ares/src/lib/include/ares_htable_vpvp.h +128 -0
  146. package/node/third_party/c-ares/src/lib/include/ares_llist.h +239 -0
  147. package/node/third_party/c-ares/src/lib/include/ares_mem.h +41 -0
  148. package/node/third_party/c-ares/src/lib/include/ares_str.h +261 -0
  149. package/node/third_party/c-ares/src/lib/inet_net_pton.c +451 -0
  150. package/node/third_party/c-ares/src/lib/inet_ntop.c +219 -0
  151. package/node/third_party/c-ares/src/lib/legacy/ares_create_query.c +78 -0
  152. package/node/third_party/c-ares/src/lib/legacy/ares_expand_name.c +99 -0
  153. package/node/third_party/c-ares/src/lib/legacy/ares_expand_string.c +107 -0
  154. package/node/third_party/c-ares/src/lib/legacy/ares_fds.c +80 -0
  155. package/node/third_party/c-ares/src/lib/legacy/ares_getsock.c +85 -0
  156. package/node/third_party/c-ares/src/lib/legacy/ares_parse_a_reply.c +107 -0
  157. package/node/third_party/c-ares/src/lib/legacy/ares_parse_aaaa_reply.c +109 -0
  158. package/node/third_party/c-ares/src/lib/legacy/ares_parse_caa_reply.c +137 -0
  159. package/node/third_party/c-ares/src/lib/legacy/ares_parse_mx_reply.c +110 -0
  160. package/node/third_party/c-ares/src/lib/legacy/ares_parse_naptr_reply.c +132 -0
  161. package/node/third_party/c-ares/src/lib/legacy/ares_parse_ns_reply.c +154 -0
  162. package/node/third_party/c-ares/src/lib/legacy/ares_parse_ptr_reply.c +213 -0
  163. package/node/third_party/c-ares/src/lib/legacy/ares_parse_soa_reply.c +115 -0
  164. package/node/third_party/c-ares/src/lib/legacy/ares_parse_srv_reply.c +114 -0
  165. package/node/third_party/c-ares/src/lib/legacy/ares_parse_txt_reply.c +144 -0
  166. package/node/third_party/c-ares/src/lib/legacy/ares_parse_uri_reply.c +113 -0
  167. package/node/third_party/c-ares/src/lib/record/ares_dns_mapping.c +982 -0
  168. package/node/third_party/c-ares/src/lib/record/ares_dns_multistring.c +309 -0
  169. package/node/third_party/c-ares/src/lib/record/ares_dns_multistring.h +72 -0
  170. package/node/third_party/c-ares/src/lib/record/ares_dns_name.c +736 -0
  171. package/node/third_party/c-ares/src/lib/record/ares_dns_parse.c +1360 -0
  172. package/node/third_party/c-ares/src/lib/record/ares_dns_private.h +273 -0
  173. package/node/third_party/c-ares/src/lib/record/ares_dns_record.c +1701 -0
  174. package/node/third_party/c-ares/src/lib/record/ares_dns_write.c +1229 -0
  175. package/node/third_party/c-ares/src/lib/str/ares_buf.c +1510 -0
  176. package/node/third_party/c-ares/src/lib/str/ares_str.c +562 -0
  177. package/node/third_party/c-ares/src/lib/str/ares_strsplit.c +90 -0
  178. package/node/third_party/c-ares/src/lib/str/ares_strsplit.h +51 -0
  179. package/node/third_party/c-ares/src/lib/thirdparty/apple/dnsinfo.h +122 -0
  180. package/node/third_party/c-ares/src/lib/util/ares_iface_ips.c +640 -0
  181. package/node/third_party/c-ares/src/lib/util/ares_iface_ips.h +140 -0
  182. package/node/third_party/c-ares/src/lib/util/ares_math.c +167 -0
  183. package/node/third_party/c-ares/src/lib/util/ares_math.h +58 -0
  184. package/node/third_party/c-ares/src/lib/util/ares_rand.c +389 -0
  185. package/node/third_party/c-ares/src/lib/util/ares_rand.h +36 -0
  186. package/node/third_party/c-ares/src/lib/util/ares_threads.c +613 -0
  187. package/node/third_party/c-ares/src/lib/util/ares_threads.h +60 -0
  188. package/node/third_party/c-ares/src/lib/util/ares_time.h +49 -0
  189. package/node/third_party/c-ares/src/lib/util/ares_timeval.c +95 -0
  190. package/node/third_party/c-ares/src/lib/util/ares_uri.c +1627 -0
  191. package/node/third_party/c-ares/src/lib/util/ares_uri.h +252 -0
  192. package/node/third_party/c-ares/src/lib/windows_port.c +29 -0
  193. package/package.json +1 -1
  194. package/prebuilt/darwin-arm64/cares-a6286c65ca9374a3.a +0 -0
  195. package/prebuilt/darwin-x64/cares-a6286c65ca9374a3.a +0 -0
  196. package/prebuilt/linux-arm64/cares-4ba05ac8e948af8e.a +0 -0
  197. package/prebuilt/linux-arm64-musl/cares-4ba05ac8e948af8e.a +0 -0
  198. package/prebuilt/linux-x64/cares-4ba05ac8e948af8e.a +0 -0
  199. package/prebuilt/linux-x64-musl/cares-4ba05ac8e948af8e.a +0 -0
  200. package/prebuilt/win32-x64/boringssl-ce573858472b7fc9.a +0 -0
  201. package/prebuilt/win32-x64/brotli-20d86a61f30baeb3.a +0 -0
  202. package/prebuilt/win32-x64/cares-49c9ec95162b912d.a +0 -0
  203. package/prebuilt/win32-x64/uv-b11bae65d7fced82.a +0 -0
  204. package/prebuilt/win32-x64/zlib-4ce2317a4c3f5fb5.a +0 -0
  205. package/prebuilt/win32-x64/zstd-015315ac7c784c73.a +0 -0
  206. package/runtime/include/js_builtins.h +5 -0
  207. package/runtime/include/js_crypto.h +11 -0
  208. package/runtime/include/js_gc.h +13 -10
  209. package/runtime/include/js_jobs.h +2 -0
  210. package/runtime/include/js_object.h +58 -0
  211. package/runtime/include/jscontext.h +1 -0
  212. package/runtime/src/crypto_internal.h +1 -0
  213. package/runtime/src/crypto_subtle.c +66 -7
  214. package/runtime/src/crypto_tls.c +265 -19
  215. package/runtime/src/gc.c +73 -92
  216. package/runtime/src/inspect.c +18 -1
  217. package/runtime/src/jobs.c +37 -22
  218. package/runtime/src/object.c +49 -2
  219. package/runtime/src/os.c +16 -6
  220. package/runtime/src/os.h +2 -0
  221. package/runtime/src/process.c +97 -10
package/cli.js CHANGED
@@ -1,13 +1,13 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire, isBuiltin } from "node:module";
3
3
  import { Worker, isMainThread, parentPort, workerData } from "node:worker_threads";
4
- import { existsSync, mkdirSync, readFileSync, readdirSync, realpathSync, renameSync, rmSync, statSync, writeFileSync } from "node:fs";
4
+ import { execFile, execFileSync, spawn, spawnSync } from "node:child_process";
5
+ import { copyFileSync, existsSync, mkdirSync, readFileSync, readdirSync, realpathSync, renameSync, rmSync, statSync, writeFileSync } from "node:fs";
5
6
  import { basename, delimiter, dirname, extname, isAbsolute, join, normalize, relative, resolve, sep } from "node:path";
6
7
  import { parseArgs, promisify } from "node:util";
7
8
  import { getHeapStatistics } from "node:v8";
8
9
  import ts from "typescript";
9
10
  import { RolldownMagicString, rolldown } from "rolldown";
10
- import { execFile, execFileSync, spawn, spawnSync } from "node:child_process";
11
11
  import { createHash } from "node:crypto";
12
12
  import { availableParallelism, homedir, tmpdir } from "node:os";
13
13
  //#region \0rolldown/runtime.js
@@ -1359,6 +1359,8 @@ var Converter = class {
1359
1359
  };
1360
1360
  }
1361
1361
  const object = this.expression(node.expression);
1362
+ const element = this.unit?.arrayElement(node.expression);
1363
+ const elem = element ? { elem: element } : {};
1362
1364
  if (ts.isPropertyAccessExpression(node)) {
1363
1365
  if (ts.isPrivateIdentifier(node.name)) return {
1364
1366
  type: "MemberExpression",
@@ -1377,7 +1379,8 @@ var Converter = class {
1377
1379
  loc,
1378
1380
  object,
1379
1381
  property: this.identifier(node.name),
1380
- computed: false
1382
+ computed: false,
1383
+ ...elem
1381
1384
  };
1382
1385
  }
1383
1386
  return {
@@ -1385,7 +1388,8 @@ var Converter = class {
1385
1388
  loc,
1386
1389
  object,
1387
1390
  property: this.expression(node.argumentExpression),
1388
- computed: true
1391
+ computed: true,
1392
+ ...elem
1389
1393
  };
1390
1394
  }
1391
1395
  /** A property name: an identifier or literal naming the key, or a computed expression. */
@@ -2901,6 +2905,21 @@ const STATIC_TYPES = {
2901
2905
  words: "null"
2902
2906
  }
2903
2907
  };
2908
+ /** Each kind's elements' type, and its kind in C (JS_SARRAY_*). */
2909
+ const ARRAY_ELEMS = {
2910
+ number: {
2911
+ type: T.Int32 | T.Double,
2912
+ c: "JS_SARRAY_NUMBER"
2913
+ },
2914
+ string: {
2915
+ type: T.String,
2916
+ c: "JS_SARRAY_STRING"
2917
+ },
2918
+ boolean: {
2919
+ type: T.Boolean,
2920
+ c: "JS_SARRAY_BOOLEAN"
2921
+ }
2922
+ };
2904
2923
  /** A declared parameter's type as ERR_INVALID_ARG_TYPE words it: "of type string or undefined",
2905
2924
  * "an instance of Float64Array". */
2906
2925
  function expectedText(t, view) {
@@ -3106,6 +3125,23 @@ const OPS = {
3106
3125
  allocates: true
3107
3126
  },
3108
3127
  math: pure(1),
3128
+ from_char_code: {
3129
+ ...pure(1),
3130
+ allocates: true
3131
+ },
3132
+ array_get: generic(2),
3133
+ array_set: {
3134
+ ...generic(3),
3135
+ result: false
3136
+ },
3137
+ array_length: {
3138
+ ...generic(1),
3139
+ callsUser: false
3140
+ },
3141
+ array_push: {
3142
+ ...generic(2),
3143
+ callsUser: false
3144
+ },
3109
3145
  int_add: pure(2),
3110
3146
  int_sub: pure(2),
3111
3147
  int_mul: pure(2),
@@ -3463,6 +3499,10 @@ function isExceptionalEdge(from, to) {
3463
3499
  }
3464
3500
  //#endregion
3465
3501
  //#region ir/src/builder.ts
3502
+ /** A literal's type. */
3503
+ function literalType(value) {
3504
+ return value === void 0 ? T.Undefined : value === null ? T.Null : typeof value === "boolean" ? T.Boolean : typeof value === "string" ? T.String : Number.isInteger(value) && Math.abs(value) <= 2147483647 && !Object.is(value, -0) ? T.Int32 : T.Double;
3505
+ }
3466
3506
  var FunctionBuilder = class {
3467
3507
  fn;
3468
3508
  current;
@@ -3579,10 +3619,9 @@ var FunctionBuilder = class {
3579
3619
  return instr;
3580
3620
  }
3581
3621
  const(value) {
3582
- const type = value === void 0 ? T.Undefined : value === null ? T.Null : typeof value === "boolean" ? T.Boolean : typeof value === "string" ? T.String : Number.isInteger(value) && Math.abs(value) <= 2147483647 && !Object.is(value, -0) ? T.Int32 : T.Double;
3583
3622
  return this.emit("const", [], {
3584
3623
  lit: { value },
3585
- type
3624
+ type: literalType(value)
3586
3625
  });
3587
3626
  }
3588
3627
  writeVariable(key, value, block = this.current) {
@@ -3798,6 +3837,10 @@ function printFunction(fn) {
3798
3837
  case "bigint": return `bigint ${i.bigint}n`;
3799
3838
  case "switch_string": return `switch_string ${name(i.operands[0])}, ${JSON.stringify(i.cases)}`;
3800
3839
  case "regexp": return `regexp /${i.regexp.pattern}/${i.regexp.flags}`;
3840
+ case "array_get":
3841
+ case "array_set":
3842
+ case "array_length":
3843
+ case "array_push": return `${i.op} ${i.elem}[] ${args}`;
3801
3844
  case "template_object": return `template_object ${JSON.stringify(i.template.cooked)}, slot ${i.index}`;
3802
3845
  case "import_meta": return `import_meta ${JSON.stringify(i.target)}, slot ${i.index}`;
3803
3846
  case "dynamic_import": return `dynamic_import ${args}, from ${JSON.stringify(i.target)}`;
@@ -4052,6 +4095,12 @@ function calleeText(e) {
4052
4095
  default: return "(intermediate value)";
4053
4096
  }
4054
4097
  }
4098
+ /** `a.push(v)` of a static array: one argument, no spread. */
4099
+ function isArrayPush(callee, e) {
4100
+ return callee.elem !== void 0 && !callee.computed && callee.property.name === "push" && e.arguments.length === 1 && e.arguments[0].type !== "SpreadElement";
4101
+ }
4102
+ /** A static array's element kind in the IR: an i32[]'s elements are Numbers its code converts. */
4103
+ const irElem = (elem) => elem === "i32" ? "number" : elem;
4055
4104
  function isConst(key) {
4056
4105
  return !("op" in key);
4057
4106
  }
@@ -4824,6 +4873,7 @@ var FunctionLowering = class {
4824
4873
  case "UpdateExpression": return this.isInt(e.argument);
4825
4874
  case "BinaryExpression": return INT_OPERATORS.has(e.operator) && this.isInt(e.left) && this.isInt(e.right);
4826
4875
  case "AssignmentExpression": return e.target.type === "Identifier" && this.isInt(e.target);
4876
+ case "MemberExpression": return e.computed && e.elem === "i32";
4827
4877
  case "ConditionalExpression": return this.isInt(e.consequent) && this.isInt(e.alternate);
4828
4878
  case "CallExpression": return e.callee.type === "Identifier" && declared(e.callee)?.returnsInt !== void 0;
4829
4879
  default: return false;
@@ -5754,9 +5804,10 @@ var FunctionLowering = class {
5754
5804
  };
5755
5805
  }
5756
5806
  const p = e.property;
5807
+ const elem = e.type === "MemberExpression" && e.elem && !(e.computed && p.type === "Literal" && typeof p.value === "string") ? { elem: e.elem } : {};
5757
5808
  let key;
5758
5809
  if (!e.computed) key = propKey(p.name);
5759
- else if (p.type === "Literal" && (typeof p.value === "string" || typeof p.value === "number")) key = propKey(p.value);
5810
+ else if (p.type === "Literal" && (typeof p.value === "string" || typeof p.value === "number") && !elem.elem) key = propKey(p.value);
5760
5811
  else key = this.expression(p);
5761
5812
  return superCallee ? {
5762
5813
  obj,
@@ -5764,7 +5815,8 @@ var FunctionLowering = class {
5764
5815
  superCallee
5765
5816
  } : {
5766
5817
  obj,
5767
- key
5818
+ key,
5819
+ ...elem
5768
5820
  };
5769
5821
  }
5770
5822
  getMember(ref) {
@@ -5777,6 +5829,11 @@ var FunctionLowering = class {
5777
5829
  ref.key
5778
5830
  ]);
5779
5831
  }
5832
+ if (ref.elem && !isConst(ref.key)) {
5833
+ const v = this.b.emit("array_get", [ref.obj, ref.key], { elem: irElem(ref.elem) });
5834
+ return ref.elem === "i32" ? this.toInt(v, "i32") : v;
5835
+ }
5836
+ if (ref.elem && "name" in ref.key && ref.key.name === "length") return this.b.emit("array_length", [ref.obj], { elem: irElem(ref.elem) });
5780
5837
  if (isConst(ref.key)) return this.b.emit("get_prop", [ref.obj], { key: ref.key });
5781
5838
  return this.b.emit("get_elem", [ref.obj, ref.key]);
5782
5839
  }
@@ -5803,7 +5860,12 @@ var FunctionLowering = class {
5803
5860
  ]);
5804
5861
  return;
5805
5862
  }
5806
- if (isConst(ref.key)) this.b.emit("set_prop", [ref.obj, value], { key: ref.key });
5863
+ if (ref.elem && !isConst(ref.key)) this.b.emit("array_set", [
5864
+ ref.obj,
5865
+ ref.key,
5866
+ ref.elem === "i32" ? this.toInt(value, "i32") : value
5867
+ ], { elem: irElem(ref.elem) });
5868
+ else if (isConst(ref.key)) this.b.emit("set_prop", [ref.obj, value], { key: ref.key });
5807
5869
  else this.b.emit("set_elem", [
5808
5870
  ref.obj,
5809
5871
  ref.key,
@@ -6046,6 +6108,12 @@ var FunctionLowering = class {
6046
6108
  call(e) {
6047
6109
  const b = this.b;
6048
6110
  const callee = e.callee;
6111
+ if (callee.type === "MemberExpression" && isArrayPush(callee, e)) {
6112
+ const obj = this.expression(callee.object);
6113
+ const v = this.expression(e.arguments[0]);
6114
+ b.loc = e.loc;
6115
+ return b.emit("array_push", [obj, callee.elem === "i32" ? this.toInt(v, "i32") : v], { elem: irElem(callee.elem) });
6116
+ }
6049
6117
  if (callee.type === "MemberExpression" || callee.type === "SuperMember") {
6050
6118
  const ref = this.memberRef(callee);
6051
6119
  b.loc = callee.loc;
@@ -7040,6 +7108,13 @@ var FunctionEmitter = class {
7040
7108
  const value = i.operands[2];
7041
7109
  return i.taView === "f64" && value.repr === "f64" ? `js_tav_put_f64${suffix}(ctx, ${view}, ${args[0]}, ${k}, ${this.as(value, "f64")}, ${strict})` : `js_tav_set_${i.taView}${suffix}(ctx, ${view}, ${args[0]}, ${k}, ${args[2]}, ${strict})`;
7042
7110
  }
7111
+ /** A static array's index, an int64_t: -1 for a Number that isn't an index. */
7112
+ arrayIndex(key) {
7113
+ if (key.op === "const" && Number.isSafeInteger(key.lit.value) && key.lit.value >= 0) return this.as(key, "i64");
7114
+ if (key.repr === "i32" || key.repr === "i64") return `(int64_t)${this.as(key, key.repr)}`;
7115
+ if (key.repr === "f64") return `js_sarray_index_f64(${this.as(key, "f64")})`;
7116
+ return `js_sarray_index(${this.v(key)})`;
7117
+ }
7043
7118
  /** A double read of a Float64Array's view: false from the access is an exception. */
7044
7119
  readDouble(i, args) {
7045
7120
  this.lines.push(` { double d; if (JS_UNLIKELY(!${this.viewAccess(i, args)})) { ${this.onException(i.block)} }`, this.hasVar(i) ? ` ${this.name(i)} = ${convert("d", "f64", i.repr)}; }` : " }");
@@ -7415,6 +7490,23 @@ var FunctionEmitter = class {
7415
7490
  case "construct_direct":
7416
7491
  this.constructDirect(i, args);
7417
7492
  return;
7493
+ case "from_char_code": {
7494
+ const c = i.operands[0];
7495
+ expr = `js_from_char_code_unit(ctx, (uint16_t)${c.repr === "i32" || c.repr === "i64" ? this.as(c, c.repr) : `js_f64_to_int32(${this.as(c, "f64")})`})`;
7496
+ break;
7497
+ }
7498
+ case "array_get":
7499
+ expr = `js_sarray_get(ctx, ${args[0]}, ${this.arrayIndex(i.operands[1])}, ${ARRAY_ELEMS[i.elem].c})`;
7500
+ break;
7501
+ case "array_set":
7502
+ status = `js_sarray_set(ctx, ${args[0]}, ${this.arrayIndex(i.operands[1])}, ${args[2]}, ${ARRAY_ELEMS[i.elem].c})`;
7503
+ break;
7504
+ case "array_length":
7505
+ expr = `js_sarray_length(ctx, ${args[0]})`;
7506
+ break;
7507
+ case "array_push":
7508
+ expr = `js_sarray_push(ctx, ${args[0]}, ${args[1]}, ${ARRAY_ELEMS[i.elem].c})`;
7509
+ break;
7418
7510
  case "math": {
7419
7511
  const f = {
7420
7512
  sqrt: "sqrt",
@@ -8589,6 +8681,7 @@ const REMOVABLE = /* @__PURE__ */ new Set([
8589
8681
  "construct_result",
8590
8682
  "char_code_at",
8591
8683
  "math",
8684
+ "from_char_code",
8592
8685
  "int_add",
8593
8686
  "int_sub",
8594
8687
  "int_mul",
@@ -8781,13 +8874,13 @@ function inlineBuiltin(i) {
8781
8874
  return null;
8782
8875
  }
8783
8876
  /** What typed code ("use static", which trusts the built-ins to be the standard ones) makes of a
8784
- * built-in call: s.charCodeAt(i) of a string, or Math's sqrt/abs/floor/ceil/trunc of a Number,
8785
- * the C helper's suffix; null for anything else. `type`: the values' types. */
8877
+ * built-in call: s.charCodeAt(i) of a string, or Math's sqrt/abs/floor/ceil/trunc or
8878
+ * String.fromCharCode of a Number, the C helper's suffix; null for anything else. `type`: the values' types. */
8786
8879
  function trustedBuiltin(i, type) {
8787
8880
  if (!isStatic(i.block.fn)) return null;
8788
8881
  const name = inlineBuiltin(i);
8789
8882
  if (name === "char_code_at") return isSubtype(type(i.operands[1]), T.String) ? name : null;
8790
- if (name?.startsWith("math_")) return isSubtype(type(i.operands[2]), Number_) ? name : null;
8883
+ if (name?.startsWith("math_") || name === "from_char_code") return isSubtype(type(i.operands[2]), Number_) ? name : null;
8791
8884
  return null;
8792
8885
  }
8793
8886
  /** The bitwise operators: ToInt32 (ToUint32) of their operands first. */
@@ -8922,6 +9015,9 @@ const specialize = {
8922
9015
  if (trusted === "char_code_at") {
8923
9016
  i.op = "char_code_at";
8924
9017
  i.operands = [i.operands[1], i.operands[2]];
9018
+ } else if (trusted === "from_char_code") {
9019
+ i.op = "from_char_code";
9020
+ i.operands = [i.operands[2]];
8925
9021
  } else {
8926
9022
  i.op = "math";
8927
9023
  i.target = trusted.slice(5);
@@ -9276,6 +9372,10 @@ function transfer(i, type, sig, bound = null) {
9276
9372
  if (readsDouble(i)) return T.Int32 | T.Double;
9277
9373
  if (i.taView && isStatic(i.block.fn)) return T.Int32 | T.Undefined;
9278
9374
  return Unknown;
9375
+ case "array_get": return ARRAY_ELEMS[i.elem].type;
9376
+ case "array_length":
9377
+ case "array_push": return T.Int32;
9378
+ case "from_char_code": return T.String;
9279
9379
  case "char_code_at":
9280
9380
  case "math": return Number_;
9281
9381
  case "int_add":
@@ -9668,6 +9768,7 @@ function constructorSlots(fn) {
9668
9768
  const promoteGlobals = {
9669
9769
  name: "promote-globals",
9670
9770
  run(m, count) {
9771
+ if (isStatic(m.main)) count("folded", "constant", foldConstants(m));
9671
9772
  const shared = /* @__PURE__ */ new Set();
9672
9773
  for (const fn of functionsOf(m)) for (const b of fn.blocks) for (const i of b.instrs) if ((i.op === "load_global" || i.op === "store_global") && fn !== m.main || i.op === "template_object" || i.op === "import_meta") shared.add(i.index);
9673
9774
  const slots = /* @__PURE__ */ new Set();
@@ -9766,6 +9867,44 @@ function promote(fn, slots, m) {
9766
9867
  removeInstrs(fn, dead);
9767
9868
  return slots.size;
9768
9869
  }
9870
+ /** A stored value that is a literal: a const, or an integer literal an int (i32) binding converts
9871
+ * to itself. */
9872
+ function literal(v) {
9873
+ if (v.op === "const") return v.lit.value;
9874
+ const c = v.operands[0];
9875
+ if (c?.op !== "const" || typeof c.lit.value !== "number") return NOT_LITERAL;
9876
+ const n = c.lit.value;
9877
+ if (v.op === "to_i64" && Number.isSafeInteger(n)) return n;
9878
+ if (v.op === "to_i32" && (n | 0) === n) return n;
9879
+ return NOT_LITERAL;
9880
+ }
9881
+ const NOT_LITERAL = Symbol("not a literal");
9882
+ /** Static code's constant module bindings, as literals in the functions that read them. */
9883
+ function foldConstants(m) {
9884
+ const stores = /* @__PURE__ */ new Map();
9885
+ for (const fn of functionsOf(m)) for (const b of fn.blocks) for (const i of b.instrs) if (i.op === "store_global" && i.operands[0].op !== "empty") stores.set(i.index, (stores.get(i.index) ?? 0) + 1);
9886
+ const constants = /* @__PURE__ */ new Map();
9887
+ for (const i of m.main.blocks[0].instrs) {
9888
+ if (OPS[i.op].callsUser) break;
9889
+ if (i.op !== "store_global" || stores.get(i.index) !== 1) continue;
9890
+ const value = literal(i.operands[0]);
9891
+ if (value !== NOT_LITERAL) constants.set(i.index, value);
9892
+ }
9893
+ let folded = 0;
9894
+ for (const fn of m.functions) for (const b of fn.blocks) for (const i of b.instrs) {
9895
+ if (i.op !== "load_global" || !constants.has(i.index)) continue;
9896
+ const value = constants.get(i.index);
9897
+ Object.assign(i, {
9898
+ op: "const",
9899
+ operands: [],
9900
+ lit: { value },
9901
+ type: literalType(value),
9902
+ index: void 0
9903
+ });
9904
+ folded++;
9905
+ }
9906
+ return folded;
9907
+ }
9769
9908
  //#endregion
9770
9909
  //#region optimizer/src/simplify.ts
9771
9910
  const NUMERIC = /* @__PURE__ */ new Set([
@@ -10883,6 +11022,7 @@ const LLHTTP = join(DIR, "third_party", "llhttp");
10883
11022
  const ZLIB = join(DIR, "third_party", "zlib");
10884
11023
  const BROTLI = join(DIR, "third_party", "brotli");
10885
11024
  const ZSTD = join(DIR, "third_party", "zstd");
11025
+ const CARES = join(DIR, "third_party", "c-ares");
10886
11026
  const INCLUDE = join(DIR, "include");
10887
11027
  const files$1 = (dir, ext) => readdirSync(dir).filter((f) => f.endsWith(ext)).map((f) => join(dir, f));
10888
11028
  /** Prelude modules may import "visaljs:host". */
@@ -10911,6 +11051,7 @@ const modules = {
10911
11051
  inspector: join(preludeDir, "inspector.js"),
10912
11052
  "inspector/promises": join(preludeDir, "inspector_promises.js"),
10913
11053
  module: join(preludeDir, "module.js"),
11054
+ dgram: join(preludeDir, "dgram.js"),
10914
11055
  net: join(preludeDir, "net.js"),
10915
11056
  os: join(preludeDir, "os.js"),
10916
11057
  path: join(preludeDir, "path.js"),
@@ -10926,6 +11067,7 @@ const modules = {
10926
11067
  sea: join(preludeDir, "sea.js"),
10927
11068
  stream: join(preludeDir, "stream.js"),
10928
11069
  _http_agent: join(preludeDir, "_http_agent.js"),
11070
+ _http_common: join(preludeDir, "_http_common.js"),
10929
11071
  _http_server: join(preludeDir, "_http_server.js"),
10930
11072
  _stream_duplex: join(preludeDir, "_stream_duplex.js"),
10931
11073
  _stream_passthrough: join(preludeDir, "_stream_passthrough.js"),
@@ -10968,6 +11110,14 @@ const implicitModules = [
10968
11110
  file: join(preludeDir, "internal", "process_stdio.js"),
10969
11111
  reached: (_code, program) => /\b(?:stdout|stderr)\b/.test(program) && STDIO_STREAM_USE.test(program)
10970
11112
  },
11113
+ {
11114
+ file: join(preludeDir, "internal", "console_global.js"),
11115
+ reached: (_code, program) => STDIO_WRITE_REPLACED.test(program)
11116
+ },
11117
+ {
11118
+ file: join(preludeDir, "internal", "console_class.js"),
11119
+ reached: (_code, program) => /\bConsole\b/.test(program)
11120
+ },
10971
11121
  {
10972
11122
  file: join(preludeDir, "internal", "process_stdin.js"),
10973
11123
  reached: (_code, program) => /\bstdin\b/.test(program)
@@ -11014,7 +11164,7 @@ const implicitModules = [
11014
11164
  },
11015
11165
  {
11016
11166
  file: join(preludeDir, "internal", "events_on.js"),
11017
- reached: (_code, program) => EVENTS_ON.test(program)
11167
+ reached: (_code, program) => EVENTS_ON.test(program) || /readline|readLines|createInterface/i.test(program) && /\bfor\s+await\b|\basyncIterator\b/.test(program)
11018
11168
  },
11019
11169
  {
11020
11170
  file: join(preludeDir, "internal", "stream_compose.js"),
@@ -11104,6 +11254,18 @@ const implicitModules = [
11104
11254
  file: join(preludeDir, "internal", "fs_filehandle.js"),
11105
11255
  reached: (_code, program) => FS_OPEN.test(program) || /\bFileHandle\b/.test(program) || /\bpromises\b/.test(program) && /\.\s*open\s*\(/.test(program)
11106
11256
  },
11257
+ {
11258
+ file: join(preludeDir, "internal", "readline_editor.js"),
11259
+ reached: (_code, program) => READLINE_EDITOR.test(program) || /readline|createInterface/i.test(program) && /\b(?:stdin|terminal)\b/.test(program)
11260
+ },
11261
+ {
11262
+ file: join(preludeDir, "internal", "dns_resolver.js"),
11263
+ reached: (_code, program) => DNS_RESOLVER.test(program) || DNS_RESOLVE_RRTYPE.test(program) || DNS_MODULE_RESOLVE.test(program)
11264
+ },
11265
+ {
11266
+ file: join(preludeDir, "internal", "crypto_x509.js"),
11267
+ reached: (_code, program) => /\b(?:X509Certificate|get(?:Peer)?X509Certificate)\b/.test(program)
11268
+ },
11107
11269
  {
11108
11270
  file: join(preludeDir, "internal", "process_more.js"),
11109
11271
  reached: (_code, program) => PROCESS_MORE.test(program)
@@ -11147,6 +11309,11 @@ const implicitModules = [
11147
11309
  ];
11148
11310
  const FETCH = /(?<![.\w$#])fetch\s*\(|[=(,]\s*fetch\s*[;,)\n]|\btypeof\s+fetch\b|\b(?:globalThis|global|self)\s*(?:\.\s*fetch\b|\[\s*["'`]fetch["'`])/;
11149
11311
  const STREAM_OPERATORS = /\.\s*(?:flatMap|toArray|drop|take|asIndexedPairs)\s*\(|\bReadable\b[\s\S]*\.\s*(?:map|filter|forEach|reduce|some|every|find)\s*\(/;
11312
+ const DNS_RESOLVER = /\b(?:Resolver|resolve(?:4|6|Any|Caa|Cname|Mx|Naptr|Ns|Ptr|Soa|Srv|Tlsa|Txt)|getServers|setServers|setLocalAddress)\b/;
11313
+ const READLINE_EDITOR = /\b(?:emitKeypressEvents|setRawMode|keypress|completer)\b/;
11314
+ const DNS_MODULE_RESOLVE = /\b(?:dns|dns_default|require_dns\(\))\s*\.\s*(?:promises\s*\.\s*)?(?:resolve|reverse)\b/;
11315
+ const DNS_RESOLVE_RRTYPE = /\.\s*resolve\s*\([^,()]+,\s*["'`](?:A|AAAA|ANY|CAA|CNAME|MX|NAPTR|NS|PTR|SOA|SRV|TLSA|TXT)["'`]/;
11316
+ const STDIO_WRITE_REPLACED = /\b(?:stdout|stderr|stream)\s*\.\s*write\s*=(?![=>])|\b_std(?:out|err)\s*=(?!=)|\b(?:channel|subscribe)\s*\(\s*["'`]console\.(?:log|info|debug|warn|error)["'`]/;
11150
11317
  const STDIO_STREAM_USE = /\.\s*(?:pipe|on|once|end|cork|uncork|destroy|removeListener|addListener|prependListener)\s*\(|\b(?:pipeline|finished)\b|\bwritable(?:Length|HighWaterMark|NeedDrain|Ended|Finished)\b/;
11151
11318
  const PROCESS_DISTINCT = "chdir|umask|uptime|cpuUsage|threadCpuUsage|resourceUsage|availableMemory|constrainedMemory|setuid|setgid|seteuid|setegid|getgroups|setgroups|initgroups|reallyExit|execve|getBuiltinModule|loadEnvFile|hasUncaughtExceptionCaptureCallback|setUncaughtExceptionCaptureCallback|allowedNodeEnvironmentFlags|setSourceMapsEnabled|sourceMapsEnabled|getActiveResourcesInfo|moduleLoadList|openStdin|debugPort|dlopen";
11152
11319
  const PROCESS_COMMON = "title|ppid|release|config|ref|unref|abort|report|domain|assert|binding|finalization";
@@ -11423,10 +11590,6 @@ const primitives = {
11423
11590
  c: "js_host_os_homedir",
11424
11591
  length: 0
11425
11592
  },
11426
- osTmpdir: {
11427
- c: "js_host_os_tmpdir",
11428
- length: 0
11429
- },
11430
11593
  osMemory: {
11431
11594
  c: "js_host_os_memory",
11432
11595
  length: 0
@@ -11495,6 +11658,10 @@ const primitives = {
11495
11658
  c: "js_util_inspect",
11496
11659
  length: 2
11497
11660
  },
11661
+ previewEntries: {
11662
+ c: "js_host_preview_entries",
11663
+ length: 2
11664
+ },
11498
11665
  utilFormat: {
11499
11666
  c: "js_util_format",
11500
11667
  length: 0
@@ -11715,6 +11882,26 @@ const primitives = {
11715
11882
  c: "js_tls_context_set_key",
11716
11883
  length: 2
11717
11884
  },
11885
+ tlsContextAddCredential: {
11886
+ c: "js_tls_context_add_credential",
11887
+ length: 3
11888
+ },
11889
+ tlsContextAllowPartialChain: {
11890
+ c: "js_tls_context_allow_partial_chain",
11891
+ length: 1
11892
+ },
11893
+ tlsContextTicketKeys: {
11894
+ c: "js_tls_context_ticket_keys",
11895
+ length: 2
11896
+ },
11897
+ tlsContextSetSessions: {
11898
+ c: "js_tls_context_set_sessions",
11899
+ length: 3
11900
+ },
11901
+ tlsPkcs12: {
11902
+ c: "js_tls_pkcs12",
11903
+ length: 2
11904
+ },
11718
11905
  tlsRootCertificates: {
11719
11906
  c: "js_tls_root_certificates",
11720
11907
  length: 0
@@ -11723,6 +11910,18 @@ const primitives = {
11723
11910
  c: "js_tls_ciphers",
11724
11911
  length: 0
11725
11912
  },
11913
+ x509Check: {
11914
+ c: "js_x509_check",
11915
+ length: 4
11916
+ },
11917
+ x509CheckIssued: {
11918
+ c: "js_x509_check_issued",
11919
+ length: 2
11920
+ },
11921
+ x509CheckKey: {
11922
+ c: "js_x509_check_key",
11923
+ length: 2
11924
+ },
11726
11925
  tlsNew: {
11727
11926
  c: "js_tls_new",
11728
11927
  length: 7
@@ -11751,6 +11950,10 @@ const primitives = {
11751
11950
  c: "js_tls_session",
11752
11951
  length: 1
11753
11952
  },
11953
+ tlsTicket: {
11954
+ c: "js_tls_ticket",
11955
+ length: 1
11956
+ },
11754
11957
  tlsExportKeyingMaterial: {
11755
11958
  c: "js_tls_export_keying_material",
11756
11959
  length: 4
@@ -11759,6 +11962,14 @@ const primitives = {
11759
11962
  c: "js_tls_set_no_renegotiation",
11760
11963
  length: 1
11761
11964
  },
11965
+ tlsEnableKeylog: {
11966
+ c: "js_tls_enable_keylog",
11967
+ length: 1
11968
+ },
11969
+ tlsSetMaxSendFragment: {
11970
+ c: "js_tls_set_max_send_fragment",
11971
+ length: 2
11972
+ },
11762
11973
  tlsFinished: {
11763
11974
  c: "js_tls_finished",
11764
11975
  length: 2
@@ -11787,6 +11998,10 @@ const primitives = {
11787
11998
  c: "js_host_http_pending",
11788
11999
  length: 1
11789
12000
  },
12001
+ httpWritten: {
12002
+ c: "js_host_http_written",
12003
+ length: 1
12004
+ },
11790
12005
  httpWatchDrain: {
11791
12006
  c: "js_host_http_watch_drain",
11792
12007
  length: 1
@@ -11819,6 +12034,94 @@ const primitives = {
11819
12034
  c: "js_host_http_date",
11820
12035
  length: 0
11821
12036
  },
12037
+ udpOpen: {
12038
+ c: "js_host_udp_open",
12039
+ length: 1
12040
+ },
12041
+ udpOpenFd: {
12042
+ c: "js_host_udp_open_fd",
12043
+ length: 2
12044
+ },
12045
+ udpFd: {
12046
+ c: "js_host_udp_fd",
12047
+ length: 1
12048
+ },
12049
+ udpBind: {
12050
+ c: "js_host_udp_bind",
12051
+ length: 4
12052
+ },
12053
+ udpConnect: {
12054
+ c: "js_host_udp_connect",
12055
+ length: 3
12056
+ },
12057
+ udpDisconnect: {
12058
+ c: "js_host_udp_disconnect",
12059
+ length: 1
12060
+ },
12061
+ udpSend: {
12062
+ c: "js_host_udp_send",
12063
+ length: 4
12064
+ },
12065
+ udpSendQueue: {
12066
+ c: "js_host_udp_send_queue",
12067
+ length: 2
12068
+ },
12069
+ udpRecvStart: {
12070
+ c: "js_host_udp_recv_start",
12071
+ length: 1
12072
+ },
12073
+ udpRecvStop: {
12074
+ c: "js_host_udp_recv_stop",
12075
+ length: 1
12076
+ },
12077
+ udpAddress: {
12078
+ c: "js_host_udp_address",
12079
+ length: 2
12080
+ },
12081
+ udpSetBroadcast: {
12082
+ c: "js_host_udp_set_broadcast",
12083
+ length: 2
12084
+ },
12085
+ udpSetTTL: {
12086
+ c: "js_host_udp_set_ttl",
12087
+ length: 2
12088
+ },
12089
+ udpSetMulticastTTL: {
12090
+ c: "js_host_udp_set_multicast_ttl",
12091
+ length: 2
12092
+ },
12093
+ udpSetMulticastLoopback: {
12094
+ c: "js_host_udp_set_multicast_loopback",
12095
+ length: 2
12096
+ },
12097
+ udpSetMulticastInterface: {
12098
+ c: "js_host_udp_set_multicast_interface",
12099
+ length: 2
12100
+ },
12101
+ udpMembership: {
12102
+ c: "js_host_udp_membership",
12103
+ length: 4
12104
+ },
12105
+ udpSourceMembership: {
12106
+ c: "js_host_udp_source_membership",
12107
+ length: 5
12108
+ },
12109
+ udpBufferSize: {
12110
+ c: "js_host_udp_buffer_size",
12111
+ length: 3
12112
+ },
12113
+ udpClose: {
12114
+ c: "js_host_udp_close",
12115
+ length: 1
12116
+ },
12117
+ udpRef: {
12118
+ c: "js_host_udp_ref",
12119
+ length: 2
12120
+ },
12121
+ udpHasRef: {
12122
+ c: "js_host_udp_has_ref",
12123
+ length: 1
12124
+ },
11822
12125
  netOpen: {
11823
12126
  c: "js_host_net_open",
11824
12127
  length: 2
@@ -11911,6 +12214,46 @@ const primitives = {
11911
12214
  c: "js_host_dns_lookup",
11912
12215
  length: 3
11913
12216
  },
12217
+ dnsLookupService: {
12218
+ c: "js_host_dns_lookup_service",
12219
+ length: 3
12220
+ },
12221
+ dnsChannel: {
12222
+ c: "js_host_dns_channel",
12223
+ length: 3
12224
+ },
12225
+ dnsQuery: {
12226
+ c: "js_host_dns_query",
12227
+ length: 4
12228
+ },
12229
+ dnsReverse: {
12230
+ c: "js_host_dns_reverse",
12231
+ length: 3
12232
+ },
12233
+ dnsParse: {
12234
+ c: "js_host_dns_parse",
12235
+ length: 2
12236
+ },
12237
+ dnsGetServers: {
12238
+ c: "js_host_dns_get_servers",
12239
+ length: 1
12240
+ },
12241
+ dnsSetServers: {
12242
+ c: "js_host_dns_set_servers",
12243
+ length: 2
12244
+ },
12245
+ dnsSetLocalAddress: {
12246
+ c: "js_host_dns_set_local_address",
12247
+ length: 3
12248
+ },
12249
+ dnsCancel: {
12250
+ c: "js_host_dns_cancel",
12251
+ length: 1
12252
+ },
12253
+ dnsStrerror: {
12254
+ c: "js_host_dns_strerror",
12255
+ length: 1
12256
+ },
11914
12257
  zlibNew: {
11915
12258
  c: "js_host_zlib_new",
11916
12259
  length: 1
@@ -12082,6 +12425,21 @@ const UV_PLATFORM = {
12082
12425
  ]
12083
12426
  }
12084
12427
  };
12428
+ const CARES_DIRS = [
12429
+ "",
12430
+ "dsa",
12431
+ "event",
12432
+ "legacy",
12433
+ "record",
12434
+ "str",
12435
+ "util"
12436
+ ].map((d) => join(CARES, "src", "lib", d));
12437
+ const CARES_CONFIG = {
12438
+ linux: "linux",
12439
+ darwin: "darwin",
12440
+ freebsd: "freebsd",
12441
+ openbsd: "openbsd"
12442
+ };
12085
12443
  const BROTLI_OS = {
12086
12444
  linux: "OS_LINUX",
12087
12445
  darwin: "OS_MACOSX",
@@ -12105,6 +12463,13 @@ function libraries(runtimeInclude, platform = process.platform) {
12105
12463
  "compress",
12106
12464
  "decompress"
12107
12465
  ].flatMap((d) => files$1(join(ZSTD, d), ".h"));
12466
+ const caresHeaders = [
12467
+ ...files$1(join(CARES, "include"), ".h"),
12468
+ ...CARES_DIRS.flatMap((d) => files$1(d, ".h")),
12469
+ ...files$1(join(CARES, "src", "lib", "include"), ".h"),
12470
+ ...files$1(join(CARES, "src", "lib", "thirdparty", "apple"), ".h"),
12471
+ ...CARES_CONFIG[platform] ? files$1(join(CARES, "config", CARES_CONFIG[platform]), ".h") : []
12472
+ ];
12108
12473
  const uvHeaders = [
12109
12474
  join(UV, "include"),
12110
12475
  join(UV, "include", "uv"),
@@ -12123,7 +12488,8 @@ function libraries(runtimeInclude, platform = process.platform) {
12123
12488
  ...uvHeaders,
12124
12489
  ...zlibHeaders,
12125
12490
  ...brotliHeaders,
12126
- ...zstdHeaders
12491
+ ...zstdHeaders,
12492
+ ...caresHeaders
12127
12493
  ],
12128
12494
  flags: [
12129
12495
  `-I${INCLUDE}`,
@@ -12132,7 +12498,10 @@ function libraries(runtimeInclude, platform = process.platform) {
12132
12498
  `-I${join(UV, "include")}`,
12133
12499
  `-I${ZLIB}`,
12134
12500
  `-I${join(BROTLI, "include")}`,
12135
- `-I${ZSTD}`
12501
+ `-I${ZSTD}`,
12502
+ `-I${join(CARES, "include")}`,
12503
+ "-DCARES_STATICLIB",
12504
+ "-DCARES_NO_DEPRECATED"
12136
12505
  ]
12137
12506
  },
12138
12507
  {
@@ -12176,6 +12545,32 @@ function libraries(runtimeInclude, platform = process.platform) {
12176
12545
  `-I${ZSTD}`
12177
12546
  ]
12178
12547
  },
12548
+ {
12549
+ name: "cares",
12550
+ sources: CARES_DIRS.flatMap((d) => files$1(d, ".c")),
12551
+ headers: caresHeaders,
12552
+ flags: [
12553
+ "-std=gnu11",
12554
+ "-w",
12555
+ "-DCARES_STATICLIB",
12556
+ "-D_LARGEFILE_SOURCE",
12557
+ "-D_FILE_OFFSET_BITS=64",
12558
+ ...platform === "win32" ? ["-DCARES_PULL_WS2TCPIP_H=1", "-D_WINSOCK_DEPRECATED_NO_WARNINGS"] : [
12559
+ "-DHAVE_CONFIG_H",
12560
+ "-D_GNU_SOURCE",
12561
+ "-D_DARWIN_USE_64_BIT_INODE=1"
12562
+ ],
12563
+ ...CARES_CONFIG[platform] ? [`-I${join(CARES, "config", CARES_CONFIG[platform])}`] : [],
12564
+ `-I${join(CARES, "include")}`,
12565
+ `-I${join(CARES, "src", "lib")}`,
12566
+ `-I${join(CARES, "src", "lib", "include")}`
12567
+ ],
12568
+ link: platform === "win32" ? [
12569
+ "ws2_32",
12570
+ "iphlpapi",
12571
+ "advapi32"
12572
+ ] : []
12573
+ },
12179
12574
  {
12180
12575
  name: "uv",
12181
12576
  sources: uvSources,
@@ -12233,6 +12628,12 @@ const notices$1 = [
12233
12628
  license: "BSD-3-Clause",
12234
12629
  files: [join(ZSTD, "LICENSE")]
12235
12630
  },
12631
+ {
12632
+ name: "c-ares",
12633
+ what: "dns.Resolver's DNS queries",
12634
+ license: "MIT",
12635
+ files: [join(CARES, "LICENSE.md")]
12636
+ },
12236
12637
  {
12237
12638
  name: "punycode.js",
12238
12639
  what: "node:punycode",
@@ -12290,10 +12691,15 @@ const INT_PARAMETERS = {
12290
12691
  function declaredSignatures(checker, sf, out) {
12291
12692
  for (const st of sf.statements) {
12292
12693
  if (!ts.isFunctionDeclaration(st) || !st.name) continue;
12694
+ const arrays = [];
12293
12695
  const types = st.parameters.map((p) => {
12294
12696
  const kind = intKind(checker, p.type);
12295
12697
  if (kind) return INT_PARAMETERS[kind];
12296
12698
  const type = checker.getTypeAtLocation(p);
12699
+ if (checker.isArrayType(type)) {
12700
+ arrays.push(p);
12701
+ return T.Object;
12702
+ }
12297
12703
  const t = irType(type);
12298
12704
  if (t === null) throw compileError(p, `parameter '${p.name.getText(sf)}' of '${st.name.text}': ${checker.typeToString(type)} isn't a static type yet`);
12299
12705
  return t;
@@ -12301,7 +12707,8 @@ function declaredSignatures(checker, sf, out) {
12301
12707
  const views = st.parameters.map((p) => viewOf(checker.getTypeAtLocation(p).getSymbol()?.name ?? ""));
12302
12708
  out.set(locKey(st), {
12303
12709
  types,
12304
- views
12710
+ views,
12711
+ arrays
12305
12712
  });
12306
12713
  }
12307
12714
  }
@@ -12328,6 +12735,56 @@ function irType(t) {
12328
12735
  if (name) return STATIC_TYPES[name].type;
12329
12736
  return viewOf(t.getSymbol()?.name ?? "") ? T.Object : null;
12330
12737
  }
12738
+ /** The primitive every part of a type is (its literals too), by the name an array's element kind has. */
12739
+ function primitiveOf(t) {
12740
+ const parts = t.isUnion() ? t.types : [t];
12741
+ for (const [flags, name] of [
12742
+ [ts.TypeFlags.NumberLike, "number"],
12743
+ [ts.TypeFlags.StringLike, "string"],
12744
+ [ts.TypeFlags.BooleanLike, "boolean"]
12745
+ ]) if (parts.every((p) => p.flags & flags)) return name;
12746
+ }
12747
+ /** The element type an array type annotation writes (T[], Array<T>, readonly T[], an alias of one). */
12748
+ function elementNode(checker, node) {
12749
+ if (!node) return void 0;
12750
+ if (ts.isArrayTypeNode(node)) return node.elementType;
12751
+ if (ts.isTypeOperatorNode(node) || ts.isParenthesizedTypeNode(node)) return elementNode(checker, node.type);
12752
+ if (!ts.isTypeReferenceNode(node)) return void 0;
12753
+ const name = node.typeName.getText();
12754
+ if ((name === "Array" || name === "ReadonlyArray") && node.typeArguments?.length === 1) return node.typeArguments[0];
12755
+ let symbol = checker.getSymbolAtLocation(node.typeName);
12756
+ if (symbol && symbol.flags & ts.SymbolFlags.Alias) symbol = checker.getAliasedSymbol(symbol);
12757
+ const declaration = symbol?.declarations?.[0];
12758
+ return declaration && ts.isTypeAliasDeclaration(declaration) ? elementNode(checker, declaration.type) : void 0;
12759
+ }
12760
+ /** The array type annotation an expression's value was declared with, if one says: a variable's
12761
+ * or parameter's (or its initializer's), a call's declared return type, a cast's. */
12762
+ function declaredArrayType(checker, node) {
12763
+ if (ts.isParenthesizedExpression(node) || ts.isNonNullExpression(node)) return declaredArrayType(checker, node.expression);
12764
+ if (ts.isAsExpression(node) || ts.isSatisfiesExpression(node)) return node.type;
12765
+ if (ts.isCallExpression(node)) {
12766
+ const declaration = checker.getResolvedSignature(node)?.getDeclaration();
12767
+ return declaration && !ts.isJSDocSignature(declaration) ? declaration.type : void 0;
12768
+ }
12769
+ if (!ts.isIdentifier(node)) return void 0;
12770
+ const declaration = checker.getSymbolAtLocation(node)?.valueDeclaration;
12771
+ if (!declaration || !(ts.isVariableDeclaration(declaration) || ts.isParameter(declaration))) return void 0;
12772
+ if (declaration.type) return declaration.type;
12773
+ return declaration.initializer ? declaredArrayType(checker, declaration.initializer) : void 0;
12774
+ }
12775
+ /** The element kind of the array `node` is, if it is one: number, i32 (the annotation names it:
12776
+ * tsc erases it to number), string, boolean; an array of anything else is an error. */
12777
+ function arrayElement(checker, node) {
12778
+ const type = checker.getTypeAtLocation(node);
12779
+ if (!checker.isArrayType(type)) return void 0;
12780
+ const element = checker.getTypeArguments(type)[0];
12781
+ const kind = primitiveOf(element);
12782
+ if (!kind) throw compileError(node, `static code doesn't have arrays of ${checker.typeToString(element)} yet`);
12783
+ if (kind !== "number") return kind;
12784
+ const int = intKind(checker, elementNode(checker, declaredArrayType(checker, node)));
12785
+ if (int === "i64") throw compileError(node, "static code doesn't have int[] yet: an i32[], or a number[]");
12786
+ return int ?? "number";
12787
+ }
12331
12788
  //#endregion
12332
12789
  //#region cli/src/static/link.ts
12333
12790
  /** A file's name in locations, as the program's: relative to the working directory. */
@@ -12420,7 +12877,8 @@ function linkUnit(program, files, hostPrimitives) {
12420
12877
  },
12421
12878
  linked: (node) => importedFile(checker, node, fileSet) !== void 0,
12422
12879
  fileName,
12423
- intKind: (type) => intKind(checker, type)
12880
+ intKind: (type) => intKind(checker, type),
12881
+ arrayElement: (node) => arrayElement(checker, node)
12424
12882
  };
12425
12883
  const exports = /* @__PURE__ */ new Map();
12426
12884
  const exportedFrom = /* @__PURE__ */ new Map();
@@ -12892,7 +13350,7 @@ function findCompilers() {
12892
13350
  "gcc",
12893
13351
  "zig cc"
12894
13352
  ]) {
12895
- const path = onPath(command(cc)[0]);
13353
+ const path = onPath(compilerCommand(cc)[0]);
12896
13354
  if (path && !found.has(path) && compilerVersion(cc)) found.set(path, cc);
12897
13355
  }
12898
13356
  if (found.size === 0) throw new Error("no C compiler found (set CC)");
@@ -12915,24 +13373,29 @@ const COMMON = [
12915
13373
  ];
12916
13374
  const LINK = process.platform === "darwin" ? ["-Wl,-dead_strip"] : ["-Wl,--gc-sections"];
12917
13375
  const STRIP = process.platform === "darwin" ? ["-Wl,-S,-x"] : ["-s"];
12918
- /** A compiler's command line, split like make splits $(CC): "zig cc", "ccache gcc". */
12919
- function command(cc) {
13376
+ /** The link's flags that write its map to `file`: ld64's, the format size.ts reads. */
13377
+ const linkMapFlags = (file) => [`-Wl,-map,${file}`];
13378
+ /** A compiler's command line, split like make splits $(CC): "zig cc", "ccache gcc". Zig gets
13379
+ * -mcpu=baseline unless $(CC) names a CPU: its default is this machine's CPU, so what it builds
13380
+ * (a cached library, a program shipped elsewhere) would crash on an older one. */
13381
+ function compilerCommand(cc) {
12920
13382
  const [program = cc, ...args] = cc.trim().split(/\s+/);
13383
+ if (/^zig(\.exe)?$/i.test(basename(program)) && !args.some((a) => /^-m(cpu|arch)=/.test(a))) args.push("-mcpu=baseline");
12921
13384
  return [program, ...args];
12922
13385
  }
12923
13386
  function runCompiler(cc, args, options) {
12924
- const [program, ...prefix] = command(cc);
13387
+ const [program, ...prefix] = compilerCommand(cc);
12925
13388
  return execFileSync(program, [...prefix, ...args], options);
12926
13389
  }
12927
13390
  /** Zig compiles C with its clang, and archives with its own ar: a machine without a C
12928
13391
  * toolchain usually lacks binutils' ar too. */
12929
13392
  function isZig(cc) {
12930
- return /^zig(\.exe)?$/i.test(basename(command(cc)[0]));
13393
+ return /^zig(\.exe)?$/i.test(basename(compilerCommand(cc)[0]));
12931
13394
  }
12932
13395
  /** "GCC 13.3.0", "clang 18.1.3", "Zig 0.16.0": the compiler's name and version, else its command. */
12933
13396
  function describeCompiler(cc) {
12934
13397
  if (isZig(cc)) try {
12935
- return `Zig ${execFileSync(command(cc)[0], ["version"], { encoding: "utf8" }).trim()}`;
13398
+ return `Zig ${execFileSync(compilerCommand(cc)[0], ["version"], { encoding: "utf8" }).trim()}`;
12936
13399
  } catch {
12937
13400
  return cc;
12938
13401
  }
@@ -12964,7 +13427,7 @@ function libraryArchive(tc, lib, building) {
12964
13427
  const prebuilt = prebuiltArchive(tc, lib);
12965
13428
  if (prebuilt) return prebuilt;
12966
13429
  const hash = createHash("sha256");
12967
- hash.update(`${tc.cc}\n${compilerVersion(tc.cc)}\n${[
13430
+ hash.update(`${compilerCommand(tc.cc).join(" ")}\n${compilerVersion(tc.cc)}\n${[
12968
13431
  ...COMMON,
12969
13432
  ...CXX,
12970
13433
  ...tc.opt,
@@ -13010,7 +13473,7 @@ function buildArchive(cc, lib, archive, { common = COMMON, flags = [], arFlags =
13010
13473
  "-o",
13011
13474
  join(objects, outputs[i])
13012
13475
  ]));
13013
- const [ar, ...arPrefix] = isZig(cc) ? [command(cc)[0], "ar"] : ["ar"];
13476
+ const [ar, ...arPrefix] = isZig(cc) ? [compilerCommand(cc)[0], "ar"] : ["ar"];
13014
13477
  execFileSync(ar, [
13015
13478
  ...arPrefix,
13016
13479
  ...arFlags,
@@ -13038,8 +13501,8 @@ const cxx = (common) => [
13038
13501
  ];
13039
13502
  const CXX = cxx(COMMON);
13040
13503
  function compileCommand(cc, src, common) {
13041
- if (!src.endsWith(".cc")) return [...command(cc), ...common];
13042
- const cmd = command(cc);
13504
+ if (!src.endsWith(".cc")) return [...compilerCommand(cc), ...common];
13505
+ const cmd = compilerCommand(cc);
13043
13506
  if (isZig(cc)) return [...cmd.map((w) => w === "cc" ? "c++" : w), ...cxx(common)];
13044
13507
  return [
13045
13508
  ...cmd,
@@ -13131,7 +13594,7 @@ function regexpCompiler(cc) {
13131
13594
  join(RUNTIME_DIR, "src", "regexp_anchor.h"),
13132
13595
  ...readdirSync(regexp).filter((f) => f.endsWith(".h")).map((f) => join(regexp, f))
13133
13596
  ];
13134
- const hash = createHash("sha256").update(`${cc}\n`);
13597
+ const hash = createHash("sha256").update(`${compilerCommand(cc).join(" ")}\n`);
13135
13598
  for (const f of [...sources, ...headers]) hash.update(f.slice(RUNTIME_DIR.length)).update(readFileSync(f));
13136
13599
  const tool = join(cacheRoot(), `regexp-compile-${hash.digest("hex").slice(0, 16)}${process.platform === "win32" ? ".exe" : ""}`);
13137
13600
  if (existsSync(tool)) return tool;
@@ -13156,14 +13619,18 @@ function regexpCompiler(cc) {
13156
13619
  /** A program's archives, in link order: the host packages' libraries, then libjsrt (which they
13157
13620
  * use), then the system libraries they need (-lโ€ฆ). Each is built the first time; `building`
13158
13621
  * hears about it. */
13622
+ function programLibraries(hosts) {
13623
+ return [...hosts.flatMap((h) => h.libraries(RUNTIME_INCLUDE)).filter((l) => l.sources.length), ...runtimeLibraries()];
13624
+ }
13159
13625
  function programArchives(tc, hosts, building) {
13160
- const libraries = [...hosts.flatMap((h) => h.libraries(RUNTIME_INCLUDE)).filter((l) => l.sources.length), ...runtimeLibraries()];
13626
+ const libraries = programLibraries(hosts);
13161
13627
  return [...libraries.map((l) => libraryArchive(tc, l, building)), ...libraries.flatMap((l) => l.link ?? []).map((l) => `-l${l}`)];
13162
13628
  }
13163
13629
  /** Compiles the program's C files and links them with `archives` (programArchives), stripping at
13164
13630
  * this link when asked. A split program's files compile `jobs` at once; `compiled` hears as each
13165
- * is done. Asynchronous, so the build's report keeps drawing. */
13166
- async function compileProgram(tc, cFiles, output, archives, { extraFlags = [], jobs = compileJobs(), compiled } = {}) {
13631
+ * is done. `mapFile`: the link writes its map there (linkMapFlags), and each C file's object stays
13632
+ * beside it, for the debug info. Asynchronous, so the build's report keeps drawing. */
13633
+ async function compileProgram(tc, cFiles, output, archives, { extraFlags = [], jobs = compileJobs(), compiled, mapFile } = {}) {
13167
13634
  const flags = [
13168
13635
  ...COMMON,
13169
13636
  ...tc.opt,
@@ -13171,20 +13638,17 @@ async function compileProgram(tc, cFiles, output, archives, { extraFlags = [], j
13171
13638
  ...extraFlags
13172
13639
  ];
13173
13640
  const link = [
13174
- ...archives,
13641
+ ...archives.map((a) => a.startsWith("-l") ? a : resolve(a)),
13175
13642
  "-lm",
13176
13643
  ...LINK,
13177
13644
  ...tc.strip ? STRIP : [],
13645
+ ...mapFile ? linkMapFlags(resolve(mapFile)) : [],
13178
13646
  "-o",
13179
- output
13647
+ resolve(output)
13180
13648
  ];
13181
- if (cFiles.length === 1) return runCompilerAsync(tc.cc, [
13182
- ...flags,
13183
- `-I${RUNTIME_INCLUDE}`,
13184
- cFiles[0],
13185
- ...link
13186
- ]);
13187
- const objects = cFiles.map((f) => f.replace(/\.c$/, ".o"));
13649
+ const cwd = dirname(resolve(cFiles[0]));
13650
+ const sources = cFiles.map((f) => relative(cwd, resolve(f)));
13651
+ const objects = sources.map((f) => f.replace(/\.c$/, ".o"));
13188
13652
  const order = cFiles.map((_, i) => i).sort((a, b) => statSync(cFiles[b]).size - statSync(cFiles[a]).size);
13189
13653
  let next = 0, done = 0;
13190
13654
  const worker = async () => {
@@ -13195,10 +13659,10 @@ async function compileProgram(tc, cFiles, output, archives, { extraFlags = [], j
13195
13659
  ...flags,
13196
13660
  `-I${RUNTIME_INCLUDE}`,
13197
13661
  "-c",
13198
- cFiles[i],
13662
+ sources[i],
13199
13663
  "-o",
13200
13664
  objects[i]
13201
- ]);
13665
+ ], cwd);
13202
13666
  } catch (e) {
13203
13667
  next = order.length;
13204
13668
  throw e;
@@ -13212,7 +13676,7 @@ async function compileProgram(tc, cFiles, output, archives, { extraFlags = [], j
13212
13676
  ...flags,
13213
13677
  ...objects,
13214
13678
  ...link
13215
- ]);
13679
+ ], cwd);
13216
13680
  }
13217
13681
  /** How many of a split program's files compile at once: one per processor and per `perJob` bytes
13218
13682
  * of available memory (a cgroup's limit counts). A file needs up to about 1.1 GB at -O2 with
@@ -13222,15 +13686,18 @@ function compileJobs(perJob = 15e8) {
13222
13686
  }
13223
13687
  /** Runs the compiler; its stderr passes through (but for notes the program can't act on), and its
13224
13688
  * tail is kept to recognize a broken toolchain. Rejects when it fails. */
13225
- function runCompilerAsync(cc, args) {
13689
+ function runCompilerAsync(cc, args, cwd) {
13226
13690
  return new Promise((resolve, reject) => {
13227
13691
  let errors = "";
13228
- const [program, ...prefix] = command(cc);
13229
- const child = spawn(program, [...prefix, ...args], { stdio: [
13230
- "ignore",
13231
- "inherit",
13232
- "pipe"
13233
- ] });
13692
+ const [program, ...prefix] = compilerCommand(cc);
13693
+ const child = spawn(program, [...prefix, ...args], {
13694
+ cwd,
13695
+ stdio: [
13696
+ "ignore",
13697
+ "inherit",
13698
+ "pipe"
13699
+ ]
13700
+ });
13234
13701
  const filter = new DiagnosticFilter((text) => process.stderr.write(text));
13235
13702
  child.stderr.on("data", (chunk) => {
13236
13703
  filter.write(chunk.toString());
@@ -13585,6 +14052,8 @@ function buildTypedUnit(files, primitives) {
13585
14052
  const exports = {};
13586
14053
  const exportedFns = /* @__PURE__ */ new Map();
13587
14054
  for (const [name, loc] of exported) {
14055
+ const array = signatures.get(loc)?.arrays[0];
14056
+ if (array) throw compileError(array, `export '${name}' takes an array: static code doesn't take arrays from JavaScript yet`);
13588
14057
  const fn = ir.functions.find((f) => at(f) === loc);
13589
14058
  exportedFns.set(name, fn.name);
13590
14059
  exports[name] = {
@@ -14577,6 +15046,316 @@ function lineCount(text) {
14577
15046
  return n;
14578
15047
  }
14579
15048
  //#endregion
15049
+ //#region cli/src/size.ts
15050
+ const ZEROFILL = /* @__PURE__ */ new Set([
15051
+ "__DATA,__bss",
15052
+ "__DATA,__common",
15053
+ "__DATA,__thread_bss"
15054
+ ]);
15055
+ const CODE = "__TEXT,__text";
15056
+ function parseLinkMap(text) {
15057
+ const objects = [], sections = [], symbols = [];
15058
+ let part = "";
15059
+ for (const line of text.split("\n")) {
15060
+ if (line.startsWith("# ")) {
15061
+ part = line.startsWith("# Object files") ? "objects" : line.startsWith("# Sections") ? "sections" : line.startsWith("# Symbols") ? "symbols" : line.startsWith("# Dead Stripped") ? "" : part;
15062
+ continue;
15063
+ }
15064
+ if (part === "objects") {
15065
+ const m = /^\[\s*(\d+)\] (.*)$/.exec(line);
15066
+ if (m) objects[Number(m[1])] = m[2];
15067
+ } else if (part === "sections") {
15068
+ const [address, bytes, segment, section] = line.split(" ");
15069
+ if (section) sections.push({
15070
+ address: parseInt(address, 16),
15071
+ size: parseInt(bytes, 16),
15072
+ name: `${segment},${section.trim()}`
15073
+ });
15074
+ } else if (part === "symbols") {
15075
+ const m = /^0x([0-9A-F]+)\t0x([0-9A-F]+)\t\[\s*(\d+)\] (.*)$/.exec(line);
15076
+ if (m) symbols.push({
15077
+ address: parseInt(m[1], 16),
15078
+ size: parseInt(m[2], 16),
15079
+ object: Number(m[3]),
15080
+ name: m[4]
15081
+ });
15082
+ }
15083
+ }
15084
+ return {
15085
+ objects,
15086
+ sections,
15087
+ symbols
15088
+ };
15089
+ }
15090
+ /** The line table's address ranges, each with its source file, sorted by address. `text` is
15091
+ * `dwarfdump --debug-line`'s output. */
15092
+ function parseLineTable(text) {
15093
+ const ranges = [];
15094
+ let dirs = [], files = [];
15095
+ let pendingFile;
15096
+ let prev;
15097
+ for (const line of text.split("\n")) {
15098
+ if (line.startsWith("debug_line[")) {
15099
+ dirs = [];
15100
+ files = [];
15101
+ prev = void 0;
15102
+ continue;
15103
+ }
15104
+ let m = /^include_directories\[\s*(\d+)\] = "(.*)"$/.exec(line);
15105
+ if (m) {
15106
+ dirs[Number(m[1])] = m[2];
15107
+ continue;
15108
+ }
15109
+ m = /^file_names\[\s*(\d+)\]:$/.exec(line);
15110
+ if (m) {
15111
+ pendingFile = Number(m[1]);
15112
+ continue;
15113
+ }
15114
+ m = /^\s+name: "(.*)"$/.exec(line);
15115
+ if (m && pendingFile !== void 0) {
15116
+ files[pendingFile] = m[1];
15117
+ continue;
15118
+ }
15119
+ m = /^\s+dir_index: (\d+)$/.exec(line);
15120
+ if (m && pendingFile !== void 0) {
15121
+ const name = files[pendingFile];
15122
+ files[pendingFile] = isAbsolute(name) ? name : join(dirs[Number(m[1])] ?? "", name);
15123
+ pendingFile = void 0;
15124
+ continue;
15125
+ }
15126
+ m = /^0x([0-9a-f]+)\s+(\d+)\s+\d+\s+(\d+)\s.*$/.exec(line);
15127
+ if (!m) continue;
15128
+ const address = parseInt(m[1], 16);
15129
+ if (prev && address > prev.address) ranges.push({
15130
+ start: prev.address,
15131
+ end: address,
15132
+ file: prev.file,
15133
+ line: prev.line
15134
+ });
15135
+ prev = line.includes("end_sequence") ? void 0 : {
15136
+ address,
15137
+ file: files[Number(m[3])] ?? "?",
15138
+ line: Number(m[2])
15139
+ };
15140
+ }
15141
+ return ranges.sort((a, b) => a.start - b.start);
15142
+ }
15143
+ /** The bundle's modules by line: its //#region comments, whose paths are relative to the entry's
15144
+ * directory (the bundler's cwd) or a virtual module's id. The source map leaves out what the
15145
+ * bundler generates or converts: JSON modules, CommonJS wrappers, namespace objects. */
15146
+ function bundleRegions(code, entryDir) {
15147
+ const { starts, files } = parseRegions(code, entryDir);
15148
+ return (line) => {
15149
+ let lo = 0, hi = starts.length;
15150
+ while (lo < hi) {
15151
+ const mid = lo + hi >> 1;
15152
+ if (starts[mid] <= line) lo = mid + 1;
15153
+ else hi = mid;
15154
+ }
15155
+ return lo ? files[lo - 1] : void 0;
15156
+ };
15157
+ }
15158
+ /** Each region's first line (1-based) and module; undefined: outside any, or the bundler's own. */
15159
+ function parseRegions(code, entryDir) {
15160
+ const starts = [], files = [];
15161
+ const lines = code.split("\n");
15162
+ for (let i = 0; i < lines.length; i++) {
15163
+ const m = /^\/\/#(region|endregion)(?: (.*))?$/.exec(lines[i]);
15164
+ if (!m) continue;
15165
+ const id = m[2]?.replace(/^(?:\0|\\0)visaljs-[\w-]+:/, "");
15166
+ starts.push(i + 1);
15167
+ files.push(m[1] === "endregion" || id === void 0 || /^(?:\0|\\0)/.test(id) ? void 0 : resolve(entryDir, id));
15168
+ }
15169
+ return {
15170
+ starts,
15171
+ files,
15172
+ lines
15173
+ };
15174
+ }
15175
+ /** The bundle's bytes by module (--emit bundle): what the compiler is given, before any C. The
15176
+ * "use static" files aren't in it (each is a stub of host imports): they come as `staticFiles`. */
15177
+ function bundleSizes(code, entryDir, staticFiles, cwd) {
15178
+ const { starts, files, lines } = parseRegions(code, entryDir);
15179
+ const totals = /* @__PURE__ */ new Map();
15180
+ const add = (group, name, bytes) => {
15181
+ const key = `${group}\0${name}`;
15182
+ (totals.get(key) ?? totals.set(key, {
15183
+ group,
15184
+ name,
15185
+ bytes: 0
15186
+ }).get(key)).bytes += bytes;
15187
+ };
15188
+ let region = -1;
15189
+ for (let i = 0; i < lines.length; i++) {
15190
+ if (starts[region + 1] === i + 1) region++;
15191
+ const file = region >= 0 ? files[region] : void 0;
15192
+ const bytes = Buffer.byteLength(lines[i]) + 1;
15193
+ const { group, name } = jsEntry(file, cwd);
15194
+ add(group, name, bytes);
15195
+ }
15196
+ for (const f of staticFiles) add("\"use static\" files (compiled apart, not in the bundle)", jsModule(f, cwd), statSync(f).size);
15197
+ return [...totals.values()];
15198
+ }
15199
+ const isCSource = (file) => /\.(?:c|cc|h|inc)$/.test(file);
15200
+ /** A JS file's group and module, the same in both reports. `file`: undefined, or the bundle
15201
+ * itself, for code the bundler generated outside any module. */
15202
+ function jsEntry(file, cwd) {
15203
+ if (file === void 0 || basename(file) === "bundle.js") return {
15204
+ group: "Bundler glue",
15205
+ name: "rolldown's runtime, imports and exports"
15206
+ };
15207
+ const name = jsModule(file, cwd);
15208
+ return {
15209
+ group: name.startsWith("node:") ? "Node built-ins" : /(?:^|[\\/])node_modules[\\/]/.test(file) ? "npm packages" : "Your code",
15210
+ name
15211
+ };
15212
+ }
15213
+ /** A JS file's module: a Node built-in, a package, or the program's own file. */
15214
+ function jsModule(file, cwd) {
15215
+ const prelude = relative(preludeDir, file);
15216
+ if (!prelude.startsWith("..") && !isAbsolute(prelude)) return `node:${prelude.replace(/\.js$/, "").replaceAll(sep, "/")}`;
15217
+ const packages = [...file.matchAll(/(?:^|[\\/])node_modules[\\/]((?:@[^\\/]+[\\/])?[^\\/]+)/g)].map((m) => m[1].replaceAll("\\", "/"));
15218
+ if (packages.length) return packages.length > 1 ? `${packages.at(-1)} (in ${packages.at(-2)})` : packages[0];
15219
+ const rel = relative(cwd, resolve(cwd, file));
15220
+ return rel.startsWith("..") ? file : rel;
15221
+ }
15222
+ /** An archive member's library and source: lib<name>.a(<i>.o), or a prebuilt <name>-<key>.a(<i>.o),
15223
+ * is the library's i-th source (buildArchive). */
15224
+ function librarySource(object, libraries) {
15225
+ const m = /([^\\/]+)\.a\((\d+)\.o\)$/.exec(object);
15226
+ if (!m) return void 0;
15227
+ const name = m[1].replace(/^lib/, "").replace(/-[0-9a-f]{16,}$/, "");
15228
+ const lib = libraries.find((l) => l.name === name);
15229
+ const src = lib?.sources[Number(m[2])];
15230
+ return {
15231
+ library: `lib${name}`,
15232
+ source: src && lib ? relative(commonDir(lib.sources), src) : `${m[2]}.o`
15233
+ };
15234
+ }
15235
+ function commonDir(files) {
15236
+ let dir = files[0] ? resolve(files[0], "..") : "";
15237
+ while (dir && !files.every((f) => f.startsWith(dir + sep))) dir = resolve(dir, "..");
15238
+ return dir;
15239
+ }
15240
+ const EMITTED_DATA = [
15241
+ [/^_\w*?jss_\d+$/, "string constants"],
15242
+ [/^_\w*?jsfi_/, "function descriptors"],
15243
+ [/^_\w*?jsrl?_\d+$/, "compiled regular expressions"],
15244
+ [/^_\w*?mod_/, "module tables (atoms, shapes)"]
15245
+ ];
15246
+ /** A data symbol's kind: ld64 names literals by their kind ("literal string: โ€ฆ", "16-byte-literal"). */
15247
+ function dataKind(name) {
15248
+ if (name.startsWith("literal string")) return "C string literals";
15249
+ if (/^\d+-byte-literal/.test(name)) return "number literals";
15250
+ return EMITTED_DATA.find(([re]) => re.test(name))?.[1] ?? "other data";
15251
+ }
15252
+ /** Each symbol's bytes, attributed: the program's code to its JS modules, its data by kind, a
15253
+ * library's to its source files. `programObjects` are the program's own objects' base names. */
15254
+ function attribute(map, lines, libraries, programObjects, cwd, regionOf = () => void 0) {
15255
+ const totals = /* @__PURE__ */ new Map();
15256
+ const add = (group, name, bytes) => {
15257
+ const key = `${group}\0${name}`;
15258
+ const e = totals.get(key) ?? totals.set(key, {
15259
+ group,
15260
+ name,
15261
+ bytes: 0
15262
+ }).get(key);
15263
+ e.bytes += bytes;
15264
+ };
15265
+ const sections = [...map.sections].sort((a, b) => a.address - b.address);
15266
+ const sectionOf = (address) => sections.find((s) => address >= s.address && address < s.address + s.size)?.name ?? "";
15267
+ let next = 0;
15268
+ const bySymbol = [...map.symbols].sort((a, b) => a.address - b.address);
15269
+ for (const sym of bySymbol) {
15270
+ if (sym.size === 0) continue;
15271
+ const section = sectionOf(sym.address);
15272
+ if (ZEROFILL.has(section)) continue;
15273
+ const object = map.objects[sym.object] ?? "";
15274
+ const program = programObjects.has(basename(object));
15275
+ if (program && section === CODE) {
15276
+ while (next < lines.length && lines[next].end <= sym.address) next++;
15277
+ const files = /* @__PURE__ */ new Map();
15278
+ for (let i = next; i < lines.length && lines[i].start < sym.address + sym.size; i++) {
15279
+ const r = lines[i];
15280
+ const bytes = Math.min(r.end, sym.address + sym.size) - Math.max(r.start, sym.address);
15281
+ const file = basename(r.file) === "bundle.js" ? regionOf(r.line) ?? r.file : r.file;
15282
+ if (bytes > 0 && !isCSource(file)) files.set(file, (files.get(file) ?? 0) + bytes);
15283
+ }
15284
+ const js = [...files.values()].reduce((a, b) => a + b, 0);
15285
+ const typed = basename(object) === "typed.o";
15286
+ if (js === 0) add("Runtime helpers (C, compiled with the program)", typed ? "in the \"use static\" unit" : "in the program", sym.size);
15287
+ for (const [file, bytes] of files) {
15288
+ const entry = typed ? {
15289
+ group: "\"use static\" files",
15290
+ name: jsModule(file, cwd)
15291
+ } : jsEntry(file, cwd);
15292
+ add(entry.group, entry.name, sym.size * bytes / js);
15293
+ }
15294
+ } else if (program) add("Program data", dataKind(sym.name), sym.size);
15295
+ else if (sym.object === 0) add("Linker", sym.name.replace(/^_+/, ""), sym.size);
15296
+ else {
15297
+ const lib = librarySource(object, libraries);
15298
+ if (lib) add(lib.library, lib.source, sym.size);
15299
+ else add("Linker", object.endsWith(".tbd") ? "stubs for system libraries" : basename(object), sym.size);
15300
+ }
15301
+ }
15302
+ const listed = /* @__PURE__ */ new Map();
15303
+ for (const sym of bySymbol) {
15304
+ const s = sectionOf(sym.address);
15305
+ listed.set(s, (listed.get(s) ?? 0) + sym.size);
15306
+ }
15307
+ for (const s of sections) {
15308
+ const rest = s.size - (listed.get(s.name) ?? 0);
15309
+ if (!ZEROFILL.has(s.name) && rest > 0) add("Linker", s.name, rest);
15310
+ }
15311
+ return [...totals.values()];
15312
+ }
15313
+ /** `binary`'s bytes, attributed: linked with linkMapFlags(`mapFile`) and not stripped, while its
15314
+ * `objects` (the program's own) still exist, for dsymutil reads their debug info. */
15315
+ function measureSizes(binary, mapFile, dsym, objects, libraries, bundle) {
15316
+ execFileSync("dsymutil", [
15317
+ binary,
15318
+ "-o",
15319
+ dsym
15320
+ ], { stdio: [
15321
+ "ignore",
15322
+ "ignore",
15323
+ "inherit"
15324
+ ] });
15325
+ const lines = parseLineTable(execFileSync("dwarfdump", ["--debug-line", dsym], {
15326
+ encoding: "utf8",
15327
+ maxBuffer: 1 << 30
15328
+ }));
15329
+ const map = parseLinkMap(readFileSync(mapFile, "latin1"));
15330
+ const regions = bundle ? bundleRegions(bundle.code, bundle.entryDir) : void 0;
15331
+ return attribute(map, lines, libraries, new Set(objects.map((o) => basename(o))), process.cwd(), regions);
15332
+ }
15333
+ const TOP = 12;
15334
+ function formatSizeReport(entries, fileBytes, all) {
15335
+ return `\nWhere the binary's ${size(entries.reduce((a, e) => a + e.bytes, 0))} of code and data come from (the file is ${size(fileBytes)}: the rest is page padding and the linker's tables):\n\n${formatEntries(entries, all)}`;
15336
+ }
15337
+ function formatBundleSizes(entries, all) {
15338
+ return `\nWhere the program's ${size(entries.reduce((a, e) => a + e.bytes, 0))} of JavaScript come from:\n\n${formatEntries(entries, all)}`;
15339
+ }
15340
+ function formatEntries(entries, all) {
15341
+ const groups = /* @__PURE__ */ new Map();
15342
+ for (const e of entries) (groups.get(e.group) ?? groups.set(e.group, []).get(e.group)).push(e);
15343
+ const sum = (es) => es.reduce((a, e) => a + e.bytes, 0);
15344
+ const counted = sum(entries);
15345
+ const pct = (bytes) => `${(100 * bytes / counted).toFixed(1).padStart(5)}%`;
15346
+ const width = Math.min(72, Math.max(...entries.map((e) => e.name.length + 6)));
15347
+ const row = (indent, name, bytes) => `${indent}${name.padEnd(width - indent.length)} ${size(Math.round(bytes)).padStart(9)} ${pct(bytes)}\n`;
15348
+ let out = "";
15349
+ for (const [group, es] of [...groups].sort((a, b) => sum(b[1]) - sum(a[1]))) {
15350
+ out += row(" ", group, sum(es));
15351
+ const sorted = [...es].sort((a, b) => b.bytes - a.bytes);
15352
+ const shown = all ? sorted : sorted.slice(0, TOP);
15353
+ for (const e of shown) out += row(" ", e.name, e.bytes);
15354
+ if (shown.length < sorted.length) out += row(" ", `${sorted.length - shown.length} more (--verbose lists them)`, sum(sorted.slice(shown.length)));
15355
+ }
15356
+ return out;
15357
+ }
15358
+ //#endregion
14580
15359
  //#region cli/src/main.ts
14581
15360
  const VERSION = "0.0.7";
14582
15361
  /** A program's C splits into files of about this many IR instructions. */
@@ -14595,10 +15374,7 @@ TypeScript (.ts, .mts, .cts, .tsx) is compiled too: its types are stripped, not
14595
15374
  for that), with the nearest tsconfig.json's settings (paths, decorators).
14596
15375
 
14597
15376
  options:
14598
- -o <file> output binary
14599
- --emit-c <dir> stop after C emission
14600
- --dump-ast print the syntax tree and stop
14601
- --dump-ir print the IR and stop
15377
+ -o <file> output binary (with --emit: what to write)
14602
15378
  --debug build without optimization (-O0), keeping symbols and debug info
14603
15379
  --symbols keep symbols and debug info in the optimized build (for profilers such as perf)
14604
15380
  --no-optimize skip the IR optimizer (to compare, or to rule it out)
@@ -14617,7 +15393,26 @@ options:
14617
15393
  --verbose list each place a warning is about
14618
15394
  --version print the version
14619
15395
  --help print this help
15396
+
15397
+ inspecting the build:
15398
+ --emit <stage> stop after a stage and write what it made:
15399
+ bundle the bundle (tree-shaken) and the "use static" files to the directory
15400
+ -o names, and how much of the bundle each module and package is
15401
+ ast the syntax tree, to stdout or the file -o names
15402
+ ir the optimized IR, to stdout or the file -o names
15403
+ c the C files, to the directory -o names
15404
+ --report <kind> build the binary, then report on it (repeatable):
15405
+ size where its bytes come from: each module, package, Node built-in and
15406
+ runtime library (macOS for now; --verbose lists every file)
14620
15407
  `;
15408
+ const STAGES = [
15409
+ "bundle",
15410
+ "ast",
15411
+ "ir",
15412
+ "c"
15413
+ ];
15414
+ const WRITES_FILES = /* @__PURE__ */ new Set(["bundle", "c"]);
15415
+ const REPORTS = ["size"];
14621
15416
  /** Runs the CLI and returns the process exit code. */
14622
15417
  async function main(argv, io) {
14623
15418
  let parsed;
@@ -14630,6 +15425,11 @@ async function main(argv, io) {
14630
15425
  type: "string",
14631
15426
  short: "o"
14632
15427
  },
15428
+ emit: { type: "string" },
15429
+ report: {
15430
+ type: "string",
15431
+ multiple: true
15432
+ },
14633
15433
  "emit-c": { type: "string" },
14634
15434
  "dump-ast": { type: "boolean" },
14635
15435
  "dump-ir": { type: "boolean" },
@@ -14680,7 +15480,18 @@ async function main(argv, io) {
14680
15480
  io.stderr(`visaljs build: expected one entry file or project directory\n${USAGE}`);
14681
15481
  return 2;
14682
15482
  }
14683
- return await build(rest[0] ?? ".", values, io);
15483
+ {
15484
+ const inspect = inspectOptions(values);
15485
+ if (typeof inspect === "string") {
15486
+ io.stderr(`visaljs: ${inspect}\n`);
15487
+ return 2;
15488
+ }
15489
+ return await build(rest[0] ?? ".", {
15490
+ ...values,
15491
+ output: inspect.emit ? void 0 : values.output,
15492
+ ...inspect
15493
+ }, io);
15494
+ }
14684
15495
  case "licenses":
14685
15496
  if (rest.length) {
14686
15497
  io.stderr(`visaljs licenses: takes no arguments\n${USAGE}`);
@@ -14693,11 +15504,53 @@ async function main(argv, io) {
14693
15504
  return 2;
14694
15505
  }
14695
15506
  }
15507
+ /** --emit and --report, with the flags they replace (--emit-c <dir>, --dump-ast, --dump-ir), or
15508
+ * what's wrong with them. */
15509
+ function inspectOptions(values) {
15510
+ const asked = [];
15511
+ if (values.emit !== void 0) asked.push({
15512
+ stage: values.emit,
15513
+ to: values.output
15514
+ });
15515
+ if (values["emit-c"] !== void 0) asked.push({
15516
+ stage: "c",
15517
+ to: values["emit-c"]
15518
+ });
15519
+ if (values["dump-ast"]) asked.push({
15520
+ stage: "ast",
15521
+ to: void 0
15522
+ });
15523
+ if (values["dump-ir"]) asked.push({
15524
+ stage: "ir",
15525
+ to: void 0
15526
+ });
15527
+ if (asked.length > 1) return "--emit takes one stage: the build stops after it";
15528
+ const reports = values.report ?? [];
15529
+ const unknown = reports.find((r) => !REPORTS.includes(r));
15530
+ if (unknown !== void 0) return `--report takes ${REPORTS.join(", ")}, not '${unknown}'`;
15531
+ if (reports.includes("size") && process.platform !== "darwin") return "--report size reads ld64's link map: it needs macOS for now";
15532
+ const [want] = asked;
15533
+ if (!want) return {
15534
+ emit: void 0,
15535
+ emitTo: void 0,
15536
+ reports
15537
+ };
15538
+ if (!STAGES.includes(want.stage)) return `--emit takes ${STAGES.join(", ")}, not '${want.stage}'`;
15539
+ const stage = want.stage;
15540
+ if (reports.length) return `--report reports on the binary: not with --emit ${stage}, which stops before it`;
15541
+ if (WRITES_FILES.has(stage) && !want.to) return `--emit ${stage} writes files: give their directory with -o`;
15542
+ return {
15543
+ emit: stage,
15544
+ emitTo: want.to,
15545
+ reports: []
15546
+ };
15547
+ }
14696
15548
  async function build(entry, options, io) {
14697
- const dump = options["dump-ast"] === true || options["dump-ir"] === true;
15549
+ const dump = options.emit === "ast" || options.emit === "ir";
14698
15550
  const style = options.quiet || dump ? void 0 : io.report;
14699
15551
  const report = new Report(io.stderr, style);
14700
- const binary = !dump && !options["emit-c"];
15552
+ const emitBundle = options.emit === "bundle" ? options.emitTo : void 0;
15553
+ const binary = options.emit === void 0;
14701
15554
  const hosts = DEFAULT_HOSTS;
14702
15555
  let primitives = hostPrimitives(hosts);
14703
15556
  const nodeEnv = options["node-env"] === "" ? void 0 : options["node-env"] ?? "production";
@@ -14734,7 +15587,12 @@ async function build(entry, options, io) {
14734
15587
  io.stderr(`visaljs: ${e.message}\n`);
14735
15588
  return 1;
14736
15589
  }
14737
- const bundled = !(options.script === true) && options["no-bundle"] !== true;
15590
+ const script = options.script === true;
15591
+ const bundled = !script && options["no-bundle"] !== true;
15592
+ if (emitBundle !== void 0 && !bundled) {
15593
+ io.stderr(`visaljs: --emit bundle writes the bundle: not with ${script ? "--script" : "--no-bundle"}\n`);
15594
+ return 2;
15595
+ }
14738
15596
  let map;
14739
15597
  const typedFiles = /* @__PURE__ */ new Set();
14740
15598
  let typed;
@@ -14747,6 +15605,12 @@ async function build(entry, options, io) {
14747
15605
  }), (b) => `Rolled ${count(b.modules, "module")} into a single file (${size(Buffer.byteLength(b.code))})` + (b.required.length ? `; for a require() at run time: ${b.required.join(", ")}` : ""));
14748
15606
  source = b.code;
14749
15607
  if (b.map) map = b.map;
15608
+ if (emitBundle !== void 0) {
15609
+ writeBundle(emitBundle, b.code, b.map, [...typedFiles]);
15610
+ report.finish("๐Ÿ“‚", (time) => `Wrote the bundle and ${count(typedFiles.size, "\"use static\" file")} to ${displayPath(resolve(emitBundle))} in ${time}`);
15611
+ io.stdout(formatBundleSizes(bundleSizes(b.code, dirname(resolve(entry)), [...typedFiles], process.cwd()), options.verbose === true));
15612
+ return 0;
15613
+ }
14750
15614
  if (typedFiles.size) {
14751
15615
  const files = [...typedFiles];
14752
15616
  typed = await report.step("๐Ÿงท", "Compiling the typed files", () => buildTypedUnit(files, primitives), (u) => [`Compiled ${count(files.length, "typed file")}: ${count(Object.keys(u.exports).length, "export")}`, ...formatReport(u.report).map((line) => ` โ€ข ${line}`)].join("\n"));
@@ -14764,7 +15628,7 @@ async function build(entry, options, io) {
14764
15628
  io.stderr(`visaljs: --jobs takes a positive whole number, not '${options.jobs}'\n`);
14765
15629
  return 2;
14766
15630
  }
14767
- const emitDir = options["emit-c"];
15631
+ const emitDir = options.emit === "c" ? options.emitTo : void 0;
14768
15632
  let output = "";
14769
15633
  if (binary) {
14770
15634
  output = pipeline?.output ?? options.output ?? basename(entry).replace(/\.(?:[cm]?[jt]s|[jt]sx)$/, "");
@@ -14775,6 +15639,7 @@ async function build(entry, options, io) {
14775
15639
  }
14776
15640
  }
14777
15641
  const dir = emitDir ?? (binary ? scratchDir() : "");
15642
+ let sizes;
14778
15643
  try {
14779
15644
  const typedLink = typed ? {
14780
15645
  atoms: [...typed.atoms],
@@ -14799,7 +15664,8 @@ async function build(entry, options, io) {
14799
15664
  }
14800
15665
  compilers = c.compilers;
14801
15666
  if (typeof c.result === "string") {
14802
- io.stdout(c.result);
15667
+ if (options.emitTo) writeFileSync(options.emitTo, c.result);
15668
+ else io.stdout(c.result);
14803
15669
  return 0;
14804
15670
  }
14805
15671
  const written = c.result;
@@ -14815,7 +15681,9 @@ async function build(entry, options, io) {
14815
15681
  cFiles.push(join(dir, "typed.c"));
14816
15682
  }
14817
15683
  const opt = [...options.debug ? ["-O0"] : ["-O2"], ...gcCheckFlags()];
14818
- const strip = !options.debug && !options.symbols;
15684
+ const sizeReport = options.reports.includes("size");
15685
+ const strip = !options.debug && !options.symbols && !sizeReport;
15686
+ const mapFile = sizeReport ? join(dir, "link.map") : void 0;
14819
15687
  const jobs = options.jobs === void 0 ? compileJobs(strip ? 8e8 : 15e8) : Number(options.jobs);
14820
15688
  try {
14821
15689
  await withCompiler(compilers, report, async (cc) => {
@@ -14833,9 +15701,21 @@ async function build(entry, options, io) {
14833
15701
  const parallel = cFiles.length > 1 ? `${cFiles.length} files, ${Math.min(jobs, cFiles.length)} at a time` : "";
14834
15702
  await report.step("๐Ÿ”จ", parallel ? `${compiling} (${parallel})` : compiling, () => compileProgram(tc, cFiles, output, archives, {
14835
15703
  jobs,
15704
+ mapFile,
14836
15705
  compiled: (done, total) => report.relabel(done < total ? `${compiling} (${done}/${total} files, ${Math.min(jobs, total)} at a time)` : `Linking with ${describeCompiler(cc)}`)
14837
15706
  }), () => `Compiled the binary with ${describeCompiler(cc)} (${[...opt, ...parallel ? [parallel] : []].join(", ")}, ${tc.strip ? "stripped" : "with debug info"})`);
14838
15707
  });
15708
+ if (mapFile) {
15709
+ sizes = await report.step("๐Ÿ“", "Measuring where the binary's bytes come from", () => measureSizes(output, mapFile, join(dir, "program.dSYM"), cFiles.map((f) => f.replace(/\.c$/, ".o")), programLibraries(hosts), bundled ? {
15710
+ code: source,
15711
+ entryDir: dirname(resolve(entry))
15712
+ } : void 0), (es) => `Measured ${count(es.length, "source")} of the binary's bytes`);
15713
+ if (!options.debug && !options.symbols) execFileSync("strip", [
15714
+ "-S",
15715
+ "-x",
15716
+ output
15717
+ ]);
15718
+ }
14839
15719
  } catch (e) {
14840
15720
  io.stderr(`visaljs: C compilation failed: ${e.message}\n`);
14841
15721
  return 1;
@@ -14848,9 +15728,23 @@ async function build(entry, options, io) {
14848
15728
  }
14849
15729
  const bytes = statSync(output).size;
14850
15730
  report.finish("๐ŸŽ‰", (time) => `Built ${displayPath(resolve(output))} in ${time}: ${size(bytes)}, ${sizeQuip(bytes)}`);
15731
+ if (sizes) io.stdout(formatSizeReport(sizes, bytes, options.verbose === true));
14851
15732
  pipeline?.done(resolve(output));
14852
15733
  return 0;
14853
15734
  }
15735
+ /** --emit bundle's files: the bundle, its map, and each "use static" file at its path from the
15736
+ * current directory under static/ (outside it: by its name). */
15737
+ function writeBundle(dir, code, map, staticFiles) {
15738
+ mkdirSync(dir, { recursive: true });
15739
+ writeFileSync(join(dir, "bundle.js"), code);
15740
+ if (map) writeFileSync(join(dir, "bundle.js.map"), map);
15741
+ for (const file of staticFiles) {
15742
+ const rel = relative(process.cwd(), file);
15743
+ const to = join(dir, "static", rel.startsWith("..") || isAbsolute(rel) ? basename(file) : rel);
15744
+ mkdirSync(dirname(to), { recursive: true });
15745
+ copyFileSync(file, to);
15746
+ }
15747
+ }
14854
15748
  const WORKER = "visaljs-compile";
14855
15749
  /** compileToC in a worker thread, so its heap (gigabytes for a large program) goes back to the
14856
15750
  * system for the C compilers when it ends. The worker is this module (bundled: cli.js). */
@@ -14957,7 +15851,7 @@ async function runCompileJob(job) {
14957
15851
  }
14958
15852
  }
14959
15853
  if (!isMainThread && workerData?.[WORKER]) await runCompileJob(workerData[WORKER]);
14960
- /** The program's C files' names, or the text --dump-ast or --dump-ir prints. Its own function, as
15854
+ /** The program's C files' names, or the text --emit ast or --emit ir writes. Its own function, as
14961
15855
  * is toIR, so the syntax tree and then the IR become garbage: a large program's take gigabytes. */
14962
15856
  async function compileToC(source, entry, map, options, report, primitives, compilers, typed, write) {
14963
15857
  const program = await toIR(source, entry, map, options, report, primitives, compilers, typed?.calls);
@@ -14995,7 +15889,7 @@ async function compileToC(source, entry, map, options, report, primitives, compi
14995
15889
  }
14996
15890
  async function toIR(source, entry, map, options, report, primitives, compilers, typedCalls) {
14997
15891
  const ast = await report.step("๐ŸŒณ", "Parsing the JavaScript", () => options.script ? parseScript(source, entry) : parseModule(source, map ? "bundle.js" : entry, map, resolve(entry), primitives), () => `Parsed ${count(lineCount(source), "line")} of JavaScript`);
14998
- if (options["dump-ast"]) return JSON.stringify(ast, null, 2) + "\n";
15892
+ if (options.emit === "ast") return JSON.stringify(ast, null, 2) + "\n";
14999
15893
  const info = analyze(ast);
15000
15894
  const evalWarn = evalWarning(evalCalls(ast, info), options.verbose === true);
15001
15895
  if (evalWarn) report.warn(evalWarn);
@@ -15009,7 +15903,7 @@ async function toIR(source, entry, map, options, report, primitives, compilers,
15009
15903
  if (typedCalls) annotateTypedCalls(lowered, typedCalls);
15010
15904
  return optimize(lowered, options["no-optimize"] ? [] : void 0, passes);
15011
15905
  }, (ir) => [`Converted ${count(ir.functions.length + 1, "function")} to IR and optimized them`, ...formatReport(passes).map((line) => ` โ€ข ${line}`)].join("\n"));
15012
- if (options["dump-ir"]) return printModule(ir);
15906
+ if (options.emit === "ir") return printModule(ir);
15013
15907
  return {
15014
15908
  ir,
15015
15909
  names: programNames(ast),